* Mainline merge as of 2006-02-16 (@111136).
[official-gcc.git] / gcc / config / arm / arm.md
blob53b633ddc7f072274e31d060ffe5a29018e2bf2d
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003, 2004, 2005, 2006  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, 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, 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    (UNSPEC_TLS      20) ; A symbol that has been treated properly for TLS usage.
94    (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
95                          ; instruction stream.
96   ]
99 ;; UNSPEC_VOLATILE Usage:
101 (define_constants
102   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
103                         ;   insn in the code.
104    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
105                         ;   instruction epilogue sequence that isn't expanded
106                         ;   into normal RTL.  Used for both normal and sibcall
107                         ;   epilogues.
108    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
109                         ;   for inlined constants.
110    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
111                         ;   table.
112    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
113                         ;   an 8-bit object.
114    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
115                         ;   a 16-bit object.
116    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
117                         ;   a 32-bit object.
118    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
119                         ;   a 64-bit object.
120    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
121    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
122    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
123    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
124    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
125    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
126    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
127                          ; handling.
128   ]
131 ;;---------------------------------------------------------------------------
132 ;; Attributes
134 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
135 ; generating ARM code.  This is used to control the length of some insn
136 ; patterns that share the same RTL in both ARM and Thumb code.
137 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
139 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
140 ; scheduling decisions for the load unit and the multiplier.
141 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
143 ; IS_XSCALE is set to 'yes' when compiling for XScale.
144 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
146 ;; Operand number of an input operand that is shifted.  Zero if the
147 ;; given instruction does not shift one of its input operands.
148 (define_attr "shift" "" (const_int 0))
150 ; Floating Point Unit.  If we only have floating point emulation, then there
151 ; is no point in scheduling the floating point insns.  (Well, for best
152 ; performance we should try and group them together).
153 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
154   (const (symbol_ref "arm_fpu_attr")))
156 ; LENGTH of an instruction (in bytes)
157 (define_attr "length" "" (const_int 4))
159 ; POOL_RANGE is how far away from a constant pool entry that this insn
160 ; can be placed.  If the distance is zero, then this insn will never
161 ; reference the pool.
162 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
163 ; before its address.
164 (define_attr "pool_range" "" (const_int 0))
165 (define_attr "neg_pool_range" "" (const_int 0))
167 ; An assembler sequence may clobber the condition codes without us knowing.
168 ; If such an insn references the pool, then we have no way of knowing how,
169 ; so use the most conservative value for pool_range.
170 (define_asm_attributes
171  [(set_attr "conds" "clob")
172   (set_attr "length" "4")
173   (set_attr "pool_range" "250")])
175 ;; The instruction used to implement a particular pattern.  This
176 ;; information is used by pipeline descriptions to provide accurate
177 ;; scheduling information.
179 (define_attr "insn"
180         "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"
181         (const_string "other"))
183 ; TYPE attribute is used to detect floating point instructions which, if
184 ; running on a co-processor can run in parallel with other, basic instructions
185 ; If write-buffer scheduling is enabled then it can also be used in the
186 ; scheduling of writes.
188 ; Classification of each insn
189 ; alu           any alu  instruction that doesn't hit memory or fp
190 ;               regs or have a shifted source operand
191 ; alu_shift     any data instruction that doesn't hit memory or fp
192 ;               regs, but has a source operand shifted by a constant
193 ; alu_shift_reg any data instruction that doesn't hit memory or fp
194 ;               regs, but has a source operand shifted by a register value
195 ; mult          a multiply instruction
196 ; block         blockage insn, this blocks all functional units
197 ; float         a floating point arithmetic operation (subject to expansion)
198 ; fdivd         DFmode floating point division
199 ; fdivs         SFmode floating point division
200 ; fmul          Floating point multiply
201 ; ffmul         Fast floating point multiply
202 ; farith        Floating point arithmetic (4 cycle)
203 ; ffarith       Fast floating point arithmetic (2 cycle)
204 ; float_em      a floating point arithmetic operation that is normally emulated
205 ;               even on a machine with an fpa.
206 ; f_load        a floating point load from memory
207 ; f_store       a floating point store to memory
208 ; f_load[sd]    single/double load from memory
209 ; f_store[sd]   single/double store to memory
210 ; f_flag        a transfer of co-processor flags to the CPSR
211 ; f_mem_r       a transfer of a floating point register to a real reg via mem
212 ; r_mem_f       the reverse of f_mem_r
213 ; f_2_r         fast transfer float to arm (no memory needed)
214 ; r_2_f         fast transfer arm to float
215 ; f_cvt         convert floating<->integral
216 ; branch        a branch
217 ; call          a subroutine call
218 ; load_byte     load byte(s) from memory to arm registers
219 ; load1         load 1 word from memory to arm registers
220 ; load2         load 2 words from memory to arm registers
221 ; load3         load 3 words from memory to arm registers
222 ; load4         load 4 words from memory to arm registers
223 ; store         store 1 word to memory from arm registers
224 ; store2        store 2 words
225 ; store3        store 3 words
226 ; store4        store 4 (or more) words
227 ;  Additions for Cirrus Maverick co-processor:
228 ; mav_farith    Floating point arithmetic (4 cycle)
229 ; mav_dmult     Double multiplies (7 cycle)
231 (define_attr "type"
232         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
233         (if_then_else 
234          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
235          (const_string "mult")
236          (const_string "alu")))
238 ; Load scheduling, set from the arm_ld_sched variable
239 ; initialized by arm_override_options() 
240 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
242 ; condition codes: this one is used by final_prescan_insn to speed up
243 ; conditionalizing instructions.  It saves having to scan the rtl to see if
244 ; it uses or alters the condition codes.
246 ; USE means that the condition codes are used by the insn in the process of
247 ;   outputting code, this means (at present) that we can't use the insn in
248 ;   inlined branches
250 ; SET means that the purpose of the insn is to set the condition codes in a
251 ;   well defined manner.
253 ; CLOB means that the condition codes are altered in an undefined manner, if
254 ;   they are altered at all
256 ; JUMP_CLOB is used when the condition cannot be represented by a single
257 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
259 ; NOCOND means that the condition codes are neither altered nor affect the
260 ;   output of this insn
262 (define_attr "conds" "use,set,clob,jump_clob,nocond"
263         (if_then_else (eq_attr "type" "call")
264          (const_string "clob")
265          (const_string "nocond")))
267 ; Predicable means that the insn can be conditionally executed based on
268 ; an automatically added predicate (additional patterns are generated by 
269 ; gen...).  We default to 'no' because no Thumb patterns match this rule
270 ; and not all ARM patterns do.
271 (define_attr "predicable" "no,yes" (const_string "no"))
273 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
274 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
275 ; suffer blockages enough to warrant modelling this (and it can adversely
276 ; affect the schedule).
277 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
279 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
280 ; to stall the processor.  Used with model_wbuf above.
281 (define_attr "write_conflict" "no,yes"
282   (if_then_else (eq_attr "type"
283                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
284                 (const_string "yes")
285                 (const_string "no")))
287 ; Classify the insns into those that take one cycle and those that take more
288 ; than one on the main cpu execution unit.
289 (define_attr "core_cycles" "single,multi"
290   (if_then_else (eq_attr "type"
291                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
292                 (const_string "single")
293                 (const_string "multi")))
295 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
296 ;; distant label.  Only applicable to Thumb code.
297 (define_attr "far_jump" "yes,no" (const_string "no"))
300 ;;---------------------------------------------------------------------------
301 ;; Mode macros
303 ; A list of modes that are exactly 64 bits in size.  We use this to expand
304 ; some splits that are the same for all modes when operating on ARM 
305 ; registers.
306 (define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
308 ;;---------------------------------------------------------------------------
309 ;; Predicates
311 (include "predicates.md")
313 ;;---------------------------------------------------------------------------
314 ;; Pipeline descriptions
316 ;; Processor type.  This is created automatically from arm-cores.def.
317 (include "arm-tune.md")
319 ;; True if the generic scheduling description should be used.
321 (define_attr "generic_sched" "yes,no"
322   (const (if_then_else 
323           (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs") 
324           (const_string "no")
325           (const_string "yes"))))
327 (define_attr "generic_vfp" "yes,no"
328   (const (if_then_else
329           (and (eq_attr "fpu" "vfp")
330                (eq_attr "tune" "!arm1020e,arm1022e"))
331           (const_string "yes")
332           (const_string "no"))))
334 (include "arm-generic.md")
335 (include "arm926ejs.md")
336 (include "arm1020e.md")
337 (include "arm1026ejs.md")
338 (include "arm1136jfs.md")
341 ;;---------------------------------------------------------------------------
342 ;; Insn patterns
344 ;; Addition insns.
346 ;; Note: For DImode insns, there is normally no reason why operands should
347 ;; not be in the same register, what we don't want is for something being
348 ;; written to partially overlap something that is an input.
349 ;; Cirrus 64bit additions should not be split because we have a native
350 ;; 64bit addition instructions.
352 (define_expand "adddi3"
353  [(parallel
354    [(set (match_operand:DI           0 "s_register_operand" "")
355           (plus:DI (match_operand:DI 1 "s_register_operand" "")
356                    (match_operand:DI 2 "s_register_operand" "")))
357     (clobber (reg:CC CC_REGNUM))])]
358   "TARGET_EITHER"
359   "
360   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
361     {
362       if (!cirrus_fp_register (operands[0], DImode))
363         operands[0] = force_reg (DImode, operands[0]);
364       if (!cirrus_fp_register (operands[1], DImode))
365         operands[1] = force_reg (DImode, operands[1]);
366       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
367       DONE;
368     }
370   if (TARGET_THUMB)
371     {
372       if (GET_CODE (operands[1]) != REG)
373         operands[1] = force_reg (SImode, operands[1]);
374       if (GET_CODE (operands[2]) != REG)
375         operands[2] = force_reg (SImode, operands[2]);
376      }
377   "
380 (define_insn "*thumb_adddi3"
381   [(set (match_operand:DI          0 "register_operand" "=l")
382         (plus:DI (match_operand:DI 1 "register_operand" "%0")
383                  (match_operand:DI 2 "register_operand" "l")))
384    (clobber (reg:CC CC_REGNUM))
385   ]
386   "TARGET_THUMB"
387   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
388   [(set_attr "length" "4")]
391 (define_insn_and_split "*arm_adddi3"
392   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
393         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
394                  (match_operand:DI 2 "s_register_operand" "r,  0")))
395    (clobber (reg:CC CC_REGNUM))]
396   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
397   "#"
398   "TARGET_ARM && reload_completed"
399   [(parallel [(set (reg:CC_C CC_REGNUM)
400                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
401                                  (match_dup 1)))
402               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
403    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
404                                (plus:SI (match_dup 4) (match_dup 5))))]
405   "
406   {
407     operands[3] = gen_highpart (SImode, operands[0]);
408     operands[0] = gen_lowpart (SImode, operands[0]);
409     operands[4] = gen_highpart (SImode, operands[1]);
410     operands[1] = gen_lowpart (SImode, operands[1]);
411     operands[5] = gen_highpart (SImode, operands[2]);
412     operands[2] = gen_lowpart (SImode, operands[2]);
413   }"
414   [(set_attr "conds" "clob")
415    (set_attr "length" "8")]
418 (define_insn_and_split "*adddi_sesidi_di"
419   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
420         (plus:DI (sign_extend:DI
421                   (match_operand:SI 2 "s_register_operand" "r,r"))
422                  (match_operand:DI 1 "s_register_operand" "r,0")))
423    (clobber (reg:CC CC_REGNUM))]
424   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
425   "#"
426   "TARGET_ARM && reload_completed"
427   [(parallel [(set (reg:CC_C CC_REGNUM)
428                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
429                                  (match_dup 1)))
430               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
431    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
432                                (plus:SI (ashiftrt:SI (match_dup 2)
433                                                      (const_int 31))
434                                         (match_dup 4))))]
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_insn_and_split "*adddi_zesidi_di"
448   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
449         (plus:DI (zero_extend:DI
450                   (match_operand:SI 2 "s_register_operand" "r,r"))
451                  (match_operand:DI 1 "s_register_operand" "r,0")))
452    (clobber (reg:CC CC_REGNUM))]
453   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
454   "#"
455   "TARGET_ARM && reload_completed"
456   [(parallel [(set (reg:CC_C CC_REGNUM)
457                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
458                                  (match_dup 1)))
459               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
460    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
461                                (plus:SI (match_dup 4) (const_int 0))))]
462   "
463   {
464     operands[3] = gen_highpart (SImode, operands[0]);
465     operands[0] = gen_lowpart (SImode, operands[0]);
466     operands[4] = gen_highpart (SImode, operands[1]);
467     operands[1] = gen_lowpart (SImode, operands[1]);
468     operands[2] = gen_lowpart (SImode, operands[2]);
469   }"
470   [(set_attr "conds" "clob")
471    (set_attr "length" "8")]
474 (define_expand "addsi3"
475   [(set (match_operand:SI          0 "s_register_operand" "")
476         (plus:SI (match_operand:SI 1 "s_register_operand" "")
477                  (match_operand:SI 2 "reg_or_int_operand" "")))]
478   "TARGET_EITHER"
479   "
480   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
481     {
482       arm_split_constant (PLUS, SImode, NULL_RTX,
483                           INTVAL (operands[2]), operands[0], operands[1],
484                           optimize && !no_new_pseudos);
485       DONE;
486     }
487   "
490 ; If there is a scratch available, this will be faster than synthesizing the
491 ; addition.
492 (define_peephole2
493   [(match_scratch:SI 3 "r")
494    (set (match_operand:SI          0 "arm_general_register_operand" "")
495         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
496                  (match_operand:SI 2 "const_int_operand"  "")))]
497   "TARGET_ARM &&
498    !(const_ok_for_arm (INTVAL (operands[2]))
499      || const_ok_for_arm (-INTVAL (operands[2])))
500     && const_ok_for_arm (~INTVAL (operands[2]))"
501   [(set (match_dup 3) (match_dup 2))
502    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
503   ""
506 (define_insn_and_split "*arm_addsi3"
507   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
508         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
509                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
510   "TARGET_ARM"
511   "@
512    add%?\\t%0, %1, %2
513    sub%?\\t%0, %1, #%n2
514    #"
515   "TARGET_ARM &&
516    GET_CODE (operands[2]) == CONST_INT
517    && !(const_ok_for_arm (INTVAL (operands[2]))
518         || const_ok_for_arm (-INTVAL (operands[2])))"
519   [(clobber (const_int 0))]
520   "
521   arm_split_constant (PLUS, SImode, curr_insn,
522                       INTVAL (operands[2]), operands[0],
523                       operands[1], 0);
524   DONE;
525   "
526   [(set_attr "length" "4,4,16")
527    (set_attr "predicable" "yes")]
530 ;; Register group 'k' is a single register group containing only the stack
531 ;; register.  Trying to reload it will always fail catastrophically,
532 ;; so never allow those alternatives to match if reloading is needed.
534 (define_insn "*thumb_addsi3"
535   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
536         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
537                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
538   "TARGET_THUMB"
539   "*
540    static const char * const asms[] = 
541    {
542      \"add\\t%0, %0, %2\",
543      \"sub\\t%0, %0, #%n2\",
544      \"add\\t%0, %1, %2\",
545      \"add\\t%0, %0, %2\",
546      \"add\\t%0, %0, %2\",
547      \"add\\t%0, %1, %2\",
548      \"add\\t%0, %1, %2\"
549    };
550    if ((which_alternative == 2 || which_alternative == 6)
551        && GET_CODE (operands[2]) == CONST_INT
552        && INTVAL (operands[2]) < 0)
553      return \"sub\\t%0, %1, #%n2\";
554    return asms[which_alternative];
555   "
556   [(set_attr "length" "2")]
559 ;; Reloading and elimination of the frame pointer can
560 ;; sometimes cause this optimization to be missed.
561 (define_peephole2
562   [(set (match_operand:SI 0 "arm_general_register_operand" "")
563         (match_operand:SI 1 "const_int_operand" ""))
564    (set (match_dup 0)
565         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
566   "TARGET_THUMB
567    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
568    && (INTVAL (operands[1]) & 3) == 0"
569   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
570   ""
573 (define_insn "*addsi3_compare0"
574   [(set (reg:CC_NOOV CC_REGNUM)
575         (compare:CC_NOOV
576          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
577                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
578          (const_int 0)))
579    (set (match_operand:SI 0 "s_register_operand" "=r,r")
580         (plus:SI (match_dup 1) (match_dup 2)))]
581   "TARGET_ARM"
582   "@
583    add%?s\\t%0, %1, %2
584    sub%?s\\t%0, %1, #%n2"
585   [(set_attr "conds" "set")]
588 (define_insn "*addsi3_compare0_scratch"
589   [(set (reg:CC_NOOV CC_REGNUM)
590         (compare:CC_NOOV
591          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
592                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
593          (const_int 0)))]
594   "TARGET_ARM"
595   "@
596    cmn%?\\t%0, %1
597    cmp%?\\t%0, #%n1"
598   [(set_attr "conds" "set")]
601 (define_insn "*compare_negsi_si"
602   [(set (reg:CC_Z CC_REGNUM)
603         (compare:CC_Z
604          (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
605          (match_operand:SI 1 "s_register_operand" "r")))]
606   "TARGET_ARM"
607   "cmn%?\\t%1, %0"
608   [(set_attr "conds" "set")]
611 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
612 ;; addend is a constant.
613 (define_insn "*cmpsi2_addneg"
614   [(set (reg:CC CC_REGNUM)
615         (compare:CC
616          (match_operand:SI 1 "s_register_operand" "r,r")
617          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
618    (set (match_operand:SI 0 "s_register_operand" "=r,r")
619         (plus:SI (match_dup 1)
620                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
621   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
622   "@
623    sub%?s\\t%0, %1, %2
624    add%?s\\t%0, %1, #%n2"
625   [(set_attr "conds" "set")]
628 ;; Convert the sequence
629 ;;  sub  rd, rn, #1
630 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
631 ;;  bne  dest
632 ;; into
633 ;;  subs rd, rn, #1
634 ;;  bcs  dest   ((unsigned)rn >= 1)
635 ;; similarly for the beq variant using bcc.
636 ;; This is a common looping idiom (while (n--))
637 (define_peephole2
638   [(set (match_operand:SI 0 "arm_general_register_operand" "")
639         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
640                  (const_int -1)))
641    (set (match_operand 2 "cc_register" "")
642         (compare (match_dup 0) (const_int -1)))
643    (set (pc)
644         (if_then_else (match_operator 3 "equality_operator"
645                        [(match_dup 2) (const_int 0)])
646                       (match_operand 4 "" "")
647                       (match_operand 5 "" "")))]
648   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
649   [(parallel[
650     (set (match_dup 2)
651          (compare:CC
652           (match_dup 1) (const_int 1)))
653     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
654    (set (pc)
655         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
656                       (match_dup 4)
657                       (match_dup 5)))]
658   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
659    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
660                                   ? GEU : LTU),
661                                  VOIDmode, 
662                                  operands[2], const0_rtx);"
665 ;; The next four insns work because they compare the result with one of
666 ;; the operands, and we know that the use of the condition code is
667 ;; either GEU or LTU, so we can use the carry flag from the addition
668 ;; instead of doing the compare a second time.
669 (define_insn "*addsi3_compare_op1"
670   [(set (reg:CC_C CC_REGNUM)
671         (compare:CC_C
672          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
674          (match_dup 1)))
675    (set (match_operand:SI 0 "s_register_operand" "=r,r")
676         (plus:SI (match_dup 1) (match_dup 2)))]
677   "TARGET_ARM"
678   "@
679    add%?s\\t%0, %1, %2
680    sub%?s\\t%0, %1, #%n2"
681   [(set_attr "conds" "set")]
684 (define_insn "*addsi3_compare_op2"
685   [(set (reg:CC_C CC_REGNUM)
686         (compare:CC_C
687          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
688                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
689          (match_dup 2)))
690    (set (match_operand:SI 0 "s_register_operand" "=r,r")
691         (plus:SI (match_dup 1) (match_dup 2)))]
692   "TARGET_ARM"
693   "@
694    add%?s\\t%0, %1, %2
695    sub%?s\\t%0, %1, #%n2"
696   [(set_attr "conds" "set")]
699 (define_insn "*compare_addsi2_op0"
700   [(set (reg:CC_C CC_REGNUM)
701         (compare:CC_C
702          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
704          (match_dup 0)))]
705   "TARGET_ARM"
706   "@
707    cmn%?\\t%0, %1
708    cmp%?\\t%0, #%n1"
709   [(set_attr "conds" "set")]
712 (define_insn "*compare_addsi2_op1"
713   [(set (reg:CC_C CC_REGNUM)
714         (compare:CC_C
715          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
716                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
717          (match_dup 1)))]
718   "TARGET_ARM"
719   "@
720    cmn%?\\t%0, %1
721    cmp%?\\t%0, #%n1"
722   [(set_attr "conds" "set")]
725 (define_insn "*addsi3_carryin"
726   [(set (match_operand:SI 0 "s_register_operand" "=r")
727         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
728                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
729                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
730   "TARGET_ARM"
731   "adc%?\\t%0, %1, %2"
732   [(set_attr "conds" "use")]
735 (define_insn "*addsi3_carryin_shift"
736   [(set (match_operand:SI 0 "s_register_operand" "=r")
737         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
738                  (plus:SI
739                    (match_operator:SI 2 "shift_operator"
740                       [(match_operand:SI 3 "s_register_operand" "r")
741                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
742                     (match_operand:SI 1 "s_register_operand" "r"))))]
743   "TARGET_ARM"
744   "adc%?\\t%0, %1, %3%S2"
745   [(set_attr "conds" "use")
746    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
747                       (const_string "alu_shift")
748                       (const_string "alu_shift_reg")))]
751 (define_insn "*addsi3_carryin_alt1"
752   [(set (match_operand:SI 0 "s_register_operand" "=r")
753         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
754                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
755                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
756   "TARGET_ARM"
757   "adc%?\\t%0, %1, %2"
758   [(set_attr "conds" "use")]
761 (define_insn "*addsi3_carryin_alt2"
762   [(set (match_operand:SI 0 "s_register_operand" "=r")
763         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
764                           (match_operand:SI 1 "s_register_operand" "r"))
765                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
766   "TARGET_ARM"
767   "adc%?\\t%0, %1, %2"
768   [(set_attr "conds" "use")]
771 (define_insn "*addsi3_carryin_alt3"
772   [(set (match_operand:SI 0 "s_register_operand" "=r")
773         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
774                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
775                  (match_operand:SI 1 "s_register_operand" "r")))]
776   "TARGET_ARM"
777   "adc%?\\t%0, %1, %2"
778   [(set_attr "conds" "use")]
781 (define_insn "incscc"
782   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
783         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
784                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
785                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
786   "TARGET_ARM"
787   "@
788   add%d2\\t%0, %1, #1
789   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
790   [(set_attr "conds" "use")
791    (set_attr "length" "4,8")]
794 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
795 (define_split
796   [(set (match_operand:SI 0 "s_register_operand" "")
797         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
798                             (match_operand:SI 2 "s_register_operand" ""))
799                  (const_int -1)))
800    (clobber (match_operand:SI 3 "s_register_operand" ""))]
801   "TARGET_ARM"
802   [(set (match_dup 3) (match_dup 1))
803    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
804   "
805   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
808 (define_expand "addsf3"
809   [(set (match_operand:SF          0 "s_register_operand" "")
810         (plus:SF (match_operand:SF 1 "s_register_operand" "")
811                  (match_operand:SF 2 "arm_float_add_operand" "")))]
812   "TARGET_ARM && TARGET_HARD_FLOAT"
813   "
814   if (TARGET_MAVERICK
815       && !cirrus_fp_register (operands[2], SFmode))
816     operands[2] = force_reg (SFmode, operands[2]);
819 (define_expand "adddf3"
820   [(set (match_operand:DF          0 "s_register_operand" "")
821         (plus:DF (match_operand:DF 1 "s_register_operand" "")
822                  (match_operand:DF 2 "arm_float_add_operand" "")))]
823   "TARGET_ARM && TARGET_HARD_FLOAT"
824   "
825   if (TARGET_MAVERICK
826       && !cirrus_fp_register (operands[2], DFmode))
827     operands[2] = force_reg (DFmode, operands[2]);
830 (define_expand "subdi3"
831  [(parallel
832    [(set (match_operand:DI            0 "s_register_operand" "")
833           (minus:DI (match_operand:DI 1 "s_register_operand" "")
834                     (match_operand:DI 2 "s_register_operand" "")))
835     (clobber (reg:CC CC_REGNUM))])]
836   "TARGET_EITHER"
837   "
838   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
839       && TARGET_ARM
840       && cirrus_fp_register (operands[0], DImode)
841       && cirrus_fp_register (operands[1], DImode))
842     {
843       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
844       DONE;
845     }
847   if (TARGET_THUMB)
848     {
849       if (GET_CODE (operands[1]) != REG)
850         operands[1] = force_reg (SImode, operands[1]);
851       if (GET_CODE (operands[2]) != REG)
852         operands[2] = force_reg (SImode, operands[2]);
853      }  
854   "
857 (define_insn "*arm_subdi3"
858   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
859         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
860                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
861    (clobber (reg:CC CC_REGNUM))]
862   "TARGET_ARM"
863   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
864   [(set_attr "conds" "clob")
865    (set_attr "length" "8")]
868 (define_insn "*thumb_subdi3"
869   [(set (match_operand:DI           0 "register_operand" "=l")
870         (minus:DI (match_operand:DI 1 "register_operand"  "0")
871                   (match_operand:DI 2 "register_operand"  "l")))
872    (clobber (reg:CC CC_REGNUM))]
873   "TARGET_THUMB"
874   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
875   [(set_attr "length" "4")]
878 (define_insn "*subdi_di_zesidi"
879   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
880         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
881                   (zero_extend:DI
882                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
883    (clobber (reg:CC CC_REGNUM))]
884   "TARGET_ARM"
885   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
886   [(set_attr "conds" "clob")
887    (set_attr "length" "8")]
890 (define_insn "*subdi_di_sesidi"
891   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
892         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
893                   (sign_extend:DI
894                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
895    (clobber (reg:CC CC_REGNUM))]
896   "TARGET_ARM"
897   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
898   [(set_attr "conds" "clob")
899    (set_attr "length" "8")]
902 (define_insn "*subdi_zesidi_di"
903   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
904         (minus:DI (zero_extend:DI
905                    (match_operand:SI 2 "s_register_operand"  "r,r"))
906                   (match_operand:DI  1 "s_register_operand" "?r,0")))
907    (clobber (reg:CC CC_REGNUM))]
908   "TARGET_ARM"
909   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
910   [(set_attr "conds" "clob")
911    (set_attr "length" "8")]
914 (define_insn "*subdi_sesidi_di"
915   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
916         (minus:DI (sign_extend:DI
917                    (match_operand:SI 2 "s_register_operand"   "r,r"))
918                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
919    (clobber (reg:CC CC_REGNUM))]
920   "TARGET_ARM"
921   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
922   [(set_attr "conds" "clob")
923    (set_attr "length" "8")]
926 (define_insn "*subdi_zesidi_zesidi"
927   [(set (match_operand:DI            0 "s_register_operand" "=r")
928         (minus:DI (zero_extend:DI
929                    (match_operand:SI 1 "s_register_operand"  "r"))
930                   (zero_extend:DI
931                    (match_operand:SI 2 "s_register_operand"  "r"))))
932    (clobber (reg:CC CC_REGNUM))]
933   "TARGET_ARM"
934   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
935   [(set_attr "conds" "clob")
936    (set_attr "length" "8")]
939 (define_expand "subsi3"
940   [(set (match_operand:SI           0 "s_register_operand" "")
941         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
942                   (match_operand:SI 2 "s_register_operand" "")))]
943   "TARGET_EITHER"
944   "
945   if (GET_CODE (operands[1]) == CONST_INT)
946     {
947       if (TARGET_ARM)
948         {
949           arm_split_constant (MINUS, SImode, NULL_RTX,
950                               INTVAL (operands[1]), operands[0],
951                               operands[2], optimize && !no_new_pseudos);
952           DONE;
953         }
954       else /* TARGET_THUMB */
955         operands[1] = force_reg (SImode, operands[1]);
956     }
957   "
960 (define_insn "*thumb_subsi3_insn"
961   [(set (match_operand:SI           0 "register_operand" "=l")
962         (minus:SI (match_operand:SI 1 "register_operand" "l")
963                   (match_operand:SI 2 "register_operand" "l")))]
964   "TARGET_THUMB"
965   "sub\\t%0, %1, %2"
966   [(set_attr "length" "2")]
969 (define_insn_and_split "*arm_subsi3_insn"
970   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
971         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
972                   (match_operand:SI 2 "s_register_operand" "r,r")))]
973   "TARGET_ARM"
974   "@
975    rsb%?\\t%0, %2, %1
976    #"
977   "TARGET_ARM
978    && GET_CODE (operands[1]) == CONST_INT
979    && !const_ok_for_arm (INTVAL (operands[1]))"
980   [(clobber (const_int 0))]
981   "
982   arm_split_constant (MINUS, SImode, curr_insn,
983                       INTVAL (operands[1]), operands[0], operands[2], 0);
984   DONE;
985   "
986   [(set_attr "length" "4,16")
987    (set_attr "predicable" "yes")]
990 (define_peephole2
991   [(match_scratch:SI 3 "r")
992    (set (match_operand:SI 0 "arm_general_register_operand" "")
993         (minus:SI (match_operand:SI 1 "const_int_operand" "")
994                   (match_operand:SI 2 "arm_general_register_operand" "")))]
995   "TARGET_ARM
996    && !const_ok_for_arm (INTVAL (operands[1]))
997    && const_ok_for_arm (~INTVAL (operands[1]))"
998   [(set (match_dup 3) (match_dup 1))
999    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1000   ""
1003 (define_insn "*subsi3_compare0"
1004   [(set (reg:CC_NOOV CC_REGNUM)
1005         (compare:CC_NOOV
1006          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1007                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1008          (const_int 0)))
1009    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1010         (minus:SI (match_dup 1) (match_dup 2)))]
1011   "TARGET_ARM"
1012   "@
1013    sub%?s\\t%0, %1, %2
1014    rsb%?s\\t%0, %2, %1"
1015   [(set_attr "conds" "set")]
1018 (define_insn "decscc"
1019   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1020         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1021                   (match_operator:SI 2 "arm_comparison_operator"
1022                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1023   "TARGET_ARM"
1024   "@
1025    sub%d2\\t%0, %1, #1
1026    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1027   [(set_attr "conds" "use")
1028    (set_attr "length" "*,8")]
1031 (define_expand "subsf3"
1032   [(set (match_operand:SF           0 "s_register_operand" "")
1033         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1034                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1035   "TARGET_ARM && TARGET_HARD_FLOAT"
1036   "
1037   if (TARGET_MAVERICK)
1038     {
1039       if (!cirrus_fp_register (operands[1], SFmode))
1040         operands[1] = force_reg (SFmode, operands[1]);
1041       if (!cirrus_fp_register (operands[2], SFmode))
1042         operands[2] = force_reg (SFmode, operands[2]);
1043     }
1046 (define_expand "subdf3"
1047   [(set (match_operand:DF           0 "s_register_operand" "")
1048         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1049                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1050   "TARGET_ARM && TARGET_HARD_FLOAT"
1051   "
1052   if (TARGET_MAVERICK)
1053     {
1054        if (!cirrus_fp_register (operands[1], DFmode))
1055          operands[1] = force_reg (DFmode, operands[1]);
1056        if (!cirrus_fp_register (operands[2], DFmode))
1057          operands[2] = force_reg (DFmode, operands[2]);
1058     }
1062 ;; Multiplication insns
1064 (define_expand "mulsi3"
1065   [(set (match_operand:SI          0 "s_register_operand" "")
1066         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1067                  (match_operand:SI 1 "s_register_operand" "")))]
1068   "TARGET_EITHER"
1069   ""
1072 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1073 (define_insn "*arm_mulsi3"
1074   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1075         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1076                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1077   "TARGET_ARM"
1078   "mul%?\\t%0, %2, %1"
1079   [(set_attr "insn" "mul")
1080    (set_attr "predicable" "yes")]
1083 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1084 ; 1 and 2; are the same, because reload will make operand 0 match 
1085 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1086 ; this by adding another alternative to match this case, and then `reload' 
1087 ; it ourselves.  This alternative must come first.
1088 (define_insn "*thumb_mulsi3"
1089   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1090         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1091                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1092   "TARGET_THUMB"
1093   "*
1094   if (which_alternative < 2)
1095     return \"mov\\t%0, %1\;mul\\t%0, %2\";
1096   else
1097     return \"mul\\t%0, %2\";
1098   "
1099   [(set_attr "length" "4,4,2")
1100    (set_attr "insn" "mul")]
1103 (define_insn "*mulsi3_compare0"
1104   [(set (reg:CC_NOOV CC_REGNUM)
1105         (compare:CC_NOOV (mult:SI
1106                           (match_operand:SI 2 "s_register_operand" "r,r")
1107                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1108                          (const_int 0)))
1109    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1110         (mult:SI (match_dup 2) (match_dup 1)))]
1111   "TARGET_ARM"
1112   "mul%?s\\t%0, %2, %1"
1113   [(set_attr "conds" "set")
1114    (set_attr "insn" "muls")]
1117 (define_insn "*mulsi_compare0_scratch"
1118   [(set (reg:CC_NOOV CC_REGNUM)
1119         (compare:CC_NOOV (mult:SI
1120                           (match_operand:SI 2 "s_register_operand" "r,r")
1121                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1122                          (const_int 0)))
1123    (clobber (match_scratch:SI 0 "=&r,&r"))]
1124   "TARGET_ARM"
1125   "mul%?s\\t%0, %2, %1"
1126   [(set_attr "conds" "set")
1127    (set_attr "insn" "muls")]
1130 ;; Unnamed templates to match MLA instruction.
1132 (define_insn "*mulsi3addsi"
1133   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1134         (plus:SI
1135           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1136                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1137           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1138   "TARGET_ARM"
1139   "mla%?\\t%0, %2, %1, %3"
1140   [(set_attr "insn" "mla")
1141    (set_attr "predicable" "yes")]
1144 (define_insn "*mulsi3addsi_compare0"
1145   [(set (reg:CC_NOOV CC_REGNUM)
1146         (compare:CC_NOOV
1147          (plus:SI (mult:SI
1148                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1149                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1150                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1151          (const_int 0)))
1152    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1153         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1154                  (match_dup 3)))]
1155   "TARGET_ARM"
1156   "mla%?s\\t%0, %2, %1, %3"
1157   [(set_attr "conds" "set")
1158    (set_attr "insn" "mlas")]
1161 (define_insn "*mulsi3addsi_compare0_scratch"
1162   [(set (reg:CC_NOOV CC_REGNUM)
1163         (compare:CC_NOOV
1164          (plus:SI (mult:SI
1165                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1166                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1167                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1168          (const_int 0)))
1169    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1170   "TARGET_ARM"
1171   "mla%?s\\t%0, %2, %1, %3"
1172   [(set_attr "conds" "set")
1173    (set_attr "insn" "mlas")]
1176 ;; Unnamed template to match long long multiply-accumulate (smlal)
1178 (define_insn "*mulsidi3adddi"
1179   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1180         (plus:DI
1181          (mult:DI
1182           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1183           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1184          (match_operand:DI 1 "s_register_operand" "0")))]
1185   "TARGET_ARM && arm_arch3m"
1186   "smlal%?\\t%Q0, %R0, %3, %2"
1187   [(set_attr "insn" "smlal")
1188    (set_attr "predicable" "yes")]
1191 (define_insn "mulsidi3"
1192   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1193         (mult:DI
1194          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1196   "TARGET_ARM && arm_arch3m"
1197   "smull%?\\t%Q0, %R0, %1, %2"
1198   [(set_attr "insn" "smull")
1199    (set_attr "predicable" "yes")]
1202 (define_insn "umulsidi3"
1203   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1204         (mult:DI
1205          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1206          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1207   "TARGET_ARM && arm_arch3m"
1208   "umull%?\\t%Q0, %R0, %1, %2"
1209   [(set_attr "insn" "umull")
1210    (set_attr "predicable" "yes")]
1213 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1215 (define_insn "*umulsidi3adddi"
1216   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1217         (plus:DI
1218          (mult:DI
1219           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1220           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1221          (match_operand:DI 1 "s_register_operand" "0")))]
1222   "TARGET_ARM && arm_arch3m"
1223   "umlal%?\\t%Q0, %R0, %3, %2"
1224   [(set_attr "insn" "umlal")
1225    (set_attr "predicable" "yes")]
1228 (define_insn "smulsi3_highpart"
1229   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1230         (truncate:SI
1231          (lshiftrt:DI
1232           (mult:DI
1233            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1234            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1235           (const_int 32))))
1236    (clobber (match_scratch:SI 3 "=&r,&r"))]
1237   "TARGET_ARM && arm_arch3m"
1238   "smull%?\\t%3, %0, %2, %1"
1239   [(set_attr "insn" "smull")
1240    (set_attr "predicable" "yes")]
1243 (define_insn "umulsi3_highpart"
1244   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1245         (truncate:SI
1246          (lshiftrt:DI
1247           (mult:DI
1248            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1249            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1250           (const_int 32))))
1251    (clobber (match_scratch:SI 3 "=&r,&r"))]
1252   "TARGET_ARM && arm_arch3m"
1253   "umull%?\\t%3, %0, %2, %1"
1254   [(set_attr "insn" "umull")
1255    (set_attr "predicable" "yes")]
1258 (define_insn "mulhisi3"
1259   [(set (match_operand:SI 0 "s_register_operand" "=r")
1260         (mult:SI (sign_extend:SI
1261                   (match_operand:HI 1 "s_register_operand" "%r"))
1262                  (sign_extend:SI
1263                   (match_operand:HI 2 "s_register_operand" "r"))))]
1264   "TARGET_ARM && arm_arch5e"
1265   "smulbb%?\\t%0, %1, %2"
1266   [(set_attr "insn" "smulxy")
1267    (set_attr "predicable" "yes")]
1270 (define_insn "*mulhisi3tb"
1271   [(set (match_operand:SI 0 "s_register_operand" "=r")
1272         (mult:SI (ashiftrt:SI
1273                   (match_operand:SI 1 "s_register_operand" "r")
1274                   (const_int 16))
1275                  (sign_extend:SI
1276                   (match_operand:HI 2 "s_register_operand" "r"))))]
1277   "TARGET_ARM && arm_arch5e"
1278   "smultb%?\\t%0, %1, %2"
1279   [(set_attr "insn" "smulxy")
1280    (set_attr "predicable" "yes")]
1283 (define_insn "*mulhisi3bt"
1284   [(set (match_operand:SI 0 "s_register_operand" "=r")
1285         (mult:SI (sign_extend:SI
1286                   (match_operand:HI 1 "s_register_operand" "r"))
1287                  (ashiftrt:SI
1288                   (match_operand:SI 2 "s_register_operand" "r")
1289                   (const_int 16))))]
1290   "TARGET_ARM && arm_arch5e"
1291   "smulbt%?\\t%0, %1, %2"
1292   [(set_attr "insn" "smulxy")
1293    (set_attr "predicable" "yes")]
1296 (define_insn "*mulhisi3tt"
1297   [(set (match_operand:SI 0 "s_register_operand" "=r")
1298         (mult:SI (ashiftrt:SI
1299                   (match_operand:SI 1 "s_register_operand" "r")
1300                   (const_int 16))
1301                  (ashiftrt:SI
1302                   (match_operand:SI 2 "s_register_operand" "r")
1303                   (const_int 16))))]
1304   "TARGET_ARM && arm_arch5e"
1305   "smultt%?\\t%0, %1, %2"
1306   [(set_attr "insn" "smulxy")
1307    (set_attr "predicable" "yes")]
1310 (define_insn "*mulhisi3addsi"
1311   [(set (match_operand:SI 0 "s_register_operand" "=r")
1312         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1313                  (mult:SI (sign_extend:SI
1314                            (match_operand:HI 2 "s_register_operand" "%r"))
1315                           (sign_extend:SI
1316                            (match_operand:HI 3 "s_register_operand" "r")))))]
1317   "TARGET_ARM && arm_arch5e"
1318   "smlabb%?\\t%0, %2, %3, %1"
1319   [(set_attr "insn" "smlaxy")
1320    (set_attr "predicable" "yes")]
1323 (define_insn "*mulhidi3adddi"
1324   [(set (match_operand:DI 0 "s_register_operand" "=r")
1325         (plus:DI
1326           (match_operand:DI 1 "s_register_operand" "0")
1327           (mult:DI (sign_extend:DI
1328                     (match_operand:HI 2 "s_register_operand" "%r"))
1329                    (sign_extend:DI
1330                     (match_operand:HI 3 "s_register_operand" "r")))))]
1331   "TARGET_ARM && arm_arch5e"
1332   "smlalbb%?\\t%Q0, %R0, %2, %3"
1333   [(set_attr "insn" "smlalxy")
1334    (set_attr "predicable" "yes")])
1336 (define_expand "mulsf3"
1337   [(set (match_operand:SF          0 "s_register_operand" "")
1338         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1339                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1340   "TARGET_ARM && TARGET_HARD_FLOAT"
1341   "
1342   if (TARGET_MAVERICK
1343       && !cirrus_fp_register (operands[2], SFmode))
1344     operands[2] = force_reg (SFmode, operands[2]);
1347 (define_expand "muldf3"
1348   [(set (match_operand:DF          0 "s_register_operand" "")
1349         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1350                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1351   "TARGET_ARM && TARGET_HARD_FLOAT"
1352   "
1353   if (TARGET_MAVERICK
1354       && !cirrus_fp_register (operands[2], DFmode))
1355     operands[2] = force_reg (DFmode, operands[2]);
1358 ;; Division insns
1360 (define_expand "divsf3"
1361   [(set (match_operand:SF 0 "s_register_operand" "")
1362         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1363                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1364   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1365   "")
1367 (define_expand "divdf3"
1368   [(set (match_operand:DF 0 "s_register_operand" "")
1369         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1370                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1371   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1372   "")
1374 ;; Modulo insns
1376 (define_expand "modsf3"
1377   [(set (match_operand:SF 0 "s_register_operand" "")
1378         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1379                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1380   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1381   "")
1383 (define_expand "moddf3"
1384   [(set (match_operand:DF 0 "s_register_operand" "")
1385         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1386                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1387   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1388   "")
1390 ;; Boolean and,ior,xor insns
1392 ;; Split up double word logical operations
1394 ;; Split up simple DImode logical operations.  Simply perform the logical
1395 ;; operation on the upper and lower halves of the registers.
1396 (define_split
1397   [(set (match_operand:DI 0 "s_register_operand" "")
1398         (match_operator:DI 6 "logical_binary_operator"
1399           [(match_operand:DI 1 "s_register_operand" "")
1400            (match_operand:DI 2 "s_register_operand" "")]))]
1401   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1402   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1403    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1404   "
1405   {
1406     operands[3] = gen_highpart (SImode, operands[0]);
1407     operands[0] = gen_lowpart (SImode, operands[0]);
1408     operands[4] = gen_highpart (SImode, operands[1]);
1409     operands[1] = gen_lowpart (SImode, operands[1]);
1410     operands[5] = gen_highpart (SImode, operands[2]);
1411     operands[2] = gen_lowpart (SImode, operands[2]);
1412   }"
1415 (define_split
1416   [(set (match_operand:DI 0 "s_register_operand" "")
1417         (match_operator:DI 6 "logical_binary_operator"
1418           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1419            (match_operand:DI 1 "s_register_operand" "")]))]
1420   "TARGET_ARM && reload_completed"
1421   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1422    (set (match_dup 3) (match_op_dup:SI 6
1423                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1424                          (match_dup 4)]))]
1425   "
1426   {
1427     operands[3] = gen_highpart (SImode, operands[0]);
1428     operands[0] = gen_lowpart (SImode, operands[0]);
1429     operands[4] = gen_highpart (SImode, operands[1]);
1430     operands[1] = gen_lowpart (SImode, operands[1]);
1431     operands[5] = gen_highpart (SImode, operands[2]);
1432     operands[2] = gen_lowpart (SImode, operands[2]);
1433   }"
1436 ;; The zero extend of operand 2 means we can just copy the high part of
1437 ;; operand1 into operand0.
1438 (define_split
1439   [(set (match_operand:DI 0 "s_register_operand" "")
1440         (ior:DI
1441           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1442           (match_operand:DI 1 "s_register_operand" "")))]
1443   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1444   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1445    (set (match_dup 3) (match_dup 4))]
1446   "
1447   {
1448     operands[4] = gen_highpart (SImode, operands[1]);
1449     operands[3] = gen_highpart (SImode, operands[0]);
1450     operands[0] = gen_lowpart (SImode, operands[0]);
1451     operands[1] = gen_lowpart (SImode, operands[1]);
1452   }"
1455 ;; The zero extend of operand 2 means we can just copy the high part of
1456 ;; operand1 into operand0.
1457 (define_split
1458   [(set (match_operand:DI 0 "s_register_operand" "")
1459         (xor:DI
1460           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1461           (match_operand:DI 1 "s_register_operand" "")))]
1462   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1463   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1464    (set (match_dup 3) (match_dup 4))]
1465   "
1466   {
1467     operands[4] = gen_highpart (SImode, operands[1]);
1468     operands[3] = gen_highpart (SImode, operands[0]);
1469     operands[0] = gen_lowpart (SImode, operands[0]);
1470     operands[1] = gen_lowpart (SImode, operands[1]);
1471   }"
1474 (define_insn "anddi3"
1475   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1476         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1477                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1478   "TARGET_ARM && ! TARGET_IWMMXT"
1479   "#"
1480   [(set_attr "length" "8")]
1483 (define_insn_and_split "*anddi_zesidi_di"
1484   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1485         (and:DI (zero_extend:DI
1486                  (match_operand:SI 2 "s_register_operand" "r,r"))
1487                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1488   "TARGET_ARM"
1489   "#"
1490   "TARGET_ARM && reload_completed"
1491   ; The zero extend of operand 2 clears the high word of the output
1492   ; operand.
1493   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1494    (set (match_dup 3) (const_int 0))]
1495   "
1496   {
1497     operands[3] = gen_highpart (SImode, operands[0]);
1498     operands[0] = gen_lowpart (SImode, operands[0]);
1499     operands[1] = gen_lowpart (SImode, operands[1]);
1500   }"
1501   [(set_attr "length" "8")]
1504 (define_insn "*anddi_sesdi_di"
1505   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1506         (and:DI (sign_extend:DI
1507                  (match_operand:SI 2 "s_register_operand" "r,r"))
1508                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1509   "TARGET_ARM"
1510   "#"
1511   [(set_attr "length" "8")]
1514 (define_expand "andsi3"
1515   [(set (match_operand:SI         0 "s_register_operand" "")
1516         (and:SI (match_operand:SI 1 "s_register_operand" "")
1517                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1518   "TARGET_EITHER"
1519   "
1520   if (TARGET_ARM)
1521     {
1522       if (GET_CODE (operands[2]) == CONST_INT)
1523         {
1524           arm_split_constant (AND, SImode, NULL_RTX,
1525                               INTVAL (operands[2]), operands[0],
1526                               operands[1], optimize && !no_new_pseudos);
1528           DONE;
1529         }
1530     }
1531   else /* TARGET_THUMB */
1532     {
1533       if (GET_CODE (operands[2]) != CONST_INT)
1534         operands[2] = force_reg (SImode, operands[2]);
1535       else
1536         {
1537           int i;
1538           
1539           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1540             {
1541               operands[2] = force_reg (SImode,
1542                                        GEN_INT (~INTVAL (operands[2])));
1543               
1544               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1545               
1546               DONE;
1547             }
1549           for (i = 9; i <= 31; i++)
1550             {
1551               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1552                 {
1553                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1554                                         const0_rtx));
1555                   DONE;
1556                 }
1557               else if ((((HOST_WIDE_INT) 1) << i) - 1
1558                        == ~INTVAL (operands[2]))
1559                 {
1560                   rtx shift = GEN_INT (i);
1561                   rtx reg = gen_reg_rtx (SImode);
1562                 
1563                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1564                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1565                   
1566                   DONE;
1567                 }
1568             }
1570           operands[2] = force_reg (SImode, operands[2]);
1571         }
1572     }
1573   "
1576 (define_insn_and_split "*arm_andsi3_insn"
1577   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1578         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1579                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1580   "TARGET_ARM"
1581   "@
1582    and%?\\t%0, %1, %2
1583    bic%?\\t%0, %1, #%B2
1584    #"
1585   "TARGET_ARM
1586    && GET_CODE (operands[2]) == CONST_INT
1587    && !(const_ok_for_arm (INTVAL (operands[2]))
1588         || const_ok_for_arm (~INTVAL (operands[2])))"
1589   [(clobber (const_int 0))]
1590   "
1591   arm_split_constant  (AND, SImode, curr_insn, 
1592                        INTVAL (operands[2]), operands[0], operands[1], 0);
1593   DONE;
1594   "
1595   [(set_attr "length" "4,4,16")
1596    (set_attr "predicable" "yes")]
1599 (define_insn "*thumb_andsi3_insn"
1600   [(set (match_operand:SI         0 "register_operand" "=l")
1601         (and:SI (match_operand:SI 1 "register_operand" "%0")
1602                 (match_operand:SI 2 "register_operand" "l")))]
1603   "TARGET_THUMB"
1604   "and\\t%0, %0, %2"
1605   [(set_attr "length" "2")]
1608 (define_insn "*andsi3_compare0"
1609   [(set (reg:CC_NOOV CC_REGNUM)
1610         (compare:CC_NOOV
1611          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1612                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1613          (const_int 0)))
1614    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1615         (and:SI (match_dup 1) (match_dup 2)))]
1616   "TARGET_ARM"
1617   "@
1618    and%?s\\t%0, %1, %2
1619    bic%?s\\t%0, %1, #%B2"
1620   [(set_attr "conds" "set")]
1623 (define_insn "*andsi3_compare0_scratch"
1624   [(set (reg:CC_NOOV CC_REGNUM)
1625         (compare:CC_NOOV
1626          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1627                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1628          (const_int 0)))
1629    (clobber (match_scratch:SI 2 "=X,r"))]
1630   "TARGET_ARM"
1631   "@
1632    tst%?\\t%0, %1
1633    bic%?s\\t%2, %0, #%B1"
1634   [(set_attr "conds" "set")]
1637 (define_insn "*zeroextractsi_compare0_scratch"
1638   [(set (reg:CC_NOOV CC_REGNUM)
1639         (compare:CC_NOOV (zero_extract:SI
1640                           (match_operand:SI 0 "s_register_operand" "r")
1641                           (match_operand 1 "const_int_operand" "n")
1642                           (match_operand 2 "const_int_operand" "n"))
1643                          (const_int 0)))]
1644   "TARGET_ARM
1645   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1646       && INTVAL (operands[1]) > 0 
1647       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1648       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1649   "*
1650   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1651                          << INTVAL (operands[2]));
1652   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1653   return \"\";
1654   "
1655   [(set_attr "conds" "set")]
1658 (define_insn_and_split "*ne_zeroextractsi"
1659   [(set (match_operand:SI 0 "s_register_operand" "=r")
1660         (ne:SI (zero_extract:SI
1661                 (match_operand:SI 1 "s_register_operand" "r")
1662                 (match_operand:SI 2 "const_int_operand" "n")
1663                 (match_operand:SI 3 "const_int_operand" "n"))
1664                (const_int 0)))
1665    (clobber (reg:CC CC_REGNUM))]
1666   "TARGET_ARM
1667    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1668        && INTVAL (operands[2]) > 0 
1669        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1670        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1671   "#"
1672   "TARGET_ARM
1673    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1674        && INTVAL (operands[2]) > 0 
1675        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1676        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1677   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1678                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1679                                     (const_int 0)))
1680               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1681    (set (match_dup 0)
1682         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1683                          (match_dup 0) (const_int 1)))]
1684   "
1685   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1686                          << INTVAL (operands[3])); 
1687   "
1688   [(set_attr "conds" "clob")
1689    (set_attr "length" "8")]
1692 (define_insn_and_split "*ne_zeroextractsi_shifted"
1693   [(set (match_operand:SI 0 "s_register_operand" "=r")
1694         (ne:SI (zero_extract:SI
1695                 (match_operand:SI 1 "s_register_operand" "r")
1696                 (match_operand:SI 2 "const_int_operand" "n")
1697                 (const_int 0))
1698                (const_int 0)))
1699    (clobber (reg:CC CC_REGNUM))]
1700   "TARGET_ARM"
1701   "#"
1702   "TARGET_ARM"
1703   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1704                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1705                                     (const_int 0)))
1706               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1707    (set (match_dup 0)
1708         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1709                          (match_dup 0) (const_int 1)))]
1710   "
1711   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1712   "
1713   [(set_attr "conds" "clob")
1714    (set_attr "length" "8")]
1717 (define_insn_and_split "*ite_ne_zeroextractsi"
1718   [(set (match_operand:SI 0 "s_register_operand" "=r")
1719         (if_then_else:SI (ne (zero_extract:SI
1720                               (match_operand:SI 1 "s_register_operand" "r")
1721                               (match_operand:SI 2 "const_int_operand" "n")
1722                               (match_operand:SI 3 "const_int_operand" "n"))
1723                              (const_int 0))
1724                          (match_operand:SI 4 "arm_not_operand" "rIK")
1725                          (const_int 0)))
1726    (clobber (reg:CC CC_REGNUM))]
1727   "TARGET_ARM
1728    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1729        && INTVAL (operands[2]) > 0 
1730        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1731        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1732    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1733   "#"
1734   "TARGET_ARM
1735    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1736        && INTVAL (operands[2]) > 0 
1737        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1738        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1739    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1740   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1741                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1742                                     (const_int 0)))
1743               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1744    (set (match_dup 0)
1745         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1746                          (match_dup 0) (match_dup 4)))]
1747   "
1748   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1749                          << INTVAL (operands[3])); 
1750   "
1751   [(set_attr "conds" "clob")
1752    (set_attr "length" "8")]
1755 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1756   [(set (match_operand:SI 0 "s_register_operand" "=r")
1757         (if_then_else:SI (ne (zero_extract:SI
1758                               (match_operand:SI 1 "s_register_operand" "r")
1759                               (match_operand:SI 2 "const_int_operand" "n")
1760                               (const_int 0))
1761                              (const_int 0))
1762                          (match_operand:SI 3 "arm_not_operand" "rIK")
1763                          (const_int 0)))
1764    (clobber (reg:CC CC_REGNUM))]
1765   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1766   "#"
1767   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1768   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1769                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1770                                     (const_int 0)))
1771               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1772    (set (match_dup 0)
1773         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1774                          (match_dup 0) (match_dup 3)))]
1775   "
1776   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1777   "
1778   [(set_attr "conds" "clob")
1779    (set_attr "length" "8")]
1782 (define_split
1783   [(set (match_operand:SI 0 "s_register_operand" "")
1784         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1785                          (match_operand:SI 2 "const_int_operand" "")
1786                          (match_operand:SI 3 "const_int_operand" "")))
1787    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1788   "TARGET_THUMB"
1789   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1790    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1791   "{
1792      HOST_WIDE_INT temp = INTVAL (operands[2]);
1794      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1795      operands[3] = GEN_INT (32 - temp);
1796    }"
1799 (define_split
1800   [(set (match_operand:SI 0 "s_register_operand" "")
1801         (match_operator:SI 1 "shiftable_operator"
1802          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1803                            (match_operand:SI 3 "const_int_operand" "")
1804                            (match_operand:SI 4 "const_int_operand" ""))
1805           (match_operand:SI 5 "s_register_operand" "")]))
1806    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1807   "TARGET_ARM"
1808   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1809    (set (match_dup 0)
1810         (match_op_dup 1
1811          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1812           (match_dup 5)]))]
1813   "{
1814      HOST_WIDE_INT temp = INTVAL (operands[3]);
1816      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1817      operands[4] = GEN_INT (32 - temp);
1818    }"
1820   
1821 (define_split
1822   [(set (match_operand:SI 0 "s_register_operand" "")
1823         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1824                          (match_operand:SI 2 "const_int_operand" "")
1825                          (match_operand:SI 3 "const_int_operand" "")))]
1826   "TARGET_THUMB"
1827   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1828    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1829   "{
1830      HOST_WIDE_INT temp = INTVAL (operands[2]);
1832      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1833      operands[3] = GEN_INT (32 - temp);
1834    }"
1837 (define_split
1838   [(set (match_operand:SI 0 "s_register_operand" "")
1839         (match_operator:SI 1 "shiftable_operator"
1840          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1841                            (match_operand:SI 3 "const_int_operand" "")
1842                            (match_operand:SI 4 "const_int_operand" ""))
1843           (match_operand:SI 5 "s_register_operand" "")]))
1844    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1845   "TARGET_ARM"
1846   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1847    (set (match_dup 0)
1848         (match_op_dup 1
1849          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1850           (match_dup 5)]))]
1851   "{
1852      HOST_WIDE_INT temp = INTVAL (operands[3]);
1854      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1855      operands[4] = GEN_INT (32 - temp);
1856    }"
1858   
1859 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1860 ;;; represented by the bitfield, then this will produce incorrect results.
1861 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1862 ;;; which have a real bit-field insert instruction, the truncation happens
1863 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1864 ;;; bit-field insert instruction, we would have to emit code here to truncate
1865 ;;; the value before we insert.  This loses some of the advantage of having
1866 ;;; this insv pattern, so this pattern needs to be reevalutated.
1868 (define_expand "insv"
1869   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1870                          (match_operand:SI 1 "general_operand" "")
1871                          (match_operand:SI 2 "general_operand" ""))
1872         (match_operand:SI 3 "reg_or_int_operand" ""))]
1873   "TARGET_ARM"
1874   "
1875   {
1876     int start_bit = INTVAL (operands[2]);
1877     int width = INTVAL (operands[1]);
1878     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1879     rtx target, subtarget;
1881     target = operands[0];
1882     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1883        subreg as the final target.  */
1884     if (GET_CODE (target) == SUBREG)
1885       {
1886         subtarget = gen_reg_rtx (SImode);
1887         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1888             < GET_MODE_SIZE (SImode))
1889           target = SUBREG_REG (target);
1890       }
1891     else
1892       subtarget = target;    
1894     if (GET_CODE (operands[3]) == CONST_INT)
1895       {
1896         /* Since we are inserting a known constant, we may be able to
1897            reduce the number of bits that we have to clear so that
1898            the mask becomes simple.  */
1899         /* ??? This code does not check to see if the new mask is actually
1900            simpler.  It may not be.  */
1901         rtx op1 = gen_reg_rtx (SImode);
1902         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1903            start of this pattern.  */
1904         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1905         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1907         emit_insn (gen_andsi3 (op1, operands[0],
1908                                gen_int_mode (~mask2, SImode)));
1909         emit_insn (gen_iorsi3 (subtarget, op1,
1910                                gen_int_mode (op3_value << start_bit, SImode)));
1911       }
1912     else if (start_bit == 0
1913              && !(const_ok_for_arm (mask)
1914                   || const_ok_for_arm (~mask)))
1915       {
1916         /* A Trick, since we are setting the bottom bits in the word,
1917            we can shift operand[3] up, operand[0] down, OR them together
1918            and rotate the result back again.  This takes 3 insns, and
1919            the third might be mergeable into another op.  */
1920         /* The shift up copes with the possibility that operand[3] is
1921            wider than the bitfield.  */
1922         rtx op0 = gen_reg_rtx (SImode);
1923         rtx op1 = gen_reg_rtx (SImode);
1925         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1926         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1927         emit_insn (gen_iorsi3  (op1, op1, op0));
1928         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1929       }
1930     else if ((width + start_bit == 32)
1931              && !(const_ok_for_arm (mask)
1932                   || const_ok_for_arm (~mask)))
1933       {
1934         /* Similar trick, but slightly less efficient.  */
1936         rtx op0 = gen_reg_rtx (SImode);
1937         rtx op1 = gen_reg_rtx (SImode);
1939         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1940         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1941         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1942         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1943       }
1944     else
1945       {
1946         rtx op0 = gen_int_mode (mask, SImode);
1947         rtx op1 = gen_reg_rtx (SImode);
1948         rtx op2 = gen_reg_rtx (SImode);
1950         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1951           {
1952             rtx tmp = gen_reg_rtx (SImode);
1954             emit_insn (gen_movsi (tmp, op0));
1955             op0 = tmp;
1956           }
1958         /* Mask out any bits in operand[3] that are not needed.  */
1959            emit_insn (gen_andsi3 (op1, operands[3], op0));
1961         if (GET_CODE (op0) == CONST_INT
1962             && (const_ok_for_arm (mask << start_bit)
1963                 || const_ok_for_arm (~(mask << start_bit))))
1964           {
1965             op0 = gen_int_mode (~(mask << start_bit), SImode);
1966             emit_insn (gen_andsi3 (op2, operands[0], op0));
1967           }
1968         else
1969           {
1970             if (GET_CODE (op0) == CONST_INT)
1971               {
1972                 rtx tmp = gen_reg_rtx (SImode);
1974                 emit_insn (gen_movsi (tmp, op0));
1975                 op0 = tmp;
1976               }
1978             if (start_bit != 0)
1979               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1980             
1981             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1982           }
1984         if (start_bit != 0)
1985           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1987         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1988       }
1990     if (subtarget != target)
1991       {
1992         /* If TARGET is still a SUBREG, then it must be wider than a word,
1993            so we must be careful only to set the subword we were asked to.  */
1994         if (GET_CODE (target) == SUBREG)
1995           emit_move_insn (target, subtarget);
1996         else
1997           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1998       }
2000     DONE;
2001   }"
2004 ; constants for op 2 will never be given to these patterns.
2005 (define_insn_and_split "*anddi_notdi_di"
2006   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2007         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2008                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2009   "TARGET_ARM"
2010   "#"
2011   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2012   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2013    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2014   "
2015   {
2016     operands[3] = gen_highpart (SImode, operands[0]);
2017     operands[0] = gen_lowpart (SImode, operands[0]);
2018     operands[4] = gen_highpart (SImode, operands[1]);
2019     operands[1] = gen_lowpart (SImode, operands[1]);
2020     operands[5] = gen_highpart (SImode, operands[2]);
2021     operands[2] = gen_lowpart (SImode, operands[2]);
2022   }"
2023   [(set_attr "length" "8")
2024    (set_attr "predicable" "yes")]
2026   
2027 (define_insn_and_split "*anddi_notzesidi_di"
2028   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2029         (and:DI (not:DI (zero_extend:DI
2030                          (match_operand:SI 2 "s_register_operand" "r,r")))
2031                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2032   "TARGET_ARM"
2033   "@
2034    bic%?\\t%Q0, %Q1, %2
2035    #"
2036   ; (not (zero_extend ...)) allows us to just copy the high word from
2037   ; operand1 to operand0.
2038   "TARGET_ARM
2039    && reload_completed
2040    && operands[0] != operands[1]"
2041   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2042    (set (match_dup 3) (match_dup 4))]
2043   "
2044   {
2045     operands[3] = gen_highpart (SImode, operands[0]);
2046     operands[0] = gen_lowpart (SImode, operands[0]);
2047     operands[4] = gen_highpart (SImode, operands[1]);
2048     operands[1] = gen_lowpart (SImode, operands[1]);
2049   }"
2050   [(set_attr "length" "4,8")
2051    (set_attr "predicable" "yes")]
2053   
2054 (define_insn_and_split "*anddi_notsesidi_di"
2055   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2056         (and:DI (not:DI (sign_extend:DI
2057                          (match_operand:SI 2 "s_register_operand" "r,r")))
2058                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2059   "TARGET_ARM"
2060   "#"
2061   "TARGET_ARM && reload_completed"
2062   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2063    (set (match_dup 3) (and:SI (not:SI
2064                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2065                                (match_dup 4)))]
2066   "
2067   {
2068     operands[3] = gen_highpart (SImode, operands[0]);
2069     operands[0] = gen_lowpart (SImode, operands[0]);
2070     operands[4] = gen_highpart (SImode, operands[1]);
2071     operands[1] = gen_lowpart (SImode, operands[1]);
2072   }"
2073   [(set_attr "length" "8")
2074    (set_attr "predicable" "yes")]
2076   
2077 (define_insn "andsi_notsi_si"
2078   [(set (match_operand:SI 0 "s_register_operand" "=r")
2079         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080                 (match_operand:SI 1 "s_register_operand" "r")))]
2081   "TARGET_ARM"
2082   "bic%?\\t%0, %1, %2"
2083   [(set_attr "predicable" "yes")]
2086 (define_insn "bicsi3"
2087   [(set (match_operand:SI                 0 "register_operand" "=l")
2088         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2089                 (match_operand:SI         2 "register_operand" "0")))]
2090   "TARGET_THUMB"
2091   "bic\\t%0, %0, %1"
2092   [(set_attr "length" "2")]
2095 (define_insn "andsi_not_shiftsi_si"
2096   [(set (match_operand:SI 0 "s_register_operand" "=r")
2097         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2098                          [(match_operand:SI 2 "s_register_operand" "r")
2099                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2100                 (match_operand:SI 1 "s_register_operand" "r")))]
2101   "TARGET_ARM"
2102   "bic%?\\t%0, %1, %2%S4"
2103   [(set_attr "predicable" "yes")
2104    (set_attr "shift" "2")
2105    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2106                       (const_string "alu_shift")
2107                       (const_string "alu_shift_reg")))]
2110 (define_insn "*andsi_notsi_si_compare0"
2111   [(set (reg:CC_NOOV CC_REGNUM)
2112         (compare:CC_NOOV
2113          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114                  (match_operand:SI 1 "s_register_operand" "r"))
2115          (const_int 0)))
2116    (set (match_operand:SI 0 "s_register_operand" "=r")
2117         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2118   "TARGET_ARM"
2119   "bic%?s\\t%0, %1, %2"
2120   [(set_attr "conds" "set")]
2123 (define_insn "*andsi_notsi_si_compare0_scratch"
2124   [(set (reg:CC_NOOV CC_REGNUM)
2125         (compare:CC_NOOV
2126          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2127                  (match_operand:SI 1 "s_register_operand" "r"))
2128          (const_int 0)))
2129    (clobber (match_scratch:SI 0 "=r"))]
2130   "TARGET_ARM"
2131   "bic%?s\\t%0, %1, %2"
2132   [(set_attr "conds" "set")]
2135 (define_insn "iordi3"
2136   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2137         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2138                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2139   "TARGET_ARM && ! TARGET_IWMMXT"
2140   "#"
2141   [(set_attr "length" "8")
2142    (set_attr "predicable" "yes")]
2145 (define_insn "*iordi_zesidi_di"
2146   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2147         (ior:DI (zero_extend:DI
2148                  (match_operand:SI 2 "s_register_operand" "r,r"))
2149                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2150   "TARGET_ARM"
2151   "@
2152    orr%?\\t%Q0, %Q1, %2
2153    #"
2154   [(set_attr "length" "4,8")
2155    (set_attr "predicable" "yes")]
2158 (define_insn "*iordi_sesidi_di"
2159   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2160         (ior:DI (sign_extend:DI
2161                  (match_operand:SI 2 "s_register_operand" "r,r"))
2162                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2163   "TARGET_ARM"
2164   "#"
2165   [(set_attr "length" "8")
2166    (set_attr "predicable" "yes")]
2169 (define_expand "iorsi3"
2170   [(set (match_operand:SI         0 "s_register_operand" "")
2171         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2172                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2173   "TARGET_EITHER"
2174   "
2175   if (GET_CODE (operands[2]) == CONST_INT)
2176     {
2177       if (TARGET_ARM)
2178         {
2179           arm_split_constant (IOR, SImode, NULL_RTX,
2180                               INTVAL (operands[2]), operands[0], operands[1],
2181                               optimize && !no_new_pseudos);
2182           DONE;
2183         }
2184       else /* TARGET_THUMB */
2185         operands [2] = force_reg (SImode, operands [2]);
2186     }
2187   "
2190 (define_insn_and_split "*arm_iorsi3"
2191   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2192         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2193                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2194   "TARGET_ARM"
2195   "@
2196    orr%?\\t%0, %1, %2
2197    #"
2198   "TARGET_ARM
2199    && GET_CODE (operands[2]) == CONST_INT
2200    && !const_ok_for_arm (INTVAL (operands[2]))"
2201   [(clobber (const_int 0))]
2202   "
2203   arm_split_constant (IOR, SImode, curr_insn, 
2204                       INTVAL (operands[2]), operands[0], operands[1], 0);
2205   DONE;
2206   "
2207   [(set_attr "length" "4,16")
2208    (set_attr "predicable" "yes")]
2211 (define_insn "*thumb_iorsi3"
2212   [(set (match_operand:SI         0 "register_operand" "=l")
2213         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2214                 (match_operand:SI 2 "register_operand" "l")))]
2215   "TARGET_THUMB"
2216   "orr\\t%0, %0, %2"
2217   [(set_attr "length" "2")]
2220 (define_peephole2
2221   [(match_scratch:SI 3 "r")
2222    (set (match_operand:SI 0 "arm_general_register_operand" "")
2223         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2224                 (match_operand:SI 2 "const_int_operand" "")))]
2225   "TARGET_ARM
2226    && !const_ok_for_arm (INTVAL (operands[2]))
2227    && const_ok_for_arm (~INTVAL (operands[2]))"
2228   [(set (match_dup 3) (match_dup 2))
2229    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2230   ""
2233 (define_insn "*iorsi3_compare0"
2234   [(set (reg:CC_NOOV CC_REGNUM)
2235         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2237                          (const_int 0)))
2238    (set (match_operand:SI 0 "s_register_operand" "=r")
2239         (ior:SI (match_dup 1) (match_dup 2)))]
2240   "TARGET_ARM"
2241   "orr%?s\\t%0, %1, %2"
2242   [(set_attr "conds" "set")]
2245 (define_insn "*iorsi3_compare0_scratch"
2246   [(set (reg:CC_NOOV CC_REGNUM)
2247         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2248                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2249                          (const_int 0)))
2250    (clobber (match_scratch:SI 0 "=r"))]
2251   "TARGET_ARM"
2252   "orr%?s\\t%0, %1, %2"
2253   [(set_attr "conds" "set")]
2256 (define_insn "xordi3"
2257   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2258         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2259                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2260   "TARGET_ARM && !TARGET_IWMMXT"
2261   "#"
2262   [(set_attr "length" "8")
2263    (set_attr "predicable" "yes")]
2266 (define_insn "*xordi_zesidi_di"
2267   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2268         (xor:DI (zero_extend:DI
2269                  (match_operand:SI 2 "s_register_operand" "r,r"))
2270                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2271   "TARGET_ARM"
2272   "@
2273    eor%?\\t%Q0, %Q1, %2
2274    #"
2275   [(set_attr "length" "4,8")
2276    (set_attr "predicable" "yes")]
2279 (define_insn "*xordi_sesidi_di"
2280   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2281         (xor:DI (sign_extend:DI
2282                  (match_operand:SI 2 "s_register_operand" "r,r"))
2283                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2284   "TARGET_ARM"
2285   "#"
2286   [(set_attr "length" "8")
2287    (set_attr "predicable" "yes")]
2290 (define_expand "xorsi3"
2291   [(set (match_operand:SI         0 "s_register_operand" "")
2292         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2293                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2294   "TARGET_EITHER"
2295   "if (TARGET_THUMB)
2296      if (GET_CODE (operands[2]) == CONST_INT)
2297        operands[2] = force_reg (SImode, operands[2]);
2298   "
2301 (define_insn "*arm_xorsi3"
2302   [(set (match_operand:SI         0 "s_register_operand" "=r")
2303         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2304                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2305   "TARGET_ARM"
2306   "eor%?\\t%0, %1, %2"
2307   [(set_attr "predicable" "yes")]
2310 (define_insn "*thumb_xorsi3"
2311   [(set (match_operand:SI         0 "register_operand" "=l")
2312         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2313                 (match_operand:SI 2 "register_operand" "l")))]
2314   "TARGET_THUMB"
2315   "eor\\t%0, %0, %2"
2316   [(set_attr "length" "2")]
2319 (define_insn "*xorsi3_compare0"
2320   [(set (reg:CC_NOOV CC_REGNUM)
2321         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2322                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2323                          (const_int 0)))
2324    (set (match_operand:SI 0 "s_register_operand" "=r")
2325         (xor:SI (match_dup 1) (match_dup 2)))]
2326   "TARGET_ARM"
2327   "eor%?s\\t%0, %1, %2"
2328   [(set_attr "conds" "set")]
2331 (define_insn "*xorsi3_compare0_scratch"
2332   [(set (reg:CC_NOOV CC_REGNUM)
2333         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2334                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2335                          (const_int 0)))]
2336   "TARGET_ARM"
2337   "teq%?\\t%0, %1"
2338   [(set_attr "conds" "set")]
2341 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2342 ; (NOT D) we can sometimes merge the final NOT into one of the following
2343 ; insns.
2345 (define_split
2346   [(set (match_operand:SI 0 "s_register_operand" "")
2347         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2348                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2349                 (match_operand:SI 3 "arm_rhs_operand" "")))
2350    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2351   "TARGET_ARM"
2352   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2353                               (not:SI (match_dup 3))))
2354    (set (match_dup 0) (not:SI (match_dup 4)))]
2355   ""
2358 (define_insn "*andsi_iorsi3_notsi"
2359   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2360         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2361                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2362                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2363   "TARGET_ARM"
2364   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2365   [(set_attr "length" "8")
2366    (set_attr "predicable" "yes")]
2369 (define_split
2370   [(set (match_operand:SI 0 "s_register_operand" "")
2371         (match_operator:SI 1 "logical_binary_operator"
2372          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2373                            (match_operand:SI 3 "const_int_operand" "")
2374                            (match_operand:SI 4 "const_int_operand" ""))
2375           (match_operator:SI 9 "logical_binary_operator"
2376            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2377                          (match_operand:SI 6 "const_int_operand" ""))
2378             (match_operand:SI 7 "s_register_operand" "")])]))
2379    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2380   "TARGET_ARM
2381    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2382    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2383   [(set (match_dup 8)
2384         (match_op_dup 1
2385          [(ashift:SI (match_dup 2) (match_dup 4))
2386           (match_dup 5)]))
2387    (set (match_dup 0)
2388         (match_op_dup 1
2389          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2390           (match_dup 7)]))]
2391   "
2392   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2395 (define_split
2396   [(set (match_operand:SI 0 "s_register_operand" "")
2397         (match_operator:SI 1 "logical_binary_operator"
2398          [(match_operator:SI 9 "logical_binary_operator"
2399            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2400                          (match_operand:SI 6 "const_int_operand" ""))
2401             (match_operand:SI 7 "s_register_operand" "")])
2402           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2403                            (match_operand:SI 3 "const_int_operand" "")
2404                            (match_operand:SI 4 "const_int_operand" ""))]))
2405    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2406   "TARGET_ARM
2407    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2408    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2409   [(set (match_dup 8)
2410         (match_op_dup 1
2411          [(ashift:SI (match_dup 2) (match_dup 4))
2412           (match_dup 5)]))
2413    (set (match_dup 0)
2414         (match_op_dup 1
2415          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2416           (match_dup 7)]))]
2417   "
2418   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2421 (define_split
2422   [(set (match_operand:SI 0 "s_register_operand" "")
2423         (match_operator:SI 1 "logical_binary_operator"
2424          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2425                            (match_operand:SI 3 "const_int_operand" "")
2426                            (match_operand:SI 4 "const_int_operand" ""))
2427           (match_operator:SI 9 "logical_binary_operator"
2428            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2429                          (match_operand:SI 6 "const_int_operand" ""))
2430             (match_operand:SI 7 "s_register_operand" "")])]))
2431    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2432   "TARGET_ARM
2433    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2434    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2435   [(set (match_dup 8)
2436         (match_op_dup 1
2437          [(ashift:SI (match_dup 2) (match_dup 4))
2438           (match_dup 5)]))
2439    (set (match_dup 0)
2440         (match_op_dup 1
2441          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2442           (match_dup 7)]))]
2443   "
2444   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2447 (define_split
2448   [(set (match_operand:SI 0 "s_register_operand" "")
2449         (match_operator:SI 1 "logical_binary_operator"
2450          [(match_operator:SI 9 "logical_binary_operator"
2451            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2452                          (match_operand:SI 6 "const_int_operand" ""))
2453             (match_operand:SI 7 "s_register_operand" "")])
2454           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2455                            (match_operand:SI 3 "const_int_operand" "")
2456                            (match_operand:SI 4 "const_int_operand" ""))]))
2457    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2458   "TARGET_ARM
2459    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2460    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2461   [(set (match_dup 8)
2462         (match_op_dup 1
2463          [(ashift:SI (match_dup 2) (match_dup 4))
2464           (match_dup 5)]))
2465    (set (match_dup 0)
2466         (match_op_dup 1
2467          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2468           (match_dup 7)]))]
2469   "
2470   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2474 ;; Minimum and maximum insns
2476 (define_expand "smaxsi3"
2477   [(parallel [
2478     (set (match_operand:SI 0 "s_register_operand" "")
2479          (smax:SI (match_operand:SI 1 "s_register_operand" "")
2480                   (match_operand:SI 2 "arm_rhs_operand" "")))
2481     (clobber (reg:CC CC_REGNUM))])]
2482   "TARGET_ARM"
2483   "
2484   if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
2485     {
2486       /* No need for a clobber of the condition code register here.  */
2487       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2488                               gen_rtx_SMAX (SImode, operands[1],
2489                                             operands[2])));
2490       DONE;
2491     }
2494 (define_insn "*smax_0"
2495   [(set (match_operand:SI 0 "s_register_operand" "=r")
2496         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2497                  (const_int 0)))]
2498   "TARGET_ARM"
2499   "bic%?\\t%0, %1, %1, asr #31"
2500   [(set_attr "predicable" "yes")]
2503 (define_insn "*smax_m1"
2504   [(set (match_operand:SI 0 "s_register_operand" "=r")
2505         (smax:SI (match_operand:SI 1 "s_register_operand" "r")
2506                  (const_int -1)))]
2507   "TARGET_ARM"
2508   "orr%?\\t%0, %1, %1, asr #31"
2509   [(set_attr "predicable" "yes")]
2512 (define_insn "*smax_insn"
2513   [(set (match_operand:SI          0 "s_register_operand" "=r,r")
2514         (smax:SI (match_operand:SI 1 "s_register_operand"  "%0,?r")
2515                  (match_operand:SI 2 "arm_rhs_operand"    "rI,rI")))
2516    (clobber (reg:CC CC_REGNUM))]
2517   "TARGET_ARM"
2518   "@
2519    cmp\\t%1, %2\;movlt\\t%0, %2
2520    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2521   [(set_attr "conds" "clob")
2522    (set_attr "length" "8,12")]
2525 (define_expand "sminsi3"
2526   [(parallel [
2527     (set (match_operand:SI 0 "s_register_operand" "")
2528          (smin:SI (match_operand:SI 1 "s_register_operand" "")
2529                   (match_operand:SI 2 "arm_rhs_operand" "")))
2530     (clobber (reg:CC CC_REGNUM))])]
2531   "TARGET_ARM"
2532   "
2533   if (operands[2] == const0_rtx)
2534     {
2535       /* No need for a clobber of the condition code register here.  */
2536       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2537                               gen_rtx_SMIN (SImode, operands[1],
2538                                             operands[2])));
2539       DONE;
2540     }
2543 (define_insn "*smin_0"
2544   [(set (match_operand:SI 0 "s_register_operand" "=r")
2545         (smin:SI (match_operand:SI 1 "s_register_operand" "r")
2546                  (const_int 0)))]
2547   "TARGET_ARM"
2548   "and%?\\t%0, %1, %1, asr #31"
2549   [(set_attr "predicable" "yes")]
2552 (define_insn "*smin_insn"
2553   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2554         (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
2555                  (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
2556    (clobber (reg:CC CC_REGNUM))]
2557   "TARGET_ARM"
2558   "@
2559    cmp\\t%1, %2\;movge\\t%0, %2
2560    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2561   [(set_attr "conds" "clob")
2562    (set_attr "length" "8,12")]
2565 (define_insn "umaxsi3"
2566   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2567         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2568                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2569    (clobber (reg:CC CC_REGNUM))]
2570   "TARGET_ARM"
2571   "@
2572    cmp\\t%1, %2\;movcc\\t%0, %2
2573    cmp\\t%1, %2\;movcs\\t%0, %1
2574    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2575   [(set_attr "conds" "clob")
2576    (set_attr "length" "8,8,12")]
2579 (define_insn "uminsi3"
2580   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2581         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2582                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2583    (clobber (reg:CC CC_REGNUM))]
2584   "TARGET_ARM"
2585   "@
2586    cmp\\t%1, %2\;movcs\\t%0, %2
2587    cmp\\t%1, %2\;movcc\\t%0, %1
2588    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2589   [(set_attr "conds" "clob")
2590    (set_attr "length" "8,8,12")]
2593 (define_insn "*store_minmaxsi"
2594   [(set (match_operand:SI 0 "memory_operand" "=m")
2595         (match_operator:SI 3 "minmax_operator"
2596          [(match_operand:SI 1 "s_register_operand" "r")
2597           (match_operand:SI 2 "s_register_operand" "r")]))
2598    (clobber (reg:CC CC_REGNUM))]
2599   "TARGET_ARM"
2600   "*
2601   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2602                                 operands[1], operands[2]);
2603   output_asm_insn (\"cmp\\t%1, %2\", operands);
2604   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2605   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2606   return \"\";
2607   "
2608   [(set_attr "conds" "clob")
2609    (set_attr "length" "12")
2610    (set_attr "type" "store1")]
2613 ; Reject the frame pointer in operand[1], since reloading this after
2614 ; it has been eliminated can cause carnage.
2615 (define_insn "*minmax_arithsi"
2616   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2617         (match_operator:SI 4 "shiftable_operator"
2618          [(match_operator:SI 5 "minmax_operator"
2619            [(match_operand:SI 2 "s_register_operand" "r,r")
2620             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2621           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2622    (clobber (reg:CC CC_REGNUM))]
2623   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2624   "*
2625   {
2626     enum rtx_code code = GET_CODE (operands[4]);
2628     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2629                                   operands[2], operands[3]);
2630     output_asm_insn (\"cmp\\t%2, %3\", operands);
2631     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2632     if (which_alternative != 0 || operands[3] != const0_rtx
2633         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2634       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2635     return \"\";
2636   }"
2637   [(set_attr "conds" "clob")
2638    (set_attr "length" "12")]
2642 ;; Shift and rotation insns
2644 (define_expand "ashldi3"
2645   [(set (match_operand:DI            0 "s_register_operand" "")
2646         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2647                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2648   "TARGET_ARM"
2649   "
2650   if (GET_CODE (operands[2]) == CONST_INT)
2651     {
2652       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2653         {
2654           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2655           DONE;
2656         }
2657         /* Ideally we shouldn't fail here if we could know that operands[1] 
2658            ends up already living in an iwmmxt register. Otherwise it's
2659            cheaper to have the alternate code being generated than moving
2660            values to iwmmxt regs and back.  */
2661         FAIL;
2662     }
2663   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2664     FAIL;
2665   "
2668 (define_insn "arm_ashldi3_1bit"
2669   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2670         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2671                    (const_int 1)))
2672    (clobber (reg:CC CC_REGNUM))]
2673   "TARGET_ARM"
2674   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2675   [(set_attr "conds" "clob")
2676    (set_attr "length" "8")]
2679 (define_expand "ashlsi3"
2680   [(set (match_operand:SI            0 "s_register_operand" "")
2681         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2682                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2683   "TARGET_EITHER"
2684   "
2685   if (GET_CODE (operands[2]) == CONST_INT
2686       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2687     {
2688       emit_insn (gen_movsi (operands[0], const0_rtx));
2689       DONE;
2690     }
2691   "
2694 (define_insn "*thumb_ashlsi3"
2695   [(set (match_operand:SI            0 "register_operand" "=l,l")
2696         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2697                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2698   "TARGET_THUMB"
2699   "lsl\\t%0, %1, %2"
2700   [(set_attr "length" "2")]
2703 (define_expand "ashrdi3"
2704   [(set (match_operand:DI              0 "s_register_operand" "")
2705         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2706                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2707   "TARGET_ARM"
2708   "
2709   if (GET_CODE (operands[2]) == CONST_INT)
2710     {
2711       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2712         {
2713           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2714           DONE;
2715         }
2716         /* Ideally we shouldn't fail here if we could know that operands[1] 
2717            ends up already living in an iwmmxt register. Otherwise it's
2718            cheaper to have the alternate code being generated than moving
2719            values to iwmmxt regs and back.  */
2720         FAIL;
2721     }
2722   else if (!TARGET_REALLY_IWMMXT)
2723     FAIL;
2724   "
2727 (define_insn "arm_ashrdi3_1bit"
2728   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2729         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2730                      (const_int 1)))
2731    (clobber (reg:CC CC_REGNUM))]
2732   "TARGET_ARM"
2733   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2734   [(set_attr "conds" "clob")
2735    (set_attr "length" "8")]
2738 (define_expand "ashrsi3"
2739   [(set (match_operand:SI              0 "s_register_operand" "")
2740         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2741                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2742   "TARGET_EITHER"
2743   "
2744   if (GET_CODE (operands[2]) == CONST_INT
2745       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2746     operands[2] = GEN_INT (31);
2747   "
2750 (define_insn "*thumb_ashrsi3"
2751   [(set (match_operand:SI              0 "register_operand" "=l,l")
2752         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2753                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2754   "TARGET_THUMB"
2755   "asr\\t%0, %1, %2"
2756   [(set_attr "length" "2")]
2759 (define_expand "lshrdi3"
2760   [(set (match_operand:DI              0 "s_register_operand" "")
2761         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2762                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2763   "TARGET_ARM"
2764   "
2765   if (GET_CODE (operands[2]) == CONST_INT)
2766     {
2767       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2768         {
2769           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2770           DONE;
2771         }
2772         /* Ideally we shouldn't fail here if we could know that operands[1] 
2773            ends up already living in an iwmmxt register. Otherwise it's
2774            cheaper to have the alternate code being generated than moving
2775            values to iwmmxt regs and back.  */
2776         FAIL;
2777     }
2778   else if (!TARGET_REALLY_IWMMXT)
2779     FAIL;
2780   "
2783 (define_insn "arm_lshrdi3_1bit"
2784   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2785         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2786                      (const_int 1)))
2787    (clobber (reg:CC CC_REGNUM))]
2788   "TARGET_ARM"
2789   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2790   [(set_attr "conds" "clob")
2791    (set_attr "length" "8")]
2794 (define_expand "lshrsi3"
2795   [(set (match_operand:SI              0 "s_register_operand" "")
2796         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2797                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2798   "TARGET_EITHER"
2799   "
2800   if (GET_CODE (operands[2]) == CONST_INT
2801       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2802     {
2803       emit_insn (gen_movsi (operands[0], const0_rtx));
2804       DONE;
2805     }
2806   "
2809 (define_insn "*thumb_lshrsi3"
2810   [(set (match_operand:SI              0 "register_operand" "=l,l")
2811         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2812                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2813   "TARGET_THUMB"
2814   "lsr\\t%0, %1, %2"
2815   [(set_attr "length" "2")]
2818 (define_expand "rotlsi3"
2819   [(set (match_operand:SI              0 "s_register_operand" "")
2820         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2821                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2822   "TARGET_ARM"
2823   "
2824   if (GET_CODE (operands[2]) == CONST_INT)
2825     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2826   else
2827     {
2828       rtx reg = gen_reg_rtx (SImode);
2829       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2830       operands[2] = reg;
2831     }
2832   "
2835 (define_expand "rotrsi3"
2836   [(set (match_operand:SI              0 "s_register_operand" "")
2837         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2838                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2839   "TARGET_EITHER"
2840   "
2841   if (TARGET_ARM)
2842     {
2843       if (GET_CODE (operands[2]) == CONST_INT
2844           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2845         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2846     }
2847   else /* TARGET_THUMB */
2848     {
2849       if (GET_CODE (operands [2]) == CONST_INT)
2850         operands [2] = force_reg (SImode, operands[2]);
2851     }
2852   "
2855 (define_insn "*thumb_rotrsi3"
2856   [(set (match_operand:SI              0 "register_operand" "=l")
2857         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2858                      (match_operand:SI 2 "register_operand" "l")))]
2859   "TARGET_THUMB"
2860   "ror\\t%0, %0, %2"
2861   [(set_attr "length" "2")]
2864 (define_insn "*arm_shiftsi3"
2865   [(set (match_operand:SI   0 "s_register_operand" "=r")
2866         (match_operator:SI  3 "shift_operator"
2867          [(match_operand:SI 1 "s_register_operand"  "r")
2868           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2869   "TARGET_ARM"
2870   "mov%?\\t%0, %1%S3"
2871   [(set_attr "predicable" "yes")
2872    (set_attr "shift" "1")
2873    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2874                       (const_string "alu_shift")
2875                       (const_string "alu_shift_reg")))]
2878 (define_insn "*shiftsi3_compare0"
2879   [(set (reg:CC_NOOV CC_REGNUM)
2880         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2881                           [(match_operand:SI 1 "s_register_operand" "r")
2882                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2883                          (const_int 0)))
2884    (set (match_operand:SI 0 "s_register_operand" "=r")
2885         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2886   "TARGET_ARM"
2887   "mov%?s\\t%0, %1%S3"
2888   [(set_attr "conds" "set")
2889    (set_attr "shift" "1")
2890    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2891                       (const_string "alu_shift")
2892                       (const_string "alu_shift_reg")))]
2895 (define_insn "*shiftsi3_compare0_scratch"
2896   [(set (reg:CC_NOOV CC_REGNUM)
2897         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2898                           [(match_operand:SI 1 "s_register_operand" "r")
2899                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2900                          (const_int 0)))
2901    (clobber (match_scratch:SI 0 "=r"))]
2902   "TARGET_ARM"
2903   "mov%?s\\t%0, %1%S3"
2904   [(set_attr "conds" "set")
2905    (set_attr "shift" "1")]
2908 (define_insn "*notsi_shiftsi"
2909   [(set (match_operand:SI 0 "s_register_operand" "=r")
2910         (not:SI (match_operator:SI 3 "shift_operator"
2911                  [(match_operand:SI 1 "s_register_operand" "r")
2912                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2913   "TARGET_ARM"
2914   "mvn%?\\t%0, %1%S3"
2915   [(set_attr "predicable" "yes")
2916    (set_attr "shift" "1")
2917    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2918                       (const_string "alu_shift")
2919                       (const_string "alu_shift_reg")))]
2922 (define_insn "*notsi_shiftsi_compare0"
2923   [(set (reg:CC_NOOV CC_REGNUM)
2924         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2925                           [(match_operand:SI 1 "s_register_operand" "r")
2926                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2927                          (const_int 0)))
2928    (set (match_operand:SI 0 "s_register_operand" "=r")
2929         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2930   "TARGET_ARM"
2931   "mvn%?s\\t%0, %1%S3"
2932   [(set_attr "conds" "set")
2933    (set_attr "shift" "1")
2934    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2935                       (const_string "alu_shift")
2936                       (const_string "alu_shift_reg")))]
2939 (define_insn "*not_shiftsi_compare0_scratch"
2940   [(set (reg:CC_NOOV CC_REGNUM)
2941         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2942                           [(match_operand:SI 1 "s_register_operand" "r")
2943                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2944                          (const_int 0)))
2945    (clobber (match_scratch:SI 0 "=r"))]
2946   "TARGET_ARM"
2947   "mvn%?s\\t%0, %1%S3"
2948   [(set_attr "conds" "set")
2949    (set_attr "shift" "1")
2950    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2951                       (const_string "alu_shift")
2952                       (const_string "alu_shift_reg")))]
2955 ;; We don't really have extzv, but defining this using shifts helps
2956 ;; to reduce register pressure later on.
2958 (define_expand "extzv"
2959   [(set (match_dup 4)
2960         (ashift:SI (match_operand:SI   1 "register_operand" "")
2961                    (match_operand:SI   2 "const_int_operand" "")))
2962    (set (match_operand:SI              0 "register_operand" "")
2963         (lshiftrt:SI (match_dup 4)
2964                      (match_operand:SI 3 "const_int_operand" "")))]
2965   "TARGET_THUMB"
2966   "
2967   {
2968     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2969     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2970     
2971     operands[3] = GEN_INT (rshift);
2972     
2973     if (lshift == 0)
2974       {
2975         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2976         DONE;
2977       }
2978       
2979     operands[2] = GEN_INT (lshift);
2980     operands[4] = gen_reg_rtx (SImode);
2981   }"
2985 ;; Unary arithmetic insns
2987 (define_expand "negdi2"
2988  [(parallel
2989    [(set (match_operand:DI          0 "s_register_operand" "")
2990           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2991     (clobber (reg:CC CC_REGNUM))])]
2992   "TARGET_EITHER"
2993   "
2994   if (TARGET_THUMB)
2995     {
2996       if (GET_CODE (operands[1]) != REG)
2997         operands[1] = force_reg (SImode, operands[1]);
2998      }
2999   "
3002 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
3003 ;; The second alternative is to allow the common case of a *full* overlap.
3004 (define_insn "*arm_negdi2"
3005   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
3006         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
3007    (clobber (reg:CC CC_REGNUM))]
3008   "TARGET_ARM"
3009   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
3010   [(set_attr "conds" "clob")
3011    (set_attr "length" "8")]
3014 (define_insn "*thumb_negdi2"
3015   [(set (match_operand:DI         0 "register_operand" "=&l")
3016         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
3017    (clobber (reg:CC CC_REGNUM))]
3018   "TARGET_THUMB"
3019   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
3020   [(set_attr "length" "6")]
3023 (define_expand "negsi2"
3024   [(set (match_operand:SI         0 "s_register_operand" "")
3025         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
3026   "TARGET_EITHER"
3027   ""
3030 (define_insn "*arm_negsi2"
3031   [(set (match_operand:SI         0 "s_register_operand" "=r")
3032         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
3033   "TARGET_ARM"
3034   "rsb%?\\t%0, %1, #0"
3035   [(set_attr "predicable" "yes")]
3038 (define_insn "*thumb_negsi2"
3039   [(set (match_operand:SI         0 "register_operand" "=l")
3040         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
3041   "TARGET_THUMB"
3042   "neg\\t%0, %1"
3043   [(set_attr "length" "2")]
3046 (define_expand "negsf2"
3047   [(set (match_operand:SF         0 "s_register_operand" "")
3048         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
3049   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3050   ""
3053 (define_expand "negdf2"
3054   [(set (match_operand:DF         0 "s_register_operand" "")
3055         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
3056   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3057   "")
3059 ;; abssi2 doesn't really clobber the condition codes if a different register
3060 ;; is being set.  To keep things simple, assume during rtl manipulations that
3061 ;; it does, but tell the final scan operator the truth.  Similarly for
3062 ;; (neg (abs...))
3064 (define_expand "abssi2"
3065   [(parallel
3066     [(set (match_operand:SI         0 "s_register_operand" "")
3067           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3068      (clobber (reg:CC CC_REGNUM))])]
3069   "TARGET_ARM"
3070   "")
3072 (define_insn "*arm_abssi2"
3073   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3074         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3075    (clobber (reg:CC CC_REGNUM))]
3076   "TARGET_ARM"
3077   "@
3078    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3079    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3080   [(set_attr "conds" "clob,*")
3081    (set_attr "shift" "1")
3082    ;; predicable can't be set based on the variant, so left as no
3083    (set_attr "length" "8")]
3086 (define_insn "*neg_abssi2"
3087   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3088         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3089    (clobber (reg:CC CC_REGNUM))]
3090   "TARGET_ARM"
3091   "@
3092    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3093    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3094   [(set_attr "conds" "clob,*")
3095    (set_attr "shift" "1")
3096    ;; predicable can't be set based on the variant, so left as no
3097    (set_attr "length" "8")]
3100 (define_expand "abssf2"
3101   [(set (match_operand:SF         0 "s_register_operand" "")
3102         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3103   "TARGET_ARM && TARGET_HARD_FLOAT"
3104   "")
3106 (define_expand "absdf2"
3107   [(set (match_operand:DF         0 "s_register_operand" "")
3108         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3109   "TARGET_ARM && TARGET_HARD_FLOAT"
3110   "")
3112 (define_expand "sqrtsf2"
3113   [(set (match_operand:SF 0 "s_register_operand" "")
3114         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3115   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3116   "")
3118 (define_expand "sqrtdf2"
3119   [(set (match_operand:DF 0 "s_register_operand" "")
3120         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3121   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3122   "")
3124 (define_insn_and_split "one_cmpldi2"
3125   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3126         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3127   "TARGET_ARM"
3128   "#"
3129   "TARGET_ARM && reload_completed"
3130   [(set (match_dup 0) (not:SI (match_dup 1)))
3131    (set (match_dup 2) (not:SI (match_dup 3)))]
3132   "
3133   {
3134     operands[2] = gen_highpart (SImode, operands[0]);
3135     operands[0] = gen_lowpart (SImode, operands[0]);
3136     operands[3] = gen_highpart (SImode, operands[1]);
3137     operands[1] = gen_lowpart (SImode, operands[1]);
3138   }"
3139   [(set_attr "length" "8")
3140    (set_attr "predicable" "yes")]
3143 (define_expand "one_cmplsi2"
3144   [(set (match_operand:SI         0 "s_register_operand" "")
3145         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3146   "TARGET_EITHER"
3147   ""
3150 (define_insn "*arm_one_cmplsi2"
3151   [(set (match_operand:SI         0 "s_register_operand" "=r")
3152         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3153   "TARGET_ARM"
3154   "mvn%?\\t%0, %1"
3155   [(set_attr "predicable" "yes")]
3158 (define_insn "*thumb_one_cmplsi2"
3159   [(set (match_operand:SI         0 "register_operand" "=l")
3160         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3161   "TARGET_THUMB"
3162   "mvn\\t%0, %1"
3163   [(set_attr "length" "2")]
3166 (define_insn "*notsi_compare0"
3167   [(set (reg:CC_NOOV CC_REGNUM)
3168         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3169                          (const_int 0)))
3170    (set (match_operand:SI 0 "s_register_operand" "=r")
3171         (not:SI (match_dup 1)))]
3172   "TARGET_ARM"
3173   "mvn%?s\\t%0, %1"
3174   [(set_attr "conds" "set")]
3177 (define_insn "*notsi_compare0_scratch"
3178   [(set (reg:CC_NOOV CC_REGNUM)
3179         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3180                          (const_int 0)))
3181    (clobber (match_scratch:SI 0 "=r"))]
3182   "TARGET_ARM"
3183   "mvn%?s\\t%0, %1"
3184   [(set_attr "conds" "set")]
3187 ;; Fixed <--> Floating conversion insns
3189 (define_expand "floatsisf2"
3190   [(set (match_operand:SF           0 "s_register_operand" "")
3191         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3192   "TARGET_ARM && TARGET_HARD_FLOAT"
3193   "
3194   if (TARGET_MAVERICK)
3195     {
3196       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3197       DONE;
3198     }
3201 (define_expand "floatsidf2"
3202   [(set (match_operand:DF           0 "s_register_operand" "")
3203         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3204   "TARGET_ARM && TARGET_HARD_FLOAT"
3205   "
3206   if (TARGET_MAVERICK)
3207     {
3208       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3209       DONE;
3210     }
3213 (define_expand "fix_truncsfsi2"
3214   [(set (match_operand:SI         0 "s_register_operand" "")
3215         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3216   "TARGET_ARM && TARGET_HARD_FLOAT"
3217   "
3218   if (TARGET_MAVERICK)
3219     {
3220       if (!cirrus_fp_register (operands[0], SImode))
3221         operands[0] = force_reg (SImode, operands[0]);
3222       if (!cirrus_fp_register (operands[1], SFmode))
3223         operands[1] = force_reg (SFmode, operands[0]);
3224       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3225       DONE;
3226     }
3229 (define_expand "fix_truncdfsi2"
3230   [(set (match_operand:SI         0 "s_register_operand" "")
3231         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3232   "TARGET_ARM && TARGET_HARD_FLOAT"
3233   "
3234   if (TARGET_MAVERICK)
3235     {
3236       if (!cirrus_fp_register (operands[1], DFmode))
3237         operands[1] = force_reg (DFmode, operands[0]);
3238       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3239       DONE;
3240     }
3243 ;; Truncation insns
3245 (define_expand "truncdfsf2"
3246   [(set (match_operand:SF  0 "s_register_operand" "")
3247         (float_truncate:SF
3248          (match_operand:DF 1 "s_register_operand" "")))]
3249   "TARGET_ARM && TARGET_HARD_FLOAT"
3250   ""
3253 ;; Zero and sign extension instructions.
3255 (define_insn "zero_extendsidi2"
3256   [(set (match_operand:DI 0 "s_register_operand" "=r")
3257         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3258   "TARGET_ARM"
3259   "*
3260     if (REGNO (operands[1])
3261         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3262       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3263     return \"mov%?\\t%R0, #0\";
3264   "
3265   [(set_attr "length" "8")
3266    (set_attr "predicable" "yes")]
3269 (define_insn "zero_extendqidi2"
3270   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3271         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3272   "TARGET_ARM"
3273   "@
3274    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3275    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3276   [(set_attr "length" "8")
3277    (set_attr "predicable" "yes")
3278    (set_attr "type" "*,load_byte")
3279    (set_attr "pool_range" "*,4092")
3280    (set_attr "neg_pool_range" "*,4084")]
3283 (define_insn "extendsidi2"
3284   [(set (match_operand:DI 0 "s_register_operand" "=r")
3285         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3286   "TARGET_ARM"
3287   "*
3288     if (REGNO (operands[1])
3289         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3290       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3291     return \"mov%?\\t%R0, %Q0, asr #31\";
3292   "
3293   [(set_attr "length" "8")
3294    (set_attr "shift" "1")
3295    (set_attr "predicable" "yes")]
3298 (define_expand "zero_extendhisi2"
3299   [(set (match_dup 2)
3300         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3301                    (const_int 16)))
3302    (set (match_operand:SI 0 "s_register_operand" "")
3303         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3304   "TARGET_EITHER"
3305   "
3306   {
3307     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3308       {
3309         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3310                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3311         DONE;
3312       }
3314     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3315       {
3316         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3317         DONE;
3318       }
3320     if (!s_register_operand (operands[1], HImode))
3321       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3323     if (arm_arch6)
3324       {
3325         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3326                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3327         DONE;
3328       }
3330     operands[1] = gen_lowpart (SImode, operands[1]);
3331     operands[2] = gen_reg_rtx (SImode);
3332   }"
3335 (define_insn "*thumb_zero_extendhisi2"
3336   [(set (match_operand:SI 0 "register_operand" "=l")
3337         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3338   "TARGET_THUMB && !arm_arch6"
3339   "*
3340   rtx mem = XEXP (operands[1], 0);
3342   if (GET_CODE (mem) == CONST)
3343     mem = XEXP (mem, 0);
3344     
3345   if (GET_CODE (mem) == LABEL_REF)
3346     return \"ldr\\t%0, %1\";
3347     
3348   if (GET_CODE (mem) == PLUS)
3349     {
3350       rtx a = XEXP (mem, 0);
3351       rtx b = XEXP (mem, 1);
3353       /* This can happen due to bugs in reload.  */
3354       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3355         {
3356           rtx ops[2];
3357           ops[0] = operands[0];
3358           ops[1] = a;
3359       
3360           output_asm_insn (\"mov        %0, %1\", ops);
3362           XEXP (mem, 0) = operands[0];
3363        }
3365       else if (   GET_CODE (a) == LABEL_REF
3366                && GET_CODE (b) == CONST_INT)
3367         return \"ldr\\t%0, %1\";
3368     }
3369     
3370   return \"ldrh\\t%0, %1\";
3371   "
3372   [(set_attr "length" "4")
3373    (set_attr "type" "load_byte")
3374    (set_attr "pool_range" "60")]
3377 (define_insn "*thumb_zero_extendhisi2_v6"
3378   [(set (match_operand:SI 0 "register_operand" "=l,l")
3379         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3380   "TARGET_THUMB && arm_arch6"
3381   "*
3382   rtx mem;
3384   if (which_alternative == 0)
3385     return \"uxth\\t%0, %1\";
3387   mem = XEXP (operands[1], 0);
3389   if (GET_CODE (mem) == CONST)
3390     mem = XEXP (mem, 0);
3391     
3392   if (GET_CODE (mem) == LABEL_REF)
3393     return \"ldr\\t%0, %1\";
3394     
3395   if (GET_CODE (mem) == PLUS)
3396     {
3397       rtx a = XEXP (mem, 0);
3398       rtx b = XEXP (mem, 1);
3400       /* This can happen due to bugs in reload.  */
3401       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3402         {
3403           rtx ops[2];
3404           ops[0] = operands[0];
3405           ops[1] = a;
3406       
3407           output_asm_insn (\"mov        %0, %1\", ops);
3409           XEXP (mem, 0) = operands[0];
3410        }
3412       else if (   GET_CODE (a) == LABEL_REF
3413                && GET_CODE (b) == CONST_INT)
3414         return \"ldr\\t%0, %1\";
3415     }
3416     
3417   return \"ldrh\\t%0, %1\";
3418   "
3419   [(set_attr "length" "2,4")
3420    (set_attr "type" "alu_shift,load_byte")
3421    (set_attr "pool_range" "*,60")]
3424 (define_insn "*arm_zero_extendhisi2"
3425   [(set (match_operand:SI 0 "s_register_operand" "=r")
3426         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3427   "TARGET_ARM && arm_arch4 && !arm_arch6"
3428   "ldr%?h\\t%0, %1"
3429   [(set_attr "type" "load_byte")
3430    (set_attr "predicable" "yes")
3431    (set_attr "pool_range" "256")
3432    (set_attr "neg_pool_range" "244")]
3435 (define_insn "*arm_zero_extendhisi2_v6"
3436   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3437         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3438   "TARGET_ARM && arm_arch6"
3439   "@
3440    uxth%?\\t%0, %1
3441    ldr%?h\\t%0, %1"
3442   [(set_attr "type" "alu_shift,load_byte")
3443    (set_attr "predicable" "yes")
3444    (set_attr "pool_range" "*,256")
3445    (set_attr "neg_pool_range" "*,244")]
3448 (define_insn "*arm_zero_extendhisi2addsi"
3449   [(set (match_operand:SI 0 "s_register_operand" "=r")
3450         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3451                  (match_operand:SI 2 "s_register_operand" "r")))]
3452   "TARGET_ARM && arm_arch6"
3453   "uxtah%?\\t%0, %2, %1"
3454   [(set_attr "type" "alu_shift")
3455    (set_attr "predicable" "yes")]
3458 (define_expand "zero_extendqisi2"
3459   [(set (match_operand:SI 0 "s_register_operand" "")
3460         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3461   "TARGET_EITHER"
3462   "
3463   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3464     {
3465       if (TARGET_ARM)
3466         {
3467           emit_insn (gen_andsi3 (operands[0],
3468                                  gen_lowpart (SImode, operands[1]),
3469                                  GEN_INT (255)));
3470         }
3471       else /* TARGET_THUMB */
3472         {
3473           rtx temp = gen_reg_rtx (SImode);
3474           rtx ops[3];
3475           
3476           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3477           operands[1] = gen_lowpart (SImode, operands[1]);
3479           ops[0] = temp;
3480           ops[1] = operands[1];
3481           ops[2] = GEN_INT (24);
3483           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3484                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3485           
3486           ops[0] = operands[0];
3487           ops[1] = temp;
3488           ops[2] = GEN_INT (24);
3490           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3491                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3492         }
3493       DONE;
3494     }
3495   "
3498 (define_insn "*thumb_zero_extendqisi2"
3499   [(set (match_operand:SI 0 "register_operand" "=l")
3500         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3501   "TARGET_THUMB && !arm_arch6"
3502   "ldrb\\t%0, %1"
3503   [(set_attr "length" "2")
3504    (set_attr "type" "load_byte")
3505    (set_attr "pool_range" "32")]
3508 (define_insn "*thumb_zero_extendqisi2_v6"
3509   [(set (match_operand:SI 0 "register_operand" "=l,l")
3510         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3511   "TARGET_THUMB && arm_arch6"
3512   "@
3513    uxtb\\t%0, %1
3514    ldrb\\t%0, %1"
3515   [(set_attr "length" "2,2")
3516    (set_attr "type" "alu_shift,load_byte")
3517    (set_attr "pool_range" "*,32")]
3520 (define_insn "*arm_zero_extendqisi2"
3521   [(set (match_operand:SI 0 "s_register_operand" "=r")
3522         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3523   "TARGET_ARM && !arm_arch6"
3524   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3525   [(set_attr "type" "load_byte")
3526    (set_attr "predicable" "yes")
3527    (set_attr "pool_range" "4096")
3528    (set_attr "neg_pool_range" "4084")]
3531 (define_insn "*arm_zero_extendqisi2_v6"
3532   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3533         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3534   "TARGET_ARM && arm_arch6"
3535   "@
3536    uxtb%?\\t%0, %1
3537    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3538   [(set_attr "type" "alu_shift,load_byte")
3539    (set_attr "predicable" "yes")
3540    (set_attr "pool_range" "*,4096")
3541    (set_attr "neg_pool_range" "*,4084")]
3544 (define_insn "*arm_zero_extendqisi2addsi"
3545   [(set (match_operand:SI 0 "s_register_operand" "=r")
3546         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3547                  (match_operand:SI 2 "s_register_operand" "r")))]
3548   "TARGET_ARM && arm_arch6"
3549   "uxtab%?\\t%0, %2, %1"
3550   [(set_attr "predicable" "yes")
3551    (set_attr "type" "alu_shift")]
3554 (define_split
3555   [(set (match_operand:SI 0 "s_register_operand" "")
3556         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3557    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3558   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3559   [(set (match_dup 2) (match_dup 1))
3560    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3561   ""
3564 (define_split
3565   [(set (match_operand:SI 0 "s_register_operand" "")
3566         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3567    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3568   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3569   [(set (match_dup 2) (match_dup 1))
3570    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3571   ""
3574 (define_insn "*compareqi_eq0"
3575   [(set (reg:CC_Z CC_REGNUM)
3576         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3577                          (const_int 0)))]
3578   "TARGET_ARM"
3579   "tst\\t%0, #255"
3580   [(set_attr "conds" "set")]
3583 (define_expand "extendhisi2"
3584   [(set (match_dup 2)
3585         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3586                    (const_int 16)))
3587    (set (match_operand:SI 0 "s_register_operand" "")
3588         (ashiftrt:SI (match_dup 2)
3589                      (const_int 16)))]
3590   "TARGET_EITHER"
3591   "
3592   {
3593     if (GET_CODE (operands[1]) == MEM)
3594       {
3595         if (TARGET_THUMB)
3596           {
3597             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3598             DONE;
3599           }
3600         else if (arm_arch4)
3601           {
3602             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3603                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3604             DONE;
3605           }
3606       }
3608     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3609       {
3610         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3611         DONE;
3612       }
3614     if (!s_register_operand (operands[1], HImode))
3615       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3617     if (arm_arch6)
3618       {
3619         if (TARGET_THUMB)
3620           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3621         else
3622           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3623                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3625         DONE;
3626       }
3628     operands[1] = gen_lowpart (SImode, operands[1]);
3629     operands[2] = gen_reg_rtx (SImode);
3630   }"
3633 (define_insn "thumb_extendhisi2"
3634   [(set (match_operand:SI 0 "register_operand" "=l")
3635         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3636    (clobber (match_scratch:SI 2 "=&l"))]
3637   "TARGET_THUMB && !arm_arch6"
3638   "*
3639   {
3640     rtx ops[4];
3641     rtx mem = XEXP (operands[1], 0);
3643     /* This code used to try to use 'V', and fix the address only if it was
3644        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3645        range of QImode offsets, and offsettable_address_p does a QImode
3646        address check.  */
3647        
3648     if (GET_CODE (mem) == CONST)
3649       mem = XEXP (mem, 0);
3650     
3651     if (GET_CODE (mem) == LABEL_REF)
3652       return \"ldr\\t%0, %1\";
3653     
3654     if (GET_CODE (mem) == PLUS)
3655       {
3656         rtx a = XEXP (mem, 0);
3657         rtx b = XEXP (mem, 1);
3659         if (GET_CODE (a) == LABEL_REF
3660             && GET_CODE (b) == CONST_INT)
3661           return \"ldr\\t%0, %1\";
3663         if (GET_CODE (b) == REG)
3664           return \"ldrsh\\t%0, %1\";
3665           
3666         ops[1] = a;
3667         ops[2] = b;
3668       }
3669     else
3670       {
3671         ops[1] = mem;
3672         ops[2] = const0_rtx;
3673       }
3675     gcc_assert (GET_CODE (ops[1]) == REG);
3677     ops[0] = operands[0];
3678     ops[3] = operands[2];
3679     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3680     return \"\";
3681   }"
3682   [(set_attr "length" "4")
3683    (set_attr "type" "load_byte")
3684    (set_attr "pool_range" "1020")]
3687 ;; We used to have an early-clobber on the scratch register here.
3688 ;; However, there's a bug somewhere in reload which means that this
3689 ;; can be partially ignored during spill allocation if the memory
3690 ;; address also needs reloading; this causes us to die later on when
3691 ;; we try to verify the operands.  Fortunately, we don't really need
3692 ;; the early-clobber: we can always use operand 0 if operand 2
3693 ;; overlaps the address.
3694 (define_insn "*thumb_extendhisi2_insn_v6"
3695   [(set (match_operand:SI 0 "register_operand" "=l,l")
3696         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3697    (clobber (match_scratch:SI 2 "=X,l"))]
3698   "TARGET_THUMB && arm_arch6"
3699   "*
3700   {
3701     rtx ops[4];
3702     rtx mem;
3704     if (which_alternative == 0)
3705       return \"sxth\\t%0, %1\";
3707     mem = XEXP (operands[1], 0);
3709     /* This code used to try to use 'V', and fix the address only if it was
3710        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3711        range of QImode offsets, and offsettable_address_p does a QImode
3712        address check.  */
3713        
3714     if (GET_CODE (mem) == CONST)
3715       mem = XEXP (mem, 0);
3716     
3717     if (GET_CODE (mem) == LABEL_REF)
3718       return \"ldr\\t%0, %1\";
3719     
3720     if (GET_CODE (mem) == PLUS)
3721       {
3722         rtx a = XEXP (mem, 0);
3723         rtx b = XEXP (mem, 1);
3725         if (GET_CODE (a) == LABEL_REF
3726             && GET_CODE (b) == CONST_INT)
3727           return \"ldr\\t%0, %1\";
3729         if (GET_CODE (b) == REG)
3730           return \"ldrsh\\t%0, %1\";
3731           
3732         ops[1] = a;
3733         ops[2] = b;
3734       }
3735     else
3736       {
3737         ops[1] = mem;
3738         ops[2] = const0_rtx;
3739       }
3740       
3741     gcc_assert (GET_CODE (ops[1]) == REG);
3743     ops[0] = operands[0];
3744     if (reg_mentioned_p (operands[2], ops[1]))
3745       ops[3] = ops[0];
3746     else
3747       ops[3] = operands[2];
3748     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3749     return \"\";
3750   }"
3751   [(set_attr "length" "2,4")
3752    (set_attr "type" "alu_shift,load_byte")
3753    (set_attr "pool_range" "*,1020")]
3756 (define_expand "extendhisi2_mem"
3757   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3758    (set (match_dup 3)
3759         (zero_extend:SI (match_dup 7)))
3760    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3761    (set (match_operand:SI 0 "" "")
3762         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3763   "TARGET_ARM"
3764   "
3765   {
3766     rtx mem1, mem2;
3767     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3769     mem1 = change_address (operands[1], QImode, addr);
3770     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3771     operands[0] = gen_lowpart (SImode, operands[0]);
3772     operands[1] = mem1;
3773     operands[2] = gen_reg_rtx (SImode);
3774     operands[3] = gen_reg_rtx (SImode);
3775     operands[6] = gen_reg_rtx (SImode);
3776     operands[7] = mem2;
3778     if (BYTES_BIG_ENDIAN)
3779       {
3780         operands[4] = operands[2];
3781         operands[5] = operands[3];
3782       }
3783     else
3784       {
3785         operands[4] = operands[3];
3786         operands[5] = operands[2];
3787       }
3788   }"
3791 (define_insn "*arm_extendhisi2"
3792   [(set (match_operand:SI 0 "s_register_operand" "=r")
3793         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3794   "TARGET_ARM && arm_arch4 && !arm_arch6"
3795   "ldr%?sh\\t%0, %1"
3796   [(set_attr "type" "load_byte")
3797    (set_attr "predicable" "yes")
3798    (set_attr "pool_range" "256")
3799    (set_attr "neg_pool_range" "244")]
3802 (define_insn "*arm_extendhisi2_v6"
3803   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3804         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3805   "TARGET_ARM && arm_arch6"
3806   "@
3807    sxth%?\\t%0, %1
3808    ldr%?sh\\t%0, %1"
3809   [(set_attr "type" "alu_shift,load_byte")
3810    (set_attr "predicable" "yes")
3811    (set_attr "pool_range" "*,256")
3812    (set_attr "neg_pool_range" "*,244")]
3815 (define_insn "*arm_extendhisi2addsi"
3816   [(set (match_operand:SI 0 "s_register_operand" "=r")
3817         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3818                  (match_operand:SI 2 "s_register_operand" "r")))]
3819   "TARGET_ARM && arm_arch6"
3820   "sxtah%?\\t%0, %2, %1"
3823 (define_expand "extendqihi2"
3824   [(set (match_dup 2)
3825         (ashift:SI (match_operand:QI 1 "general_operand" "")
3826                    (const_int 24)))
3827    (set (match_operand:HI 0 "s_register_operand" "")
3828         (ashiftrt:SI (match_dup 2)
3829                      (const_int 24)))]
3830   "TARGET_ARM"
3831   "
3832   {
3833     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3834       {
3835         emit_insn (gen_rtx_SET (VOIDmode,
3836                                 operands[0],
3837                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3838         DONE;
3839       }
3840     if (!s_register_operand (operands[1], QImode))
3841       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3842     operands[0] = gen_lowpart (SImode, operands[0]);
3843     operands[1] = gen_lowpart (SImode, operands[1]);
3844     operands[2] = gen_reg_rtx (SImode);
3845   }"
3848 (define_insn "*extendqihi_insn"
3849   [(set (match_operand:HI 0 "s_register_operand" "=r")
3850         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3851   "TARGET_ARM && arm_arch4"
3852   "ldr%?sb\\t%0, %1"
3853   [(set_attr "type" "load_byte")
3854    (set_attr "predicable" "yes")
3855    (set_attr "pool_range" "256")
3856    (set_attr "neg_pool_range" "244")]
3859 (define_expand "extendqisi2"
3860   [(set (match_dup 2)
3861         (ashift:SI (match_operand:QI 1 "general_operand" "")
3862                    (const_int 24)))
3863    (set (match_operand:SI 0 "s_register_operand" "")
3864         (ashiftrt:SI (match_dup 2)
3865                      (const_int 24)))]
3866   "TARGET_EITHER"
3867   "
3868   {
3869     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3870       {
3871         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3872                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3873         DONE;
3874       }
3876     if (!s_register_operand (operands[1], QImode))
3877       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3879     if (arm_arch6)
3880       {
3881         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3882                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3883         DONE;
3884       }
3886     operands[1] = gen_lowpart (SImode, operands[1]);
3887     operands[2] = gen_reg_rtx (SImode);
3888   }"
3891 (define_insn "*arm_extendqisi"
3892   [(set (match_operand:SI 0 "s_register_operand" "=r")
3893         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3894   "TARGET_ARM && arm_arch4 && !arm_arch6"
3895   "ldr%?sb\\t%0, %1"
3896   [(set_attr "type" "load_byte")
3897    (set_attr "predicable" "yes")
3898    (set_attr "pool_range" "256")
3899    (set_attr "neg_pool_range" "244")]
3902 (define_insn "*arm_extendqisi_v6"
3903   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3904         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3905   "TARGET_ARM && arm_arch6"
3906   "@
3907    sxtb%?\\t%0, %1
3908    ldr%?sb\\t%0, %1"
3909   [(set_attr "type" "alu_shift,load_byte")
3910    (set_attr "predicable" "yes")
3911    (set_attr "pool_range" "*,256")
3912    (set_attr "neg_pool_range" "*,244")]
3915 (define_insn "*arm_extendqisi2addsi"
3916   [(set (match_operand:SI 0 "s_register_operand" "=r")
3917         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3918                  (match_operand:SI 2 "s_register_operand" "r")))]
3919   "TARGET_ARM && arm_arch6"
3920   "sxtab%?\\t%0, %2, %1"
3921   [(set_attr "type" "alu_shift")
3922    (set_attr "predicable" "yes")]
3925 (define_insn "*thumb_extendqisi2"
3926   [(set (match_operand:SI 0 "register_operand" "=l,l")
3927         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3928   "TARGET_THUMB && !arm_arch6"
3929   "*
3930   {
3931     rtx ops[3];
3932     rtx mem = XEXP (operands[1], 0);
3933     
3934     if (GET_CODE (mem) == CONST)
3935       mem = XEXP (mem, 0);
3936     
3937     if (GET_CODE (mem) == LABEL_REF)
3938       return \"ldr\\t%0, %1\";
3940     if (GET_CODE (mem) == PLUS
3941         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3942       return \"ldr\\t%0, %1\";
3943       
3944     if (which_alternative == 0)
3945       return \"ldrsb\\t%0, %1\";
3946       
3947     ops[0] = operands[0];
3948     
3949     if (GET_CODE (mem) == PLUS)
3950       {
3951         rtx a = XEXP (mem, 0);
3952         rtx b = XEXP (mem, 1);
3953         
3954         ops[1] = a;
3955         ops[2] = b;
3957         if (GET_CODE (a) == REG)
3958           {
3959             if (GET_CODE (b) == REG)
3960               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3961             else if (REGNO (a) == REGNO (ops[0]))
3962               {
3963                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3964                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3965                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3966               }
3967             else
3968               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3969           }
3970         else
3971           {
3972             gcc_assert (GET_CODE (b) == REG);
3973             if (REGNO (b) == REGNO (ops[0]))
3974               {
3975                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", 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               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3981           }
3982       }
3983     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3984       {
3985         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3986         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3987         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3988       }
3989     else
3990       {
3991         ops[1] = mem;
3992         ops[2] = const0_rtx;
3993         
3994         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3995       }
3996     return \"\";
3997   }"
3998   [(set_attr "length" "2,6")
3999    (set_attr "type" "load_byte,load_byte")
4000    (set_attr "pool_range" "32,32")]
4003 (define_insn "*thumb_extendqisi2_v6"
4004   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
4005         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
4006   "TARGET_THUMB && arm_arch6"
4007   "*
4008   {
4009     rtx ops[3];
4010     rtx mem;
4012     if (which_alternative == 0)
4013       return \"sxtb\\t%0, %1\";
4015     mem = XEXP (operands[1], 0);
4016     
4017     if (GET_CODE (mem) == CONST)
4018       mem = XEXP (mem, 0);
4019     
4020     if (GET_CODE (mem) == LABEL_REF)
4021       return \"ldr\\t%0, %1\";
4023     if (GET_CODE (mem) == PLUS
4024         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4025       return \"ldr\\t%0, %1\";
4026       
4027     if (which_alternative == 0)
4028       return \"ldrsb\\t%0, %1\";
4029       
4030     ops[0] = operands[0];
4031     
4032     if (GET_CODE (mem) == PLUS)
4033       {
4034         rtx a = XEXP (mem, 0);
4035         rtx b = XEXP (mem, 1);
4036         
4037         ops[1] = a;
4038         ops[2] = b;
4040         if (GET_CODE (a) == REG)
4041           {
4042             if (GET_CODE (b) == REG)
4043               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4044             else if (REGNO (a) == REGNO (ops[0]))
4045               {
4046                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4047                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4048               }
4049             else
4050               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4051           }
4052         else
4053           {
4054             gcc_assert (GET_CODE (b) == REG);
4055             if (REGNO (b) == REGNO (ops[0]))
4056               {
4057                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4058                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4059               }
4060             else
4061               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4062           }
4063       }
4064     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4065       {
4066         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4067         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4068       }
4069     else
4070       {
4071         ops[1] = mem;
4072         ops[2] = const0_rtx;
4073         
4074         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4075       }
4076     return \"\";
4077   }"
4078   [(set_attr "length" "2,2,4")
4079    (set_attr "type" "alu_shift,load_byte,load_byte")
4080    (set_attr "pool_range" "*,32,32")]
4083 (define_expand "extendsfdf2"
4084   [(set (match_operand:DF                  0 "s_register_operand" "")
4085         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4086   "TARGET_ARM && TARGET_HARD_FLOAT"
4087   ""
4090 ;; Move insns (including loads and stores)
4092 ;; XXX Just some ideas about movti.
4093 ;; I don't think these are a good idea on the arm, there just aren't enough
4094 ;; registers
4095 ;;(define_expand "loadti"
4096 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4097 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4098 ;;  "" "")
4100 ;;(define_expand "storeti"
4101 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4102 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4103 ;;  "" "")
4105 ;;(define_expand "movti"
4106 ;;  [(set (match_operand:TI 0 "general_operand" "")
4107 ;;      (match_operand:TI 1 "general_operand" ""))]
4108 ;;  ""
4109 ;;  "
4111 ;;  rtx insn;
4113 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4114 ;;    operands[1] = copy_to_reg (operands[1]);
4115 ;;  if (GET_CODE (operands[0]) == MEM)
4116 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4117 ;;  else if (GET_CODE (operands[1]) == MEM)
4118 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4119 ;;  else
4120 ;;    FAIL;
4122 ;;  emit_insn (insn);
4123 ;;  DONE;
4124 ;;}")
4126 ;; Recognize garbage generated above.
4128 ;;(define_insn ""
4129 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4130 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4131 ;;  ""
4132 ;;  "*
4133 ;;  {
4134 ;;    register mem = (which_alternative < 3);
4135 ;;    register const char *template;
4137 ;;    operands[mem] = XEXP (operands[mem], 0);
4138 ;;    switch (which_alternative)
4139 ;;      {
4140 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4141 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4142 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4143 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4144 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4145 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4146 ;;      }
4147 ;;    output_asm_insn (template, operands);
4148 ;;    return \"\";
4149 ;;  }")
4151 (define_expand "movdi"
4152   [(set (match_operand:DI 0 "general_operand" "")
4153         (match_operand:DI 1 "general_operand" ""))]
4154   "TARGET_EITHER"
4155   "
4156   if (!no_new_pseudos)
4157     {
4158       if (GET_CODE (operands[0]) != REG)
4159         operands[1] = force_reg (DImode, operands[1]);
4160     }
4161   "
4164 (define_insn "*arm_movdi"
4165   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4166         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4167   "TARGET_ARM
4168    && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4169    && !TARGET_IWMMXT
4170    && (   register_operand (operands[0], DImode)
4171        || register_operand (operands[1], DImode))"
4172   "*
4173   switch (which_alternative)
4174     {
4175     case 0:
4176     case 1:
4177     case 2:
4178       return \"#\";
4179     default:
4180       return output_move_double (operands);
4181     }
4182   "
4183   [(set_attr "length" "8,12,16,8,8")
4184    (set_attr "type" "*,*,*,load2,store2")
4185    (set_attr "pool_range" "*,*,*,1020,*")
4186    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4189 (define_split
4190   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4191         (match_operand:ANY64 1 "const_double_operand" ""))]
4192   "TARGET_ARM
4193    && reload_completed
4194    && (arm_const_double_inline_cost (operands[1])
4195        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4196   [(const_int 0)]
4197   "
4198   arm_split_constant (SET, SImode, curr_insn,
4199                       INTVAL (gen_lowpart (SImode, operands[1])),
4200                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4201   arm_split_constant (SET, SImode, curr_insn,
4202                       INTVAL (gen_highpart_mode (SImode,
4203                                                  GET_MODE (operands[0]),
4204                                                  operands[1])),
4205                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4206   DONE;
4207   "
4210 ; If optimizing for size, or if we have load delay slots, then 
4211 ; we want to split the constant into two separate operations. 
4212 ; In both cases this may split a trivial part into a single data op
4213 ; leaving a single complex constant to load.  We can also get longer
4214 ; offsets in a LDR which means we get better chances of sharing the pool
4215 ; entries.  Finally, we can normally do a better job of scheduling
4216 ; LDR instructions than we can with LDM.
4217 ; This pattern will only match if the one above did not.
4218 (define_split
4219   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4220         (match_operand:ANY64 1 "const_double_operand" ""))]
4221   "TARGET_ARM && reload_completed
4222    && arm_const_double_by_parts (operands[1])"
4223   [(set (match_dup 0) (match_dup 1))
4224    (set (match_dup 2) (match_dup 3))]
4225   "
4226   operands[2] = gen_highpart (SImode, operands[0]);
4227   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4228                                    operands[1]);
4229   operands[0] = gen_lowpart (SImode, operands[0]);
4230   operands[1] = gen_lowpart (SImode, operands[1]);
4231   "
4234 (define_split
4235   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4236         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4237   "TARGET_EITHER && reload_completed"
4238   [(set (match_dup 0) (match_dup 1))
4239    (set (match_dup 2) (match_dup 3))]
4240   "
4241   operands[2] = gen_highpart (SImode, operands[0]);
4242   operands[3] = gen_highpart (SImode, operands[1]);
4243   operands[0] = gen_lowpart (SImode, operands[0]);
4244   operands[1] = gen_lowpart (SImode, operands[1]);
4246   /* Handle a partial overlap.  */
4247   if (rtx_equal_p (operands[0], operands[3]))
4248     {
4249       rtx tmp0 = operands[0];
4250       rtx tmp1 = operands[1];
4252       operands[0] = operands[2];
4253       operands[1] = operands[3];
4254       operands[2] = tmp0;
4255       operands[3] = tmp1;
4256     }
4257   "
4260 ;; We can't actually do base+index doubleword loads if the index and
4261 ;; destination overlap.  Split here so that we at least have chance to
4262 ;; schedule.
4263 (define_split
4264   [(set (match_operand:DI 0 "s_register_operand" "")
4265         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4266                          (match_operand:SI 2 "s_register_operand" ""))))]
4267   "TARGET_LDRD
4268   && reg_overlap_mentioned_p (operands[0], operands[1])
4269   && reg_overlap_mentioned_p (operands[0], operands[2])"
4270   [(set (match_dup 4)
4271         (plus:SI (match_dup 1)
4272                  (match_dup 2)))
4273    (set (match_dup 0)
4274         (mem:DI (match_dup 4)))]
4275   "
4276   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4277   "
4280 ;;; ??? This should have alternatives for constants.
4281 ;;; ??? This was originally identical to the movdf_insn pattern.
4282 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4283 ;;; thumb_reorg with a memory reference.
4284 (define_insn "*thumb_movdi_insn"
4285   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4286         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4287   "TARGET_THUMB
4288    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4289    && (   register_operand (operands[0], DImode)
4290        || register_operand (operands[1], DImode))"
4291   "*
4292   {
4293   switch (which_alternative)
4294     {
4295     default:
4296     case 0:
4297       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4298         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4299       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4300     case 1:
4301       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4302     case 2:
4303       operands[1] = GEN_INT (- INTVAL (operands[1]));
4304       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4305     case 3:
4306       return \"ldmia\\t%1, {%0, %H0}\";
4307     case 4:
4308       return \"stmia\\t%0, {%1, %H1}\";
4309     case 5:
4310       return thumb_load_double_from_address (operands);
4311     case 6:
4312       operands[2] = gen_rtx_MEM (SImode,
4313                              plus_constant (XEXP (operands[0], 0), 4));
4314       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4315       return \"\";
4316     case 7:
4317       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4318         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4319       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4320     }
4321   }"
4322   [(set_attr "length" "4,4,6,2,2,6,4,4")
4323    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4324    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4327 (define_expand "movsi"
4328   [(set (match_operand:SI 0 "general_operand" "")
4329         (match_operand:SI 1 "general_operand" ""))]
4330   "TARGET_EITHER"
4331   "
4332   if (TARGET_ARM)
4333     {
4334       /* Everything except mem = const or mem = mem can be done easily.  */
4335       if (GET_CODE (operands[0]) == MEM)
4336         operands[1] = force_reg (SImode, operands[1]);
4337       if (arm_general_register_operand (operands[0], SImode)
4338           && GET_CODE (operands[1]) == CONST_INT
4339           && !(const_ok_for_arm (INTVAL (operands[1]))
4340                || const_ok_for_arm (~INTVAL (operands[1]))))
4341         {
4342            arm_split_constant (SET, SImode, NULL_RTX,
4343                                INTVAL (operands[1]), operands[0], NULL_RTX,
4344                                optimize && !no_new_pseudos);
4345           DONE;
4346         }
4347     }
4348   else /* TARGET_THUMB....  */
4349     {
4350       if (!no_new_pseudos)
4351         {
4352           if (GET_CODE (operands[0]) != REG)
4353             operands[1] = force_reg (SImode, operands[1]);
4354         }
4355     }
4357   /* Recognize the case where operand[1] is a reference to thread-local
4358      data and load its address to a register.  */
4359   if (arm_tls_referenced_p (operands[1]))
4360     {
4361       rtx tmp = operands[1];
4362       rtx addend = NULL;
4364       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4365         {
4366           addend = XEXP (XEXP (tmp, 0), 1);
4367           tmp = XEXP (XEXP (tmp, 0), 0);
4368         }
4370       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4371       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4373       tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4374       if (addend)
4375         {
4376           tmp = gen_rtx_PLUS (SImode, tmp, addend);
4377           tmp = force_operand (tmp, operands[0]);
4378         }
4379       operands[1] = tmp;
4380     }
4381   else if (flag_pic
4382            && (CONSTANT_P (operands[1])
4383                || symbol_mentioned_p (operands[1])
4384                || label_mentioned_p (operands[1])))
4385       operands[1] = legitimize_pic_address (operands[1], SImode,
4386                                             (no_new_pseudos ? operands[0] : 0));
4387   "
4390 (define_insn "*arm_movsi_insn"
4391   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4392         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4393   "TARGET_ARM && ! TARGET_IWMMXT
4394    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4395    && (   register_operand (operands[0], SImode)
4396        || register_operand (operands[1], SImode))"
4397   "@
4398    mov%?\\t%0, %1
4399    mvn%?\\t%0, #%B1
4400    ldr%?\\t%0, %1
4401    str%?\\t%1, %0"
4402   [(set_attr "type" "*,*,load1,store1")
4403    (set_attr "predicable" "yes")
4404    (set_attr "pool_range" "*,*,4096,*")
4405    (set_attr "neg_pool_range" "*,*,4084,*")]
4408 (define_split
4409   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4410         (match_operand:SI 1 "const_int_operand" ""))]
4411   "TARGET_ARM
4412   && (!(const_ok_for_arm (INTVAL (operands[1]))
4413         || const_ok_for_arm (~INTVAL (operands[1]))))"
4414   [(clobber (const_int 0))]
4415   "
4416   arm_split_constant (SET, SImode, NULL_RTX, 
4417                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4418   DONE;
4419   "
4422 (define_insn "*thumb_movsi_insn"
4423   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4424         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4425   "TARGET_THUMB
4426    && (   register_operand (operands[0], SImode) 
4427        || register_operand (operands[1], SImode))"
4428   "@
4429    mov  %0, %1
4430    mov  %0, %1
4431    #
4432    #
4433    ldmia\\t%1, {%0}
4434    stmia\\t%0, {%1}
4435    ldr\\t%0, %1
4436    str\\t%1, %0
4437    mov\\t%0, %1"
4438   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4439    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4440    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4443 (define_split 
4444   [(set (match_operand:SI 0 "register_operand" "")
4445         (match_operand:SI 1 "const_int_operand" ""))]
4446   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4447   [(set (match_dup 0) (match_dup 1))
4448    (set (match_dup 0) (neg:SI (match_dup 0)))]
4449   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4452 (define_split 
4453   [(set (match_operand:SI 0 "register_operand" "")
4454         (match_operand:SI 1 "const_int_operand" ""))]
4455   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4456   [(set (match_dup 0) (match_dup 1))
4457    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4458   "
4459   {
4460     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4461     unsigned HOST_WIDE_INT mask = 0xff;
4462     int i;
4463     
4464     for (i = 0; i < 25; i++)
4465       if ((val & (mask << i)) == val)
4466         break;
4468     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4469     if (i == 0)
4470       FAIL;
4472     operands[1] = GEN_INT (val >> i);
4473     operands[2] = GEN_INT (i);
4474   }"
4477 ;; When generating pic, we need to load the symbol offset into a register.
4478 ;; So that the optimizer does not confuse this with a normal symbol load
4479 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4480 ;; since that is the only type of relocation we can use.
4482 ;; The rather odd constraints on the following are to force reload to leave
4483 ;; the insn alone, and to force the minipool generation pass to then move
4484 ;; the GOT symbol to memory.
4486 (define_insn "pic_load_addr_arm"
4487   [(set (match_operand:SI 0 "s_register_operand" "=r")
4488         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4489   "TARGET_ARM && flag_pic"
4490   "ldr%?\\t%0, %1"
4491   [(set_attr "type" "load1")
4492    (set (attr "pool_range")     (const_int 4096))
4493    (set (attr "neg_pool_range") (const_int 4084))]
4496 (define_insn "pic_load_addr_thumb"
4497   [(set (match_operand:SI 0 "s_register_operand" "=l")
4498         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4499   "TARGET_THUMB && flag_pic"
4500   "ldr\\t%0, %1"
4501   [(set_attr "type" "load1")
4502    (set (attr "pool_range") (const_int 1024))]
4505 ;; This variant is used for AOF assembly, since it needs to mention the
4506 ;; pic register in the rtl.
4507 (define_expand "pic_load_addr_based"
4508   [(set (match_operand:SI 0 "s_register_operand" "")
4509         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4510   "TARGET_ARM && flag_pic"
4511   "operands[2] = cfun->machine->pic_reg;"
4514 (define_insn "*pic_load_addr_based_insn"
4515   [(set (match_operand:SI 0 "s_register_operand" "=r")
4516         (unspec:SI [(match_operand 1 "" "")
4517                     (match_operand 2 "s_register_operand" "r")]
4518                    UNSPEC_PIC_SYM))]
4519   "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
4520   "*
4521 #ifdef AOF_ASSEMBLER
4522   operands[1] = aof_pic_entry (operands[1]);
4523 #endif
4524   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4525   return \"\";
4526   "
4527   [(set_attr "type" "load1")
4528    (set (attr "pool_range")
4529         (if_then_else (eq_attr "is_thumb" "yes")
4530                       (const_int 1024)
4531                       (const_int 4096)))
4532    (set (attr "neg_pool_range")
4533         (if_then_else (eq_attr "is_thumb" "yes")
4534                       (const_int 0)
4535                       (const_int 4084)))]
4538 (define_insn "pic_add_dot_plus_four"
4539   [(set (match_operand:SI 0 "register_operand" "=r")
4540         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4541                              (const (plus:SI (pc) (const_int 4))))]
4542                    UNSPEC_PIC_BASE))
4543    (use (match_operand 2 "" ""))]
4544   "TARGET_THUMB"
4545   "*
4546   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4547                                      INTVAL (operands[2]));
4548   return \"add\\t%0, %|pc\";
4549   "
4550   [(set_attr "length" "2")]
4553 (define_insn "pic_add_dot_plus_eight"
4554   [(set (match_operand:SI 0 "register_operand" "=r")
4555         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4556                              (const (plus:SI (pc) (const_int 8))))]
4557                    UNSPEC_PIC_BASE))
4558    (use (match_operand 2 "" ""))]
4559   "TARGET_ARM"
4560   "*
4561     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4562                                        INTVAL (operands[2]));
4563     return \"add%?\\t%0, %|pc, %1\";
4564   "
4565   [(set_attr "predicable" "yes")]
4568 (define_insn "tls_load_dot_plus_eight"
4569   [(set (match_operand:SI 0 "register_operand" "+r")
4570         (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4571                                      (const (plus:SI (pc) (const_int 8))))]
4572                            UNSPEC_PIC_BASE)))
4573    (use (match_operand 2 "" ""))]
4574   "TARGET_ARM"
4575   "*
4576     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4577                                        INTVAL (operands[2]));
4578     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4579   "
4580   [(set_attr "predicable" "yes")]
4583 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4584 ;; followed by a load.  These sequences can be crunched down to
4585 ;; tls_load_dot_plus_eight by a peephole.
4587 (define_peephole2
4588   [(parallel [(set (match_operand:SI 0 "register_operand" "")
4589                    (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4590                                         (const (plus:SI (pc) (const_int 8))))]
4591                               UNSPEC_PIC_BASE))
4592               (use (label_ref (match_operand 1 "" "")))])
4593    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4594   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4595   [(parallel [(set (match_dup 2)
4596                    (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4597                                                 (const (plus:SI (pc) (const_int 8))))]
4598                                       UNSPEC_PIC_BASE)))
4599               (use (label_ref (match_dup 1)))])]
4600   ""
4603 (define_expand "builtin_setjmp_receiver"
4604   [(label_ref (match_operand 0 "" ""))]
4605   "flag_pic"
4606   "
4608   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4609      register.  */
4610   if (arm_pic_register != INVALID_REGNUM)
4611     arm_load_pic_register (1UL << 3);
4612   DONE;
4615 ;; If copying one reg to another we can set the condition codes according to
4616 ;; its value.  Such a move is common after a return from subroutine and the
4617 ;; result is being tested against zero.
4619 (define_insn "*movsi_compare0"
4620   [(set (reg:CC CC_REGNUM)
4621         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4622                     (const_int 0)))
4623    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4624         (match_dup 1))]
4625   "TARGET_ARM"
4626   "@
4627    cmp%?\\t%0, #0
4628    sub%?s\\t%0, %1, #0"
4629   [(set_attr "conds" "set")]
4632 ;; Subroutine to store a half word from a register into memory.
4633 ;; Operand 0 is the source register (HImode)
4634 ;; Operand 1 is the destination address in a register (SImode)
4636 ;; In both this routine and the next, we must be careful not to spill
4637 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4638 ;; can generate unrecognizable rtl.
4640 (define_expand "storehi"
4641   [;; store the low byte
4642    (set (match_operand 1 "" "") (match_dup 3))
4643    ;; extract the high byte
4644    (set (match_dup 2)
4645         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4646    ;; store the high byte
4647    (set (match_dup 4) (match_dup 5))]
4648   "TARGET_ARM"
4649   "
4650   {
4651     rtx op1 = operands[1];
4652     rtx addr = XEXP (op1, 0);
4653     enum rtx_code code = GET_CODE (addr);
4655     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4656         || code == MINUS)
4657       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4659     operands[4] = adjust_address (op1, QImode, 1);
4660     operands[1] = adjust_address (operands[1], QImode, 0);
4661     operands[3] = gen_lowpart (QImode, operands[0]);
4662     operands[0] = gen_lowpart (SImode, operands[0]);
4663     operands[2] = gen_reg_rtx (SImode);
4664     operands[5] = gen_lowpart (QImode, operands[2]);
4665   }"
4668 (define_expand "storehi_bigend"
4669   [(set (match_dup 4) (match_dup 3))
4670    (set (match_dup 2)
4671         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4672    (set (match_operand 1 "" "") (match_dup 5))]
4673   "TARGET_ARM"
4674   "
4675   {
4676     rtx op1 = operands[1];
4677     rtx addr = XEXP (op1, 0);
4678     enum rtx_code code = GET_CODE (addr);
4680     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4681         || code == MINUS)
4682       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4684     operands[4] = adjust_address (op1, QImode, 1);
4685     operands[1] = adjust_address (operands[1], QImode, 0);
4686     operands[3] = gen_lowpart (QImode, operands[0]);
4687     operands[0] = gen_lowpart (SImode, operands[0]);
4688     operands[2] = gen_reg_rtx (SImode);
4689     operands[5] = gen_lowpart (QImode, operands[2]);
4690   }"
4693 ;; Subroutine to store a half word integer constant into memory.
4694 (define_expand "storeinthi"
4695   [(set (match_operand 0 "" "")
4696         (match_operand 1 "" ""))
4697    (set (match_dup 3) (match_dup 2))]
4698   "TARGET_ARM"
4699   "
4700   {
4701     HOST_WIDE_INT value = INTVAL (operands[1]);
4702     rtx addr = XEXP (operands[0], 0);
4703     rtx op0 = operands[0];
4704     enum rtx_code code = GET_CODE (addr);
4706     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4707         || code == MINUS)
4708       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4710     operands[1] = gen_reg_rtx (SImode);
4711     if (BYTES_BIG_ENDIAN)
4712       {
4713         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4714         if ((value & 255) == ((value >> 8) & 255))
4715           operands[2] = operands[1];
4716         else
4717           {
4718             operands[2] = gen_reg_rtx (SImode);
4719             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4720           }
4721       }
4722     else
4723       {
4724         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4725         if ((value & 255) == ((value >> 8) & 255))
4726           operands[2] = operands[1];
4727         else
4728           {
4729             operands[2] = gen_reg_rtx (SImode);
4730             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4731           }
4732       }
4734     operands[3] = adjust_address (op0, QImode, 1);
4735     operands[0] = adjust_address (operands[0], QImode, 0);
4736     operands[2] = gen_lowpart (QImode, operands[2]);
4737     operands[1] = gen_lowpart (QImode, operands[1]);
4738   }"
4741 (define_expand "storehi_single_op"
4742   [(set (match_operand:HI 0 "memory_operand" "")
4743         (match_operand:HI 1 "general_operand" ""))]
4744   "TARGET_ARM && arm_arch4"
4745   "
4746   if (!s_register_operand (operands[1], HImode))
4747     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4748   "
4751 (define_expand "movhi"
4752   [(set (match_operand:HI 0 "general_operand" "")
4753         (match_operand:HI 1 "general_operand" ""))]
4754   "TARGET_EITHER"
4755   "
4756   if (TARGET_ARM)
4757     {
4758       if (!no_new_pseudos)
4759         {
4760           if (GET_CODE (operands[0]) == MEM)
4761             {
4762               if (arm_arch4)
4763                 {
4764                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4765                   DONE;
4766                 }
4767               if (GET_CODE (operands[1]) == CONST_INT)
4768                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4769               else
4770                 {
4771                   if (GET_CODE (operands[1]) == MEM)
4772                     operands[1] = force_reg (HImode, operands[1]);
4773                   if (BYTES_BIG_ENDIAN)
4774                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4775                   else
4776                    emit_insn (gen_storehi (operands[1], operands[0]));
4777                 }
4778               DONE;
4779             }
4780           /* Sign extend a constant, and keep it in an SImode reg.  */
4781           else if (GET_CODE (operands[1]) == CONST_INT)
4782             {
4783               rtx reg = gen_reg_rtx (SImode);
4784               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4786               /* If the constant is already valid, leave it alone.  */
4787               if (!const_ok_for_arm (val))
4788                 {
4789                   /* If setting all the top bits will make the constant 
4790                      loadable in a single instruction, then set them.  
4791                      Otherwise, sign extend the number.  */
4793                   if (const_ok_for_arm (~(val | ~0xffff)))
4794                     val |= ~0xffff;
4795                   else if (val & 0x8000)
4796                     val |= ~0xffff;
4797                 }
4799               emit_insn (gen_movsi (reg, GEN_INT (val)));
4800               operands[1] = gen_lowpart (HImode, reg);
4801             }
4802           else if (arm_arch4 && optimize && !no_new_pseudos
4803                    && GET_CODE (operands[1]) == MEM)
4804             {
4805               rtx reg = gen_reg_rtx (SImode);
4807               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4808               operands[1] = gen_lowpart (HImode, reg);
4809             }
4810           else if (!arm_arch4)
4811             {
4812               if (GET_CODE (operands[1]) == MEM)
4813                 {
4814                   rtx base;
4815                   rtx offset = const0_rtx;
4816                   rtx reg = gen_reg_rtx (SImode);
4818                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4819                        || (GET_CODE (base) == PLUS
4820                            && (GET_CODE (offset = XEXP (base, 1))
4821                                == CONST_INT)
4822                            && ((INTVAL(offset) & 1) != 1)
4823                            && GET_CODE (base = XEXP (base, 0)) == REG))
4824                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4825                     {
4826                       rtx new;
4828                       new = widen_memory_access (operands[1], SImode,
4829                                                  ((INTVAL (offset) & ~3)
4830                                                   - INTVAL (offset)));
4831                       emit_insn (gen_movsi (reg, new));
4832                       if (((INTVAL (offset) & 2) != 0)
4833                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4834                         {
4835                           rtx reg2 = gen_reg_rtx (SImode);
4837                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4838                           reg = reg2;
4839                         }
4840                     }
4841                   else
4842                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4844                   operands[1] = gen_lowpart (HImode, reg);
4845                }
4846            }
4847         }
4848       /* Handle loading a large integer during reload.  */
4849       else if (GET_CODE (operands[1]) == CONST_INT
4850                && !const_ok_for_arm (INTVAL (operands[1]))
4851                && !const_ok_for_arm (~INTVAL (operands[1])))
4852         {
4853           /* Writing a constant to memory needs a scratch, which should
4854              be handled with SECONDARY_RELOADs.  */
4855           gcc_assert (GET_CODE (operands[0]) == REG);
4857           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4858           emit_insn (gen_movsi (operands[0], operands[1]));
4859           DONE;
4860        }
4861     }
4862   else /* TARGET_THUMB */
4863     {
4864       if (!no_new_pseudos)
4865         {
4866           if (GET_CODE (operands[1]) == CONST_INT)
4867             {
4868               rtx reg = gen_reg_rtx (SImode);
4870               emit_insn (gen_movsi (reg, operands[1]));
4871               operands[1] = gen_lowpart (HImode, reg);
4872             }
4874           /* ??? We shouldn't really get invalid addresses here, but this can
4875              happen if we are passed a SP (never OK for HImode/QImode) or 
4876              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4877              HImode/QImode) relative address.  */
4878           /* ??? This should perhaps be fixed elsewhere, for instance, in
4879              fixup_stack_1, by checking for other kinds of invalid addresses,
4880              e.g. a bare reference to a virtual register.  This may confuse the
4881              alpha though, which must handle this case differently.  */
4882           if (GET_CODE (operands[0]) == MEM
4883               && !memory_address_p (GET_MODE (operands[0]),
4884                                     XEXP (operands[0], 0)))
4885             operands[0]
4886               = replace_equiv_address (operands[0],
4887                                        copy_to_reg (XEXP (operands[0], 0)));
4888    
4889           if (GET_CODE (operands[1]) == MEM
4890               && !memory_address_p (GET_MODE (operands[1]),
4891                                     XEXP (operands[1], 0)))
4892             operands[1]
4893               = replace_equiv_address (operands[1],
4894                                        copy_to_reg (XEXP (operands[1], 0)));
4896           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4897             {
4898               rtx reg = gen_reg_rtx (SImode);
4900               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4901               operands[1] = gen_lowpart (HImode, reg);
4902             }
4904           if (GET_CODE (operands[0]) == MEM)
4905             operands[1] = force_reg (HImode, operands[1]);
4906         }
4907       else if (GET_CODE (operands[1]) == CONST_INT
4908                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4909         {
4910           /* Handle loading a large integer during reload.  */
4912           /* Writing a constant to memory needs a scratch, which should
4913              be handled with SECONDARY_RELOADs.  */
4914           gcc_assert (GET_CODE (operands[0]) == REG);
4916           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4917           emit_insn (gen_movsi (operands[0], operands[1]));
4918           DONE;
4919         }
4920     }
4921   "
4924 (define_insn "*thumb_movhi_insn"
4925   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4926         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4927   "TARGET_THUMB
4928    && (   register_operand (operands[0], HImode)
4929        || register_operand (operands[1], HImode))"
4930   "*
4931   switch (which_alternative)
4932     {
4933     case 0: return \"add        %0, %1, #0\";
4934     case 2: return \"strh       %1, %0\";
4935     case 3: return \"mov        %0, %1\";
4936     case 4: return \"mov        %0, %1\";
4937     case 5: return \"mov        %0, %1\";
4938     default: gcc_unreachable ();
4939     case 1:
4940       /* The stack pointer can end up being taken as an index register.
4941           Catch this case here and deal with it.  */
4942       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4943           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4944           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4945         {
4946           rtx ops[2];
4947           ops[0] = operands[0];
4948           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4949       
4950           output_asm_insn (\"mov        %0, %1\", ops);
4952           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4953     
4954         }
4955       return \"ldrh     %0, %1\";
4956     }"
4957   [(set_attr "length" "2,4,2,2,2,2")
4958    (set_attr "type" "*,load1,store1,*,*,*")]
4962 (define_expand "movhi_bytes"
4963   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4964    (set (match_dup 3)
4965         (zero_extend:SI (match_dup 6)))
4966    (set (match_operand:SI 0 "" "")
4967          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4968   "TARGET_ARM"
4969   "
4970   {
4971     rtx mem1, mem2;
4972     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4974     mem1 = change_address (operands[1], QImode, addr);
4975     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4976     operands[0] = gen_lowpart (SImode, operands[0]);
4977     operands[1] = mem1;
4978     operands[2] = gen_reg_rtx (SImode);
4979     operands[3] = gen_reg_rtx (SImode);
4980     operands[6] = mem2;
4982     if (BYTES_BIG_ENDIAN)
4983       {
4984         operands[4] = operands[2];
4985         operands[5] = operands[3];
4986       }
4987     else
4988       {
4989         operands[4] = operands[3];
4990         operands[5] = operands[2];
4991       }
4992   }"
4995 (define_expand "movhi_bigend"
4996   [(set (match_dup 2)
4997         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4998                    (const_int 16)))
4999    (set (match_dup 3)
5000         (ashiftrt:SI (match_dup 2) (const_int 16)))
5001    (set (match_operand:HI 0 "s_register_operand" "")
5002         (match_dup 4))]
5003   "TARGET_ARM"
5004   "
5005   operands[2] = gen_reg_rtx (SImode);
5006   operands[3] = gen_reg_rtx (SImode);
5007   operands[4] = gen_lowpart (HImode, operands[3]);
5008   "
5011 ;; Pattern to recognize insn generated default case above
5012 (define_insn "*movhi_insn_arch4"
5013   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
5014         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
5015   "TARGET_ARM
5016    && arm_arch4
5017    && (GET_CODE (operands[1]) != CONST_INT
5018        || const_ok_for_arm (INTVAL (operands[1]))
5019        || const_ok_for_arm (~INTVAL (operands[1])))"
5020   "@
5021    mov%?\\t%0, %1\\t%@ movhi
5022    mvn%?\\t%0, #%B1\\t%@ movhi
5023    str%?h\\t%1, %0\\t%@ movhi
5024    ldr%?h\\t%0, %1\\t%@ movhi"
5025   [(set_attr "type" "*,*,store1,load1")
5026    (set_attr "predicable" "yes")
5027    (set_attr "pool_range" "*,*,*,256")
5028    (set_attr "neg_pool_range" "*,*,*,244")]
5031 (define_insn "*movhi_bytes"
5032   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
5033         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
5034   "TARGET_ARM"
5035   "@
5036    mov%?\\t%0, %1\\t%@ movhi
5037    mvn%?\\t%0, #%B1\\t%@ movhi"
5038   [(set_attr "predicable" "yes")]
5041 (define_expand "thumb_movhi_clobber"
5042   [(set (match_operand:HI     0 "memory_operand"   "")
5043         (match_operand:HI     1 "register_operand" ""))
5044    (clobber (match_operand:DI 2 "register_operand" ""))]
5045   "TARGET_THUMB"
5046   "
5047   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
5048       && REGNO (operands[1]) <= LAST_LO_REGNUM)
5049     {
5050       emit_insn (gen_movhi (operands[0], operands[1]));
5051       DONE;
5052     }
5053   /* XXX Fixme, need to handle other cases here as well.  */
5054   gcc_unreachable ();
5055   "
5057         
5058 ;; We use a DImode scratch because we may occasionally need an additional
5059 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5060 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5061 (define_expand "reload_outhi"
5062   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5063               (match_operand:HI 1 "s_register_operand"        "r")
5064               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5065   "TARGET_EITHER"
5066   "if (TARGET_ARM)
5067      arm_reload_out_hi (operands);
5068    else
5069      thumb_reload_out_hi (operands);
5070   DONE;
5071   "
5074 (define_expand "reload_inhi"
5075   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5076               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5077               (match_operand:DI 2 "s_register_operand" "=&r")])]
5078   "TARGET_EITHER"
5079   "
5080   if (TARGET_ARM)
5081     arm_reload_in_hi (operands);
5082   else
5083     thumb_reload_out_hi (operands);
5084   DONE;
5087 (define_expand "movqi"
5088   [(set (match_operand:QI 0 "general_operand" "")
5089         (match_operand:QI 1 "general_operand" ""))]
5090   "TARGET_EITHER"
5091   "
5092   /* Everything except mem = const or mem = mem can be done easily */
5094   if (!no_new_pseudos)
5095     {
5096       if (GET_CODE (operands[1]) == CONST_INT)
5097         {
5098           rtx reg = gen_reg_rtx (SImode);
5100           emit_insn (gen_movsi (reg, operands[1]));
5101           operands[1] = gen_lowpart (QImode, reg);
5102         }
5104       if (TARGET_THUMB)
5105         {
5106           /* ??? We shouldn't really get invalid addresses here, but this can
5107              happen if we are passed a SP (never OK for HImode/QImode) or
5108              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5109              HImode/QImode) relative address.  */
5110           /* ??? This should perhaps be fixed elsewhere, for instance, in
5111              fixup_stack_1, by checking for other kinds of invalid addresses,
5112              e.g. a bare reference to a virtual register.  This may confuse the
5113              alpha though, which must handle this case differently.  */
5114           if (GET_CODE (operands[0]) == MEM
5115               && !memory_address_p (GET_MODE (operands[0]),
5116                                      XEXP (operands[0], 0)))
5117             operands[0]
5118               = replace_equiv_address (operands[0],
5119                                        copy_to_reg (XEXP (operands[0], 0)));
5120           if (GET_CODE (operands[1]) == MEM
5121               && !memory_address_p (GET_MODE (operands[1]),
5122                                     XEXP (operands[1], 0)))
5123              operands[1]
5124                = replace_equiv_address (operands[1],
5125                                         copy_to_reg (XEXP (operands[1], 0)));
5126         }
5128       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5129         {
5130           rtx reg = gen_reg_rtx (SImode);
5132           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5133           operands[1] = gen_lowpart (QImode, reg);
5134         }
5136       if (GET_CODE (operands[0]) == MEM)
5137         operands[1] = force_reg (QImode, operands[1]);
5138     }
5139   else if (TARGET_THUMB
5140            && GET_CODE (operands[1]) == CONST_INT
5141            && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5142     {
5143       /* Handle loading a large integer during reload.  */
5145       /* Writing a constant to memory needs a scratch, which should
5146          be handled with SECONDARY_RELOADs.  */
5147       gcc_assert (GET_CODE (operands[0]) == REG);
5149       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5150       emit_insn (gen_movsi (operands[0], operands[1]));
5151       DONE;
5152     }
5153   "
5157 (define_insn "*arm_movqi_insn"
5158   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5159         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5160   "TARGET_ARM
5161    && (   register_operand (operands[0], QImode)
5162        || register_operand (operands[1], QImode))"
5163   "@
5164    mov%?\\t%0, %1
5165    mvn%?\\t%0, #%B1
5166    ldr%?b\\t%0, %1
5167    str%?b\\t%1, %0"
5168   [(set_attr "type" "*,*,load1,store1")
5169    (set_attr "predicable" "yes")]
5172 (define_insn "*thumb_movqi_insn"
5173   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5174         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5175   "TARGET_THUMB
5176    && (   register_operand (operands[0], QImode)
5177        || register_operand (operands[1], QImode))"
5178   "@
5179    add\\t%0, %1, #0
5180    ldrb\\t%0, %1
5181    strb\\t%1, %0
5182    mov\\t%0, %1
5183    mov\\t%0, %1
5184    mov\\t%0, %1"
5185   [(set_attr "length" "2")
5186    (set_attr "type" "*,load1,store1,*,*,*")
5187    (set_attr "pool_range" "*,32,*,*,*,*")]
5190 (define_expand "movsf"
5191   [(set (match_operand:SF 0 "general_operand" "")
5192         (match_operand:SF 1 "general_operand" ""))]
5193   "TARGET_EITHER"
5194   "
5195   if (TARGET_ARM)
5196     {
5197       if (GET_CODE (operands[0]) == MEM)
5198         operands[1] = force_reg (SFmode, operands[1]);
5199     }
5200   else /* TARGET_THUMB */
5201     {
5202       if (!no_new_pseudos)
5203         {
5204            if (GET_CODE (operands[0]) != REG)
5205              operands[1] = force_reg (SFmode, operands[1]);
5206         }
5207     }
5208   "
5211 ;; Transform a floating-point move of a constant into a core register into
5212 ;; an SImode operation.
5213 (define_split
5214   [(set (match_operand:SF 0 "arm_general_register_operand" "")
5215         (match_operand:SF 1 "immediate_operand" ""))]
5216   "TARGET_ARM
5217    && reload_completed
5218    && GET_CODE (operands[1]) == CONST_DOUBLE"
5219   [(set (match_dup 2) (match_dup 3))]
5220   "
5221   operands[2] = gen_lowpart (SImode, operands[0]);
5222   operands[3] = gen_lowpart (SImode, operands[1]);
5223   if (operands[2] == 0 || operands[3] == 0)
5224     FAIL;
5225   "
5228 (define_insn "*arm_movsf_soft_insn"
5229   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5230         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5231   "TARGET_ARM
5232    && TARGET_SOFT_FLOAT
5233    && (GET_CODE (operands[0]) != MEM
5234        || register_operand (operands[1], SFmode))"
5235   "@
5236    mov%?\\t%0, %1
5237    ldr%?\\t%0, %1\\t%@ float
5238    str%?\\t%1, %0\\t%@ float"
5239   [(set_attr "length" "4,4,4")
5240    (set_attr "predicable" "yes")
5241    (set_attr "type" "*,load1,store1")
5242    (set_attr "pool_range" "*,4096,*")
5243    (set_attr "neg_pool_range" "*,4084,*")]
5246 ;;; ??? This should have alternatives for constants.
5247 (define_insn "*thumb_movsf_insn"
5248   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5249         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5250   "TARGET_THUMB
5251    && (   register_operand (operands[0], SFmode) 
5252        || register_operand (operands[1], SFmode))"
5253   "@
5254    add\\t%0, %1, #0
5255    ldmia\\t%1, {%0}
5256    stmia\\t%0, {%1}
5257    ldr\\t%0, %1
5258    str\\t%1, %0
5259    mov\\t%0, %1
5260    mov\\t%0, %1"
5261   [(set_attr "length" "2")
5262    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5263    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5266 (define_expand "movdf"
5267   [(set (match_operand:DF 0 "general_operand" "")
5268         (match_operand:DF 1 "general_operand" ""))]
5269   "TARGET_EITHER"
5270   "
5271   if (TARGET_ARM)
5272     {
5273       if (GET_CODE (operands[0]) == MEM)
5274         operands[1] = force_reg (DFmode, operands[1]);
5275     }
5276   else /* TARGET_THUMB */
5277     {
5278       if (!no_new_pseudos)
5279         {
5280           if (GET_CODE (operands[0]) != REG)
5281             operands[1] = force_reg (DFmode, operands[1]);
5282         }
5283     }
5284   "
5287 ;; Reloading a df mode value stored in integer regs to memory can require a
5288 ;; scratch reg.
5289 (define_expand "reload_outdf"
5290   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5291    (match_operand:DF 1 "s_register_operand" "r")
5292    (match_operand:SI 2 "s_register_operand" "=&r")]
5293   "TARGET_ARM"
5294   "
5295   {
5296     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5298     if (code == REG)
5299       operands[2] = XEXP (operands[0], 0);
5300     else if (code == POST_INC || code == PRE_DEC)
5301       {
5302         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5303         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5304         emit_insn (gen_movdi (operands[0], operands[1]));
5305         DONE;
5306       }
5307     else if (code == PRE_INC)
5308       {
5309         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5311         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5312         operands[2] = reg;
5313       }
5314     else if (code == POST_DEC)
5315       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5316     else
5317       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5318                              XEXP (XEXP (operands[0], 0), 1)));
5320     emit_insn (gen_rtx_SET (VOIDmode,
5321                             replace_equiv_address (operands[0], operands[2]),
5322                             operands[1]));
5324     if (code == POST_DEC)
5325       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5327     DONE;
5328   }"
5331 (define_insn "*movdf_soft_insn"
5332   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5333         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5334   "TARGET_ARM && TARGET_SOFT_FLOAT
5335    && (   register_operand (operands[0], DFmode)
5336        || register_operand (operands[1], DFmode))"
5337   "*
5338   switch (which_alternative)
5339     {
5340     case 0:
5341     case 1:
5342     case 2:
5343       return \"#\";
5344     default:
5345       return output_move_double (operands);
5346     }
5347   "
5348   [(set_attr "length" "8,12,16,8,8")
5349    (set_attr "type" "*,*,*,load2,store2")
5350    (set_attr "pool_range" "1020")
5351    (set_attr "neg_pool_range" "1008")]
5354 ;;; ??? This should have alternatives for constants.
5355 ;;; ??? This was originally identical to the movdi_insn pattern.
5356 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5357 ;;; thumb_reorg with a memory reference.
5358 (define_insn "*thumb_movdf_insn"
5359   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5360         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5361   "TARGET_THUMB
5362    && (   register_operand (operands[0], DFmode)
5363        || register_operand (operands[1], DFmode))"
5364   "*
5365   switch (which_alternative)
5366     {
5367     default:
5368     case 0:
5369       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5370         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5371       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5372     case 1:
5373       return \"ldmia\\t%1, {%0, %H0}\";
5374     case 2:
5375       return \"stmia\\t%0, {%1, %H1}\";
5376     case 3:
5377       return thumb_load_double_from_address (operands);
5378     case 4:
5379       operands[2] = gen_rtx_MEM (SImode,
5380                                  plus_constant (XEXP (operands[0], 0), 4));
5381       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5382       return \"\";
5383     case 5:
5384       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5385         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5386       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5387     }
5388   "
5389   [(set_attr "length" "4,2,2,6,4,4")
5390    (set_attr "type" "*,load2,store2,load2,store2,*")
5391    (set_attr "pool_range" "*,*,*,1020,*,*")]
5394 (define_expand "movxf"
5395   [(set (match_operand:XF 0 "general_operand" "")
5396         (match_operand:XF 1 "general_operand" ""))]
5397   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5398   "
5399   if (GET_CODE (operands[0]) == MEM)
5400     operands[1] = force_reg (XFmode, operands[1]);
5401   "
5404 ;; Vector Moves
5405 (define_expand "movv2si"
5406   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5407         (match_operand:V2SI 1 "general_operand" ""))]
5408   "TARGET_REALLY_IWMMXT"
5412 (define_expand "movv4hi"
5413   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5414         (match_operand:V4HI 1 "general_operand" ""))]
5415   "TARGET_REALLY_IWMMXT"
5419 (define_expand "movv8qi"
5420   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5421         (match_operand:V8QI 1 "general_operand" ""))]
5422   "TARGET_REALLY_IWMMXT"
5427 ;; load- and store-multiple insns
5428 ;; The arm can load/store any set of registers, provided that they are in
5429 ;; ascending order; but that is beyond GCC so stick with what it knows.
5431 (define_expand "load_multiple"
5432   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5433                           (match_operand:SI 1 "" ""))
5434                      (use (match_operand:SI 2 "" ""))])]
5435   "TARGET_ARM"
5437   HOST_WIDE_INT offset = 0;
5439   /* Support only fixed point registers.  */
5440   if (GET_CODE (operands[2]) != CONST_INT
5441       || INTVAL (operands[2]) > 14
5442       || INTVAL (operands[2]) < 2
5443       || GET_CODE (operands[1]) != MEM
5444       || GET_CODE (operands[0]) != REG
5445       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5446       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5447     FAIL;
5449   operands[3]
5450     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5451                              force_reg (SImode, XEXP (operands[1], 0)),
5452                              TRUE, FALSE, operands[1], &offset);
5455 ;; Load multiple with write-back
5457 (define_insn "*ldmsi_postinc4"
5458   [(match_parallel 0 "load_multiple_operation"
5459     [(set (match_operand:SI 1 "s_register_operand" "=r")
5460           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5461                    (const_int 16)))
5462      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5463           (mem:SI (match_dup 2)))
5464      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5465           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5466      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5467           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5468      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5469           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5470   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5471   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5472   [(set_attr "type" "load4")
5473    (set_attr "predicable" "yes")]
5476 (define_insn "*ldmsi_postinc4_thumb"
5477   [(match_parallel 0 "load_multiple_operation"
5478     [(set (match_operand:SI 1 "s_register_operand" "=l")
5479           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5480                    (const_int 16)))
5481      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5482           (mem:SI (match_dup 2)))
5483      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5484           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5485      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5486           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5487      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5488           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5489   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5490   "ldmia\\t%1!, {%3, %4, %5, %6}"
5491   [(set_attr "type" "load4")]
5494 (define_insn "*ldmsi_postinc3"
5495   [(match_parallel 0 "load_multiple_operation"
5496     [(set (match_operand:SI 1 "s_register_operand" "=r")
5497           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5498                    (const_int 12)))
5499      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5500           (mem:SI (match_dup 2)))
5501      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5502           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5503      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5504           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5505   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5506   "ldm%?ia\\t%1!, {%3, %4, %5}"
5507   [(set_attr "type" "load3")
5508    (set_attr "predicable" "yes")]
5511 (define_insn "*ldmsi_postinc2"
5512   [(match_parallel 0 "load_multiple_operation"
5513     [(set (match_operand:SI 1 "s_register_operand" "=r")
5514           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5515                    (const_int 8)))
5516      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5517           (mem:SI (match_dup 2)))
5518      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5519           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5520   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5521   "ldm%?ia\\t%1!, {%3, %4}"
5522   [(set_attr "type" "load2")
5523    (set_attr "predicable" "yes")]
5526 ;; Ordinary load multiple
5528 (define_insn "*ldmsi4"
5529   [(match_parallel 0 "load_multiple_operation"
5530     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5531           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5532      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5533           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5534      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5535           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5536      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5537           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5538   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5539   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5540   [(set_attr "type" "load4")
5541    (set_attr "predicable" "yes")]
5544 (define_insn "*ldmsi3"
5545   [(match_parallel 0 "load_multiple_operation"
5546     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5547           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5548      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5549           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5550      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5551           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5552   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5553   "ldm%?ia\\t%1, {%2, %3, %4}"
5554   [(set_attr "type" "load3")
5555    (set_attr "predicable" "yes")]
5558 (define_insn "*ldmsi2"
5559   [(match_parallel 0 "load_multiple_operation"
5560     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5561           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5562      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5563           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5564   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5565   "ldm%?ia\\t%1, {%2, %3}"
5566   [(set_attr "type" "load2")
5567    (set_attr "predicable" "yes")]
5570 (define_expand "store_multiple"
5571   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5572                           (match_operand:SI 1 "" ""))
5573                      (use (match_operand:SI 2 "" ""))])]
5574   "TARGET_ARM"
5576   HOST_WIDE_INT offset = 0;
5578   /* Support only fixed point registers.  */
5579   if (GET_CODE (operands[2]) != CONST_INT
5580       || INTVAL (operands[2]) > 14
5581       || INTVAL (operands[2]) < 2
5582       || GET_CODE (operands[1]) != REG
5583       || GET_CODE (operands[0]) != MEM
5584       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5585       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5586     FAIL;
5588   operands[3]
5589     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5590                               force_reg (SImode, XEXP (operands[0], 0)),
5591                               TRUE, FALSE, operands[0], &offset);
5594 ;; Store multiple with write-back
5596 (define_insn "*stmsi_postinc4"
5597   [(match_parallel 0 "store_multiple_operation"
5598     [(set (match_operand:SI 1 "s_register_operand" "=r")
5599           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5600                    (const_int 16)))
5601      (set (mem:SI (match_dup 2))
5602           (match_operand:SI 3 "arm_hard_register_operand" ""))
5603      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5604           (match_operand:SI 4 "arm_hard_register_operand" ""))
5605      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5606           (match_operand:SI 5 "arm_hard_register_operand" ""))
5607      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5608           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5609   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5610   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5611   [(set_attr "predicable" "yes")
5612    (set_attr "type" "store4")]
5615 (define_insn "*stmsi_postinc4_thumb"
5616   [(match_parallel 0 "store_multiple_operation"
5617     [(set (match_operand:SI 1 "s_register_operand" "=l")
5618           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5619                    (const_int 16)))
5620      (set (mem:SI (match_dup 2))
5621           (match_operand:SI 3 "arm_hard_register_operand" ""))
5622      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5623           (match_operand:SI 4 "arm_hard_register_operand" ""))
5624      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5625           (match_operand:SI 5 "arm_hard_register_operand" ""))
5626      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5627           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5628   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5629   "stmia\\t%1!, {%3, %4, %5, %6}"
5630   [(set_attr "type" "store4")]
5633 (define_insn "*stmsi_postinc3"
5634   [(match_parallel 0 "store_multiple_operation"
5635     [(set (match_operand:SI 1 "s_register_operand" "=r")
5636           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5637                    (const_int 12)))
5638      (set (mem:SI (match_dup 2))
5639           (match_operand:SI 3 "arm_hard_register_operand" ""))
5640      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5641           (match_operand:SI 4 "arm_hard_register_operand" ""))
5642      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5643           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5644   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5645   "stm%?ia\\t%1!, {%3, %4, %5}"
5646   [(set_attr "predicable" "yes")
5647    (set_attr "type" "store3")]
5650 (define_insn "*stmsi_postinc2"
5651   [(match_parallel 0 "store_multiple_operation"
5652     [(set (match_operand:SI 1 "s_register_operand" "=r")
5653           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5654                    (const_int 8)))
5655      (set (mem:SI (match_dup 2))
5656           (match_operand:SI 3 "arm_hard_register_operand" ""))
5657      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5658           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5659   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5660   "stm%?ia\\t%1!, {%3, %4}"
5661   [(set_attr "predicable" "yes")
5662    (set_attr "type" "store2")]
5665 ;; Ordinary store multiple
5667 (define_insn "*stmsi4"
5668   [(match_parallel 0 "store_multiple_operation"
5669     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5670           (match_operand:SI 2 "arm_hard_register_operand" ""))
5671      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5672           (match_operand:SI 3 "arm_hard_register_operand" ""))
5673      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5674           (match_operand:SI 4 "arm_hard_register_operand" ""))
5675      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5676           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5677   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5678   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5679   [(set_attr "predicable" "yes")
5680    (set_attr "type" "store4")]
5683 (define_insn "*stmsi3"
5684   [(match_parallel 0 "store_multiple_operation"
5685     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5686           (match_operand:SI 2 "arm_hard_register_operand" ""))
5687      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5688           (match_operand:SI 3 "arm_hard_register_operand" ""))
5689      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5690           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5691   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5692   "stm%?ia\\t%1, {%2, %3, %4}"
5693   [(set_attr "predicable" "yes")
5694    (set_attr "type" "store3")]
5697 (define_insn "*stmsi2"
5698   [(match_parallel 0 "store_multiple_operation"
5699     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5700           (match_operand:SI 2 "arm_hard_register_operand" ""))
5701      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5702           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5703   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5704   "stm%?ia\\t%1, {%2, %3}"
5705   [(set_attr "predicable" "yes")
5706    (set_attr "type" "store2")]
5709 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5710 ;; We could let this apply for blocks of less than this, but it clobbers so
5711 ;; many registers that there is then probably a better way.
5713 (define_expand "movmemqi"
5714   [(match_operand:BLK 0 "general_operand" "")
5715    (match_operand:BLK 1 "general_operand" "")
5716    (match_operand:SI 2 "const_int_operand" "")
5717    (match_operand:SI 3 "const_int_operand" "")]
5718   "TARGET_EITHER"
5719   "
5720   if (TARGET_ARM)
5721     {
5722       if (arm_gen_movmemqi (operands))
5723         DONE;
5724       FAIL;
5725     }
5726   else /* TARGET_THUMB */
5727     {
5728       if (   INTVAL (operands[3]) != 4
5729           || INTVAL (operands[2]) > 48)
5730         FAIL;
5732       thumb_expand_movmemqi (operands);
5733       DONE;
5734     }
5735   "
5738 ;; Thumb block-move insns
5740 (define_insn "movmem12b"
5741   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5742         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5743    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5744         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5745    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5746         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5747    (set (match_operand:SI 0 "register_operand" "=l")
5748         (plus:SI (match_dup 2) (const_int 12)))
5749    (set (match_operand:SI 1 "register_operand" "=l")
5750         (plus:SI (match_dup 3) (const_int 12)))
5751    (clobber (match_scratch:SI 4 "=&l"))
5752    (clobber (match_scratch:SI 5 "=&l"))
5753    (clobber (match_scratch:SI 6 "=&l"))]
5754   "TARGET_THUMB"
5755   "* return thumb_output_move_mem_multiple (3, operands);"
5756   [(set_attr "length" "4")
5757    ; This isn't entirely accurate...  It loads as well, but in terms of
5758    ; scheduling the following insn it is better to consider it as a store
5759    (set_attr "type" "store3")]
5762 (define_insn "movmem8b"
5763   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5764         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5765    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5766         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5767    (set (match_operand:SI 0 "register_operand" "=l")
5768         (plus:SI (match_dup 2) (const_int 8)))
5769    (set (match_operand:SI 1 "register_operand" "=l")
5770         (plus:SI (match_dup 3) (const_int 8)))
5771    (clobber (match_scratch:SI 4 "=&l"))
5772    (clobber (match_scratch:SI 5 "=&l"))]
5773   "TARGET_THUMB"
5774   "* return thumb_output_move_mem_multiple (2, operands);"
5775   [(set_attr "length" "4")
5776    ; This isn't entirely accurate...  It loads as well, but in terms of
5777    ; scheduling the following insn it is better to consider it as a store
5778    (set_attr "type" "store2")]
5783 ;; Compare & branch insns
5784 ;; The range calculations are based as follows:
5785 ;; For forward branches, the address calculation returns the address of
5786 ;; the next instruction.  This is 2 beyond the branch instruction.
5787 ;; For backward branches, the address calculation returns the address of
5788 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5789 ;; instruction for the shortest sequence, and 4 before the branch instruction
5790 ;; if we have to jump around an unconditional branch.
5791 ;; To the basic branch range the PC offset must be added (this is +4).
5792 ;; So for forward branches we have 
5793 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5794 ;; And for backward branches we have 
5795 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5797 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5798 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5800 (define_expand "cbranchsi4"
5801   [(set (pc) (if_then_else
5802               (match_operator 0 "arm_comparison_operator"
5803                [(match_operand:SI 1 "s_register_operand" "")
5804                 (match_operand:SI 2 "nonmemory_operand" "")])
5805               (label_ref (match_operand 3 "" ""))
5806               (pc)))]
5807   "TARGET_THUMB"
5808   "
5809   if (thumb_cmpneg_operand (operands[2], SImode))
5810     {
5811       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5812                                               operands[3], operands[0]));
5813       DONE;
5814     }
5815   if (!thumb_cmp_operand (operands[2], SImode))
5816     operands[2] = force_reg (SImode, operands[2]);
5817   ")
5819 (define_insn "*cbranchsi4_insn"
5820   [(set (pc) (if_then_else
5821               (match_operator 0 "arm_comparison_operator"
5822                [(match_operand:SI 1 "s_register_operand" "l,*h")
5823                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5824               (label_ref (match_operand 3 "" ""))
5825               (pc)))]
5826   "TARGET_THUMB"
5827   "*
5828   output_asm_insn (\"cmp\\t%1, %2\", operands);
5830   switch (get_attr_length (insn))
5831     {
5832     case 4:  return \"b%d0\\t%l3\";
5833     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5834     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5835     }
5836   "
5837   [(set (attr "far_jump")
5838         (if_then_else
5839             (eq_attr "length" "8")
5840             (const_string "yes")
5841             (const_string "no")))
5842    (set (attr "length") 
5843         (if_then_else
5844             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5845                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5846             (const_int 4)
5847             (if_then_else
5848                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5849                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5850                 (const_int 6)
5851                 (const_int 8))))]
5854 (define_insn "cbranchsi4_scratch"
5855   [(set (pc) (if_then_else
5856               (match_operator 4 "arm_comparison_operator"
5857                [(match_operand:SI 1 "s_register_operand" "l,0")
5858                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5859               (label_ref (match_operand 3 "" ""))
5860               (pc)))
5861    (clobber (match_scratch:SI 0 "=l,l"))]
5862   "TARGET_THUMB"
5863   "*
5864   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5866   switch (get_attr_length (insn))
5867     {
5868     case 4:  return \"b%d4\\t%l3\";
5869     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5870     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5871     }
5872   "
5873   [(set (attr "far_jump")
5874         (if_then_else
5875             (eq_attr "length" "8")
5876             (const_string "yes")
5877             (const_string "no")))
5878    (set (attr "length") 
5879         (if_then_else
5880             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5881                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5882             (const_int 4)
5883             (if_then_else
5884                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5885                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5886                 (const_int 6)
5887                 (const_int 8))))]
5889 (define_insn "*movsi_cbranchsi4"
5890   [(set (pc)
5891         (if_then_else
5892          (match_operator 3 "arm_comparison_operator"
5893           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5894            (const_int 0)])
5895          (label_ref (match_operand 2 "" ""))
5896          (pc)))
5897    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5898         (match_dup 1))]
5899   "TARGET_THUMB"
5900   "*{
5901   if (which_alternative == 0)
5902     output_asm_insn (\"cmp\t%0, #0\", operands);
5903   else if (which_alternative == 1)
5904     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5905   else
5906     {
5907       output_asm_insn (\"cmp\t%1, #0\", operands);
5908       if (which_alternative == 2)
5909         output_asm_insn (\"mov\t%0, %1\", operands);
5910       else
5911         output_asm_insn (\"str\t%1, %0\", operands);
5912     }
5913   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5914     {
5915     case 4:  return \"b%d3\\t%l2\";
5916     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5917     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5918     }
5919   }"
5920   [(set (attr "far_jump")
5921         (if_then_else
5922             (ior (and (gt (symbol_ref ("which_alternative"))
5923                           (const_int 1))
5924                       (eq_attr "length" "8"))
5925                  (eq_attr "length" "10"))
5926             (const_string "yes")
5927             (const_string "no")))
5928    (set (attr "length")
5929      (if_then_else
5930        (le (symbol_ref ("which_alternative"))
5931                        (const_int 1))
5932        (if_then_else
5933          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5934               (le (minus (match_dup 2) (pc)) (const_int 256)))
5935          (const_int 4)
5936          (if_then_else
5937            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5938                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5939            (const_int 6)
5940            (const_int 8)))
5941        (if_then_else
5942          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5943               (le (minus (match_dup 2) (pc)) (const_int 256)))
5944          (const_int 6)
5945          (if_then_else
5946            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5947                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5948            (const_int 8)
5949            (const_int 10)))))]
5952 (define_insn "*negated_cbranchsi4"
5953   [(set (pc)
5954         (if_then_else
5955          (match_operator 0 "equality_operator"
5956           [(match_operand:SI 1 "s_register_operand" "l")
5957            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5958          (label_ref (match_operand 3 "" ""))
5959          (pc)))]
5960   "TARGET_THUMB"
5961   "*
5962   output_asm_insn (\"cmn\\t%1, %2\", operands);
5963   switch (get_attr_length (insn))
5964     {
5965     case 4:  return \"b%d0\\t%l3\";
5966     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5967     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5968     }
5969   "
5970   [(set (attr "far_jump")
5971         (if_then_else
5972             (eq_attr "length" "8")
5973             (const_string "yes")
5974             (const_string "no")))
5975    (set (attr "length") 
5976         (if_then_else
5977             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5978                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5979             (const_int 4)
5980             (if_then_else
5981                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5982                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5983                 (const_int 6)
5984                 (const_int 8))))]
5987 (define_insn "*tbit_cbranch"
5988   [(set (pc)
5989         (if_then_else
5990          (match_operator 0 "equality_operator"
5991           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5992                             (const_int 1)
5993                             (match_operand:SI 2 "const_int_operand" "i"))
5994            (const_int 0)])
5995          (label_ref (match_operand 3 "" ""))
5996          (pc)))
5997    (clobber (match_scratch:SI 4 "=l"))]
5998   "TARGET_THUMB"
5999   "*
6000   {
6001   rtx op[3];
6002   op[0] = operands[4];
6003   op[1] = operands[1];
6004   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
6006   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6007   switch (get_attr_length (insn))
6008     {
6009     case 4:  return \"b%d0\\t%l3\";
6010     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6011     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6012     }
6013   }"
6014   [(set (attr "far_jump")
6015         (if_then_else
6016             (eq_attr "length" "8")
6017             (const_string "yes")
6018             (const_string "no")))
6019    (set (attr "length") 
6020         (if_then_else
6021             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6022                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6023             (const_int 4)
6024             (if_then_else
6025                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6026                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6027                 (const_int 6)
6028                 (const_int 8))))]
6030   
6031 (define_insn "*tlobits_cbranch"
6032   [(set (pc)
6033         (if_then_else
6034          (match_operator 0 "equality_operator"
6035           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
6036                             (match_operand:SI 2 "const_int_operand" "i")
6037                             (const_int 0))
6038            (const_int 0)])
6039          (label_ref (match_operand 3 "" ""))
6040          (pc)))
6041    (clobber (match_scratch:SI 4 "=l"))]
6042   "TARGET_THUMB"
6043   "*
6044   {
6045   rtx op[3];
6046   op[0] = operands[4];
6047   op[1] = operands[1];
6048   op[2] = GEN_INT (32 - INTVAL (operands[2]));
6050   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
6051   switch (get_attr_length (insn))
6052     {
6053     case 4:  return \"b%d0\\t%l3\";
6054     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6055     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6056     }
6057   }"
6058   [(set (attr "far_jump")
6059         (if_then_else
6060             (eq_attr "length" "8")
6061             (const_string "yes")
6062             (const_string "no")))
6063    (set (attr "length") 
6064         (if_then_else
6065             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6066                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6067             (const_int 4)
6068             (if_then_else
6069                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6070                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6071                 (const_int 6)
6072                 (const_int 8))))]
6074   
6075 (define_insn "*tstsi3_cbranch"
6076   [(set (pc)
6077         (if_then_else
6078          (match_operator 3 "equality_operator"
6079           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
6080                    (match_operand:SI 1 "s_register_operand" "l"))
6081            (const_int 0)])
6082          (label_ref (match_operand 2 "" ""))
6083          (pc)))]
6084   "TARGET_THUMB"
6085   "*
6086   {
6087   output_asm_insn (\"tst\\t%0, %1\", operands);
6088   switch (get_attr_length (insn))
6089     {
6090     case 4:  return \"b%d3\\t%l2\";
6091     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
6092     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
6093     }
6094   }"
6095   [(set (attr "far_jump")
6096         (if_then_else
6097             (eq_attr "length" "8")
6098             (const_string "yes")
6099             (const_string "no")))
6100    (set (attr "length") 
6101         (if_then_else
6102             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
6103                  (le (minus (match_dup 2) (pc)) (const_int 256)))
6104             (const_int 4)
6105             (if_then_else
6106                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6107                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
6108                 (const_int 6)
6109                 (const_int 8))))]
6111   
6112 (define_insn "*andsi3_cbranch"
6113   [(set (pc)
6114         (if_then_else
6115          (match_operator 5 "equality_operator"
6116           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6117                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6118            (const_int 0)])
6119          (label_ref (match_operand 4 "" ""))
6120          (pc)))
6121    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6122         (and:SI (match_dup 2) (match_dup 3)))
6123    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6124   "TARGET_THUMB"
6125   "*
6126   {
6127   if (which_alternative == 0)
6128     output_asm_insn (\"and\\t%0, %3\", operands);
6129   else if (which_alternative == 1)
6130     {
6131       output_asm_insn (\"and\\t%1, %3\", operands);
6132       output_asm_insn (\"mov\\t%0, %1\", operands);
6133     }
6134   else
6135     {
6136       output_asm_insn (\"and\\t%1, %3\", operands);
6137       output_asm_insn (\"str\\t%1, %0\", operands);
6138     }
6140   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6141     {
6142     case 4:  return \"b%d5\\t%l4\";
6143     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6144     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6145     }
6146   }"
6147   [(set (attr "far_jump")
6148         (if_then_else
6149             (ior (and (eq (symbol_ref ("which_alternative"))
6150                           (const_int 0))
6151                       (eq_attr "length" "8"))
6152                  (eq_attr "length" "10"))
6153             (const_string "yes")
6154             (const_string "no")))
6155    (set (attr "length")
6156      (if_then_else
6157        (eq (symbol_ref ("which_alternative"))
6158                        (const_int 0))
6159        (if_then_else
6160          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6161               (le (minus (match_dup 4) (pc)) (const_int 256)))
6162          (const_int 4)
6163          (if_then_else
6164            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6165                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6166            (const_int 6)
6167            (const_int 8)))
6168        (if_then_else
6169          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6170               (le (minus (match_dup 4) (pc)) (const_int 256)))
6171          (const_int 6)
6172          (if_then_else
6173            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6174                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6175            (const_int 8)
6176            (const_int 10)))))]
6179 (define_insn "*orrsi3_cbranch_scratch"
6180   [(set (pc)
6181         (if_then_else
6182          (match_operator 4 "equality_operator"
6183           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6184                    (match_operand:SI 2 "s_register_operand" "l"))
6185            (const_int 0)])
6186          (label_ref (match_operand 3 "" ""))
6187          (pc)))
6188    (clobber (match_scratch:SI 0 "=l"))]
6189   "TARGET_THUMB"
6190   "*
6191   {
6192   output_asm_insn (\"orr\\t%0, %2\", operands);
6193   switch (get_attr_length (insn))
6194     {
6195     case 4:  return \"b%d4\\t%l3\";
6196     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6197     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6198     }
6199   }"
6200   [(set (attr "far_jump")
6201         (if_then_else
6202             (eq_attr "length" "8")
6203             (const_string "yes")
6204             (const_string "no")))
6205    (set (attr "length") 
6206         (if_then_else
6207             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6208                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6209             (const_int 4)
6210             (if_then_else
6211                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6212                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6213                 (const_int 6)
6214                 (const_int 8))))]
6216   
6217 (define_insn "*orrsi3_cbranch"
6218   [(set (pc)
6219         (if_then_else
6220          (match_operator 5 "equality_operator"
6221           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6222                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6223            (const_int 0)])
6224          (label_ref (match_operand 4 "" ""))
6225          (pc)))
6226    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6227         (ior:SI (match_dup 2) (match_dup 3)))
6228    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6229   "TARGET_THUMB"
6230   "*
6231   {
6232   if (which_alternative == 0)
6233     output_asm_insn (\"orr\\t%0, %3\", operands);
6234   else if (which_alternative == 1)
6235     {
6236       output_asm_insn (\"orr\\t%1, %3\", operands);
6237       output_asm_insn (\"mov\\t%0, %1\", operands);
6238     }
6239   else
6240     {
6241       output_asm_insn (\"orr\\t%1, %3\", operands);
6242       output_asm_insn (\"str\\t%1, %0\", operands);
6243     }
6245   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6246     {
6247     case 4:  return \"b%d5\\t%l4\";
6248     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6249     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6250     }
6251   }"
6252   [(set (attr "far_jump")
6253         (if_then_else
6254             (ior (and (eq (symbol_ref ("which_alternative"))
6255                           (const_int 0))
6256                       (eq_attr "length" "8"))
6257                  (eq_attr "length" "10"))
6258             (const_string "yes")
6259             (const_string "no")))
6260    (set (attr "length")
6261      (if_then_else
6262        (eq (symbol_ref ("which_alternative"))
6263                        (const_int 0))
6264        (if_then_else
6265          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6266               (le (minus (match_dup 4) (pc)) (const_int 256)))
6267          (const_int 4)
6268          (if_then_else
6269            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6270                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6271            (const_int 6)
6272            (const_int 8)))
6273        (if_then_else
6274          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6275               (le (minus (match_dup 4) (pc)) (const_int 256)))
6276          (const_int 6)
6277          (if_then_else
6278            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6279                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6280            (const_int 8)
6281            (const_int 10)))))]
6284 (define_insn "*xorsi3_cbranch_scratch"
6285   [(set (pc)
6286         (if_then_else
6287          (match_operator 4 "equality_operator"
6288           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6289                    (match_operand:SI 2 "s_register_operand" "l"))
6290            (const_int 0)])
6291          (label_ref (match_operand 3 "" ""))
6292          (pc)))
6293    (clobber (match_scratch:SI 0 "=l"))]
6294   "TARGET_THUMB"
6295   "*
6296   {
6297   output_asm_insn (\"eor\\t%0, %2\", operands);
6298   switch (get_attr_length (insn))
6299     {
6300     case 4:  return \"b%d4\\t%l3\";
6301     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6302     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6303     }
6304   }"
6305   [(set (attr "far_jump")
6306         (if_then_else
6307             (eq_attr "length" "8")
6308             (const_string "yes")
6309             (const_string "no")))
6310    (set (attr "length") 
6311         (if_then_else
6312             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6313                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6314             (const_int 4)
6315             (if_then_else
6316                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6317                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6318                 (const_int 6)
6319                 (const_int 8))))]
6321   
6322 (define_insn "*xorsi3_cbranch"
6323   [(set (pc)
6324         (if_then_else
6325          (match_operator 5 "equality_operator"
6326           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6327                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6328            (const_int 0)])
6329          (label_ref (match_operand 4 "" ""))
6330          (pc)))
6331    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6332         (xor:SI (match_dup 2) (match_dup 3)))
6333    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6334   "TARGET_THUMB"
6335   "*
6336   {
6337   if (which_alternative == 0)
6338     output_asm_insn (\"eor\\t%0, %3\", operands);
6339   else if (which_alternative == 1)
6340     {
6341       output_asm_insn (\"eor\\t%1, %3\", operands);
6342       output_asm_insn (\"mov\\t%0, %1\", operands);
6343     }
6344   else
6345     {
6346       output_asm_insn (\"eor\\t%1, %3\", operands);
6347       output_asm_insn (\"str\\t%1, %0\", operands);
6348     }
6350   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6351     {
6352     case 4:  return \"b%d5\\t%l4\";
6353     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6354     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6355     }
6356   }"
6357   [(set (attr "far_jump")
6358         (if_then_else
6359             (ior (and (eq (symbol_ref ("which_alternative"))
6360                           (const_int 0))
6361                       (eq_attr "length" "8"))
6362                  (eq_attr "length" "10"))
6363             (const_string "yes")
6364             (const_string "no")))
6365    (set (attr "length")
6366      (if_then_else
6367        (eq (symbol_ref ("which_alternative"))
6368                        (const_int 0))
6369        (if_then_else
6370          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6371               (le (minus (match_dup 4) (pc)) (const_int 256)))
6372          (const_int 4)
6373          (if_then_else
6374            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6375                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6376            (const_int 6)
6377            (const_int 8)))
6378        (if_then_else
6379          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6380               (le (minus (match_dup 4) (pc)) (const_int 256)))
6381          (const_int 6)
6382          (if_then_else
6383            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6384                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6385            (const_int 8)
6386            (const_int 10)))))]
6389 (define_insn "*bicsi3_cbranch_scratch"
6390   [(set (pc)
6391         (if_then_else
6392          (match_operator 4 "equality_operator"
6393           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6394                    (match_operand:SI 1 "s_register_operand" "0"))
6395            (const_int 0)])
6396          (label_ref (match_operand 3 "" ""))
6397          (pc)))
6398    (clobber (match_scratch:SI 0 "=l"))]
6399   "TARGET_THUMB"
6400   "*
6401   {
6402   output_asm_insn (\"bic\\t%0, %2\", operands);
6403   switch (get_attr_length (insn))
6404     {
6405     case 4:  return \"b%d4\\t%l3\";
6406     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6407     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6408     }
6409   }"
6410   [(set (attr "far_jump")
6411         (if_then_else
6412             (eq_attr "length" "8")
6413             (const_string "yes")
6414             (const_string "no")))
6415    (set (attr "length") 
6416         (if_then_else
6417             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6418                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6419             (const_int 4)
6420             (if_then_else
6421                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6422                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6423                 (const_int 6)
6424                 (const_int 8))))]
6426   
6427 (define_insn "*bicsi3_cbranch"
6428   [(set (pc)
6429         (if_then_else
6430          (match_operator 5 "equality_operator"
6431           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6432                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6433            (const_int 0)])
6434          (label_ref (match_operand 4 "" ""))
6435          (pc)))
6436    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6437         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6438    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6439   "TARGET_THUMB"
6440   "*
6441   {
6442   if (which_alternative == 0)
6443     output_asm_insn (\"bic\\t%0, %3\", operands);
6444   else if (which_alternative <= 2)
6445     {
6446       output_asm_insn (\"bic\\t%1, %3\", operands);
6447       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6448          conditions again, since we're only testing for equality.  */
6449       output_asm_insn (\"mov\\t%0, %1\", operands);
6450     }
6451   else
6452     {
6453       output_asm_insn (\"bic\\t%1, %3\", operands);
6454       output_asm_insn (\"str\\t%1, %0\", operands);
6455     }
6457   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6458     {
6459     case 4:  return \"b%d5\\t%l4\";
6460     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6461     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6462     }
6463   }"
6464   [(set (attr "far_jump")
6465         (if_then_else
6466             (ior (and (eq (symbol_ref ("which_alternative"))
6467                           (const_int 0))
6468                       (eq_attr "length" "8"))
6469                  (eq_attr "length" "10"))
6470             (const_string "yes")
6471             (const_string "no")))
6472    (set (attr "length")
6473      (if_then_else
6474        (eq (symbol_ref ("which_alternative"))
6475                        (const_int 0))
6476        (if_then_else
6477          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6478               (le (minus (match_dup 4) (pc)) (const_int 256)))
6479          (const_int 4)
6480          (if_then_else
6481            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6482                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6483            (const_int 6)
6484            (const_int 8)))
6485        (if_then_else
6486          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6487               (le (minus (match_dup 4) (pc)) (const_int 256)))
6488          (const_int 6)
6489          (if_then_else
6490            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6491                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6492            (const_int 8)
6493            (const_int 10)))))]
6496 (define_insn "*cbranchne_decr1"
6497   [(set (pc)
6498         (if_then_else (match_operator 3 "equality_operator"
6499                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6500                         (const_int 0)])
6501                       (label_ref (match_operand 4 "" ""))
6502                       (pc)))
6503    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6504         (plus:SI (match_dup 2) (const_int -1)))
6505    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6506   "TARGET_THUMB"
6507   "*
6508    {
6509      rtx cond[2];
6510      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6511                                 ? GEU : LTU),
6512                                VOIDmode, operands[2], const1_rtx);
6513      cond[1] = operands[4];
6515      if (which_alternative == 0)
6516        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6517      else if (which_alternative == 1)
6518        {
6519          /* We must provide an alternative for a hi reg because reload 
6520             cannot handle output reloads on a jump instruction, but we
6521             can't subtract into that.  Fortunately a mov from lo to hi
6522             does not clobber the condition codes.  */
6523          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6524          output_asm_insn (\"mov\\t%0, %1\", operands);
6525        }
6526      else
6527        {
6528          /* Similarly, but the target is memory.  */
6529          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6530          output_asm_insn (\"str\\t%1, %0\", operands);
6531        }
6533      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6534        {
6535          case 4:
6536            output_asm_insn (\"b%d0\\t%l1\", cond);
6537            return \"\";
6538          case 6:
6539            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6540            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6541          default:
6542            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6543            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6544        }
6545    }
6546   "
6547   [(set (attr "far_jump")
6548         (if_then_else
6549             (ior (and (eq (symbol_ref ("which_alternative"))
6550                           (const_int 0))
6551                       (eq_attr "length" "8"))
6552                  (eq_attr "length" "10"))
6553             (const_string "yes")
6554             (const_string "no")))
6555    (set_attr_alternative "length"
6556       [
6557        ;; Alternative 0
6558        (if_then_else
6559          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6560               (le (minus (match_dup 4) (pc)) (const_int 256)))
6561          (const_int 4)
6562          (if_then_else
6563            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6564                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6565            (const_int 6)
6566            (const_int 8)))
6567        ;; Alternative 1
6568        (if_then_else
6569          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6570               (le (minus (match_dup 4) (pc)) (const_int 256)))
6571          (const_int 6)
6572          (if_then_else
6573            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6574                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6575            (const_int 8)
6576            (const_int 10)))
6577        ;; Alternative 2
6578        (if_then_else
6579          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6580               (le (minus (match_dup 4) (pc)) (const_int 256)))
6581          (const_int 6)
6582          (if_then_else
6583            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6584                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6585            (const_int 8)
6586            (const_int 10)))
6587        ;; Alternative 3
6588        (if_then_else
6589          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6590               (le (minus (match_dup 4) (pc)) (const_int 256)))
6591          (const_int 6)
6592          (if_then_else
6593            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6594                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6595            (const_int 8)
6596            (const_int 10)))])]
6599 (define_insn "*addsi3_cbranch"
6600   [(set (pc)
6601         (if_then_else
6602          (match_operator 4 "comparison_operator"
6603           [(plus:SI
6604             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6605             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6606            (const_int 0)])
6607          (label_ref (match_operand 5 "" ""))
6608          (pc)))
6609    (set
6610     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6611     (plus:SI (match_dup 2) (match_dup 3)))
6612    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6613   "TARGET_THUMB
6614    && (GET_CODE (operands[4]) == EQ
6615        || GET_CODE (operands[4]) == NE
6616        || GET_CODE (operands[4]) == GE
6617        || GET_CODE (operands[4]) == LT)"
6618   "*
6619    {
6620      rtx cond[3];
6622      
6623      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6624      cond[1] = operands[2];
6625      cond[2] = operands[3];
6627      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6628        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6629      else
6630        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6632      if (which_alternative >= 3
6633          && which_alternative < 4)
6634        output_asm_insn (\"mov\\t%0, %1\", operands);
6635      else if (which_alternative >= 4)
6636        output_asm_insn (\"str\\t%1, %0\", operands);
6638      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6639        {
6640          case 4:
6641            return \"b%d4\\t%l5\";
6642          case 6:
6643            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6644          default:
6645            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6646        }
6647    }
6648   "
6649   [(set (attr "far_jump")
6650         (if_then_else
6651             (ior (and (lt (symbol_ref ("which_alternative"))
6652                           (const_int 3))
6653                       (eq_attr "length" "8"))
6654                  (eq_attr "length" "10"))
6655             (const_string "yes")
6656             (const_string "no")))
6657    (set (attr "length")
6658      (if_then_else
6659        (lt (symbol_ref ("which_alternative"))
6660                        (const_int 3))
6661        (if_then_else
6662          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6663               (le (minus (match_dup 5) (pc)) (const_int 256)))
6664          (const_int 4)
6665          (if_then_else
6666            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6667                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6668            (const_int 6)
6669            (const_int 8)))
6670        (if_then_else
6671          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6672               (le (minus (match_dup 5) (pc)) (const_int 256)))
6673          (const_int 6)
6674          (if_then_else
6675            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6676                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6677            (const_int 8)
6678            (const_int 10)))))]
6681 (define_insn "*addsi3_cbranch_scratch"
6682   [(set (pc)
6683         (if_then_else
6684          (match_operator 3 "comparison_operator"
6685           [(plus:SI
6686             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6687             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6688            (const_int 0)])
6689          (label_ref (match_operand 4 "" ""))
6690          (pc)))
6691    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6692   "TARGET_THUMB
6693    && (GET_CODE (operands[3]) == EQ
6694        || GET_CODE (operands[3]) == NE
6695        || GET_CODE (operands[3]) == GE
6696        || GET_CODE (operands[3]) == LT)"
6697   "*
6698    {
6699      switch (which_alternative)
6700        {
6701        case 0:
6702          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6703          break;
6704        case 1:
6705          output_asm_insn (\"cmn\t%1, %2\", operands);
6706          break;
6707        case 2:
6708          if (INTVAL (operands[2]) < 0)
6709            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6710          else
6711            output_asm_insn (\"add\t%0, %1, %2\", operands);
6712          break;
6713        case 3:
6714          if (INTVAL (operands[2]) < 0)
6715            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6716          else
6717            output_asm_insn (\"add\t%0, %0, %2\", operands);
6718          break;
6719        }
6721      switch (get_attr_length (insn))
6722        {
6723          case 4:
6724            return \"b%d3\\t%l4\";
6725          case 6:
6726            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6727          default:
6728            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6729        }
6730    }
6731   "
6732   [(set (attr "far_jump")
6733         (if_then_else
6734             (eq_attr "length" "8")
6735             (const_string "yes")
6736             (const_string "no")))
6737    (set (attr "length")
6738        (if_then_else
6739          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6740               (le (minus (match_dup 4) (pc)) (const_int 256)))
6741          (const_int 4)
6742          (if_then_else
6743            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6744                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6745            (const_int 6)
6746            (const_int 8))))]
6749 (define_insn "*subsi3_cbranch"
6750   [(set (pc)
6751         (if_then_else
6752          (match_operator 4 "comparison_operator"
6753           [(minus:SI
6754             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6755             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6756            (const_int 0)])
6757          (label_ref (match_operand 5 "" ""))
6758          (pc)))
6759    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6760         (minus:SI (match_dup 2) (match_dup 3)))
6761    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6762   "TARGET_THUMB
6763    && (GET_CODE (operands[4]) == EQ
6764        || GET_CODE (operands[4]) == NE
6765        || GET_CODE (operands[4]) == GE
6766        || GET_CODE (operands[4]) == LT)"
6767   "*
6768    {
6769      if (which_alternative == 0)
6770        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6771      else if (which_alternative == 1)
6772        {
6773          /* We must provide an alternative for a hi reg because reload 
6774             cannot handle output reloads on a jump instruction, but we
6775             can't subtract into that.  Fortunately a mov from lo to hi
6776             does not clobber the condition codes.  */
6777          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6778          output_asm_insn (\"mov\\t%0, %1\", operands);
6779        }
6780      else
6781        {
6782          /* Similarly, but the target is memory.  */
6783          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6784          output_asm_insn (\"str\\t%1, %0\", operands);
6785        }
6787      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6788        {
6789          case 4:
6790            return \"b%d4\\t%l5\";
6791          case 6:
6792            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6793          default:
6794            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6795        }
6796    }
6797   "
6798   [(set (attr "far_jump")
6799         (if_then_else
6800             (ior (and (eq (symbol_ref ("which_alternative"))
6801                           (const_int 0))
6802                       (eq_attr "length" "8"))
6803                  (eq_attr "length" "10"))
6804             (const_string "yes")
6805             (const_string "no")))
6806    (set (attr "length")
6807      (if_then_else
6808        (eq (symbol_ref ("which_alternative"))
6809                        (const_int 0))
6810        (if_then_else
6811          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6812               (le (minus (match_dup 5) (pc)) (const_int 256)))
6813          (const_int 4)
6814          (if_then_else
6815            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6816                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6817            (const_int 6)
6818            (const_int 8)))
6819        (if_then_else
6820          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6821               (le (minus (match_dup 5) (pc)) (const_int 256)))
6822          (const_int 6)
6823          (if_then_else
6824            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6825                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6826            (const_int 8)
6827            (const_int 10)))))]
6830 (define_insn "*subsi3_cbranch_scratch"
6831   [(set (pc)
6832         (if_then_else
6833          (match_operator 0 "arm_comparison_operator"
6834           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6835                      (match_operand:SI 2 "nonmemory_operand" "l"))
6836            (const_int 0)])
6837          (label_ref (match_operand 3 "" ""))
6838          (pc)))]
6839   "TARGET_THUMB
6840    && (GET_CODE (operands[0]) == EQ
6841        || GET_CODE (operands[0]) == NE
6842        || GET_CODE (operands[0]) == GE
6843        || GET_CODE (operands[0]) == LT)"
6844   "*
6845   output_asm_insn (\"cmp\\t%1, %2\", operands);
6846   switch (get_attr_length (insn))
6847     {
6848     case 4:  return \"b%d0\\t%l3\";
6849     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6850     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6851     }
6852   "
6853   [(set (attr "far_jump")
6854         (if_then_else
6855             (eq_attr "length" "8")
6856             (const_string "yes")
6857             (const_string "no")))
6858    (set (attr "length") 
6859         (if_then_else
6860             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6861                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6862             (const_int 4)
6863             (if_then_else
6864                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6865                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6866                 (const_int 6)
6867                 (const_int 8))))]
6870 ;; Comparison and test insns
6872 (define_expand "cmpsi"
6873   [(match_operand:SI 0 "s_register_operand" "")
6874    (match_operand:SI 1 "arm_add_operand" "")]
6875   "TARGET_ARM"
6876   "{
6877     arm_compare_op0 = operands[0];
6878     arm_compare_op1 = operands[1];
6879     DONE;
6880   }"
6883 (define_expand "cmpsf"
6884   [(match_operand:SF 0 "s_register_operand" "")
6885    (match_operand:SF 1 "arm_float_compare_operand" "")]
6886   "TARGET_ARM && TARGET_HARD_FLOAT"
6887   "
6888   arm_compare_op0 = operands[0];
6889   arm_compare_op1 = operands[1];
6890   DONE;
6891   "
6894 (define_expand "cmpdf"
6895   [(match_operand:DF 0 "s_register_operand" "")
6896    (match_operand:DF 1 "arm_float_compare_operand" "")]
6897   "TARGET_ARM && TARGET_HARD_FLOAT"
6898   "
6899   arm_compare_op0 = operands[0];
6900   arm_compare_op1 = operands[1];
6901   DONE;
6902   "
6905 (define_insn "*arm_cmpsi_insn"
6906   [(set (reg:CC CC_REGNUM)
6907         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6908                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6909   "TARGET_ARM"
6910   "@
6911    cmp%?\\t%0, %1
6912    cmn%?\\t%0, #%n1"
6913   [(set_attr "conds" "set")]
6916 (define_insn "*cmpsi_shiftsi"
6917   [(set (reg:CC CC_REGNUM)
6918         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6919                     (match_operator:SI  3 "shift_operator"
6920                      [(match_operand:SI 1 "s_register_operand" "r")
6921                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6922   "TARGET_ARM"
6923   "cmp%?\\t%0, %1%S3"
6924   [(set_attr "conds" "set")
6925    (set_attr "shift" "1")
6926    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6927                       (const_string "alu_shift")
6928                       (const_string "alu_shift_reg")))]
6931 (define_insn "*cmpsi_shiftsi_swp"
6932   [(set (reg:CC_SWP CC_REGNUM)
6933         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6934                          [(match_operand:SI 1 "s_register_operand" "r")
6935                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6936                         (match_operand:SI 0 "s_register_operand" "r")))]
6937   "TARGET_ARM"
6938   "cmp%?\\t%0, %1%S3"
6939   [(set_attr "conds" "set")
6940    (set_attr "shift" "1")
6941    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6942                       (const_string "alu_shift")
6943                       (const_string "alu_shift_reg")))]
6946 (define_insn "*cmpsi_negshiftsi_si"
6947   [(set (reg:CC_Z CC_REGNUM)
6948         (compare:CC_Z
6949          (neg:SI (match_operator:SI 1 "shift_operator"
6950                     [(match_operand:SI 2 "s_register_operand" "r")
6951                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6952          (match_operand:SI 0 "s_register_operand" "r")))]
6953   "TARGET_ARM"
6954   "cmn%?\\t%0, %2%S1"
6955   [(set_attr "conds" "set")
6956    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6957                                     (const_string "alu_shift")
6958                                     (const_string "alu_shift_reg")))]
6961 ;; Cirrus SF compare instruction
6962 (define_insn "*cirrus_cmpsf"
6963   [(set (reg:CCFP CC_REGNUM)
6964         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6965                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6966   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6967   "cfcmps%?\\tr15, %V0, %V1"
6968   [(set_attr "type"   "mav_farith")
6969    (set_attr "cirrus" "compare")]
6972 ;; Cirrus DF compare instruction
6973 (define_insn "*cirrus_cmpdf"
6974   [(set (reg:CCFP CC_REGNUM)
6975         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6976                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6977   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6978   "cfcmpd%?\\tr15, %V0, %V1"
6979   [(set_attr "type"   "mav_farith")
6980    (set_attr "cirrus" "compare")]
6983 ;; Cirrus DI compare instruction
6984 (define_expand "cmpdi"
6985   [(match_operand:DI 0 "cirrus_fp_register" "")
6986    (match_operand:DI 1 "cirrus_fp_register" "")]
6987   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6988   "{
6989      arm_compare_op0 = operands[0];
6990      arm_compare_op1 = operands[1];
6991      DONE;
6992    }")
6994 (define_insn "*cirrus_cmpdi"
6995   [(set (reg:CC CC_REGNUM)
6996         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6997                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6998   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6999   "cfcmp64%?\\tr15, %V0, %V1"
7000   [(set_attr "type"   "mav_farith")
7001    (set_attr "cirrus" "compare")]
7004 ; This insn allows redundant compares to be removed by cse, nothing should
7005 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
7006 ; is deleted later on. The match_dup will match the mode here, so that
7007 ; mode changes of the condition codes aren't lost by this even though we don't
7008 ; specify what they are.
7010 (define_insn "*deleted_compare"
7011   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
7012   "TARGET_ARM"
7013   "\\t%@ deleted compare"
7014   [(set_attr "conds" "set")
7015    (set_attr "length" "0")]
7019 ;; Conditional branch insns
7021 (define_expand "beq"
7022   [(set (pc)
7023         (if_then_else (eq (match_dup 1) (const_int 0))
7024                       (label_ref (match_operand 0 "" ""))
7025                       (pc)))]
7026   "TARGET_ARM"
7027   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7030 (define_expand "bne"
7031   [(set (pc)
7032         (if_then_else (ne (match_dup 1) (const_int 0))
7033                       (label_ref (match_operand 0 "" ""))
7034                       (pc)))]
7035   "TARGET_ARM"
7036   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7039 (define_expand "bgt"
7040   [(set (pc)
7041         (if_then_else (gt (match_dup 1) (const_int 0))
7042                       (label_ref (match_operand 0 "" ""))
7043                       (pc)))]
7044   "TARGET_ARM"
7045   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7048 (define_expand "ble"
7049   [(set (pc)
7050         (if_then_else (le (match_dup 1) (const_int 0))
7051                       (label_ref (match_operand 0 "" ""))
7052                       (pc)))]
7053   "TARGET_ARM"
7054   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7057 (define_expand "bge"
7058   [(set (pc)
7059         (if_then_else (ge (match_dup 1) (const_int 0))
7060                       (label_ref (match_operand 0 "" ""))
7061                       (pc)))]
7062   "TARGET_ARM"
7063   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7066 (define_expand "blt"
7067   [(set (pc)
7068         (if_then_else (lt (match_dup 1) (const_int 0))
7069                       (label_ref (match_operand 0 "" ""))
7070                       (pc)))]
7071   "TARGET_ARM"
7072   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7075 (define_expand "bgtu"
7076   [(set (pc)
7077         (if_then_else (gtu (match_dup 1) (const_int 0))
7078                       (label_ref (match_operand 0 "" ""))
7079                       (pc)))]
7080   "TARGET_ARM"
7081   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7084 (define_expand "bleu"
7085   [(set (pc)
7086         (if_then_else (leu (match_dup 1) (const_int 0))
7087                       (label_ref (match_operand 0 "" ""))
7088                       (pc)))]
7089   "TARGET_ARM"
7090   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7093 (define_expand "bgeu"
7094   [(set (pc)
7095         (if_then_else (geu (match_dup 1) (const_int 0))
7096                       (label_ref (match_operand 0 "" ""))
7097                       (pc)))]
7098   "TARGET_ARM"
7099   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7102 (define_expand "bltu"
7103   [(set (pc)
7104         (if_then_else (ltu (match_dup 1) (const_int 0))
7105                       (label_ref (match_operand 0 "" ""))
7106                       (pc)))]
7107   "TARGET_ARM"
7108   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7111 (define_expand "bunordered"
7112   [(set (pc)
7113         (if_then_else (unordered (match_dup 1) (const_int 0))
7114                       (label_ref (match_operand 0 "" ""))
7115                       (pc)))]
7116   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7117   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7118                                       arm_compare_op1);"
7121 (define_expand "bordered"
7122   [(set (pc)
7123         (if_then_else (ordered (match_dup 1) (const_int 0))
7124                       (label_ref (match_operand 0 "" ""))
7125                       (pc)))]
7126   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7127   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7128                                       arm_compare_op1);"
7131 (define_expand "bungt"
7132   [(set (pc)
7133         (if_then_else (ungt (match_dup 1) (const_int 0))
7134                       (label_ref (match_operand 0 "" ""))
7135                       (pc)))]
7136   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7137   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7140 (define_expand "bunlt"
7141   [(set (pc)
7142         (if_then_else (unlt (match_dup 1) (const_int 0))
7143                       (label_ref (match_operand 0 "" ""))
7144                       (pc)))]
7145   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7146   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7149 (define_expand "bunge"
7150   [(set (pc)
7151         (if_then_else (unge (match_dup 1) (const_int 0))
7152                       (label_ref (match_operand 0 "" ""))
7153                       (pc)))]
7154   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7155   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7158 (define_expand "bunle"
7159   [(set (pc)
7160         (if_then_else (unle (match_dup 1) (const_int 0))
7161                       (label_ref (match_operand 0 "" ""))
7162                       (pc)))]
7163   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7164   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7167 ;; The following two patterns need two branch instructions, since there is
7168 ;; no single instruction that will handle all cases.
7169 (define_expand "buneq"
7170   [(set (pc)
7171         (if_then_else (uneq (match_dup 1) (const_int 0))
7172                       (label_ref (match_operand 0 "" ""))
7173                       (pc)))]
7174   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7175   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7178 (define_expand "bltgt"
7179   [(set (pc)
7180         (if_then_else (ltgt (match_dup 1) (const_int 0))
7181                       (label_ref (match_operand 0 "" ""))
7182                       (pc)))]
7183   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7184   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7188 ;; Patterns to match conditional branch insns.
7191 ; Special pattern to match UNEQ.
7192 (define_insn "*arm_buneq"
7193   [(set (pc)
7194         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7195                       (label_ref (match_operand 0 "" ""))
7196                       (pc)))]
7197   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7198   "*
7199   gcc_assert (!arm_ccfsm_state);
7201   return \"bvs\\t%l0\;beq\\t%l0\";
7202   "
7203   [(set_attr "conds" "jump_clob")
7204    (set_attr "length" "8")]
7207 ; Special pattern to match LTGT.
7208 (define_insn "*arm_bltgt"
7209   [(set (pc)
7210         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7211                       (label_ref (match_operand 0 "" ""))
7212                       (pc)))]
7213   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7214   "*
7215   gcc_assert (!arm_ccfsm_state);
7217   return \"bmi\\t%l0\;bgt\\t%l0\";
7218   "
7219   [(set_attr "conds" "jump_clob")
7220    (set_attr "length" "8")]
7223 (define_insn "*arm_cond_branch"
7224   [(set (pc)
7225         (if_then_else (match_operator 1 "arm_comparison_operator"
7226                        [(match_operand 2 "cc_register" "") (const_int 0)])
7227                       (label_ref (match_operand 0 "" ""))
7228                       (pc)))]
7229   "TARGET_ARM"
7230   "*
7231   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7232     {
7233       arm_ccfsm_state += 2;
7234       return \"\";
7235     }
7236   return \"b%d1\\t%l0\";
7237   "
7238   [(set_attr "conds" "use")
7239    (set_attr "type" "branch")]
7242 ; Special pattern to match reversed UNEQ.
7243 (define_insn "*arm_buneq_reversed"
7244   [(set (pc)
7245         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7246                       (pc)
7247                       (label_ref (match_operand 0 "" ""))))]
7248   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7249   "*
7250   gcc_assert (!arm_ccfsm_state);
7252   return \"bmi\\t%l0\;bgt\\t%l0\";
7253   "
7254   [(set_attr "conds" "jump_clob")
7255    (set_attr "length" "8")]
7258 ; Special pattern to match reversed LTGT.
7259 (define_insn "*arm_bltgt_reversed"
7260   [(set (pc)
7261         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7262                       (pc)
7263                       (label_ref (match_operand 0 "" ""))))]
7264   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7265   "*
7266   gcc_assert (!arm_ccfsm_state);
7268   return \"bvs\\t%l0\;beq\\t%l0\";
7269   "
7270   [(set_attr "conds" "jump_clob")
7271    (set_attr "length" "8")]
7274 (define_insn "*arm_cond_branch_reversed"
7275   [(set (pc)
7276         (if_then_else (match_operator 1 "arm_comparison_operator"
7277                        [(match_operand 2 "cc_register" "") (const_int 0)])
7278                       (pc)
7279                       (label_ref (match_operand 0 "" ""))))]
7280   "TARGET_ARM"
7281   "*
7282   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7283     {
7284       arm_ccfsm_state += 2;
7285       return \"\";
7286     }
7287   return \"b%D1\\t%l0\";
7288   "
7289   [(set_attr "conds" "use")
7290    (set_attr "type" "branch")]
7295 ; scc insns
7297 (define_expand "seq"
7298   [(set (match_operand:SI 0 "s_register_operand" "")
7299         (eq:SI (match_dup 1) (const_int 0)))]
7300   "TARGET_ARM"
7301   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7304 (define_expand "sne"
7305   [(set (match_operand:SI 0 "s_register_operand" "")
7306         (ne:SI (match_dup 1) (const_int 0)))]
7307   "TARGET_ARM"
7308   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7311 (define_expand "sgt"
7312   [(set (match_operand:SI 0 "s_register_operand" "")
7313         (gt:SI (match_dup 1) (const_int 0)))]
7314   "TARGET_ARM"
7315   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7318 (define_expand "sle"
7319   [(set (match_operand:SI 0 "s_register_operand" "")
7320         (le:SI (match_dup 1) (const_int 0)))]
7321   "TARGET_ARM"
7322   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7325 (define_expand "sge"
7326   [(set (match_operand:SI 0 "s_register_operand" "")
7327         (ge:SI (match_dup 1) (const_int 0)))]
7328   "TARGET_ARM"
7329   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7332 (define_expand "slt"
7333   [(set (match_operand:SI 0 "s_register_operand" "")
7334         (lt:SI (match_dup 1) (const_int 0)))]
7335   "TARGET_ARM"
7336   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7339 (define_expand "sgtu"
7340   [(set (match_operand:SI 0 "s_register_operand" "")
7341         (gtu:SI (match_dup 1) (const_int 0)))]
7342   "TARGET_ARM"
7343   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7346 (define_expand "sleu"
7347   [(set (match_operand:SI 0 "s_register_operand" "")
7348         (leu:SI (match_dup 1) (const_int 0)))]
7349   "TARGET_ARM"
7350   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7353 (define_expand "sgeu"
7354   [(set (match_operand:SI 0 "s_register_operand" "")
7355         (geu:SI (match_dup 1) (const_int 0)))]
7356   "TARGET_ARM"
7357   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7360 (define_expand "sltu"
7361   [(set (match_operand:SI 0 "s_register_operand" "")
7362         (ltu:SI (match_dup 1) (const_int 0)))]
7363   "TARGET_ARM"
7364   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7367 (define_expand "sunordered"
7368   [(set (match_operand:SI 0 "s_register_operand" "")
7369         (unordered:SI (match_dup 1) (const_int 0)))]
7370   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7371   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7372                                       arm_compare_op1);"
7375 (define_expand "sordered"
7376   [(set (match_operand:SI 0 "s_register_operand" "")
7377         (ordered:SI (match_dup 1) (const_int 0)))]
7378   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7379   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7380                                       arm_compare_op1);"
7383 (define_expand "sungt"
7384   [(set (match_operand:SI 0 "s_register_operand" "")
7385         (ungt:SI (match_dup 1) (const_int 0)))]
7386   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7387   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7388                                       arm_compare_op1);"
7391 (define_expand "sunge"
7392   [(set (match_operand:SI 0 "s_register_operand" "")
7393         (unge:SI (match_dup 1) (const_int 0)))]
7394   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7395   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7396                                       arm_compare_op1);"
7399 (define_expand "sunlt"
7400   [(set (match_operand:SI 0 "s_register_operand" "")
7401         (unlt:SI (match_dup 1) (const_int 0)))]
7402   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7403   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7404                                       arm_compare_op1);"
7407 (define_expand "sunle"
7408   [(set (match_operand:SI 0 "s_register_operand" "")
7409         (unle:SI (match_dup 1) (const_int 0)))]
7410   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7411   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7412                                       arm_compare_op1);"
7415 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7416 ;;; simple ARM instructions. 
7418 ; (define_expand "suneq"
7419 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7420 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7421 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7422 ;   "gcc_unreachable ();"
7423 ; )
7425 ; (define_expand "sltgt"
7426 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7427 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7428 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7429 ;   "gcc_unreachable ();"
7430 ; )
7432 (define_insn "*mov_scc"
7433   [(set (match_operand:SI 0 "s_register_operand" "=r")
7434         (match_operator:SI 1 "arm_comparison_operator"
7435          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7436   "TARGET_ARM"
7437   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7438   [(set_attr "conds" "use")
7439    (set_attr "length" "8")]
7442 (define_insn "*mov_negscc"
7443   [(set (match_operand:SI 0 "s_register_operand" "=r")
7444         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7445                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7446   "TARGET_ARM"
7447   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7448   [(set_attr "conds" "use")
7449    (set_attr "length" "8")]
7452 (define_insn "*mov_notscc"
7453   [(set (match_operand:SI 0 "s_register_operand" "=r")
7454         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7455                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7456   "TARGET_ARM"
7457   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7458   [(set_attr "conds" "use")
7459    (set_attr "length" "8")]
7463 ;; Conditional move insns
7465 (define_expand "movsicc"
7466   [(set (match_operand:SI 0 "s_register_operand" "")
7467         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7468                          (match_operand:SI 2 "arm_not_operand" "")
7469                          (match_operand:SI 3 "arm_not_operand" "")))]
7470   "TARGET_ARM"
7471   "
7472   {
7473     enum rtx_code code = GET_CODE (operands[1]);
7474     rtx ccreg;
7476     if (code == UNEQ || code == LTGT)
7477       FAIL;
7479     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7480     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7481   }"
7484 (define_expand "movsfcc"
7485   [(set (match_operand:SF 0 "s_register_operand" "")
7486         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7487                          (match_operand:SF 2 "s_register_operand" "")
7488                          (match_operand:SF 3 "nonmemory_operand" "")))]
7489   "TARGET_ARM"
7490   "
7491   {
7492     enum rtx_code code = GET_CODE (operands[1]);
7493     rtx ccreg;
7495     if (code == UNEQ || code == LTGT)
7496       FAIL;
7498     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7499        Otherwise, ensure it is a valid FP add operand */
7500     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7501         || (!arm_float_add_operand (operands[3], SFmode)))
7502       operands[3] = force_reg (SFmode, operands[3]);
7504     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7505     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7506   }"
7509 (define_expand "movdfcc"
7510   [(set (match_operand:DF 0 "s_register_operand" "")
7511         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7512                          (match_operand:DF 2 "s_register_operand" "")
7513                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7514   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7515   "
7516   {
7517     enum rtx_code code = GET_CODE (operands[1]);
7518     rtx ccreg;
7520     if (code == UNEQ || code == LTGT)
7521       FAIL;
7523     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7524     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7525   }"
7528 (define_insn "*movsicc_insn"
7529   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7530         (if_then_else:SI
7531          (match_operator 3 "arm_comparison_operator"
7532           [(match_operand 4 "cc_register" "") (const_int 0)])
7533          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7534          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7535   "TARGET_ARM"
7536   "@
7537    mov%D3\\t%0, %2
7538    mvn%D3\\t%0, #%B2
7539    mov%d3\\t%0, %1
7540    mvn%d3\\t%0, #%B1
7541    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7542    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7543    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7544    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7545   [(set_attr "length" "4,4,4,4,8,8,8,8")
7546    (set_attr "conds" "use")]
7549 (define_insn "*movsfcc_soft_insn"
7550   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7551         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7552                           [(match_operand 4 "cc_register" "") (const_int 0)])
7553                          (match_operand:SF 1 "s_register_operand" "0,r")
7554                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7555   "TARGET_ARM && TARGET_SOFT_FLOAT"
7556   "@
7557    mov%D3\\t%0, %2
7558    mov%d3\\t%0, %1"
7559   [(set_attr "conds" "use")]
7563 ;; Jump and linkage insns
7565 (define_expand "jump"
7566   [(set (pc)
7567         (label_ref (match_operand 0 "" "")))]
7568   "TARGET_EITHER"
7569   ""
7572 (define_insn "*arm_jump"
7573   [(set (pc)
7574         (label_ref (match_operand 0 "" "")))]
7575   "TARGET_ARM"
7576   "*
7577   {
7578     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7579       {
7580         arm_ccfsm_state += 2;
7581         return \"\";
7582       }
7583     return \"b%?\\t%l0\";
7584   }
7585   "
7586   [(set_attr "predicable" "yes")]
7589 (define_insn "*thumb_jump"
7590   [(set (pc)
7591         (label_ref (match_operand 0 "" "")))]
7592   "TARGET_THUMB"
7593   "*
7594   if (get_attr_length (insn) == 2)
7595     return \"b\\t%l0\";
7596   return \"bl\\t%l0\\t%@ far jump\";
7597   "
7598   [(set (attr "far_jump")
7599         (if_then_else
7600             (eq_attr "length" "4")
7601             (const_string "yes")
7602             (const_string "no")))
7603    (set (attr "length") 
7604         (if_then_else
7605             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7606                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7607             (const_int 2)
7608             (const_int 4)))]
7611 (define_expand "call"
7612   [(parallel [(call (match_operand 0 "memory_operand" "")
7613                     (match_operand 1 "general_operand" ""))
7614               (use (match_operand 2 "" ""))
7615               (clobber (reg:SI LR_REGNUM))])]
7616   "TARGET_EITHER"
7617   "
7618   {
7619     rtx callee;
7620     
7621     /* In an untyped call, we can get NULL for operand 2.  */
7622     if (operands[2] == NULL_RTX)
7623       operands[2] = const0_rtx;
7624       
7625     /* This is to decide if we should generate indirect calls by loading the
7626        32 bit address of the callee into a register before performing the
7627        branch and link.  operand[2] encodes the long_call/short_call
7628        attribute of the function being called.  This attribute is set whenever
7629        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7630        is used, and the short_call attribute can also be set if function is
7631        declared as static or if it has already been defined in the current
7632        compilation unit.  See arm.c and arm.h for info about this.  The third
7633        parameter to arm_is_longcall_p is used to tell it which pattern
7634        invoked it.  */
7635     callee  = XEXP (operands[0], 0);
7636     
7637     if ((GET_CODE (callee) == SYMBOL_REF
7638          && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7639         || (GET_CODE (callee) != SYMBOL_REF
7640             && GET_CODE (callee) != REG))
7641       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7642   }"
7645 (define_insn "*call_reg_armv5"
7646   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7647          (match_operand 1 "" ""))
7648    (use (match_operand 2 "" ""))
7649    (clobber (reg:SI LR_REGNUM))]
7650   "TARGET_ARM && arm_arch5"
7651   "blx%?\\t%0"
7652   [(set_attr "type" "call")]
7655 (define_insn "*call_reg_arm"
7656   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7657          (match_operand 1 "" ""))
7658    (use (match_operand 2 "" ""))
7659    (clobber (reg:SI LR_REGNUM))]
7660   "TARGET_ARM && !arm_arch5"
7661   "*
7662   return output_call (operands);
7663   "
7664   ;; length is worst case, normally it is only two
7665   [(set_attr "length" "12")
7666    (set_attr "type" "call")]
7669 (define_insn "*call_mem"
7670   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
7671          (match_operand 1 "" ""))
7672    (use (match_operand 2 "" ""))
7673    (clobber (reg:SI LR_REGNUM))]
7674   "TARGET_ARM"
7675   "*
7676   return output_call_mem (operands);
7677   "
7678   [(set_attr "length" "12")
7679    (set_attr "type" "call")]
7682 (define_insn "*call_reg_thumb_v5"
7683   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7684          (match_operand 1 "" ""))
7685    (use (match_operand 2 "" ""))
7686    (clobber (reg:SI LR_REGNUM))]
7687   "TARGET_THUMB && arm_arch5"
7688   "blx\\t%0"
7689   [(set_attr "length" "2")
7690    (set_attr "type" "call")]
7693 (define_insn "*call_reg_thumb"
7694   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7695          (match_operand 1 "" ""))
7696    (use (match_operand 2 "" ""))
7697    (clobber (reg:SI LR_REGNUM))]
7698   "TARGET_THUMB && !arm_arch5"
7699   "*
7700   {
7701     if (!TARGET_CALLER_INTERWORKING)
7702       return thumb_call_via_reg (operands[0]);
7703     else if (operands[1] == const0_rtx)
7704       return \"bl\\t%__interwork_call_via_%0\";
7705     else if (frame_pointer_needed)
7706       return \"bl\\t%__interwork_r7_call_via_%0\";
7707     else
7708       return \"bl\\t%__interwork_r11_call_via_%0\";
7709   }"
7710   [(set_attr "type" "call")]
7713 (define_expand "call_value"
7714   [(parallel [(set (match_operand       0 "" "")
7715                    (call (match_operand 1 "memory_operand" "")
7716                          (match_operand 2 "general_operand" "")))
7717               (use (match_operand 3 "" ""))
7718               (clobber (reg:SI LR_REGNUM))])]
7719   "TARGET_EITHER"
7720   "
7721   {
7722     rtx callee = XEXP (operands[1], 0);
7723     
7724     /* In an untyped call, we can get NULL for operand 2.  */
7725     if (operands[3] == 0)
7726       operands[3] = const0_rtx;
7727       
7728     /* See the comment in define_expand \"call\".  */
7729     if ((GET_CODE (callee) == SYMBOL_REF
7730          && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7731         || (GET_CODE (callee) != SYMBOL_REF
7732             && GET_CODE (callee) != REG))
7733       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7734   }"
7737 (define_insn "*call_value_reg_armv5"
7738   [(set (match_operand 0 "" "")
7739         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7740               (match_operand 2 "" "")))
7741    (use (match_operand 3 "" ""))
7742    (clobber (reg:SI LR_REGNUM))]
7743   "TARGET_ARM && arm_arch5"
7744   "blx%?\\t%1"
7745   [(set_attr "type" "call")]
7748 (define_insn "*call_value_reg_arm"
7749   [(set (match_operand 0 "" "")
7750         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7751               (match_operand 2 "" "")))
7752    (use (match_operand 3 "" ""))
7753    (clobber (reg:SI LR_REGNUM))]
7754   "TARGET_ARM && !arm_arch5"
7755   "*
7756   return output_call (&operands[1]);
7757   "
7758   [(set_attr "length" "12")
7759    (set_attr "type" "call")]
7762 (define_insn "*call_value_mem"
7763   [(set (match_operand 0 "" "")
7764         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
7765               (match_operand 2 "" "")))
7766    (use (match_operand 3 "" ""))
7767    (clobber (reg:SI LR_REGNUM))]
7768   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7769   "*
7770   return output_call_mem (&operands[1]);
7771   "
7772   [(set_attr "length" "12")
7773    (set_attr "type" "call")]
7776 (define_insn "*call_value_reg_thumb_v5"
7777   [(set (match_operand 0 "" "")
7778         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7779               (match_operand 2 "" "")))
7780    (use (match_operand 3 "" ""))
7781    (clobber (reg:SI LR_REGNUM))]
7782   "TARGET_THUMB && arm_arch5"
7783   "blx\\t%1"
7784   [(set_attr "length" "2")
7785    (set_attr "type" "call")]
7788 (define_insn "*call_value_reg_thumb"
7789   [(set (match_operand 0 "" "")
7790         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7791               (match_operand 2 "" "")))
7792    (use (match_operand 3 "" ""))
7793    (clobber (reg:SI LR_REGNUM))]
7794   "TARGET_THUMB && !arm_arch5"
7795   "*
7796   {
7797     if (!TARGET_CALLER_INTERWORKING)
7798       return thumb_call_via_reg (operands[1]);
7799     else if (operands[2] == const0_rtx)
7800       return \"bl\\t%__interwork_call_via_%1\";
7801     else if (frame_pointer_needed)
7802       return \"bl\\t%__interwork_r7_call_via_%1\";
7803     else
7804       return \"bl\\t%__interwork_r11_call_via_%1\";
7805   }"
7806   [(set_attr "type" "call")]
7809 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7810 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7812 (define_insn "*call_symbol"
7813   [(call (mem:SI (match_operand:SI 0 "" ""))
7814          (match_operand 1 "" ""))
7815    (use (match_operand 2 "" ""))
7816    (clobber (reg:SI LR_REGNUM))]
7817   "TARGET_ARM
7818    && (GET_CODE (operands[0]) == SYMBOL_REF)
7819    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7820   "*
7821   {
7822     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7823   }"
7824   [(set_attr "type" "call")]
7827 (define_insn "*call_value_symbol"
7828   [(set (match_operand 0 "" "")
7829         (call (mem:SI (match_operand:SI 1 "" ""))
7830         (match_operand:SI 2 "" "")))
7831    (use (match_operand 3 "" ""))
7832    (clobber (reg:SI LR_REGNUM))]
7833   "TARGET_ARM
7834    && (GET_CODE (operands[1]) == SYMBOL_REF)
7835    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7836   "*
7837   {
7838     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7839   }"
7840   [(set_attr "type" "call")]
7843 (define_insn "*call_insn"
7844   [(call (mem:SI (match_operand:SI 0 "" ""))
7845          (match_operand:SI 1 "" ""))
7846    (use (match_operand 2 "" ""))
7847    (clobber (reg:SI LR_REGNUM))]
7848   "TARGET_THUMB
7849    && GET_CODE (operands[0]) == SYMBOL_REF
7850    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7851   "bl\\t%a0"
7852   [(set_attr "length" "4")
7853    (set_attr "type" "call")]
7856 (define_insn "*call_value_insn"
7857   [(set (match_operand 0 "" "")
7858         (call (mem:SI (match_operand 1 "" ""))
7859               (match_operand 2 "" "")))
7860    (use (match_operand 3 "" ""))
7861    (clobber (reg:SI LR_REGNUM))]
7862   "TARGET_THUMB
7863    && GET_CODE (operands[1]) == SYMBOL_REF
7864    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7865   "bl\\t%a1"
7866   [(set_attr "length" "4")
7867    (set_attr "type" "call")]
7870 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7871 (define_expand "sibcall"
7872   [(parallel [(call (match_operand 0 "memory_operand" "")
7873                     (match_operand 1 "general_operand" ""))
7874               (return)
7875               (use (match_operand 2 "" ""))])]
7876   "TARGET_ARM"
7877   "
7878   {
7879     if (operands[2] == NULL_RTX)
7880       operands[2] = const0_rtx;
7881   }"
7884 (define_expand "sibcall_value"
7885   [(parallel [(set (match_operand 0 "" "")
7886                    (call (match_operand 1 "memory_operand" "")
7887                          (match_operand 2 "general_operand" "")))
7888               (return)
7889               (use (match_operand 3 "" ""))])]
7890   "TARGET_ARM"
7891   "
7892   {
7893     if (operands[3] == NULL_RTX)
7894       operands[3] = const0_rtx;
7895   }"
7898 (define_insn "*sibcall_insn"
7899  [(call (mem:SI (match_operand:SI 0 "" "X"))
7900         (match_operand 1 "" ""))
7901   (return)
7902   (use (match_operand 2 "" ""))]
7903   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7904   "*
7905   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7906   "
7907   [(set_attr "type" "call")]
7910 (define_insn "*sibcall_value_insn"
7911  [(set (match_operand 0 "" "")
7912        (call (mem:SI (match_operand:SI 1 "" "X"))
7913              (match_operand 2 "" "")))
7914   (return)
7915   (use (match_operand 3 "" ""))]
7916   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7917   "*
7918   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7919   "
7920   [(set_attr "type" "call")]
7923 ;; Often the return insn will be the same as loading from memory, so set attr
7924 (define_insn "return"
7925   [(return)]
7926   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7927   "*
7928   {
7929     if (arm_ccfsm_state == 2)
7930       {
7931         arm_ccfsm_state += 2;
7932         return \"\";
7933       }
7934     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7935   }"
7936   [(set_attr "type" "load1")
7937    (set_attr "length" "12")
7938    (set_attr "predicable" "yes")]
7941 (define_insn "*cond_return"
7942   [(set (pc)
7943         (if_then_else (match_operator 0 "arm_comparison_operator"
7944                        [(match_operand 1 "cc_register" "") (const_int 0)])
7945                       (return)
7946                       (pc)))]
7947   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7948   "*
7949   {
7950     if (arm_ccfsm_state == 2)
7951       {
7952         arm_ccfsm_state += 2;
7953         return \"\";
7954       }
7955     return output_return_instruction (operands[0], TRUE, FALSE);
7956   }"
7957   [(set_attr "conds" "use")
7958    (set_attr "length" "12")
7959    (set_attr "type" "load1")]
7962 (define_insn "*cond_return_inverted"
7963   [(set (pc)
7964         (if_then_else (match_operator 0 "arm_comparison_operator"
7965                        [(match_operand 1 "cc_register" "") (const_int 0)])
7966                       (pc)
7967                       (return)))]
7968   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7969   "*
7970   {
7971     if (arm_ccfsm_state == 2)
7972       {
7973         arm_ccfsm_state += 2;
7974         return \"\";
7975       }
7976     return output_return_instruction (operands[0], TRUE, TRUE);
7977   }"
7978   [(set_attr "conds" "use")
7979    (set_attr "length" "12")
7980    (set_attr "type" "load1")]
7983 ;; Generate a sequence of instructions to determine if the processor is
7984 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7985 ;; mask.
7987 (define_expand "return_addr_mask"
7988   [(set (match_dup 1)
7989       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7990                        (const_int 0)))
7991    (set (match_operand:SI 0 "s_register_operand" "")
7992       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7993                        (const_int -1)
7994                        (const_int 67108860)))] ; 0x03fffffc
7995   "TARGET_ARM"
7996   "
7997   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7998   ")
8000 (define_insn "*check_arch2"
8001   [(set (match_operand:CC_NOOV 0 "cc_register" "")
8002       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
8003                        (const_int 0)))]
8004   "TARGET_ARM"
8005   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
8006   [(set_attr "length" "8")
8007    (set_attr "conds" "set")]
8010 ;; Call subroutine returning any type.
8012 (define_expand "untyped_call"
8013   [(parallel [(call (match_operand 0 "" "")
8014                     (const_int 0))
8015               (match_operand 1 "" "")
8016               (match_operand 2 "" "")])]
8017   "TARGET_EITHER"
8018   "
8019   {
8020     int i;
8021     rtx par = gen_rtx_PARALLEL (VOIDmode,
8022                                 rtvec_alloc (XVECLEN (operands[2], 0)));
8023     rtx addr = gen_reg_rtx (Pmode);
8024     rtx mem;
8025     int size = 0;
8027     emit_move_insn (addr, XEXP (operands[1], 0));
8028     mem = change_address (operands[1], BLKmode, addr);
8030     for (i = 0; i < XVECLEN (operands[2], 0); i++)
8031       {
8032         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
8034         /* Default code only uses r0 as a return value, but we could
8035            be using anything up to 4 registers.  */
8036         if (REGNO (src) == R0_REGNUM)
8037           src = gen_rtx_REG (TImode, R0_REGNUM);
8039         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
8040                                                  GEN_INT (size));
8041         size += GET_MODE_SIZE (GET_MODE (src));
8042       }
8044     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
8045                                     const0_rtx));
8047     size = 0;
8049     for (i = 0; i < XVECLEN (par, 0); i++)
8050       {
8051         HOST_WIDE_INT offset = 0;
8052         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
8054         if (size != 0)
8055           emit_move_insn (addr, plus_constant (addr, size));
8057         mem = change_address (mem, GET_MODE (reg), NULL);
8058         if (REGNO (reg) == R0_REGNUM)
8059           {
8060             /* On thumb we have to use a write-back instruction.  */
8061             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
8062                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8063             size = TARGET_ARM ? 16 : 0;
8064           }
8065         else
8066           {
8067             emit_move_insn (mem, reg);
8068             size = GET_MODE_SIZE (GET_MODE (reg));
8069           }
8070       }
8072     /* The optimizer does not know that the call sets the function value
8073        registers we stored in the result block.  We avoid problems by
8074        claiming that all hard registers are used and clobbered at this
8075        point.  */
8076     emit_insn (gen_blockage ());
8078     DONE;
8079   }"
8082 (define_expand "untyped_return"
8083   [(match_operand:BLK 0 "memory_operand" "")
8084    (match_operand 1 "" "")]
8085   "TARGET_EITHER"
8086   "
8087   {
8088     int i;
8089     rtx addr = gen_reg_rtx (Pmode);
8090     rtx mem;
8091     int size = 0;
8093     emit_move_insn (addr, XEXP (operands[0], 0));
8094     mem = change_address (operands[0], BLKmode, addr);
8096     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8097       {
8098         HOST_WIDE_INT offset = 0;
8099         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
8101         if (size != 0)
8102           emit_move_insn (addr, plus_constant (addr, size));
8104         mem = change_address (mem, GET_MODE (reg), NULL);
8105         if (REGNO (reg) == R0_REGNUM)
8106           {
8107             /* On thumb we have to use a write-back instruction.  */
8108             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8109                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8110             size = TARGET_ARM ? 16 : 0;
8111           }
8112         else
8113           {
8114             emit_move_insn (reg, mem);
8115             size = GET_MODE_SIZE (GET_MODE (reg));
8116           }
8117       }
8119     /* Emit USE insns before the return.  */
8120     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8121       emit_insn (gen_rtx_USE (VOIDmode,
8122                               SET_DEST (XVECEXP (operands[1], 0, i))));
8124     /* Construct the return.  */
8125     expand_naked_return ();
8127     DONE;
8128   }"
8131 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8132 ;; all of memory.  This blocks insns from being moved across this point.
8134 (define_insn "blockage"
8135   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8136   "TARGET_EITHER"
8137   ""
8138   [(set_attr "length" "0")
8139    (set_attr "type" "block")]
8142 (define_expand "casesi"
8143   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8144    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8145    (match_operand:SI 2 "const_int_operand" "")  ; total range
8146    (match_operand:SI 3 "" "")                   ; table label
8147    (match_operand:SI 4 "" "")]                  ; Out of range label
8148   "TARGET_ARM"
8149   "
8150   {
8151     rtx reg;
8152     if (operands[1] != const0_rtx)
8153       {
8154         reg = gen_reg_rtx (SImode);
8156         emit_insn (gen_addsi3 (reg, operands[0],
8157                                GEN_INT (-INTVAL (operands[1]))));
8158         operands[0] = reg;
8159       }
8161     if (!const_ok_for_arm (INTVAL (operands[2])))
8162       operands[2] = force_reg (SImode, operands[2]);
8164     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8165                                          operands[4]));
8166     DONE;
8167   }"
8170 ;; The USE in this pattern is needed to tell flow analysis that this is
8171 ;; a CASESI insn.  It has no other purpose.
8172 (define_insn "casesi_internal"
8173   [(parallel [(set (pc)
8174                (if_then_else
8175                 (leu (match_operand:SI 0 "s_register_operand" "r")
8176                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8177                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8178                                  (label_ref (match_operand 2 "" ""))))
8179                 (label_ref (match_operand 3 "" ""))))
8180               (clobber (reg:CC CC_REGNUM))
8181               (use (label_ref (match_dup 2)))])]
8182   "TARGET_ARM"
8183   "*
8184     if (flag_pic)
8185       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8186     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8187   "
8188   [(set_attr "conds" "clob")
8189    (set_attr "length" "12")]
8192 (define_expand "indirect_jump"
8193   [(set (pc)
8194         (match_operand:SI 0 "s_register_operand" ""))]
8195   "TARGET_EITHER"
8196   ""
8199 ;; NB Never uses BX.
8200 (define_insn "*arm_indirect_jump"
8201   [(set (pc)
8202         (match_operand:SI 0 "s_register_operand" "r"))]
8203   "TARGET_ARM"
8204   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8205   [(set_attr "predicable" "yes")]
8208 (define_insn "*load_indirect_jump"
8209   [(set (pc)
8210         (match_operand:SI 0 "memory_operand" "m"))]
8211   "TARGET_ARM"
8212   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8213   [(set_attr "type" "load1")
8214    (set_attr "pool_range" "4096")
8215    (set_attr "neg_pool_range" "4084")
8216    (set_attr "predicable" "yes")]
8219 ;; NB Never uses BX.
8220 (define_insn "*thumb_indirect_jump"
8221   [(set (pc)
8222         (match_operand:SI 0 "register_operand" "l*r"))]
8223   "TARGET_THUMB"
8224   "mov\\tpc, %0"
8225   [(set_attr "conds" "clob")
8226    (set_attr "length" "2")]
8230 ;; Misc insns
8232 (define_insn "nop"
8233   [(const_int 0)]
8234   "TARGET_EITHER"
8235   "*
8236   if (TARGET_ARM)
8237     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8238   return  \"mov\\tr8, r8\";
8239   "
8240   [(set (attr "length")
8241         (if_then_else (eq_attr "is_thumb" "yes")
8242                       (const_int 2)
8243                       (const_int 4)))]
8247 ;; Patterns to allow combination of arithmetic, cond code and shifts
8249 (define_insn "*arith_shiftsi"
8250   [(set (match_operand:SI 0 "s_register_operand" "=r")
8251         (match_operator:SI 1 "shiftable_operator"
8252           [(match_operator:SI 3 "shift_operator"
8253              [(match_operand:SI 4 "s_register_operand" "r")
8254               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8255            (match_operand:SI 2 "s_register_operand" "r")]))]
8256   "TARGET_ARM"
8257   "%i1%?\\t%0, %2, %4%S3"
8258   [(set_attr "predicable" "yes")
8259    (set_attr "shift" "4")
8260    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8261                       (const_string "alu_shift")
8262                       (const_string "alu_shift_reg")))]
8265 (define_split
8266   [(set (match_operand:SI 0 "s_register_operand" "")
8267         (match_operator:SI 1 "shiftable_operator"
8268          [(match_operator:SI 2 "shiftable_operator"
8269            [(match_operator:SI 3 "shift_operator"
8270              [(match_operand:SI 4 "s_register_operand" "")
8271               (match_operand:SI 5 "reg_or_int_operand" "")])
8272             (match_operand:SI 6 "s_register_operand" "")])
8273           (match_operand:SI 7 "arm_rhs_operand" "")]))
8274    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8275   "TARGET_ARM"
8276   [(set (match_dup 8)
8277         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8278                          (match_dup 6)]))
8279    (set (match_dup 0)
8280         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8281   "")
8283 (define_insn "*arith_shiftsi_compare0"
8284   [(set (reg:CC_NOOV CC_REGNUM)
8285         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8286                           [(match_operator:SI 3 "shift_operator"
8287                             [(match_operand:SI 4 "s_register_operand" "r")
8288                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8289                            (match_operand:SI 2 "s_register_operand" "r")])
8290                          (const_int 0)))
8291    (set (match_operand:SI 0 "s_register_operand" "=r")
8292         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8293                          (match_dup 2)]))]
8294   "TARGET_ARM"
8295   "%i1%?s\\t%0, %2, %4%S3"
8296   [(set_attr "conds" "set")
8297    (set_attr "shift" "4")
8298    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8299                       (const_string "alu_shift")
8300                       (const_string "alu_shift_reg")))]
8303 (define_insn "*arith_shiftsi_compare0_scratch"
8304   [(set (reg:CC_NOOV CC_REGNUM)
8305         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8306                           [(match_operator:SI 3 "shift_operator"
8307                             [(match_operand:SI 4 "s_register_operand" "r")
8308                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8309                            (match_operand:SI 2 "s_register_operand" "r")])
8310                          (const_int 0)))
8311    (clobber (match_scratch:SI 0 "=r"))]
8312   "TARGET_ARM"
8313   "%i1%?s\\t%0, %2, %4%S3"
8314   [(set_attr "conds" "set")
8315    (set_attr "shift" "4")
8316    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8317                       (const_string "alu_shift")
8318                       (const_string "alu_shift_reg")))]
8321 (define_insn "*sub_shiftsi"
8322   [(set (match_operand:SI 0 "s_register_operand" "=r")
8323         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8324                   (match_operator:SI 2 "shift_operator"
8325                    [(match_operand:SI 3 "s_register_operand" "r")
8326                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8327   "TARGET_ARM"
8328   "sub%?\\t%0, %1, %3%S2"
8329   [(set_attr "predicable" "yes")
8330    (set_attr "shift" "3")
8331    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8332                       (const_string "alu_shift")
8333                       (const_string "alu_shift_reg")))]
8336 (define_insn "*sub_shiftsi_compare0"
8337   [(set (reg:CC_NOOV CC_REGNUM)
8338         (compare:CC_NOOV
8339          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8340                    (match_operator:SI 2 "shift_operator"
8341                     [(match_operand:SI 3 "s_register_operand" "r")
8342                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8343          (const_int 0)))
8344    (set (match_operand:SI 0 "s_register_operand" "=r")
8345         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8346                                                  (match_dup 4)])))]
8347   "TARGET_ARM"
8348   "sub%?s\\t%0, %1, %3%S2"
8349   [(set_attr "conds" "set")
8350    (set_attr "shift" "3")
8351    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8352                       (const_string "alu_shift")
8353                       (const_string "alu_shift_reg")))]
8356 (define_insn "*sub_shiftsi_compare0_scratch"
8357   [(set (reg:CC_NOOV CC_REGNUM)
8358         (compare:CC_NOOV
8359          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8360                    (match_operator:SI 2 "shift_operator"
8361                     [(match_operand:SI 3 "s_register_operand" "r")
8362                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8363          (const_int 0)))
8364    (clobber (match_scratch:SI 0 "=r"))]
8365   "TARGET_ARM"
8366   "sub%?s\\t%0, %1, %3%S2"
8367   [(set_attr "conds" "set")
8368    (set_attr "shift" "3")
8369    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8370                       (const_string "alu_shift")
8371                       (const_string "alu_shift_reg")))]
8376 (define_insn "*and_scc"
8377   [(set (match_operand:SI 0 "s_register_operand" "=r")
8378         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8379                  [(match_operand 3 "cc_register" "") (const_int 0)])
8380                 (match_operand:SI 2 "s_register_operand" "r")))]
8381   "TARGET_ARM"
8382   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8383   [(set_attr "conds" "use")
8384    (set_attr "length" "8")]
8387 (define_insn "*ior_scc"
8388   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8389         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8390                  [(match_operand 3 "cc_register" "") (const_int 0)])
8391                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8392   "TARGET_ARM"
8393   "@
8394    orr%d2\\t%0, %1, #1
8395    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8396   [(set_attr "conds" "use")
8397    (set_attr "length" "4,8")]
8400 (define_insn "*compare_scc"
8401   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8402         (match_operator:SI 1 "arm_comparison_operator"
8403          [(match_operand:SI 2 "s_register_operand" "r,r")
8404           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8405    (clobber (reg:CC CC_REGNUM))]
8406   "TARGET_ARM"
8407   "*
8408     if (operands[3] == const0_rtx)
8409       {
8410         if (GET_CODE (operands[1]) == LT)
8411           return \"mov\\t%0, %2, lsr #31\";
8413         if (GET_CODE (operands[1]) == GE)
8414           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8416         if (GET_CODE (operands[1]) == EQ)
8417           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8418       }
8420     if (GET_CODE (operands[1]) == NE)
8421       {
8422         if (which_alternative == 1)
8423           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8424         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8425       }
8426     if (which_alternative == 1)
8427       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8428     else
8429       output_asm_insn (\"cmp\\t%2, %3\", operands);
8430     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8431   "
8432   [(set_attr "conds" "clob")
8433    (set_attr "length" "12")]
8436 (define_insn "*cond_move"
8437   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8438         (if_then_else:SI (match_operator 3 "equality_operator"
8439                           [(match_operator 4 "arm_comparison_operator"
8440                             [(match_operand 5 "cc_register" "") (const_int 0)])
8441                            (const_int 0)])
8442                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8443                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8444   "TARGET_ARM"
8445   "*
8446     if (GET_CODE (operands[3]) == NE)
8447       {
8448         if (which_alternative != 1)
8449           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8450         if (which_alternative != 0)
8451           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8452         return \"\";
8453       }
8454     if (which_alternative != 0)
8455       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8456     if (which_alternative != 1)
8457       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8458     return \"\";
8459   "
8460   [(set_attr "conds" "use")
8461    (set_attr "length" "4,4,8")]
8464 (define_insn "*cond_arith"
8465   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8466         (match_operator:SI 5 "shiftable_operator" 
8467          [(match_operator:SI 4 "arm_comparison_operator"
8468            [(match_operand:SI 2 "s_register_operand" "r,r")
8469             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8470           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8471    (clobber (reg:CC CC_REGNUM))]
8472   "TARGET_ARM"
8473   "*
8474     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8475       return \"%i5\\t%0, %1, %2, lsr #31\";
8477     output_asm_insn (\"cmp\\t%2, %3\", operands);
8478     if (GET_CODE (operands[5]) == AND)
8479       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8480     else if (GET_CODE (operands[5]) == MINUS)
8481       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8482     else if (which_alternative != 0)
8483       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8484     return \"%i5%d4\\t%0, %1, #1\";
8485   "
8486   [(set_attr "conds" "clob")
8487    (set_attr "length" "12")]
8490 (define_insn "*cond_sub"
8491   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8492         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8493                   (match_operator:SI 4 "arm_comparison_operator"
8494                    [(match_operand:SI 2 "s_register_operand" "r,r")
8495                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8496    (clobber (reg:CC CC_REGNUM))]
8497   "TARGET_ARM"
8498   "*
8499     output_asm_insn (\"cmp\\t%2, %3\", operands);
8500     if (which_alternative != 0)
8501       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8502     return \"sub%d4\\t%0, %1, #1\";
8503   "
8504   [(set_attr "conds" "clob")
8505    (set_attr "length" "8,12")]
8508 (define_insn "*cmp_ite0"
8509   [(set (match_operand 6 "dominant_cc_register" "")
8510         (compare
8511          (if_then_else:SI
8512           (match_operator 4 "arm_comparison_operator"
8513            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8514             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8515           (match_operator:SI 5 "arm_comparison_operator"
8516            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8517             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8518           (const_int 0))
8519          (const_int 0)))]
8520   "TARGET_ARM"
8521   "*
8522   {
8523     static const char * const opcodes[4][2] =
8524     {
8525       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8526        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8527       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8528        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8529       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8530        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8531       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8532        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8533     };
8534     int swap =
8535       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8537     return opcodes[which_alternative][swap];
8538   }"
8539   [(set_attr "conds" "set")
8540    (set_attr "length" "8")]
8543 (define_insn "*cmp_ite1"
8544   [(set (match_operand 6 "dominant_cc_register" "")
8545         (compare
8546          (if_then_else:SI
8547           (match_operator 4 "arm_comparison_operator"
8548            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8549             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8550           (match_operator:SI 5 "arm_comparison_operator"
8551            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8552             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8553           (const_int 1))
8554          (const_int 0)))]
8555   "TARGET_ARM"
8556   "*
8557   {
8558     static const char * const opcodes[4][2] =
8559     {
8560       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8561        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8562       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8563        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8564       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8565        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8566       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8567        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8568     };
8569     int swap =
8570       comparison_dominates_p (GET_CODE (operands[5]),
8571                               reverse_condition (GET_CODE (operands[4])));
8573     return opcodes[which_alternative][swap];
8574   }"
8575   [(set_attr "conds" "set")
8576    (set_attr "length" "8")]
8579 (define_insn "*cmp_and"
8580   [(set (match_operand 6 "dominant_cc_register" "")
8581         (compare
8582          (and:SI
8583           (match_operator 4 "arm_comparison_operator"
8584            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8585             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8586           (match_operator:SI 5 "arm_comparison_operator"
8587            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8588             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8589          (const_int 0)))]
8590   "TARGET_ARM"
8591   "*
8592   {
8593     static const char *const opcodes[4][2] =
8594     {
8595       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8596        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8597       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8598        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8599       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8600        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8601       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8602        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8603     };
8604     int swap =
8605       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8607     return opcodes[which_alternative][swap];
8608   }"
8609   [(set_attr "conds" "set")
8610    (set_attr "predicable" "no")
8611    (set_attr "length" "8")]
8614 (define_insn "*cmp_ior"
8615   [(set (match_operand 6 "dominant_cc_register" "")
8616         (compare
8617          (ior:SI
8618           (match_operator 4 "arm_comparison_operator"
8619            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8620             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8621           (match_operator:SI 5 "arm_comparison_operator"
8622            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8623             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8624          (const_int 0)))]
8625   "TARGET_ARM"
8626   "*
8628   static const char *const opcodes[4][2] =
8629   {
8630     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8631      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8632     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8633      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8634     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8635      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8636     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8637      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8638   };
8639   int swap =
8640     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8642   return opcodes[which_alternative][swap];
8645   [(set_attr "conds" "set")
8646    (set_attr "length" "8")]
8649 (define_insn_and_split "*ior_scc_scc"
8650   [(set (match_operand:SI 0 "s_register_operand" "=r")
8651         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8652                  [(match_operand:SI 1 "s_register_operand" "r")
8653                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8654                 (match_operator:SI 6 "arm_comparison_operator"
8655                  [(match_operand:SI 4 "s_register_operand" "r")
8656                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8657    (clobber (reg:CC CC_REGNUM))]
8658   "TARGET_ARM
8659    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8660        != CCmode)"
8661   "#"
8662   "TARGET_ARM && reload_completed"
8663   [(set (match_dup 7)
8664         (compare
8665          (ior:SI
8666           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8667           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8668          (const_int 0)))
8669    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8670   "operands[7]
8671      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8672                                                   DOM_CC_X_OR_Y),
8673                     CC_REGNUM);"
8674   [(set_attr "conds" "clob")
8675    (set_attr "length" "16")])
8677 ; If the above pattern is followed by a CMP insn, then the compare is 
8678 ; redundant, since we can rework the conditional instruction that follows.
8679 (define_insn_and_split "*ior_scc_scc_cmp"
8680   [(set (match_operand 0 "dominant_cc_register" "")
8681         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8682                           [(match_operand:SI 1 "s_register_operand" "r")
8683                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8684                          (match_operator:SI 6 "arm_comparison_operator"
8685                           [(match_operand:SI 4 "s_register_operand" "r")
8686                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8687                  (const_int 0)))
8688    (set (match_operand:SI 7 "s_register_operand" "=r")
8689         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8690                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8691   "TARGET_ARM"
8692   "#"
8693   "TARGET_ARM && reload_completed"
8694   [(set (match_dup 0)
8695         (compare
8696          (ior:SI
8697           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8698           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8699          (const_int 0)))
8700    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8701   ""
8702   [(set_attr "conds" "set")
8703    (set_attr "length" "16")])
8705 (define_insn_and_split "*and_scc_scc"
8706   [(set (match_operand:SI 0 "s_register_operand" "=r")
8707         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8708                  [(match_operand:SI 1 "s_register_operand" "r")
8709                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8710                 (match_operator:SI 6 "arm_comparison_operator"
8711                  [(match_operand:SI 4 "s_register_operand" "r")
8712                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8713    (clobber (reg:CC CC_REGNUM))]
8714   "TARGET_ARM
8715    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8716        != CCmode)"
8717   "#"
8718   "TARGET_ARM && reload_completed
8719    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8720        != CCmode)"
8721   [(set (match_dup 7)
8722         (compare
8723          (and:SI
8724           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8725           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8726          (const_int 0)))
8727    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8728   "operands[7]
8729      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8730                                                   DOM_CC_X_AND_Y),
8731                     CC_REGNUM);"
8732   [(set_attr "conds" "clob")
8733    (set_attr "length" "16")])
8735 ; If the above pattern is followed by a CMP insn, then the compare is 
8736 ; redundant, since we can rework the conditional instruction that follows.
8737 (define_insn_and_split "*and_scc_scc_cmp"
8738   [(set (match_operand 0 "dominant_cc_register" "")
8739         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8740                           [(match_operand:SI 1 "s_register_operand" "r")
8741                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8742                          (match_operator:SI 6 "arm_comparison_operator"
8743                           [(match_operand:SI 4 "s_register_operand" "r")
8744                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8745                  (const_int 0)))
8746    (set (match_operand:SI 7 "s_register_operand" "=r")
8747         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8748                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8749   "TARGET_ARM"
8750   "#"
8751   "TARGET_ARM && reload_completed"
8752   [(set (match_dup 0)
8753         (compare
8754          (and:SI
8755           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8756           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8757          (const_int 0)))
8758    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8759   ""
8760   [(set_attr "conds" "set")
8761    (set_attr "length" "16")])
8763 ;; If there is no dominance in the comparison, then we can still save an
8764 ;; instruction in the AND case, since we can know that the second compare
8765 ;; need only zero the value if false (if true, then the value is already
8766 ;; correct).
8767 (define_insn_and_split "*and_scc_scc_nodom"
8768   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8769         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8770                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8771                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8772                 (match_operator:SI 6 "arm_comparison_operator"
8773                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8774                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8775    (clobber (reg:CC CC_REGNUM))]
8776   "TARGET_ARM
8777    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8778        == CCmode)"
8779   "#"
8780   "TARGET_ARM && reload_completed"
8781   [(parallel [(set (match_dup 0)
8782                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8783               (clobber (reg:CC CC_REGNUM))])
8784    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8785    (set (match_dup 0)
8786         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8787                          (match_dup 0)
8788                          (const_int 0)))]
8789   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8790                                               operands[4], operands[5]),
8791                               CC_REGNUM);
8792    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8793                                   operands[5]);"
8794   [(set_attr "conds" "clob")
8795    (set_attr "length" "20")])
8797 (define_split
8798   [(set (reg:CC_NOOV CC_REGNUM)
8799         (compare:CC_NOOV (ior:SI
8800                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8801                                   (const_int 1))
8802                           (match_operator:SI 1 "comparison_operator"
8803                            [(match_operand:SI 2 "s_register_operand" "")
8804                             (match_operand:SI 3 "arm_add_operand" "")]))
8805                          (const_int 0)))
8806    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8807   "TARGET_ARM"
8808   [(set (match_dup 4)
8809         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8810                 (match_dup 0)))
8811    (set (reg:CC_NOOV CC_REGNUM)
8812         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8813                          (const_int 0)))]
8814   "")
8816 (define_split
8817   [(set (reg:CC_NOOV CC_REGNUM)
8818         (compare:CC_NOOV (ior:SI
8819                           (match_operator:SI 1 "comparison_operator"
8820                            [(match_operand:SI 2 "s_register_operand" "")
8821                             (match_operand:SI 3 "arm_add_operand" "")])
8822                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8823                                   (const_int 1)))
8824                          (const_int 0)))
8825    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8826   "TARGET_ARM"
8827   [(set (match_dup 4)
8828         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8829                 (match_dup 0)))
8830    (set (reg:CC_NOOV CC_REGNUM)
8831         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8832                          (const_int 0)))]
8833   "")
8835 (define_insn "*negscc"
8836   [(set (match_operand:SI 0 "s_register_operand" "=r")
8837         (neg:SI (match_operator 3 "arm_comparison_operator"
8838                  [(match_operand:SI 1 "s_register_operand" "r")
8839                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8840    (clobber (reg:CC CC_REGNUM))]
8841   "TARGET_ARM"
8842   "*
8843   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8844     return \"mov\\t%0, %1, asr #31\";
8846   if (GET_CODE (operands[3]) == NE)
8847     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8849   if (GET_CODE (operands[3]) == GT)
8850     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8852   output_asm_insn (\"cmp\\t%1, %2\", operands);
8853   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8854   return \"mvn%d3\\t%0, #0\";
8855   "
8856   [(set_attr "conds" "clob")
8857    (set_attr "length" "12")]
8860 (define_insn "movcond"
8861   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8862         (if_then_else:SI
8863          (match_operator 5 "arm_comparison_operator"
8864           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8865            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8866          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8867          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8868    (clobber (reg:CC CC_REGNUM))]
8869   "TARGET_ARM"
8870   "*
8871   if (GET_CODE (operands[5]) == LT
8872       && (operands[4] == const0_rtx))
8873     {
8874       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8875         {
8876           if (operands[2] == const0_rtx)
8877             return \"and\\t%0, %1, %3, asr #31\";
8878           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8879         }
8880       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8881         {
8882           if (operands[1] == const0_rtx)
8883             return \"bic\\t%0, %2, %3, asr #31\";
8884           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8885         }
8886       /* The only case that falls through to here is when both ops 1 & 2
8887          are constants.  */
8888     }
8890   if (GET_CODE (operands[5]) == GE
8891       && (operands[4] == const0_rtx))
8892     {
8893       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8894         {
8895           if (operands[2] == const0_rtx)
8896             return \"bic\\t%0, %1, %3, asr #31\";
8897           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8898         }
8899       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8900         {
8901           if (operands[1] == const0_rtx)
8902             return \"and\\t%0, %2, %3, asr #31\";
8903           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8904         }
8905       /* The only case that falls through to here is when both ops 1 & 2
8906          are constants.  */
8907     }
8908   if (GET_CODE (operands[4]) == CONST_INT
8909       && !const_ok_for_arm (INTVAL (operands[4])))
8910     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8911   else
8912     output_asm_insn (\"cmp\\t%3, %4\", operands);
8913   if (which_alternative != 0)
8914     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8915   if (which_alternative != 1)
8916     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8917   return \"\";
8918   "
8919   [(set_attr "conds" "clob")
8920    (set_attr "length" "8,8,12")]
8923 (define_insn "*ifcompare_plus_move"
8924   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8925         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8926                           [(match_operand:SI 4 "s_register_operand" "r,r")
8927                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8928                          (plus:SI
8929                           (match_operand:SI 2 "s_register_operand" "r,r")
8930                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8931                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8932    (clobber (reg:CC CC_REGNUM))]
8933   "TARGET_ARM"
8934   "#"
8935   [(set_attr "conds" "clob")
8936    (set_attr "length" "8,12")]
8939 (define_insn "*if_plus_move"
8940   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8941         (if_then_else:SI
8942          (match_operator 4 "arm_comparison_operator"
8943           [(match_operand 5 "cc_register" "") (const_int 0)])
8944          (plus:SI
8945           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8946           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8947          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8948   "TARGET_ARM"
8949   "@
8950    add%d4\\t%0, %2, %3
8951    sub%d4\\t%0, %2, #%n3
8952    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8953    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8954   [(set_attr "conds" "use")
8955    (set_attr "length" "4,4,8,8")
8956    (set_attr "type" "*,*,*,*")]
8959 (define_insn "*ifcompare_move_plus"
8960   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8961         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8962                           [(match_operand:SI 4 "s_register_operand" "r,r")
8963                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8964                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8965                          (plus:SI
8966                           (match_operand:SI 2 "s_register_operand" "r,r")
8967                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8968    (clobber (reg:CC CC_REGNUM))]
8969   "TARGET_ARM"
8970   "#"
8971   [(set_attr "conds" "clob")
8972    (set_attr "length" "8,12")]
8975 (define_insn "*if_move_plus"
8976   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8977         (if_then_else:SI
8978          (match_operator 4 "arm_comparison_operator"
8979           [(match_operand 5 "cc_register" "") (const_int 0)])
8980          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8981          (plus:SI
8982           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8983           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8984   "TARGET_ARM"
8985   "@
8986    add%D4\\t%0, %2, %3
8987    sub%D4\\t%0, %2, #%n3
8988    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8989    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8990   [(set_attr "conds" "use")
8991    (set_attr "length" "4,4,8,8")
8992    (set_attr "type" "*,*,*,*")]
8995 (define_insn "*ifcompare_arith_arith"
8996   [(set (match_operand:SI 0 "s_register_operand" "=r")
8997         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8998                           [(match_operand:SI 5 "s_register_operand" "r")
8999                            (match_operand:SI 6 "arm_add_operand" "rIL")])
9000                          (match_operator:SI 8 "shiftable_operator"
9001                           [(match_operand:SI 1 "s_register_operand" "r")
9002                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9003                          (match_operator:SI 7 "shiftable_operator"
9004                           [(match_operand:SI 3 "s_register_operand" "r")
9005                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
9006    (clobber (reg:CC CC_REGNUM))]
9007   "TARGET_ARM"
9008   "#"
9009   [(set_attr "conds" "clob")
9010    (set_attr "length" "12")]
9013 (define_insn "*if_arith_arith"
9014   [(set (match_operand:SI 0 "s_register_operand" "=r")
9015         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
9016                           [(match_operand 8 "cc_register" "") (const_int 0)])
9017                          (match_operator:SI 6 "shiftable_operator"
9018                           [(match_operand:SI 1 "s_register_operand" "r")
9019                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
9020                          (match_operator:SI 7 "shiftable_operator"
9021                           [(match_operand:SI 3 "s_register_operand" "r")
9022                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
9023   "TARGET_ARM"
9024   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
9025   [(set_attr "conds" "use")
9026    (set_attr "length" "8")]
9029 (define_insn "*ifcompare_arith_move"
9030   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9031         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9032                           [(match_operand:SI 2 "s_register_operand" "r,r")
9033                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
9034                          (match_operator:SI 7 "shiftable_operator"
9035                           [(match_operand:SI 4 "s_register_operand" "r,r")
9036                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
9037                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
9038    (clobber (reg:CC CC_REGNUM))]
9039   "TARGET_ARM"
9040   "*
9041   /* If we have an operation where (op x 0) is the identity operation and
9042      the conditional operator is LT or GE and we are comparing against zero and
9043      everything is in registers then we can do this in two instructions.  */
9044   if (operands[3] == const0_rtx
9045       && GET_CODE (operands[7]) != AND
9046       && GET_CODE (operands[5]) == REG
9047       && GET_CODE (operands[1]) == REG 
9048       && REGNO (operands[1]) == REGNO (operands[4])
9049       && REGNO (operands[4]) != REGNO (operands[0]))
9050     {
9051       if (GET_CODE (operands[6]) == LT)
9052         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9053       else if (GET_CODE (operands[6]) == GE)
9054         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
9055     }
9056   if (GET_CODE (operands[3]) == CONST_INT
9057       && !const_ok_for_arm (INTVAL (operands[3])))
9058     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
9059   else
9060     output_asm_insn (\"cmp\\t%2, %3\", operands);
9061   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
9062   if (which_alternative != 0)
9063     return \"mov%D6\\t%0, %1\";
9064   return \"\";
9065   "
9066   [(set_attr "conds" "clob")
9067    (set_attr "length" "8,12")]
9070 (define_insn "*if_arith_move"
9071   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9072         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9073                           [(match_operand 6 "cc_register" "") (const_int 0)])
9074                          (match_operator:SI 5 "shiftable_operator"
9075                           [(match_operand:SI 2 "s_register_operand" "r,r")
9076                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
9077                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
9078   "TARGET_ARM"
9079   "@
9080    %I5%d4\\t%0, %2, %3
9081    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
9082   [(set_attr "conds" "use")
9083    (set_attr "length" "4,8")
9084    (set_attr "type" "*,*")]
9087 (define_insn "*ifcompare_move_arith"
9088   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9089         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
9090                           [(match_operand:SI 4 "s_register_operand" "r,r")
9091                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9092                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9093                          (match_operator:SI 7 "shiftable_operator"
9094                           [(match_operand:SI 2 "s_register_operand" "r,r")
9095                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
9096    (clobber (reg:CC CC_REGNUM))]
9097   "TARGET_ARM"
9098   "*
9099   /* If we have an operation where (op x 0) is the identity operation and
9100      the conditional operator is LT or GE and we are comparing against zero and
9101      everything is in registers then we can do this in two instructions */
9102   if (operands[5] == const0_rtx
9103       && GET_CODE (operands[7]) != AND
9104       && GET_CODE (operands[3]) == REG
9105       && GET_CODE (operands[1]) == REG 
9106       && REGNO (operands[1]) == REGNO (operands[2])
9107       && REGNO (operands[2]) != REGNO (operands[0]))
9108     {
9109       if (GET_CODE (operands[6]) == GE)
9110         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9111       else if (GET_CODE (operands[6]) == LT)
9112         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9113     }
9115   if (GET_CODE (operands[5]) == CONST_INT
9116       && !const_ok_for_arm (INTVAL (operands[5])))
9117     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9118   else
9119     output_asm_insn (\"cmp\\t%4, %5\", operands);
9121   if (which_alternative != 0)
9122     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9123   return \"%I7%D6\\t%0, %2, %3\";
9124   "
9125   [(set_attr "conds" "clob")
9126    (set_attr "length" "8,12")]
9129 (define_insn "*if_move_arith"
9130   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9131         (if_then_else:SI
9132          (match_operator 4 "arm_comparison_operator"
9133           [(match_operand 6 "cc_register" "") (const_int 0)])
9134          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9135          (match_operator:SI 5 "shiftable_operator"
9136           [(match_operand:SI 2 "s_register_operand" "r,r")
9137            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9138   "TARGET_ARM"
9139   "@
9140    %I5%D4\\t%0, %2, %3
9141    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9142   [(set_attr "conds" "use")
9143    (set_attr "length" "4,8")
9144    (set_attr "type" "*,*")]
9147 (define_insn "*ifcompare_move_not"
9148   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9149         (if_then_else:SI
9150          (match_operator 5 "arm_comparison_operator"
9151           [(match_operand:SI 3 "s_register_operand" "r,r")
9152            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9153          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9154          (not:SI
9155           (match_operand:SI 2 "s_register_operand" "r,r"))))
9156    (clobber (reg:CC CC_REGNUM))]
9157   "TARGET_ARM"
9158   "#"
9159   [(set_attr "conds" "clob")
9160    (set_attr "length" "8,12")]
9163 (define_insn "*if_move_not"
9164   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9165         (if_then_else:SI
9166          (match_operator 4 "arm_comparison_operator"
9167           [(match_operand 3 "cc_register" "") (const_int 0)])
9168          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9169          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9170   "TARGET_ARM"
9171   "@
9172    mvn%D4\\t%0, %2
9173    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9174    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9175   [(set_attr "conds" "use")
9176    (set_attr "length" "4,8,8")]
9179 (define_insn "*ifcompare_not_move"
9180   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9181         (if_then_else:SI 
9182          (match_operator 5 "arm_comparison_operator"
9183           [(match_operand:SI 3 "s_register_operand" "r,r")
9184            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9185          (not:SI
9186           (match_operand:SI 2 "s_register_operand" "r,r"))
9187          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9188    (clobber (reg:CC CC_REGNUM))]
9189   "TARGET_ARM"
9190   "#"
9191   [(set_attr "conds" "clob")
9192    (set_attr "length" "8,12")]
9195 (define_insn "*if_not_move"
9196   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9197         (if_then_else:SI
9198          (match_operator 4 "arm_comparison_operator"
9199           [(match_operand 3 "cc_register" "") (const_int 0)])
9200          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9201          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9202   "TARGET_ARM"
9203   "@
9204    mvn%d4\\t%0, %2
9205    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9206    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9207   [(set_attr "conds" "use")
9208    (set_attr "length" "4,8,8")]
9211 (define_insn "*ifcompare_shift_move"
9212   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9213         (if_then_else:SI
9214          (match_operator 6 "arm_comparison_operator"
9215           [(match_operand:SI 4 "s_register_operand" "r,r")
9216            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9217          (match_operator:SI 7 "shift_operator"
9218           [(match_operand:SI 2 "s_register_operand" "r,r")
9219            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9220          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9221    (clobber (reg:CC CC_REGNUM))]
9222   "TARGET_ARM"
9223   "#"
9224   [(set_attr "conds" "clob")
9225    (set_attr "length" "8,12")]
9228 (define_insn "*if_shift_move"
9229   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9230         (if_then_else:SI
9231          (match_operator 5 "arm_comparison_operator"
9232           [(match_operand 6 "cc_register" "") (const_int 0)])
9233          (match_operator:SI 4 "shift_operator"
9234           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9235            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9236          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9237   "TARGET_ARM"
9238   "@
9239    mov%d5\\t%0, %2%S4
9240    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9241    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9242   [(set_attr "conds" "use")
9243    (set_attr "shift" "2")
9244    (set_attr "length" "4,8,8")
9245    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9246                       (const_string "alu_shift")
9247                       (const_string "alu_shift_reg")))]
9250 (define_insn "*ifcompare_move_shift"
9251   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9252         (if_then_else:SI
9253          (match_operator 6 "arm_comparison_operator"
9254           [(match_operand:SI 4 "s_register_operand" "r,r")
9255            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9256          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9257          (match_operator:SI 7 "shift_operator"
9258           [(match_operand:SI 2 "s_register_operand" "r,r")
9259            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9260    (clobber (reg:CC CC_REGNUM))]
9261   "TARGET_ARM"
9262   "#"
9263   [(set_attr "conds" "clob")
9264    (set_attr "length" "8,12")]
9267 (define_insn "*if_move_shift"
9268   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9269         (if_then_else:SI
9270          (match_operator 5 "arm_comparison_operator"
9271           [(match_operand 6 "cc_register" "") (const_int 0)])
9272          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9273          (match_operator:SI 4 "shift_operator"
9274           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9275            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9276   "TARGET_ARM"
9277   "@
9278    mov%D5\\t%0, %2%S4
9279    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9280    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9281   [(set_attr "conds" "use")
9282    (set_attr "shift" "2")
9283    (set_attr "length" "4,8,8")
9284    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9285                       (const_string "alu_shift")
9286                       (const_string "alu_shift_reg")))]
9289 (define_insn "*ifcompare_shift_shift"
9290   [(set (match_operand:SI 0 "s_register_operand" "=r")
9291         (if_then_else:SI
9292          (match_operator 7 "arm_comparison_operator"
9293           [(match_operand:SI 5 "s_register_operand" "r")
9294            (match_operand:SI 6 "arm_add_operand" "rIL")])
9295          (match_operator:SI 8 "shift_operator"
9296           [(match_operand:SI 1 "s_register_operand" "r")
9297            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9298          (match_operator:SI 9 "shift_operator"
9299           [(match_operand:SI 3 "s_register_operand" "r")
9300            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9301    (clobber (reg:CC CC_REGNUM))]
9302   "TARGET_ARM"
9303   "#"
9304   [(set_attr "conds" "clob")
9305    (set_attr "length" "12")]
9308 (define_insn "*if_shift_shift"
9309   [(set (match_operand:SI 0 "s_register_operand" "=r")
9310         (if_then_else:SI
9311          (match_operator 5 "arm_comparison_operator"
9312           [(match_operand 8 "cc_register" "") (const_int 0)])
9313          (match_operator:SI 6 "shift_operator"
9314           [(match_operand:SI 1 "s_register_operand" "r")
9315            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9316          (match_operator:SI 7 "shift_operator"
9317           [(match_operand:SI 3 "s_register_operand" "r")
9318            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9319   "TARGET_ARM"
9320   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9321   [(set_attr "conds" "use")
9322    (set_attr "shift" "1")
9323    (set_attr "length" "8")
9324    (set (attr "type") (if_then_else
9325                         (and (match_operand 2 "const_int_operand" "")
9326                              (match_operand 4 "const_int_operand" ""))
9327                       (const_string "alu_shift")
9328                       (const_string "alu_shift_reg")))]
9331 (define_insn "*ifcompare_not_arith"
9332   [(set (match_operand:SI 0 "s_register_operand" "=r")
9333         (if_then_else:SI
9334          (match_operator 6 "arm_comparison_operator"
9335           [(match_operand:SI 4 "s_register_operand" "r")
9336            (match_operand:SI 5 "arm_add_operand" "rIL")])
9337          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9338          (match_operator:SI 7 "shiftable_operator"
9339           [(match_operand:SI 2 "s_register_operand" "r")
9340            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9341    (clobber (reg:CC CC_REGNUM))]
9342   "TARGET_ARM"
9343   "#"
9344   [(set_attr "conds" "clob")
9345    (set_attr "length" "12")]
9348 (define_insn "*if_not_arith"
9349   [(set (match_operand:SI 0 "s_register_operand" "=r")
9350         (if_then_else:SI
9351          (match_operator 5 "arm_comparison_operator"
9352           [(match_operand 4 "cc_register" "") (const_int 0)])
9353          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9354          (match_operator:SI 6 "shiftable_operator"
9355           [(match_operand:SI 2 "s_register_operand" "r")
9356            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9357   "TARGET_ARM"
9358   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9359   [(set_attr "conds" "use")
9360    (set_attr "length" "8")]
9363 (define_insn "*ifcompare_arith_not"
9364   [(set (match_operand:SI 0 "s_register_operand" "=r")
9365         (if_then_else:SI
9366          (match_operator 6 "arm_comparison_operator"
9367           [(match_operand:SI 4 "s_register_operand" "r")
9368            (match_operand:SI 5 "arm_add_operand" "rIL")])
9369          (match_operator:SI 7 "shiftable_operator"
9370           [(match_operand:SI 2 "s_register_operand" "r")
9371            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9372          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9373    (clobber (reg:CC CC_REGNUM))]
9374   "TARGET_ARM"
9375   "#"
9376   [(set_attr "conds" "clob")
9377    (set_attr "length" "12")]
9380 (define_insn "*if_arith_not"
9381   [(set (match_operand:SI 0 "s_register_operand" "=r")
9382         (if_then_else:SI
9383          (match_operator 5 "arm_comparison_operator"
9384           [(match_operand 4 "cc_register" "") (const_int 0)])
9385          (match_operator:SI 6 "shiftable_operator"
9386           [(match_operand:SI 2 "s_register_operand" "r")
9387            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9388          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9389   "TARGET_ARM"
9390   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9391   [(set_attr "conds" "use")
9392    (set_attr "length" "8")]
9395 (define_insn "*ifcompare_neg_move"
9396   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9397         (if_then_else:SI
9398          (match_operator 5 "arm_comparison_operator"
9399           [(match_operand:SI 3 "s_register_operand" "r,r")
9400            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9401          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9402          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9403    (clobber (reg:CC CC_REGNUM))]
9404   "TARGET_ARM"
9405   "#"
9406   [(set_attr "conds" "clob")
9407    (set_attr "length" "8,12")]
9410 (define_insn "*if_neg_move"
9411   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9412         (if_then_else:SI
9413          (match_operator 4 "arm_comparison_operator"
9414           [(match_operand 3 "cc_register" "") (const_int 0)])
9415          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9416          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9417   "TARGET_ARM"
9418   "@
9419    rsb%d4\\t%0, %2, #0
9420    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9421    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9422   [(set_attr "conds" "use")
9423    (set_attr "length" "4,8,8")]
9426 (define_insn "*ifcompare_move_neg"
9427   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9428         (if_then_else:SI
9429          (match_operator 5 "arm_comparison_operator"
9430           [(match_operand:SI 3 "s_register_operand" "r,r")
9431            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9432          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9433          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9434    (clobber (reg:CC CC_REGNUM))]
9435   "TARGET_ARM"
9436   "#"
9437   [(set_attr "conds" "clob")
9438    (set_attr "length" "8,12")]
9441 (define_insn "*if_move_neg"
9442   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9443         (if_then_else:SI
9444          (match_operator 4 "arm_comparison_operator"
9445           [(match_operand 3 "cc_register" "") (const_int 0)])
9446          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9447          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9448   "TARGET_ARM"
9449   "@
9450    rsb%D4\\t%0, %2, #0
9451    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9452    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9453   [(set_attr "conds" "use")
9454    (set_attr "length" "4,8,8")]
9457 (define_insn "*arith_adjacentmem"
9458   [(set (match_operand:SI 0 "s_register_operand" "=r")
9459         (match_operator:SI 1 "shiftable_operator"
9460          [(match_operand:SI 2 "memory_operand" "m")
9461           (match_operand:SI 3 "memory_operand" "m")]))
9462    (clobber (match_scratch:SI 4 "=r"))]
9463   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9464   "*
9465   {
9466     rtx ldm[3];
9467     rtx arith[4];
9468     rtx base_reg;
9469     HOST_WIDE_INT val1 = 0, val2 = 0;
9471     if (REGNO (operands[0]) > REGNO (operands[4]))
9472       {
9473         ldm[1] = operands[4];
9474         ldm[2] = operands[0];
9475       }
9476     else
9477       {
9478         ldm[1] = operands[0];
9479         ldm[2] = operands[4];
9480       }
9482     base_reg = XEXP (operands[2], 0);
9484     if (!REG_P (base_reg))
9485       {
9486         val1 = INTVAL (XEXP (base_reg, 1));
9487         base_reg = XEXP (base_reg, 0);
9488       }
9490     if (!REG_P (XEXP (operands[3], 0)))
9491       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9493     arith[0] = operands[0];
9494     arith[3] = operands[1];
9496     if (val1 < val2)
9497       {
9498         arith[1] = ldm[1];
9499         arith[2] = ldm[2];
9500       }
9501     else
9502       {
9503         arith[1] = ldm[2];
9504         arith[2] = ldm[1];
9505       }
9507     ldm[0] = base_reg;
9508     if (val1 !=0 && val2 != 0)
9509       {
9510         if (val1 == 4 || val2 == 4)
9511           /* Other val must be 8, since we know they are adjacent and neither
9512              is zero.  */
9513           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9514         else
9515           {
9516             rtx ops[3];
9518             ldm[0] = ops[0] = operands[4];
9519             ops[1] = base_reg;
9520             ops[2] = GEN_INT (val1);
9521             output_add_immediate (ops);
9522             if (val1 < val2)
9523               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9524             else
9525               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9526           }
9527       }
9528     else if (val1 != 0)
9529       {
9530         if (val1 < val2)
9531           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9532         else
9533           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9534       }
9535     else
9536       {
9537         if (val1 < val2)
9538           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9539         else
9540           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9541       }
9542     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9543     return \"\";
9544   }"
9545   [(set_attr "length" "12")
9546    (set_attr "predicable" "yes")
9547    (set_attr "type" "load1")]
9550 ; This pattern is never tried by combine, so do it as a peephole
9552 (define_peephole2
9553   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9554         (match_operand:SI 1 "arm_general_register_operand" ""))
9555    (set (reg:CC CC_REGNUM)
9556         (compare:CC (match_dup 1) (const_int 0)))]
9557   "TARGET_ARM"
9558   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9559               (set (match_dup 0) (match_dup 1))])]
9560   ""
9563 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9564 ; reversed, check that the memory references aren't volatile.
9566 (define_peephole
9567   [(set (match_operand:SI 0 "s_register_operand" "=r")
9568         (match_operand:SI 4 "memory_operand" "m"))
9569    (set (match_operand:SI 1 "s_register_operand" "=r")
9570         (match_operand:SI 5 "memory_operand" "m"))
9571    (set (match_operand:SI 2 "s_register_operand" "=r")
9572         (match_operand:SI 6 "memory_operand" "m"))
9573    (set (match_operand:SI 3 "s_register_operand" "=r")
9574         (match_operand:SI 7 "memory_operand" "m"))]
9575   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9576   "*
9577   return emit_ldm_seq (operands, 4);
9578   "
9581 (define_peephole
9582   [(set (match_operand:SI 0 "s_register_operand" "=r")
9583         (match_operand:SI 3 "memory_operand" "m"))
9584    (set (match_operand:SI 1 "s_register_operand" "=r")
9585         (match_operand:SI 4 "memory_operand" "m"))
9586    (set (match_operand:SI 2 "s_register_operand" "=r")
9587         (match_operand:SI 5 "memory_operand" "m"))]
9588   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9589   "*
9590   return emit_ldm_seq (operands, 3);
9591   "
9594 (define_peephole
9595   [(set (match_operand:SI 0 "s_register_operand" "=r")
9596         (match_operand:SI 2 "memory_operand" "m"))
9597    (set (match_operand:SI 1 "s_register_operand" "=r")
9598         (match_operand:SI 3 "memory_operand" "m"))]
9599   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9600   "*
9601   return emit_ldm_seq (operands, 2);
9602   "
9605 (define_peephole
9606   [(set (match_operand:SI 4 "memory_operand" "=m")
9607         (match_operand:SI 0 "s_register_operand" "r"))
9608    (set (match_operand:SI 5 "memory_operand" "=m")
9609         (match_operand:SI 1 "s_register_operand" "r"))
9610    (set (match_operand:SI 6 "memory_operand" "=m")
9611         (match_operand:SI 2 "s_register_operand" "r"))
9612    (set (match_operand:SI 7 "memory_operand" "=m")
9613         (match_operand:SI 3 "s_register_operand" "r"))]
9614   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9615   "*
9616   return emit_stm_seq (operands, 4);
9617   "
9620 (define_peephole
9621   [(set (match_operand:SI 3 "memory_operand" "=m")
9622         (match_operand:SI 0 "s_register_operand" "r"))
9623    (set (match_operand:SI 4 "memory_operand" "=m")
9624         (match_operand:SI 1 "s_register_operand" "r"))
9625    (set (match_operand:SI 5 "memory_operand" "=m")
9626         (match_operand:SI 2 "s_register_operand" "r"))]
9627   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9628   "*
9629   return emit_stm_seq (operands, 3);
9630   "
9633 (define_peephole
9634   [(set (match_operand:SI 2 "memory_operand" "=m")
9635         (match_operand:SI 0 "s_register_operand" "r"))
9636    (set (match_operand:SI 3 "memory_operand" "=m")
9637         (match_operand:SI 1 "s_register_operand" "r"))]
9638   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9639   "*
9640   return emit_stm_seq (operands, 2);
9641   "
9644 (define_split
9645   [(set (match_operand:SI 0 "s_register_operand" "")
9646         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9647                        (const_int 0))
9648                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9649                          [(match_operand:SI 3 "s_register_operand" "")
9650                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9651    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9652   "TARGET_ARM"
9653   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9654    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9655                               (match_dup 5)))]
9656   ""
9659 ;; This split can be used because CC_Z mode implies that the following
9660 ;; branch will be an equality, or an unsigned inequality, so the sign
9661 ;; extension is not needed.
9663 (define_split
9664   [(set (reg:CC_Z CC_REGNUM)
9665         (compare:CC_Z
9666          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9667                     (const_int 24))
9668          (match_operand 1 "const_int_operand" "")))
9669    (clobber (match_scratch:SI 2 ""))]
9670   "TARGET_ARM
9671    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9672        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9673   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9674    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9675   "
9676   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9677   "
9680 (define_expand "prologue"
9681   [(clobber (const_int 0))]
9682   "TARGET_EITHER"
9683   "if (TARGET_ARM)
9684      arm_expand_prologue ();
9685    else
9686      thumb_expand_prologue ();
9687   DONE;
9688   "
9691 (define_expand "epilogue"
9692   [(clobber (const_int 0))]
9693   "TARGET_EITHER"
9694   "
9695   if (current_function_calls_eh_return)
9696     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9697   if (TARGET_THUMB)
9698     thumb_expand_epilogue ();
9699   else if (USE_RETURN_INSN (FALSE))
9700     {
9701       emit_jump_insn (gen_return ());
9702       DONE;
9703     }
9704   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9705         gen_rtvec (1,
9706                 gen_rtx_RETURN (VOIDmode)),
9707         VUNSPEC_EPILOGUE));
9708   DONE;
9709   "
9712 ;; Note - although unspec_volatile's USE all hard registers,
9713 ;; USEs are ignored after relaod has completed.  Thus we need
9714 ;; to add an unspec of the link register to ensure that flow
9715 ;; does not think that it is unused by the sibcall branch that
9716 ;; will replace the standard function epilogue.
9717 (define_insn "sibcall_epilogue"
9718   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9719               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9720   "TARGET_ARM"
9721   "*
9722   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9723     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9724   return arm_output_epilogue (next_nonnote_insn (insn));
9725   "
9726 ;; Length is absolute worst case
9727   [(set_attr "length" "44")
9728    (set_attr "type" "block")
9729    ;; We don't clobber the conditions, but the potential length of this
9730    ;; operation is sufficient to make conditionalizing the sequence 
9731    ;; unlikely to be profitable.
9732    (set_attr "conds" "clob")]
9735 (define_insn "*epilogue_insns"
9736   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9737   "TARGET_EITHER"
9738   "*
9739   if (TARGET_ARM)
9740     return arm_output_epilogue (NULL);
9741   else /* TARGET_THUMB */
9742     return thumb_unexpanded_epilogue ();
9743   "
9744   ; Length is absolute worst case
9745   [(set_attr "length" "44")
9746    (set_attr "type" "block")
9747    ;; We don't clobber the conditions, but the potential length of this
9748    ;; operation is sufficient to make conditionalizing the sequence 
9749    ;; unlikely to be profitable.
9750    (set_attr "conds" "clob")]
9753 (define_expand "eh_epilogue"
9754   [(use (match_operand:SI 0 "register_operand" ""))
9755    (use (match_operand:SI 1 "register_operand" ""))
9756    (use (match_operand:SI 2 "register_operand" ""))]
9757   "TARGET_EITHER"
9758   "
9759   {
9760     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9761     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9762       {
9763         rtx ra = gen_rtx_REG (Pmode, 2);
9765         emit_move_insn (ra, operands[2]);
9766         operands[2] = ra;
9767       }
9768     /* This is a hack -- we may have crystalized the function type too
9769        early.  */
9770     cfun->machine->func_type = 0;
9771   }"
9774 ;; This split is only used during output to reduce the number of patterns
9775 ;; that need assembler instructions adding to them.  We allowed the setting
9776 ;; of the conditions to be implicit during rtl generation so that
9777 ;; the conditional compare patterns would work.  However this conflicts to
9778 ;; some extent with the conditional data operations, so we have to split them
9779 ;; up again here.
9781 (define_split
9782   [(set (match_operand:SI 0 "s_register_operand" "")
9783         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9784                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9785                          (match_dup 0)
9786                          (match_operand 4 "" "")))
9787    (clobber (reg:CC CC_REGNUM))]
9788   "TARGET_ARM && reload_completed"
9789   [(set (match_dup 5) (match_dup 6))
9790    (cond_exec (match_dup 7)
9791               (set (match_dup 0) (match_dup 4)))]
9792   "
9793   {
9794     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9795                                              operands[2], operands[3]);
9796     enum rtx_code rc = GET_CODE (operands[1]);
9798     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9799     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9800     if (mode == CCFPmode || mode == CCFPEmode)
9801       rc = reverse_condition_maybe_unordered (rc);
9802     else
9803       rc = reverse_condition (rc);
9805     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9806   }"
9809 (define_split
9810   [(set (match_operand:SI 0 "s_register_operand" "")
9811         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9812                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9813                          (match_operand 4 "" "")
9814                          (match_dup 0)))
9815    (clobber (reg:CC CC_REGNUM))]
9816   "TARGET_ARM && reload_completed"
9817   [(set (match_dup 5) (match_dup 6))
9818    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9819               (set (match_dup 0) (match_dup 4)))]
9820   "
9821   {
9822     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9823                                              operands[2], operands[3]);
9825     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9826     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9827   }"
9830 (define_split
9831   [(set (match_operand:SI 0 "s_register_operand" "")
9832         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9833                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9834                          (match_operand 4 "" "")
9835                          (match_operand 5 "" "")))
9836    (clobber (reg:CC CC_REGNUM))]
9837   "TARGET_ARM && reload_completed"
9838   [(set (match_dup 6) (match_dup 7))
9839    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9840               (set (match_dup 0) (match_dup 4)))
9841    (cond_exec (match_dup 8)
9842               (set (match_dup 0) (match_dup 5)))]
9843   "
9844   {
9845     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9846                                              operands[2], operands[3]);
9847     enum rtx_code rc = GET_CODE (operands[1]);
9849     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9850     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9851     if (mode == CCFPmode || mode == CCFPEmode)
9852       rc = reverse_condition_maybe_unordered (rc);
9853     else
9854       rc = reverse_condition (rc);
9856     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9857   }"
9860 (define_split
9861   [(set (match_operand:SI 0 "s_register_operand" "")
9862         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9863                           [(match_operand:SI 2 "s_register_operand" "")
9864                            (match_operand:SI 3 "arm_add_operand" "")])
9865                          (match_operand:SI 4 "arm_rhs_operand" "")
9866                          (not:SI
9867                           (match_operand:SI 5 "s_register_operand" ""))))
9868    (clobber (reg:CC CC_REGNUM))]
9869   "TARGET_ARM && reload_completed"
9870   [(set (match_dup 6) (match_dup 7))
9871    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9872               (set (match_dup 0) (match_dup 4)))
9873    (cond_exec (match_dup 8)
9874               (set (match_dup 0) (not:SI (match_dup 5))))]
9875   "
9876   {
9877     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9878                                              operands[2], operands[3]);
9879     enum rtx_code rc = GET_CODE (operands[1]);
9881     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9882     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9883     if (mode == CCFPmode || mode == CCFPEmode)
9884       rc = reverse_condition_maybe_unordered (rc);
9885     else
9886       rc = reverse_condition (rc);
9888     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9889   }"
9892 (define_insn "*cond_move_not"
9893   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9894         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9895                           [(match_operand 3 "cc_register" "") (const_int 0)])
9896                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9897                          (not:SI
9898                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9899   "TARGET_ARM"
9900   "@
9901    mvn%D4\\t%0, %2
9902    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9903   [(set_attr "conds" "use")
9904    (set_attr "length" "4,8")]
9907 ;; The next two patterns occur when an AND operation is followed by a
9908 ;; scc insn sequence 
9910 (define_insn "*sign_extract_onebit"
9911   [(set (match_operand:SI 0 "s_register_operand" "=r")
9912         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9913                          (const_int 1)
9914                          (match_operand:SI 2 "const_int_operand" "n")))
9915     (clobber (reg:CC CC_REGNUM))]
9916   "TARGET_ARM"
9917   "*
9918     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9919     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9920     return \"mvnne\\t%0, #0\";
9921   "
9922   [(set_attr "conds" "clob")
9923    (set_attr "length" "8")]
9926 (define_insn "*not_signextract_onebit"
9927   [(set (match_operand:SI 0 "s_register_operand" "=r")
9928         (not:SI
9929          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9930                           (const_int 1)
9931                           (match_operand:SI 2 "const_int_operand" "n"))))
9932    (clobber (reg:CC CC_REGNUM))]
9933   "TARGET_ARM"
9934   "*
9935     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9936     output_asm_insn (\"tst\\t%1, %2\", operands);
9937     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9938     return \"movne\\t%0, #0\";
9939   "
9940   [(set_attr "conds" "clob")
9941    (set_attr "length" "12")]
9944 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9945 ;; expressions.  For simplicity, the first register is also in the unspec
9946 ;; part.
9947 (define_insn "*push_multi"
9948   [(match_parallel 2 "multi_register_push"
9949     [(set (match_operand:BLK 0 "memory_operand" "=m")
9950           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9951                       UNSPEC_PUSH_MULT))])]
9952   "TARGET_ARM"
9953   "*
9954   {
9955     int num_saves = XVECLEN (operands[2], 0);
9956      
9957     /* For the StrongARM at least it is faster to
9958        use STR to store only a single register.  */
9959     if (num_saves == 1)
9960       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9961     else
9962       {
9963         int i;
9964         char pattern[100];
9966         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9968         for (i = 1; i < num_saves; i++)
9969           {
9970             strcat (pattern, \", %|\");
9971             strcat (pattern,
9972                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9973           }
9975         strcat (pattern, \"}\");
9976         output_asm_insn (pattern, operands);
9977       }
9979     return \"\";
9980   }"
9981   [(set_attr "type" "store4")]
9984 (define_insn "stack_tie"
9985   [(set (mem:BLK (scratch))
9986         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9987                      (match_operand:SI 1 "s_register_operand" "r")]
9988                     UNSPEC_PRLG_STK))]
9989   ""
9990   ""
9991   [(set_attr "length" "0")]
9994 ;; Similarly for the floating point registers
9995 (define_insn "*push_fp_multi"
9996   [(match_parallel 2 "multi_register_push"
9997     [(set (match_operand:BLK 0 "memory_operand" "=m")
9998           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9999                       UNSPEC_PUSH_MULT))])]
10000   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10001   "*
10002   {
10003     char pattern[100];
10005     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10006     output_asm_insn (pattern, operands);
10007     return \"\";
10008   }"
10009   [(set_attr "type" "f_store")]
10012 ;; Special patterns for dealing with the constant pool
10014 (define_insn "align_4"
10015   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10016   "TARGET_EITHER"
10017   "*
10018   assemble_align (32);
10019   return \"\";
10020   "
10023 (define_insn "align_8"
10024   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10025   "TARGET_EITHER"
10026   "*
10027   assemble_align (64);
10028   return \"\";
10029   "
10032 (define_insn "consttable_end"
10033   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10034   "TARGET_EITHER"
10035   "*
10036   making_const_table = FALSE;
10037   return \"\";
10038   "
10041 (define_insn "consttable_1"
10042   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10043   "TARGET_THUMB"
10044   "*
10045   making_const_table = TRUE;
10046   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10047   assemble_zeros (3);
10048   return \"\";
10049   "
10050   [(set_attr "length" "4")]
10053 (define_insn "consttable_2"
10054   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10055   "TARGET_THUMB"
10056   "*
10057   making_const_table = TRUE;
10058   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10059   assemble_zeros (2);
10060   return \"\";
10061   "
10062   [(set_attr "length" "4")]
10065 (define_insn "consttable_4"
10066   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10067   "TARGET_EITHER"
10068   "*
10069   {
10070     making_const_table = TRUE;
10071     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10072       {
10073       case MODE_FLOAT:
10074       {
10075         REAL_VALUE_TYPE r;
10076         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10077         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10078         break;
10079       }
10080       default:
10081         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10082         break;
10083       }
10084     return \"\";
10085   }"
10086   [(set_attr "length" "4")]
10089 (define_insn "consttable_8"
10090   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10091   "TARGET_EITHER"
10092   "*
10093   {
10094     making_const_table = TRUE;
10095     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10096       {
10097        case MODE_FLOAT:
10098         {
10099           REAL_VALUE_TYPE r;
10100           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10101           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10102           break;
10103         }
10104       default:
10105         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10106         break;
10107       }
10108     return \"\";
10109   }"
10110   [(set_attr "length" "8")]
10113 ;; Miscellaneous Thumb patterns
10115 (define_expand "tablejump"
10116   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10117               (use (label_ref (match_operand 1 "" "")))])]
10118   "TARGET_THUMB"
10119   "
10120   if (flag_pic)
10121     {
10122       /* Hopefully, CSE will eliminate this copy.  */
10123       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10124       rtx reg2 = gen_reg_rtx (SImode);
10126       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10127       operands[0] = reg2;
10128     }
10129   "
10132 ;; NB never uses BX.
10133 (define_insn "*thumb_tablejump"
10134   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10135    (use (label_ref (match_operand 1 "" "")))]
10136   "TARGET_THUMB"
10137   "mov\\t%|pc, %0"
10138   [(set_attr "length" "2")]
10141 ;; V5 Instructions,
10143 (define_insn "clzsi2"
10144   [(set (match_operand:SI 0 "s_register_operand" "=r")
10145         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10146   "TARGET_ARM && arm_arch5"
10147   "clz%?\\t%0, %1"
10148   [(set_attr "predicable" "yes")])
10150 (define_expand "ffssi2"
10151   [(set (match_operand:SI 0 "s_register_operand" "")
10152         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10153   "TARGET_ARM && arm_arch5"
10154   "
10155   {
10156     rtx t1, t2, t3;
10158     t1 = gen_reg_rtx (SImode);
10159     t2 = gen_reg_rtx (SImode);
10160     t3 = gen_reg_rtx (SImode);
10162     emit_insn (gen_negsi2 (t1, operands[1]));
10163     emit_insn (gen_andsi3 (t2, operands[1], t1));
10164     emit_insn (gen_clzsi2 (t3, t2));
10165     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10166     DONE;
10167   }"
10170 (define_expand "ctzsi2"
10171   [(set (match_operand:SI 0 "s_register_operand" "")
10172         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10173   "TARGET_ARM && arm_arch5"
10174   "
10175   {
10176     rtx t1, t2, t3;
10178     t1 = gen_reg_rtx (SImode);
10179     t2 = gen_reg_rtx (SImode);
10180     t3 = gen_reg_rtx (SImode);
10182     emit_insn (gen_negsi2 (t1, operands[1]));
10183     emit_insn (gen_andsi3 (t2, operands[1], t1));
10184     emit_insn (gen_clzsi2 (t3, t2));
10185     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10186     DONE;
10187   }"
10190 ;; V5E instructions.
10192 (define_insn "prefetch"
10193   [(prefetch (match_operand:SI 0 "address_operand" "p")
10194              (match_operand:SI 1 "" "")
10195              (match_operand:SI 2 "" ""))]
10196   "TARGET_ARM && arm_arch5e"
10197   "pld\\t%a0")
10199 ;; General predication pattern
10201 (define_cond_exec
10202   [(match_operator 0 "arm_comparison_operator"
10203     [(match_operand 1 "cc_register" "")
10204      (const_int 0)])]
10205   "TARGET_ARM"
10206   ""
10209 (define_insn "prologue_use"
10210   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10211   ""
10212   "%@ %0 needed for prologue"
10216 ;; Patterns for exception handling
10218 (define_expand "eh_return"
10219   [(use (match_operand 0 "general_operand" ""))]
10220   "TARGET_EITHER"
10221   "
10222   {
10223     if (TARGET_ARM)
10224       emit_insn (gen_arm_eh_return (operands[0]));
10225     else
10226       emit_insn (gen_thumb_eh_return (operands[0]));
10227     DONE;
10228   }"
10230                                    
10231 ;; We can't expand this before we know where the link register is stored.
10232 (define_insn_and_split "arm_eh_return"
10233   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10234                     VUNSPEC_EH_RETURN)
10235    (clobber (match_scratch:SI 1 "=&r"))]
10236   "TARGET_ARM"
10237   "#"
10238   "&& reload_completed"
10239   [(const_int 0)]
10240   "
10241   {
10242     arm_set_return_address (operands[0], operands[1]);
10243     DONE;
10244   }"
10247 (define_insn_and_split "thumb_eh_return"
10248   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10249                     VUNSPEC_EH_RETURN)
10250    (clobber (match_scratch:SI 1 "=&l"))]
10251   "TARGET_THUMB"
10252   "#"
10253   "&& reload_completed"
10254   [(const_int 0)]
10255   "
10256   {
10257     thumb_set_return_address (operands[0], operands[1]);
10258     DONE;
10259   }"
10263 ;; TLS support
10265 (define_insn "load_tp_hard"
10266   [(set (match_operand:SI 0 "register_operand" "=r")
10267         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10268   "TARGET_HARD_TP"
10269   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10270   [(set_attr "predicable" "yes")]
10273 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
10274 (define_insn "load_tp_soft"
10275   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10276    (clobber (reg:SI LR_REGNUM))
10277    (clobber (reg:SI IP_REGNUM))
10278    (clobber (reg:CC CC_REGNUM))]
10279   "TARGET_SOFT_TP"
10280   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10281   [(set_attr "conds" "clob")]
10284 ;; Load the FPA co-processor patterns
10285 (include "fpa.md")
10286 ;; Load the Maverick co-processor patterns
10287 (include "cirrus.md")
10288 ;; Load the Intel Wireless Multimedia Extension patterns
10289 (include "iwmmxt.md")
10290 ;; Load the VFP co-processor patterns
10291 (include "vfp.md")