* arm.md (minmax_arithsi): Reject all eliminable registers, not just
[official-gcc.git] / gcc / config / arm / arm.md
blobf86ce20299c6c89f088bd6789fbdf36e19cc8ef7
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003, 2004, 2005  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   [(R0_REGNUM        0)         ; First CORE register
34    (IP_REGNUM       12)         ; Scratch register
35    (SP_REGNUM       13)         ; Stack pointer
36    (LR_REGNUM       14)         ; Return address register
37    (PC_REGNUM       15)         ; Program counter
38    (CC_REGNUM       24)         ; Condition code pseudo register
39    (LAST_ARM_REGNUM 15)         ;
40    (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
41    (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
42   ]
44 ;; 3rd operand to select_dominance_cc_mode
45 (define_constants
46   [(DOM_CC_X_AND_Y  0)
47    (DOM_CC_NX_OR_Y  1)
48    (DOM_CC_X_OR_Y   2)
49   ]
52 ;; UNSPEC Usage:
53 ;; Note: sin and cos are no-longer used.
55 (define_constants
56   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
60                         ;   operand 0 is the result,
61                         ;   operand 1 the parameter.
62    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63                         ;   operand 0 is the first register,
64                         ;   subsequent registers are in parallel (use ...)
65                         ;   expressions.
66    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
67                         ;   usage, that is, we will add the pic_register
68                         ;   value to it before trying to dereference it.
69    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
70                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
71                         ;   described by the RTL but must be wrapped to
72                         ;   prevent combine from trying to rip it apart.
73    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
74                         ;   being scheduled before the stack adjustment insn.
75    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76                         ; this unspec is used to prevent the deletion of
77                         ; instructions setting registers for EH handling
78                         ; and stack frame generation.  Operand 0 is the
79                         ; register to "use".
80    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93   ]
96 ;; UNSPEC_VOLATILE Usage:
98 (define_constants
99   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
100                         ;   insn in the code.
101    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
102                         ;   instruction epilogue sequence that isn't expanded
103                         ;   into normal RTL.  Used for both normal and sibcall
104                         ;   epilogues.
105    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
106                         ;   for inlined constants.
107    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
108                         ;   table.
109    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
110                         ;   an 8-bit object.
111    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
112                         ;   a 16-bit object.
113    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
114                         ;   a 32-bit object.
115    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
116                         ;   a 64-bit object.
117    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
118    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
119    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
120    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
121    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
122    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
123    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
124                          ; handling.
125   ]
128 ;;---------------------------------------------------------------------------
129 ;; Attributes
131 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
132 ; generating ARM code.  This is used to control the length of some insn
133 ; patterns that share the same RTL in both ARM and Thumb code.
134 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
140 ; IS_XSCALE is set to 'yes' when compiling for XScale.
141 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 ;; Operand number of an input operand that is shifted.  Zero if the
144 ;; given instruction does not shift one of its input operands.
145 (define_attr "shift" "" (const_int 0))
147 ; Floating Point Unit.  If we only have floating point emulation, then there
148 ; is no point in scheduling the floating point insns.  (Well, for best
149 ; performance we should try and group them together).
150 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
151   (const (symbol_ref "arm_fpu_attr")))
153 ; LENGTH of an instruction (in bytes)
154 (define_attr "length" "" (const_int 4))
156 ; POOL_RANGE is how far away from a constant pool entry that this insn
157 ; can be placed.  If the distance is zero, then this insn will never
158 ; reference the pool.
159 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
160 ; before its address.
161 (define_attr "pool_range" "" (const_int 0))
162 (define_attr "neg_pool_range" "" (const_int 0))
164 ; An assembler sequence may clobber the condition codes without us knowing.
165 ; If such an insn references the pool, then we have no way of knowing how,
166 ; so use the most conservative value for pool_range.
167 (define_asm_attributes
168  [(set_attr "conds" "clob")
169   (set_attr "length" "4")
170   (set_attr "pool_range" "250")])
172 ;; The instruction used to implement a particular pattern.  This
173 ;; information is used by pipeline descriptions to provide accurate
174 ;; scheduling information.
176 (define_attr "insn"
177         "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
178         (const_string "other"))
180 ; TYPE attribute is used to detect floating point instructions which, if
181 ; running on a co-processor can run in parallel with other, basic instructions
182 ; If write-buffer scheduling is enabled then it can also be used in the
183 ; scheduling of writes.
185 ; Classification of each insn
186 ; alu           any alu  instruction that doesn't hit memory or fp
187 ;               regs or have a shifted source operand
188 ; alu_shift     any data instruction that doesn't hit memory or fp
189 ;               regs, but has a source operand shifted by a constant
190 ; alu_shift_reg any data instruction that doesn't hit memory or fp
191 ;               regs, but has a source operand shifted by a register value
192 ; mult          a multiply instruction
193 ; block         blockage insn, this blocks all functional units
194 ; float         a floating point arithmetic operation (subject to expansion)
195 ; fdivd         DFmode floating point division
196 ; fdivs         SFmode floating point division
197 ; fmul          Floating point multiply
198 ; ffmul         Fast floating point multiply
199 ; farith        Floating point arithmetic (4 cycle)
200 ; ffarith       Fast floating point arithmetic (2 cycle)
201 ; float_em      a floating point arithmetic operation that is normally emulated
202 ;               even on a machine with an fpa.
203 ; f_load        a floating point load from memory
204 ; f_store       a floating point store to memory
205 ; f_mem_r       a transfer of a floating point register to a real reg via mem
206 ; r_mem_f       the reverse of f_mem_r
207 ; f_2_r         fast transfer float to arm (no memory needed)
208 ; r_2_f         fast transfer arm to float
209 ; branch        a branch
210 ; call          a subroutine call
211 ; load_byte     load byte(s) from memory to arm registers
212 ; load1         load 1 word from memory to arm registers
213 ; load2         load 2 words from memory to arm registers
214 ; load3         load 3 words from memory to arm registers
215 ; load4         load 4 words from memory to arm registers
216 ; store         store 1 word to memory from arm registers
217 ; store2        store 2 words
218 ; store3        store 3 words
219 ; store4        store 4 (or more) words
220 ;  Additions for Cirrus Maverick co-processor:
221 ; mav_farith    Floating point arithmetic (4 cycle)
222 ; mav_dmult     Double multiplies (7 cycle)
224 (define_attr "type"
225         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
226         (if_then_else 
227          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
228          (const_string "mult")
229          (const_string "alu")))
231 ; Load scheduling, set from the arm_ld_sched variable
232 ; initialized by arm_override_options() 
233 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
235 ; condition codes: this one is used by final_prescan_insn to speed up
236 ; conditionalizing instructions.  It saves having to scan the rtl to see if
237 ; it uses or alters the condition codes.
239 ; USE means that the condition codes are used by the insn in the process of
240 ;   outputting code, this means (at present) that we can't use the insn in
241 ;   inlined branches
243 ; SET means that the purpose of the insn is to set the condition codes in a
244 ;   well defined manner.
246 ; CLOB means that the condition codes are altered in an undefined manner, if
247 ;   they are altered at all
249 ; JUMP_CLOB is used when the condition cannot be represented by a single
250 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
252 ; NOCOND means that the condition codes are neither altered nor affect the
253 ;   output of this insn
255 (define_attr "conds" "use,set,clob,jump_clob,nocond"
256         (if_then_else (eq_attr "type" "call")
257          (const_string "clob")
258          (const_string "nocond")))
260 ; Predicable means that the insn can be conditionally executed based on
261 ; an automatically added predicate (additional patterns are generated by 
262 ; gen...).  We default to 'no' because no Thumb patterns match this rule
263 ; and not all ARM patterns do.
264 (define_attr "predicable" "no,yes" (const_string "no"))
266 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
267 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
268 ; suffer blockages enough to warrant modelling this (and it can adversely
269 ; affect the schedule).
270 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
272 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
273 ; to stall the processor.  Used with model_wbuf above.
274 (define_attr "write_conflict" "no,yes"
275   (if_then_else (eq_attr "type"
276                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
277                 (const_string "yes")
278                 (const_string "no")))
280 ; Classify the insns into those that take one cycle and those that take more
281 ; than one on the main cpu execution unit.
282 (define_attr "core_cycles" "single,multi"
283   (if_then_else (eq_attr "type"
284                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
285                 (const_string "single")
286                 (const_string "multi")))
288 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
289 ;; distant label.  Only applicable to Thumb code.
290 (define_attr "far_jump" "yes,no" (const_string "no"))
292 (include "predicates.md")
294 ;;---------------------------------------------------------------------------
295 ;; Pipeline descriptions
297 ;; Processor type.  This is created automatically from arm-cores.def.
298 (include "arm-tune.md")
300 ;; True if the generic scheduling description should be used.
302 (define_attr "generic_sched" "yes,no"
303   (const (if_then_else 
304           (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
305           (const_string "no")
306           (const_string "yes"))))
308 (include "arm-generic.md")
309 (include "arm926ejs.md")
310 (include "arm1026ejs.md")
311 (include "arm1136jfs.md")
314 ;;---------------------------------------------------------------------------
315 ;; Insn patterns
317 ;; Addition insns.
319 ;; Note: For DImode insns, there is normally no reason why operands should
320 ;; not be in the same register, what we don't want is for something being
321 ;; written to partially overlap something that is an input.
322 ;; Cirrus 64bit additions should not be split because we have a native
323 ;; 64bit addition instructions.
325 (define_expand "adddi3"
326  [(parallel
327    [(set (match_operand:DI           0 "s_register_operand" "")
328           (plus:DI (match_operand:DI 1 "s_register_operand" "")
329                    (match_operand:DI 2 "s_register_operand" "")))
330     (clobber (reg:CC CC_REGNUM))])]
331   "TARGET_EITHER"
332   "
333   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
334     {
335       if (!cirrus_fp_register (operands[0], DImode))
336         operands[0] = force_reg (DImode, operands[0]);
337       if (!cirrus_fp_register (operands[1], DImode))
338         operands[1] = force_reg (DImode, operands[1]);
339       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
340       DONE;
341     }
343   if (TARGET_THUMB)
344     {
345       if (GET_CODE (operands[1]) != REG)
346         operands[1] = force_reg (SImode, operands[1]);
347       if (GET_CODE (operands[2]) != REG)
348         operands[2] = force_reg (SImode, operands[2]);
349      }
350   "
353 (define_insn "*thumb_adddi3"
354   [(set (match_operand:DI          0 "register_operand" "=l")
355         (plus:DI (match_operand:DI 1 "register_operand" "%0")
356                  (match_operand:DI 2 "register_operand" "l")))
357    (clobber (reg:CC CC_REGNUM))
358   ]
359   "TARGET_THUMB"
360   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
361   [(set_attr "length" "4")]
364 (define_insn_and_split "*arm_adddi3"
365   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
366         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
367                  (match_operand:DI 2 "s_register_operand" "r,  0")))
368    (clobber (reg:CC CC_REGNUM))]
369   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
370   "#"
371   "TARGET_ARM && reload_completed"
372   [(parallel [(set (reg:CC_C CC_REGNUM)
373                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
374                                  (match_dup 1)))
375               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
376    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
377                                (plus:SI (match_dup 4) (match_dup 5))))]
378   "
379   {
380     operands[3] = gen_highpart (SImode, operands[0]);
381     operands[0] = gen_lowpart (SImode, operands[0]);
382     operands[4] = gen_highpart (SImode, operands[1]);
383     operands[1] = gen_lowpart (SImode, operands[1]);
384     operands[5] = gen_highpart (SImode, operands[2]);
385     operands[2] = gen_lowpart (SImode, operands[2]);
386   }"
387   [(set_attr "conds" "clob")
388    (set_attr "length" "8")]
391 (define_insn_and_split "*adddi_sesidi_di"
392   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
393         (plus:DI (sign_extend:DI
394                   (match_operand:SI 2 "s_register_operand" "r,r"))
395                  (match_operand:DI 1 "s_register_operand" "r,0")))
396    (clobber (reg:CC CC_REGNUM))]
397   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
398   "#"
399   "TARGET_ARM && reload_completed"
400   [(parallel [(set (reg:CC_C CC_REGNUM)
401                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
402                                  (match_dup 1)))
403               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
404    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
405                                (plus:SI (ashiftrt:SI (match_dup 2)
406                                                      (const_int 31))
407                                         (match_dup 4))))]
408   "
409   {
410     operands[3] = gen_highpart (SImode, operands[0]);
411     operands[0] = gen_lowpart (SImode, operands[0]);
412     operands[4] = gen_highpart (SImode, operands[1]);
413     operands[1] = gen_lowpart (SImode, operands[1]);
414     operands[2] = gen_lowpart (SImode, operands[2]);
415   }"
416   [(set_attr "conds" "clob")
417    (set_attr "length" "8")]
420 (define_insn_and_split "*adddi_zesidi_di"
421   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
422         (plus:DI (zero_extend:DI
423                   (match_operand:SI 2 "s_register_operand" "r,r"))
424                  (match_operand:DI 1 "s_register_operand" "r,0")))
425    (clobber (reg:CC CC_REGNUM))]
426   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
427   "#"
428   "TARGET_ARM && reload_completed"
429   [(parallel [(set (reg:CC_C CC_REGNUM)
430                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
431                                  (match_dup 1)))
432               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
433    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
434                                (plus:SI (match_dup 4) (const_int 0))))]
435   "
436   {
437     operands[3] = gen_highpart (SImode, operands[0]);
438     operands[0] = gen_lowpart (SImode, operands[0]);
439     operands[4] = gen_highpart (SImode, operands[1]);
440     operands[1] = gen_lowpart (SImode, operands[1]);
441     operands[2] = gen_lowpart (SImode, operands[2]);
442   }"
443   [(set_attr "conds" "clob")
444    (set_attr "length" "8")]
447 (define_expand "addsi3"
448   [(set (match_operand:SI          0 "s_register_operand" "")
449         (plus:SI (match_operand:SI 1 "s_register_operand" "")
450                  (match_operand:SI 2 "reg_or_int_operand" "")))]
451   "TARGET_EITHER"
452   "
453   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
454     {
455       arm_split_constant (PLUS, SImode, NULL_RTX,
456                           INTVAL (operands[2]), operands[0], operands[1],
457                           optimize && !no_new_pseudos);
458       DONE;
459     }
460   "
463 ; If there is a scratch available, this will be faster than synthesizing the
464 ; addition.
465 (define_peephole2
466   [(match_scratch:SI 3 "r")
467    (set (match_operand:SI          0 "arm_general_register_operand" "")
468         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
469                  (match_operand:SI 2 "const_int_operand"  "")))]
470   "TARGET_ARM &&
471    !(const_ok_for_arm (INTVAL (operands[2]))
472      || const_ok_for_arm (-INTVAL (operands[2])))
473     && const_ok_for_arm (~INTVAL (operands[2]))"
474   [(set (match_dup 3) (match_dup 2))
475    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
476   ""
479 (define_insn_and_split "*arm_addsi3"
480   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
481         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
482                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
483   "TARGET_ARM"
484   "@
485    add%?\\t%0, %1, %2
486    sub%?\\t%0, %1, #%n2
487    #"
488   "TARGET_ARM &&
489    GET_CODE (operands[2]) == CONST_INT
490    && !(const_ok_for_arm (INTVAL (operands[2]))
491         || const_ok_for_arm (-INTVAL (operands[2])))"
492   [(clobber (const_int 0))]
493   "
494   arm_split_constant (PLUS, SImode, curr_insn,
495                       INTVAL (operands[2]), operands[0],
496                       operands[1], 0);
497   DONE;
498   "
499   [(set_attr "length" "4,4,16")
500    (set_attr "predicable" "yes")]
503 ;; Register group 'k' is a single register group containing only the stack
504 ;; register.  Trying to reload it will always fail catastrophically,
505 ;; so never allow those alternatives to match if reloading is needed.
507 (define_insn "*thumb_addsi3"
508   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
509         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
510                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
511   "TARGET_THUMB"
512   "*
513    static const char * const asms[] = 
514    {
515      \"add\\t%0, %0, %2\",
516      \"sub\\t%0, %0, #%n2\",
517      \"add\\t%0, %1, %2\",
518      \"add\\t%0, %0, %2\",
519      \"add\\t%0, %0, %2\",
520      \"add\\t%0, %1, %2\",
521      \"add\\t%0, %1, %2\"
522    };
523    if ((which_alternative == 2 || which_alternative == 6)
524        && GET_CODE (operands[2]) == CONST_INT
525        && INTVAL (operands[2]) < 0)
526      return \"sub\\t%0, %1, #%n2\";
527    return asms[which_alternative];
528   "
529   [(set_attr "length" "2")]
532 ;; Reloading and elimination of the frame pointer can
533 ;; sometimes cause this optimization to be missed.
534 (define_peephole2
535   [(set (match_operand:SI 0 "arm_general_register_operand" "")
536         (match_operand:SI 1 "const_int_operand" ""))
537    (set (match_dup 0)
538         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
539   "TARGET_THUMB
540    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
541    && (INTVAL (operands[1]) & 3) == 0"
542   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
543   ""
546 (define_insn "*addsi3_compare0"
547   [(set (reg:CC_NOOV CC_REGNUM)
548         (compare:CC_NOOV
549          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
550                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
551          (const_int 0)))
552    (set (match_operand:SI 0 "s_register_operand" "=r,r")
553         (plus:SI (match_dup 1) (match_dup 2)))]
554   "TARGET_ARM"
555   "@
556    add%?s\\t%0, %1, %2
557    sub%?s\\t%0, %1, #%n2"
558   [(set_attr "conds" "set")]
561 (define_insn "*addsi3_compare0_scratch"
562   [(set (reg:CC_NOOV CC_REGNUM)
563         (compare:CC_NOOV
564          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
565                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
566          (const_int 0)))]
567   "TARGET_ARM"
568   "@
569    cmn%?\\t%0, %1
570    cmp%?\\t%0, #%n1"
571   [(set_attr "conds" "set")]
574 ;; These patterns are the same ones as the two regular addsi3_compare0
575 ;; patterns, except we write them slightly different - the combiner
576 ;; tends to generate them this way.
577 (define_insn "*addsi3_compare0_for_combiner"
578   [(set (reg:CC CC_REGNUM)
579         (compare:CC
580          (match_operand:SI 1 "s_register_operand" "r,r")
581          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
582    (set (match_operand:SI 0 "s_register_operand" "=r,r")
583         (plus:SI (match_dup 1) (match_dup 2)))]
584   "TARGET_ARM"
585   "@
586    add%?s\\t%0, %1, %2
587    sub%?s\\t%0, %1, #%n2"
588   [(set_attr "conds" "set")]
591 (define_insn "*addsi3_compare0_scratch_for_combiner"
592   [(set (reg:CC CC_REGNUM)
593         (compare:CC
594          (match_operand:SI 0 "s_register_operand" "r,r")
595          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
596   "TARGET_ARM"
597   "@
598    cmn%?\\t%0, %1
599    cmp%?\\t%0, #%n1"
600   [(set_attr "conds" "set")]
603 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
604 ;; addend is a constant.
605 (define_insn "*cmpsi2_addneg"
606   [(set (reg:CC CC_REGNUM)
607         (compare:CC
608          (match_operand:SI 1 "s_register_operand" "r,r")
609          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
610    (set (match_operand:SI 0 "s_register_operand" "=r,r")
611         (plus:SI (match_dup 1)
612                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
613   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
614   "@
615    sub%?s\\t%0, %1, %2
616    add%?s\\t%0, %1, #%n2"
617   [(set_attr "conds" "set")]
620 ;; Convert the sequence
621 ;;  sub  rd, rn, #1
622 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
623 ;;  bne  dest
624 ;; into
625 ;;  subs rd, rn, #1
626 ;;  bcs  dest   ((unsigned)rn >= 1)
627 ;; similarly for the beq variant using bcc.
628 ;; This is a common looping idiom (while (n--))
629 (define_peephole2
630   [(set (match_operand:SI 0 "arm_general_register_operand" "")
631         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
632                  (const_int -1)))
633    (set (match_operand 2 "cc_register" "")
634         (compare (match_dup 0) (const_int -1)))
635    (set (pc)
636         (if_then_else (match_operator 3 "equality_operator"
637                        [(match_dup 2) (const_int 0)])
638                       (match_operand 4 "" "")
639                       (match_operand 5 "" "")))]
640   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
641   [(parallel[
642     (set (match_dup 2)
643          (compare:CC
644           (match_dup 1) (const_int 1)))
645     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
646    (set (pc)
647         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
648                       (match_dup 4)
649                       (match_dup 5)))]
650   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
651    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
652                                   ? GEU : LTU),
653                                  VOIDmode, 
654                                  operands[2], const0_rtx);"
657 ;; The next four insns work because they compare the result with one of
658 ;; the operands, and we know that the use of the condition code is
659 ;; either GEU or LTU, so we can use the carry flag from the addition
660 ;; instead of doing the compare a second time.
661 (define_insn "*addsi3_compare_op1"
662   [(set (reg:CC_C CC_REGNUM)
663         (compare:CC_C
664          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
665                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
666          (match_dup 1)))
667    (set (match_operand:SI 0 "s_register_operand" "=r,r")
668         (plus:SI (match_dup 1) (match_dup 2)))]
669   "TARGET_ARM"
670   "@
671    add%?s\\t%0, %1, %2
672    sub%?s\\t%0, %1, #%n2"
673   [(set_attr "conds" "set")]
676 (define_insn "*addsi3_compare_op2"
677   [(set (reg:CC_C CC_REGNUM)
678         (compare:CC_C
679          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
680                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
681          (match_dup 2)))
682    (set (match_operand:SI 0 "s_register_operand" "=r,r")
683         (plus:SI (match_dup 1) (match_dup 2)))]
684   "TARGET_ARM"
685   "@
686    add%?s\\t%0, %1, %2
687    sub%?s\\t%0, %1, #%n2"
688   [(set_attr "conds" "set")]
691 (define_insn "*compare_addsi2_op0"
692   [(set (reg:CC_C CC_REGNUM)
693         (compare:CC_C
694          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
695                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
696          (match_dup 0)))]
697   "TARGET_ARM"
698   "@
699    cmn%?\\t%0, %1
700    cmp%?\\t%0, #%n1"
701   [(set_attr "conds" "set")]
704 (define_insn "*compare_addsi2_op1"
705   [(set (reg:CC_C CC_REGNUM)
706         (compare:CC_C
707          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
708                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
709          (match_dup 1)))]
710   "TARGET_ARM"
711   "@
712    cmn%?\\t%0, %1
713    cmp%?\\t%0, #%n1"
714   [(set_attr "conds" "set")]
717 (define_insn "*addsi3_carryin"
718   [(set (match_operand:SI 0 "s_register_operand" "=r")
719         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
720                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
721                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
722   "TARGET_ARM"
723   "adc%?\\t%0, %1, %2"
724   [(set_attr "conds" "use")]
727 (define_insn "*addsi3_carryin_shift"
728   [(set (match_operand:SI 0 "s_register_operand" "=r")
729         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
730                  (plus:SI
731                    (match_operator:SI 2 "shift_operator"
732                       [(match_operand:SI 3 "s_register_operand" "r")
733                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
734                     (match_operand:SI 1 "s_register_operand" "r"))))]
735   "TARGET_ARM"
736   "adc%?\\t%0, %1, %3%S2"
737   [(set_attr "conds" "use")
738    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
739                       (const_string "alu_shift")
740                       (const_string "alu_shift_reg")))]
743 (define_insn "*addsi3_carryin_alt1"
744   [(set (match_operand:SI 0 "s_register_operand" "=r")
745         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
746                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
747                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
748   "TARGET_ARM"
749   "adc%?\\t%0, %1, %2"
750   [(set_attr "conds" "use")]
753 (define_insn "*addsi3_carryin_alt2"
754   [(set (match_operand:SI 0 "s_register_operand" "=r")
755         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
756                           (match_operand:SI 1 "s_register_operand" "r"))
757                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
758   "TARGET_ARM"
759   "adc%?\\t%0, %1, %2"
760   [(set_attr "conds" "use")]
763 (define_insn "*addsi3_carryin_alt3"
764   [(set (match_operand:SI 0 "s_register_operand" "=r")
765         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
766                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
767                  (match_operand:SI 1 "s_register_operand" "r")))]
768   "TARGET_ARM"
769   "adc%?\\t%0, %1, %2"
770   [(set_attr "conds" "use")]
773 (define_insn "incscc"
774   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
775         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
776                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
777                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
778   "TARGET_ARM"
779   "@
780   add%d2\\t%0, %1, #1
781   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
782   [(set_attr "conds" "use")
783    (set_attr "length" "4,8")]
786 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
787 (define_split
788   [(set (match_operand:SI 0 "s_register_operand" "")
789         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
790                             (match_operand:SI 2 "s_register_operand" ""))
791                  (const_int -1)))
792    (clobber (match_operand:SI 3 "s_register_operand" ""))]
793   "TARGET_ARM"
794   [(set (match_dup 3) (match_dup 1))
795    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
796   "
797   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
800 (define_expand "addsf3"
801   [(set (match_operand:SF          0 "s_register_operand" "")
802         (plus:SF (match_operand:SF 1 "s_register_operand" "")
803                  (match_operand:SF 2 "arm_float_add_operand" "")))]
804   "TARGET_ARM && TARGET_HARD_FLOAT"
805   "
806   if (TARGET_MAVERICK
807       && !cirrus_fp_register (operands[2], SFmode))
808     operands[2] = force_reg (SFmode, operands[2]);
811 (define_expand "adddf3"
812   [(set (match_operand:DF          0 "s_register_operand" "")
813         (plus:DF (match_operand:DF 1 "s_register_operand" "")
814                  (match_operand:DF 2 "arm_float_add_operand" "")))]
815   "TARGET_ARM && TARGET_HARD_FLOAT"
816   "
817   if (TARGET_MAVERICK
818       && !cirrus_fp_register (operands[2], DFmode))
819     operands[2] = force_reg (DFmode, operands[2]);
822 (define_expand "subdi3"
823  [(parallel
824    [(set (match_operand:DI            0 "s_register_operand" "")
825           (minus:DI (match_operand:DI 1 "s_register_operand" "")
826                     (match_operand:DI 2 "s_register_operand" "")))
827     (clobber (reg:CC CC_REGNUM))])]
828   "TARGET_EITHER"
829   "
830   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
831       && TARGET_ARM
832       && cirrus_fp_register (operands[0], DImode)
833       && cirrus_fp_register (operands[1], DImode))
834     {
835       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
836       DONE;
837     }
839   if (TARGET_THUMB)
840     {
841       if (GET_CODE (operands[1]) != REG)
842         operands[1] = force_reg (SImode, operands[1]);
843       if (GET_CODE (operands[2]) != REG)
844         operands[2] = force_reg (SImode, operands[2]);
845      }  
846   "
849 (define_insn "*arm_subdi3"
850   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
851         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
852                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
853    (clobber (reg:CC CC_REGNUM))]
854   "TARGET_ARM"
855   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
856   [(set_attr "conds" "clob")
857    (set_attr "length" "8")]
860 (define_insn "*thumb_subdi3"
861   [(set (match_operand:DI           0 "register_operand" "=l")
862         (minus:DI (match_operand:DI 1 "register_operand"  "0")
863                   (match_operand:DI 2 "register_operand"  "l")))
864    (clobber (reg:CC CC_REGNUM))]
865   "TARGET_THUMB"
866   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
867   [(set_attr "length" "4")]
870 (define_insn "*subdi_di_zesidi"
871   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
872         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
873                   (zero_extend:DI
874                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
875    (clobber (reg:CC CC_REGNUM))]
876   "TARGET_ARM"
877   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
878   [(set_attr "conds" "clob")
879    (set_attr "length" "8")]
882 (define_insn "*subdi_di_sesidi"
883   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
884         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
885                   (sign_extend:DI
886                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
887    (clobber (reg:CC CC_REGNUM))]
888   "TARGET_ARM"
889   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
890   [(set_attr "conds" "clob")
891    (set_attr "length" "8")]
894 (define_insn "*subdi_zesidi_di"
895   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
896         (minus:DI (zero_extend:DI
897                    (match_operand:SI 2 "s_register_operand"  "r,r"))
898                   (match_operand:DI  1 "s_register_operand" "?r,0")))
899    (clobber (reg:CC CC_REGNUM))]
900   "TARGET_ARM"
901   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
902   [(set_attr "conds" "clob")
903    (set_attr "length" "8")]
906 (define_insn "*subdi_sesidi_di"
907   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
908         (minus:DI (sign_extend:DI
909                    (match_operand:SI 2 "s_register_operand"   "r,r"))
910                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
911    (clobber (reg:CC CC_REGNUM))]
912   "TARGET_ARM"
913   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
914   [(set_attr "conds" "clob")
915    (set_attr "length" "8")]
918 (define_insn "*subdi_zesidi_zesidi"
919   [(set (match_operand:DI            0 "s_register_operand" "=r")
920         (minus:DI (zero_extend:DI
921                    (match_operand:SI 1 "s_register_operand"  "r"))
922                   (zero_extend:DI
923                    (match_operand:SI 2 "s_register_operand"  "r"))))
924    (clobber (reg:CC CC_REGNUM))]
925   "TARGET_ARM"
926   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
927   [(set_attr "conds" "clob")
928    (set_attr "length" "8")]
931 (define_expand "subsi3"
932   [(set (match_operand:SI           0 "s_register_operand" "")
933         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
934                   (match_operand:SI 2 "s_register_operand" "")))]
935   "TARGET_EITHER"
936   "
937   if (GET_CODE (operands[1]) == CONST_INT)
938     {
939       if (TARGET_ARM)
940         {
941           arm_split_constant (MINUS, SImode, NULL_RTX,
942                               INTVAL (operands[1]), operands[0],
943                               operands[2], optimize && !no_new_pseudos);
944           DONE;
945         }
946       else /* TARGET_THUMB */
947         operands[1] = force_reg (SImode, operands[1]);
948     }
949   "
952 (define_insn "*thumb_subsi3_insn"
953   [(set (match_operand:SI           0 "register_operand" "=l")
954         (minus:SI (match_operand:SI 1 "register_operand" "l")
955                   (match_operand:SI 2 "register_operand" "l")))]
956   "TARGET_THUMB"
957   "sub\\t%0, %1, %2"
958   [(set_attr "length" "2")]
961 (define_insn_and_split "*arm_subsi3_insn"
962   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
963         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
964                   (match_operand:SI 2 "s_register_operand" "r,r")))]
965   "TARGET_ARM"
966   "@
967    rsb%?\\t%0, %2, %1
968    #"
969   "TARGET_ARM
970    && GET_CODE (operands[1]) == CONST_INT
971    && !const_ok_for_arm (INTVAL (operands[1]))"
972   [(clobber (const_int 0))]
973   "
974   arm_split_constant (MINUS, SImode, curr_insn,
975                       INTVAL (operands[1]), operands[0], operands[2], 0);
976   DONE;
977   "
978   [(set_attr "length" "4,16")
979    (set_attr "predicable" "yes")]
982 (define_peephole2
983   [(match_scratch:SI 3 "r")
984    (set (match_operand:SI 0 "arm_general_register_operand" "")
985         (minus:SI (match_operand:SI 1 "const_int_operand" "")
986                   (match_operand:SI 2 "arm_general_register_operand" "")))]
987   "TARGET_ARM
988    && !const_ok_for_arm (INTVAL (operands[1]))
989    && const_ok_for_arm (~INTVAL (operands[1]))"
990   [(set (match_dup 3) (match_dup 1))
991    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
992   ""
995 (define_insn "*subsi3_compare0"
996   [(set (reg:CC_NOOV CC_REGNUM)
997         (compare:CC_NOOV
998          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
999                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1000          (const_int 0)))
1001    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1002         (minus:SI (match_dup 1) (match_dup 2)))]
1003   "TARGET_ARM"
1004   "@
1005    sub%?s\\t%0, %1, %2
1006    rsb%?s\\t%0, %2, %1"
1007   [(set_attr "conds" "set")]
1010 (define_insn "decscc"
1011   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1012         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1013                   (match_operator:SI 2 "arm_comparison_operator"
1014                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1015   "TARGET_ARM"
1016   "@
1017    sub%d2\\t%0, %1, #1
1018    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1019   [(set_attr "conds" "use")
1020    (set_attr "length" "*,8")]
1023 (define_expand "subsf3"
1024   [(set (match_operand:SF           0 "s_register_operand" "")
1025         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1026                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1027   "TARGET_ARM && TARGET_HARD_FLOAT"
1028   "
1029   if (TARGET_MAVERICK)
1030     {
1031       if (!cirrus_fp_register (operands[1], SFmode))
1032         operands[1] = force_reg (SFmode, operands[1]);
1033       if (!cirrus_fp_register (operands[2], SFmode))
1034         operands[2] = force_reg (SFmode, operands[2]);
1035     }
1038 (define_expand "subdf3"
1039   [(set (match_operand:DF           0 "s_register_operand" "")
1040         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1041                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1042   "TARGET_ARM && TARGET_HARD_FLOAT"
1043   "
1044   if (TARGET_MAVERICK)
1045     {
1046        if (!cirrus_fp_register (operands[1], DFmode))
1047          operands[1] = force_reg (DFmode, operands[1]);
1048        if (!cirrus_fp_register (operands[2], DFmode))
1049          operands[2] = force_reg (DFmode, operands[2]);
1050     }
1054 ;; Multiplication insns
1056 (define_expand "mulsi3"
1057   [(set (match_operand:SI          0 "s_register_operand" "")
1058         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1059                  (match_operand:SI 1 "s_register_operand" "")))]
1060   "TARGET_EITHER"
1061   ""
1064 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1065 (define_insn "*arm_mulsi3"
1066   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1067         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1068                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1069   "TARGET_ARM"
1070   "mul%?\\t%0, %2, %1"
1071   [(set_attr "insn" "mul")
1072    (set_attr "predicable" "yes")]
1075 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1076 ; 1 and 2; are the same, because reload will make operand 0 match 
1077 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1078 ; this by adding another alternative to match this case, and then `reload' 
1079 ; it ourselves.  This alternative must come first.
1080 (define_insn "*thumb_mulsi3"
1081   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1082         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1083                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1084   "TARGET_THUMB"
1085   "*
1086   if (which_alternative < 2)
1087     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1088   else
1089     return \"mul\\t%0, %0, %2\";
1090   "
1091   [(set_attr "length" "4,4,2")
1092    (set_attr "insn" "mul")]
1095 (define_insn "*mulsi3_compare0"
1096   [(set (reg:CC_NOOV CC_REGNUM)
1097         (compare:CC_NOOV (mult:SI
1098                           (match_operand:SI 2 "s_register_operand" "r,r")
1099                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1100                          (const_int 0)))
1101    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1102         (mult:SI (match_dup 2) (match_dup 1)))]
1103   "TARGET_ARM"
1104   "mul%?s\\t%0, %2, %1"
1105   [(set_attr "conds" "set")
1106    (set_attr "insn" "muls")]
1109 (define_insn "*mulsi_compare0_scratch"
1110   [(set (reg:CC_NOOV CC_REGNUM)
1111         (compare:CC_NOOV (mult:SI
1112                           (match_operand:SI 2 "s_register_operand" "r,r")
1113                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1114                          (const_int 0)))
1115    (clobber (match_scratch:SI 0 "=&r,&r"))]
1116   "TARGET_ARM"
1117   "mul%?s\\t%0, %2, %1"
1118   [(set_attr "conds" "set")
1119    (set_attr "insn" "muls")]
1122 ;; Unnamed templates to match MLA instruction.
1124 (define_insn "*mulsi3addsi"
1125   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1126         (plus:SI
1127           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1128                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1129           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1130   "TARGET_ARM"
1131   "mla%?\\t%0, %2, %1, %3"
1132   [(set_attr "insn" "mla")
1133    (set_attr "predicable" "yes")]
1136 (define_insn "*mulsi3addsi_compare0"
1137   [(set (reg:CC_NOOV CC_REGNUM)
1138         (compare:CC_NOOV
1139          (plus:SI (mult:SI
1140                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1141                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1142                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1143          (const_int 0)))
1144    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1145         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1146                  (match_dup 3)))]
1147   "TARGET_ARM"
1148   "mla%?s\\t%0, %2, %1, %3"
1149   [(set_attr "conds" "set")
1150    (set_attr "insn" "mlas")]
1153 (define_insn "*mulsi3addsi_compare0_scratch"
1154   [(set (reg:CC_NOOV CC_REGNUM)
1155         (compare:CC_NOOV
1156          (plus:SI (mult:SI
1157                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1158                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1159                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1160          (const_int 0)))
1161    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1162   "TARGET_ARM"
1163   "mla%?s\\t%0, %2, %1, %3"
1164   [(set_attr "conds" "set")
1165    (set_attr "insn" "mlas")]
1168 ;; Unnamed template to match long long multiply-accumulate (smlal)
1170 (define_insn "*mulsidi3adddi"
1171   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1172         (plus:DI
1173          (mult:DI
1174           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1175           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1176          (match_operand:DI 1 "s_register_operand" "0")))]
1177   "TARGET_ARM && arm_arch3m"
1178   "smlal%?\\t%Q0, %R0, %3, %2"
1179   [(set_attr "insn" "smlal")
1180    (set_attr "predicable" "yes")]
1183 (define_insn "mulsidi3"
1184   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1185         (mult:DI
1186          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1187          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1188   "TARGET_ARM && arm_arch3m"
1189   "smull%?\\t%Q0, %R0, %1, %2"
1190   [(set_attr "insn" "smull")
1191    (set_attr "predicable" "yes")]
1194 (define_insn "umulsidi3"
1195   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1196         (mult:DI
1197          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1198          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1199   "TARGET_ARM && arm_arch3m"
1200   "umull%?\\t%Q0, %R0, %1, %2"
1201   [(set_attr "insn" "umull")
1202    (set_attr "predicable" "yes")]
1205 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1207 (define_insn "*umulsidi3adddi"
1208   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1209         (plus:DI
1210          (mult:DI
1211           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1212           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1213          (match_operand:DI 1 "s_register_operand" "0")))]
1214   "TARGET_ARM && arm_arch3m"
1215   "umlal%?\\t%Q0, %R0, %3, %2"
1216   [(set_attr "insn" "umlal")
1217    (set_attr "predicable" "yes")]
1220 (define_insn "smulsi3_highpart"
1221   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1222         (truncate:SI
1223          (lshiftrt:DI
1224           (mult:DI
1225            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1226            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1227           (const_int 32))))
1228    (clobber (match_scratch:SI 3 "=&r,&r"))]
1229   "TARGET_ARM && arm_arch3m"
1230   "smull%?\\t%3, %0, %2, %1"
1231   [(set_attr "insn" "smull")
1232    (set_attr "predicable" "yes")]
1235 (define_insn "umulsi3_highpart"
1236   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1237         (truncate:SI
1238          (lshiftrt:DI
1239           (mult:DI
1240            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1241            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1242           (const_int 32))))
1243    (clobber (match_scratch:SI 3 "=&r,&r"))]
1244   "TARGET_ARM && arm_arch3m"
1245   "umull%?\\t%3, %0, %2, %1"
1246   [(set_attr "insn" "umull")
1247    (set_attr "predicable" "yes")]
1250 (define_insn "mulhisi3"
1251   [(set (match_operand:SI 0 "s_register_operand" "=r")
1252         (mult:SI (sign_extend:SI
1253                   (match_operand:HI 1 "s_register_operand" "%r"))
1254                  (sign_extend:SI
1255                   (match_operand:HI 2 "s_register_operand" "r"))))]
1256   "TARGET_ARM && arm_arch5e"
1257   "smulbb%?\\t%0, %1, %2"
1258   [(set_attr "insn" "smulxy")
1259    (set_attr "predicable" "yes")]
1262 (define_insn "*mulhisi3tb"
1263   [(set (match_operand:SI 0 "s_register_operand" "=r")
1264         (mult:SI (ashiftrt:SI
1265                   (match_operand:SI 1 "s_register_operand" "r")
1266                   (const_int 16))
1267                  (sign_extend:SI
1268                   (match_operand:HI 2 "s_register_operand" "r"))))]
1269   "TARGET_ARM && arm_arch5e"
1270   "smultb%?\\t%0, %1, %2"
1271   [(set_attr "insn" "smulxy")
1272    (set_attr "predicable" "yes")]
1275 (define_insn "*mulhisi3bt"
1276   [(set (match_operand:SI 0 "s_register_operand" "=r")
1277         (mult:SI (sign_extend:SI
1278                   (match_operand:HI 1 "s_register_operand" "r"))
1279                  (ashiftrt:SI
1280                   (match_operand:SI 2 "s_register_operand" "r")
1281                   (const_int 16))))]
1282   "TARGET_ARM && arm_arch5e"
1283   "smulbt%?\\t%0, %1, %2"
1284   [(set_attr "insn" "smulxy")
1285    (set_attr "predicable" "yes")]
1288 (define_insn "*mulhisi3tt"
1289   [(set (match_operand:SI 0 "s_register_operand" "=r")
1290         (mult:SI (ashiftrt:SI
1291                   (match_operand:SI 1 "s_register_operand" "r")
1292                   (const_int 16))
1293                  (ashiftrt:SI
1294                   (match_operand:SI 2 "s_register_operand" "r")
1295                   (const_int 16))))]
1296   "TARGET_ARM && arm_arch5e"
1297   "smultt%?\\t%0, %1, %2"
1298   [(set_attr "insn" "smulxy")
1299    (set_attr "predicable" "yes")]
1302 (define_insn "*mulhisi3addsi"
1303   [(set (match_operand:SI 0 "s_register_operand" "=r")
1304         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1305                  (mult:SI (sign_extend:SI
1306                            (match_operand:HI 2 "s_register_operand" "%r"))
1307                           (sign_extend:SI
1308                            (match_operand:HI 3 "s_register_operand" "r")))))]
1309   "TARGET_ARM && arm_arch5e"
1310   "smlabb%?\\t%0, %2, %3, %1"
1311   [(set_attr "insn" "smlaxy")
1312    (set_attr "predicable" "yes")]
1315 (define_insn "*mulhidi3adddi"
1316   [(set (match_operand:DI 0 "s_register_operand" "=r")
1317         (plus:DI
1318           (match_operand:DI 1 "s_register_operand" "0")
1319           (mult:DI (sign_extend:DI
1320                     (match_operand:HI 2 "s_register_operand" "%r"))
1321                    (sign_extend:DI
1322                     (match_operand:HI 3 "s_register_operand" "r")))))]
1323   "TARGET_ARM && arm_arch5e"
1324   "smlalbb%?\\t%Q0, %R0, %2, %3"
1325   [(set_attr "insn" "smlalxy")
1326    (set_attr "predicable" "yes")])
1328 (define_expand "mulsf3"
1329   [(set (match_operand:SF          0 "s_register_operand" "")
1330         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1331                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1332   "TARGET_ARM && TARGET_HARD_FLOAT"
1333   "
1334   if (TARGET_MAVERICK
1335       && !cirrus_fp_register (operands[2], SFmode))
1336     operands[2] = force_reg (SFmode, operands[2]);
1339 (define_expand "muldf3"
1340   [(set (match_operand:DF          0 "s_register_operand" "")
1341         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1342                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1343   "TARGET_ARM && TARGET_HARD_FLOAT"
1344   "
1345   if (TARGET_MAVERICK
1346       && !cirrus_fp_register (operands[2], DFmode))
1347     operands[2] = force_reg (DFmode, operands[2]);
1350 ;; Division insns
1352 (define_expand "divsf3"
1353   [(set (match_operand:SF 0 "s_register_operand" "")
1354         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1355                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1356   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1357   "")
1359 (define_expand "divdf3"
1360   [(set (match_operand:DF 0 "s_register_operand" "")
1361         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1362                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1363   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1364   "")
1366 ;; Modulo insns
1368 (define_expand "modsf3"
1369   [(set (match_operand:SF 0 "s_register_operand" "")
1370         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1371                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1372   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1373   "")
1375 (define_expand "moddf3"
1376   [(set (match_operand:DF 0 "s_register_operand" "")
1377         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1378                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1379   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1380   "")
1382 ;; Boolean and,ior,xor insns
1384 ;; Split up double word logical operations
1386 ;; Split up simple DImode logical operations.  Simply perform the logical
1387 ;; operation on the upper and lower halves of the registers.
1388 (define_split
1389   [(set (match_operand:DI 0 "s_register_operand" "")
1390         (match_operator:DI 6 "logical_binary_operator"
1391           [(match_operand:DI 1 "s_register_operand" "")
1392            (match_operand:DI 2 "s_register_operand" "")]))]
1393   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1394   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1395    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1396   "
1397   {
1398     operands[3] = gen_highpart (SImode, operands[0]);
1399     operands[0] = gen_lowpart (SImode, operands[0]);
1400     operands[4] = gen_highpart (SImode, operands[1]);
1401     operands[1] = gen_lowpart (SImode, operands[1]);
1402     operands[5] = gen_highpart (SImode, operands[2]);
1403     operands[2] = gen_lowpart (SImode, operands[2]);
1404   }"
1407 (define_split
1408   [(set (match_operand:DI 0 "s_register_operand" "")
1409         (match_operator:DI 6 "logical_binary_operator"
1410           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1411            (match_operand:DI 1 "s_register_operand" "")]))]
1412   "TARGET_ARM && reload_completed"
1413   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1414    (set (match_dup 3) (match_op_dup:SI 6
1415                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1416                          (match_dup 4)]))]
1417   "
1418   {
1419     operands[3] = gen_highpart (SImode, operands[0]);
1420     operands[0] = gen_lowpart (SImode, operands[0]);
1421     operands[4] = gen_highpart (SImode, operands[1]);
1422     operands[1] = gen_lowpart (SImode, operands[1]);
1423     operands[5] = gen_highpart (SImode, operands[2]);
1424     operands[2] = gen_lowpart (SImode, operands[2]);
1425   }"
1428 ;; The zero extend of operand 2 means we can just copy the high part of
1429 ;; operand1 into operand0.
1430 (define_split
1431   [(set (match_operand:DI 0 "s_register_operand" "")
1432         (ior:DI
1433           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1434           (match_operand:DI 1 "s_register_operand" "")))]
1435   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1436   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1437    (set (match_dup 3) (match_dup 4))]
1438   "
1439   {
1440     operands[4] = gen_highpart (SImode, operands[1]);
1441     operands[3] = gen_highpart (SImode, operands[0]);
1442     operands[0] = gen_lowpart (SImode, operands[0]);
1443     operands[1] = gen_lowpart (SImode, operands[1]);
1444   }"
1447 ;; The zero extend of operand 2 means we can just copy the high part of
1448 ;; operand1 into operand0.
1449 (define_split
1450   [(set (match_operand:DI 0 "s_register_operand" "")
1451         (xor:DI
1452           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1453           (match_operand:DI 1 "s_register_operand" "")))]
1454   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1455   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1456    (set (match_dup 3) (match_dup 4))]
1457   "
1458   {
1459     operands[4] = gen_highpart (SImode, operands[1]);
1460     operands[3] = gen_highpart (SImode, operands[0]);
1461     operands[0] = gen_lowpart (SImode, operands[0]);
1462     operands[1] = gen_lowpart (SImode, operands[1]);
1463   }"
1466 (define_insn "anddi3"
1467   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1468         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1469                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1470   "TARGET_ARM && ! TARGET_IWMMXT"
1471   "#"
1472   [(set_attr "length" "8")]
1475 (define_insn_and_split "*anddi_zesidi_di"
1476   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1477         (and:DI (zero_extend:DI
1478                  (match_operand:SI 2 "s_register_operand" "r,r"))
1479                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1480   "TARGET_ARM"
1481   "#"
1482   "TARGET_ARM && reload_completed"
1483   ; The zero extend of operand 2 clears the high word of the output
1484   ; operand.
1485   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1486    (set (match_dup 3) (const_int 0))]
1487   "
1488   {
1489     operands[3] = gen_highpart (SImode, operands[0]);
1490     operands[0] = gen_lowpart (SImode, operands[0]);
1491     operands[1] = gen_lowpart (SImode, operands[1]);
1492   }"
1493   [(set_attr "length" "8")]
1496 (define_insn "*anddi_sesdi_di"
1497   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1498         (and:DI (sign_extend:DI
1499                  (match_operand:SI 2 "s_register_operand" "r,r"))
1500                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1501   "TARGET_ARM"
1502   "#"
1503   [(set_attr "length" "8")]
1506 (define_expand "andsi3"
1507   [(set (match_operand:SI         0 "s_register_operand" "")
1508         (and:SI (match_operand:SI 1 "s_register_operand" "")
1509                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1510   "TARGET_EITHER"
1511   "
1512   if (TARGET_ARM)
1513     {
1514       if (GET_CODE (operands[2]) == CONST_INT)
1515         {
1516           arm_split_constant (AND, SImode, NULL_RTX,
1517                               INTVAL (operands[2]), operands[0],
1518                               operands[1], optimize && !no_new_pseudos);
1520           DONE;
1521         }
1522     }
1523   else /* TARGET_THUMB */
1524     {
1525       if (GET_CODE (operands[2]) != CONST_INT)
1526         operands[2] = force_reg (SImode, operands[2]);
1527       else
1528         {
1529           int i;
1530           
1531           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1532             {
1533               operands[2] = force_reg (SImode,
1534                                        GEN_INT (~INTVAL (operands[2])));
1535               
1536               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1537               
1538               DONE;
1539             }
1541           for (i = 9; i <= 31; i++)
1542             {
1543               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1544                 {
1545                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1546                                         const0_rtx));
1547                   DONE;
1548                 }
1549               else if ((((HOST_WIDE_INT) 1) << i) - 1
1550                        == ~INTVAL (operands[2]))
1551                 {
1552                   rtx shift = GEN_INT (i);
1553                   rtx reg = gen_reg_rtx (SImode);
1554                 
1555                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1556                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1557                   
1558                   DONE;
1559                 }
1560             }
1562           operands[2] = force_reg (SImode, operands[2]);
1563         }
1564     }
1565   "
1568 (define_insn_and_split "*arm_andsi3_insn"
1569   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1570         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1571                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1572   "TARGET_ARM"
1573   "@
1574    and%?\\t%0, %1, %2
1575    bic%?\\t%0, %1, #%B2
1576    #"
1577   "TARGET_ARM
1578    && GET_CODE (operands[2]) == CONST_INT
1579    && !(const_ok_for_arm (INTVAL (operands[2]))
1580         || const_ok_for_arm (~INTVAL (operands[2])))"
1581   [(clobber (const_int 0))]
1582   "
1583   arm_split_constant  (AND, SImode, curr_insn, 
1584                        INTVAL (operands[2]), operands[0], operands[1], 0);
1585   DONE;
1586   "
1587   [(set_attr "length" "4,4,16")
1588    (set_attr "predicable" "yes")]
1591 (define_insn "*thumb_andsi3_insn"
1592   [(set (match_operand:SI         0 "register_operand" "=l")
1593         (and:SI (match_operand:SI 1 "register_operand" "%0")
1594                 (match_operand:SI 2 "register_operand" "l")))]
1595   "TARGET_THUMB"
1596   "and\\t%0, %0, %2"
1597   [(set_attr "length" "2")]
1600 (define_insn "*andsi3_compare0"
1601   [(set (reg:CC_NOOV CC_REGNUM)
1602         (compare:CC_NOOV
1603          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1604                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1605          (const_int 0)))
1606    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1607         (and:SI (match_dup 1) (match_dup 2)))]
1608   "TARGET_ARM"
1609   "@
1610    and%?s\\t%0, %1, %2
1611    bic%?s\\t%0, %1, #%B2"
1612   [(set_attr "conds" "set")]
1615 (define_insn "*andsi3_compare0_scratch"
1616   [(set (reg:CC_NOOV CC_REGNUM)
1617         (compare:CC_NOOV
1618          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1619                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1620          (const_int 0)))
1621    (clobber (match_scratch:SI 2 "=X,r"))]
1622   "TARGET_ARM"
1623   "@
1624    tst%?\\t%0, %1
1625    bic%?s\\t%2, %0, #%B1"
1626   [(set_attr "conds" "set")]
1629 (define_insn "*zeroextractsi_compare0_scratch"
1630   [(set (reg:CC_NOOV CC_REGNUM)
1631         (compare:CC_NOOV (zero_extract:SI
1632                           (match_operand:SI 0 "s_register_operand" "r")
1633                           (match_operand 1 "const_int_operand" "n")
1634                           (match_operand 2 "const_int_operand" "n"))
1635                          (const_int 0)))]
1636   "TARGET_ARM
1637   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1638       && INTVAL (operands[1]) > 0 
1639       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1640       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1641   "*
1642   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1643                          << INTVAL (operands[2]));
1644   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1645   return \"\";
1646   "
1647   [(set_attr "conds" "set")]
1650 (define_insn_and_split "*ne_zeroextractsi"
1651   [(set (match_operand:SI 0 "s_register_operand" "=r")
1652         (ne:SI (zero_extract:SI
1653                 (match_operand:SI 1 "s_register_operand" "r")
1654                 (match_operand:SI 2 "const_int_operand" "n")
1655                 (match_operand:SI 3 "const_int_operand" "n"))
1656                (const_int 0)))
1657    (clobber (reg:CC CC_REGNUM))]
1658   "TARGET_ARM
1659    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1660        && INTVAL (operands[2]) > 0 
1661        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1662        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1663   "#"
1664   "TARGET_ARM
1665    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1666        && INTVAL (operands[2]) > 0 
1667        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1668        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1669   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1670                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1671                                     (const_int 0)))
1672               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1673    (set (match_dup 0)
1674         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1675                          (match_dup 0) (const_int 1)))]
1676   "
1677   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1678                          << INTVAL (operands[3])); 
1679   "
1680   [(set_attr "conds" "clob")
1681    (set_attr "length" "8")]
1684 (define_insn_and_split "*ne_zeroextractsi_shifted"
1685   [(set (match_operand:SI 0 "s_register_operand" "=r")
1686         (ne:SI (zero_extract:SI
1687                 (match_operand:SI 1 "s_register_operand" "r")
1688                 (match_operand:SI 2 "const_int_operand" "n")
1689                 (const_int 0))
1690                (const_int 0)))
1691    (clobber (reg:CC CC_REGNUM))]
1692   "TARGET_ARM"
1693   "#"
1694   "TARGET_ARM"
1695   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1696                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1697                                     (const_int 0)))
1698               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1699    (set (match_dup 0)
1700         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1701                          (match_dup 0) (const_int 1)))]
1702   "
1703   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1704   "
1705   [(set_attr "conds" "clob")
1706    (set_attr "length" "8")]
1709 (define_insn_and_split "*ite_ne_zeroextractsi"
1710   [(set (match_operand:SI 0 "s_register_operand" "=r")
1711         (if_then_else:SI (ne (zero_extract:SI
1712                               (match_operand:SI 1 "s_register_operand" "r")
1713                               (match_operand:SI 2 "const_int_operand" "n")
1714                               (match_operand:SI 3 "const_int_operand" "n"))
1715                              (const_int 0))
1716                          (match_operand:SI 4 "arm_not_operand" "rIK")
1717                          (const_int 0)))
1718    (clobber (reg:CC CC_REGNUM))]
1719   "TARGET_ARM
1720    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1721        && INTVAL (operands[2]) > 0 
1722        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1723        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1724    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1725   "#"
1726   "TARGET_ARM
1727    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1728        && INTVAL (operands[2]) > 0 
1729        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1730        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1731    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1732   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1733                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1734                                     (const_int 0)))
1735               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1736    (set (match_dup 0)
1737         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1738                          (match_dup 0) (match_dup 4)))]
1739   "
1740   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1741                          << INTVAL (operands[3])); 
1742   "
1743   [(set_attr "conds" "clob")
1744    (set_attr "length" "8")]
1747 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1748   [(set (match_operand:SI 0 "s_register_operand" "=r")
1749         (if_then_else:SI (ne (zero_extract:SI
1750                               (match_operand:SI 1 "s_register_operand" "r")
1751                               (match_operand:SI 2 "const_int_operand" "n")
1752                               (const_int 0))
1753                              (const_int 0))
1754                          (match_operand:SI 3 "arm_not_operand" "rIK")
1755                          (const_int 0)))
1756    (clobber (reg:CC CC_REGNUM))]
1757   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1758   "#"
1759   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1760   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1761                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1762                                     (const_int 0)))
1763               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1764    (set (match_dup 0)
1765         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1766                          (match_dup 0) (match_dup 3)))]
1767   "
1768   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1769   "
1770   [(set_attr "conds" "clob")
1771    (set_attr "length" "8")]
1774 (define_split
1775   [(set (match_operand:SI 0 "s_register_operand" "")
1776         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1777                          (match_operand:SI 2 "const_int_operand" "")
1778                          (match_operand:SI 3 "const_int_operand" "")))
1779    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1780   "TARGET_THUMB"
1781   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1782    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1783   "{
1784      HOST_WIDE_INT temp = INTVAL (operands[2]);
1786      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1787      operands[3] = GEN_INT (32 - temp);
1788    }"
1791 (define_split
1792   [(set (match_operand:SI 0 "s_register_operand" "")
1793         (match_operator:SI 1 "shiftable_operator"
1794          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1795                            (match_operand:SI 3 "const_int_operand" "")
1796                            (match_operand:SI 4 "const_int_operand" ""))
1797           (match_operand:SI 5 "s_register_operand" "")]))
1798    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1799   "TARGET_ARM"
1800   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1801    (set (match_dup 0)
1802         (match_op_dup 1
1803          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1804           (match_dup 5)]))]
1805   "{
1806      HOST_WIDE_INT temp = INTVAL (operands[3]);
1808      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1809      operands[4] = GEN_INT (32 - temp);
1810    }"
1812   
1813 (define_split
1814   [(set (match_operand:SI 0 "s_register_operand" "")
1815         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1816                          (match_operand:SI 2 "const_int_operand" "")
1817                          (match_operand:SI 3 "const_int_operand" "")))]
1818   "TARGET_THUMB"
1819   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1820    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1821   "{
1822      HOST_WIDE_INT temp = INTVAL (operands[2]);
1824      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1825      operands[3] = GEN_INT (32 - temp);
1826    }"
1829 (define_split
1830   [(set (match_operand:SI 0 "s_register_operand" "")
1831         (match_operator:SI 1 "shiftable_operator"
1832          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1833                            (match_operand:SI 3 "const_int_operand" "")
1834                            (match_operand:SI 4 "const_int_operand" ""))
1835           (match_operand:SI 5 "s_register_operand" "")]))
1836    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1837   "TARGET_ARM"
1838   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1839    (set (match_dup 0)
1840         (match_op_dup 1
1841          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1842           (match_dup 5)]))]
1843   "{
1844      HOST_WIDE_INT temp = INTVAL (operands[3]);
1846      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1847      operands[4] = GEN_INT (32 - temp);
1848    }"
1850   
1851 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1852 ;;; represented by the bitfield, then this will produce incorrect results.
1853 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1854 ;;; which have a real bit-field insert instruction, the truncation happens
1855 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1856 ;;; bit-field insert instruction, we would have to emit code here to truncate
1857 ;;; the value before we insert.  This loses some of the advantage of having
1858 ;;; this insv pattern, so this pattern needs to be reevalutated.
1860 (define_expand "insv"
1861   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1862                          (match_operand:SI 1 "general_operand" "")
1863                          (match_operand:SI 2 "general_operand" ""))
1864         (match_operand:SI 3 "reg_or_int_operand" ""))]
1865   "TARGET_ARM"
1866   "
1867   {
1868     int start_bit = INTVAL (operands[2]);
1869     int width = INTVAL (operands[1]);
1870     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1871     rtx target, subtarget;
1873     target = operands[0];
1874     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1875        subreg as the final target.  */
1876     if (GET_CODE (target) == SUBREG)
1877       {
1878         subtarget = gen_reg_rtx (SImode);
1879         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1880             < GET_MODE_SIZE (SImode))
1881           target = SUBREG_REG (target);
1882       }
1883     else
1884       subtarget = target;    
1886     if (GET_CODE (operands[3]) == CONST_INT)
1887       {
1888         /* Since we are inserting a known constant, we may be able to
1889            reduce the number of bits that we have to clear so that
1890            the mask becomes simple.  */
1891         /* ??? This code does not check to see if the new mask is actually
1892            simpler.  It may not be.  */
1893         rtx op1 = gen_reg_rtx (SImode);
1894         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1895            start of this pattern.  */
1896         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1897         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1899         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1900         emit_insn (gen_iorsi3 (subtarget, op1,
1901                                gen_int_mode (op3_value << start_bit, SImode)));
1902       }
1903     else if (start_bit == 0
1904              && !(const_ok_for_arm (mask)
1905                   || const_ok_for_arm (~mask)))
1906       {
1907         /* A Trick, since we are setting the bottom bits in the word,
1908            we can shift operand[3] up, operand[0] down, OR them together
1909            and rotate the result back again.  This takes 3 insns, and
1910            the third might be mergeable into another op.  */
1911         /* The shift up copes with the possibility that operand[3] is
1912            wider than the bitfield.  */
1913         rtx op0 = gen_reg_rtx (SImode);
1914         rtx op1 = gen_reg_rtx (SImode);
1916         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1917         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1918         emit_insn (gen_iorsi3  (op1, op1, op0));
1919         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1920       }
1921     else if ((width + start_bit == 32)
1922              && !(const_ok_for_arm (mask)
1923                   || const_ok_for_arm (~mask)))
1924       {
1925         /* Similar trick, but slightly less efficient.  */
1927         rtx op0 = gen_reg_rtx (SImode);
1928         rtx op1 = gen_reg_rtx (SImode);
1930         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1931         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1932         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1933         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1934       }
1935     else
1936       {
1937         rtx op0 = GEN_INT (mask);
1938         rtx op1 = gen_reg_rtx (SImode);
1939         rtx op2 = gen_reg_rtx (SImode);
1941         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1942           {
1943             rtx tmp = gen_reg_rtx (SImode);
1945             emit_insn (gen_movsi (tmp, op0));
1946             op0 = tmp;
1947           }
1949         /* Mask out any bits in operand[3] that are not needed.  */
1950            emit_insn (gen_andsi3 (op1, operands[3], op0));
1952         if (GET_CODE (op0) == CONST_INT
1953             && (const_ok_for_arm (mask << start_bit)
1954                 || const_ok_for_arm (~(mask << start_bit))))
1955           {
1956             op0 = GEN_INT (~(mask << start_bit));
1957             emit_insn (gen_andsi3 (op2, operands[0], op0));
1958           }
1959         else
1960           {
1961             if (GET_CODE (op0) == CONST_INT)
1962               {
1963                 rtx tmp = gen_reg_rtx (SImode);
1965                 emit_insn (gen_movsi (tmp, op0));
1966                 op0 = tmp;
1967               }
1969             if (start_bit != 0)
1970               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1971             
1972             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1973           }
1975         if (start_bit != 0)
1976           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1978         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1979       }
1981     if (subtarget != target)
1982       {
1983         /* If TARGET is still a SUBREG, then it must be wider than a word,
1984            so we must be careful only to set the subword we were asked to.  */
1985         if (GET_CODE (target) == SUBREG)
1986           emit_move_insn (target, subtarget);
1987         else
1988           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1989       }
1991     DONE;
1992   }"
1995 ; constants for op 2 will never be given to these patterns.
1996 (define_insn_and_split "*anddi_notdi_di"
1997   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1998         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1999                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2000   "TARGET_ARM"
2001   "#"
2002   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2003   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2004    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2005   "
2006   {
2007     operands[3] = gen_highpart (SImode, operands[0]);
2008     operands[0] = gen_lowpart (SImode, operands[0]);
2009     operands[4] = gen_highpart (SImode, operands[1]);
2010     operands[1] = gen_lowpart (SImode, operands[1]);
2011     operands[5] = gen_highpart (SImode, operands[2]);
2012     operands[2] = gen_lowpart (SImode, operands[2]);
2013   }"
2014   [(set_attr "length" "8")
2015    (set_attr "predicable" "yes")]
2017   
2018 (define_insn_and_split "*anddi_notzesidi_di"
2019   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2020         (and:DI (not:DI (zero_extend:DI
2021                          (match_operand:SI 2 "s_register_operand" "r,r")))
2022                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2023   "TARGET_ARM"
2024   "@
2025    bic%?\\t%Q0, %Q1, %2
2026    #"
2027   ; (not (zero_extend ...)) allows us to just copy the high word from
2028   ; operand1 to operand0.
2029   "TARGET_ARM
2030    && reload_completed
2031    && operands[0] != operands[1]"
2032   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2033    (set (match_dup 3) (match_dup 4))]
2034   "
2035   {
2036     operands[3] = gen_highpart (SImode, operands[0]);
2037     operands[0] = gen_lowpart (SImode, operands[0]);
2038     operands[4] = gen_highpart (SImode, operands[1]);
2039     operands[1] = gen_lowpart (SImode, operands[1]);
2040   }"
2041   [(set_attr "length" "4,8")
2042    (set_attr "predicable" "yes")]
2044   
2045 (define_insn_and_split "*anddi_notsesidi_di"
2046   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2047         (and:DI (not:DI (sign_extend:DI
2048                          (match_operand:SI 2 "s_register_operand" "r,r")))
2049                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2050   "TARGET_ARM"
2051   "#"
2052   "TARGET_ARM && reload_completed"
2053   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2054    (set (match_dup 3) (and:SI (not:SI
2055                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2056                                (match_dup 4)))]
2057   "
2058   {
2059     operands[3] = gen_highpart (SImode, operands[0]);
2060     operands[0] = gen_lowpart (SImode, operands[0]);
2061     operands[4] = gen_highpart (SImode, operands[1]);
2062     operands[1] = gen_lowpart (SImode, operands[1]);
2063   }"
2064   [(set_attr "length" "8")
2065    (set_attr "predicable" "yes")]
2067   
2068 (define_insn "andsi_notsi_si"
2069   [(set (match_operand:SI 0 "s_register_operand" "=r")
2070         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2071                 (match_operand:SI 1 "s_register_operand" "r")))]
2072   "TARGET_ARM"
2073   "bic%?\\t%0, %1, %2"
2074   [(set_attr "predicable" "yes")]
2077 (define_insn "bicsi3"
2078   [(set (match_operand:SI                 0 "register_operand" "=l")
2079         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2080                 (match_operand:SI         2 "register_operand" "0")))]
2081   "TARGET_THUMB"
2082   "bic\\t%0, %0, %1"
2083   [(set_attr "length" "2")]
2086 (define_insn "andsi_not_shiftsi_si"
2087   [(set (match_operand:SI 0 "s_register_operand" "=r")
2088         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2089                          [(match_operand:SI 2 "s_register_operand" "r")
2090                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2091                 (match_operand:SI 1 "s_register_operand" "r")))]
2092   "TARGET_ARM"
2093   "bic%?\\t%0, %1, %2%S4"
2094   [(set_attr "predicable" "yes")
2095    (set_attr "shift" "2")
2096    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2097                       (const_string "alu_shift")
2098                       (const_string "alu_shift_reg")))]
2101 (define_insn "*andsi_notsi_si_compare0"
2102   [(set (reg:CC_NOOV CC_REGNUM)
2103         (compare:CC_NOOV
2104          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2105                  (match_operand:SI 1 "s_register_operand" "r"))
2106          (const_int 0)))
2107    (set (match_operand:SI 0 "s_register_operand" "=r")
2108         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2109   "TARGET_ARM"
2110   "bic%?s\\t%0, %1, %2"
2111   [(set_attr "conds" "set")]
2114 (define_insn "*andsi_notsi_si_compare0_scratch"
2115   [(set (reg:CC_NOOV CC_REGNUM)
2116         (compare:CC_NOOV
2117          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2118                  (match_operand:SI 1 "s_register_operand" "r"))
2119          (const_int 0)))
2120    (clobber (match_scratch:SI 0 "=r"))]
2121   "TARGET_ARM"
2122   "bic%?s\\t%0, %1, %2"
2123   [(set_attr "conds" "set")]
2126 (define_insn "iordi3"
2127   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2128         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2129                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2130   "TARGET_ARM && ! TARGET_IWMMXT"
2131   "#"
2132   [(set_attr "length" "8")
2133    (set_attr "predicable" "yes")]
2136 (define_insn "*iordi_zesidi_di"
2137   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2138         (ior:DI (zero_extend:DI
2139                  (match_operand:SI 2 "s_register_operand" "r,r"))
2140                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2141   "TARGET_ARM"
2142   "@
2143    orr%?\\t%Q0, %Q1, %2
2144    #"
2145   [(set_attr "length" "4,8")
2146    (set_attr "predicable" "yes")]
2149 (define_insn "*iordi_sesidi_di"
2150   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2151         (ior:DI (sign_extend:DI
2152                  (match_operand:SI 2 "s_register_operand" "r,r"))
2153                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2154   "TARGET_ARM"
2155   "#"
2156   [(set_attr "length" "8")
2157    (set_attr "predicable" "yes")]
2160 (define_expand "iorsi3"
2161   [(set (match_operand:SI         0 "s_register_operand" "")
2162         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2163                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2164   "TARGET_EITHER"
2165   "
2166   if (GET_CODE (operands[2]) == CONST_INT)
2167     {
2168       if (TARGET_ARM)
2169         {
2170           arm_split_constant (IOR, SImode, NULL_RTX,
2171                               INTVAL (operands[2]), operands[0], operands[1],
2172                               optimize && !no_new_pseudos);
2173           DONE;
2174         }
2175       else /* TARGET_THUMB */
2176         operands [2] = force_reg (SImode, operands [2]);
2177     }
2178   "
2181 (define_insn_and_split "*arm_iorsi3"
2182   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2183         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2184                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2185   "TARGET_ARM"
2186   "@
2187    orr%?\\t%0, %1, %2
2188    #"
2189   "TARGET_ARM
2190    && GET_CODE (operands[2]) == CONST_INT
2191    && !const_ok_for_arm (INTVAL (operands[2]))"
2192   [(clobber (const_int 0))]
2193   "
2194   arm_split_constant (IOR, SImode, curr_insn, 
2195                       INTVAL (operands[2]), operands[0], operands[1], 0);
2196   DONE;
2197   "
2198   [(set_attr "length" "4,16")
2199    (set_attr "predicable" "yes")]
2202 (define_insn "*thumb_iorsi3"
2203   [(set (match_operand:SI         0 "register_operand" "=l")
2204         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2205                 (match_operand:SI 2 "register_operand" "l")))]
2206   "TARGET_THUMB"
2207   "orr\\t%0, %0, %2"
2208   [(set_attr "length" "2")]
2211 (define_peephole2
2212   [(match_scratch:SI 3 "r")
2213    (set (match_operand:SI 0 "arm_general_register_operand" "")
2214         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2215                 (match_operand:SI 2 "const_int_operand" "")))]
2216   "TARGET_ARM
2217    && !const_ok_for_arm (INTVAL (operands[2]))
2218    && const_ok_for_arm (~INTVAL (operands[2]))"
2219   [(set (match_dup 3) (match_dup 2))
2220    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2221   ""
2224 (define_insn "*iorsi3_compare0"
2225   [(set (reg:CC_NOOV CC_REGNUM)
2226         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2227                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2228                          (const_int 0)))
2229    (set (match_operand:SI 0 "s_register_operand" "=r")
2230         (ior:SI (match_dup 1) (match_dup 2)))]
2231   "TARGET_ARM"
2232   "orr%?s\\t%0, %1, %2"
2233   [(set_attr "conds" "set")]
2236 (define_insn "*iorsi3_compare0_scratch"
2237   [(set (reg:CC_NOOV CC_REGNUM)
2238         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2239                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2240                          (const_int 0)))
2241    (clobber (match_scratch:SI 0 "=r"))]
2242   "TARGET_ARM"
2243   "orr%?s\\t%0, %1, %2"
2244   [(set_attr "conds" "set")]
2247 (define_insn "xordi3"
2248   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2249         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2250                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2251   "TARGET_ARM && !TARGET_IWMMXT"
2252   "#"
2253   [(set_attr "length" "8")
2254    (set_attr "predicable" "yes")]
2257 (define_insn "*xordi_zesidi_di"
2258   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2259         (xor:DI (zero_extend:DI
2260                  (match_operand:SI 2 "s_register_operand" "r,r"))
2261                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2262   "TARGET_ARM"
2263   "@
2264    eor%?\\t%Q0, %Q1, %2
2265    #"
2266   [(set_attr "length" "4,8")
2267    (set_attr "predicable" "yes")]
2270 (define_insn "*xordi_sesidi_di"
2271   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2272         (xor:DI (sign_extend:DI
2273                  (match_operand:SI 2 "s_register_operand" "r,r"))
2274                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2275   "TARGET_ARM"
2276   "#"
2277   [(set_attr "length" "8")
2278    (set_attr "predicable" "yes")]
2281 (define_expand "xorsi3"
2282   [(set (match_operand:SI         0 "s_register_operand" "")
2283         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2284                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2285   "TARGET_EITHER"
2286   "if (TARGET_THUMB)
2287      if (GET_CODE (operands[2]) == CONST_INT)
2288        operands[2] = force_reg (SImode, operands[2]);
2289   "
2292 (define_insn "*arm_xorsi3"
2293   [(set (match_operand:SI         0 "s_register_operand" "=r")
2294         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2295                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2296   "TARGET_ARM"
2297   "eor%?\\t%0, %1, %2"
2298   [(set_attr "predicable" "yes")]
2301 (define_insn "*thumb_xorsi3"
2302   [(set (match_operand:SI         0 "register_operand" "=l")
2303         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2304                 (match_operand:SI 2 "register_operand" "l")))]
2305   "TARGET_THUMB"
2306   "eor\\t%0, %0, %2"
2307   [(set_attr "length" "2")]
2310 (define_insn "*xorsi3_compare0"
2311   [(set (reg:CC_NOOV CC_REGNUM)
2312         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2313                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2314                          (const_int 0)))
2315    (set (match_operand:SI 0 "s_register_operand" "=r")
2316         (xor:SI (match_dup 1) (match_dup 2)))]
2317   "TARGET_ARM"
2318   "eor%?s\\t%0, %1, %2"
2319   [(set_attr "conds" "set")]
2322 (define_insn "*xorsi3_compare0_scratch"
2323   [(set (reg:CC_NOOV CC_REGNUM)
2324         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2325                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2326                          (const_int 0)))]
2327   "TARGET_ARM"
2328   "teq%?\\t%0, %1"
2329   [(set_attr "conds" "set")]
2332 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2333 ; (NOT D) we can sometimes merge the final NOT into one of the following
2334 ; insns.
2336 (define_split
2337   [(set (match_operand:SI 0 "s_register_operand" "")
2338         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2339                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2340                 (match_operand:SI 3 "arm_rhs_operand" "")))
2341    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2342   "TARGET_ARM"
2343   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2344                               (not:SI (match_dup 3))))
2345    (set (match_dup 0) (not:SI (match_dup 4)))]
2346   ""
2349 (define_insn "*andsi_iorsi3_notsi"
2350   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2351         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2352                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2353                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2354   "TARGET_ARM"
2355   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2356   [(set_attr "length" "8")
2357    (set_attr "predicable" "yes")]
2360 (define_split
2361   [(set (match_operand:SI 0 "s_register_operand" "")
2362         (match_operator:SI 1 "logical_binary_operator"
2363          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2364                            (match_operand:SI 3 "const_int_operand" "")
2365                            (match_operand:SI 4 "const_int_operand" ""))
2366           (match_operator:SI 9 "logical_binary_operator"
2367            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2368                          (match_operand:SI 6 "const_int_operand" ""))
2369             (match_operand:SI 7 "s_register_operand" "")])]))
2370    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2371   "TARGET_ARM
2372    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2373    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2374   [(set (match_dup 8)
2375         (match_op_dup 1
2376          [(ashift:SI (match_dup 2) (match_dup 4))
2377           (match_dup 5)]))
2378    (set (match_dup 0)
2379         (match_op_dup 1
2380          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2381           (match_dup 7)]))]
2382   "
2383   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2386 (define_split
2387   [(set (match_operand:SI 0 "s_register_operand" "")
2388         (match_operator:SI 1 "logical_binary_operator"
2389          [(match_operator:SI 9 "logical_binary_operator"
2390            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2391                          (match_operand:SI 6 "const_int_operand" ""))
2392             (match_operand:SI 7 "s_register_operand" "")])
2393           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2394                            (match_operand:SI 3 "const_int_operand" "")
2395                            (match_operand:SI 4 "const_int_operand" ""))]))
2396    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2397   "TARGET_ARM
2398    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2399    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2400   [(set (match_dup 8)
2401         (match_op_dup 1
2402          [(ashift:SI (match_dup 2) (match_dup 4))
2403           (match_dup 5)]))
2404    (set (match_dup 0)
2405         (match_op_dup 1
2406          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2407           (match_dup 7)]))]
2408   "
2409   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2412 (define_split
2413   [(set (match_operand:SI 0 "s_register_operand" "")
2414         (match_operator:SI 1 "logical_binary_operator"
2415          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2416                            (match_operand:SI 3 "const_int_operand" "")
2417                            (match_operand:SI 4 "const_int_operand" ""))
2418           (match_operator:SI 9 "logical_binary_operator"
2419            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2420                          (match_operand:SI 6 "const_int_operand" ""))
2421             (match_operand:SI 7 "s_register_operand" "")])]))
2422    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2423   "TARGET_ARM
2424    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2425    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2426   [(set (match_dup 8)
2427         (match_op_dup 1
2428          [(ashift:SI (match_dup 2) (match_dup 4))
2429           (match_dup 5)]))
2430    (set (match_dup 0)
2431         (match_op_dup 1
2432          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2433           (match_dup 7)]))]
2434   "
2435   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2438 (define_split
2439   [(set (match_operand:SI 0 "s_register_operand" "")
2440         (match_operator:SI 1 "logical_binary_operator"
2441          [(match_operator:SI 9 "logical_binary_operator"
2442            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2443                          (match_operand:SI 6 "const_int_operand" ""))
2444             (match_operand:SI 7 "s_register_operand" "")])
2445           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2446                            (match_operand:SI 3 "const_int_operand" "")
2447                            (match_operand:SI 4 "const_int_operand" ""))]))
2448    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2449   "TARGET_ARM
2450    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2451    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2452   [(set (match_dup 8)
2453         (match_op_dup 1
2454          [(ashift:SI (match_dup 2) (match_dup 4))
2455           (match_dup 5)]))
2456    (set (match_dup 0)
2457         (match_op_dup 1
2458          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2459           (match_dup 7)]))]
2460   "
2461   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2465 ;; Minimum and maximum insns
2467 (define_insn "smaxsi3"
2468   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2469         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2470                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2471    (clobber (reg:CC CC_REGNUM))]
2472   "TARGET_ARM"
2473   "@
2474    cmp\\t%1, %2\;movlt\\t%0, %2
2475    cmp\\t%1, %2\;movge\\t%0, %1
2476    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2477   [(set_attr "conds" "clob")
2478    (set_attr "length" "8,8,12")]
2481 (define_insn "sminsi3"
2482   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2483         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2484                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2485    (clobber (reg:CC CC_REGNUM))]
2486   "TARGET_ARM"
2487   "@
2488    cmp\\t%1, %2\;movge\\t%0, %2
2489    cmp\\t%1, %2\;movlt\\t%0, %1
2490    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2491   [(set_attr "conds" "clob")
2492    (set_attr "length" "8,8,12")]
2495 (define_insn "umaxsi3"
2496   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2497         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2498                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2499    (clobber (reg:CC CC_REGNUM))]
2500   "TARGET_ARM"
2501   "@
2502    cmp\\t%1, %2\;movcc\\t%0, %2
2503    cmp\\t%1, %2\;movcs\\t%0, %1
2504    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2505   [(set_attr "conds" "clob")
2506    (set_attr "length" "8,8,12")]
2509 (define_insn "uminsi3"
2510   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2511         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2512                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2513    (clobber (reg:CC CC_REGNUM))]
2514   "TARGET_ARM"
2515   "@
2516    cmp\\t%1, %2\;movcs\\t%0, %2
2517    cmp\\t%1, %2\;movcc\\t%0, %1
2518    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2519   [(set_attr "conds" "clob")
2520    (set_attr "length" "8,8,12")]
2523 (define_insn "*store_minmaxsi"
2524   [(set (match_operand:SI 0 "memory_operand" "=m")
2525         (match_operator:SI 3 "minmax_operator"
2526          [(match_operand:SI 1 "s_register_operand" "r")
2527           (match_operand:SI 2 "s_register_operand" "r")]))
2528    (clobber (reg:CC CC_REGNUM))]
2529   "TARGET_ARM"
2530   "*
2531   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2532                                 operands[1], operands[2]);
2533   output_asm_insn (\"cmp\\t%1, %2\", operands);
2534   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2535   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2536   return \"\";
2537   "
2538   [(set_attr "conds" "clob")
2539    (set_attr "length" "12")
2540    (set_attr "type" "store1")]
2543 ; Reject the frame pointer in operand[1], since reloading this after
2544 ; it has been eliminated can cause carnage.
2545 (define_insn "*minmax_arithsi"
2546   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2547         (match_operator:SI 4 "shiftable_operator"
2548          [(match_operator:SI 5 "minmax_operator"
2549            [(match_operand:SI 2 "s_register_operand" "r,r")
2550             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2551           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2552    (clobber (reg:CC CC_REGNUM))]
2553   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2554   "*
2555   {
2556     enum rtx_code code = GET_CODE (operands[4]);
2558     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2559                                   operands[2], operands[3]);
2560     output_asm_insn (\"cmp\\t%2, %3\", operands);
2561     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2562     if (which_alternative != 0 || operands[3] != const0_rtx
2563         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2564       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2565     return \"\";
2566   }"
2567   [(set_attr "conds" "clob")
2568    (set_attr "length" "12")]
2572 ;; Shift and rotation insns
2574 (define_expand "ashldi3"
2575   [(set (match_operand:DI            0 "s_register_operand" "")
2576         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2577                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2578   "TARGET_ARM"
2579   "
2580   if (GET_CODE (operands[2]) == CONST_INT)
2581     {
2582       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2583         {
2584           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2585           DONE;
2586         }
2587         /* Ideally we shouldn't fail here if we could know that operands[1] 
2588            ends up already living in an iwmmxt register. Otherwise it's
2589            cheaper to have the alternate code being generated than moving
2590            values to iwmmxt regs and back.  */
2591         FAIL;
2592     }
2593   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2594     FAIL;
2595   "
2598 (define_insn "arm_ashldi3_1bit"
2599   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2600         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2601                    (const_int 1)))
2602    (clobber (reg:CC CC_REGNUM))]
2603   "TARGET_ARM"
2604   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2605   [(set_attr "conds" "clob")
2606    (set_attr "length" "8")]
2609 (define_expand "ashlsi3"
2610   [(set (match_operand:SI            0 "s_register_operand" "")
2611         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2612                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2613   "TARGET_EITHER"
2614   "
2615   if (GET_CODE (operands[2]) == CONST_INT
2616       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2617     {
2618       emit_insn (gen_movsi (operands[0], const0_rtx));
2619       DONE;
2620     }
2621   "
2624 (define_insn "*thumb_ashlsi3"
2625   [(set (match_operand:SI            0 "register_operand" "=l,l")
2626         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2627                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2628   "TARGET_THUMB"
2629   "lsl\\t%0, %1, %2"
2630   [(set_attr "length" "2")]
2633 (define_expand "ashrdi3"
2634   [(set (match_operand:DI              0 "s_register_operand" "")
2635         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2636                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2637   "TARGET_ARM"
2638   "
2639   if (GET_CODE (operands[2]) == CONST_INT)
2640     {
2641       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2642         {
2643           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2644           DONE;
2645         }
2646         /* Ideally we shouldn't fail here if we could know that operands[1] 
2647            ends up already living in an iwmmxt register. Otherwise it's
2648            cheaper to have the alternate code being generated than moving
2649            values to iwmmxt regs and back.  */
2650         FAIL;
2651     }
2652   else if (!TARGET_REALLY_IWMMXT)
2653     FAIL;
2654   "
2657 (define_insn "arm_ashrdi3_1bit"
2658   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2659         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2660                      (const_int 1)))
2661    (clobber (reg:CC CC_REGNUM))]
2662   "TARGET_ARM"
2663   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2664   [(set_attr "conds" "clob")
2665    (set_attr "length" "8")]
2668 (define_expand "ashrsi3"
2669   [(set (match_operand:SI              0 "s_register_operand" "")
2670         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2671                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2672   "TARGET_EITHER"
2673   "
2674   if (GET_CODE (operands[2]) == CONST_INT
2675       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2676     operands[2] = GEN_INT (31);
2677   "
2680 (define_insn "*thumb_ashrsi3"
2681   [(set (match_operand:SI              0 "register_operand" "=l,l")
2682         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2683                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2684   "TARGET_THUMB"
2685   "asr\\t%0, %1, %2"
2686   [(set_attr "length" "2")]
2689 (define_expand "lshrdi3"
2690   [(set (match_operand:DI              0 "s_register_operand" "")
2691         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2692                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2693   "TARGET_ARM"
2694   "
2695   if (GET_CODE (operands[2]) == CONST_INT)
2696     {
2697       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2698         {
2699           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2700           DONE;
2701         }
2702         /* Ideally we shouldn't fail here if we could know that operands[1] 
2703            ends up already living in an iwmmxt register. Otherwise it's
2704            cheaper to have the alternate code being generated than moving
2705            values to iwmmxt regs and back.  */
2706         FAIL;
2707     }
2708   else if (!TARGET_REALLY_IWMMXT)
2709     FAIL;
2710   "
2713 (define_insn "arm_lshrdi3_1bit"
2714   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2715         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2716                      (const_int 1)))
2717    (clobber (reg:CC CC_REGNUM))]
2718   "TARGET_ARM"
2719   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2720   [(set_attr "conds" "clob")
2721    (set_attr "length" "8")]
2724 (define_expand "lshrsi3"
2725   [(set (match_operand:SI              0 "s_register_operand" "")
2726         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2727                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2728   "TARGET_EITHER"
2729   "
2730   if (GET_CODE (operands[2]) == CONST_INT
2731       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2732     {
2733       emit_insn (gen_movsi (operands[0], const0_rtx));
2734       DONE;
2735     }
2736   "
2739 (define_insn "*thumb_lshrsi3"
2740   [(set (match_operand:SI              0 "register_operand" "=l,l")
2741         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2742                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2743   "TARGET_THUMB"
2744   "lsr\\t%0, %1, %2"
2745   [(set_attr "length" "2")]
2748 (define_expand "rotlsi3"
2749   [(set (match_operand:SI              0 "s_register_operand" "")
2750         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2751                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2752   "TARGET_ARM"
2753   "
2754   if (GET_CODE (operands[2]) == CONST_INT)
2755     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2756   else
2757     {
2758       rtx reg = gen_reg_rtx (SImode);
2759       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2760       operands[2] = reg;
2761     }
2762   "
2765 (define_expand "rotrsi3"
2766   [(set (match_operand:SI              0 "s_register_operand" "")
2767         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2768                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2769   "TARGET_EITHER"
2770   "
2771   if (TARGET_ARM)
2772     {
2773       if (GET_CODE (operands[2]) == CONST_INT
2774           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2775         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2776     }
2777   else /* TARGET_THUMB */
2778     {
2779       if (GET_CODE (operands [2]) == CONST_INT)
2780         operands [2] = force_reg (SImode, operands[2]);
2781     }
2782   "
2785 (define_insn "*thumb_rotrsi3"
2786   [(set (match_operand:SI              0 "register_operand" "=l")
2787         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2788                      (match_operand:SI 2 "register_operand" "l")))]
2789   "TARGET_THUMB"
2790   "ror\\t%0, %0, %2"
2791   [(set_attr "length" "2")]
2794 (define_insn "*arm_shiftsi3"
2795   [(set (match_operand:SI   0 "s_register_operand" "=r")
2796         (match_operator:SI  3 "shift_operator"
2797          [(match_operand:SI 1 "s_register_operand"  "r")
2798           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2799   "TARGET_ARM"
2800   "mov%?\\t%0, %1%S3"
2801   [(set_attr "predicable" "yes")
2802    (set_attr "shift" "1")
2803    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2804                       (const_string "alu_shift")
2805                       (const_string "alu_shift_reg")))]
2808 (define_insn "*shiftsi3_compare0"
2809   [(set (reg:CC_NOOV CC_REGNUM)
2810         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2811                           [(match_operand:SI 1 "s_register_operand" "r")
2812                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2813                          (const_int 0)))
2814    (set (match_operand:SI 0 "s_register_operand" "=r")
2815         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2816   "TARGET_ARM"
2817   "mov%?s\\t%0, %1%S3"
2818   [(set_attr "conds" "set")
2819    (set_attr "shift" "1")
2820    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2821                       (const_string "alu_shift")
2822                       (const_string "alu_shift_reg")))]
2825 (define_insn "*shiftsi3_compare0_scratch"
2826   [(set (reg:CC_NOOV CC_REGNUM)
2827         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2828                           [(match_operand:SI 1 "s_register_operand" "r")
2829                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2830                          (const_int 0)))
2831    (clobber (match_scratch:SI 0 "=r"))]
2832   "TARGET_ARM"
2833   "mov%?s\\t%0, %1%S3"
2834   [(set_attr "conds" "set")
2835    (set_attr "shift" "1")]
2838 (define_insn "*notsi_shiftsi"
2839   [(set (match_operand:SI 0 "s_register_operand" "=r")
2840         (not:SI (match_operator:SI 3 "shift_operator"
2841                  [(match_operand:SI 1 "s_register_operand" "r")
2842                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2843   "TARGET_ARM"
2844   "mvn%?\\t%0, %1%S3"
2845   [(set_attr "predicable" "yes")
2846    (set_attr "shift" "1")
2847    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2848                       (const_string "alu_shift")
2849                       (const_string "alu_shift_reg")))]
2852 (define_insn "*notsi_shiftsi_compare0"
2853   [(set (reg:CC_NOOV CC_REGNUM)
2854         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2855                           [(match_operand:SI 1 "s_register_operand" "r")
2856                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2857                          (const_int 0)))
2858    (set (match_operand:SI 0 "s_register_operand" "=r")
2859         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2860   "TARGET_ARM"
2861   "mvn%?s\\t%0, %1%S3"
2862   [(set_attr "conds" "set")
2863    (set_attr "shift" "1")
2864    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2865                       (const_string "alu_shift")
2866                       (const_string "alu_shift_reg")))]
2869 (define_insn "*not_shiftsi_compare0_scratch"
2870   [(set (reg:CC_NOOV CC_REGNUM)
2871         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2872                           [(match_operand:SI 1 "s_register_operand" "r")
2873                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2874                          (const_int 0)))
2875    (clobber (match_scratch:SI 0 "=r"))]
2876   "TARGET_ARM"
2877   "mvn%?s\\t%0, %1%S3"
2878   [(set_attr "conds" "set")
2879    (set_attr "shift" "1")
2880    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2881                       (const_string "alu_shift")
2882                       (const_string "alu_shift_reg")))]
2885 ;; We don't really have extzv, but defining this using shifts helps
2886 ;; to reduce register pressure later on.
2888 (define_expand "extzv"
2889   [(set (match_dup 4)
2890         (ashift:SI (match_operand:SI   1 "register_operand" "")
2891                    (match_operand:SI   2 "const_int_operand" "")))
2892    (set (match_operand:SI              0 "register_operand" "")
2893         (lshiftrt:SI (match_dup 4)
2894                      (match_operand:SI 3 "const_int_operand" "")))]
2895   "TARGET_THUMB"
2896   "
2897   {
2898     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2899     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2900     
2901     operands[3] = GEN_INT (rshift);
2902     
2903     if (lshift == 0)
2904       {
2905         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2906         DONE;
2907       }
2908       
2909     operands[2] = GEN_INT (lshift);
2910     operands[4] = gen_reg_rtx (SImode);
2911   }"
2915 ;; Unary arithmetic insns
2917 (define_expand "negdi2"
2918  [(parallel
2919    [(set (match_operand:DI          0 "s_register_operand" "")
2920           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2921     (clobber (reg:CC CC_REGNUM))])]
2922   "TARGET_EITHER"
2923   "
2924   if (TARGET_THUMB)
2925     {
2926       if (GET_CODE (operands[1]) != REG)
2927         operands[1] = force_reg (SImode, operands[1]);
2928      }
2929   "
2932 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2933 ;; The second alternative is to allow the common case of a *full* overlap.
2934 (define_insn "*arm_negdi2"
2935   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2936         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2937    (clobber (reg:CC CC_REGNUM))]
2938   "TARGET_ARM"
2939   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2940   [(set_attr "conds" "clob")
2941    (set_attr "length" "8")]
2944 (define_insn "*thumb_negdi2"
2945   [(set (match_operand:DI         0 "register_operand" "=&l")
2946         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2947    (clobber (reg:CC CC_REGNUM))]
2948   "TARGET_THUMB"
2949   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2950   [(set_attr "length" "6")]
2953 (define_expand "negsi2"
2954   [(set (match_operand:SI         0 "s_register_operand" "")
2955         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2956   "TARGET_EITHER"
2957   ""
2960 (define_insn "*arm_negsi2"
2961   [(set (match_operand:SI         0 "s_register_operand" "=r")
2962         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2963   "TARGET_ARM"
2964   "rsb%?\\t%0, %1, #0"
2965   [(set_attr "predicable" "yes")]
2968 (define_insn "*thumb_negsi2"
2969   [(set (match_operand:SI         0 "register_operand" "=l")
2970         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2971   "TARGET_THUMB"
2972   "neg\\t%0, %1"
2973   [(set_attr "length" "2")]
2976 (define_expand "negsf2"
2977   [(set (match_operand:SF         0 "s_register_operand" "")
2978         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2979   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2980   ""
2983 (define_expand "negdf2"
2984   [(set (match_operand:DF         0 "s_register_operand" "")
2985         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2986   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2987   "")
2989 ;; abssi2 doesn't really clobber the condition codes if a different register
2990 ;; is being set.  To keep things simple, assume during rtl manipulations that
2991 ;; it does, but tell the final scan operator the truth.  Similarly for
2992 ;; (neg (abs...))
2994 (define_expand "abssi2"
2995   [(parallel
2996     [(set (match_operand:SI         0 "s_register_operand" "")
2997           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2998      (clobber (reg:CC CC_REGNUM))])]
2999   "TARGET_ARM"
3000   "")
3002 (define_insn "*arm_abssi2"
3003   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3004         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3005    (clobber (reg:CC CC_REGNUM))]
3006   "TARGET_ARM"
3007   "@
3008    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3009    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3010   [(set_attr "conds" "clob,*")
3011    (set_attr "shift" "1")
3012    ;; predicable can't be set based on the variant, so left as no
3013    (set_attr "length" "8")]
3016 (define_insn "*neg_abssi2"
3017   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3018         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3019    (clobber (reg:CC CC_REGNUM))]
3020   "TARGET_ARM"
3021   "@
3022    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3023    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3024   [(set_attr "conds" "clob,*")
3025    (set_attr "shift" "1")
3026    ;; predicable can't be set based on the variant, so left as no
3027    (set_attr "length" "8")]
3030 (define_expand "abssf2"
3031   [(set (match_operand:SF         0 "s_register_operand" "")
3032         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3033   "TARGET_ARM && TARGET_HARD_FLOAT"
3034   "")
3036 (define_expand "absdf2"
3037   [(set (match_operand:DF         0 "s_register_operand" "")
3038         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3039   "TARGET_ARM && TARGET_HARD_FLOAT"
3040   "")
3042 (define_expand "sqrtsf2"
3043   [(set (match_operand:SF 0 "s_register_operand" "")
3044         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3045   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3046   "")
3048 (define_expand "sqrtdf2"
3049   [(set (match_operand:DF 0 "s_register_operand" "")
3050         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3051   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3052   "")
3054 (define_insn_and_split "one_cmpldi2"
3055   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3056         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3057   "TARGET_ARM"
3058   "#"
3059   "TARGET_ARM && reload_completed"
3060   [(set (match_dup 0) (not:SI (match_dup 1)))
3061    (set (match_dup 2) (not:SI (match_dup 3)))]
3062   "
3063   {
3064     operands[2] = gen_highpart (SImode, operands[0]);
3065     operands[0] = gen_lowpart (SImode, operands[0]);
3066     operands[3] = gen_highpart (SImode, operands[1]);
3067     operands[1] = gen_lowpart (SImode, operands[1]);
3068   }"
3069   [(set_attr "length" "8")
3070    (set_attr "predicable" "yes")]
3073 (define_expand "one_cmplsi2"
3074   [(set (match_operand:SI         0 "s_register_operand" "")
3075         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3076   "TARGET_EITHER"
3077   ""
3080 (define_insn "*arm_one_cmplsi2"
3081   [(set (match_operand:SI         0 "s_register_operand" "=r")
3082         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3083   "TARGET_ARM"
3084   "mvn%?\\t%0, %1"
3085   [(set_attr "predicable" "yes")]
3088 (define_insn "*thumb_one_cmplsi2"
3089   [(set (match_operand:SI         0 "register_operand" "=l")
3090         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3091   "TARGET_THUMB"
3092   "mvn\\t%0, %1"
3093   [(set_attr "length" "2")]
3096 (define_insn "*notsi_compare0"
3097   [(set (reg:CC_NOOV CC_REGNUM)
3098         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3099                          (const_int 0)))
3100    (set (match_operand:SI 0 "s_register_operand" "=r")
3101         (not:SI (match_dup 1)))]
3102   "TARGET_ARM"
3103   "mvn%?s\\t%0, %1"
3104   [(set_attr "conds" "set")]
3107 (define_insn "*notsi_compare0_scratch"
3108   [(set (reg:CC_NOOV CC_REGNUM)
3109         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3110                          (const_int 0)))
3111    (clobber (match_scratch:SI 0 "=r"))]
3112   "TARGET_ARM"
3113   "mvn%?s\\t%0, %1"
3114   [(set_attr "conds" "set")]
3117 ;; Fixed <--> Floating conversion insns
3119 (define_expand "floatsisf2"
3120   [(set (match_operand:SF           0 "s_register_operand" "")
3121         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3122   "TARGET_ARM && TARGET_HARD_FLOAT"
3123   "
3124   if (TARGET_MAVERICK)
3125     {
3126       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3127       DONE;
3128     }
3131 (define_expand "floatsidf2"
3132   [(set (match_operand:DF           0 "s_register_operand" "")
3133         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3134   "TARGET_ARM && TARGET_HARD_FLOAT"
3135   "
3136   if (TARGET_MAVERICK)
3137     {
3138       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3139       DONE;
3140     }
3143 (define_expand "fix_truncsfsi2"
3144   [(set (match_operand:SI         0 "s_register_operand" "")
3145         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3146   "TARGET_ARM && TARGET_HARD_FLOAT"
3147   "
3148   if (TARGET_MAVERICK)
3149     {
3150       if (!cirrus_fp_register (operands[0], SImode))
3151         operands[0] = force_reg (SImode, operands[0]);
3152       if (!cirrus_fp_register (operands[1], SFmode))
3153         operands[1] = force_reg (SFmode, operands[0]);
3154       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3155       DONE;
3156     }
3159 (define_expand "fix_truncdfsi2"
3160   [(set (match_operand:SI         0 "s_register_operand" "")
3161         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3162   "TARGET_ARM && TARGET_HARD_FLOAT"
3163   "
3164   if (TARGET_MAVERICK)
3165     {
3166       if (!cirrus_fp_register (operands[1], DFmode))
3167         operands[1] = force_reg (DFmode, operands[0]);
3168       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3169       DONE;
3170     }
3173 ;; Truncation insns
3175 (define_expand "truncdfsf2"
3176   [(set (match_operand:SF  0 "s_register_operand" "")
3177         (float_truncate:SF
3178          (match_operand:DF 1 "s_register_operand" "")))]
3179   "TARGET_ARM && TARGET_HARD_FLOAT"
3180   ""
3183 ;; Zero and sign extension instructions.
3185 (define_insn "zero_extendsidi2"
3186   [(set (match_operand:DI 0 "s_register_operand" "=r")
3187         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3188   "TARGET_ARM"
3189   "*
3190     if (REGNO (operands[1])
3191         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3192       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3193     return \"mov%?\\t%R0, #0\";
3194   "
3195   [(set_attr "length" "8")
3196    (set_attr "predicable" "yes")]
3199 (define_insn "zero_extendqidi2"
3200   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3201         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3202   "TARGET_ARM"
3203   "@
3204    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3205    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3206   [(set_attr "length" "8")
3207    (set_attr "predicable" "yes")
3208    (set_attr "type" "*,load_byte")
3209    (set_attr "pool_range" "*,4092")
3210    (set_attr "neg_pool_range" "*,4084")]
3213 (define_insn "extendsidi2"
3214   [(set (match_operand:DI 0 "s_register_operand" "=r")
3215         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3216   "TARGET_ARM"
3217   "*
3218     if (REGNO (operands[1])
3219         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3220       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3221     return \"mov%?\\t%R0, %Q0, asr #31\";
3222   "
3223   [(set_attr "length" "8")
3224    (set_attr "shift" "1")
3225    (set_attr "predicable" "yes")]
3228 (define_expand "zero_extendhisi2"
3229   [(set (match_dup 2)
3230         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3231                    (const_int 16)))
3232    (set (match_operand:SI 0 "s_register_operand" "")
3233         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3234   "TARGET_EITHER"
3235   "
3236   {
3237     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3238       {
3239         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3240                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3241         DONE;
3242       }
3244     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3245       {
3246         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3247         DONE;
3248       }
3250     if (!s_register_operand (operands[1], HImode))
3251       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3253     if (arm_arch6)
3254       {
3255         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3256                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3257         DONE;
3258       }
3260     operands[1] = gen_lowpart (SImode, operands[1]);
3261     operands[2] = gen_reg_rtx (SImode);
3262   }"
3265 (define_insn "*thumb_zero_extendhisi2"
3266   [(set (match_operand:SI 0 "register_operand" "=l")
3267         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3268   "TARGET_THUMB && !arm_arch6"
3269   "*
3270   rtx mem = XEXP (operands[1], 0);
3272   if (GET_CODE (mem) == CONST)
3273     mem = XEXP (mem, 0);
3274     
3275   if (GET_CODE (mem) == LABEL_REF)
3276     return \"ldr\\t%0, %1\";
3277     
3278   if (GET_CODE (mem) == PLUS)
3279     {
3280       rtx a = XEXP (mem, 0);
3281       rtx b = XEXP (mem, 1);
3283       /* This can happen due to bugs in reload.  */
3284       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3285         {
3286           rtx ops[2];
3287           ops[0] = operands[0];
3288           ops[1] = a;
3289       
3290           output_asm_insn (\"mov        %0, %1\", ops);
3292           XEXP (mem, 0) = operands[0];
3293        }
3295       else if (   GET_CODE (a) == LABEL_REF
3296                && GET_CODE (b) == CONST_INT)
3297         return \"ldr\\t%0, %1\";
3298     }
3299     
3300   return \"ldrh\\t%0, %1\";
3301   "
3302   [(set_attr "length" "4")
3303    (set_attr "type" "load_byte")
3304    (set_attr "pool_range" "60")]
3307 (define_insn "*thumb_zero_extendhisi2_v6"
3308   [(set (match_operand:SI 0 "register_operand" "=l,l")
3309         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3310   "TARGET_THUMB && arm_arch6"
3311   "*
3312   rtx mem;
3314   if (which_alternative == 0)
3315     return \"uxth\\t%0, %1\";
3317   mem = XEXP (operands[1], 0);
3319   if (GET_CODE (mem) == CONST)
3320     mem = XEXP (mem, 0);
3321     
3322   if (GET_CODE (mem) == LABEL_REF)
3323     return \"ldr\\t%0, %1\";
3324     
3325   if (GET_CODE (mem) == PLUS)
3326     {
3327       rtx a = XEXP (mem, 0);
3328       rtx b = XEXP (mem, 1);
3330       /* This can happen due to bugs in reload.  */
3331       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3332         {
3333           rtx ops[2];
3334           ops[0] = operands[0];
3335           ops[1] = a;
3336       
3337           output_asm_insn (\"mov        %0, %1\", ops);
3339           XEXP (mem, 0) = operands[0];
3340        }
3342       else if (   GET_CODE (a) == LABEL_REF
3343                && GET_CODE (b) == CONST_INT)
3344         return \"ldr\\t%0, %1\";
3345     }
3346     
3347   return \"ldrh\\t%0, %1\";
3348   "
3349   [(set_attr "length" "2,4")
3350    (set_attr "type" "alu_shift,load_byte")
3351    (set_attr "pool_range" "*,60")]
3354 (define_insn "*arm_zero_extendhisi2"
3355   [(set (match_operand:SI 0 "s_register_operand" "=r")
3356         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3357   "TARGET_ARM && arm_arch4 && !arm_arch6"
3358   "ldr%?h\\t%0, %1"
3359   [(set_attr "type" "load_byte")
3360    (set_attr "predicable" "yes")
3361    (set_attr "pool_range" "256")
3362    (set_attr "neg_pool_range" "244")]
3365 (define_insn "*arm_zero_extendhisi2_v6"
3366   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3367         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3368   "TARGET_ARM && arm_arch6"
3369   "@
3370    uxth%?\\t%0, %1
3371    ldr%?h\\t%0, %1"
3372   [(set_attr "type" "alu_shift,load_byte")
3373    (set_attr "predicable" "yes")
3374    (set_attr "pool_range" "*,256")
3375    (set_attr "neg_pool_range" "*,244")]
3378 (define_insn "*arm_zero_extendhisi2addsi"
3379   [(set (match_operand:SI 0 "s_register_operand" "=r")
3380         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3381                  (match_operand:SI 2 "s_register_operand" "r")))]
3382   "TARGET_ARM && arm_arch6"
3383   "uxtah%?\\t%0, %2, %1"
3384   [(set_attr "type" "alu_shift")
3385    (set_attr "predicable" "yes")]
3388 (define_split
3389   [(set (match_operand:SI 0 "s_register_operand" "")
3390         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3391    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3392   "TARGET_ARM && (!arm_arch4)"
3393   [(set (match_dup 2) (match_dup 1))
3394    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3395   "
3396   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3397     FAIL;
3398   "
3401 (define_split
3402   [(set (match_operand:SI 0 "s_register_operand" "")
3403         (match_operator:SI 3 "shiftable_operator"
3404          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3405           (match_operand:SI 4 "s_register_operand" "")]))
3406    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3407   "TARGET_ARM && (!arm_arch4)"
3408   [(set (match_dup 2) (match_dup 1))
3409    (set (match_dup 0)
3410         (match_op_dup 3
3411          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3412   "
3413   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3414     FAIL;
3415   "
3418 (define_expand "zero_extendqisi2"
3419   [(set (match_operand:SI 0 "s_register_operand" "")
3420         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3421   "TARGET_EITHER"
3422   "
3423   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3424     {
3425       if (TARGET_ARM)
3426         {
3427           emit_insn (gen_andsi3 (operands[0],
3428                                  gen_lowpart (SImode, operands[1]),
3429                                  GEN_INT (255)));
3430         }
3431       else /* TARGET_THUMB */
3432         {
3433           rtx temp = gen_reg_rtx (SImode);
3434           rtx ops[3];
3435           
3436           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3437           operands[1] = gen_lowpart (SImode, operands[1]);
3439           ops[0] = temp;
3440           ops[1] = operands[1];
3441           ops[2] = GEN_INT (24);
3443           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3444                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3445           
3446           ops[0] = operands[0];
3447           ops[1] = temp;
3448           ops[2] = GEN_INT (24);
3450           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3451                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3452         }
3453       DONE;
3454     }
3455   "
3458 (define_insn "*thumb_zero_extendqisi2"
3459   [(set (match_operand:SI 0 "register_operand" "=l")
3460         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3461   "TARGET_THUMB && !arm_arch6"
3462   "ldrb\\t%0, %1"
3463   [(set_attr "length" "2")
3464    (set_attr "type" "load_byte")
3465    (set_attr "pool_range" "32")]
3468 (define_insn "*thumb_zero_extendqisi2_v6"
3469   [(set (match_operand:SI 0 "register_operand" "=l,l")
3470         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3471   "TARGET_THUMB && arm_arch6"
3472   "@
3473    uxtb\\t%0, %1
3474    ldrb\\t%0, %1"
3475   [(set_attr "length" "2,2")
3476    (set_attr "type" "alu_shift,load_byte")
3477    (set_attr "pool_range" "*,32")]
3480 (define_insn "*arm_zero_extendqisi2"
3481   [(set (match_operand:SI 0 "s_register_operand" "=r")
3482         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3483   "TARGET_ARM && !arm_arch6"
3484   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3485   [(set_attr "type" "load_byte")
3486    (set_attr "predicable" "yes")
3487    (set_attr "pool_range" "4096")
3488    (set_attr "neg_pool_range" "4084")]
3491 (define_insn "*arm_zero_extendqisi2_v6"
3492   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3493         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3494   "TARGET_ARM && arm_arch6"
3495   "@
3496    uxtb%?\\t%0, %1
3497    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3498   [(set_attr "type" "alu_shift,load_byte")
3499    (set_attr "predicable" "yes")
3500    (set_attr "pool_range" "*,4096")
3501    (set_attr "neg_pool_range" "*,4084")]
3504 (define_insn "*arm_zero_extendqisi2addsi"
3505   [(set (match_operand:SI 0 "s_register_operand" "=r")
3506         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3507                  (match_operand:SI 2 "s_register_operand" "r")))]
3508   "TARGET_ARM && arm_arch6"
3509   "uxtab%?\\t%0, %2, %1"
3510   [(set_attr "predicable" "yes")
3511    (set_attr "type" "alu_shift")]
3514 (define_split
3515   [(set (match_operand:SI 0 "s_register_operand" "")
3516         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3517    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3518   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3519   [(set (match_dup 2) (match_dup 1))
3520    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3521   ""
3524 (define_insn "*compareqi_eq0"
3525   [(set (reg:CC_Z CC_REGNUM)
3526         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3527                          (const_int 0)))]
3528   "TARGET_ARM"
3529   "tst\\t%0, #255"
3530   [(set_attr "conds" "set")]
3533 (define_expand "extendhisi2"
3534   [(set (match_dup 2)
3535         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3536                    (const_int 16)))
3537    (set (match_operand:SI 0 "s_register_operand" "")
3538         (ashiftrt:SI (match_dup 2)
3539                      (const_int 16)))]
3540   "TARGET_EITHER"
3541   "
3542   {
3543     if (GET_CODE (operands[1]) == MEM)
3544       {
3545         if (TARGET_THUMB)
3546           {
3547             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3548             DONE;
3549           }
3550         else if (arm_arch4)
3551           {
3552             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3553                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3554             DONE;
3555           }
3556       }
3558     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3559       {
3560         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3561         DONE;
3562       }
3564     if (!s_register_operand (operands[1], HImode))
3565       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3567     if (arm_arch6)
3568       {
3569         if (TARGET_THUMB)
3570           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3571         else
3572           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3573                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3575         DONE;
3576       }
3578     operands[1] = gen_lowpart (SImode, operands[1]);
3579     operands[2] = gen_reg_rtx (SImode);
3580   }"
3583 (define_insn "thumb_extendhisi2"
3584   [(set (match_operand:SI 0 "register_operand" "=l")
3585         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3586    (clobber (match_scratch:SI 2 "=&l"))]
3587   "TARGET_THUMB && !arm_arch6"
3588   "*
3589   {
3590     rtx ops[4];
3591     rtx mem = XEXP (operands[1], 0);
3593     /* This code used to try to use 'V', and fix the address only if it was
3594        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3595        range of QImode offsets, and offsettable_address_p does a QImode
3596        address check.  */
3597        
3598     if (GET_CODE (mem) == CONST)
3599       mem = XEXP (mem, 0);
3600     
3601     if (GET_CODE (mem) == LABEL_REF)
3602       return \"ldr\\t%0, %1\";
3603     
3604     if (GET_CODE (mem) == PLUS)
3605       {
3606         rtx a = XEXP (mem, 0);
3607         rtx b = XEXP (mem, 1);
3609         if (GET_CODE (a) == LABEL_REF
3610             && GET_CODE (b) == CONST_INT)
3611           return \"ldr\\t%0, %1\";
3613         if (GET_CODE (b) == REG)
3614           return \"ldrsh\\t%0, %1\";
3615           
3616         ops[1] = a;
3617         ops[2] = b;
3618       }
3619     else
3620       {
3621         ops[1] = mem;
3622         ops[2] = const0_rtx;
3623       }
3624       
3625     if (GET_CODE (ops[1]) != REG)
3626       {
3627         debug_rtx (ops[1]);
3628         abort ();
3629       }
3631     ops[0] = operands[0];
3632     ops[3] = operands[2];
3633     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3634     return \"\";
3635   }"
3636   [(set_attr "length" "4")
3637    (set_attr "type" "load_byte")
3638    (set_attr "pool_range" "1020")]
3641 ;; We used to have an early-clobber on the scratch register here.
3642 ;; However, there's a bug somewhere in reload which means that this
3643 ;; can be partially ignored during spill allocation if the memory
3644 ;; address also needs reloading; this causes an abort later on when
3645 ;; we try to verify the operands.  Fortunately, we don't really need
3646 ;; the early-clobber: we can always use operand 0 if operand 2
3647 ;; overlaps the address.
3648 (define_insn "*thumb_extendhisi2_insn_v6"
3649   [(set (match_operand:SI 0 "register_operand" "=l,l")
3650         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3651    (clobber (match_scratch:SI 2 "=X,l"))]
3652   "TARGET_THUMB && arm_arch6"
3653   "*
3654   {
3655     rtx ops[4];
3656     rtx mem;
3658     if (which_alternative == 0)
3659       return \"sxth\\t%0, %1\";
3661     mem = XEXP (operands[1], 0);
3663     /* This code used to try to use 'V', and fix the address only if it was
3664        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3665        range of QImode offsets, and offsettable_address_p does a QImode
3666        address check.  */
3667        
3668     if (GET_CODE (mem) == CONST)
3669       mem = XEXP (mem, 0);
3670     
3671     if (GET_CODE (mem) == LABEL_REF)
3672       return \"ldr\\t%0, %1\";
3673     
3674     if (GET_CODE (mem) == PLUS)
3675       {
3676         rtx a = XEXP (mem, 0);
3677         rtx b = XEXP (mem, 1);
3679         if (GET_CODE (a) == LABEL_REF
3680             && GET_CODE (b) == CONST_INT)
3681           return \"ldr\\t%0, %1\";
3683         if (GET_CODE (b) == REG)
3684           return \"ldrsh\\t%0, %1\";
3685           
3686         ops[1] = a;
3687         ops[2] = b;
3688       }
3689     else
3690       {
3691         ops[1] = mem;
3692         ops[2] = const0_rtx;
3693       }
3694       
3695     if (GET_CODE (ops[1]) != REG)
3696       {
3697         debug_rtx (ops[1]);
3698         abort ();
3699       }
3701     ops[0] = operands[0];
3702     if (reg_mentioned_p (operands[2], ops[1]))
3703       ops[3] = ops[0];
3704     else
3705       ops[3] = operands[2];
3706     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3707     return \"\";
3708   }"
3709   [(set_attr "length" "2,4")
3710    (set_attr "type" "alu_shift,load_byte")
3711    (set_attr "pool_range" "*,1020")]
3714 (define_expand "extendhisi2_mem"
3715   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3716    (set (match_dup 3)
3717         (zero_extend:SI (match_dup 7)))
3718    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3719    (set (match_operand:SI 0 "" "")
3720         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3721   "TARGET_ARM"
3722   "
3723   {
3724     rtx mem1, mem2;
3725     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3727     mem1 = gen_rtx_MEM (QImode, addr);
3728     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3729     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3730     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3731     operands[0] = gen_lowpart (SImode, operands[0]);
3732     operands[1] = mem1;
3733     operands[2] = gen_reg_rtx (SImode);
3734     operands[3] = gen_reg_rtx (SImode);
3735     operands[6] = gen_reg_rtx (SImode);
3736     operands[7] = mem2;
3738     if (BYTES_BIG_ENDIAN)
3739       {
3740         operands[4] = operands[2];
3741         operands[5] = operands[3];
3742       }
3743     else
3744       {
3745         operands[4] = operands[3];
3746         operands[5] = operands[2];
3747       }
3748   }"
3751 (define_insn "*arm_extendhisi2"
3752   [(set (match_operand:SI 0 "s_register_operand" "=r")
3753         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3754   "TARGET_ARM && arm_arch4 && !arm_arch6"
3755   "ldr%?sh\\t%0, %1"
3756   [(set_attr "type" "load_byte")
3757    (set_attr "predicable" "yes")
3758    (set_attr "pool_range" "256")
3759    (set_attr "neg_pool_range" "244")]
3762 (define_insn "*arm_extendhisi2_v6"
3763   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3764         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3765   "TARGET_ARM && arm_arch6"
3766   "@
3767    sxth%?\\t%0, %1
3768    ldr%?sh\\t%0, %1"
3769   [(set_attr "type" "alu_shift,load_byte")
3770    (set_attr "predicable" "yes")
3771    (set_attr "pool_range" "*,256")
3772    (set_attr "neg_pool_range" "*,244")]
3775 (define_insn "*arm_extendhisi2addsi"
3776   [(set (match_operand:SI 0 "s_register_operand" "=r")
3777         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3778                  (match_operand:SI 2 "s_register_operand" "r")))]
3779   "TARGET_ARM && arm_arch6"
3780   "sxtah%?\\t%0, %2, %1"
3783 (define_split
3784   [(set (match_operand:SI                 0 "s_register_operand" "")
3785         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3786    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3787   "TARGET_ARM && (!arm_arch4)"
3788   [(set (match_dup 2) (match_dup 1))
3789    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3790   "
3791   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3792     FAIL;
3793   "
3796 (define_split
3797   [(set (match_operand:SI                   0 "s_register_operand" "")
3798         (match_operator:SI                  3 "shiftable_operator"
3799          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3800           (match_operand:SI                 4 "s_register_operand" "")]))
3801    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3802   "TARGET_ARM && (!arm_arch4)"
3803   [(set (match_dup 2) (match_dup 1))
3804    (set (match_dup 0)
3805         (match_op_dup 3
3806          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3807   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3808      FAIL;
3809   "
3812 (define_expand "extendqihi2"
3813   [(set (match_dup 2)
3814         (ashift:SI (match_operand:QI 1 "general_operand" "")
3815                    (const_int 24)))
3816    (set (match_operand:HI 0 "s_register_operand" "")
3817         (ashiftrt:SI (match_dup 2)
3818                      (const_int 24)))]
3819   "TARGET_ARM"
3820   "
3821   {
3822     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3823       {
3824         emit_insn (gen_rtx_SET (VOIDmode,
3825                                 operands[0],
3826                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3827         DONE;
3828       }
3829     if (!s_register_operand (operands[1], QImode))
3830       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3831     operands[0] = gen_lowpart (SImode, operands[0]);
3832     operands[1] = gen_lowpart (SImode, operands[1]);
3833     operands[2] = gen_reg_rtx (SImode);
3834   }"
3837 (define_insn "*extendqihi_insn"
3838   [(set (match_operand:HI 0 "s_register_operand" "=r")
3839         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3840   "TARGET_ARM && arm_arch4"
3841   "ldr%?sb\\t%0, %1"
3842   [(set_attr "type" "load_byte")
3843    (set_attr "predicable" "yes")
3844    (set_attr "pool_range" "256")
3845    (set_attr "neg_pool_range" "244")]
3848 (define_expand "extendqisi2"
3849   [(set (match_dup 2)
3850         (ashift:SI (match_operand:QI 1 "general_operand" "")
3851                    (const_int 24)))
3852    (set (match_operand:SI 0 "s_register_operand" "")
3853         (ashiftrt:SI (match_dup 2)
3854                      (const_int 24)))]
3855   "TARGET_EITHER"
3856   "
3857   {
3858     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3859       {
3860         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3861                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3862         DONE;
3863       }
3865     if (!s_register_operand (operands[1], QImode))
3866       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3868     if (arm_arch6)
3869       {
3870         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3871                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3872         DONE;
3873       }
3875     operands[1] = gen_lowpart (SImode, operands[1]);
3876     operands[2] = gen_reg_rtx (SImode);
3877   }"
3880 (define_insn "*arm_extendqisi"
3881   [(set (match_operand:SI 0 "s_register_operand" "=r")
3882         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3883   "TARGET_ARM && arm_arch4 && !arm_arch6"
3884   "ldr%?sb\\t%0, %1"
3885   [(set_attr "type" "load_byte")
3886    (set_attr "predicable" "yes")
3887    (set_attr "pool_range" "256")
3888    (set_attr "neg_pool_range" "244")]
3891 (define_insn "*arm_extendqisi_v6"
3892   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3893         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3894   "TARGET_ARM && arm_arch6"
3895   "@
3896    sxtb%?\\t%0, %1
3897    ldr%?sb\\t%0, %1"
3898   [(set_attr "type" "alu_shift,load_byte")
3899    (set_attr "predicable" "yes")
3900    (set_attr "pool_range" "*,256")
3901    (set_attr "neg_pool_range" "*,244")]
3904 (define_insn "*arm_extendqisi2addsi"
3905   [(set (match_operand:SI 0 "s_register_operand" "=r")
3906         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3907                  (match_operand:SI 2 "s_register_operand" "r")))]
3908   "TARGET_ARM && arm_arch6"
3909   "sxtab%?\\t%0, %2, %1"
3910   [(set_attr "type" "alu_shift")
3911    (set_attr "predicable" "yes")]
3914 (define_insn "*thumb_extendqisi2"
3915   [(set (match_operand:SI 0 "register_operand" "=l,l")
3916         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3917   "TARGET_THUMB && !arm_arch6"
3918   "*
3919   {
3920     rtx ops[3];
3921     rtx mem = XEXP (operands[1], 0);
3922     
3923     if (GET_CODE (mem) == CONST)
3924       mem = XEXP (mem, 0);
3925     
3926     if (GET_CODE (mem) == LABEL_REF)
3927       return \"ldr\\t%0, %1\";
3929     if (GET_CODE (mem) == PLUS
3930         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3931       return \"ldr\\t%0, %1\";
3932       
3933     if (which_alternative == 0)
3934       return \"ldrsb\\t%0, %1\";
3935       
3936     ops[0] = operands[0];
3937     
3938     if (GET_CODE (mem) == PLUS)
3939       {
3940         rtx a = XEXP (mem, 0);
3941         rtx b = XEXP (mem, 1);
3942         
3943         ops[1] = a;
3944         ops[2] = b;
3946         if (GET_CODE (a) == REG)
3947           {
3948             if (GET_CODE (b) == REG)
3949               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3950             else if (REGNO (a) == REGNO (ops[0]))
3951               {
3952                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3953                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3954                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3955               }
3956             else
3957               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3958           }
3959         else if (GET_CODE (b) != REG)
3960           abort ();
3961         else
3962           {
3963             if (REGNO (b) == REGNO (ops[0]))
3964               {
3965                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3966                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3967                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3968               }
3969             else
3970               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3971           }
3972       }
3973     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3974       {
3975         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3976         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3977         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3978       }
3979     else
3980       {
3981         ops[1] = mem;
3982         ops[2] = const0_rtx;
3983         
3984         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3985       }
3986     return \"\";
3987   }"
3988   [(set_attr "length" "2,6")
3989    (set_attr "type" "load_byte,load_byte")
3990    (set_attr "pool_range" "32,32")]
3993 (define_insn "*thumb_extendqisi2_v6"
3994   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3995         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3996   "TARGET_THUMB && arm_arch6"
3997   "*
3998   {
3999     rtx ops[3];
4000     rtx mem;
4002     if (which_alternative == 0)
4003       return \"sxtb\\t%0, %1\";
4005     mem = XEXP (operands[1], 0);
4006     
4007     if (GET_CODE (mem) == CONST)
4008       mem = XEXP (mem, 0);
4009     
4010     if (GET_CODE (mem) == LABEL_REF)
4011       return \"ldr\\t%0, %1\";
4013     if (GET_CODE (mem) == PLUS
4014         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4015       return \"ldr\\t%0, %1\";
4016       
4017     if (which_alternative == 0)
4018       return \"ldrsb\\t%0, %1\";
4019       
4020     ops[0] = operands[0];
4021     
4022     if (GET_CODE (mem) == PLUS)
4023       {
4024         rtx a = XEXP (mem, 0);
4025         rtx b = XEXP (mem, 1);
4026         
4027         ops[1] = a;
4028         ops[2] = b;
4030         if (GET_CODE (a) == REG)
4031           {
4032             if (GET_CODE (b) == REG)
4033               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4034             else if (REGNO (a) == REGNO (ops[0]))
4035               {
4036                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4037                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4038               }
4039             else
4040               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4041           }
4042         else if (GET_CODE (b) != REG)
4043           abort ();
4044         else
4045           {
4046             if (REGNO (b) == REGNO (ops[0]))
4047               {
4048                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4049                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4050               }
4051             else
4052               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4053           }
4054       }
4055     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4056       {
4057         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4058         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4059       }
4060     else
4061       {
4062         ops[1] = mem;
4063         ops[2] = const0_rtx;
4064         
4065         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4066       }
4067     return \"\";
4068   }"
4069   [(set_attr "length" "2,2,4")
4070    (set_attr "type" "alu_shift,load_byte,load_byte")
4071    (set_attr "pool_range" "*,32,32")]
4074 (define_expand "extendsfdf2"
4075   [(set (match_operand:DF                  0 "s_register_operand" "")
4076         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4077   "TARGET_ARM && TARGET_HARD_FLOAT"
4078   ""
4081 ;; Move insns (including loads and stores)
4083 ;; XXX Just some ideas about movti.
4084 ;; I don't think these are a good idea on the arm, there just aren't enough
4085 ;; registers
4086 ;;(define_expand "loadti"
4087 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4088 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4089 ;;  "" "")
4091 ;;(define_expand "storeti"
4092 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4093 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4094 ;;  "" "")
4096 ;;(define_expand "movti"
4097 ;;  [(set (match_operand:TI 0 "general_operand" "")
4098 ;;      (match_operand:TI 1 "general_operand" ""))]
4099 ;;  ""
4100 ;;  "
4102 ;;  rtx insn;
4104 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4105 ;;    operands[1] = copy_to_reg (operands[1]);
4106 ;;  if (GET_CODE (operands[0]) == MEM)
4107 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4108 ;;  else if (GET_CODE (operands[1]) == MEM)
4109 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4110 ;;  else
4111 ;;    FAIL;
4113 ;;  emit_insn (insn);
4114 ;;  DONE;
4115 ;;}")
4117 ;; Recognize garbage generated above.
4119 ;;(define_insn ""
4120 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4121 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4122 ;;  ""
4123 ;;  "*
4124 ;;  {
4125 ;;    register mem = (which_alternative < 3);
4126 ;;    register const char *template;
4128 ;;    operands[mem] = XEXP (operands[mem], 0);
4129 ;;    switch (which_alternative)
4130 ;;      {
4131 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4132 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4133 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4134 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4135 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4136 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4137 ;;      }
4138 ;;    output_asm_insn (template, operands);
4139 ;;    return \"\";
4140 ;;  }")
4142 (define_expand "movdi"
4143   [(set (match_operand:DI 0 "general_operand" "")
4144         (match_operand:DI 1 "general_operand" ""))]
4145   "TARGET_EITHER"
4146   "
4147   if (TARGET_THUMB)
4148     {
4149       if (!no_new_pseudos)
4150         {
4151           if (GET_CODE (operands[0]) != REG)
4152             operands[1] = force_reg (DImode, operands[1]);
4153         }
4154     }
4155   "
4158 (define_insn "*arm_movdi"
4159   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,   r, r, r, m")
4160         (match_operand:DI 1 "di_operand"              "rIKDa,Db,Dc,mi,r"))]
4161   "TARGET_ARM
4162   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4163   && !TARGET_IWMMXT"
4164   "*
4165   return (output_move_double (operands));
4166   "
4167   [(set_attr "length" "8,12,16,8,8")
4168    (set_attr "type" "*,*,*,load2,store2")
4169    (set_attr "pool_range" "*,*,*,1020,*")
4170    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4173 ;; We can't actually do base+index doubleword loads if the index and
4174 ;; destination overlap.  Split here so that we at least have chance to
4175 ;; schedule.
4176 (define_split
4177   [(set (match_operand:DI 0 "s_register_operand" "")
4178         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4179                          (match_operand:SI 2 "s_register_operand" ""))))]
4180   "TARGET_LDRD
4181   && reg_overlap_mentioned_p (operands[0], operands[1])
4182   && reg_overlap_mentioned_p (operands[0], operands[2])"
4183   [(set (match_dup 4)
4184         (plus:SI (match_dup 1)
4185                  (match_dup 2)))
4186    (set (match_dup 0)
4187         (mem:DI (match_dup 4)))]
4188   "
4189   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4190   "
4193 ;;; ??? This should have alternatives for constants.
4194 ;;; ??? This was originally identical to the movdf_insn pattern.
4195 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4196 ;;; thumb_reorg with a memory reference.
4197 (define_insn "*thumb_movdi_insn"
4198   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4199         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4200   "TARGET_THUMB
4201    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4202    && (   register_operand (operands[0], DImode)
4203        || register_operand (operands[1], DImode))"
4204   "*
4205   {
4206   switch (which_alternative)
4207     {
4208     default:
4209     case 0:
4210       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4211         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4212       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4213     case 1:
4214       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4215     case 2:
4216       operands[1] = GEN_INT (- INTVAL (operands[1]));
4217       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4218     case 3:
4219       return \"ldmia\\t%1, {%0, %H0}\";
4220     case 4:
4221       return \"stmia\\t%0, {%1, %H1}\";
4222     case 5:
4223       return thumb_load_double_from_address (operands);
4224     case 6:
4225       operands[2] = gen_rtx_MEM (SImode,
4226                              plus_constant (XEXP (operands[0], 0), 4));
4227       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4228       return \"\";
4229     case 7:
4230       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4231         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4232       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4233     }
4234   }"
4235   [(set_attr "length" "4,4,6,2,2,6,4,4")
4236    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4237    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4240 (define_expand "movsi"
4241   [(set (match_operand:SI 0 "general_operand" "")
4242         (match_operand:SI 1 "general_operand" ""))]
4243   "TARGET_EITHER"
4244   "
4245   if (TARGET_ARM)
4246     {
4247       /* Everything except mem = const or mem = mem can be done easily.  */
4248       if (GET_CODE (operands[0]) == MEM)
4249         operands[1] = force_reg (SImode, operands[1]);
4250       if (arm_general_register_operand (operands[0], SImode)
4251           && GET_CODE (operands[1]) == CONST_INT
4252           && !(const_ok_for_arm (INTVAL (operands[1]))
4253                || const_ok_for_arm (~INTVAL (operands[1]))))
4254         {
4255            arm_split_constant (SET, SImode, NULL_RTX,
4256                                INTVAL (operands[1]), operands[0], NULL_RTX,
4257                                optimize && !no_new_pseudos);
4258           DONE;
4259         }
4260     }
4261   else /* TARGET_THUMB....  */
4262     {
4263       if (!no_new_pseudos)
4264         {
4265           if (GET_CODE (operands[0]) != REG)
4266             operands[1] = force_reg (SImode, operands[1]);
4267         }
4268     }
4269     
4270   if (flag_pic
4271       && (CONSTANT_P (operands[1])
4272          || symbol_mentioned_p (operands[1])
4273          || label_mentioned_p (operands[1])))
4274     operands[1] = legitimize_pic_address (operands[1], SImode,
4275                                           (no_new_pseudos ? operands[0] : 0));
4276   "
4279 (define_insn "*arm_movsi_insn"
4280   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4281         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4282   "TARGET_ARM && ! TARGET_IWMMXT
4283    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4284    && (   register_operand (operands[0], SImode)
4285        || register_operand (operands[1], SImode))"
4286   "@
4287    mov%?\\t%0, %1
4288    mvn%?\\t%0, #%B1
4289    ldr%?\\t%0, %1
4290    str%?\\t%1, %0"
4291   [(set_attr "type" "*,*,load1,store1")
4292    (set_attr "predicable" "yes")
4293    (set_attr "pool_range" "*,*,4096,*")
4294    (set_attr "neg_pool_range" "*,*,4084,*")]
4297 (define_split
4298   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4299         (match_operand:SI 1 "const_int_operand" ""))]
4300   "TARGET_ARM
4301   && (!(const_ok_for_arm (INTVAL (operands[1]))
4302         || const_ok_for_arm (~INTVAL (operands[1]))))"
4303   [(clobber (const_int 0))]
4304   "
4305   arm_split_constant (SET, SImode, NULL_RTX, 
4306                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4307   DONE;
4308   "
4311 (define_insn "*thumb_movsi_insn"
4312   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4313         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4314   "TARGET_THUMB
4315    && (   register_operand (operands[0], SImode) 
4316        || register_operand (operands[1], SImode))"
4317   "@
4318    mov  %0, %1
4319    mov  %0, %1
4320    #
4321    #
4322    ldmia\\t%1, {%0}
4323    stmia\\t%0, {%1}
4324    ldr\\t%0, %1
4325    str\\t%1, %0
4326    mov\\t%0, %1"
4327   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4328    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4329    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4332 (define_split 
4333   [(set (match_operand:SI 0 "register_operand" "")
4334         (match_operand:SI 1 "const_int_operand" ""))]
4335   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4336   [(set (match_dup 0) (match_dup 1))
4337    (set (match_dup 0) (neg:SI (match_dup 0)))]
4338   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4341 (define_split 
4342   [(set (match_operand:SI 0 "register_operand" "")
4343         (match_operand:SI 1 "const_int_operand" ""))]
4344   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4345   [(set (match_dup 0) (match_dup 1))
4346    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4347   "
4348   {
4349     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4350     unsigned HOST_WIDE_INT mask = 0xff;
4351     int i;
4352     
4353     for (i = 0; i < 25; i++)
4354       if ((val & (mask << i)) == val)
4355         break;
4357     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4358     if (i == 0)
4359       FAIL;
4361     operands[1] = GEN_INT (val >> i);
4362     operands[2] = GEN_INT (i);
4363   }"
4366 ;; When generating pic, we need to load the symbol offset into a register.
4367 ;; So that the optimizer does not confuse this with a normal symbol load
4368 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4369 ;; since that is the only type of relocation we can use.
4371 ;; The rather odd constraints on the following are to force reload to leave
4372 ;; the insn alone, and to force the minipool generation pass to then move
4373 ;; the GOT symbol to memory.
4375 (define_insn "pic_load_addr_arm"
4376   [(set (match_operand:SI 0 "s_register_operand" "=r")
4377         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4378   "TARGET_ARM && flag_pic"
4379   "ldr%?\\t%0, %1"
4380   [(set_attr "type" "load1")
4381    (set (attr "pool_range")     (const_int 4096))
4382    (set (attr "neg_pool_range") (const_int 4084))]
4385 (define_insn "pic_load_addr_thumb"
4386   [(set (match_operand:SI 0 "s_register_operand" "=l")
4387         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4388   "TARGET_THUMB && flag_pic"
4389   "ldr\\t%0, %1"
4390   [(set_attr "type" "load1")
4391    (set (attr "pool_range") (const_int 1024))]
4394 ;; This variant is used for AOF assembly, since it needs to mention the
4395 ;; pic register in the rtl.
4396 (define_expand "pic_load_addr_based"
4397   [(set (match_operand:SI 0 "s_register_operand" "")
4398         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4399   "TARGET_ARM && flag_pic"
4400   "operands[2] = pic_offset_table_rtx;"
4403 (define_insn "*pic_load_addr_based_insn"
4404   [(set (match_operand:SI 0 "s_register_operand" "=r")
4405         (unspec:SI [(match_operand 1 "" "")
4406                     (match_operand 2 "s_register_operand" "r")]
4407                    UNSPEC_PIC_SYM))]
4408   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4409   "*
4410 #ifdef AOF_ASSEMBLER
4411   operands[1] = aof_pic_entry (operands[1]);
4412 #endif
4413   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4414   return \"\";
4415   "
4416   [(set_attr "type" "load1")
4417    (set (attr "pool_range")
4418         (if_then_else (eq_attr "is_thumb" "yes")
4419                       (const_int 1024)
4420                       (const_int 4096)))
4421    (set (attr "neg_pool_range")
4422         (if_then_else (eq_attr "is_thumb" "yes")
4423                       (const_int 0)
4424                       (const_int 4084)))]
4427 (define_insn "pic_add_dot_plus_four"
4428   [(set (match_operand:SI 0 "register_operand" "+r")
4429         (unspec:SI [(plus:SI (match_dup 0)
4430                              (const (plus:SI (pc) (const_int 4))))]
4431                    UNSPEC_PIC_BASE))
4432    (use (label_ref (match_operand 1 "" "")))]
4433   "TARGET_THUMB && flag_pic"
4434   "*
4435   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4436                              CODE_LABEL_NUMBER (operands[1]));
4437   return \"add\\t%0, %|pc\";
4438   "
4439   [(set_attr "length" "2")]
4442 (define_insn "pic_add_dot_plus_eight"
4443   [(set (match_operand:SI 0 "register_operand" "+r")
4444         (unspec:SI [(plus:SI (match_dup 0)
4445                              (const (plus:SI (pc) (const_int 8))))]
4446                    UNSPEC_PIC_BASE))
4447    (use (label_ref (match_operand 1 "" "")))]
4448   "TARGET_ARM && flag_pic"
4449   "*
4450     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4451                                CODE_LABEL_NUMBER (operands[1]));
4452     return \"add%?\\t%0, %|pc, %0\";
4453   "
4454   [(set_attr "predicable" "yes")]
4457 (define_expand "builtin_setjmp_receiver"
4458   [(label_ref (match_operand 0 "" ""))]
4459   "flag_pic"
4460   "
4462   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4463      register.  */
4464   arm_load_pic_register (3);
4465   DONE;
4468 ;; If copying one reg to another we can set the condition codes according to
4469 ;; its value.  Such a move is common after a return from subroutine and the
4470 ;; result is being tested against zero.
4472 (define_insn "*movsi_compare0"
4473   [(set (reg:CC CC_REGNUM)
4474         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4475                     (const_int 0)))
4476    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4477         (match_dup 1))]
4478   "TARGET_ARM"
4479   "@
4480    cmp%?\\t%0, #0
4481    sub%?s\\t%0, %1, #0"
4482   [(set_attr "conds" "set")]
4485 ;; Subroutine to store a half word from a register into memory.
4486 ;; Operand 0 is the source register (HImode)
4487 ;; Operand 1 is the destination address in a register (SImode)
4489 ;; In both this routine and the next, we must be careful not to spill
4490 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4491 ;; can generate unrecognizable rtl.
4493 (define_expand "storehi"
4494   [;; store the low byte
4495    (set (match_operand 1 "" "") (match_dup 3))
4496    ;; extract the high byte
4497    (set (match_dup 2)
4498         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4499    ;; store the high byte
4500    (set (match_dup 4) (match_dup 5))]
4501   "TARGET_ARM"
4502   "
4503   {
4504     rtx op1 = operands[1];
4505     rtx addr = XEXP (op1, 0);
4506     enum rtx_code code = GET_CODE (addr);
4508     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4509         || code == MINUS)
4510       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4512     operands[4] = adjust_address (op1, QImode, 1);
4513     operands[1] = adjust_address (operands[1], QImode, 0);
4514     operands[3] = gen_lowpart (QImode, operands[0]);
4515     operands[0] = gen_lowpart (SImode, operands[0]);
4516     operands[2] = gen_reg_rtx (SImode);
4517     operands[5] = gen_lowpart (QImode, operands[2]);
4518   }"
4521 (define_expand "storehi_bigend"
4522   [(set (match_dup 4) (match_dup 3))
4523    (set (match_dup 2)
4524         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4525    (set (match_operand 1 "" "") (match_dup 5))]
4526   "TARGET_ARM"
4527   "
4528   {
4529     rtx op1 = operands[1];
4530     rtx addr = XEXP (op1, 0);
4531     enum rtx_code code = GET_CODE (addr);
4533     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4534         || code == MINUS)
4535       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4537     operands[4] = adjust_address (op1, QImode, 1);
4538     operands[1] = adjust_address (operands[1], QImode, 0);
4539     operands[3] = gen_lowpart (QImode, operands[0]);
4540     operands[0] = gen_lowpart (SImode, operands[0]);
4541     operands[2] = gen_reg_rtx (SImode);
4542     operands[5] = gen_lowpart (QImode, operands[2]);
4543   }"
4546 ;; Subroutine to store a half word integer constant into memory.
4547 (define_expand "storeinthi"
4548   [(set (match_operand 0 "" "")
4549         (match_operand 1 "" ""))
4550    (set (match_dup 3) (match_dup 2))]
4551   "TARGET_ARM"
4552   "
4553   {
4554     HOST_WIDE_INT value = INTVAL (operands[1]);
4555     rtx addr = XEXP (operands[0], 0);
4556     rtx op0 = operands[0];
4557     enum rtx_code code = GET_CODE (addr);
4559     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4560         || code == MINUS)
4561       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4563     operands[1] = gen_reg_rtx (SImode);
4564     if (BYTES_BIG_ENDIAN)
4565       {
4566         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4567         if ((value & 255) == ((value >> 8) & 255))
4568           operands[2] = operands[1];
4569         else
4570           {
4571             operands[2] = gen_reg_rtx (SImode);
4572             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4573           }
4574       }
4575     else
4576       {
4577         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4578         if ((value & 255) == ((value >> 8) & 255))
4579           operands[2] = operands[1];
4580         else
4581           {
4582             operands[2] = gen_reg_rtx (SImode);
4583             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4584           }
4585       }
4587     operands[3] = adjust_address (op0, QImode, 1);
4588     operands[0] = adjust_address (operands[0], QImode, 0);
4589     operands[2] = gen_lowpart (QImode, operands[2]);
4590     operands[1] = gen_lowpart (QImode, operands[1]);
4591   }"
4594 (define_expand "storehi_single_op"
4595   [(set (match_operand:HI 0 "memory_operand" "")
4596         (match_operand:HI 1 "general_operand" ""))]
4597   "TARGET_ARM && arm_arch4"
4598   "
4599   if (!s_register_operand (operands[1], HImode))
4600     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4601   "
4604 (define_expand "movhi"
4605   [(set (match_operand:HI 0 "general_operand" "")
4606         (match_operand:HI 1 "general_operand" ""))]
4607   "TARGET_EITHER"
4608   "
4609   if (TARGET_ARM)
4610     {
4611       if (!no_new_pseudos)
4612         {
4613           if (GET_CODE (operands[0]) == MEM)
4614             {
4615               if (arm_arch4)
4616                 {
4617                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4618                   DONE;
4619                 }
4620               if (GET_CODE (operands[1]) == CONST_INT)
4621                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4622               else
4623                 {
4624                   if (GET_CODE (operands[1]) == MEM)
4625                     operands[1] = force_reg (HImode, operands[1]);
4626                   if (BYTES_BIG_ENDIAN)
4627                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4628                   else
4629                    emit_insn (gen_storehi (operands[1], operands[0]));
4630                 }
4631               DONE;
4632             }
4633           /* Sign extend a constant, and keep it in an SImode reg.  */
4634           else if (GET_CODE (operands[1]) == CONST_INT)
4635             {
4636               rtx reg = gen_reg_rtx (SImode);
4637               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4639               /* If the constant is already valid, leave it alone.  */
4640               if (!const_ok_for_arm (val))
4641                 {
4642                   /* If setting all the top bits will make the constant 
4643                      loadable in a single instruction, then set them.  
4644                      Otherwise, sign extend the number.  */
4646                   if (const_ok_for_arm (~(val | ~0xffff)))
4647                     val |= ~0xffff;
4648                   else if (val & 0x8000)
4649                     val |= ~0xffff;
4650                 }
4652               emit_insn (gen_movsi (reg, GEN_INT (val)));
4653               operands[1] = gen_lowpart (HImode, reg);
4654             }
4655           else if (arm_arch4 && optimize && !no_new_pseudos
4656                    && GET_CODE (operands[1]) == MEM)
4657             {
4658               rtx reg = gen_reg_rtx (SImode);
4660               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4661               operands[1] = gen_lowpart (HImode, reg);
4662             }
4663           else if (!arm_arch4)
4664             {
4665               if (GET_CODE (operands[1]) == MEM)
4666                 {
4667                   rtx base;
4668                   rtx offset = const0_rtx;
4669                   rtx reg = gen_reg_rtx (SImode);
4671                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4672                        || (GET_CODE (base) == PLUS
4673                            && (GET_CODE (offset = XEXP (base, 1))
4674                                == CONST_INT)
4675                            && ((INTVAL(offset) & 1) != 1)
4676                            && GET_CODE (base = XEXP (base, 0)) == REG))
4677                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4678                     {
4679                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4680                       rtx new;
4682                       new = gen_rtx_MEM (SImode,
4683                                          plus_constant (base, new_offset));
4684                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4685                       emit_insn (gen_movsi (reg, new));
4686                       if (((INTVAL (offset) & 2) != 0)
4687                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4688                         {
4689                           rtx reg2 = gen_reg_rtx (SImode);
4691                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4692                           reg = reg2;
4693                         }
4694                     }
4695                   else
4696                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4698                   operands[1] = gen_lowpart (HImode, reg);
4699                }
4700            }
4701         }
4702       /* Handle loading a large integer during reload.  */
4703       else if (GET_CODE (operands[1]) == CONST_INT
4704                && !const_ok_for_arm (INTVAL (operands[1]))
4705                && !const_ok_for_arm (~INTVAL (operands[1])))
4706         {
4707           /* Writing a constant to memory needs a scratch, which should
4708              be handled with SECONDARY_RELOADs.  */
4709           if (GET_CODE (operands[0]) != REG)
4710             abort ();
4712           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4713           emit_insn (gen_movsi (operands[0], operands[1]));
4714           DONE;
4715        }
4716     }
4717   else /* TARGET_THUMB */
4718     {
4719       if (!no_new_pseudos)
4720         {
4721           if (GET_CODE (operands[0]) != REG)
4722             operands[1] = force_reg (HImode, operands[1]);
4724           /* ??? We shouldn't really get invalid addresses here, but this can
4725              happen if we are passed a SP (never OK for HImode/QImode) or 
4726              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4727              HImode/QImode) relative address.  */
4728           /* ??? This should perhaps be fixed elsewhere, for instance, in
4729              fixup_stack_1, by checking for other kinds of invalid addresses,
4730              e.g. a bare reference to a virtual register.  This may confuse the
4731              alpha though, which must handle this case differently.  */
4732           if (GET_CODE (operands[0]) == MEM
4733               && !memory_address_p (GET_MODE (operands[0]),
4734                                     XEXP (operands[0], 0)))
4735             operands[0]
4736               = replace_equiv_address (operands[0],
4737                                        copy_to_reg (XEXP (operands[0], 0)));
4738    
4739           if (GET_CODE (operands[1]) == MEM
4740               && !memory_address_p (GET_MODE (operands[1]),
4741                                     XEXP (operands[1], 0)))
4742             operands[1]
4743               = replace_equiv_address (operands[1],
4744                                        copy_to_reg (XEXP (operands[1], 0)));
4745         }
4746       /* Handle loading a large integer during reload.  */
4747       else if (GET_CODE (operands[1]) == CONST_INT
4748                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4749         {
4750           /* Writing a constant to memory needs a scratch, which should
4751              be handled with SECONDARY_RELOADs.  */
4752           if (GET_CODE (operands[0]) != REG)
4753             abort ();
4755           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4756           emit_insn (gen_movsi (operands[0], operands[1]));
4757           DONE;
4758         }
4759     }
4760   "
4763 (define_insn "*thumb_movhi_insn"
4764   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4765         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4766   "TARGET_THUMB
4767    && (   register_operand (operands[0], HImode)
4768        || register_operand (operands[1], HImode))"
4769   "*
4770   switch (which_alternative)
4771     {
4772     case 0: return \"add        %0, %1, #0\";
4773     case 2: return \"strh       %1, %0\";
4774     case 3: return \"mov        %0, %1\";
4775     case 4: return \"mov        %0, %1\";
4776     case 5: return \"mov        %0, %1\";
4777     default: abort ();
4778     case 1:
4779       /* The stack pointer can end up being taken as an index register.
4780           Catch this case here and deal with it.  */
4781       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4782           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4783           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4784         {
4785           rtx ops[2];
4786           ops[0] = operands[0];
4787           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4788       
4789           output_asm_insn (\"mov        %0, %1\", ops);
4791           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4792     
4793         }
4794       return \"ldrh     %0, %1\";
4795     }"
4796   [(set_attr "length" "2,4,2,2,2,2")
4797    (set_attr "type" "*,load1,store1,*,*,*")]
4801 (define_expand "movhi_bytes"
4802   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4803    (set (match_dup 3)
4804         (zero_extend:SI (match_dup 6)))
4805    (set (match_operand:SI 0 "" "")
4806          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4807   "TARGET_ARM"
4808   "
4809   {
4810     rtx mem1, mem2;
4811     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4813     mem1 = gen_rtx_MEM (QImode, addr);
4814     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4815     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4816     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4817     operands[0] = gen_lowpart (SImode, operands[0]);
4818     operands[1] = mem1;
4819     operands[2] = gen_reg_rtx (SImode);
4820     operands[3] = gen_reg_rtx (SImode);
4821     operands[6] = mem2;
4823     if (BYTES_BIG_ENDIAN)
4824       {
4825         operands[4] = operands[2];
4826         operands[5] = operands[3];
4827       }
4828     else
4829       {
4830         operands[4] = operands[3];
4831         operands[5] = operands[2];
4832       }
4833   }"
4836 (define_expand "movhi_bigend"
4837   [(set (match_dup 2)
4838         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4839                    (const_int 16)))
4840    (set (match_dup 3)
4841         (ashiftrt:SI (match_dup 2) (const_int 16)))
4842    (set (match_operand:HI 0 "s_register_operand" "")
4843         (match_dup 4))]
4844   "TARGET_ARM"
4845   "
4846   operands[2] = gen_reg_rtx (SImode);
4847   operands[3] = gen_reg_rtx (SImode);
4848   operands[4] = gen_lowpart (HImode, operands[3]);
4849   "
4852 ;; Pattern to recognize insn generated default case above
4853 (define_insn "*movhi_insn_arch4"
4854   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4855         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4856   "TARGET_ARM
4857    && arm_arch4
4858    && (GET_CODE (operands[1]) != CONST_INT
4859        || const_ok_for_arm (INTVAL (operands[1]))
4860        || const_ok_for_arm (~INTVAL (operands[1])))"
4861   "@
4862    mov%?\\t%0, %1\\t%@ movhi
4863    mvn%?\\t%0, #%B1\\t%@ movhi
4864    str%?h\\t%1, %0\\t%@ movhi 
4865    ldr%?h\\t%0, %1\\t%@ movhi"
4866   [(set_attr "type" "*,*,store1,load1")
4867    (set_attr "predicable" "yes")
4868    (set_attr "pool_range" "*,*,*,256")
4869    (set_attr "neg_pool_range" "*,*,*,244")]
4872 (define_insn "*movhi_bytes"
4873   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4874         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4875   "TARGET_ARM"
4876   "@
4877    mov%?\\t%0, %1\\t%@ movhi
4878    mvn%?\\t%0, #%B1\\t%@ movhi"
4879   [(set_attr "predicable" "yes")]
4882 (define_insn "thumb_movhi_clobber"
4883   [(set (match_operand:HI     0 "memory_operand"   "=m")
4884         (match_operand:HI     1 "register_operand" "l"))
4885    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4886   "TARGET_THUMB"
4887   "*
4888   abort ();"
4890         
4891 ;; We use a DImode scratch because we may occasionally need an additional
4892 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4893 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4894 (define_expand "reload_outhi"
4895   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4896               (match_operand:HI 1 "s_register_operand"        "r")
4897               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4898   "TARGET_EITHER"
4899   "if (TARGET_ARM)
4900      arm_reload_out_hi (operands);
4901    else
4902      thumb_reload_out_hi (operands);
4903   DONE;
4904   "
4907 (define_expand "reload_inhi"
4908   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4909               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4910               (match_operand:DI 2 "s_register_operand" "=&r")])]
4911   "TARGET_EITHER"
4912   "
4913   if (TARGET_ARM)
4914     arm_reload_in_hi (operands);
4915   else
4916     thumb_reload_out_hi (operands);
4917   DONE;
4920 (define_expand "movqi"
4921   [(set (match_operand:QI 0 "general_operand" "")
4922         (match_operand:QI 1 "general_operand" ""))]
4923   "TARGET_EITHER"
4924   "
4925   if (TARGET_ARM)
4926     {
4927       /* Everything except mem = const or mem = mem can be done easily */
4929       if (!no_new_pseudos)
4930         {
4931           if (GET_CODE (operands[1]) == CONST_INT)
4932             {
4933               rtx reg = gen_reg_rtx (SImode);
4935               emit_insn (gen_movsi (reg, operands[1]));
4936               operands[1] = gen_lowpart (QImode, reg);
4937             }
4938           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4939             {
4940               rtx reg = gen_reg_rtx (SImode);
4942               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4943               operands[1] = gen_lowpart (QImode, reg);
4944             }
4945           if (GET_CODE (operands[0]) == MEM)
4946             operands[1] = force_reg (QImode, operands[1]);
4947         }
4948     }
4949   else /* TARGET_THUMB */
4950     {
4951       if (!no_new_pseudos)
4952         {
4953           if (GET_CODE (operands[0]) != REG)
4954             operands[1] = force_reg (QImode, operands[1]);
4956           /* ??? We shouldn't really get invalid addresses here, but this can
4957              happen if we are passed a SP (never OK for HImode/QImode) or
4958              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4959              HImode/QImode) relative address.  */
4960           /* ??? This should perhaps be fixed elsewhere, for instance, in
4961              fixup_stack_1, by checking for other kinds of invalid addresses,
4962              e.g. a bare reference to a virtual register.  This may confuse the
4963              alpha though, which must handle this case differently.  */
4964           if (GET_CODE (operands[0]) == MEM
4965               && !memory_address_p (GET_MODE (operands[0]),
4966                                      XEXP (operands[0], 0)))
4967             operands[0]
4968               = replace_equiv_address (operands[0],
4969                                        copy_to_reg (XEXP (operands[0], 0)));
4970           if (GET_CODE (operands[1]) == MEM
4971               && !memory_address_p (GET_MODE (operands[1]),
4972                                     XEXP (operands[1], 0)))
4973              operands[1]
4974                = replace_equiv_address (operands[1],
4975                                         copy_to_reg (XEXP (operands[1], 0)));
4976         }
4977       /* Handle loading a large integer during reload.  */
4978       else if (GET_CODE (operands[1]) == CONST_INT
4979                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4980         {
4981           /* Writing a constant to memory needs a scratch, which should
4982              be handled with SECONDARY_RELOADs.  */
4983           if (GET_CODE (operands[0]) != REG)
4984             abort ();
4986           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4987           emit_insn (gen_movsi (operands[0], operands[1]));
4988           DONE;
4989        }
4990     }
4991   "
4995 (define_insn "*arm_movqi_insn"
4996   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4997         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4998   "TARGET_ARM
4999    && (   register_operand (operands[0], QImode)
5000        || register_operand (operands[1], QImode))"
5001   "@
5002    mov%?\\t%0, %1
5003    mvn%?\\t%0, #%B1
5004    ldr%?b\\t%0, %1
5005    str%?b\\t%1, %0"
5006   [(set_attr "type" "*,*,load1,store1")
5007    (set_attr "predicable" "yes")]
5010 (define_insn "*thumb_movqi_insn"
5011   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5012         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5013   "TARGET_THUMB
5014    && (   register_operand (operands[0], QImode)
5015        || register_operand (operands[1], QImode))"
5016   "@
5017    add\\t%0, %1, #0
5018    ldrb\\t%0, %1
5019    strb\\t%1, %0
5020    mov\\t%0, %1
5021    mov\\t%0, %1
5022    mov\\t%0, %1"
5023   [(set_attr "length" "2")
5024    (set_attr "type" "*,load1,store1,*,*,*")
5025    (set_attr "pool_range" "*,32,*,*,*,*")]
5028 (define_expand "movsf"
5029   [(set (match_operand:SF 0 "general_operand" "")
5030         (match_operand:SF 1 "general_operand" ""))]
5031   "TARGET_EITHER"
5032   "
5033   if (TARGET_ARM)
5034     {
5035       if (GET_CODE (operands[0]) == MEM)
5036         operands[1] = force_reg (SFmode, operands[1]);
5037     }
5038   else /* TARGET_THUMB */
5039     {
5040       if (!no_new_pseudos)
5041         {
5042            if (GET_CODE (operands[0]) != REG)
5043              operands[1] = force_reg (SFmode, operands[1]);
5044         }
5045     }
5046   "
5049 (define_split
5050   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5051         (match_operand:SF 1 "immediate_operand" ""))]
5052   "TARGET_ARM
5053    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5054    && reload_completed
5055    && GET_CODE (operands[1]) == CONST_DOUBLE"
5056   [(set (match_dup 2) (match_dup 3))]
5057   "
5058   operands[2] = gen_lowpart (SImode, operands[0]);
5059   operands[3] = gen_lowpart (SImode, operands[1]);
5060   if (operands[2] == 0 || operands[3] == 0)
5061     FAIL;
5062   "
5065 (define_insn "*arm_movsf_soft_insn"
5066   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5067         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5068   "TARGET_ARM
5069    && TARGET_SOFT_FLOAT
5070    && (GET_CODE (operands[0]) != MEM
5071        || register_operand (operands[1], SFmode))"
5072   "@
5073    mov%?\\t%0, %1
5074    ldr%?\\t%0, %1\\t%@ float
5075    str%?\\t%1, %0\\t%@ float"
5076   [(set_attr "length" "4,4,4")
5077    (set_attr "predicable" "yes")
5078    (set_attr "type" "*,load1,store1")
5079    (set_attr "pool_range" "*,4096,*")
5080    (set_attr "neg_pool_range" "*,4084,*")]
5083 ;;; ??? This should have alternatives for constants.
5084 (define_insn "*thumb_movsf_insn"
5085   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5086         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5087   "TARGET_THUMB
5088    && (   register_operand (operands[0], SFmode) 
5089        || register_operand (operands[1], SFmode))"
5090   "@
5091    add\\t%0, %1, #0
5092    ldmia\\t%1, {%0}
5093    stmia\\t%0, {%1}
5094    ldr\\t%0, %1
5095    str\\t%1, %0
5096    mov\\t%0, %1
5097    mov\\t%0, %1"
5098   [(set_attr "length" "2")
5099    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5100    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5103 (define_expand "movdf"
5104   [(set (match_operand:DF 0 "general_operand" "")
5105         (match_operand:DF 1 "general_operand" ""))]
5106   "TARGET_EITHER"
5107   "
5108   if (TARGET_ARM)
5109     {
5110       if (GET_CODE (operands[0]) == MEM)
5111         operands[1] = force_reg (DFmode, operands[1]);
5112     }
5113   else /* TARGET_THUMB */
5114     {
5115       if (!no_new_pseudos)
5116         {
5117           if (GET_CODE (operands[0]) != REG)
5118             operands[1] = force_reg (DFmode, operands[1]);
5119         }
5120     }
5121   "
5124 ;; Reloading a df mode value stored in integer regs to memory can require a
5125 ;; scratch reg.
5126 (define_expand "reload_outdf"
5127   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5128    (match_operand:DF 1 "s_register_operand" "r")
5129    (match_operand:SI 2 "s_register_operand" "=&r")]
5130   "TARGET_ARM"
5131   "
5132   {
5133     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5135     if (code == REG)
5136       operands[2] = XEXP (operands[0], 0);
5137     else if (code == POST_INC || code == PRE_DEC)
5138       {
5139         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5140         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5141         emit_insn (gen_movdi (operands[0], operands[1]));
5142         DONE;
5143       }
5144     else if (code == PRE_INC)
5145       {
5146         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5148         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5149         operands[2] = reg;
5150       }
5151     else if (code == POST_DEC)
5152       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5153     else
5154       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5155                              XEXP (XEXP (operands[0], 0), 1)));
5157     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5158                             operands[1]));
5160     if (code == POST_DEC)
5161       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5163     DONE;
5164   }"
5167 (define_insn "*movdf_soft_insn"
5168   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5169         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5170   "TARGET_ARM && TARGET_SOFT_FLOAT
5171   "
5172   "* return output_move_double (operands);"
5173   [(set_attr "length" "8,12,16,8,8")
5174    (set_attr "type" "*,*,*,load2,store2")
5175    (set_attr "pool_range" "1020")
5176    (set_attr "neg_pool_range" "1008")]
5179 ;;; ??? This should have alternatives for constants.
5180 ;;; ??? This was originally identical to the movdi_insn pattern.
5181 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5182 ;;; thumb_reorg with a memory reference.
5183 (define_insn "*thumb_movdf_insn"
5184   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5185         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5186   "TARGET_THUMB
5187    && (   register_operand (operands[0], DFmode)
5188        || register_operand (operands[1], DFmode))"
5189   "*
5190   switch (which_alternative)
5191     {
5192     default:
5193     case 0:
5194       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5195         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5196       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5197     case 1:
5198       return \"ldmia\\t%1, {%0, %H0}\";
5199     case 2:
5200       return \"stmia\\t%0, {%1, %H1}\";
5201     case 3:
5202       return thumb_load_double_from_address (operands);
5203     case 4:
5204       operands[2] = gen_rtx_MEM (SImode,
5205                                  plus_constant (XEXP (operands[0], 0), 4));
5206       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5207       return \"\";
5208     case 5:
5209       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5210         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5211       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5212     }
5213   "
5214   [(set_attr "length" "4,2,2,6,4,4")
5215    (set_attr "type" "*,load2,store2,load2,store2,*")
5216    (set_attr "pool_range" "*,*,*,1020,*,*")]
5219 (define_expand "movxf"
5220   [(set (match_operand:XF 0 "general_operand" "")
5221         (match_operand:XF 1 "general_operand" ""))]
5222   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5223   "
5224   if (GET_CODE (operands[0]) == MEM)
5225     operands[1] = force_reg (XFmode, operands[1]);
5226   "
5229 ;; Vector Moves
5230 (define_expand "movv2si"
5231   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5232         (match_operand:V2SI 1 "general_operand" ""))]
5233   "TARGET_REALLY_IWMMXT"
5237 (define_expand "movv4hi"
5238   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5239         (match_operand:V4HI 1 "general_operand" ""))]
5240   "TARGET_REALLY_IWMMXT"
5244 (define_expand "movv8qi"
5245   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5246         (match_operand:V8QI 1 "general_operand" ""))]
5247   "TARGET_REALLY_IWMMXT"
5252 ;; load- and store-multiple insns
5253 ;; The arm can load/store any set of registers, provided that they are in
5254 ;; ascending order; but that is beyond GCC so stick with what it knows.
5256 (define_expand "load_multiple"
5257   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5258                           (match_operand:SI 1 "" ""))
5259                      (use (match_operand:SI 2 "" ""))])]
5260   "TARGET_ARM"
5262   HOST_WIDE_INT offset = 0;
5264   /* Support only fixed point registers.  */
5265   if (GET_CODE (operands[2]) != CONST_INT
5266       || INTVAL (operands[2]) > 14
5267       || INTVAL (operands[2]) < 2
5268       || GET_CODE (operands[1]) != MEM
5269       || GET_CODE (operands[0]) != REG
5270       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5271       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5272     FAIL;
5274   operands[3]
5275     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5276                              force_reg (SImode, XEXP (operands[1], 0)),
5277                              TRUE, FALSE, operands[1], &offset);
5280 ;; Load multiple with write-back
5282 (define_insn "*ldmsi_postinc4"
5283   [(match_parallel 0 "load_multiple_operation"
5284     [(set (match_operand:SI 1 "s_register_operand" "=r")
5285           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5286                    (const_int 16)))
5287      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5288           (mem:SI (match_dup 2)))
5289      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5290           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5291      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5292           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5293      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5294           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5295   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5296   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5297   [(set_attr "type" "load4")
5298    (set_attr "predicable" "yes")]
5301 (define_insn "*ldmsi_postinc4_thumb"
5302   [(match_parallel 0 "load_multiple_operation"
5303     [(set (match_operand:SI 1 "s_register_operand" "=l")
5304           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5305                    (const_int 16)))
5306      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5307           (mem:SI (match_dup 2)))
5308      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5309           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5310      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5311           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5312      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5313           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5314   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5315   "ldmia\\t%1!, {%3, %4, %5, %6}"
5316   [(set_attr "type" "load4")]
5319 (define_insn "*ldmsi_postinc3"
5320   [(match_parallel 0 "load_multiple_operation"
5321     [(set (match_operand:SI 1 "s_register_operand" "=r")
5322           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5323                    (const_int 12)))
5324      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5325           (mem:SI (match_dup 2)))
5326      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5327           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5328      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5329           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5330   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5331   "ldm%?ia\\t%1!, {%3, %4, %5}"
5332   [(set_attr "type" "load3")
5333    (set_attr "predicable" "yes")]
5336 (define_insn "*ldmsi_postinc2"
5337   [(match_parallel 0 "load_multiple_operation"
5338     [(set (match_operand:SI 1 "s_register_operand" "=r")
5339           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5340                    (const_int 8)))
5341      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5342           (mem:SI (match_dup 2)))
5343      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5344           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5345   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5346   "ldm%?ia\\t%1!, {%3, %4}"
5347   [(set_attr "type" "load2")
5348    (set_attr "predicable" "yes")]
5351 ;; Ordinary load multiple
5353 (define_insn "*ldmsi4"
5354   [(match_parallel 0 "load_multiple_operation"
5355     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5356           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5357      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5358           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5359      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5360           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5361      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5362           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5363   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5364   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5365   [(set_attr "type" "load4")
5366    (set_attr "predicable" "yes")]
5369 (define_insn "*ldmsi3"
5370   [(match_parallel 0 "load_multiple_operation"
5371     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5372           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5373      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5374           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5375      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5376           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5377   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5378   "ldm%?ia\\t%1, {%2, %3, %4}"
5379   [(set_attr "type" "load3")
5380    (set_attr "predicable" "yes")]
5383 (define_insn "*ldmsi2"
5384   [(match_parallel 0 "load_multiple_operation"
5385     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5386           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5387      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5388           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5389   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5390   "ldm%?ia\\t%1, {%2, %3}"
5391   [(set_attr "type" "load2")
5392    (set_attr "predicable" "yes")]
5395 (define_expand "store_multiple"
5396   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5397                           (match_operand:SI 1 "" ""))
5398                      (use (match_operand:SI 2 "" ""))])]
5399   "TARGET_ARM"
5401   HOST_WIDE_INT offset = 0;
5403   /* Support only fixed point registers.  */
5404   if (GET_CODE (operands[2]) != CONST_INT
5405       || INTVAL (operands[2]) > 14
5406       || INTVAL (operands[2]) < 2
5407       || GET_CODE (operands[1]) != REG
5408       || GET_CODE (operands[0]) != MEM
5409       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5410       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5411     FAIL;
5413   operands[3]
5414     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5415                               force_reg (SImode, XEXP (operands[0], 0)),
5416                               TRUE, FALSE, operands[0], &offset);
5419 ;; Store multiple with write-back
5421 (define_insn "*stmsi_postinc4"
5422   [(match_parallel 0 "store_multiple_operation"
5423     [(set (match_operand:SI 1 "s_register_operand" "=r")
5424           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5425                    (const_int 16)))
5426      (set (mem:SI (match_dup 2))
5427           (match_operand:SI 3 "arm_hard_register_operand" ""))
5428      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5429           (match_operand:SI 4 "arm_hard_register_operand" ""))
5430      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5431           (match_operand:SI 5 "arm_hard_register_operand" ""))
5432      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5433           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5434   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5435   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5436   [(set_attr "predicable" "yes")
5437    (set_attr "type" "store4")]
5440 (define_insn "*stmsi_postinc4_thumb"
5441   [(match_parallel 0 "store_multiple_operation"
5442     [(set (match_operand:SI 1 "s_register_operand" "=l")
5443           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5444                    (const_int 16)))
5445      (set (mem:SI (match_dup 2))
5446           (match_operand:SI 3 "arm_hard_register_operand" ""))
5447      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5448           (match_operand:SI 4 "arm_hard_register_operand" ""))
5449      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5450           (match_operand:SI 5 "arm_hard_register_operand" ""))
5451      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5452           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5453   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5454   "stmia\\t%1!, {%3, %4, %5, %6}"
5455   [(set_attr "type" "store4")]
5458 (define_insn "*stmsi_postinc3"
5459   [(match_parallel 0 "store_multiple_operation"
5460     [(set (match_operand:SI 1 "s_register_operand" "=r")
5461           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5462                    (const_int 12)))
5463      (set (mem:SI (match_dup 2))
5464           (match_operand:SI 3 "arm_hard_register_operand" ""))
5465      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5466           (match_operand:SI 4 "arm_hard_register_operand" ""))
5467      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5468           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5469   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5470   "stm%?ia\\t%1!, {%3, %4, %5}"
5471   [(set_attr "predicable" "yes")
5472    (set_attr "type" "store3")]
5475 (define_insn "*stmsi_postinc2"
5476   [(match_parallel 0 "store_multiple_operation"
5477     [(set (match_operand:SI 1 "s_register_operand" "=r")
5478           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5479                    (const_int 8)))
5480      (set (mem:SI (match_dup 2))
5481           (match_operand:SI 3 "arm_hard_register_operand" ""))
5482      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5483           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5484   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5485   "stm%?ia\\t%1!, {%3, %4}"
5486   [(set_attr "predicable" "yes")
5487    (set_attr "type" "store2")]
5490 ;; Ordinary store multiple
5492 (define_insn "*stmsi4"
5493   [(match_parallel 0 "store_multiple_operation"
5494     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5495           (match_operand:SI 2 "arm_hard_register_operand" ""))
5496      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5497           (match_operand:SI 3 "arm_hard_register_operand" ""))
5498      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5499           (match_operand:SI 4 "arm_hard_register_operand" ""))
5500      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5501           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5502   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5503   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5504   [(set_attr "predicable" "yes")
5505    (set_attr "type" "store4")]
5508 (define_insn "*stmsi3"
5509   [(match_parallel 0 "store_multiple_operation"
5510     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5511           (match_operand:SI 2 "arm_hard_register_operand" ""))
5512      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5513           (match_operand:SI 3 "arm_hard_register_operand" ""))
5514      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5515           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5516   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5517   "stm%?ia\\t%1, {%2, %3, %4}"
5518   [(set_attr "predicable" "yes")
5519    (set_attr "type" "store3")]
5522 (define_insn "*stmsi2"
5523   [(match_parallel 0 "store_multiple_operation"
5524     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5525           (match_operand:SI 2 "arm_hard_register_operand" ""))
5526      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5527           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5528   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5529   "stm%?ia\\t%1, {%2, %3}"
5530   [(set_attr "predicable" "yes")
5531    (set_attr "type" "store2")]
5534 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5535 ;; We could let this apply for blocks of less than this, but it clobbers so
5536 ;; many registers that there is then probably a better way.
5538 (define_expand "movmemqi"
5539   [(match_operand:BLK 0 "general_operand" "")
5540    (match_operand:BLK 1 "general_operand" "")
5541    (match_operand:SI 2 "const_int_operand" "")
5542    (match_operand:SI 3 "const_int_operand" "")]
5543   "TARGET_EITHER"
5544   "
5545   if (TARGET_ARM)
5546     {
5547       if (arm_gen_movmemqi (operands))
5548         DONE;
5549       FAIL;
5550     }
5551   else /* TARGET_THUMB */
5552     {
5553       if (   INTVAL (operands[3]) != 4
5554           || INTVAL (operands[2]) > 48)
5555         FAIL;
5557       thumb_expand_movmemqi (operands);
5558       DONE;
5559     }
5560   "
5563 ;; Thumb block-move insns
5565 (define_insn "movmem12b"
5566   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5567         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5568    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5569         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5570    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5571         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5572    (set (match_operand:SI 0 "register_operand" "=l")
5573         (plus:SI (match_dup 2) (const_int 12)))
5574    (set (match_operand:SI 1 "register_operand" "=l")
5575         (plus:SI (match_dup 3) (const_int 12)))
5576    (clobber (match_scratch:SI 4 "=&l"))
5577    (clobber (match_scratch:SI 5 "=&l"))
5578    (clobber (match_scratch:SI 6 "=&l"))]
5579   "TARGET_THUMB"
5580   "* return thumb_output_move_mem_multiple (3, operands);"
5581   [(set_attr "length" "4")
5582    ; This isn't entirely accurate...  It loads as well, but in terms of
5583    ; scheduling the following insn it is better to consider it as a store
5584    (set_attr "type" "store3")]
5587 (define_insn "movmem8b"
5588   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5589         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5590    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5591         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5592    (set (match_operand:SI 0 "register_operand" "=l")
5593         (plus:SI (match_dup 2) (const_int 8)))
5594    (set (match_operand:SI 1 "register_operand" "=l")
5595         (plus:SI (match_dup 3) (const_int 8)))
5596    (clobber (match_scratch:SI 4 "=&l"))
5597    (clobber (match_scratch:SI 5 "=&l"))]
5598   "TARGET_THUMB"
5599   "* return thumb_output_move_mem_multiple (2, operands);"
5600   [(set_attr "length" "4")
5601    ; This isn't entirely accurate...  It loads as well, but in terms of
5602    ; scheduling the following insn it is better to consider it as a store
5603    (set_attr "type" "store2")]
5608 ;; Compare & branch insns
5609 ;; The range calculations are based as follows:
5610 ;; For forward branches, the address calculation returns the address of
5611 ;; the next instruction.  This is 2 beyond the branch instruction.
5612 ;; For backward branches, the address calculation returns the address of
5613 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5614 ;; instruction for the shortest sequence, and 4 before the branch instruction
5615 ;; if we have to jump around an unconditional branch.
5616 ;; To the basic branch range the PC offset must be added (this is +4).
5617 ;; So for forward branches we have 
5618 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5619 ;; And for backward branches we have 
5620 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5622 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5623 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5625 (define_expand "cbranchsi4"
5626   [(set (pc) (if_then_else
5627               (match_operator 0 "arm_comparison_operator"
5628                [(match_operand:SI 1 "s_register_operand" "")
5629                 (match_operand:SI 2 "nonmemory_operand" "")])
5630               (label_ref (match_operand 3 "" ""))
5631               (pc)))]
5632   "TARGET_THUMB"
5633   "
5634   if (thumb_cmpneg_operand (operands[2], SImode))
5635     {
5636       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5637                                               operands[3], operands[0]));
5638       DONE;
5639     }
5640   if (!thumb_cmp_operand (operands[2], SImode))
5641     operands[2] = force_reg (SImode, operands[2]);
5642   ")
5644 (define_insn "*cbranchsi4_insn"
5645   [(set (pc) (if_then_else
5646               (match_operator 0 "arm_comparison_operator"
5647                [(match_operand:SI 1 "s_register_operand" "l,*h")
5648                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5649               (label_ref (match_operand 3 "" ""))
5650               (pc)))]
5651   "TARGET_THUMB"
5652   "*
5653   output_asm_insn (\"cmp\\t%1, %2\", operands);
5655   switch (get_attr_length (insn))
5656     {
5657     case 4:  return \"b%d0\\t%l3\";
5658     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5659     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5660     }
5661   "
5662   [(set (attr "far_jump")
5663         (if_then_else
5664             (eq_attr "length" "8")
5665             (const_string "yes")
5666             (const_string "no")))
5667    (set (attr "length") 
5668         (if_then_else
5669             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5670                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5671             (const_int 4)
5672             (if_then_else
5673                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5674                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5675                 (const_int 6)
5676                 (const_int 8))))]
5679 (define_insn "cbranchsi4_scratch"
5680   [(set (pc) (if_then_else
5681               (match_operator 4 "arm_comparison_operator"
5682                [(match_operand:SI 1 "s_register_operand" "l,0")
5683                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5684               (label_ref (match_operand 3 "" ""))
5685               (pc)))
5686    (clobber (match_scratch:SI 0 "=l,l"))]
5687   "TARGET_THUMB"
5688   "*
5689   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5691   switch (get_attr_length (insn))
5692     {
5693     case 4:  return \"b%d4\\t%l3\";
5694     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5695     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5696     }
5697   "
5698   [(set (attr "far_jump")
5699         (if_then_else
5700             (eq_attr "length" "8")
5701             (const_string "yes")
5702             (const_string "no")))
5703    (set (attr "length") 
5704         (if_then_else
5705             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5706                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5707             (const_int 4)
5708             (if_then_else
5709                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5710                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5711                 (const_int 6)
5712                 (const_int 8))))]
5714 (define_insn "*movsi_cbranchsi4"
5715   [(set (pc)
5716         (if_then_else
5717          (match_operator 3 "arm_comparison_operator"
5718           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5719            (const_int 0)])
5720          (label_ref (match_operand 2 "" ""))
5721          (pc)))
5722    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5723         (match_dup 1))]
5724   "TARGET_THUMB"
5725   "*{
5726   if (which_alternative == 0)
5727     output_asm_insn (\"cmp\t%0, #0\", operands);
5728   else if (which_alternative == 1)
5729     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5730   else
5731     {
5732       output_asm_insn (\"cmp\t%1, #0\", operands);
5733       if (which_alternative == 2)
5734         output_asm_insn (\"mov\t%0, %1\", operands);
5735       else
5736         output_asm_insn (\"str\t%1, %0\", operands);
5737     }
5738   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5739     {
5740     case 4:  return \"b%d3\\t%l2\";
5741     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5742     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5743     }
5744   }"
5745   [(set (attr "far_jump")
5746         (if_then_else
5747             (ior (and (gt (symbol_ref ("which_alternative"))
5748                           (const_int 1))
5749                       (eq_attr "length" "8"))
5750                  (eq_attr "length" "10"))
5751             (const_string "yes")
5752             (const_string "no")))
5753    (set (attr "length")
5754      (if_then_else
5755        (le (symbol_ref ("which_alternative"))
5756                        (const_int 1))
5757        (if_then_else
5758          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5759               (le (minus (match_dup 2) (pc)) (const_int 256)))
5760          (const_int 4)
5761          (if_then_else
5762            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5763                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5764            (const_int 6)
5765            (const_int 8)))
5766        (if_then_else
5767          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5768               (le (minus (match_dup 2) (pc)) (const_int 256)))
5769          (const_int 6)
5770          (if_then_else
5771            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5772                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5773            (const_int 8)
5774            (const_int 10)))))]
5777 (define_insn "*negated_cbranchsi4"
5778   [(set (pc)
5779         (if_then_else
5780          (match_operator 0 "arm_comparison_operator"
5781           [(match_operand:SI 1 "s_register_operand" "l")
5782            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5783          (label_ref (match_operand 3 "" ""))
5784          (pc)))]
5785   "TARGET_THUMB"
5786   "*
5787   output_asm_insn (\"cmn\\t%1, %2\", operands);
5788   switch (get_attr_length (insn))
5789     {
5790     case 4:  return \"b%d0\\t%l3\";
5791     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5792     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5793     }
5794   "
5795   [(set (attr "far_jump")
5796         (if_then_else
5797             (eq_attr "length" "8")
5798             (const_string "yes")
5799             (const_string "no")))
5800    (set (attr "length") 
5801         (if_then_else
5802             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5803                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5804             (const_int 4)
5805             (if_then_else
5806                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5807                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5808                 (const_int 6)
5809                 (const_int 8))))]
5812 (define_insn "*tbit_cbranch"
5813   [(set (pc)
5814         (if_then_else
5815          (match_operator 0 "equality_operator"
5816           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5817                             (const_int 1)
5818                             (match_operand:SI 2 "const_int_operand" "i"))
5819            (const_int 0)])
5820          (label_ref (match_operand 3 "" ""))
5821          (pc)))
5822    (clobber (match_scratch:SI 4 "=l"))]
5823   "TARGET_THUMB"
5824   "*
5825   {
5826   rtx op[3];
5827   op[0] = operands[4];
5828   op[1] = operands[1];
5829   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5831   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5832   switch (get_attr_length (insn))
5833     {
5834     case 4:  return \"b%d0\\t%l3\";
5835     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5836     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5837     }
5838   }"
5839   [(set (attr "far_jump")
5840         (if_then_else
5841             (eq_attr "length" "8")
5842             (const_string "yes")
5843             (const_string "no")))
5844    (set (attr "length") 
5845         (if_then_else
5846             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5847                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5848             (const_int 4)
5849             (if_then_else
5850                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5851                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5852                 (const_int 6)
5853                 (const_int 8))))]
5855   
5856 (define_insn "*tstsi3_cbranch"
5857   [(set (pc)
5858         (if_then_else
5859          (match_operator 3 "equality_operator"
5860           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5861                    (match_operand:SI 1 "s_register_operand" "l"))
5862            (const_int 0)])
5863          (label_ref (match_operand 2 "" ""))
5864          (pc)))]
5865   "TARGET_THUMB"
5866   "*
5867   {
5868   output_asm_insn (\"tst\\t%0, %1\", operands);
5869   switch (get_attr_length (insn))
5870     {
5871     case 4:  return \"b%d3\\t%l2\";
5872     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5873     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5874     }
5875   }"
5876   [(set (attr "far_jump")
5877         (if_then_else
5878             (eq_attr "length" "8")
5879             (const_string "yes")
5880             (const_string "no")))
5881    (set (attr "length") 
5882         (if_then_else
5883             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5884                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5885             (const_int 4)
5886             (if_then_else
5887                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5888                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5889                 (const_int 6)
5890                 (const_int 8))))]
5892   
5893 (define_insn "*andsi3_cbranch"
5894   [(set (pc)
5895         (if_then_else
5896          (match_operator 5 "equality_operator"
5897           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5898                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5899            (const_int 0)])
5900          (label_ref (match_operand 4 "" ""))
5901          (pc)))
5902    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5903         (and:SI (match_dup 2) (match_dup 3)))
5904    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5905   "TARGET_THUMB"
5906   "*
5907   {
5908   if (which_alternative == 0)
5909     output_asm_insn (\"and\\t%0, %3\", operands);
5910   else if (which_alternative == 1)
5911     {
5912       output_asm_insn (\"and\\t%1, %3\", operands);
5913       output_asm_insn (\"mov\\t%0, %1\", operands);
5914     }
5915   else
5916     {
5917       output_asm_insn (\"and\\t%1, %3\", operands);
5918       output_asm_insn (\"str\\t%1, %0\", operands);
5919     }
5921   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5922     {
5923     case 4:  return \"b%d5\\t%l4\";
5924     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5925     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5926     }
5927   }"
5928   [(set (attr "far_jump")
5929         (if_then_else
5930             (ior (and (eq (symbol_ref ("which_alternative"))
5931                           (const_int 0))
5932                       (eq_attr "length" "8"))
5933                  (eq_attr "length" "10"))
5934             (const_string "yes")
5935             (const_string "no")))
5936    (set (attr "length")
5937      (if_then_else
5938        (eq (symbol_ref ("which_alternative"))
5939                        (const_int 0))
5940        (if_then_else
5941          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5942               (le (minus (match_dup 4) (pc)) (const_int 256)))
5943          (const_int 4)
5944          (if_then_else
5945            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5946                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5947            (const_int 6)
5948            (const_int 8)))
5949        (if_then_else
5950          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5951               (le (minus (match_dup 4) (pc)) (const_int 256)))
5952          (const_int 6)
5953          (if_then_else
5954            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5955                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5956            (const_int 8)
5957            (const_int 10)))))]
5960 (define_insn "*orrsi3_cbranch_scratch"
5961   [(set (pc)
5962         (if_then_else
5963          (match_operator 4 "equality_operator"
5964           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5965                    (match_operand:SI 2 "s_register_operand" "l"))
5966            (const_int 0)])
5967          (label_ref (match_operand 3 "" ""))
5968          (pc)))
5969    (clobber (match_scratch:SI 0 "=l"))]
5970   "TARGET_THUMB"
5971   "*
5972   {
5973   output_asm_insn (\"orr\\t%0, %2\", operands);
5974   switch (get_attr_length (insn))
5975     {
5976     case 4:  return \"b%d4\\t%l3\";
5977     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5978     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5979     }
5980   }"
5981   [(set (attr "far_jump")
5982         (if_then_else
5983             (eq_attr "length" "8")
5984             (const_string "yes")
5985             (const_string "no")))
5986    (set (attr "length") 
5987         (if_then_else
5988             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5989                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5990             (const_int 4)
5991             (if_then_else
5992                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5993                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5994                 (const_int 6)
5995                 (const_int 8))))]
5997   
5998 (define_insn "*orrsi3_cbranch"
5999   [(set (pc)
6000         (if_then_else
6001          (match_operator 5 "equality_operator"
6002           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6003                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6004            (const_int 0)])
6005          (label_ref (match_operand 4 "" ""))
6006          (pc)))
6007    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6008         (ior:SI (match_dup 2) (match_dup 3)))
6009    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6010   "TARGET_THUMB"
6011   "*
6012   {
6013   if (which_alternative == 0)
6014     output_asm_insn (\"orr\\t%0, %3\", operands);
6015   else if (which_alternative == 1)
6016     {
6017       output_asm_insn (\"orr\\t%1, %3\", operands);
6018       output_asm_insn (\"mov\\t%0, %1\", operands);
6019     }
6020   else
6021     {
6022       output_asm_insn (\"orr\\t%1, %3\", operands);
6023       output_asm_insn (\"str\\t%1, %0\", operands);
6024     }
6026   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6027     {
6028     case 4:  return \"b%d5\\t%l4\";
6029     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6030     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6031     }
6032   }"
6033   [(set (attr "far_jump")
6034         (if_then_else
6035             (ior (and (eq (symbol_ref ("which_alternative"))
6036                           (const_int 0))
6037                       (eq_attr "length" "8"))
6038                  (eq_attr "length" "10"))
6039             (const_string "yes")
6040             (const_string "no")))
6041    (set (attr "length")
6042      (if_then_else
6043        (eq (symbol_ref ("which_alternative"))
6044                        (const_int 0))
6045        (if_then_else
6046          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6047               (le (minus (match_dup 4) (pc)) (const_int 256)))
6048          (const_int 4)
6049          (if_then_else
6050            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6051                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6052            (const_int 6)
6053            (const_int 8)))
6054        (if_then_else
6055          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6056               (le (minus (match_dup 4) (pc)) (const_int 256)))
6057          (const_int 6)
6058          (if_then_else
6059            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6060                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6061            (const_int 8)
6062            (const_int 10)))))]
6065 (define_insn "*xorsi3_cbranch_scratch"
6066   [(set (pc)
6067         (if_then_else
6068          (match_operator 4 "equality_operator"
6069           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6070                    (match_operand:SI 2 "s_register_operand" "l"))
6071            (const_int 0)])
6072          (label_ref (match_operand 3 "" ""))
6073          (pc)))
6074    (clobber (match_scratch:SI 0 "=l"))]
6075   "TARGET_THUMB"
6076   "*
6077   {
6078   output_asm_insn (\"eor\\t%0, %2\", operands);
6079   switch (get_attr_length (insn))
6080     {
6081     case 4:  return \"b%d4\\t%l3\";
6082     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6083     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6084     }
6085   }"
6086   [(set (attr "far_jump")
6087         (if_then_else
6088             (eq_attr "length" "8")
6089             (const_string "yes")
6090             (const_string "no")))
6091    (set (attr "length") 
6092         (if_then_else
6093             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6094                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6095             (const_int 4)
6096             (if_then_else
6097                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6098                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6099                 (const_int 6)
6100                 (const_int 8))))]
6102   
6103 (define_insn "*xorsi3_cbranch"
6104   [(set (pc)
6105         (if_then_else
6106          (match_operator 5 "equality_operator"
6107           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6108                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6109            (const_int 0)])
6110          (label_ref (match_operand 4 "" ""))
6111          (pc)))
6112    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6113         (xor:SI (match_dup 2) (match_dup 3)))
6114    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6115   "TARGET_THUMB"
6116   "*
6117   {
6118   if (which_alternative == 0)
6119     output_asm_insn (\"eor\\t%0, %3\", operands);
6120   else if (which_alternative == 1)
6121     {
6122       output_asm_insn (\"eor\\t%1, %3\", operands);
6123       output_asm_insn (\"mov\\t%0, %1\", operands);
6124     }
6125   else
6126     {
6127       output_asm_insn (\"eor\\t%1, %3\", operands);
6128       output_asm_insn (\"str\\t%1, %0\", operands);
6129     }
6131   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6132     {
6133     case 4:  return \"b%d5\\t%l4\";
6134     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6135     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6136     }
6137   }"
6138   [(set (attr "far_jump")
6139         (if_then_else
6140             (ior (and (eq (symbol_ref ("which_alternative"))
6141                           (const_int 0))
6142                       (eq_attr "length" "8"))
6143                  (eq_attr "length" "10"))
6144             (const_string "yes")
6145             (const_string "no")))
6146    (set (attr "length")
6147      (if_then_else
6148        (eq (symbol_ref ("which_alternative"))
6149                        (const_int 0))
6150        (if_then_else
6151          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6152               (le (minus (match_dup 4) (pc)) (const_int 256)))
6153          (const_int 4)
6154          (if_then_else
6155            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6156                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6157            (const_int 6)
6158            (const_int 8)))
6159        (if_then_else
6160          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6161               (le (minus (match_dup 4) (pc)) (const_int 256)))
6162          (const_int 6)
6163          (if_then_else
6164            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6165                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6166            (const_int 8)
6167            (const_int 10)))))]
6170 (define_insn "*bicsi3_cbranch_scratch"
6171   [(set (pc)
6172         (if_then_else
6173          (match_operator 4 "equality_operator"
6174           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6175                    (match_operand:SI 1 "s_register_operand" "0"))
6176            (const_int 0)])
6177          (label_ref (match_operand 3 "" ""))
6178          (pc)))
6179    (clobber (match_scratch:SI 0 "=l"))]
6180   "TARGET_THUMB"
6181   "*
6182   {
6183   output_asm_insn (\"bic\\t%0, %2\", operands);
6184   switch (get_attr_length (insn))
6185     {
6186     case 4:  return \"b%d4\\t%l3\";
6187     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6188     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6189     }
6190   }"
6191   [(set (attr "far_jump")
6192         (if_then_else
6193             (eq_attr "length" "8")
6194             (const_string "yes")
6195             (const_string "no")))
6196    (set (attr "length") 
6197         (if_then_else
6198             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6199                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6200             (const_int 4)
6201             (if_then_else
6202                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6203                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6204                 (const_int 6)
6205                 (const_int 8))))]
6207   
6208 (define_insn "*bicsi3_cbranch"
6209   [(set (pc)
6210         (if_then_else
6211          (match_operator 5 "equality_operator"
6212           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6213                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6214            (const_int 0)])
6215          (label_ref (match_operand 4 "" ""))
6216          (pc)))
6217    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6218         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6219    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6220   "TARGET_THUMB"
6221   "*
6222   {
6223   if (which_alternative == 0)
6224     output_asm_insn (\"bic\\t%0, %3\", operands);
6225   else if (which_alternative <= 2)
6226     {
6227       output_asm_insn (\"bic\\t%1, %3\", operands);
6228       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6229          conditions again, since we're only testing for equality.  */
6230       output_asm_insn (\"mov\\t%0, %1\", operands);
6231     }
6232   else
6233     {
6234       output_asm_insn (\"bic\\t%1, %3\", operands);
6235       output_asm_insn (\"str\\t%1, %0\", operands);
6236     }
6238   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6239     {
6240     case 4:  return \"b%d5\\t%l4\";
6241     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6242     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6243     }
6244   }"
6245   [(set (attr "far_jump")
6246         (if_then_else
6247             (ior (and (eq (symbol_ref ("which_alternative"))
6248                           (const_int 0))
6249                       (eq_attr "length" "8"))
6250                  (eq_attr "length" "10"))
6251             (const_string "yes")
6252             (const_string "no")))
6253    (set (attr "length")
6254      (if_then_else
6255        (eq (symbol_ref ("which_alternative"))
6256                        (const_int 0))
6257        (if_then_else
6258          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6259               (le (minus (match_dup 4) (pc)) (const_int 256)))
6260          (const_int 4)
6261          (if_then_else
6262            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6263                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6264            (const_int 6)
6265            (const_int 8)))
6266        (if_then_else
6267          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6268               (le (minus (match_dup 4) (pc)) (const_int 256)))
6269          (const_int 6)
6270          (if_then_else
6271            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6272                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6273            (const_int 8)
6274            (const_int 10)))))]
6277 (define_insn "*cbranchne_decr1"
6278   [(set (pc)
6279         (if_then_else (match_operator 3 "equality_operator"
6280                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6281                         (const_int 0)])
6282                       (label_ref (match_operand 4 "" ""))
6283                       (pc)))
6284    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6285         (plus:SI (match_dup 2) (const_int -1)))
6286    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6287   "TARGET_THUMB"
6288   "*
6289    {
6290      rtx cond[2];
6291      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6292                                 ? GEU : LTU),
6293                                VOIDmode, operands[2], const1_rtx);
6294      cond[1] = operands[4];
6296      if (which_alternative == 0)
6297        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6298      else if (which_alternative == 1)
6299        {
6300          /* We must provide an alternative for a hi reg because reload 
6301             cannot handle output reloads on a jump instruction, but we
6302             can't subtract into that.  Fortunately a mov from lo to hi
6303             does not clobber the condition codes.  */
6304          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6305          output_asm_insn (\"mov\\t%0, %1\", operands);
6306        }
6307      else
6308        {
6309          /* Similarly, but the target is memory.  */
6310          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6311          output_asm_insn (\"str\\t%1, %0\", operands);
6312        }
6314      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6315        {
6316          case 4:
6317            output_asm_insn (\"b%d0\\t%l1\", cond);
6318            return \"\";
6319          case 6:
6320            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6321            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6322          default:
6323            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6324            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6325        }
6326    }
6327   "
6328   [(set (attr "far_jump")
6329         (if_then_else
6330             (ior (and (eq (symbol_ref ("which_alternative"))
6331                           (const_int 0))
6332                       (eq_attr "length" "8"))
6333                  (eq_attr "length" "10"))
6334             (const_string "yes")
6335             (const_string "no")))
6336    (set_attr_alternative "length"
6337       [
6338        ;; Alternative 0
6339        (if_then_else
6340          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6341               (le (minus (match_dup 4) (pc)) (const_int 256)))
6342          (const_int 4)
6343          (if_then_else
6344            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6345                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6346            (const_int 6)
6347            (const_int 8)))
6348        ;; Alternative 1
6349        (if_then_else
6350          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6351               (le (minus (match_dup 4) (pc)) (const_int 256)))
6352          (const_int 6)
6353          (if_then_else
6354            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6355                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6356            (const_int 8)
6357            (const_int 10)))
6358        ;; Alternative 2
6359        (if_then_else
6360          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6361               (le (minus (match_dup 4) (pc)) (const_int 256)))
6362          (const_int 6)
6363          (if_then_else
6364            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6365                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6366            (const_int 8)
6367            (const_int 10)))
6368        ;; Alternative 3
6369        (if_then_else
6370          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6371               (le (minus (match_dup 4) (pc)) (const_int 256)))
6372          (const_int 6)
6373          (if_then_else
6374            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6375                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6376            (const_int 8)
6377            (const_int 10)))])]
6380 (define_insn "*addsi3_cbranch"
6381   [(set (pc)
6382         (if_then_else
6383          (match_operator 4 "comparison_operator"
6384           [(plus:SI
6385             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6386             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6387            (const_int 0)])
6388          (label_ref (match_operand 5 "" ""))
6389          (pc)))
6390    (set
6391     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6392     (plus:SI (match_dup 2) (match_dup 3)))
6393    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6394   "TARGET_THUMB
6395    && (GET_CODE (operands[4]) == EQ
6396        || GET_CODE (operands[4]) == NE
6397        || GET_CODE (operands[4]) == GE
6398        || GET_CODE (operands[4]) == LT)"
6399   "*
6400    {
6401      rtx cond[3];
6403      
6404      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6405      cond[1] = operands[2];
6406      cond[2] = operands[3];
6408      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6409        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6410      else
6411        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6413      if (which_alternative >= 3
6414          && which_alternative < 4)
6415        output_asm_insn (\"mov\\t%0, %1\", operands);
6416      else if (which_alternative >= 4)
6417        output_asm_insn (\"str\\t%1, %0\", operands);
6419      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6420        {
6421          case 4:
6422            return \"b%d4\\t%l5\";
6423          case 6:
6424            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6425          default:
6426            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6427        }
6428    }
6429   "
6430   [(set (attr "far_jump")
6431         (if_then_else
6432             (ior (and (lt (symbol_ref ("which_alternative"))
6433                           (const_int 3))
6434                       (eq_attr "length" "8"))
6435                  (eq_attr "length" "10"))
6436             (const_string "yes")
6437             (const_string "no")))
6438    (set (attr "length")
6439      (if_then_else
6440        (lt (symbol_ref ("which_alternative"))
6441                        (const_int 3))
6442        (if_then_else
6443          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6444               (le (minus (match_dup 5) (pc)) (const_int 256)))
6445          (const_int 4)
6446          (if_then_else
6447            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6448                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6449            (const_int 6)
6450            (const_int 8)))
6451        (if_then_else
6452          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6453               (le (minus (match_dup 5) (pc)) (const_int 256)))
6454          (const_int 6)
6455          (if_then_else
6456            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6457                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6458            (const_int 8)
6459            (const_int 10)))))]
6462 (define_insn "*addsi3_cbranch_scratch"
6463   [(set (pc)
6464         (if_then_else
6465          (match_operator 3 "comparison_operator"
6466           [(plus:SI
6467             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6468             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6469            (const_int 0)])
6470          (label_ref (match_operand 4 "" ""))
6471          (pc)))
6472    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6473   "TARGET_THUMB
6474    && (GET_CODE (operands[3]) == EQ
6475        || GET_CODE (operands[3]) == NE
6476        || GET_CODE (operands[3]) == GE
6477        || GET_CODE (operands[3]) == LT)"
6478   "*
6479    {
6480      switch (which_alternative)
6481        {
6482        case 0:
6483          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6484          break;
6485        case 1:
6486          output_asm_insn (\"cmn\t%1, %2\", operands);
6487          break;
6488        case 2:
6489          if (INTVAL (operands[2]) < 0)
6490            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6491          else
6492            output_asm_insn (\"add\t%0, %1, %2\", operands);
6493          break;
6494        case 3:
6495          if (INTVAL (operands[2]) < 0)
6496            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6497          else
6498            output_asm_insn (\"add\t%0, %0, %2\", operands);
6499          break;
6500        }
6502      switch (get_attr_length (insn))
6503        {
6504          case 4:
6505            return \"b%d3\\t%l4\";
6506          case 6:
6507            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6508          default:
6509            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6510        }
6511    }
6512   "
6513   [(set (attr "far_jump")
6514         (if_then_else
6515             (eq_attr "length" "8")
6516             (const_string "yes")
6517             (const_string "no")))
6518    (set (attr "length")
6519        (if_then_else
6520          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6521               (le (minus (match_dup 4) (pc)) (const_int 256)))
6522          (const_int 4)
6523          (if_then_else
6524            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6525                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6526            (const_int 6)
6527            (const_int 8))))]
6530 (define_insn "*subsi3_cbranch"
6531   [(set (pc)
6532         (if_then_else
6533          (match_operator 4 "comparison_operator"
6534           [(minus:SI
6535             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6536             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6537            (const_int 0)])
6538          (label_ref (match_operand 5 "" ""))
6539          (pc)))
6540    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6541         (minus:SI (match_dup 2) (match_dup 3)))
6542    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6543   "TARGET_THUMB
6544    && (GET_CODE (operands[4]) == EQ
6545        || GET_CODE (operands[4]) == NE
6546        || GET_CODE (operands[4]) == GE
6547        || GET_CODE (operands[4]) == LT)"
6548   "*
6549    {
6550      if (which_alternative == 0)
6551        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6552      else if (which_alternative == 1)
6553        {
6554          /* We must provide an alternative for a hi reg because reload 
6555             cannot handle output reloads on a jump instruction, but we
6556             can't subtract into that.  Fortunately a mov from lo to hi
6557             does not clobber the condition codes.  */
6558          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6559          output_asm_insn (\"mov\\t%0, %1\", operands);
6560        }
6561      else
6562        {
6563          /* Similarly, but the target is memory.  */
6564          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6565          output_asm_insn (\"str\\t%1, %0\", operands);
6566        }
6568      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6569        {
6570          case 4:
6571            return \"b%d4\\t%l5\";
6572          case 6:
6573            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6574          default:
6575            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6576        }
6577    }
6578   "
6579   [(set (attr "far_jump")
6580         (if_then_else
6581             (ior (and (eq (symbol_ref ("which_alternative"))
6582                           (const_int 0))
6583                       (eq_attr "length" "8"))
6584                  (eq_attr "length" "10"))
6585             (const_string "yes")
6586             (const_string "no")))
6587    (set (attr "length")
6588      (if_then_else
6589        (eq (symbol_ref ("which_alternative"))
6590                        (const_int 0))
6591        (if_then_else
6592          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6593               (le (minus (match_dup 5) (pc)) (const_int 256)))
6594          (const_int 4)
6595          (if_then_else
6596            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6597                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6598            (const_int 6)
6599            (const_int 8)))
6600        (if_then_else
6601          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6602               (le (minus (match_dup 5) (pc)) (const_int 256)))
6603          (const_int 6)
6604          (if_then_else
6605            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6606                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6607            (const_int 8)
6608            (const_int 10)))))]
6611 (define_insn "*subsi3_cbranch_scratch"
6612   [(set (pc)
6613         (if_then_else
6614          (match_operator 0 "arm_comparison_operator"
6615           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6616                      (match_operand:SI 2 "nonmemory_operand" "l"))
6617            (const_int 0)])
6618          (label_ref (match_operand 3 "" ""))
6619          (pc)))]
6620   "TARGET_THUMB
6621    && (GET_CODE (operands[0]) == EQ
6622        || GET_CODE (operands[0]) == NE
6623        || GET_CODE (operands[0]) == GE
6624        || GET_CODE (operands[0]) == LT)"
6625   "*
6626   output_asm_insn (\"cmp\\t%1, %2\", operands);
6627   switch (get_attr_length (insn))
6628     {
6629     case 4:  return \"b%d0\\t%l3\";
6630     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6631     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6632     }
6633   "
6634   [(set (attr "far_jump")
6635         (if_then_else
6636             (eq_attr "length" "8")
6637             (const_string "yes")
6638             (const_string "no")))
6639    (set (attr "length") 
6640         (if_then_else
6641             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6642                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6643             (const_int 4)
6644             (if_then_else
6645                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6646                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6647                 (const_int 6)
6648                 (const_int 8))))]
6651 ;; Comparison and test insns
6653 (define_expand "cmpsi"
6654   [(match_operand:SI 0 "s_register_operand" "")
6655    (match_operand:SI 1 "arm_add_operand" "")]
6656   "TARGET_ARM"
6657   "{
6658     arm_compare_op0 = operands[0];
6659     arm_compare_op1 = operands[1];
6660     DONE;
6661   }"
6664 (define_expand "cmpsf"
6665   [(match_operand:SF 0 "s_register_operand" "")
6666    (match_operand:SF 1 "arm_float_compare_operand" "")]
6667   "TARGET_ARM && TARGET_HARD_FLOAT"
6668   "
6669   arm_compare_op0 = operands[0];
6670   arm_compare_op1 = operands[1];
6671   DONE;
6672   "
6675 (define_expand "cmpdf"
6676   [(match_operand:DF 0 "s_register_operand" "")
6677    (match_operand:DF 1 "arm_float_compare_operand" "")]
6678   "TARGET_ARM && TARGET_HARD_FLOAT"
6679   "
6680   arm_compare_op0 = operands[0];
6681   arm_compare_op1 = operands[1];
6682   DONE;
6683   "
6686 (define_insn "*arm_cmpsi_insn"
6687   [(set (reg:CC CC_REGNUM)
6688         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6689                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6690   "TARGET_ARM"
6691   "@
6692    cmp%?\\t%0, %1
6693    cmn%?\\t%0, #%n1"
6694   [(set_attr "conds" "set")]
6697 (define_insn "*cmpsi_shiftsi"
6698   [(set (reg:CC CC_REGNUM)
6699         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6700                     (match_operator:SI  3 "shift_operator"
6701                      [(match_operand:SI 1 "s_register_operand" "r")
6702                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6703   "TARGET_ARM"
6704   "cmp%?\\t%0, %1%S3"
6705   [(set_attr "conds" "set")
6706    (set_attr "shift" "1")
6707    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6708                       (const_string "alu_shift")
6709                       (const_string "alu_shift_reg")))]
6712 (define_insn "*cmpsi_shiftsi_swp"
6713   [(set (reg:CC_SWP CC_REGNUM)
6714         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6715                          [(match_operand:SI 1 "s_register_operand" "r")
6716                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6717                         (match_operand:SI 0 "s_register_operand" "r")))]
6718   "TARGET_ARM"
6719   "cmp%?\\t%0, %1%S3"
6720   [(set_attr "conds" "set")
6721    (set_attr "shift" "1")
6722    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6723                       (const_string "alu_shift")
6724                       (const_string "alu_shift_reg")))]
6727 (define_insn "*cmpsi_neg_shiftsi"
6728   [(set (reg:CC CC_REGNUM)
6729         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6730                     (neg:SI (match_operator:SI 3 "shift_operator"
6731                              [(match_operand:SI 1 "s_register_operand" "r")
6732                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6733   "TARGET_ARM"
6734   "cmn%?\\t%0, %1%S3"
6735   [(set_attr "conds" "set")
6736    (set_attr "shift" "1")
6737    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6738                       (const_string "alu_shift")
6739                       (const_string "alu_shift_reg")))]
6742 ;; Cirrus SF compare instruction
6743 (define_insn "*cirrus_cmpsf"
6744   [(set (reg:CCFP CC_REGNUM)
6745         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6746                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6747   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6748   "cfcmps%?\\tr15, %V0, %V1"
6749   [(set_attr "type"   "mav_farith")
6750    (set_attr "cirrus" "compare")]
6753 ;; Cirrus DF compare instruction
6754 (define_insn "*cirrus_cmpdf"
6755   [(set (reg:CCFP CC_REGNUM)
6756         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6757                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6758   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6759   "cfcmpd%?\\tr15, %V0, %V1"
6760   [(set_attr "type"   "mav_farith")
6761    (set_attr "cirrus" "compare")]
6764 ;; Cirrus DI compare instruction
6765 (define_expand "cmpdi"
6766   [(match_operand:DI 0 "cirrus_fp_register" "")
6767    (match_operand:DI 1 "cirrus_fp_register" "")]
6768   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6769   "{
6770      arm_compare_op0 = operands[0];
6771      arm_compare_op1 = operands[1];
6772      DONE;
6773    }")
6775 (define_insn "*cirrus_cmpdi"
6776   [(set (reg:CC CC_REGNUM)
6777         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6778                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6779   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6780   "cfcmp64%?\\tr15, %V0, %V1"
6781   [(set_attr "type"   "mav_farith")
6782    (set_attr "cirrus" "compare")]
6785 ; This insn allows redundant compares to be removed by cse, nothing should
6786 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6787 ; is deleted later on. The match_dup will match the mode here, so that
6788 ; mode changes of the condition codes aren't lost by this even though we don't
6789 ; specify what they are.
6791 (define_insn "*deleted_compare"
6792   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6793   "TARGET_ARM"
6794   "\\t%@ deleted compare"
6795   [(set_attr "conds" "set")
6796    (set_attr "length" "0")]
6800 ;; Conditional branch insns
6802 (define_expand "beq"
6803   [(set (pc)
6804         (if_then_else (eq (match_dup 1) (const_int 0))
6805                       (label_ref (match_operand 0 "" ""))
6806                       (pc)))]
6807   "TARGET_ARM"
6808   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6811 (define_expand "bne"
6812   [(set (pc)
6813         (if_then_else (ne (match_dup 1) (const_int 0))
6814                       (label_ref (match_operand 0 "" ""))
6815                       (pc)))]
6816   "TARGET_ARM"
6817   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6820 (define_expand "bgt"
6821   [(set (pc)
6822         (if_then_else (gt (match_dup 1) (const_int 0))
6823                       (label_ref (match_operand 0 "" ""))
6824                       (pc)))]
6825   "TARGET_ARM"
6826   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6829 (define_expand "ble"
6830   [(set (pc)
6831         (if_then_else (le (match_dup 1) (const_int 0))
6832                       (label_ref (match_operand 0 "" ""))
6833                       (pc)))]
6834   "TARGET_ARM"
6835   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6838 (define_expand "bge"
6839   [(set (pc)
6840         (if_then_else (ge (match_dup 1) (const_int 0))
6841                       (label_ref (match_operand 0 "" ""))
6842                       (pc)))]
6843   "TARGET_ARM"
6844   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6847 (define_expand "blt"
6848   [(set (pc)
6849         (if_then_else (lt (match_dup 1) (const_int 0))
6850                       (label_ref (match_operand 0 "" ""))
6851                       (pc)))]
6852   "TARGET_ARM"
6853   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6856 (define_expand "bgtu"
6857   [(set (pc)
6858         (if_then_else (gtu (match_dup 1) (const_int 0))
6859                       (label_ref (match_operand 0 "" ""))
6860                       (pc)))]
6861   "TARGET_ARM"
6862   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6865 (define_expand "bleu"
6866   [(set (pc)
6867         (if_then_else (leu (match_dup 1) (const_int 0))
6868                       (label_ref (match_operand 0 "" ""))
6869                       (pc)))]
6870   "TARGET_ARM"
6871   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6874 (define_expand "bgeu"
6875   [(set (pc)
6876         (if_then_else (geu (match_dup 1) (const_int 0))
6877                       (label_ref (match_operand 0 "" ""))
6878                       (pc)))]
6879   "TARGET_ARM"
6880   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6883 (define_expand "bltu"
6884   [(set (pc)
6885         (if_then_else (ltu (match_dup 1) (const_int 0))
6886                       (label_ref (match_operand 0 "" ""))
6887                       (pc)))]
6888   "TARGET_ARM"
6889   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6892 (define_expand "bunordered"
6893   [(set (pc)
6894         (if_then_else (unordered (match_dup 1) (const_int 0))
6895                       (label_ref (match_operand 0 "" ""))
6896                       (pc)))]
6897   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6898   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6899                                       arm_compare_op1);"
6902 (define_expand "bordered"
6903   [(set (pc)
6904         (if_then_else (ordered (match_dup 1) (const_int 0))
6905                       (label_ref (match_operand 0 "" ""))
6906                       (pc)))]
6907   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6908   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6909                                       arm_compare_op1);"
6912 (define_expand "bungt"
6913   [(set (pc)
6914         (if_then_else (ungt (match_dup 1) (const_int 0))
6915                       (label_ref (match_operand 0 "" ""))
6916                       (pc)))]
6917   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6918   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6921 (define_expand "bunlt"
6922   [(set (pc)
6923         (if_then_else (unlt (match_dup 1) (const_int 0))
6924                       (label_ref (match_operand 0 "" ""))
6925                       (pc)))]
6926   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6927   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6930 (define_expand "bunge"
6931   [(set (pc)
6932         (if_then_else (unge (match_dup 1) (const_int 0))
6933                       (label_ref (match_operand 0 "" ""))
6934                       (pc)))]
6935   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6936   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6939 (define_expand "bunle"
6940   [(set (pc)
6941         (if_then_else (unle (match_dup 1) (const_int 0))
6942                       (label_ref (match_operand 0 "" ""))
6943                       (pc)))]
6944   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6945   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6948 ;; The following two patterns need two branch instructions, since there is
6949 ;; no single instruction that will handle all cases.
6950 (define_expand "buneq"
6951   [(set (pc)
6952         (if_then_else (uneq (match_dup 1) (const_int 0))
6953                       (label_ref (match_operand 0 "" ""))
6954                       (pc)))]
6955   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6956   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6959 (define_expand "bltgt"
6960   [(set (pc)
6961         (if_then_else (ltgt (match_dup 1) (const_int 0))
6962                       (label_ref (match_operand 0 "" ""))
6963                       (pc)))]
6964   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6965   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6969 ;; Patterns to match conditional branch insns.
6972 ; Special pattern to match UNEQ.
6973 (define_insn "*arm_buneq"
6974   [(set (pc)
6975         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6976                       (label_ref (match_operand 0 "" ""))
6977                       (pc)))]
6978   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6979   "*
6980   if (arm_ccfsm_state != 0)
6981     abort ();
6983   return \"bvs\\t%l0\;beq\\t%l0\";
6984   "
6985   [(set_attr "conds" "jump_clob")
6986    (set_attr "length" "8")]
6989 ; Special pattern to match LTGT.
6990 (define_insn "*arm_bltgt"
6991   [(set (pc)
6992         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6993                       (label_ref (match_operand 0 "" ""))
6994                       (pc)))]
6995   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6996   "*
6997   if (arm_ccfsm_state != 0)
6998     abort ();
7000   return \"bmi\\t%l0\;bgt\\t%l0\";
7001   "
7002   [(set_attr "conds" "jump_clob")
7003    (set_attr "length" "8")]
7006 (define_insn "*arm_cond_branch"
7007   [(set (pc)
7008         (if_then_else (match_operator 1 "arm_comparison_operator"
7009                        [(match_operand 2 "cc_register" "") (const_int 0)])
7010                       (label_ref (match_operand 0 "" ""))
7011                       (pc)))]
7012   "TARGET_ARM"
7013   "*
7014   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7015     {
7016       arm_ccfsm_state += 2;
7017       return \"\";
7018     }
7019   return \"b%d1\\t%l0\";
7020   "
7021   [(set_attr "conds" "use")
7022    (set_attr "type" "branch")]
7025 ; Special pattern to match reversed UNEQ.
7026 (define_insn "*arm_buneq_reversed"
7027   [(set (pc)
7028         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7029                       (pc)
7030                       (label_ref (match_operand 0 "" ""))))]
7031   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7032   "*
7033   if (arm_ccfsm_state != 0)
7034     abort ();
7036   return \"bmi\\t%l0\;bgt\\t%l0\";
7037   "
7038   [(set_attr "conds" "jump_clob")
7039    (set_attr "length" "8")]
7042 ; Special pattern to match reversed LTGT.
7043 (define_insn "*arm_bltgt_reversed"
7044   [(set (pc)
7045         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7046                       (pc)
7047                       (label_ref (match_operand 0 "" ""))))]
7048   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7049   "*
7050   if (arm_ccfsm_state != 0)
7051     abort ();
7053   return \"bvs\\t%l0\;beq\\t%l0\";
7054   "
7055   [(set_attr "conds" "jump_clob")
7056    (set_attr "length" "8")]
7059 (define_insn "*arm_cond_branch_reversed"
7060   [(set (pc)
7061         (if_then_else (match_operator 1 "arm_comparison_operator"
7062                        [(match_operand 2 "cc_register" "") (const_int 0)])
7063                       (pc)
7064                       (label_ref (match_operand 0 "" ""))))]
7065   "TARGET_ARM"
7066   "*
7067   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7068     {
7069       arm_ccfsm_state += 2;
7070       return \"\";
7071     }
7072   return \"b%D1\\t%l0\";
7073   "
7074   [(set_attr "conds" "use")
7075    (set_attr "type" "branch")]
7080 ; scc insns
7082 (define_expand "seq"
7083   [(set (match_operand:SI 0 "s_register_operand" "")
7084         (eq:SI (match_dup 1) (const_int 0)))]
7085   "TARGET_ARM"
7086   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7089 (define_expand "sne"
7090   [(set (match_operand:SI 0 "s_register_operand" "")
7091         (ne:SI (match_dup 1) (const_int 0)))]
7092   "TARGET_ARM"
7093   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7096 (define_expand "sgt"
7097   [(set (match_operand:SI 0 "s_register_operand" "")
7098         (gt:SI (match_dup 1) (const_int 0)))]
7099   "TARGET_ARM"
7100   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7103 (define_expand "sle"
7104   [(set (match_operand:SI 0 "s_register_operand" "")
7105         (le:SI (match_dup 1) (const_int 0)))]
7106   "TARGET_ARM"
7107   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7110 (define_expand "sge"
7111   [(set (match_operand:SI 0 "s_register_operand" "")
7112         (ge:SI (match_dup 1) (const_int 0)))]
7113   "TARGET_ARM"
7114   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7117 (define_expand "slt"
7118   [(set (match_operand:SI 0 "s_register_operand" "")
7119         (lt:SI (match_dup 1) (const_int 0)))]
7120   "TARGET_ARM"
7121   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7124 (define_expand "sgtu"
7125   [(set (match_operand:SI 0 "s_register_operand" "")
7126         (gtu:SI (match_dup 1) (const_int 0)))]
7127   "TARGET_ARM"
7128   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7131 (define_expand "sleu"
7132   [(set (match_operand:SI 0 "s_register_operand" "")
7133         (leu:SI (match_dup 1) (const_int 0)))]
7134   "TARGET_ARM"
7135   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7138 (define_expand "sgeu"
7139   [(set (match_operand:SI 0 "s_register_operand" "")
7140         (geu:SI (match_dup 1) (const_int 0)))]
7141   "TARGET_ARM"
7142   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7145 (define_expand "sltu"
7146   [(set (match_operand:SI 0 "s_register_operand" "")
7147         (ltu:SI (match_dup 1) (const_int 0)))]
7148   "TARGET_ARM"
7149   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7152 (define_expand "sunordered"
7153   [(set (match_operand:SI 0 "s_register_operand" "")
7154         (unordered:SI (match_dup 1) (const_int 0)))]
7155   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7156   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7157                                       arm_compare_op1);"
7160 (define_expand "sordered"
7161   [(set (match_operand:SI 0 "s_register_operand" "")
7162         (ordered:SI (match_dup 1) (const_int 0)))]
7163   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7164   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7165                                       arm_compare_op1);"
7168 (define_expand "sungt"
7169   [(set (match_operand:SI 0 "s_register_operand" "")
7170         (ungt:SI (match_dup 1) (const_int 0)))]
7171   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7172   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7173                                       arm_compare_op1);"
7176 (define_expand "sunge"
7177   [(set (match_operand:SI 0 "s_register_operand" "")
7178         (unge:SI (match_dup 1) (const_int 0)))]
7179   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7180   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7181                                       arm_compare_op1);"
7184 (define_expand "sunlt"
7185   [(set (match_operand:SI 0 "s_register_operand" "")
7186         (unlt:SI (match_dup 1) (const_int 0)))]
7187   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7188   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7189                                       arm_compare_op1);"
7192 (define_expand "sunle"
7193   [(set (match_operand:SI 0 "s_register_operand" "")
7194         (unle:SI (match_dup 1) (const_int 0)))]
7195   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7196   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7197                                       arm_compare_op1);"
7200 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7201 ;;; simple ARM instructions. 
7203 ; (define_expand "suneq"
7204 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7205 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7206 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7207 ;   "abort ();"
7208 ; )
7210 ; (define_expand "sltgt"
7211 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7212 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7213 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7214 ;   "abort ();"
7215 ; )
7217 (define_insn "*mov_scc"
7218   [(set (match_operand:SI 0 "s_register_operand" "=r")
7219         (match_operator:SI 1 "arm_comparison_operator"
7220          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7221   "TARGET_ARM"
7222   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7223   [(set_attr "conds" "use")
7224    (set_attr "length" "8")]
7227 (define_insn "*mov_negscc"
7228   [(set (match_operand:SI 0 "s_register_operand" "=r")
7229         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7230                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7231   "TARGET_ARM"
7232   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7233   [(set_attr "conds" "use")
7234    (set_attr "length" "8")]
7237 (define_insn "*mov_notscc"
7238   [(set (match_operand:SI 0 "s_register_operand" "=r")
7239         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7240                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7241   "TARGET_ARM"
7242   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7243   [(set_attr "conds" "use")
7244    (set_attr "length" "8")]
7248 ;; Conditional move insns
7250 (define_expand "movsicc"
7251   [(set (match_operand:SI 0 "s_register_operand" "")
7252         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7253                          (match_operand:SI 2 "arm_not_operand" "")
7254                          (match_operand:SI 3 "arm_not_operand" "")))]
7255   "TARGET_ARM"
7256   "
7257   {
7258     enum rtx_code code = GET_CODE (operands[1]);
7259     rtx ccreg;
7261     if (code == UNEQ || code == LTGT)
7262       FAIL;
7264     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7265     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7266   }"
7269 (define_expand "movsfcc"
7270   [(set (match_operand:SF 0 "s_register_operand" "")
7271         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7272                          (match_operand:SF 2 "s_register_operand" "")
7273                          (match_operand:SF 3 "nonmemory_operand" "")))]
7274   "TARGET_ARM"
7275   "
7276   {
7277     enum rtx_code code = GET_CODE (operands[1]);
7278     rtx ccreg;
7280     if (code == UNEQ || code == LTGT)
7281       FAIL;
7283     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7284        Otherwise, ensure it is a valid FP add operand */
7285     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7286         || (!arm_float_add_operand (operands[3], SFmode)))
7287       operands[3] = force_reg (SFmode, operands[3]);
7289     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7290     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7291   }"
7294 (define_expand "movdfcc"
7295   [(set (match_operand:DF 0 "s_register_operand" "")
7296         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7297                          (match_operand:DF 2 "s_register_operand" "")
7298                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7299   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7300   "
7301   {
7302     enum rtx_code code = GET_CODE (operands[1]);
7303     rtx ccreg;
7305     if (code == UNEQ || code == LTGT)
7306       FAIL;
7308     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7309     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7310   }"
7313 (define_insn "*movsicc_insn"
7314   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7315         (if_then_else:SI
7316          (match_operator 3 "arm_comparison_operator"
7317           [(match_operand 4 "cc_register" "") (const_int 0)])
7318          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7319          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7320   "TARGET_ARM"
7321   "@
7322    mov%D3\\t%0, %2
7323    mvn%D3\\t%0, #%B2
7324    mov%d3\\t%0, %1
7325    mvn%d3\\t%0, #%B1
7326    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7327    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7328    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7329    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7330   [(set_attr "length" "4,4,4,4,8,8,8,8")
7331    (set_attr "conds" "use")]
7334 (define_insn "*movsfcc_soft_insn"
7335   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7336         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7337                           [(match_operand 4 "cc_register" "") (const_int 0)])
7338                          (match_operand:SF 1 "s_register_operand" "0,r")
7339                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7340   "TARGET_ARM && TARGET_SOFT_FLOAT"
7341   "@
7342    mov%D3\\t%0, %2
7343    mov%d3\\t%0, %1"
7344   [(set_attr "conds" "use")]
7348 ;; Jump and linkage insns
7350 (define_expand "jump"
7351   [(set (pc)
7352         (label_ref (match_operand 0 "" "")))]
7353   "TARGET_EITHER"
7354   ""
7357 (define_insn "*arm_jump"
7358   [(set (pc)
7359         (label_ref (match_operand 0 "" "")))]
7360   "TARGET_ARM"
7361   "*
7362   {
7363     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7364       {
7365         arm_ccfsm_state += 2;
7366         return \"\";
7367       }
7368     return \"b%?\\t%l0\";
7369   }
7370   "
7371   [(set_attr "predicable" "yes")]
7374 (define_insn "*thumb_jump"
7375   [(set (pc)
7376         (label_ref (match_operand 0 "" "")))]
7377   "TARGET_THUMB"
7378   "*
7379   if (get_attr_length (insn) == 2)
7380     return \"b\\t%l0\";
7381   return \"bl\\t%l0\\t%@ far jump\";
7382   "
7383   [(set (attr "far_jump")
7384         (if_then_else
7385             (eq_attr "length" "4")
7386             (const_string "yes")
7387             (const_string "no")))
7388    (set (attr "length") 
7389         (if_then_else
7390             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7391                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7392             (const_int 2)
7393             (const_int 4)))]
7396 (define_expand "call"
7397   [(parallel [(call (match_operand 0 "memory_operand" "")
7398                     (match_operand 1 "general_operand" ""))
7399               (use (match_operand 2 "" ""))
7400               (clobber (reg:SI LR_REGNUM))])]
7401   "TARGET_EITHER"
7402   "
7403   {
7404     rtx callee;
7405     
7406     /* In an untyped call, we can get NULL for operand 2.  */
7407     if (operands[2] == NULL_RTX)
7408       operands[2] = const0_rtx;
7409       
7410     /* This is to decide if we should generate indirect calls by loading the
7411        32 bit address of the callee into a register before performing the
7412        branch and link.  operand[2] encodes the long_call/short_call
7413        attribute of the function being called.  This attribute is set whenever
7414        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7415        is used, and the short_call attribute can also be set if function is
7416        declared as static or if it has already been defined in the current
7417        compilation unit.  See arm.c and arm.h for info about this.  The third
7418        parameter to arm_is_longcall_p is used to tell it which pattern
7419        invoked it.  */
7420     callee  = XEXP (operands[0], 0);
7421     
7422     if (GET_CODE (callee) != REG
7423        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7424       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7425   }"
7428 (define_insn "*call_reg_armv5"
7429   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7430          (match_operand 1 "" ""))
7431    (use (match_operand 2 "" ""))
7432    (clobber (reg:SI LR_REGNUM))]
7433   "TARGET_ARM && arm_arch5"
7434   "blx%?\\t%0"
7435   [(set_attr "type" "call")]
7438 (define_insn "*call_reg_arm"
7439   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7440          (match_operand 1 "" ""))
7441    (use (match_operand 2 "" ""))
7442    (clobber (reg:SI LR_REGNUM))]
7443   "TARGET_ARM && !arm_arch5"
7444   "*
7445   return output_call (operands);
7446   "
7447   ;; length is worst case, normally it is only two
7448   [(set_attr "length" "12")
7449    (set_attr "type" "call")]
7452 (define_insn "*call_mem"
7453   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7454          (match_operand 1 "" ""))
7455    (use (match_operand 2 "" ""))
7456    (clobber (reg:SI LR_REGNUM))]
7457   "TARGET_ARM"
7458   "*
7459   return output_call_mem (operands);
7460   "
7461   [(set_attr "length" "12")
7462    (set_attr "type" "call")]
7465 (define_insn "*call_reg_thumb_v5"
7466   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7467          (match_operand 1 "" ""))
7468    (use (match_operand 2 "" ""))
7469    (clobber (reg:SI LR_REGNUM))]
7470   "TARGET_THUMB && arm_arch5"
7471   "blx\\t%0"
7472   [(set_attr "length" "2")
7473    (set_attr "type" "call")]
7476 (define_insn "*call_reg_thumb"
7477   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7478          (match_operand 1 "" ""))
7479    (use (match_operand 2 "" ""))
7480    (clobber (reg:SI LR_REGNUM))]
7481   "TARGET_THUMB && !arm_arch5"
7482   "*
7483   {
7484     if (!TARGET_CALLER_INTERWORKING)
7485       return thumb_call_via_reg (operands[0]);
7486     else if (operands[1] == const0_rtx)
7487       return \"bl\\t%__interwork_call_via_%0\";
7488     else if (frame_pointer_needed)
7489       return \"bl\\t%__interwork_r7_call_via_%0\";
7490     else
7491       return \"bl\\t%__interwork_r11_call_via_%0\";
7492   }"
7493   [(set_attr "type" "call")]
7496 (define_expand "call_value"
7497   [(parallel [(set (match_operand       0 "" "")
7498                    (call (match_operand 1 "memory_operand" "")
7499                          (match_operand 2 "general_operand" "")))
7500               (use (match_operand 3 "" ""))
7501               (clobber (reg:SI LR_REGNUM))])]
7502   "TARGET_EITHER"
7503   "
7504   {
7505     rtx callee = XEXP (operands[1], 0);
7506     
7507     /* In an untyped call, we can get NULL for operand 2.  */
7508     if (operands[3] == 0)
7509       operands[3] = const0_rtx;
7510       
7511     /* See the comment in define_expand \"call\".  */
7512     if (GET_CODE (callee) != REG
7513         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7514       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7515   }"
7518 (define_insn "*call_value_reg_armv5"
7519   [(set (match_operand 0 "" "")
7520         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7521               (match_operand 2 "" "")))
7522    (use (match_operand 3 "" ""))
7523    (clobber (reg:SI LR_REGNUM))]
7524   "TARGET_ARM && arm_arch5"
7525   "blx%?\\t%1"
7526   [(set_attr "type" "call")]
7529 (define_insn "*call_value_reg_arm"
7530   [(set (match_operand 0 "" "")
7531         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7532               (match_operand 2 "" "")))
7533    (use (match_operand 3 "" ""))
7534    (clobber (reg:SI LR_REGNUM))]
7535   "TARGET_ARM && !arm_arch5"
7536   "*
7537   return output_call (&operands[1]);
7538   "
7539   [(set_attr "length" "12")
7540    (set_attr "type" "call")]
7543 (define_insn "*call_value_mem"
7544   [(set (match_operand 0 "" "")
7545         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7546               (match_operand 2 "" "")))
7547    (use (match_operand 3 "" ""))
7548    (clobber (reg:SI LR_REGNUM))]
7549   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7550   "*
7551   return output_call_mem (&operands[1]);
7552   "
7553   [(set_attr "length" "12")
7554    (set_attr "type" "call")]
7557 (define_insn "*call_value_reg_thumb_v5"
7558   [(set (match_operand 0 "" "")
7559         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7560               (match_operand 2 "" "")))
7561    (use (match_operand 3 "" ""))
7562    (clobber (reg:SI LR_REGNUM))]
7563   "TARGET_THUMB && arm_arch5"
7564   "blx\\t%1"
7565   [(set_attr "length" "2")
7566    (set_attr "type" "call")]
7569 (define_insn "*call_value_reg_thumb"
7570   [(set (match_operand 0 "" "")
7571         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7572               (match_operand 2 "" "")))
7573    (use (match_operand 3 "" ""))
7574    (clobber (reg:SI LR_REGNUM))]
7575   "TARGET_THUMB && !arm_arch5"
7576   "*
7577   {
7578     if (!TARGET_CALLER_INTERWORKING)
7579       return thumb_call_via_reg (operands[1]);
7580     else if (operands[2] == const0_rtx)
7581       return \"bl\\t%__interwork_call_via_%1\";
7582     else if (frame_pointer_needed)
7583       return \"bl\\t%__interwork_r7_call_via_%1\";
7584     else
7585       return \"bl\\t%__interwork_r11_call_via_%1\";
7586   }"
7587   [(set_attr "type" "call")]
7590 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7591 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7593 (define_insn "*call_symbol"
7594   [(call (mem:SI (match_operand:SI 0 "" ""))
7595          (match_operand 1 "" ""))
7596    (use (match_operand 2 "" ""))
7597    (clobber (reg:SI LR_REGNUM))]
7598   "TARGET_ARM
7599    && (GET_CODE (operands[0]) == SYMBOL_REF)
7600    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7601   "*
7602   {
7603     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7604   }"
7605   [(set_attr "type" "call")]
7608 (define_insn "*call_value_symbol"
7609   [(set (match_operand 0 "" "")
7610         (call (mem:SI (match_operand:SI 1 "" ""))
7611         (match_operand:SI 2 "" "")))
7612    (use (match_operand 3 "" ""))
7613    (clobber (reg:SI LR_REGNUM))]
7614   "TARGET_ARM
7615    && (GET_CODE (operands[1]) == SYMBOL_REF)
7616    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7617   "*
7618   {
7619     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7620   }"
7621   [(set_attr "type" "call")]
7624 (define_insn "*call_insn"
7625   [(call (mem:SI (match_operand:SI 0 "" ""))
7626          (match_operand:SI 1 "" ""))
7627    (use (match_operand 2 "" ""))
7628    (clobber (reg:SI LR_REGNUM))]
7629   "TARGET_THUMB
7630    && GET_CODE (operands[0]) == SYMBOL_REF
7631    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7632   "bl\\t%a0"
7633   [(set_attr "length" "4")
7634    (set_attr "type" "call")]
7637 (define_insn "*call_value_insn"
7638   [(set (match_operand 0 "" "")
7639         (call (mem:SI (match_operand 1 "" ""))
7640               (match_operand 2 "" "")))
7641    (use (match_operand 3 "" ""))
7642    (clobber (reg:SI LR_REGNUM))]
7643   "TARGET_THUMB
7644    && GET_CODE (operands[1]) == SYMBOL_REF
7645    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7646   "bl\\t%a1"
7647   [(set_attr "length" "4")
7648    (set_attr "type" "call")]
7651 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7652 (define_expand "sibcall"
7653   [(parallel [(call (match_operand 0 "memory_operand" "")
7654                     (match_operand 1 "general_operand" ""))
7655               (return)
7656               (use (match_operand 2 "" ""))])]
7657   "TARGET_ARM"
7658   "
7659   {
7660     if (operands[2] == NULL_RTX)
7661       operands[2] = const0_rtx;
7662   }"
7665 (define_expand "sibcall_value"
7666   [(parallel [(set (match_operand 0 "" "")
7667                    (call (match_operand 1 "memory_operand" "")
7668                          (match_operand 2 "general_operand" "")))
7669               (return)
7670               (use (match_operand 3 "" ""))])]
7671   "TARGET_ARM"
7672   "
7673   {
7674     if (operands[3] == NULL_RTX)
7675       operands[3] = const0_rtx;
7676   }"
7679 (define_insn "*sibcall_insn"
7680  [(call (mem:SI (match_operand:SI 0 "" "X"))
7681         (match_operand 1 "" ""))
7682   (return)
7683   (use (match_operand 2 "" ""))]
7684   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7685   "*
7686   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7687   "
7688   [(set_attr "type" "call")]
7691 (define_insn "*sibcall_value_insn"
7692  [(set (match_operand 0 "" "")
7693        (call (mem:SI (match_operand:SI 1 "" "X"))
7694              (match_operand 2 "" "")))
7695   (return)
7696   (use (match_operand 3 "" ""))]
7697   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7698   "*
7699   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7700   "
7701   [(set_attr "type" "call")]
7704 ;; Often the return insn will be the same as loading from memory, so set attr
7705 (define_insn "return"
7706   [(return)]
7707   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7708   "*
7709   {
7710     if (arm_ccfsm_state == 2)
7711       {
7712         arm_ccfsm_state += 2;
7713         return \"\";
7714       }
7715     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7716   }"
7717   [(set_attr "type" "load1")
7718    (set_attr "length" "12")
7719    (set_attr "predicable" "yes")]
7722 (define_insn "*cond_return"
7723   [(set (pc)
7724         (if_then_else (match_operator 0 "arm_comparison_operator"
7725                        [(match_operand 1 "cc_register" "") (const_int 0)])
7726                       (return)
7727                       (pc)))]
7728   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7729   "*
7730   {
7731     if (arm_ccfsm_state == 2)
7732       {
7733         arm_ccfsm_state += 2;
7734         return \"\";
7735       }
7736     return output_return_instruction (operands[0], TRUE, FALSE);
7737   }"
7738   [(set_attr "conds" "use")
7739    (set_attr "length" "12")
7740    (set_attr "type" "load1")]
7743 (define_insn "*cond_return_inverted"
7744   [(set (pc)
7745         (if_then_else (match_operator 0 "arm_comparison_operator"
7746                        [(match_operand 1 "cc_register" "") (const_int 0)])
7747                       (pc)
7748                       (return)))]
7749   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7750   "*
7751   {
7752     if (arm_ccfsm_state == 2)
7753       {
7754         arm_ccfsm_state += 2;
7755         return \"\";
7756       }
7757     return output_return_instruction (operands[0], TRUE, TRUE);
7758   }"
7759   [(set_attr "conds" "use")
7760    (set_attr "length" "12")
7761    (set_attr "type" "load1")]
7764 ;; Generate a sequence of instructions to determine if the processor is
7765 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7766 ;; mask.
7768 (define_expand "return_addr_mask"
7769   [(set (match_dup 1)
7770       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7771                        (const_int 0)))
7772    (set (match_operand:SI 0 "s_register_operand" "")
7773       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7774                        (const_int -1)
7775                        (const_int 67108860)))] ; 0x03fffffc
7776   "TARGET_ARM"
7777   "
7778   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7779   ")
7781 (define_insn "*check_arch2"
7782   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7783       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7784                        (const_int 0)))]
7785   "TARGET_ARM"
7786   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7787   [(set_attr "length" "8")
7788    (set_attr "conds" "set")]
7791 ;; Call subroutine returning any type.
7793 (define_expand "untyped_call"
7794   [(parallel [(call (match_operand 0 "" "")
7795                     (const_int 0))
7796               (match_operand 1 "" "")
7797               (match_operand 2 "" "")])]
7798   "TARGET_EITHER"
7799   "
7800   {
7801     int i;
7802     rtx par = gen_rtx_PARALLEL (VOIDmode,
7803                                 rtvec_alloc (XVECLEN (operands[2], 0)));
7804     rtx addr = gen_reg_rtx (Pmode);
7805     rtx mem;
7806     int size = 0;
7808     emit_move_insn (addr, XEXP (operands[1], 0));
7809     mem = change_address (operands[1], BLKmode, addr);
7811     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7812       {
7813         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7815         /* Default code only uses r0 as a return value, but we could
7816            be using anything up to 4 registers.  */
7817         if (REGNO (src) == R0_REGNUM)
7818           src = gen_rtx_REG (TImode, R0_REGNUM);
7820         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7821                                                  GEN_INT (size));
7822         size += GET_MODE_SIZE (GET_MODE (src));
7823       }
7825     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7826                                     const0_rtx));
7828     size = 0;
7830     for (i = 0; i < XVECLEN (par, 0); i++)
7831       {
7832         HOST_WIDE_INT offset = 0;
7833         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7835         if (size != 0)
7836           emit_move_insn (addr, plus_constant (addr, size));
7838         mem = change_address (mem, GET_MODE (reg), NULL);
7839         if (REGNO (reg) == R0_REGNUM)
7840           {
7841             /* On thumb we have to use a write-back instruction.  */
7842             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7843                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7844             size = TARGET_ARM ? 16 : 0;
7845           }
7846         else
7847           {
7848             emit_move_insn (mem, reg);
7849             size = GET_MODE_SIZE (GET_MODE (reg));
7850           }
7851       }
7853     /* The optimizer does not know that the call sets the function value
7854        registers we stored in the result block.  We avoid problems by
7855        claiming that all hard registers are used and clobbered at this
7856        point.  */
7857     emit_insn (gen_blockage ());
7859     DONE;
7860   }"
7863 (define_expand "untyped_return"
7864   [(match_operand:BLK 0 "memory_operand" "")
7865    (match_operand 1 "" "")]
7866   "TARGET_EITHER"
7867   "
7868   {
7869     int i;
7870     rtx addr = gen_reg_rtx (Pmode);
7871     rtx mem;
7872     int size = 0;
7874     emit_move_insn (addr, XEXP (operands[0], 0));
7875     mem = change_address (operands[0], BLKmode, addr);
7877     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7878       {
7879         HOST_WIDE_INT offset = 0;
7880         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7882         if (size != 0)
7883           emit_move_insn (addr, plus_constant (addr, size));
7885         mem = change_address (mem, GET_MODE (reg), NULL);
7886         if (REGNO (reg) == R0_REGNUM)
7887           {
7888             /* On thumb we have to use a write-back instruction.  */
7889             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7890                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7891             size = TARGET_ARM ? 16 : 0;
7892           }
7893         else
7894           {
7895             emit_move_insn (reg, mem);
7896             size = GET_MODE_SIZE (GET_MODE (reg));
7897           }
7898       }
7900     /* Emit USE insns before the return.  */
7901     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7902       emit_insn (gen_rtx_USE (VOIDmode,
7903                               SET_DEST (XVECEXP (operands[1], 0, i))));
7905     /* Construct the return.  */
7906     expand_naked_return ();
7908     DONE;
7909   }"
7912 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7913 ;; all of memory.  This blocks insns from being moved across this point.
7915 (define_insn "blockage"
7916   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7917   "TARGET_EITHER"
7918   ""
7919   [(set_attr "length" "0")
7920    (set_attr "type" "block")]
7923 (define_expand "casesi"
7924   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7925    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7926    (match_operand:SI 2 "const_int_operand" "")  ; total range
7927    (match_operand:SI 3 "" "")                   ; table label
7928    (match_operand:SI 4 "" "")]                  ; Out of range label
7929   "TARGET_ARM"
7930   "
7931   {
7932     rtx reg;
7933     if (operands[1] != const0_rtx)
7934       {
7935         reg = gen_reg_rtx (SImode);
7937         emit_insn (gen_addsi3 (reg, operands[0],
7938                                GEN_INT (-INTVAL (operands[1]))));
7939         operands[0] = reg;
7940       }
7942     if (!const_ok_for_arm (INTVAL (operands[2])))
7943       operands[2] = force_reg (SImode, operands[2]);
7945     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7946                                          operands[4]));
7947     DONE;
7948   }"
7951 ;; The USE in this pattern is needed to tell flow analysis that this is
7952 ;; a CASESI insn.  It has no other purpose.
7953 (define_insn "casesi_internal"
7954   [(parallel [(set (pc)
7955                (if_then_else
7956                 (leu (match_operand:SI 0 "s_register_operand" "r")
7957                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7958                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7959                                  (label_ref (match_operand 2 "" ""))))
7960                 (label_ref (match_operand 3 "" ""))))
7961               (clobber (reg:CC CC_REGNUM))
7962               (use (label_ref (match_dup 2)))])]
7963   "TARGET_ARM"
7964   "*
7965     if (flag_pic)
7966       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7967     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7968   "
7969   [(set_attr "conds" "clob")
7970    (set_attr "length" "12")]
7973 (define_expand "indirect_jump"
7974   [(set (pc)
7975         (match_operand:SI 0 "s_register_operand" ""))]
7976   "TARGET_EITHER"
7977   ""
7980 ;; NB Never uses BX.
7981 (define_insn "*arm_indirect_jump"
7982   [(set (pc)
7983         (match_operand:SI 0 "s_register_operand" "r"))]
7984   "TARGET_ARM"
7985   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7986   [(set_attr "predicable" "yes")]
7989 (define_insn "*load_indirect_jump"
7990   [(set (pc)
7991         (match_operand:SI 0 "memory_operand" "m"))]
7992   "TARGET_ARM"
7993   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7994   [(set_attr "type" "load1")
7995    (set_attr "pool_range" "4096")
7996    (set_attr "neg_pool_range" "4084")
7997    (set_attr "predicable" "yes")]
8000 ;; NB Never uses BX.
8001 (define_insn "*thumb_indirect_jump"
8002   [(set (pc)
8003         (match_operand:SI 0 "register_operand" "l*r"))]
8004   "TARGET_THUMB"
8005   "mov\\tpc, %0"
8006   [(set_attr "conds" "clob")
8007    (set_attr "length" "2")]
8011 ;; Misc insns
8013 (define_insn "nop"
8014   [(const_int 0)]
8015   "TARGET_EITHER"
8016   "*
8017   if (TARGET_ARM)
8018     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8019   return  \"mov\\tr8, r8\";
8020   "
8021   [(set (attr "length")
8022         (if_then_else (eq_attr "is_thumb" "yes")
8023                       (const_int 2)
8024                       (const_int 4)))]
8028 ;; Patterns to allow combination of arithmetic, cond code and shifts
8030 (define_insn "*arith_shiftsi"
8031   [(set (match_operand:SI 0 "s_register_operand" "=r")
8032         (match_operator:SI 1 "shiftable_operator"
8033           [(match_operator:SI 3 "shift_operator"
8034              [(match_operand:SI 4 "s_register_operand" "r")
8035               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8036            (match_operand:SI 2 "s_register_operand" "r")]))]
8037   "TARGET_ARM"
8038   "%i1%?\\t%0, %2, %4%S3"
8039   [(set_attr "predicable" "yes")
8040    (set_attr "shift" "4")
8041    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8042                       (const_string "alu_shift")
8043                       (const_string "alu_shift_reg")))]
8046 (define_split
8047   [(set (match_operand:SI 0 "s_register_operand" "")
8048         (match_operator:SI 1 "shiftable_operator"
8049          [(match_operator:SI 2 "shiftable_operator"
8050            [(match_operator:SI 3 "shift_operator"
8051              [(match_operand:SI 4 "s_register_operand" "")
8052               (match_operand:SI 5 "reg_or_int_operand" "")])
8053             (match_operand:SI 6 "s_register_operand" "")])
8054           (match_operand:SI 7 "arm_rhs_operand" "")]))
8055    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8056   "TARGET_ARM"
8057   [(set (match_dup 8)
8058         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8059                          (match_dup 6)]))
8060    (set (match_dup 0)
8061         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8062   "")
8064 (define_insn "*arith_shiftsi_compare0"
8065   [(set (reg:CC_NOOV CC_REGNUM)
8066         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8067                           [(match_operator:SI 3 "shift_operator"
8068                             [(match_operand:SI 4 "s_register_operand" "r")
8069                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8070                            (match_operand:SI 2 "s_register_operand" "r")])
8071                          (const_int 0)))
8072    (set (match_operand:SI 0 "s_register_operand" "=r")
8073         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8074                          (match_dup 2)]))]
8075   "TARGET_ARM"
8076   "%i1%?s\\t%0, %2, %4%S3"
8077   [(set_attr "conds" "set")
8078    (set_attr "shift" "4")
8079    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8080                       (const_string "alu_shift")
8081                       (const_string "alu_shift_reg")))]
8084 (define_insn "*arith_shiftsi_compare0_scratch"
8085   [(set (reg:CC_NOOV CC_REGNUM)
8086         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8087                           [(match_operator:SI 3 "shift_operator"
8088                             [(match_operand:SI 4 "s_register_operand" "r")
8089                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8090                            (match_operand:SI 2 "s_register_operand" "r")])
8091                          (const_int 0)))
8092    (clobber (match_scratch:SI 0 "=r"))]
8093   "TARGET_ARM"
8094   "%i1%?s\\t%0, %2, %4%S3"
8095   [(set_attr "conds" "set")
8096    (set_attr "shift" "4")
8097    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8098                       (const_string "alu_shift")
8099                       (const_string "alu_shift_reg")))]
8102 (define_insn "*sub_shiftsi"
8103   [(set (match_operand:SI 0 "s_register_operand" "=r")
8104         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8105                   (match_operator:SI 2 "shift_operator"
8106                    [(match_operand:SI 3 "s_register_operand" "r")
8107                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8108   "TARGET_ARM"
8109   "sub%?\\t%0, %1, %3%S2"
8110   [(set_attr "predicable" "yes")
8111    (set_attr "shift" "3")
8112    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8113                       (const_string "alu_shift")
8114                       (const_string "alu_shift_reg")))]
8117 (define_insn "*sub_shiftsi_compare0"
8118   [(set (reg:CC_NOOV CC_REGNUM)
8119         (compare:CC_NOOV
8120          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8121                    (match_operator:SI 2 "shift_operator"
8122                     [(match_operand:SI 3 "s_register_operand" "r")
8123                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8124          (const_int 0)))
8125    (set (match_operand:SI 0 "s_register_operand" "=r")
8126         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8127                                                  (match_dup 4)])))]
8128   "TARGET_ARM"
8129   "sub%?s\\t%0, %1, %3%S2"
8130   [(set_attr "conds" "set")
8131    (set_attr "shift" "3")
8132    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8133                       (const_string "alu_shift")
8134                       (const_string "alu_shift_reg")))]
8137 (define_insn "*sub_shiftsi_compare0_scratch"
8138   [(set (reg:CC_NOOV CC_REGNUM)
8139         (compare:CC_NOOV
8140          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8141                    (match_operator:SI 2 "shift_operator"
8142                     [(match_operand:SI 3 "s_register_operand" "r")
8143                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8144          (const_int 0)))
8145    (clobber (match_scratch:SI 0 "=r"))]
8146   "TARGET_ARM"
8147   "sub%?s\\t%0, %1, %3%S2"
8148   [(set_attr "conds" "set")
8149    (set_attr "shift" "3")
8150    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8151                       (const_string "alu_shift")
8152                       (const_string "alu_shift_reg")))]
8157 (define_insn "*and_scc"
8158   [(set (match_operand:SI 0 "s_register_operand" "=r")
8159         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8160                  [(match_operand 3 "cc_register" "") (const_int 0)])
8161                 (match_operand:SI 2 "s_register_operand" "r")))]
8162   "TARGET_ARM"
8163   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8164   [(set_attr "conds" "use")
8165    (set_attr "length" "8")]
8168 (define_insn "*ior_scc"
8169   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8170         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8171                  [(match_operand 3 "cc_register" "") (const_int 0)])
8172                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8173   "TARGET_ARM"
8174   "@
8175    orr%d2\\t%0, %1, #1
8176    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8177   [(set_attr "conds" "use")
8178    (set_attr "length" "4,8")]
8181 (define_insn "*compare_scc"
8182   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8183         (match_operator:SI 1 "arm_comparison_operator"
8184          [(match_operand:SI 2 "s_register_operand" "r,r")
8185           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8186    (clobber (reg:CC CC_REGNUM))]
8187   "TARGET_ARM"
8188   "*
8189     if (operands[3] == const0_rtx)
8190       {
8191         if (GET_CODE (operands[1]) == LT)
8192           return \"mov\\t%0, %2, lsr #31\";
8194         if (GET_CODE (operands[1]) == GE)
8195           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8197         if (GET_CODE (operands[1]) == EQ)
8198           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8199       }
8201     if (GET_CODE (operands[1]) == NE)
8202       {
8203         if (which_alternative == 1)
8204           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8205         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8206       }
8207     if (which_alternative == 1)
8208       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8209     else
8210       output_asm_insn (\"cmp\\t%2, %3\", operands);
8211     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8212   "
8213   [(set_attr "conds" "clob")
8214    (set_attr "length" "12")]
8217 (define_insn "*cond_move"
8218   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8219         (if_then_else:SI (match_operator 3 "equality_operator"
8220                           [(match_operator 4 "arm_comparison_operator"
8221                             [(match_operand 5 "cc_register" "") (const_int 0)])
8222                            (const_int 0)])
8223                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8224                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8225   "TARGET_ARM"
8226   "*
8227     if (GET_CODE (operands[3]) == NE)
8228       {
8229         if (which_alternative != 1)
8230           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8231         if (which_alternative != 0)
8232           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8233         return \"\";
8234       }
8235     if (which_alternative != 0)
8236       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8237     if (which_alternative != 1)
8238       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8239     return \"\";
8240   "
8241   [(set_attr "conds" "use")
8242    (set_attr "length" "4,4,8")]
8245 (define_insn "*cond_arith"
8246   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8247         (match_operator:SI 5 "shiftable_operator" 
8248          [(match_operator:SI 4 "arm_comparison_operator"
8249            [(match_operand:SI 2 "s_register_operand" "r,r")
8250             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8251           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8252    (clobber (reg:CC CC_REGNUM))]
8253   "TARGET_ARM"
8254   "*
8255     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8256       return \"%i5\\t%0, %1, %2, lsr #31\";
8258     output_asm_insn (\"cmp\\t%2, %3\", operands);
8259     if (GET_CODE (operands[5]) == AND)
8260       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8261     else if (GET_CODE (operands[5]) == MINUS)
8262       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8263     else if (which_alternative != 0)
8264       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8265     return \"%i5%d4\\t%0, %1, #1\";
8266   "
8267   [(set_attr "conds" "clob")
8268    (set_attr "length" "12")]
8271 (define_insn "*cond_sub"
8272   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8273         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8274                   (match_operator:SI 4 "arm_comparison_operator"
8275                    [(match_operand:SI 2 "s_register_operand" "r,r")
8276                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8277    (clobber (reg:CC CC_REGNUM))]
8278   "TARGET_ARM"
8279   "*
8280     output_asm_insn (\"cmp\\t%2, %3\", operands);
8281     if (which_alternative != 0)
8282       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8283     return \"sub%d4\\t%0, %1, #1\";
8284   "
8285   [(set_attr "conds" "clob")
8286    (set_attr "length" "8,12")]
8289 (define_insn "*cmp_ite0"
8290   [(set (match_operand 6 "dominant_cc_register" "")
8291         (compare
8292          (if_then_else:SI
8293           (match_operator 4 "arm_comparison_operator"
8294            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8295             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8296           (match_operator:SI 5 "arm_comparison_operator"
8297            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8298             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8299           (const_int 0))
8300          (const_int 0)))]
8301   "TARGET_ARM"
8302   "*
8303   {
8304     static const char * const opcodes[4][2] =
8305     {
8306       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8307        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8308       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8309        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8310       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8311        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8312       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8313        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8314     };
8315     int swap =
8316       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8318     return opcodes[which_alternative][swap];
8319   }"
8320   [(set_attr "conds" "set")
8321    (set_attr "length" "8")]
8324 (define_insn "*cmp_ite1"
8325   [(set (match_operand 6 "dominant_cc_register" "")
8326         (compare
8327          (if_then_else:SI
8328           (match_operator 4 "arm_comparison_operator"
8329            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8330             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8331           (match_operator:SI 5 "arm_comparison_operator"
8332            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8333             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8334           (const_int 1))
8335          (const_int 0)))]
8336   "TARGET_ARM"
8337   "*
8338   {
8339     static const char * const opcodes[4][2] =
8340     {
8341       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8342        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8343       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8344        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8345       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8346        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8347       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8348        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8349     };
8350     int swap =
8351       comparison_dominates_p (GET_CODE (operands[5]),
8352                               reverse_condition (GET_CODE (operands[4])));
8354     return opcodes[which_alternative][swap];
8355   }"
8356   [(set_attr "conds" "set")
8357    (set_attr "length" "8")]
8360 (define_insn "*cmp_and"
8361   [(set (match_operand 6 "dominant_cc_register" "")
8362         (compare
8363          (and:SI
8364           (match_operator 4 "arm_comparison_operator"
8365            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8366             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8367           (match_operator:SI 5 "arm_comparison_operator"
8368            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8369             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8370          (const_int 0)))]
8371   "TARGET_ARM"
8372   "*
8373   {
8374     static const char *const opcodes[4][2] =
8375     {
8376       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8377        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8378       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8379        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8380       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8381        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8382       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8383        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8384     };
8385     int swap =
8386       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8388     return opcodes[which_alternative][swap];
8389   }"
8390   [(set_attr "conds" "set")
8391    (set_attr "predicable" "no")
8392    (set_attr "length" "8")]
8395 (define_insn "*cmp_ior"
8396   [(set (match_operand 6 "dominant_cc_register" "")
8397         (compare
8398          (ior:SI
8399           (match_operator 4 "arm_comparison_operator"
8400            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8401             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8402           (match_operator:SI 5 "arm_comparison_operator"
8403            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8404             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8405          (const_int 0)))]
8406   "TARGET_ARM"
8407   "*
8409   static const char *const opcodes[4][2] =
8410   {
8411     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8412      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8413     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8414      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8415     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8416      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8417     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8418      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8419   };
8420   int swap =
8421     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8423   return opcodes[which_alternative][swap];
8426   [(set_attr "conds" "set")
8427    (set_attr "length" "8")]
8430 (define_insn_and_split "*ior_scc_scc"
8431   [(set (match_operand:SI 0 "s_register_operand" "=r")
8432         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8433                  [(match_operand:SI 1 "s_register_operand" "r")
8434                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8435                 (match_operator:SI 6 "arm_comparison_operator"
8436                  [(match_operand:SI 4 "s_register_operand" "r")
8437                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8438    (clobber (reg:CC CC_REGNUM))]
8439   "TARGET_ARM
8440    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8441        != CCmode)"
8442   "#"
8443   "TARGET_ARM && reload_completed"
8444   [(set (match_dup 7)
8445         (compare
8446          (ior:SI
8447           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8448           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8449          (const_int 0)))
8450    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8451   "operands[7]
8452      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8453                                                   DOM_CC_X_OR_Y),
8454                     CC_REGNUM);"
8455   [(set_attr "conds" "clob")
8456    (set_attr "length" "16")])
8458 ; If the above pattern is followed by a CMP insn, then the compare is 
8459 ; redundant, since we can rework the conditional instruction that follows.
8460 (define_insn_and_split "*ior_scc_scc_cmp"
8461   [(set (match_operand 0 "dominant_cc_register" "")
8462         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8463                           [(match_operand:SI 1 "s_register_operand" "r")
8464                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8465                          (match_operator:SI 6 "arm_comparison_operator"
8466                           [(match_operand:SI 4 "s_register_operand" "r")
8467                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8468                  (const_int 0)))
8469    (set (match_operand:SI 7 "s_register_operand" "=r")
8470         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8471                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8472   "TARGET_ARM"
8473   "#"
8474   "TARGET_ARM && reload_completed"
8475   [(set (match_dup 0)
8476         (compare
8477          (ior:SI
8478           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8479           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8480          (const_int 0)))
8481    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8482   ""
8483   [(set_attr "conds" "set")
8484    (set_attr "length" "16")])
8486 (define_insn_and_split "*and_scc_scc"
8487   [(set (match_operand:SI 0 "s_register_operand" "=r")
8488         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8489                  [(match_operand:SI 1 "s_register_operand" "r")
8490                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8491                 (match_operator:SI 6 "arm_comparison_operator"
8492                  [(match_operand:SI 4 "s_register_operand" "r")
8493                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8494    (clobber (reg:CC CC_REGNUM))]
8495   "TARGET_ARM
8496    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8497        != CCmode)"
8498   "#"
8499   "TARGET_ARM && reload_completed
8500    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8501        != CCmode)"
8502   [(set (match_dup 7)
8503         (compare
8504          (and:SI
8505           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8506           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8507          (const_int 0)))
8508    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8509   "operands[7]
8510      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8511                                                   DOM_CC_X_AND_Y),
8512                     CC_REGNUM);"
8513   [(set_attr "conds" "clob")
8514    (set_attr "length" "16")])
8516 ; If the above pattern is followed by a CMP insn, then the compare is 
8517 ; redundant, since we can rework the conditional instruction that follows.
8518 (define_insn_and_split "*and_scc_scc_cmp"
8519   [(set (match_operand 0 "dominant_cc_register" "")
8520         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8521                           [(match_operand:SI 1 "s_register_operand" "r")
8522                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8523                          (match_operator:SI 6 "arm_comparison_operator"
8524                           [(match_operand:SI 4 "s_register_operand" "r")
8525                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8526                  (const_int 0)))
8527    (set (match_operand:SI 7 "s_register_operand" "=r")
8528         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8529                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8530   "TARGET_ARM"
8531   "#"
8532   "TARGET_ARM && reload_completed"
8533   [(set (match_dup 0)
8534         (compare
8535          (and:SI
8536           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8537           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8538          (const_int 0)))
8539    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8540   ""
8541   [(set_attr "conds" "set")
8542    (set_attr "length" "16")])
8544 ;; If there is no dominance in the comparison, then we can still save an
8545 ;; instruction in the AND case, since we can know that the second compare
8546 ;; need only zero the value if false (if true, then the value is already
8547 ;; correct).
8548 (define_insn_and_split "*and_scc_scc_nodom"
8549   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8550         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8551                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8552                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8553                 (match_operator:SI 6 "arm_comparison_operator"
8554                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8555                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8556    (clobber (reg:CC CC_REGNUM))]
8557   "TARGET_ARM
8558    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8559        == CCmode)"
8560   "#"
8561   "TARGET_ARM && reload_completed"
8562   [(parallel [(set (match_dup 0)
8563                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8564               (clobber (reg:CC CC_REGNUM))])
8565    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8566    (set (match_dup 0)
8567         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8568                          (match_dup 0)
8569                          (const_int 0)))]
8570   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8571                                               operands[4], operands[5]),
8572                               CC_REGNUM);
8573    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8574                                   operands[5]);"
8575   [(set_attr "conds" "clob")
8576    (set_attr "length" "20")])
8578 (define_split
8579   [(set (reg:CC_NOOV CC_REGNUM)
8580         (compare:CC_NOOV (ior:SI
8581                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8582                                   (const_int 1))
8583                           (match_operator:SI 1 "comparison_operator"
8584                            [(match_operand:SI 2 "s_register_operand" "")
8585                             (match_operand:SI 3 "arm_add_operand" "")]))
8586                          (const_int 0)))
8587    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8588   "TARGET_ARM"
8589   [(set (match_dup 4)
8590         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8591                 (match_dup 0)))
8592    (set (reg:CC_NOOV CC_REGNUM)
8593         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8594                          (const_int 0)))]
8595   "")
8597 (define_split
8598   [(set (reg:CC_NOOV CC_REGNUM)
8599         (compare:CC_NOOV (ior:SI
8600                           (match_operator:SI 1 "comparison_operator"
8601                            [(match_operand:SI 2 "s_register_operand" "")
8602                             (match_operand:SI 3 "arm_add_operand" "")])
8603                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8604                                   (const_int 1)))
8605                          (const_int 0)))
8606    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8607   "TARGET_ARM"
8608   [(set (match_dup 4)
8609         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8610                 (match_dup 0)))
8611    (set (reg:CC_NOOV CC_REGNUM)
8612         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8613                          (const_int 0)))]
8614   "")
8616 (define_insn "*negscc"
8617   [(set (match_operand:SI 0 "s_register_operand" "=r")
8618         (neg:SI (match_operator 3 "arm_comparison_operator"
8619                  [(match_operand:SI 1 "s_register_operand" "r")
8620                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8621    (clobber (reg:CC CC_REGNUM))]
8622   "TARGET_ARM"
8623   "*
8624   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8625     return \"mov\\t%0, %1, asr #31\";
8627   if (GET_CODE (operands[3]) == NE)
8628     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8630   if (GET_CODE (operands[3]) == GT)
8631     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8633   output_asm_insn (\"cmp\\t%1, %2\", operands);
8634   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8635   return \"mvn%d3\\t%0, #0\";
8636   "
8637   [(set_attr "conds" "clob")
8638    (set_attr "length" "12")]
8641 (define_insn "movcond"
8642   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8643         (if_then_else:SI
8644          (match_operator 5 "arm_comparison_operator"
8645           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8646            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8647          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8648          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8649    (clobber (reg:CC CC_REGNUM))]
8650   "TARGET_ARM"
8651   "*
8652   if (GET_CODE (operands[5]) == LT
8653       && (operands[4] == const0_rtx))
8654     {
8655       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8656         {
8657           if (operands[2] == const0_rtx)
8658             return \"and\\t%0, %1, %3, asr #31\";
8659           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8660         }
8661       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8662         {
8663           if (operands[1] == const0_rtx)
8664             return \"bic\\t%0, %2, %3, asr #31\";
8665           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8666         }
8667       /* The only case that falls through to here is when both ops 1 & 2
8668          are constants.  */
8669     }
8671   if (GET_CODE (operands[5]) == GE
8672       && (operands[4] == const0_rtx))
8673     {
8674       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8675         {
8676           if (operands[2] == const0_rtx)
8677             return \"bic\\t%0, %1, %3, asr #31\";
8678           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8679         }
8680       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8681         {
8682           if (operands[1] == const0_rtx)
8683             return \"and\\t%0, %2, %3, asr #31\";
8684           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8685         }
8686       /* The only case that falls through to here is when both ops 1 & 2
8687          are constants.  */
8688     }
8689   if (GET_CODE (operands[4]) == CONST_INT
8690       && !const_ok_for_arm (INTVAL (operands[4])))
8691     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8692   else
8693     output_asm_insn (\"cmp\\t%3, %4\", operands);
8694   if (which_alternative != 0)
8695     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8696   if (which_alternative != 1)
8697     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8698   return \"\";
8699   "
8700   [(set_attr "conds" "clob")
8701    (set_attr "length" "8,8,12")]
8704 (define_insn "*ifcompare_plus_move"
8705   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8706         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8707                           [(match_operand:SI 4 "s_register_operand" "r,r")
8708                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8709                          (plus:SI
8710                           (match_operand:SI 2 "s_register_operand" "r,r")
8711                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8712                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8713    (clobber (reg:CC CC_REGNUM))]
8714   "TARGET_ARM"
8715   "#"
8716   [(set_attr "conds" "clob")
8717    (set_attr "length" "8,12")]
8720 (define_insn "*if_plus_move"
8721   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8722         (if_then_else:SI
8723          (match_operator 4 "arm_comparison_operator"
8724           [(match_operand 5 "cc_register" "") (const_int 0)])
8725          (plus:SI
8726           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8727           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8728          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8729   "TARGET_ARM"
8730   "@
8731    add%d4\\t%0, %2, %3
8732    sub%d4\\t%0, %2, #%n3
8733    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8734    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8735   [(set_attr "conds" "use")
8736    (set_attr "length" "4,4,8,8")
8737    (set_attr "type" "*,*,*,*")]
8740 (define_insn "*ifcompare_move_plus"
8741   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8742         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8743                           [(match_operand:SI 4 "s_register_operand" "r,r")
8744                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8745                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8746                          (plus:SI
8747                           (match_operand:SI 2 "s_register_operand" "r,r")
8748                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8749    (clobber (reg:CC CC_REGNUM))]
8750   "TARGET_ARM"
8751   "#"
8752   [(set_attr "conds" "clob")
8753    (set_attr "length" "8,12")]
8756 (define_insn "*if_move_plus"
8757   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8758         (if_then_else:SI
8759          (match_operator 4 "arm_comparison_operator"
8760           [(match_operand 5 "cc_register" "") (const_int 0)])
8761          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8762          (plus:SI
8763           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8764           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8765   "TARGET_ARM"
8766   "@
8767    add%D4\\t%0, %2, %3
8768    sub%D4\\t%0, %2, #%n3
8769    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8770    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8771   [(set_attr "conds" "use")
8772    (set_attr "length" "4,4,8,8")
8773    (set_attr "type" "*,*,*,*")]
8776 (define_insn "*ifcompare_arith_arith"
8777   [(set (match_operand:SI 0 "s_register_operand" "=r")
8778         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8779                           [(match_operand:SI 5 "s_register_operand" "r")
8780                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8781                          (match_operator:SI 8 "shiftable_operator"
8782                           [(match_operand:SI 1 "s_register_operand" "r")
8783                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8784                          (match_operator:SI 7 "shiftable_operator"
8785                           [(match_operand:SI 3 "s_register_operand" "r")
8786                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8787    (clobber (reg:CC CC_REGNUM))]
8788   "TARGET_ARM"
8789   "#"
8790   [(set_attr "conds" "clob")
8791    (set_attr "length" "12")]
8794 (define_insn "*if_arith_arith"
8795   [(set (match_operand:SI 0 "s_register_operand" "=r")
8796         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8797                           [(match_operand 8 "cc_register" "") (const_int 0)])
8798                          (match_operator:SI 6 "shiftable_operator"
8799                           [(match_operand:SI 1 "s_register_operand" "r")
8800                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8801                          (match_operator:SI 7 "shiftable_operator"
8802                           [(match_operand:SI 3 "s_register_operand" "r")
8803                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8804   "TARGET_ARM"
8805   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8806   [(set_attr "conds" "use")
8807    (set_attr "length" "8")]
8810 (define_insn "*ifcompare_arith_move"
8811   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8812         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8813                           [(match_operand:SI 2 "s_register_operand" "r,r")
8814                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8815                          (match_operator:SI 7 "shiftable_operator"
8816                           [(match_operand:SI 4 "s_register_operand" "r,r")
8817                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8818                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8819    (clobber (reg:CC CC_REGNUM))]
8820   "TARGET_ARM"
8821   "*
8822   /* If we have an operation where (op x 0) is the identity operation and
8823      the conditional operator is LT or GE and we are comparing against zero and
8824      everything is in registers then we can do this in two instructions.  */
8825   if (operands[3] == const0_rtx
8826       && GET_CODE (operands[7]) != AND
8827       && GET_CODE (operands[5]) == REG
8828       && GET_CODE (operands[1]) == REG 
8829       && REGNO (operands[1]) == REGNO (operands[4])
8830       && REGNO (operands[4]) != REGNO (operands[0]))
8831     {
8832       if (GET_CODE (operands[6]) == LT)
8833         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8834       else if (GET_CODE (operands[6]) == GE)
8835         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8836     }
8837   if (GET_CODE (operands[3]) == CONST_INT
8838       && !const_ok_for_arm (INTVAL (operands[3])))
8839     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8840   else
8841     output_asm_insn (\"cmp\\t%2, %3\", operands);
8842   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8843   if (which_alternative != 0)
8844     return \"mov%D6\\t%0, %1\";
8845   return \"\";
8846   "
8847   [(set_attr "conds" "clob")
8848    (set_attr "length" "8,12")]
8851 (define_insn "*if_arith_move"
8852   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8853         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8854                           [(match_operand 6 "cc_register" "") (const_int 0)])
8855                          (match_operator:SI 5 "shiftable_operator"
8856                           [(match_operand:SI 2 "s_register_operand" "r,r")
8857                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8858                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8859   "TARGET_ARM"
8860   "@
8861    %I5%d4\\t%0, %2, %3
8862    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8863   [(set_attr "conds" "use")
8864    (set_attr "length" "4,8")
8865    (set_attr "type" "*,*")]
8868 (define_insn "*ifcompare_move_arith"
8869   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8870         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8871                           [(match_operand:SI 4 "s_register_operand" "r,r")
8872                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8873                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8874                          (match_operator:SI 7 "shiftable_operator"
8875                           [(match_operand:SI 2 "s_register_operand" "r,r")
8876                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8877    (clobber (reg:CC CC_REGNUM))]
8878   "TARGET_ARM"
8879   "*
8880   /* If we have an operation where (op x 0) is the identity operation and
8881      the conditional operator is LT or GE and we are comparing against zero and
8882      everything is in registers then we can do this in two instructions */
8883   if (operands[5] == const0_rtx
8884       && GET_CODE (operands[7]) != AND
8885       && GET_CODE (operands[3]) == REG
8886       && GET_CODE (operands[1]) == REG 
8887       && REGNO (operands[1]) == REGNO (operands[2])
8888       && REGNO (operands[2]) != REGNO (operands[0]))
8889     {
8890       if (GET_CODE (operands[6]) == GE)
8891         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8892       else if (GET_CODE (operands[6]) == LT)
8893         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8894     }
8896   if (GET_CODE (operands[5]) == CONST_INT
8897       && !const_ok_for_arm (INTVAL (operands[5])))
8898     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8899   else
8900     output_asm_insn (\"cmp\\t%4, %5\", operands);
8902   if (which_alternative != 0)
8903     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8904   return \"%I7%D6\\t%0, %2, %3\";
8905   "
8906   [(set_attr "conds" "clob")
8907    (set_attr "length" "8,12")]
8910 (define_insn "*if_move_arith"
8911   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8912         (if_then_else:SI
8913          (match_operator 4 "arm_comparison_operator"
8914           [(match_operand 6 "cc_register" "") (const_int 0)])
8915          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8916          (match_operator:SI 5 "shiftable_operator"
8917           [(match_operand:SI 2 "s_register_operand" "r,r")
8918            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8919   "TARGET_ARM"
8920   "@
8921    %I5%D4\\t%0, %2, %3
8922    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8923   [(set_attr "conds" "use")
8924    (set_attr "length" "4,8")
8925    (set_attr "type" "*,*")]
8928 (define_insn "*ifcompare_move_not"
8929   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8930         (if_then_else:SI
8931          (match_operator 5 "arm_comparison_operator"
8932           [(match_operand:SI 3 "s_register_operand" "r,r")
8933            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8934          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8935          (not:SI
8936           (match_operand:SI 2 "s_register_operand" "r,r"))))
8937    (clobber (reg:CC CC_REGNUM))]
8938   "TARGET_ARM"
8939   "#"
8940   [(set_attr "conds" "clob")
8941    (set_attr "length" "8,12")]
8944 (define_insn "*if_move_not"
8945   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8946         (if_then_else:SI
8947          (match_operator 4 "arm_comparison_operator"
8948           [(match_operand 3 "cc_register" "") (const_int 0)])
8949          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8950          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8951   "TARGET_ARM"
8952   "@
8953    mvn%D4\\t%0, %2
8954    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8955    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8956   [(set_attr "conds" "use")
8957    (set_attr "length" "4,8,8")]
8960 (define_insn "*ifcompare_not_move"
8961   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8962         (if_then_else:SI 
8963          (match_operator 5 "arm_comparison_operator"
8964           [(match_operand:SI 3 "s_register_operand" "r,r")
8965            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8966          (not:SI
8967           (match_operand:SI 2 "s_register_operand" "r,r"))
8968          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8969    (clobber (reg:CC CC_REGNUM))]
8970   "TARGET_ARM"
8971   "#"
8972   [(set_attr "conds" "clob")
8973    (set_attr "length" "8,12")]
8976 (define_insn "*if_not_move"
8977   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8978         (if_then_else:SI
8979          (match_operator 4 "arm_comparison_operator"
8980           [(match_operand 3 "cc_register" "") (const_int 0)])
8981          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8982          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8983   "TARGET_ARM"
8984   "@
8985    mvn%d4\\t%0, %2
8986    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8987    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8988   [(set_attr "conds" "use")
8989    (set_attr "length" "4,8,8")]
8992 (define_insn "*ifcompare_shift_move"
8993   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8994         (if_then_else:SI
8995          (match_operator 6 "arm_comparison_operator"
8996           [(match_operand:SI 4 "s_register_operand" "r,r")
8997            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8998          (match_operator:SI 7 "shift_operator"
8999           [(match_operand:SI 2 "s_register_operand" "r,r")
9000            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9001          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9002    (clobber (reg:CC CC_REGNUM))]
9003   "TARGET_ARM"
9004   "#"
9005   [(set_attr "conds" "clob")
9006    (set_attr "length" "8,12")]
9009 (define_insn "*if_shift_move"
9010   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9011         (if_then_else:SI
9012          (match_operator 5 "arm_comparison_operator"
9013           [(match_operand 6 "cc_register" "") (const_int 0)])
9014          (match_operator:SI 4 "shift_operator"
9015           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9016            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9017          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9018   "TARGET_ARM"
9019   "@
9020    mov%d5\\t%0, %2%S4
9021    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9022    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9023   [(set_attr "conds" "use")
9024    (set_attr "shift" "2")
9025    (set_attr "length" "4,8,8")
9026    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9027                       (const_string "alu_shift")
9028                       (const_string "alu_shift_reg")))]
9031 (define_insn "*ifcompare_move_shift"
9032   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9033         (if_then_else:SI
9034          (match_operator 6 "arm_comparison_operator"
9035           [(match_operand:SI 4 "s_register_operand" "r,r")
9036            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9037          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9038          (match_operator:SI 7 "shift_operator"
9039           [(match_operand:SI 2 "s_register_operand" "r,r")
9040            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9041    (clobber (reg:CC CC_REGNUM))]
9042   "TARGET_ARM"
9043   "#"
9044   [(set_attr "conds" "clob")
9045    (set_attr "length" "8,12")]
9048 (define_insn "*if_move_shift"
9049   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9050         (if_then_else:SI
9051          (match_operator 5 "arm_comparison_operator"
9052           [(match_operand 6 "cc_register" "") (const_int 0)])
9053          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9054          (match_operator:SI 4 "shift_operator"
9055           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9056            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9057   "TARGET_ARM"
9058   "@
9059    mov%D5\\t%0, %2%S4
9060    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9061    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9062   [(set_attr "conds" "use")
9063    (set_attr "shift" "2")
9064    (set_attr "length" "4,8,8")
9065    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9066                       (const_string "alu_shift")
9067                       (const_string "alu_shift_reg")))]
9070 (define_insn "*ifcompare_shift_shift"
9071   [(set (match_operand:SI 0 "s_register_operand" "=r")
9072         (if_then_else:SI
9073          (match_operator 7 "arm_comparison_operator"
9074           [(match_operand:SI 5 "s_register_operand" "r")
9075            (match_operand:SI 6 "arm_add_operand" "rIL")])
9076          (match_operator:SI 8 "shift_operator"
9077           [(match_operand:SI 1 "s_register_operand" "r")
9078            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9079          (match_operator:SI 9 "shift_operator"
9080           [(match_operand:SI 3 "s_register_operand" "r")
9081            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9082    (clobber (reg:CC CC_REGNUM))]
9083   "TARGET_ARM"
9084   "#"
9085   [(set_attr "conds" "clob")
9086    (set_attr "length" "12")]
9089 (define_insn "*if_shift_shift"
9090   [(set (match_operand:SI 0 "s_register_operand" "=r")
9091         (if_then_else:SI
9092          (match_operator 5 "arm_comparison_operator"
9093           [(match_operand 8 "cc_register" "") (const_int 0)])
9094          (match_operator:SI 6 "shift_operator"
9095           [(match_operand:SI 1 "s_register_operand" "r")
9096            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9097          (match_operator:SI 7 "shift_operator"
9098           [(match_operand:SI 3 "s_register_operand" "r")
9099            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9100   "TARGET_ARM"
9101   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9102   [(set_attr "conds" "use")
9103    (set_attr "shift" "1")
9104    (set_attr "length" "8")
9105    (set (attr "type") (if_then_else
9106                         (and (match_operand 2 "const_int_operand" "")
9107                              (match_operand 4 "const_int_operand" ""))
9108                       (const_string "alu_shift")
9109                       (const_string "alu_shift_reg")))]
9112 (define_insn "*ifcompare_not_arith"
9113   [(set (match_operand:SI 0 "s_register_operand" "=r")
9114         (if_then_else:SI
9115          (match_operator 6 "arm_comparison_operator"
9116           [(match_operand:SI 4 "s_register_operand" "r")
9117            (match_operand:SI 5 "arm_add_operand" "rIL")])
9118          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9119          (match_operator:SI 7 "shiftable_operator"
9120           [(match_operand:SI 2 "s_register_operand" "r")
9121            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9122    (clobber (reg:CC CC_REGNUM))]
9123   "TARGET_ARM"
9124   "#"
9125   [(set_attr "conds" "clob")
9126    (set_attr "length" "12")]
9129 (define_insn "*if_not_arith"
9130   [(set (match_operand:SI 0 "s_register_operand" "=r")
9131         (if_then_else:SI
9132          (match_operator 5 "arm_comparison_operator"
9133           [(match_operand 4 "cc_register" "") (const_int 0)])
9134          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9135          (match_operator:SI 6 "shiftable_operator"
9136           [(match_operand:SI 2 "s_register_operand" "r")
9137            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9138   "TARGET_ARM"
9139   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9140   [(set_attr "conds" "use")
9141    (set_attr "length" "8")]
9144 (define_insn "*ifcompare_arith_not"
9145   [(set (match_operand:SI 0 "s_register_operand" "=r")
9146         (if_then_else:SI
9147          (match_operator 6 "arm_comparison_operator"
9148           [(match_operand:SI 4 "s_register_operand" "r")
9149            (match_operand:SI 5 "arm_add_operand" "rIL")])
9150          (match_operator:SI 7 "shiftable_operator"
9151           [(match_operand:SI 2 "s_register_operand" "r")
9152            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9153          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9154    (clobber (reg:CC CC_REGNUM))]
9155   "TARGET_ARM"
9156   "#"
9157   [(set_attr "conds" "clob")
9158    (set_attr "length" "12")]
9161 (define_insn "*if_arith_not"
9162   [(set (match_operand:SI 0 "s_register_operand" "=r")
9163         (if_then_else:SI
9164          (match_operator 5 "arm_comparison_operator"
9165           [(match_operand 4 "cc_register" "") (const_int 0)])
9166          (match_operator:SI 6 "shiftable_operator"
9167           [(match_operand:SI 2 "s_register_operand" "r")
9168            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9169          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9170   "TARGET_ARM"
9171   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9172   [(set_attr "conds" "use")
9173    (set_attr "length" "8")]
9176 (define_insn "*ifcompare_neg_move"
9177   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9178         (if_then_else:SI
9179          (match_operator 5 "arm_comparison_operator"
9180           [(match_operand:SI 3 "s_register_operand" "r,r")
9181            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9182          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9183          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9184    (clobber (reg:CC CC_REGNUM))]
9185   "TARGET_ARM"
9186   "#"
9187   [(set_attr "conds" "clob")
9188    (set_attr "length" "8,12")]
9191 (define_insn "*if_neg_move"
9192   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9193         (if_then_else:SI
9194          (match_operator 4 "arm_comparison_operator"
9195           [(match_operand 3 "cc_register" "") (const_int 0)])
9196          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9197          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9198   "TARGET_ARM"
9199   "@
9200    rsb%d4\\t%0, %2, #0
9201    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9202    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9203   [(set_attr "conds" "use")
9204    (set_attr "length" "4,8,8")]
9207 (define_insn "*ifcompare_move_neg"
9208   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9209         (if_then_else:SI
9210          (match_operator 5 "arm_comparison_operator"
9211           [(match_operand:SI 3 "s_register_operand" "r,r")
9212            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9213          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9214          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9215    (clobber (reg:CC CC_REGNUM))]
9216   "TARGET_ARM"
9217   "#"
9218   [(set_attr "conds" "clob")
9219    (set_attr "length" "8,12")]
9222 (define_insn "*if_move_neg"
9223   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9224         (if_then_else:SI
9225          (match_operator 4 "arm_comparison_operator"
9226           [(match_operand 3 "cc_register" "") (const_int 0)])
9227          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9228          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9229   "TARGET_ARM"
9230   "@
9231    rsb%D4\\t%0, %2, #0
9232    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9233    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9234   [(set_attr "conds" "use")
9235    (set_attr "length" "4,8,8")]
9238 (define_insn "*arith_adjacentmem"
9239   [(set (match_operand:SI 0 "s_register_operand" "=r")
9240         (match_operator:SI 1 "shiftable_operator"
9241          [(match_operand:SI 2 "memory_operand" "m")
9242           (match_operand:SI 3 "memory_operand" "m")]))
9243    (clobber (match_scratch:SI 4 "=r"))]
9244   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9245   "*
9246   {
9247     rtx ldm[3];
9248     rtx arith[4];
9249     int val1 = 0, val2 = 0;
9251     if (REGNO (operands[0]) > REGNO (operands[4]))
9252       {
9253         ldm[1] = operands[4];
9254         ldm[2] = operands[0];
9255       }
9256     else
9257       {
9258         ldm[1] = operands[0];
9259         ldm[2] = operands[4];
9260       }
9261     if (GET_CODE (XEXP (operands[2], 0)) != REG)
9262       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9263     if (GET_CODE (XEXP (operands[3], 0)) != REG)
9264       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9265     arith[0] = operands[0];
9266     arith[3] = operands[1];
9267     if (val1 < val2)
9268       {
9269         arith[1] = ldm[1];
9270         arith[2] = ldm[2];
9271       }
9272     else
9273       {
9274         arith[1] = ldm[2];
9275         arith[2] = ldm[1];
9276       }
9277    if (val1 && val2)
9278       {
9279         rtx ops[3];
9280         ldm[0] = ops[0] = operands[4];
9281         ops[1] = XEXP (XEXP (operands[2], 0), 0);
9282         ops[2] = XEXP (XEXP (operands[2], 0), 1);
9283         output_add_immediate (ops);
9284         if (val1 < val2)
9285           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9286         else
9287           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9288       }
9289     else if (val1)
9290       {
9291         ldm[0] = XEXP (operands[3], 0);
9292         if (val1 < val2)
9293           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9294         else
9295           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9296       }
9297     else
9298       {
9299         ldm[0] = XEXP (operands[2], 0);
9300         if (val1 < val2)
9301           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9302         else
9303           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9304       }
9305     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9306     return \"\";
9307   }"
9308   [(set_attr "length" "12")
9309    (set_attr "predicable" "yes")
9310    (set_attr "type" "load1")]
9313 ;; the arm can support extended pre-inc instructions
9315 ;; In all these cases, we use operands 0 and 1 for the register being
9316 ;; incremented because those are the operands that local-alloc will
9317 ;; tie and these are the pair most likely to be tieable (and the ones
9318 ;; that will benefit the most).
9320 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9321 ;; elimination will cause too many headaches.
9323 (define_insn "*strqi_preinc"
9324   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9325                          (match_operand:SI 2 "index_operand" "rJ")))
9326         (match_operand:QI 3 "s_register_operand" "r"))
9327    (set (match_operand:SI 0 "s_register_operand" "=r")
9328         (plus:SI (match_dup 1) (match_dup 2)))]
9329   "TARGET_ARM
9330    && !arm_eliminable_register (operands[0])
9331    && !arm_eliminable_register (operands[1])
9332    && !arm_eliminable_register (operands[2])"
9333   "str%?b\\t%3, [%0, %2]!"
9334   [(set_attr "type" "store1")
9335    (set_attr "predicable" "yes")]
9338 (define_insn "*strqi_predec"
9339   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9340                           (match_operand:SI 2 "s_register_operand" "r")))
9341         (match_operand:QI 3 "s_register_operand" "r"))
9342    (set (match_operand:SI 0 "s_register_operand" "=r")
9343         (minus:SI (match_dup 1) (match_dup 2)))]
9344   "TARGET_ARM
9345    && !arm_eliminable_register (operands[0])
9346    && !arm_eliminable_register (operands[1])
9347    && !arm_eliminable_register (operands[2])"
9348   "str%?b\\t%3, [%0, -%2]!"
9349   [(set_attr "type" "store1")
9350    (set_attr "predicable" "yes")]
9353 (define_insn "*loadqi_preinc"
9354   [(set (match_operand:QI 3 "s_register_operand" "=r")
9355         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9356                          (match_operand:SI 2 "index_operand" "rJ"))))
9357    (set (match_operand:SI 0 "s_register_operand" "=r")
9358         (plus:SI (match_dup 1) (match_dup 2)))]
9359   "TARGET_ARM
9360    && !arm_eliminable_register (operands[0])
9361    && !arm_eliminable_register (operands[1])
9362    && !arm_eliminable_register (operands[2])"
9363   "ldr%?b\\t%3, [%0, %2]!"
9364   [(set_attr "type" "load_byte")
9365    (set_attr "predicable" "yes")]
9368 (define_insn "*loadqi_predec"
9369   [(set (match_operand:QI 3 "s_register_operand" "=r")
9370         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9371                           (match_operand:SI 2 "s_register_operand" "r"))))
9372    (set (match_operand:SI 0 "s_register_operand" "=r")
9373         (minus:SI (match_dup 1) (match_dup 2)))]
9374   "TARGET_ARM
9375    && !arm_eliminable_register (operands[0])
9376    && !arm_eliminable_register (operands[1])
9377    && !arm_eliminable_register (operands[2])"
9378   "ldr%?b\\t%3, [%0, -%2]!"
9379   [(set_attr "type" "load_byte")
9380    (set_attr "predicable" "yes")]
9383 (define_insn "*loadqisi_preinc"
9384   [(set (match_operand:SI 3 "s_register_operand" "=r")
9385         (zero_extend:SI
9386          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9387                           (match_operand:SI 2 "index_operand" "rJ")))))
9388    (set (match_operand:SI 0 "s_register_operand" "=r")
9389         (plus:SI (match_dup 1) (match_dup 2)))]
9390   "TARGET_ARM
9391    && !arm_eliminable_register (operands[0])
9392    && !arm_eliminable_register (operands[1])
9393    && !arm_eliminable_register (operands[2])"
9394   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9395   [(set_attr "type" "load_byte")
9396    (set_attr "predicable" "yes")]
9399 (define_insn "*loadqisi_predec"
9400   [(set (match_operand:SI 3 "s_register_operand" "=r")
9401         (zero_extend:SI
9402          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9403                            (match_operand:SI 2 "s_register_operand" "r")))))
9404    (set (match_operand:SI 0 "s_register_operand" "=r")
9405         (minus:SI (match_dup 1) (match_dup 2)))]
9406   "TARGET_ARM
9407    && !arm_eliminable_register (operands[0])
9408    && !arm_eliminable_register (operands[1])
9409    && !arm_eliminable_register (operands[2])"
9410   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9411   [(set_attr "type" "load_byte")
9412    (set_attr "predicable" "yes")]
9415 (define_insn "*strsi_preinc"
9416   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9417                          (match_operand:SI 2 "index_operand" "rJ")))
9418         (match_operand:SI 3 "s_register_operand" "r"))
9419    (set (match_operand:SI 0 "s_register_operand" "=r")
9420         (plus:SI (match_dup 1) (match_dup 2)))]
9421   "TARGET_ARM
9422    && !arm_eliminable_register (operands[0])
9423    && !arm_eliminable_register (operands[1])
9424    && !arm_eliminable_register (operands[2])"
9425   "str%?\\t%3, [%0, %2]!"
9426   [(set_attr "type" "store1")
9427    (set_attr "predicable" "yes")]
9430 (define_insn "*strsi_predec"
9431   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9432                           (match_operand:SI 2 "s_register_operand" "r")))
9433         (match_operand:SI 3 "s_register_operand" "r"))
9434    (set (match_operand:SI 0 "s_register_operand" "=r")
9435         (minus:SI (match_dup 1) (match_dup 2)))]
9436   "TARGET_ARM
9437    && !arm_eliminable_register (operands[0])
9438    && !arm_eliminable_register (operands[1])
9439    && !arm_eliminable_register (operands[2])"
9440   "str%?\\t%3, [%0, -%2]!"
9441   [(set_attr "type" "store1")
9442    (set_attr "predicable" "yes")]
9445 (define_insn "*loadsi_preinc"
9446   [(set (match_operand:SI 3 "s_register_operand" "=r")
9447         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9448                          (match_operand:SI 2 "index_operand" "rJ"))))
9449    (set (match_operand:SI 0 "s_register_operand" "=r")
9450         (plus:SI (match_dup 1) (match_dup 2)))]
9451   "TARGET_ARM
9452    && !arm_eliminable_register (operands[0])
9453    && !arm_eliminable_register (operands[1])
9454    && !arm_eliminable_register (operands[2])"
9455   "ldr%?\\t%3, [%0, %2]!"
9456   [(set_attr "type" "load1")
9457    (set_attr "predicable" "yes")]
9460 (define_insn "*loadsi_predec"
9461   [(set (match_operand:SI 3 "s_register_operand" "=r")
9462         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9463                           (match_operand:SI 2 "s_register_operand" "r"))))
9464    (set (match_operand:SI 0 "s_register_operand" "=r")
9465         (minus:SI (match_dup 1) (match_dup 2)))]
9466   "TARGET_ARM
9467    && !arm_eliminable_register (operands[0])
9468    && !arm_eliminable_register (operands[1])
9469    && !arm_eliminable_register (operands[2])"
9470   "ldr%?\\t%3, [%0, -%2]!"
9471   [(set_attr "type" "load1")
9472    (set_attr "predicable" "yes")]
9475 (define_insn "*strqi_shiftpreinc"
9476   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9477                           [(match_operand:SI 3 "s_register_operand" "r")
9478                            (match_operand:SI 4 "const_shift_operand" "n")])
9479                          (match_operand:SI 1 "s_register_operand" "0")))
9480         (match_operand:QI 5 "s_register_operand" "r"))
9481    (set (match_operand:SI 0 "s_register_operand" "=r")
9482         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9483                  (match_dup 1)))]
9484   "TARGET_ARM
9485    && !arm_eliminable_register (operands[0])
9486    && !arm_eliminable_register (operands[1])
9487    && !arm_eliminable_register (operands[3])"
9488   "str%?b\\t%5, [%0, %3%S2]!"
9489   [(set_attr "type" "store1")
9490    (set_attr "predicable" "yes")]
9493 (define_insn "*strqi_shiftpredec"
9494   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9495                           (match_operator:SI 2 "shift_operator"
9496                            [(match_operand:SI 3 "s_register_operand" "r")
9497                             (match_operand:SI 4 "const_shift_operand" "n")])))
9498         (match_operand:QI 5 "s_register_operand" "r"))
9499    (set (match_operand:SI 0 "s_register_operand" "=r")
9500         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9501                                                  (match_dup 4)])))]
9502   "TARGET_ARM
9503    && !arm_eliminable_register (operands[0])
9504    && !arm_eliminable_register (operands[1])
9505    && !arm_eliminable_register (operands[3])"
9506   "str%?b\\t%5, [%0, -%3%S2]!"
9507   [(set_attr "type" "store1")
9508    (set_attr "predicable" "yes")]
9511 (define_insn "*loadqi_shiftpreinc"
9512   [(set (match_operand:QI 5 "s_register_operand" "=r")
9513         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9514                           [(match_operand:SI 3 "s_register_operand" "r")
9515                            (match_operand:SI 4 "const_shift_operand" "n")])
9516                          (match_operand:SI 1 "s_register_operand" "0"))))
9517    (set (match_operand:SI 0 "s_register_operand" "=r")
9518         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9519                  (match_dup 1)))]
9520   "TARGET_ARM
9521    && !arm_eliminable_register (operands[0])
9522    && !arm_eliminable_register (operands[1])
9523    && !arm_eliminable_register (operands[3])"
9524   "ldr%?b\\t%5, [%0, %3%S2]!"
9525   [(set_attr "type" "load_byte")
9526    (set_attr "predicable" "yes")]
9529 (define_insn "*loadqi_shiftpredec"
9530   [(set (match_operand:QI 5 "s_register_operand" "=r")
9531         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9532                           (match_operator:SI 2 "shift_operator"
9533                            [(match_operand:SI 3 "s_register_operand" "r")
9534                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9535    (set (match_operand:SI 0 "s_register_operand" "=r")
9536         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9537                                                  (match_dup 4)])))]
9538   "TARGET_ARM
9539    && !arm_eliminable_register (operands[0])
9540    && !arm_eliminable_register (operands[1])
9541    && !arm_eliminable_register (operands[3])"
9542   "ldr%?b\\t%5, [%0, -%3%S2]!"
9543   [(set_attr "type" "load_byte")
9544    (set_attr "predicable" "yes")]
9547 (define_insn "*strsi_shiftpreinc"
9548   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9549                           [(match_operand:SI 3 "s_register_operand" "r")
9550                            (match_operand:SI 4 "const_shift_operand" "n")])
9551                          (match_operand:SI 1 "s_register_operand" "0")))
9552         (match_operand:SI 5 "s_register_operand" "r"))
9553    (set (match_operand:SI 0 "s_register_operand" "=r")
9554         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9555                  (match_dup 1)))]
9556   "TARGET_ARM
9557    && !arm_eliminable_register (operands[0])
9558    && !arm_eliminable_register (operands[1])
9559    && !arm_eliminable_register (operands[3])"
9560   "str%?\\t%5, [%0, %3%S2]!"
9561   [(set_attr "type" "store1")
9562    (set_attr "predicable" "yes")]
9565 (define_insn "*strsi_shiftpredec"
9566   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9567                           (match_operator:SI 2 "shift_operator"
9568                            [(match_operand:SI 3 "s_register_operand" "r")
9569                             (match_operand:SI 4 "const_shift_operand" "n")])))
9570         (match_operand:SI 5 "s_register_operand" "r"))
9571    (set (match_operand:SI 0 "s_register_operand" "=r")
9572         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9573                                                  (match_dup 4)])))]
9574   "TARGET_ARM
9575    && !arm_eliminable_register (operands[0])
9576    && !arm_eliminable_register (operands[1])
9577    && !arm_eliminable_register (operands[3])"
9578   "str%?\\t%5, [%0, -%3%S2]!"
9579   [(set_attr "type" "store1")
9580    (set_attr "predicable" "yes")]
9583 (define_insn "*loadsi_shiftpreinc"
9584   [(set (match_operand:SI 5 "s_register_operand" "=r")
9585         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9586                           [(match_operand:SI 3 "s_register_operand" "r")
9587                            (match_operand:SI 4 "const_shift_operand" "n")])
9588                          (match_operand:SI 1 "s_register_operand" "0"))))
9589    (set (match_operand:SI 0 "s_register_operand" "=r")
9590         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9591                  (match_dup 1)))]
9592   "TARGET_ARM
9593    && !arm_eliminable_register (operands[0])
9594    && !arm_eliminable_register (operands[1])
9595    && !arm_eliminable_register (operands[3])"
9596   "ldr%?\\t%5, [%0, %3%S2]!"
9597   [(set_attr "type" "load1")
9598    (set_attr "predicable" "yes")]
9601 (define_insn "*loadsi_shiftpredec"
9602   [(set (match_operand:SI 5 "s_register_operand" "=r")
9603         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9604                           (match_operator:SI 2 "shift_operator"
9605                            [(match_operand:SI 3 "s_register_operand" "r")
9606                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9607    (set (match_operand:SI 0 "s_register_operand" "=r")
9608         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9609                                                  (match_dup 4)])))]
9610   "TARGET_ARM
9611    && !arm_eliminable_register (operands[0])
9612    && !arm_eliminable_register (operands[1])
9613    && !arm_eliminable_register (operands[3])"
9614   "ldr%?\\t%5, [%0, -%3%S2]!"
9615   [(set_attr "type" "load1")
9616    (set_attr "predicable" "yes")])
9618 ; It can also support extended post-inc expressions, but combine doesn't
9619 ; try these....
9620 ; It doesn't seem worth adding peepholes for anything but the most common
9621 ; cases since, unlike combine, the increment must immediately follow the load
9622 ; for this pattern to match.
9623 ; We must watch to see that the source/destination register isn't also the
9624 ; same as the base address register, and that if the index is a register,
9625 ; that it is not the same as the base address register.  In such cases the
9626 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9627 ; we cannot use it.
9629 (define_peephole
9630   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9631         (match_operand:QI 2 "s_register_operand" "r"))
9632    (set (match_dup 0)
9633         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9634   "TARGET_ARM
9635    && (REGNO (operands[2]) != REGNO (operands[0]))
9636    && (GET_CODE (operands[1]) != REG
9637        || (REGNO (operands[1]) != REGNO (operands[0])))"
9638   "str%?b\\t%2, [%0], %1"
9641 (define_peephole
9642   [(set (match_operand:QI 0 "s_register_operand" "=r")
9643         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9644    (set (match_dup 1)
9645         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9646   "TARGET_ARM
9647    && REGNO (operands[0]) != REGNO(operands[1])
9648    && (GET_CODE (operands[2]) != REG
9649        || REGNO(operands[0]) != REGNO (operands[2]))"
9650   "ldr%?b\\t%0, [%1], %2"
9653 (define_peephole
9654   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9655         (match_operand:SI 2 "s_register_operand" "r"))
9656    (set (match_dup 0)
9657         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9658   "TARGET_ARM
9659    && (REGNO (operands[2]) != REGNO (operands[0]))
9660    && (GET_CODE (operands[1]) != REG
9661        || (REGNO (operands[1]) != REGNO (operands[0])))"
9662   "str%?\\t%2, [%0], %1"
9665 (define_peephole
9666   [(set (match_operand:SI 0 "s_register_operand" "=r")
9667         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9668    (set (match_dup 1)
9669         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9670   "TARGET_ARM
9671    && REGNO (operands[0]) != REGNO(operands[1])
9672    && (GET_CODE (operands[2]) != REG
9673        || REGNO(operands[0]) != REGNO (operands[2]))"
9674   "ldr%?\\t%0, [%1], %2"
9677 (define_peephole
9678   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9679                          (match_operand:SI 1 "index_operand" "rJ")))
9680         (match_operand:QI 2 "s_register_operand" "r"))
9681    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9682   "TARGET_ARM
9683    && (REGNO (operands[2]) != REGNO (operands[0]))
9684    && (GET_CODE (operands[1]) != REG
9685        || (REGNO (operands[1]) != REGNO (operands[0])))"
9686   "str%?b\\t%2, [%0, %1]!"
9689 (define_peephole
9690   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9691                           [(match_operand:SI 0 "s_register_operand" "r")
9692                            (match_operand:SI 1 "const_int_operand" "n")])
9693                          (match_operand:SI 2 "s_register_operand" "+r")))
9694         (match_operand:QI 3 "s_register_operand" "r"))
9695    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9696                                (match_dup 2)))]
9697   "TARGET_ARM
9698    && (REGNO (operands[3]) != REGNO (operands[2]))
9699    && (REGNO (operands[0]) != REGNO (operands[2]))"
9700   "str%?b\\t%3, [%2, %0%S4]!"
9703 ; This pattern is never tried by combine, so do it as a peephole
9705 (define_peephole2
9706   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9707         (match_operand:SI 1 "arm_general_register_operand" ""))
9708    (set (reg:CC CC_REGNUM)
9709         (compare:CC (match_dup 1) (const_int 0)))]
9710   "TARGET_ARM"
9711   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9712               (set (match_dup 0) (match_dup 1))])]
9713   ""
9716 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9717 ; reversed, check that the memory references aren't volatile.
9719 (define_peephole
9720   [(set (match_operand:SI 0 "s_register_operand" "=r")
9721         (match_operand:SI 4 "memory_operand" "m"))
9722    (set (match_operand:SI 1 "s_register_operand" "=r")
9723         (match_operand:SI 5 "memory_operand" "m"))
9724    (set (match_operand:SI 2 "s_register_operand" "=r")
9725         (match_operand:SI 6 "memory_operand" "m"))
9726    (set (match_operand:SI 3 "s_register_operand" "=r")
9727         (match_operand:SI 7 "memory_operand" "m"))]
9728   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9729   "*
9730   return emit_ldm_seq (operands, 4);
9731   "
9734 (define_peephole
9735   [(set (match_operand:SI 0 "s_register_operand" "=r")
9736         (match_operand:SI 3 "memory_operand" "m"))
9737    (set (match_operand:SI 1 "s_register_operand" "=r")
9738         (match_operand:SI 4 "memory_operand" "m"))
9739    (set (match_operand:SI 2 "s_register_operand" "=r")
9740         (match_operand:SI 5 "memory_operand" "m"))]
9741   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9742   "*
9743   return emit_ldm_seq (operands, 3);
9744   "
9747 (define_peephole
9748   [(set (match_operand:SI 0 "s_register_operand" "=r")
9749         (match_operand:SI 2 "memory_operand" "m"))
9750    (set (match_operand:SI 1 "s_register_operand" "=r")
9751         (match_operand:SI 3 "memory_operand" "m"))]
9752   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9753   "*
9754   return emit_ldm_seq (operands, 2);
9755   "
9758 (define_peephole
9759   [(set (match_operand:SI 4 "memory_operand" "=m")
9760         (match_operand:SI 0 "s_register_operand" "r"))
9761    (set (match_operand:SI 5 "memory_operand" "=m")
9762         (match_operand:SI 1 "s_register_operand" "r"))
9763    (set (match_operand:SI 6 "memory_operand" "=m")
9764         (match_operand:SI 2 "s_register_operand" "r"))
9765    (set (match_operand:SI 7 "memory_operand" "=m")
9766         (match_operand:SI 3 "s_register_operand" "r"))]
9767   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9768   "*
9769   return emit_stm_seq (operands, 4);
9770   "
9773 (define_peephole
9774   [(set (match_operand:SI 3 "memory_operand" "=m")
9775         (match_operand:SI 0 "s_register_operand" "r"))
9776    (set (match_operand:SI 4 "memory_operand" "=m")
9777         (match_operand:SI 1 "s_register_operand" "r"))
9778    (set (match_operand:SI 5 "memory_operand" "=m")
9779         (match_operand:SI 2 "s_register_operand" "r"))]
9780   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9781   "*
9782   return emit_stm_seq (operands, 3);
9783   "
9786 (define_peephole
9787   [(set (match_operand:SI 2 "memory_operand" "=m")
9788         (match_operand:SI 0 "s_register_operand" "r"))
9789    (set (match_operand:SI 3 "memory_operand" "=m")
9790         (match_operand:SI 1 "s_register_operand" "r"))]
9791   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9792   "*
9793   return emit_stm_seq (operands, 2);
9794   "
9797 (define_split
9798   [(set (match_operand:SI 0 "s_register_operand" "")
9799         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9800                        (const_int 0))
9801                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9802                          [(match_operand:SI 3 "s_register_operand" "")
9803                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9804    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9805   "TARGET_ARM"
9806   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9807    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9808                               (match_dup 5)))]
9809   ""
9812 ;; This split can be used because CC_Z mode implies that the following
9813 ;; branch will be an equality, or an unsigned inequality, so the sign
9814 ;; extension is not needed.
9816 (define_split
9817   [(set (reg:CC_Z CC_REGNUM)
9818         (compare:CC_Z
9819          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9820                     (const_int 24))
9821          (match_operand 1 "const_int_operand" "")))
9822    (clobber (match_scratch:SI 2 ""))]
9823   "TARGET_ARM
9824    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9825        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9826   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9827    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9828   "
9829   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9830   "
9833 (define_expand "prologue"
9834   [(clobber (const_int 0))]
9835   "TARGET_EITHER"
9836   "if (TARGET_ARM)
9837      arm_expand_prologue ();
9838    else
9839      thumb_expand_prologue ();
9840   DONE;
9841   "
9844 (define_expand "epilogue"
9845   [(clobber (const_int 0))]
9846   "TARGET_EITHER"
9847   "
9848   if (current_function_calls_eh_return)
9849     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9850   if (TARGET_THUMB)
9851     thumb_expand_epilogue ();
9852   else if (USE_RETURN_INSN (FALSE))
9853     {
9854       emit_jump_insn (gen_return ());
9855       DONE;
9856     }
9857   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9858         gen_rtvec (1,
9859                 gen_rtx_RETURN (VOIDmode)),
9860         VUNSPEC_EPILOGUE));
9861   DONE;
9862   "
9865 ;; Note - although unspec_volatile's USE all hard registers,
9866 ;; USEs are ignored after relaod has completed.  Thus we need
9867 ;; to add an unspec of the link register to ensure that flow
9868 ;; does not think that it is unused by the sibcall branch that
9869 ;; will replace the standard function epilogue.
9870 (define_insn "sibcall_epilogue"
9871   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9872               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9873   "TARGET_ARM"
9874   "*
9875   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9876     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9877   return arm_output_epilogue (next_nonnote_insn (insn));
9878   "
9879 ;; Length is absolute worst case
9880   [(set_attr "length" "44")
9881    (set_attr "type" "block")
9882    ;; We don't clobber the conditions, but the potential length of this
9883    ;; operation is sufficient to make conditionalizing the sequence 
9884    ;; unlikely to be profitable.
9885    (set_attr "conds" "clob")]
9888 (define_insn "*epilogue_insns"
9889   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9890   "TARGET_EITHER"
9891   "*
9892   if (TARGET_ARM)
9893     return arm_output_epilogue (NULL);
9894   else /* TARGET_THUMB */
9895     return thumb_unexpanded_epilogue ();
9896   "
9897   ; Length is absolute worst case
9898   [(set_attr "length" "44")
9899    (set_attr "type" "block")
9900    ;; We don't clobber the conditions, but the potential length of this
9901    ;; operation is sufficient to make conditionalizing the sequence 
9902    ;; unlikely to be profitable.
9903    (set_attr "conds" "clob")]
9906 (define_expand "eh_epilogue"
9907   [(use (match_operand:SI 0 "register_operand" ""))
9908    (use (match_operand:SI 1 "register_operand" ""))
9909    (use (match_operand:SI 2 "register_operand" ""))]
9910   "TARGET_EITHER"
9911   "
9912   {
9913     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9914     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9915       {
9916         rtx ra = gen_rtx_REG (Pmode, 2);
9918         emit_move_insn (ra, operands[2]);
9919         operands[2] = ra;
9920       }
9921     /* This is a hack -- we may have crystalized the function type too
9922        early.  */
9923     cfun->machine->func_type = 0;
9924   }"
9927 ;; This split is only used during output to reduce the number of patterns
9928 ;; that need assembler instructions adding to them.  We allowed the setting
9929 ;; of the conditions to be implicit during rtl generation so that
9930 ;; the conditional compare patterns would work.  However this conflicts to
9931 ;; some extent with the conditional data operations, so we have to split them
9932 ;; up again here.
9934 (define_split
9935   [(set (match_operand:SI 0 "s_register_operand" "")
9936         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9937                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9938                          (match_dup 0)
9939                          (match_operand 4 "" "")))
9940    (clobber (reg:CC CC_REGNUM))]
9941   "TARGET_ARM && reload_completed"
9942   [(set (match_dup 5) (match_dup 6))
9943    (cond_exec (match_dup 7)
9944               (set (match_dup 0) (match_dup 4)))]
9945   "
9946   {
9947     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9948                                              operands[2], operands[3]);
9949     enum rtx_code rc = GET_CODE (operands[1]);
9951     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9952     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9953     if (mode == CCFPmode || mode == CCFPEmode)
9954       rc = reverse_condition_maybe_unordered (rc);
9955     else
9956       rc = reverse_condition (rc);
9958     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9959   }"
9962 (define_split
9963   [(set (match_operand:SI 0 "s_register_operand" "")
9964         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9965                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9966                          (match_operand 4 "" "")
9967                          (match_dup 0)))
9968    (clobber (reg:CC CC_REGNUM))]
9969   "TARGET_ARM && reload_completed"
9970   [(set (match_dup 5) (match_dup 6))
9971    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9972               (set (match_dup 0) (match_dup 4)))]
9973   "
9974   {
9975     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9976                                              operands[2], operands[3]);
9978     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9979     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9980   }"
9983 (define_split
9984   [(set (match_operand:SI 0 "s_register_operand" "")
9985         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9986                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9987                          (match_operand 4 "" "")
9988                          (match_operand 5 "" "")))
9989    (clobber (reg:CC CC_REGNUM))]
9990   "TARGET_ARM && reload_completed"
9991   [(set (match_dup 6) (match_dup 7))
9992    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9993               (set (match_dup 0) (match_dup 4)))
9994    (cond_exec (match_dup 8)
9995               (set (match_dup 0) (match_dup 5)))]
9996   "
9997   {
9998     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9999                                              operands[2], operands[3]);
10000     enum rtx_code rc = GET_CODE (operands[1]);
10002     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10003     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10004     if (mode == CCFPmode || mode == CCFPEmode)
10005       rc = reverse_condition_maybe_unordered (rc);
10006     else
10007       rc = reverse_condition (rc);
10009     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10010   }"
10013 (define_split
10014   [(set (match_operand:SI 0 "s_register_operand" "")
10015         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10016                           [(match_operand:SI 2 "s_register_operand" "")
10017                            (match_operand:SI 3 "arm_add_operand" "")])
10018                          (match_operand:SI 4 "arm_rhs_operand" "")
10019                          (not:SI
10020                           (match_operand:SI 5 "s_register_operand" ""))))
10021    (clobber (reg:CC CC_REGNUM))]
10022   "TARGET_ARM && reload_completed"
10023   [(set (match_dup 6) (match_dup 7))
10024    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10025               (set (match_dup 0) (match_dup 4)))
10026    (cond_exec (match_dup 8)
10027               (set (match_dup 0) (not:SI (match_dup 5))))]
10028   "
10029   {
10030     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10031                                              operands[2], operands[3]);
10032     enum rtx_code rc = GET_CODE (operands[1]);
10034     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10035     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10036     if (mode == CCFPmode || mode == CCFPEmode)
10037       rc = reverse_condition_maybe_unordered (rc);
10038     else
10039       rc = reverse_condition (rc);
10041     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10042   }"
10045 (define_insn "*cond_move_not"
10046   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10047         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10048                           [(match_operand 3 "cc_register" "") (const_int 0)])
10049                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10050                          (not:SI
10051                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10052   "TARGET_ARM"
10053   "@
10054    mvn%D4\\t%0, %2
10055    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10056   [(set_attr "conds" "use")
10057    (set_attr "length" "4,8")]
10060 ;; The next two patterns occur when an AND operation is followed by a
10061 ;; scc insn sequence 
10063 (define_insn "*sign_extract_onebit"
10064   [(set (match_operand:SI 0 "s_register_operand" "=r")
10065         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10066                          (const_int 1)
10067                          (match_operand:SI 2 "const_int_operand" "n")))
10068     (clobber (reg:CC CC_REGNUM))]
10069   "TARGET_ARM"
10070   "*
10071     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10072     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10073     return \"mvnne\\t%0, #0\";
10074   "
10075   [(set_attr "conds" "clob")
10076    (set_attr "length" "8")]
10079 (define_insn "*not_signextract_onebit"
10080   [(set (match_operand:SI 0 "s_register_operand" "=r")
10081         (not:SI
10082          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10083                           (const_int 1)
10084                           (match_operand:SI 2 "const_int_operand" "n"))))
10085    (clobber (reg:CC CC_REGNUM))]
10086   "TARGET_ARM"
10087   "*
10088     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10089     output_asm_insn (\"tst\\t%1, %2\", operands);
10090     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10091     return \"movne\\t%0, #0\";
10092   "
10093   [(set_attr "conds" "clob")
10094    (set_attr "length" "12")]
10097 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10098 ;; expressions.  For simplicity, the first register is also in the unspec
10099 ;; part.
10100 (define_insn "*push_multi"
10101   [(match_parallel 2 "multi_register_push"
10102     [(set (match_operand:BLK 0 "memory_operand" "=m")
10103           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10104                       UNSPEC_PUSH_MULT))])]
10105   "TARGET_ARM"
10106   "*
10107   {
10108     int num_saves = XVECLEN (operands[2], 0);
10109      
10110     /* For the StrongARM at least it is faster to
10111        use STR to store only a single register.  */
10112     if (num_saves == 1)
10113       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10114     else
10115       {
10116         int i;
10117         char pattern[100];
10119         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10121         for (i = 1; i < num_saves; i++)
10122           {
10123             strcat (pattern, \", %|\");
10124             strcat (pattern,
10125                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10126           }
10128         strcat (pattern, \"}\");
10129         output_asm_insn (pattern, operands);
10130       }
10132     return \"\";
10133   }"
10134   [(set_attr "type" "store4")]
10137 (define_insn "stack_tie"
10138   [(set (mem:BLK (scratch))
10139         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10140                      (match_operand:SI 1 "s_register_operand" "r")]
10141                     UNSPEC_PRLG_STK))]
10142   ""
10143   ""
10144   [(set_attr "length" "0")]
10147 ;; Similarly for the floating point registers
10148 (define_insn "*push_fp_multi"
10149   [(match_parallel 2 "multi_register_push"
10150     [(set (match_operand:BLK 0 "memory_operand" "=m")
10151           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10152                       UNSPEC_PUSH_MULT))])]
10153   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10154   "*
10155   {
10156     char pattern[100];
10158     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10159     output_asm_insn (pattern, operands);
10160     return \"\";
10161   }"
10162   [(set_attr "type" "f_store")]
10165 ;; Special patterns for dealing with the constant pool
10167 (define_insn "align_4"
10168   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10169   "TARGET_EITHER"
10170   "*
10171   assemble_align (32);
10172   return \"\";
10173   "
10176 (define_insn "align_8"
10177   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10178   "TARGET_EITHER"
10179   "*
10180   assemble_align (64);
10181   return \"\";
10182   "
10185 (define_insn "consttable_end"
10186   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10187   "TARGET_EITHER"
10188   "*
10189   making_const_table = FALSE;
10190   return \"\";
10191   "
10194 (define_insn "consttable_1"
10195   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10196   "TARGET_THUMB"
10197   "*
10198   making_const_table = TRUE;
10199   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10200   assemble_zeros (3);
10201   return \"\";
10202   "
10203   [(set_attr "length" "4")]
10206 (define_insn "consttable_2"
10207   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10208   "TARGET_THUMB"
10209   "*
10210   making_const_table = TRUE;
10211   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10212   assemble_zeros (2);
10213   return \"\";
10214   "
10215   [(set_attr "length" "4")]
10218 (define_insn "consttable_4"
10219   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10220   "TARGET_EITHER"
10221   "*
10222   {
10223     making_const_table = TRUE;
10224     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10225       {
10226       case MODE_FLOAT:
10227       {
10228         REAL_VALUE_TYPE r;
10229         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10230         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10231         break;
10232       }
10233       default:
10234         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10235         break;
10236       }
10237     return \"\";
10238   }"
10239   [(set_attr "length" "4")]
10242 (define_insn "consttable_8"
10243   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10244   "TARGET_EITHER"
10245   "*
10246   {
10247     making_const_table = TRUE;
10248     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10249       {
10250        case MODE_FLOAT:
10251         {
10252           REAL_VALUE_TYPE r;
10253           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10254           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10255           break;
10256         }
10257       default:
10258         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10259         break;
10260       }
10261     return \"\";
10262   }"
10263   [(set_attr "length" "8")]
10266 ;; Miscellaneous Thumb patterns
10268 (define_expand "tablejump"
10269   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10270               (use (label_ref (match_operand 1 "" "")))])]
10271   "TARGET_THUMB"
10272   "
10273   if (flag_pic)
10274     {
10275       /* Hopefully, CSE will eliminate this copy.  */
10276       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10277       rtx reg2 = gen_reg_rtx (SImode);
10279       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10280       operands[0] = reg2;
10281     }
10282   "
10285 ;; NB never uses BX.
10286 (define_insn "*thumb_tablejump"
10287   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10288    (use (label_ref (match_operand 1 "" "")))]
10289   "TARGET_THUMB"
10290   "mov\\t%|pc, %0"
10291   [(set_attr "length" "2")]
10294 ;; V5 Instructions,
10296 (define_insn "clzsi2"
10297   [(set (match_operand:SI 0 "s_register_operand" "=r")
10298         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10299   "TARGET_ARM && arm_arch5"
10300   "clz%?\\t%0, %1"
10301   [(set_attr "predicable" "yes")])
10303 (define_expand "ffssi2"
10304   [(set (match_operand:SI 0 "s_register_operand" "")
10305         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10306   "TARGET_ARM && arm_arch5"
10307   "
10308   {
10309     rtx t1, t2, t3;
10311     t1 = gen_reg_rtx (SImode);
10312     t2 = gen_reg_rtx (SImode);
10313     t3 = gen_reg_rtx (SImode);
10315     emit_insn (gen_negsi2 (t1, operands[1]));
10316     emit_insn (gen_andsi3 (t2, operands[1], t1));
10317     emit_insn (gen_clzsi2 (t3, t2));
10318     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10319     DONE;
10320   }"
10323 (define_expand "ctzsi2"
10324   [(set (match_operand:SI 0 "s_register_operand" "")
10325         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10326   "TARGET_ARM && arm_arch5"
10327   "
10328   {
10329     rtx t1, t2, t3;
10331     t1 = gen_reg_rtx (SImode);
10332     t2 = gen_reg_rtx (SImode);
10333     t3 = gen_reg_rtx (SImode);
10335     emit_insn (gen_negsi2 (t1, operands[1]));
10336     emit_insn (gen_andsi3 (t2, operands[1], t1));
10337     emit_insn (gen_clzsi2 (t3, t2));
10338     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10339     DONE;
10340   }"
10343 ;; V5E instructions.
10345 (define_insn "prefetch"
10346   [(prefetch (match_operand:SI 0 "address_operand" "p")
10347              (match_operand:SI 1 "" "")
10348              (match_operand:SI 2 "" ""))]
10349   "TARGET_ARM && arm_arch5e"
10350   "pld\\t%a0")
10352 ;; General predication pattern
10354 (define_cond_exec
10355   [(match_operator 0 "arm_comparison_operator"
10356     [(match_operand 1 "cc_register" "")
10357      (const_int 0)])]
10358   "TARGET_ARM"
10359   ""
10362 (define_insn "prologue_use"
10363   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10364   ""
10365   "%@ %0 needed for prologue"
10369 ;; Patterns for exception handling
10371 (define_expand "eh_return"
10372   [(use (match_operand 0 "general_operand" ""))]
10373   "TARGET_EITHER"
10374   "
10375   {
10376     if (TARGET_ARM)
10377       emit_insn (gen_arm_eh_return (operands[0]));
10378     else
10379       emit_insn (gen_thumb_eh_return (operands[0]));
10380     DONE;
10381   }"
10383                                    
10384 ;; We can't expand this before we know where the link register is stored.
10385 (define_insn_and_split "arm_eh_return"
10386   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10387                     VUNSPEC_EH_RETURN)
10388    (clobber (match_scratch:SI 1 "=&r"))]
10389   "TARGET_ARM"
10390   "#"
10391   "&& reload_completed"
10392   [(const_int 0)]
10393   "
10394   {
10395     arm_set_return_address (operands[0], operands[1]);
10396     DONE;
10397   }"
10400 (define_insn_and_split "thumb_eh_return"
10401   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10402                     VUNSPEC_EH_RETURN)
10403    (clobber (match_scratch:SI 1 "=&l"))]
10404   "TARGET_THUMB"
10405   "#"
10406   "&& reload_completed"
10407   [(const_int 0)]
10408   "
10409   {
10410     thumb_set_return_address (operands[0], operands[1]);
10411     DONE;
10412   }"
10415 ;; Load the FPA co-processor patterns
10416 (include "fpa.md")
10417 ;; Load the Maverick co-processor patterns
10418 (include "cirrus.md")
10419 ;; Load the Intel Wireless Multimedia Extension patterns
10420 (include "iwmmxt.md")
10421 ;; Load the VFP co-processor patterns
10422 (include "vfp.md")