PR target/592
[official-gcc.git] / gcc / config / arm / arm.md
blob239961ad554c1ed32106089dd7f1d6592edf5427
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_insn "smaxsi3"
2477   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2478         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2479                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2480    (clobber (reg:CC CC_REGNUM))]
2481   "TARGET_ARM"
2482   "@
2483    cmp\\t%1, %2\;movlt\\t%0, %2
2484    cmp\\t%1, %2\;movge\\t%0, %1
2485    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2486   [(set_attr "conds" "clob")
2487    (set_attr "length" "8,8,12")]
2490 (define_insn "sminsi3"
2491   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2492         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2493                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2494    (clobber (reg:CC CC_REGNUM))]
2495   "TARGET_ARM"
2496   "@
2497    cmp\\t%1, %2\;movge\\t%0, %2
2498    cmp\\t%1, %2\;movlt\\t%0, %1
2499    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2500   [(set_attr "conds" "clob")
2501    (set_attr "length" "8,8,12")]
2504 (define_insn "umaxsi3"
2505   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2506         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2507                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2508    (clobber (reg:CC CC_REGNUM))]
2509   "TARGET_ARM"
2510   "@
2511    cmp\\t%1, %2\;movcc\\t%0, %2
2512    cmp\\t%1, %2\;movcs\\t%0, %1
2513    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2514   [(set_attr "conds" "clob")
2515    (set_attr "length" "8,8,12")]
2518 (define_insn "uminsi3"
2519   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2520         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2521                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2522    (clobber (reg:CC CC_REGNUM))]
2523   "TARGET_ARM"
2524   "@
2525    cmp\\t%1, %2\;movcs\\t%0, %2
2526    cmp\\t%1, %2\;movcc\\t%0, %1
2527    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2528   [(set_attr "conds" "clob")
2529    (set_attr "length" "8,8,12")]
2532 (define_insn "*store_minmaxsi"
2533   [(set (match_operand:SI 0 "memory_operand" "=m")
2534         (match_operator:SI 3 "minmax_operator"
2535          [(match_operand:SI 1 "s_register_operand" "r")
2536           (match_operand:SI 2 "s_register_operand" "r")]))
2537    (clobber (reg:CC CC_REGNUM))]
2538   "TARGET_ARM"
2539   "*
2540   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2541                                 operands[1], operands[2]);
2542   output_asm_insn (\"cmp\\t%1, %2\", operands);
2543   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2544   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2545   return \"\";
2546   "
2547   [(set_attr "conds" "clob")
2548    (set_attr "length" "12")
2549    (set_attr "type" "store1")]
2552 ; Reject the frame pointer in operand[1], since reloading this after
2553 ; it has been eliminated can cause carnage.
2554 (define_insn "*minmax_arithsi"
2555   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2556         (match_operator:SI 4 "shiftable_operator"
2557          [(match_operator:SI 5 "minmax_operator"
2558            [(match_operand:SI 2 "s_register_operand" "r,r")
2559             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2560           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2561    (clobber (reg:CC CC_REGNUM))]
2562   "TARGET_ARM && !arm_eliminable_register (operands[1])"
2563   "*
2564   {
2565     enum rtx_code code = GET_CODE (operands[4]);
2567     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2568                                   operands[2], operands[3]);
2569     output_asm_insn (\"cmp\\t%2, %3\", operands);
2570     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2571     if (which_alternative != 0 || operands[3] != const0_rtx
2572         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2573       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2574     return \"\";
2575   }"
2576   [(set_attr "conds" "clob")
2577    (set_attr "length" "12")]
2581 ;; Shift and rotation insns
2583 (define_expand "ashldi3"
2584   [(set (match_operand:DI            0 "s_register_operand" "")
2585         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2586                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2587   "TARGET_ARM"
2588   "
2589   if (GET_CODE (operands[2]) == CONST_INT)
2590     {
2591       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2592         {
2593           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2594           DONE;
2595         }
2596         /* Ideally we shouldn't fail here if we could know that operands[1] 
2597            ends up already living in an iwmmxt register. Otherwise it's
2598            cheaper to have the alternate code being generated than moving
2599            values to iwmmxt regs and back.  */
2600         FAIL;
2601     }
2602   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2603     FAIL;
2604   "
2607 (define_insn "arm_ashldi3_1bit"
2608   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2609         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2610                    (const_int 1)))
2611    (clobber (reg:CC CC_REGNUM))]
2612   "TARGET_ARM"
2613   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2614   [(set_attr "conds" "clob")
2615    (set_attr "length" "8")]
2618 (define_expand "ashlsi3"
2619   [(set (match_operand:SI            0 "s_register_operand" "")
2620         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2621                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2622   "TARGET_EITHER"
2623   "
2624   if (GET_CODE (operands[2]) == CONST_INT
2625       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2626     {
2627       emit_insn (gen_movsi (operands[0], const0_rtx));
2628       DONE;
2629     }
2630   "
2633 (define_insn "*thumb_ashlsi3"
2634   [(set (match_operand:SI            0 "register_operand" "=l,l")
2635         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2636                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2637   "TARGET_THUMB"
2638   "lsl\\t%0, %1, %2"
2639   [(set_attr "length" "2")]
2642 (define_expand "ashrdi3"
2643   [(set (match_operand:DI              0 "s_register_operand" "")
2644         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2645                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2646   "TARGET_ARM"
2647   "
2648   if (GET_CODE (operands[2]) == CONST_INT)
2649     {
2650       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2651         {
2652           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2653           DONE;
2654         }
2655         /* Ideally we shouldn't fail here if we could know that operands[1] 
2656            ends up already living in an iwmmxt register. Otherwise it's
2657            cheaper to have the alternate code being generated than moving
2658            values to iwmmxt regs and back.  */
2659         FAIL;
2660     }
2661   else if (!TARGET_REALLY_IWMMXT)
2662     FAIL;
2663   "
2666 (define_insn "arm_ashrdi3_1bit"
2667   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2668         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2669                      (const_int 1)))
2670    (clobber (reg:CC CC_REGNUM))]
2671   "TARGET_ARM"
2672   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2673   [(set_attr "conds" "clob")
2674    (set_attr "length" "8")]
2677 (define_expand "ashrsi3"
2678   [(set (match_operand:SI              0 "s_register_operand" "")
2679         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2680                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2681   "TARGET_EITHER"
2682   "
2683   if (GET_CODE (operands[2]) == CONST_INT
2684       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2685     operands[2] = GEN_INT (31);
2686   "
2689 (define_insn "*thumb_ashrsi3"
2690   [(set (match_operand:SI              0 "register_operand" "=l,l")
2691         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2692                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2693   "TARGET_THUMB"
2694   "asr\\t%0, %1, %2"
2695   [(set_attr "length" "2")]
2698 (define_expand "lshrdi3"
2699   [(set (match_operand:DI              0 "s_register_operand" "")
2700         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2701                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2702   "TARGET_ARM"
2703   "
2704   if (GET_CODE (operands[2]) == CONST_INT)
2705     {
2706       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2707         {
2708           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2709           DONE;
2710         }
2711         /* Ideally we shouldn't fail here if we could know that operands[1] 
2712            ends up already living in an iwmmxt register. Otherwise it's
2713            cheaper to have the alternate code being generated than moving
2714            values to iwmmxt regs and back.  */
2715         FAIL;
2716     }
2717   else if (!TARGET_REALLY_IWMMXT)
2718     FAIL;
2719   "
2722 (define_insn "arm_lshrdi3_1bit"
2723   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2724         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2725                      (const_int 1)))
2726    (clobber (reg:CC CC_REGNUM))]
2727   "TARGET_ARM"
2728   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2729   [(set_attr "conds" "clob")
2730    (set_attr "length" "8")]
2733 (define_expand "lshrsi3"
2734   [(set (match_operand:SI              0 "s_register_operand" "")
2735         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2736                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2737   "TARGET_EITHER"
2738   "
2739   if (GET_CODE (operands[2]) == CONST_INT
2740       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2741     {
2742       emit_insn (gen_movsi (operands[0], const0_rtx));
2743       DONE;
2744     }
2745   "
2748 (define_insn "*thumb_lshrsi3"
2749   [(set (match_operand:SI              0 "register_operand" "=l,l")
2750         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2751                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2752   "TARGET_THUMB"
2753   "lsr\\t%0, %1, %2"
2754   [(set_attr "length" "2")]
2757 (define_expand "rotlsi3"
2758   [(set (match_operand:SI              0 "s_register_operand" "")
2759         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2760                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2761   "TARGET_ARM"
2762   "
2763   if (GET_CODE (operands[2]) == CONST_INT)
2764     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2765   else
2766     {
2767       rtx reg = gen_reg_rtx (SImode);
2768       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2769       operands[2] = reg;
2770     }
2771   "
2774 (define_expand "rotrsi3"
2775   [(set (match_operand:SI              0 "s_register_operand" "")
2776         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2777                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2778   "TARGET_EITHER"
2779   "
2780   if (TARGET_ARM)
2781     {
2782       if (GET_CODE (operands[2]) == CONST_INT
2783           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2784         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2785     }
2786   else /* TARGET_THUMB */
2787     {
2788       if (GET_CODE (operands [2]) == CONST_INT)
2789         operands [2] = force_reg (SImode, operands[2]);
2790     }
2791   "
2794 (define_insn "*thumb_rotrsi3"
2795   [(set (match_operand:SI              0 "register_operand" "=l")
2796         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2797                      (match_operand:SI 2 "register_operand" "l")))]
2798   "TARGET_THUMB"
2799   "ror\\t%0, %0, %2"
2800   [(set_attr "length" "2")]
2803 (define_insn "*arm_shiftsi3"
2804   [(set (match_operand:SI   0 "s_register_operand" "=r")
2805         (match_operator:SI  3 "shift_operator"
2806          [(match_operand:SI 1 "s_register_operand"  "r")
2807           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2808   "TARGET_ARM"
2809   "mov%?\\t%0, %1%S3"
2810   [(set_attr "predicable" "yes")
2811    (set_attr "shift" "1")
2812    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2813                       (const_string "alu_shift")
2814                       (const_string "alu_shift_reg")))]
2817 (define_insn "*shiftsi3_compare0"
2818   [(set (reg:CC_NOOV CC_REGNUM)
2819         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2820                           [(match_operand:SI 1 "s_register_operand" "r")
2821                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2822                          (const_int 0)))
2823    (set (match_operand:SI 0 "s_register_operand" "=r")
2824         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2825   "TARGET_ARM"
2826   "mov%?s\\t%0, %1%S3"
2827   [(set_attr "conds" "set")
2828    (set_attr "shift" "1")
2829    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2830                       (const_string "alu_shift")
2831                       (const_string "alu_shift_reg")))]
2834 (define_insn "*shiftsi3_compare0_scratch"
2835   [(set (reg:CC_NOOV CC_REGNUM)
2836         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2837                           [(match_operand:SI 1 "s_register_operand" "r")
2838                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2839                          (const_int 0)))
2840    (clobber (match_scratch:SI 0 "=r"))]
2841   "TARGET_ARM"
2842   "mov%?s\\t%0, %1%S3"
2843   [(set_attr "conds" "set")
2844    (set_attr "shift" "1")]
2847 (define_insn "*notsi_shiftsi"
2848   [(set (match_operand:SI 0 "s_register_operand" "=r")
2849         (not:SI (match_operator:SI 3 "shift_operator"
2850                  [(match_operand:SI 1 "s_register_operand" "r")
2851                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2852   "TARGET_ARM"
2853   "mvn%?\\t%0, %1%S3"
2854   [(set_attr "predicable" "yes")
2855    (set_attr "shift" "1")
2856    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2857                       (const_string "alu_shift")
2858                       (const_string "alu_shift_reg")))]
2861 (define_insn "*notsi_shiftsi_compare0"
2862   [(set (reg:CC_NOOV CC_REGNUM)
2863         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2864                           [(match_operand:SI 1 "s_register_operand" "r")
2865                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2866                          (const_int 0)))
2867    (set (match_operand:SI 0 "s_register_operand" "=r")
2868         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2869   "TARGET_ARM"
2870   "mvn%?s\\t%0, %1%S3"
2871   [(set_attr "conds" "set")
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 "*not_shiftsi_compare0_scratch"
2879   [(set (reg:CC_NOOV CC_REGNUM)
2880         (compare:CC_NOOV (not:SI (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    (clobber (match_scratch:SI 0 "=r"))]
2885   "TARGET_ARM"
2886   "mvn%?s\\t%0, %1%S3"
2887   [(set_attr "conds" "set")
2888    (set_attr "shift" "1")
2889    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2890                       (const_string "alu_shift")
2891                       (const_string "alu_shift_reg")))]
2894 ;; We don't really have extzv, but defining this using shifts helps
2895 ;; to reduce register pressure later on.
2897 (define_expand "extzv"
2898   [(set (match_dup 4)
2899         (ashift:SI (match_operand:SI   1 "register_operand" "")
2900                    (match_operand:SI   2 "const_int_operand" "")))
2901    (set (match_operand:SI              0 "register_operand" "")
2902         (lshiftrt:SI (match_dup 4)
2903                      (match_operand:SI 3 "const_int_operand" "")))]
2904   "TARGET_THUMB"
2905   "
2906   {
2907     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2908     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2909     
2910     operands[3] = GEN_INT (rshift);
2911     
2912     if (lshift == 0)
2913       {
2914         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2915         DONE;
2916       }
2917       
2918     operands[2] = GEN_INT (lshift);
2919     operands[4] = gen_reg_rtx (SImode);
2920   }"
2924 ;; Unary arithmetic insns
2926 (define_expand "negdi2"
2927  [(parallel
2928    [(set (match_operand:DI          0 "s_register_operand" "")
2929           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2930     (clobber (reg:CC CC_REGNUM))])]
2931   "TARGET_EITHER"
2932   "
2933   if (TARGET_THUMB)
2934     {
2935       if (GET_CODE (operands[1]) != REG)
2936         operands[1] = force_reg (SImode, operands[1]);
2937      }
2938   "
2941 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2942 ;; The second alternative is to allow the common case of a *full* overlap.
2943 (define_insn "*arm_negdi2"
2944   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2945         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2946    (clobber (reg:CC CC_REGNUM))]
2947   "TARGET_ARM"
2948   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2949   [(set_attr "conds" "clob")
2950    (set_attr "length" "8")]
2953 (define_insn "*thumb_negdi2"
2954   [(set (match_operand:DI         0 "register_operand" "=&l")
2955         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2956    (clobber (reg:CC CC_REGNUM))]
2957   "TARGET_THUMB"
2958   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2959   [(set_attr "length" "6")]
2962 (define_expand "negsi2"
2963   [(set (match_operand:SI         0 "s_register_operand" "")
2964         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2965   "TARGET_EITHER"
2966   ""
2969 (define_insn "*arm_negsi2"
2970   [(set (match_operand:SI         0 "s_register_operand" "=r")
2971         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2972   "TARGET_ARM"
2973   "rsb%?\\t%0, %1, #0"
2974   [(set_attr "predicable" "yes")]
2977 (define_insn "*thumb_negsi2"
2978   [(set (match_operand:SI         0 "register_operand" "=l")
2979         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2980   "TARGET_THUMB"
2981   "neg\\t%0, %1"
2982   [(set_attr "length" "2")]
2985 (define_expand "negsf2"
2986   [(set (match_operand:SF         0 "s_register_operand" "")
2987         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2988   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2989   ""
2992 (define_expand "negdf2"
2993   [(set (match_operand:DF         0 "s_register_operand" "")
2994         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2995   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2996   "")
2998 ;; abssi2 doesn't really clobber the condition codes if a different register
2999 ;; is being set.  To keep things simple, assume during rtl manipulations that
3000 ;; it does, but tell the final scan operator the truth.  Similarly for
3001 ;; (neg (abs...))
3003 (define_expand "abssi2"
3004   [(parallel
3005     [(set (match_operand:SI         0 "s_register_operand" "")
3006           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3007      (clobber (reg:CC CC_REGNUM))])]
3008   "TARGET_ARM"
3009   "")
3011 (define_insn "*arm_abssi2"
3012   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3013         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3014    (clobber (reg:CC CC_REGNUM))]
3015   "TARGET_ARM"
3016   "@
3017    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3018    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3019   [(set_attr "conds" "clob,*")
3020    (set_attr "shift" "1")
3021    ;; predicable can't be set based on the variant, so left as no
3022    (set_attr "length" "8")]
3025 (define_insn "*neg_abssi2"
3026   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3027         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3028    (clobber (reg:CC CC_REGNUM))]
3029   "TARGET_ARM"
3030   "@
3031    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3032    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3033   [(set_attr "conds" "clob,*")
3034    (set_attr "shift" "1")
3035    ;; predicable can't be set based on the variant, so left as no
3036    (set_attr "length" "8")]
3039 (define_expand "abssf2"
3040   [(set (match_operand:SF         0 "s_register_operand" "")
3041         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3042   "TARGET_ARM && TARGET_HARD_FLOAT"
3043   "")
3045 (define_expand "absdf2"
3046   [(set (match_operand:DF         0 "s_register_operand" "")
3047         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3048   "TARGET_ARM && TARGET_HARD_FLOAT"
3049   "")
3051 (define_expand "sqrtsf2"
3052   [(set (match_operand:SF 0 "s_register_operand" "")
3053         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3054   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3055   "")
3057 (define_expand "sqrtdf2"
3058   [(set (match_operand:DF 0 "s_register_operand" "")
3059         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3060   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3061   "")
3063 (define_insn_and_split "one_cmpldi2"
3064   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3065         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3066   "TARGET_ARM"
3067   "#"
3068   "TARGET_ARM && reload_completed"
3069   [(set (match_dup 0) (not:SI (match_dup 1)))
3070    (set (match_dup 2) (not:SI (match_dup 3)))]
3071   "
3072   {
3073     operands[2] = gen_highpart (SImode, operands[0]);
3074     operands[0] = gen_lowpart (SImode, operands[0]);
3075     operands[3] = gen_highpart (SImode, operands[1]);
3076     operands[1] = gen_lowpart (SImode, operands[1]);
3077   }"
3078   [(set_attr "length" "8")
3079    (set_attr "predicable" "yes")]
3082 (define_expand "one_cmplsi2"
3083   [(set (match_operand:SI         0 "s_register_operand" "")
3084         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3085   "TARGET_EITHER"
3086   ""
3089 (define_insn "*arm_one_cmplsi2"
3090   [(set (match_operand:SI         0 "s_register_operand" "=r")
3091         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3092   "TARGET_ARM"
3093   "mvn%?\\t%0, %1"
3094   [(set_attr "predicable" "yes")]
3097 (define_insn "*thumb_one_cmplsi2"
3098   [(set (match_operand:SI         0 "register_operand" "=l")
3099         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3100   "TARGET_THUMB"
3101   "mvn\\t%0, %1"
3102   [(set_attr "length" "2")]
3105 (define_insn "*notsi_compare0"
3106   [(set (reg:CC_NOOV CC_REGNUM)
3107         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3108                          (const_int 0)))
3109    (set (match_operand:SI 0 "s_register_operand" "=r")
3110         (not:SI (match_dup 1)))]
3111   "TARGET_ARM"
3112   "mvn%?s\\t%0, %1"
3113   [(set_attr "conds" "set")]
3116 (define_insn "*notsi_compare0_scratch"
3117   [(set (reg:CC_NOOV CC_REGNUM)
3118         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3119                          (const_int 0)))
3120    (clobber (match_scratch:SI 0 "=r"))]
3121   "TARGET_ARM"
3122   "mvn%?s\\t%0, %1"
3123   [(set_attr "conds" "set")]
3126 ;; Fixed <--> Floating conversion insns
3128 (define_expand "floatsisf2"
3129   [(set (match_operand:SF           0 "s_register_operand" "")
3130         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3131   "TARGET_ARM && TARGET_HARD_FLOAT"
3132   "
3133   if (TARGET_MAVERICK)
3134     {
3135       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3136       DONE;
3137     }
3140 (define_expand "floatsidf2"
3141   [(set (match_operand:DF           0 "s_register_operand" "")
3142         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3143   "TARGET_ARM && TARGET_HARD_FLOAT"
3144   "
3145   if (TARGET_MAVERICK)
3146     {
3147       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3148       DONE;
3149     }
3152 (define_expand "fix_truncsfsi2"
3153   [(set (match_operand:SI         0 "s_register_operand" "")
3154         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3155   "TARGET_ARM && TARGET_HARD_FLOAT"
3156   "
3157   if (TARGET_MAVERICK)
3158     {
3159       if (!cirrus_fp_register (operands[0], SImode))
3160         operands[0] = force_reg (SImode, operands[0]);
3161       if (!cirrus_fp_register (operands[1], SFmode))
3162         operands[1] = force_reg (SFmode, operands[0]);
3163       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3164       DONE;
3165     }
3168 (define_expand "fix_truncdfsi2"
3169   [(set (match_operand:SI         0 "s_register_operand" "")
3170         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3171   "TARGET_ARM && TARGET_HARD_FLOAT"
3172   "
3173   if (TARGET_MAVERICK)
3174     {
3175       if (!cirrus_fp_register (operands[1], DFmode))
3176         operands[1] = force_reg (DFmode, operands[0]);
3177       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3178       DONE;
3179     }
3182 ;; Truncation insns
3184 (define_expand "truncdfsf2"
3185   [(set (match_operand:SF  0 "s_register_operand" "")
3186         (float_truncate:SF
3187          (match_operand:DF 1 "s_register_operand" "")))]
3188   "TARGET_ARM && TARGET_HARD_FLOAT"
3189   ""
3192 ;; Zero and sign extension instructions.
3194 (define_insn "zero_extendsidi2"
3195   [(set (match_operand:DI 0 "s_register_operand" "=r")
3196         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3197   "TARGET_ARM"
3198   "*
3199     if (REGNO (operands[1])
3200         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3201       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3202     return \"mov%?\\t%R0, #0\";
3203   "
3204   [(set_attr "length" "8")
3205    (set_attr "predicable" "yes")]
3208 (define_insn "zero_extendqidi2"
3209   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3210         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3211   "TARGET_ARM"
3212   "@
3213    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3214    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3215   [(set_attr "length" "8")
3216    (set_attr "predicable" "yes")
3217    (set_attr "type" "*,load_byte")
3218    (set_attr "pool_range" "*,4092")
3219    (set_attr "neg_pool_range" "*,4084")]
3222 (define_insn "extendsidi2"
3223   [(set (match_operand:DI 0 "s_register_operand" "=r")
3224         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3225   "TARGET_ARM"
3226   "*
3227     if (REGNO (operands[1])
3228         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3229       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3230     return \"mov%?\\t%R0, %Q0, asr #31\";
3231   "
3232   [(set_attr "length" "8")
3233    (set_attr "shift" "1")
3234    (set_attr "predicable" "yes")]
3237 (define_expand "zero_extendhisi2"
3238   [(set (match_dup 2)
3239         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3240                    (const_int 16)))
3241    (set (match_operand:SI 0 "s_register_operand" "")
3242         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3243   "TARGET_EITHER"
3244   "
3245   {
3246     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3247       {
3248         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3249                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3250         DONE;
3251       }
3253     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3254       {
3255         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3256         DONE;
3257       }
3259     if (!s_register_operand (operands[1], HImode))
3260       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3262     if (arm_arch6)
3263       {
3264         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3265                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3266         DONE;
3267       }
3269     operands[1] = gen_lowpart (SImode, operands[1]);
3270     operands[2] = gen_reg_rtx (SImode);
3271   }"
3274 (define_insn "*thumb_zero_extendhisi2"
3275   [(set (match_operand:SI 0 "register_operand" "=l")
3276         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3277   "TARGET_THUMB && !arm_arch6"
3278   "*
3279   rtx mem = XEXP (operands[1], 0);
3281   if (GET_CODE (mem) == CONST)
3282     mem = XEXP (mem, 0);
3283     
3284   if (GET_CODE (mem) == LABEL_REF)
3285     return \"ldr\\t%0, %1\";
3286     
3287   if (GET_CODE (mem) == PLUS)
3288     {
3289       rtx a = XEXP (mem, 0);
3290       rtx b = XEXP (mem, 1);
3292       /* This can happen due to bugs in reload.  */
3293       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3294         {
3295           rtx ops[2];
3296           ops[0] = operands[0];
3297           ops[1] = a;
3298       
3299           output_asm_insn (\"mov        %0, %1\", ops);
3301           XEXP (mem, 0) = operands[0];
3302        }
3304       else if (   GET_CODE (a) == LABEL_REF
3305                && GET_CODE (b) == CONST_INT)
3306         return \"ldr\\t%0, %1\";
3307     }
3308     
3309   return \"ldrh\\t%0, %1\";
3310   "
3311   [(set_attr "length" "4")
3312    (set_attr "type" "load_byte")
3313    (set_attr "pool_range" "60")]
3316 (define_insn "*thumb_zero_extendhisi2_v6"
3317   [(set (match_operand:SI 0 "register_operand" "=l,l")
3318         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3319   "TARGET_THUMB && arm_arch6"
3320   "*
3321   rtx mem;
3323   if (which_alternative == 0)
3324     return \"uxth\\t%0, %1\";
3326   mem = XEXP (operands[1], 0);
3328   if (GET_CODE (mem) == CONST)
3329     mem = XEXP (mem, 0);
3330     
3331   if (GET_CODE (mem) == LABEL_REF)
3332     return \"ldr\\t%0, %1\";
3333     
3334   if (GET_CODE (mem) == PLUS)
3335     {
3336       rtx a = XEXP (mem, 0);
3337       rtx b = XEXP (mem, 1);
3339       /* This can happen due to bugs in reload.  */
3340       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3341         {
3342           rtx ops[2];
3343           ops[0] = operands[0];
3344           ops[1] = a;
3345       
3346           output_asm_insn (\"mov        %0, %1\", ops);
3348           XEXP (mem, 0) = operands[0];
3349        }
3351       else if (   GET_CODE (a) == LABEL_REF
3352                && GET_CODE (b) == CONST_INT)
3353         return \"ldr\\t%0, %1\";
3354     }
3355     
3356   return \"ldrh\\t%0, %1\";
3357   "
3358   [(set_attr "length" "2,4")
3359    (set_attr "type" "alu_shift,load_byte")
3360    (set_attr "pool_range" "*,60")]
3363 (define_insn "*arm_zero_extendhisi2"
3364   [(set (match_operand:SI 0 "s_register_operand" "=r")
3365         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3366   "TARGET_ARM && arm_arch4 && !arm_arch6"
3367   "ldr%?h\\t%0, %1"
3368   [(set_attr "type" "load_byte")
3369    (set_attr "predicable" "yes")
3370    (set_attr "pool_range" "256")
3371    (set_attr "neg_pool_range" "244")]
3374 (define_insn "*arm_zero_extendhisi2_v6"
3375   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3376         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3377   "TARGET_ARM && arm_arch6"
3378   "@
3379    uxth%?\\t%0, %1
3380    ldr%?h\\t%0, %1"
3381   [(set_attr "type" "alu_shift,load_byte")
3382    (set_attr "predicable" "yes")
3383    (set_attr "pool_range" "*,256")
3384    (set_attr "neg_pool_range" "*,244")]
3387 (define_insn "*arm_zero_extendhisi2addsi"
3388   [(set (match_operand:SI 0 "s_register_operand" "=r")
3389         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3390                  (match_operand:SI 2 "s_register_operand" "r")))]
3391   "TARGET_ARM && arm_arch6"
3392   "uxtah%?\\t%0, %2, %1"
3393   [(set_attr "type" "alu_shift")
3394    (set_attr "predicable" "yes")]
3397 (define_expand "zero_extendqisi2"
3398   [(set (match_operand:SI 0 "s_register_operand" "")
3399         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3400   "TARGET_EITHER"
3401   "
3402   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3403     {
3404       if (TARGET_ARM)
3405         {
3406           emit_insn (gen_andsi3 (operands[0],
3407                                  gen_lowpart (SImode, operands[1]),
3408                                  GEN_INT (255)));
3409         }
3410       else /* TARGET_THUMB */
3411         {
3412           rtx temp = gen_reg_rtx (SImode);
3413           rtx ops[3];
3414           
3415           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3416           operands[1] = gen_lowpart (SImode, operands[1]);
3418           ops[0] = temp;
3419           ops[1] = operands[1];
3420           ops[2] = GEN_INT (24);
3422           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3423                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3424           
3425           ops[0] = operands[0];
3426           ops[1] = temp;
3427           ops[2] = GEN_INT (24);
3429           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3430                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3431         }
3432       DONE;
3433     }
3434   "
3437 (define_insn "*thumb_zero_extendqisi2"
3438   [(set (match_operand:SI 0 "register_operand" "=l")
3439         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3440   "TARGET_THUMB && !arm_arch6"
3441   "ldrb\\t%0, %1"
3442   [(set_attr "length" "2")
3443    (set_attr "type" "load_byte")
3444    (set_attr "pool_range" "32")]
3447 (define_insn "*thumb_zero_extendqisi2_v6"
3448   [(set (match_operand:SI 0 "register_operand" "=l,l")
3449         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3450   "TARGET_THUMB && arm_arch6"
3451   "@
3452    uxtb\\t%0, %1
3453    ldrb\\t%0, %1"
3454   [(set_attr "length" "2,2")
3455    (set_attr "type" "alu_shift,load_byte")
3456    (set_attr "pool_range" "*,32")]
3459 (define_insn "*arm_zero_extendqisi2"
3460   [(set (match_operand:SI 0 "s_register_operand" "=r")
3461         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3462   "TARGET_ARM && !arm_arch6"
3463   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3464   [(set_attr "type" "load_byte")
3465    (set_attr "predicable" "yes")
3466    (set_attr "pool_range" "4096")
3467    (set_attr "neg_pool_range" "4084")]
3470 (define_insn "*arm_zero_extendqisi2_v6"
3471   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3472         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3473   "TARGET_ARM && arm_arch6"
3474   "@
3475    uxtb%?\\t%0, %1
3476    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3477   [(set_attr "type" "alu_shift,load_byte")
3478    (set_attr "predicable" "yes")
3479    (set_attr "pool_range" "*,4096")
3480    (set_attr "neg_pool_range" "*,4084")]
3483 (define_insn "*arm_zero_extendqisi2addsi"
3484   [(set (match_operand:SI 0 "s_register_operand" "=r")
3485         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3486                  (match_operand:SI 2 "s_register_operand" "r")))]
3487   "TARGET_ARM && arm_arch6"
3488   "uxtab%?\\t%0, %2, %1"
3489   [(set_attr "predicable" "yes")
3490    (set_attr "type" "alu_shift")]
3493 (define_split
3494   [(set (match_operand:SI 0 "s_register_operand" "")
3495         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3496    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3497   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3498   [(set (match_dup 2) (match_dup 1))
3499    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3500   ""
3503 (define_split
3504   [(set (match_operand:SI 0 "s_register_operand" "")
3505         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
3506    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3507   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
3508   [(set (match_dup 2) (match_dup 1))
3509    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3510   ""
3513 (define_insn "*compareqi_eq0"
3514   [(set (reg:CC_Z CC_REGNUM)
3515         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3516                          (const_int 0)))]
3517   "TARGET_ARM"
3518   "tst\\t%0, #255"
3519   [(set_attr "conds" "set")]
3522 (define_expand "extendhisi2"
3523   [(set (match_dup 2)
3524         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3525                    (const_int 16)))
3526    (set (match_operand:SI 0 "s_register_operand" "")
3527         (ashiftrt:SI (match_dup 2)
3528                      (const_int 16)))]
3529   "TARGET_EITHER"
3530   "
3531   {
3532     if (GET_CODE (operands[1]) == MEM)
3533       {
3534         if (TARGET_THUMB)
3535           {
3536             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3537             DONE;
3538           }
3539         else if (arm_arch4)
3540           {
3541             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3542                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3543             DONE;
3544           }
3545       }
3547     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3548       {
3549         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3550         DONE;
3551       }
3553     if (!s_register_operand (operands[1], HImode))
3554       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3556     if (arm_arch6)
3557       {
3558         if (TARGET_THUMB)
3559           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3560         else
3561           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3562                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3564         DONE;
3565       }
3567     operands[1] = gen_lowpart (SImode, operands[1]);
3568     operands[2] = gen_reg_rtx (SImode);
3569   }"
3572 (define_insn "thumb_extendhisi2"
3573   [(set (match_operand:SI 0 "register_operand" "=l")
3574         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3575    (clobber (match_scratch:SI 2 "=&l"))]
3576   "TARGET_THUMB && !arm_arch6"
3577   "*
3578   {
3579     rtx ops[4];
3580     rtx mem = XEXP (operands[1], 0);
3582     /* This code used to try to use 'V', and fix the address only if it was
3583        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3584        range of QImode offsets, and offsettable_address_p does a QImode
3585        address check.  */
3586        
3587     if (GET_CODE (mem) == CONST)
3588       mem = XEXP (mem, 0);
3589     
3590     if (GET_CODE (mem) == LABEL_REF)
3591       return \"ldr\\t%0, %1\";
3592     
3593     if (GET_CODE (mem) == PLUS)
3594       {
3595         rtx a = XEXP (mem, 0);
3596         rtx b = XEXP (mem, 1);
3598         if (GET_CODE (a) == LABEL_REF
3599             && GET_CODE (b) == CONST_INT)
3600           return \"ldr\\t%0, %1\";
3602         if (GET_CODE (b) == REG)
3603           return \"ldrsh\\t%0, %1\";
3604           
3605         ops[1] = a;
3606         ops[2] = b;
3607       }
3608     else
3609       {
3610         ops[1] = mem;
3611         ops[2] = const0_rtx;
3612       }
3614     gcc_assert (GET_CODE (ops[1]) == REG);
3616     ops[0] = operands[0];
3617     ops[3] = operands[2];
3618     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3619     return \"\";
3620   }"
3621   [(set_attr "length" "4")
3622    (set_attr "type" "load_byte")
3623    (set_attr "pool_range" "1020")]
3626 ;; We used to have an early-clobber on the scratch register here.
3627 ;; However, there's a bug somewhere in reload which means that this
3628 ;; can be partially ignored during spill allocation if the memory
3629 ;; address also needs reloading; this causes us to die later on when
3630 ;; we try to verify the operands.  Fortunately, we don't really need
3631 ;; the early-clobber: we can always use operand 0 if operand 2
3632 ;; overlaps the address.
3633 (define_insn "*thumb_extendhisi2_insn_v6"
3634   [(set (match_operand:SI 0 "register_operand" "=l,l")
3635         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3636    (clobber (match_scratch:SI 2 "=X,l"))]
3637   "TARGET_THUMB && arm_arch6"
3638   "*
3639   {
3640     rtx ops[4];
3641     rtx mem;
3643     if (which_alternative == 0)
3644       return \"sxth\\t%0, %1\";
3646     mem = XEXP (operands[1], 0);
3648     /* This code used to try to use 'V', and fix the address only if it was
3649        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3650        range of QImode offsets, and offsettable_address_p does a QImode
3651        address check.  */
3652        
3653     if (GET_CODE (mem) == CONST)
3654       mem = XEXP (mem, 0);
3655     
3656     if (GET_CODE (mem) == LABEL_REF)
3657       return \"ldr\\t%0, %1\";
3658     
3659     if (GET_CODE (mem) == PLUS)
3660       {
3661         rtx a = XEXP (mem, 0);
3662         rtx b = XEXP (mem, 1);
3664         if (GET_CODE (a) == LABEL_REF
3665             && GET_CODE (b) == CONST_INT)
3666           return \"ldr\\t%0, %1\";
3668         if (GET_CODE (b) == REG)
3669           return \"ldrsh\\t%0, %1\";
3670           
3671         ops[1] = a;
3672         ops[2] = b;
3673       }
3674     else
3675       {
3676         ops[1] = mem;
3677         ops[2] = const0_rtx;
3678       }
3679       
3680     gcc_assert (GET_CODE (ops[1]) == REG);
3682     ops[0] = operands[0];
3683     if (reg_mentioned_p (operands[2], ops[1]))
3684       ops[3] = ops[0];
3685     else
3686       ops[3] = operands[2];
3687     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3688     return \"\";
3689   }"
3690   [(set_attr "length" "2,4")
3691    (set_attr "type" "alu_shift,load_byte")
3692    (set_attr "pool_range" "*,1020")]
3695 (define_expand "extendhisi2_mem"
3696   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3697    (set (match_dup 3)
3698         (zero_extend:SI (match_dup 7)))
3699    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3700    (set (match_operand:SI 0 "" "")
3701         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3702   "TARGET_ARM"
3703   "
3704   {
3705     rtx mem1, mem2;
3706     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3708     mem1 = change_address (operands[1], QImode, addr);
3709     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3710     operands[0] = gen_lowpart (SImode, operands[0]);
3711     operands[1] = mem1;
3712     operands[2] = gen_reg_rtx (SImode);
3713     operands[3] = gen_reg_rtx (SImode);
3714     operands[6] = gen_reg_rtx (SImode);
3715     operands[7] = mem2;
3717     if (BYTES_BIG_ENDIAN)
3718       {
3719         operands[4] = operands[2];
3720         operands[5] = operands[3];
3721       }
3722     else
3723       {
3724         operands[4] = operands[3];
3725         operands[5] = operands[2];
3726       }
3727   }"
3730 (define_insn "*arm_extendhisi2"
3731   [(set (match_operand:SI 0 "s_register_operand" "=r")
3732         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3733   "TARGET_ARM && arm_arch4 && !arm_arch6"
3734   "ldr%?sh\\t%0, %1"
3735   [(set_attr "type" "load_byte")
3736    (set_attr "predicable" "yes")
3737    (set_attr "pool_range" "256")
3738    (set_attr "neg_pool_range" "244")]
3741 (define_insn "*arm_extendhisi2_v6"
3742   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3743         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3744   "TARGET_ARM && arm_arch6"
3745   "@
3746    sxth%?\\t%0, %1
3747    ldr%?sh\\t%0, %1"
3748   [(set_attr "type" "alu_shift,load_byte")
3749    (set_attr "predicable" "yes")
3750    (set_attr "pool_range" "*,256")
3751    (set_attr "neg_pool_range" "*,244")]
3754 (define_insn "*arm_extendhisi2addsi"
3755   [(set (match_operand:SI 0 "s_register_operand" "=r")
3756         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3757                  (match_operand:SI 2 "s_register_operand" "r")))]
3758   "TARGET_ARM && arm_arch6"
3759   "sxtah%?\\t%0, %2, %1"
3762 (define_expand "extendqihi2"
3763   [(set (match_dup 2)
3764         (ashift:SI (match_operand:QI 1 "general_operand" "")
3765                    (const_int 24)))
3766    (set (match_operand:HI 0 "s_register_operand" "")
3767         (ashiftrt:SI (match_dup 2)
3768                      (const_int 24)))]
3769   "TARGET_ARM"
3770   "
3771   {
3772     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3773       {
3774         emit_insn (gen_rtx_SET (VOIDmode,
3775                                 operands[0],
3776                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3777         DONE;
3778       }
3779     if (!s_register_operand (operands[1], QImode))
3780       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3781     operands[0] = gen_lowpart (SImode, operands[0]);
3782     operands[1] = gen_lowpart (SImode, operands[1]);
3783     operands[2] = gen_reg_rtx (SImode);
3784   }"
3787 (define_insn "*extendqihi_insn"
3788   [(set (match_operand:HI 0 "s_register_operand" "=r")
3789         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3790   "TARGET_ARM && arm_arch4"
3791   "ldr%?sb\\t%0, %1"
3792   [(set_attr "type" "load_byte")
3793    (set_attr "predicable" "yes")
3794    (set_attr "pool_range" "256")
3795    (set_attr "neg_pool_range" "244")]
3798 (define_expand "extendqisi2"
3799   [(set (match_dup 2)
3800         (ashift:SI (match_operand:QI 1 "general_operand" "")
3801                    (const_int 24)))
3802    (set (match_operand:SI 0 "s_register_operand" "")
3803         (ashiftrt:SI (match_dup 2)
3804                      (const_int 24)))]
3805   "TARGET_EITHER"
3806   "
3807   {
3808     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3809       {
3810         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3811                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3812         DONE;
3813       }
3815     if (!s_register_operand (operands[1], QImode))
3816       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3818     if (arm_arch6)
3819       {
3820         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3821                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3822         DONE;
3823       }
3825     operands[1] = gen_lowpart (SImode, operands[1]);
3826     operands[2] = gen_reg_rtx (SImode);
3827   }"
3830 (define_insn "*arm_extendqisi"
3831   [(set (match_operand:SI 0 "s_register_operand" "=r")
3832         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3833   "TARGET_ARM && arm_arch4 && !arm_arch6"
3834   "ldr%?sb\\t%0, %1"
3835   [(set_attr "type" "load_byte")
3836    (set_attr "predicable" "yes")
3837    (set_attr "pool_range" "256")
3838    (set_attr "neg_pool_range" "244")]
3841 (define_insn "*arm_extendqisi_v6"
3842   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3843         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3844   "TARGET_ARM && arm_arch6"
3845   "@
3846    sxtb%?\\t%0, %1
3847    ldr%?sb\\t%0, %1"
3848   [(set_attr "type" "alu_shift,load_byte")
3849    (set_attr "predicable" "yes")
3850    (set_attr "pool_range" "*,256")
3851    (set_attr "neg_pool_range" "*,244")]
3854 (define_insn "*arm_extendqisi2addsi"
3855   [(set (match_operand:SI 0 "s_register_operand" "=r")
3856         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3857                  (match_operand:SI 2 "s_register_operand" "r")))]
3858   "TARGET_ARM && arm_arch6"
3859   "sxtab%?\\t%0, %2, %1"
3860   [(set_attr "type" "alu_shift")
3861    (set_attr "predicable" "yes")]
3864 (define_insn "*thumb_extendqisi2"
3865   [(set (match_operand:SI 0 "register_operand" "=l,l")
3866         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3867   "TARGET_THUMB && !arm_arch6"
3868   "*
3869   {
3870     rtx ops[3];
3871     rtx mem = XEXP (operands[1], 0);
3872     
3873     if (GET_CODE (mem) == CONST)
3874       mem = XEXP (mem, 0);
3875     
3876     if (GET_CODE (mem) == LABEL_REF)
3877       return \"ldr\\t%0, %1\";
3879     if (GET_CODE (mem) == PLUS
3880         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3881       return \"ldr\\t%0, %1\";
3882       
3883     if (which_alternative == 0)
3884       return \"ldrsb\\t%0, %1\";
3885       
3886     ops[0] = operands[0];
3887     
3888     if (GET_CODE (mem) == PLUS)
3889       {
3890         rtx a = XEXP (mem, 0);
3891         rtx b = XEXP (mem, 1);
3892         
3893         ops[1] = a;
3894         ops[2] = b;
3896         if (GET_CODE (a) == REG)
3897           {
3898             if (GET_CODE (b) == REG)
3899               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3900             else if (REGNO (a) == REGNO (ops[0]))
3901               {
3902                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3903                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3904                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3905               }
3906             else
3907               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3908           }
3909         else
3910           {
3911             gcc_assert (GET_CODE (b) == REG);
3912             if (REGNO (b) == REGNO (ops[0]))
3913               {
3914                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3915                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3916                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3917               }
3918             else
3919               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3920           }
3921       }
3922     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3923       {
3924         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3925         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3926         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3927       }
3928     else
3929       {
3930         ops[1] = mem;
3931         ops[2] = const0_rtx;
3932         
3933         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3934       }
3935     return \"\";
3936   }"
3937   [(set_attr "length" "2,6")
3938    (set_attr "type" "load_byte,load_byte")
3939    (set_attr "pool_range" "32,32")]
3942 (define_insn "*thumb_extendqisi2_v6"
3943   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3944         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3945   "TARGET_THUMB && arm_arch6"
3946   "*
3947   {
3948     rtx ops[3];
3949     rtx mem;
3951     if (which_alternative == 0)
3952       return \"sxtb\\t%0, %1\";
3954     mem = XEXP (operands[1], 0);
3955     
3956     if (GET_CODE (mem) == CONST)
3957       mem = XEXP (mem, 0);
3958     
3959     if (GET_CODE (mem) == LABEL_REF)
3960       return \"ldr\\t%0, %1\";
3962     if (GET_CODE (mem) == PLUS
3963         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3964       return \"ldr\\t%0, %1\";
3965       
3966     if (which_alternative == 0)
3967       return \"ldrsb\\t%0, %1\";
3968       
3969     ops[0] = operands[0];
3970     
3971     if (GET_CODE (mem) == PLUS)
3972       {
3973         rtx a = XEXP (mem, 0);
3974         rtx b = XEXP (mem, 1);
3975         
3976         ops[1] = a;
3977         ops[2] = b;
3979         if (GET_CODE (a) == REG)
3980           {
3981             if (GET_CODE (b) == REG)
3982               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3983             else if (REGNO (a) == REGNO (ops[0]))
3984               {
3985                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3986                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3987               }
3988             else
3989               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3990           }
3991         else
3992           {
3993             gcc_assert (GET_CODE (b) == REG);
3994             if (REGNO (b) == REGNO (ops[0]))
3995               {
3996                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3997                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3998               }
3999             else
4000               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4001           }
4002       }
4003     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4004       {
4005         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4006         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4007       }
4008     else
4009       {
4010         ops[1] = mem;
4011         ops[2] = const0_rtx;
4012         
4013         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4014       }
4015     return \"\";
4016   }"
4017   [(set_attr "length" "2,2,4")
4018    (set_attr "type" "alu_shift,load_byte,load_byte")
4019    (set_attr "pool_range" "*,32,32")]
4022 (define_expand "extendsfdf2"
4023   [(set (match_operand:DF                  0 "s_register_operand" "")
4024         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4025   "TARGET_ARM && TARGET_HARD_FLOAT"
4026   ""
4029 ;; Move insns (including loads and stores)
4031 ;; XXX Just some ideas about movti.
4032 ;; I don't think these are a good idea on the arm, there just aren't enough
4033 ;; registers
4034 ;;(define_expand "loadti"
4035 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4036 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4037 ;;  "" "")
4039 ;;(define_expand "storeti"
4040 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4041 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4042 ;;  "" "")
4044 ;;(define_expand "movti"
4045 ;;  [(set (match_operand:TI 0 "general_operand" "")
4046 ;;      (match_operand:TI 1 "general_operand" ""))]
4047 ;;  ""
4048 ;;  "
4050 ;;  rtx insn;
4052 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4053 ;;    operands[1] = copy_to_reg (operands[1]);
4054 ;;  if (GET_CODE (operands[0]) == MEM)
4055 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4056 ;;  else if (GET_CODE (operands[1]) == MEM)
4057 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4058 ;;  else
4059 ;;    FAIL;
4061 ;;  emit_insn (insn);
4062 ;;  DONE;
4063 ;;}")
4065 ;; Recognize garbage generated above.
4067 ;;(define_insn ""
4068 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4069 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4070 ;;  ""
4071 ;;  "*
4072 ;;  {
4073 ;;    register mem = (which_alternative < 3);
4074 ;;    register const char *template;
4076 ;;    operands[mem] = XEXP (operands[mem], 0);
4077 ;;    switch (which_alternative)
4078 ;;      {
4079 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4080 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4081 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4082 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4083 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4084 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4085 ;;      }
4086 ;;    output_asm_insn (template, operands);
4087 ;;    return \"\";
4088 ;;  }")
4090 (define_expand "movdi"
4091   [(set (match_operand:DI 0 "general_operand" "")
4092         (match_operand:DI 1 "general_operand" ""))]
4093   "TARGET_EITHER"
4094   "
4095   if (TARGET_THUMB)
4096     {
4097       if (!no_new_pseudos)
4098         {
4099           if (GET_CODE (operands[0]) != REG)
4100             operands[1] = force_reg (DImode, operands[1]);
4101         }
4102     }
4103   "
4106 (define_insn "*arm_movdi"
4107   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4108         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4109   "TARGET_ARM
4110   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4111   && !TARGET_IWMMXT"
4112   "*
4113   switch (which_alternative)
4114     {
4115     case 0:
4116     case 1:
4117     case 2:
4118       return \"#\";
4119     default:
4120       return output_move_double (operands);
4121     }
4122   "
4123   [(set_attr "length" "8,12,16,8,8")
4124    (set_attr "type" "*,*,*,load2,store2")
4125    (set_attr "pool_range" "*,*,*,1020,*")
4126    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4129 (define_split
4130   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4131         (match_operand:ANY64 1 "const_double_operand" ""))]
4132   "TARGET_ARM
4133    && reload_completed
4134    && (arm_const_double_inline_cost (operands[1])
4135        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4136   [(const_int 0)]
4137   "
4138   arm_split_constant (SET, SImode, curr_insn,
4139                       INTVAL (gen_lowpart (SImode, operands[1])),
4140                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4141   arm_split_constant (SET, SImode, curr_insn,
4142                       INTVAL (gen_highpart_mode (SImode,
4143                                                  GET_MODE (operands[0]),
4144                                                  operands[1])),
4145                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4146   DONE;
4147   "
4150 ; If optimizing for size, or if we have load delay slots, then 
4151 ; we want to split the constant into two separate operations. 
4152 ; In both cases this may split a trivial part into a single data op
4153 ; leaving a single complex constant to load.  We can also get longer
4154 ; offsets in a LDR which means we get better chances of sharing the pool
4155 ; entries.  Finally, we can normally do a better job of scheduling
4156 ; LDR instructions than we can with LDM.
4157 ; This pattern will only match if the one above did not.
4158 (define_split
4159   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4160         (match_operand:ANY64 1 "const_double_operand" ""))]
4161   "TARGET_ARM && reload_completed
4162    && arm_const_double_by_parts (operands[1])"
4163   [(set (match_dup 0) (match_dup 1))
4164    (set (match_dup 2) (match_dup 3))]
4165   "
4166   operands[2] = gen_highpart (SImode, operands[0]);
4167   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4168                                    operands[1]);
4169   operands[0] = gen_lowpart (SImode, operands[0]);
4170   operands[1] = gen_lowpart (SImode, operands[1]);
4171   "
4174 (define_split
4175   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4176         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4177   "TARGET_EITHER && reload_completed"
4178   [(set (match_dup 0) (match_dup 1))
4179    (set (match_dup 2) (match_dup 3))]
4180   "
4181   operands[2] = gen_highpart (SImode, operands[0]);
4182   operands[3] = gen_highpart (SImode, operands[1]);
4183   operands[0] = gen_lowpart (SImode, operands[0]);
4184   operands[1] = gen_lowpart (SImode, operands[1]);
4186   /* Handle a partial overlap.  */
4187   if (rtx_equal_p (operands[0], operands[3]))
4188     {
4189       rtx tmp0 = operands[0];
4190       rtx tmp1 = operands[1];
4192       operands[0] = operands[2];
4193       operands[1] = operands[3];
4194       operands[2] = tmp0;
4195       operands[3] = tmp1;
4196     }
4197   "
4200 ;; We can't actually do base+index doubleword loads if the index and
4201 ;; destination overlap.  Split here so that we at least have chance to
4202 ;; schedule.
4203 (define_split
4204   [(set (match_operand:DI 0 "s_register_operand" "")
4205         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4206                          (match_operand:SI 2 "s_register_operand" ""))))]
4207   "TARGET_LDRD
4208   && reg_overlap_mentioned_p (operands[0], operands[1])
4209   && reg_overlap_mentioned_p (operands[0], operands[2])"
4210   [(set (match_dup 4)
4211         (plus:SI (match_dup 1)
4212                  (match_dup 2)))
4213    (set (match_dup 0)
4214         (mem:DI (match_dup 4)))]
4215   "
4216   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4217   "
4220 ;;; ??? This should have alternatives for constants.
4221 ;;; ??? This was originally identical to the movdf_insn pattern.
4222 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4223 ;;; thumb_reorg with a memory reference.
4224 (define_insn "*thumb_movdi_insn"
4225   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4226         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4227   "TARGET_THUMB
4228    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4229    && (   register_operand (operands[0], DImode)
4230        || register_operand (operands[1], DImode))"
4231   "*
4232   {
4233   switch (which_alternative)
4234     {
4235     default:
4236     case 0:
4237       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4238         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4239       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4240     case 1:
4241       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4242     case 2:
4243       operands[1] = GEN_INT (- INTVAL (operands[1]));
4244       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4245     case 3:
4246       return \"ldmia\\t%1, {%0, %H0}\";
4247     case 4:
4248       return \"stmia\\t%0, {%1, %H1}\";
4249     case 5:
4250       return thumb_load_double_from_address (operands);
4251     case 6:
4252       operands[2] = gen_rtx_MEM (SImode,
4253                              plus_constant (XEXP (operands[0], 0), 4));
4254       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4255       return \"\";
4256     case 7:
4257       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4258         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4259       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4260     }
4261   }"
4262   [(set_attr "length" "4,4,6,2,2,6,4,4")
4263    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4264    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4267 (define_expand "movsi"
4268   [(set (match_operand:SI 0 "general_operand" "")
4269         (match_operand:SI 1 "general_operand" ""))]
4270   "TARGET_EITHER"
4271   "
4272   if (TARGET_ARM)
4273     {
4274       /* Everything except mem = const or mem = mem can be done easily.  */
4275       if (GET_CODE (operands[0]) == MEM)
4276         operands[1] = force_reg (SImode, operands[1]);
4277       if (arm_general_register_operand (operands[0], SImode)
4278           && GET_CODE (operands[1]) == CONST_INT
4279           && !(const_ok_for_arm (INTVAL (operands[1]))
4280                || const_ok_for_arm (~INTVAL (operands[1]))))
4281         {
4282            arm_split_constant (SET, SImode, NULL_RTX,
4283                                INTVAL (operands[1]), operands[0], NULL_RTX,
4284                                optimize && !no_new_pseudos);
4285           DONE;
4286         }
4287     }
4288   else /* TARGET_THUMB....  */
4289     {
4290       if (!no_new_pseudos)
4291         {
4292           if (GET_CODE (operands[0]) != REG)
4293             operands[1] = force_reg (SImode, operands[1]);
4294         }
4295     }
4297   /* Recognize the case where operand[1] is a reference to thread-local
4298      data and load its address to a register.  */
4299   if (arm_tls_referenced_p (operands[1]))
4300     {
4301       rtx tmp = operands[1];
4302       rtx addend = NULL;
4304       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4305         {
4306           addend = XEXP (XEXP (tmp, 0), 1);
4307           tmp = XEXP (XEXP (tmp, 0), 0);
4308         }
4310       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4311       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4313       tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4314       if (addend)
4315         {
4316           tmp = gen_rtx_PLUS (SImode, tmp, addend);
4317           tmp = force_operand (tmp, operands[0]);
4318         }
4319       operands[1] = tmp;
4320     }
4321   else if (flag_pic
4322            && (CONSTANT_P (operands[1])
4323                || symbol_mentioned_p (operands[1])
4324                || label_mentioned_p (operands[1])))
4325       operands[1] = legitimize_pic_address (operands[1], SImode,
4326                                             (no_new_pseudos ? operands[0] : 0));
4327   "
4330 (define_insn "*arm_movsi_insn"
4331   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4332         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4333   "TARGET_ARM && ! TARGET_IWMMXT
4334    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4335    && (   register_operand (operands[0], SImode)
4336        || register_operand (operands[1], SImode))"
4337   "@
4338    mov%?\\t%0, %1
4339    mvn%?\\t%0, #%B1
4340    ldr%?\\t%0, %1
4341    str%?\\t%1, %0"
4342   [(set_attr "type" "*,*,load1,store1")
4343    (set_attr "predicable" "yes")
4344    (set_attr "pool_range" "*,*,4096,*")
4345    (set_attr "neg_pool_range" "*,*,4084,*")]
4348 (define_split
4349   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4350         (match_operand:SI 1 "const_int_operand" ""))]
4351   "TARGET_ARM
4352   && (!(const_ok_for_arm (INTVAL (operands[1]))
4353         || const_ok_for_arm (~INTVAL (operands[1]))))"
4354   [(clobber (const_int 0))]
4355   "
4356   arm_split_constant (SET, SImode, NULL_RTX, 
4357                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4358   DONE;
4359   "
4362 (define_insn "*thumb_movsi_insn"
4363   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4364         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4365   "TARGET_THUMB
4366    && (   register_operand (operands[0], SImode) 
4367        || register_operand (operands[1], SImode))"
4368   "@
4369    mov  %0, %1
4370    mov  %0, %1
4371    #
4372    #
4373    ldmia\\t%1, {%0}
4374    stmia\\t%0, {%1}
4375    ldr\\t%0, %1
4376    str\\t%1, %0
4377    mov\\t%0, %1"
4378   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4379    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4380    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4383 (define_split 
4384   [(set (match_operand:SI 0 "register_operand" "")
4385         (match_operand:SI 1 "const_int_operand" ""))]
4386   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4387   [(set (match_dup 0) (match_dup 1))
4388    (set (match_dup 0) (neg:SI (match_dup 0)))]
4389   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4392 (define_split 
4393   [(set (match_operand:SI 0 "register_operand" "")
4394         (match_operand:SI 1 "const_int_operand" ""))]
4395   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4396   [(set (match_dup 0) (match_dup 1))
4397    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4398   "
4399   {
4400     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4401     unsigned HOST_WIDE_INT mask = 0xff;
4402     int i;
4403     
4404     for (i = 0; i < 25; i++)
4405       if ((val & (mask << i)) == val)
4406         break;
4408     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4409     if (i == 0)
4410       FAIL;
4412     operands[1] = GEN_INT (val >> i);
4413     operands[2] = GEN_INT (i);
4414   }"
4417 ;; When generating pic, we need to load the symbol offset into a register.
4418 ;; So that the optimizer does not confuse this with a normal symbol load
4419 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4420 ;; since that is the only type of relocation we can use.
4422 ;; The rather odd constraints on the following are to force reload to leave
4423 ;; the insn alone, and to force the minipool generation pass to then move
4424 ;; the GOT symbol to memory.
4426 (define_insn "pic_load_addr_arm"
4427   [(set (match_operand:SI 0 "s_register_operand" "=r")
4428         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4429   "TARGET_ARM && flag_pic"
4430   "ldr%?\\t%0, %1"
4431   [(set_attr "type" "load1")
4432    (set (attr "pool_range")     (const_int 4096))
4433    (set (attr "neg_pool_range") (const_int 4084))]
4436 (define_insn "pic_load_addr_thumb"
4437   [(set (match_operand:SI 0 "s_register_operand" "=l")
4438         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4439   "TARGET_THUMB && flag_pic"
4440   "ldr\\t%0, %1"
4441   [(set_attr "type" "load1")
4442    (set (attr "pool_range") (const_int 1024))]
4445 ;; This variant is used for AOF assembly, since it needs to mention the
4446 ;; pic register in the rtl.
4447 (define_expand "pic_load_addr_based"
4448   [(set (match_operand:SI 0 "s_register_operand" "")
4449         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4450   "TARGET_ARM && flag_pic"
4451   "operands[2] = cfun->machine->pic_reg;"
4454 (define_insn "*pic_load_addr_based_insn"
4455   [(set (match_operand:SI 0 "s_register_operand" "=r")
4456         (unspec:SI [(match_operand 1 "" "")
4457                     (match_operand 2 "s_register_operand" "r")]
4458                    UNSPEC_PIC_SYM))]
4459   "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
4460   "*
4461 #ifdef AOF_ASSEMBLER
4462   operands[1] = aof_pic_entry (operands[1]);
4463 #endif
4464   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4465   return \"\";
4466   "
4467   [(set_attr "type" "load1")
4468    (set (attr "pool_range")
4469         (if_then_else (eq_attr "is_thumb" "yes")
4470                       (const_int 1024)
4471                       (const_int 4096)))
4472    (set (attr "neg_pool_range")
4473         (if_then_else (eq_attr "is_thumb" "yes")
4474                       (const_int 0)
4475                       (const_int 4084)))]
4478 (define_insn "pic_add_dot_plus_four"
4479   [(set (match_operand:SI 0 "register_operand" "=r")
4480         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4481                              (const (plus:SI (pc) (const_int 4))))]
4482                    UNSPEC_PIC_BASE))
4483    (use (match_operand 2 "" ""))]
4484   "TARGET_THUMB"
4485   "*
4486   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4487                                      INTVAL (operands[2]));
4488   return \"add\\t%0, %|pc\";
4489   "
4490   [(set_attr "length" "2")]
4493 (define_insn "pic_add_dot_plus_eight"
4494   [(set (match_operand:SI 0 "register_operand" "=r")
4495         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4496                              (const (plus:SI (pc) (const_int 8))))]
4497                    UNSPEC_PIC_BASE))
4498    (use (match_operand 2 "" ""))]
4499   "TARGET_ARM"
4500   "*
4501     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4502                                        INTVAL (operands[2]));
4503     return \"add%?\\t%0, %|pc, %1\";
4504   "
4505   [(set_attr "predicable" "yes")]
4508 (define_insn "tls_load_dot_plus_eight"
4509   [(set (match_operand:SI 0 "register_operand" "+r")
4510         (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4511                                      (const (plus:SI (pc) (const_int 8))))]
4512                            UNSPEC_PIC_BASE)))
4513    (use (match_operand 2 "" ""))]
4514   "TARGET_ARM"
4515   "*
4516     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4517                                        INTVAL (operands[2]));
4518     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4519   "
4520   [(set_attr "predicable" "yes")]
4523 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4524 ;; followed by a load.  These sequences can be crunched down to
4525 ;; tls_load_dot_plus_eight by a peephole.
4527 (define_peephole2
4528   [(parallel [(set (match_operand:SI 0 "register_operand" "")
4529                    (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4530                                         (const (plus:SI (pc) (const_int 8))))]
4531                               UNSPEC_PIC_BASE))
4532               (use (label_ref (match_operand 1 "" "")))])
4533    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4534   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4535   [(parallel [(set (match_dup 2)
4536                    (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4537                                                 (const (plus:SI (pc) (const_int 8))))]
4538                                       UNSPEC_PIC_BASE)))
4539               (use (label_ref (match_dup 1)))])]
4540   ""
4543 (define_expand "builtin_setjmp_receiver"
4544   [(label_ref (match_operand 0 "" ""))]
4545   "flag_pic"
4546   "
4548   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4549      register.  */
4550   if (arm_pic_register != INVALID_REGNUM)
4551     arm_load_pic_register (1UL << 3);
4552   DONE;
4555 ;; If copying one reg to another we can set the condition codes according to
4556 ;; its value.  Such a move is common after a return from subroutine and the
4557 ;; result is being tested against zero.
4559 (define_insn "*movsi_compare0"
4560   [(set (reg:CC CC_REGNUM)
4561         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4562                     (const_int 0)))
4563    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4564         (match_dup 1))]
4565   "TARGET_ARM"
4566   "@
4567    cmp%?\\t%0, #0
4568    sub%?s\\t%0, %1, #0"
4569   [(set_attr "conds" "set")]
4572 ;; Subroutine to store a half word from a register into memory.
4573 ;; Operand 0 is the source register (HImode)
4574 ;; Operand 1 is the destination address in a register (SImode)
4576 ;; In both this routine and the next, we must be careful not to spill
4577 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4578 ;; can generate unrecognizable rtl.
4580 (define_expand "storehi"
4581   [;; store the low byte
4582    (set (match_operand 1 "" "") (match_dup 3))
4583    ;; extract the high byte
4584    (set (match_dup 2)
4585         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4586    ;; store the high byte
4587    (set (match_dup 4) (match_dup 5))]
4588   "TARGET_ARM"
4589   "
4590   {
4591     rtx op1 = operands[1];
4592     rtx addr = XEXP (op1, 0);
4593     enum rtx_code code = GET_CODE (addr);
4595     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4596         || code == MINUS)
4597       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4599     operands[4] = adjust_address (op1, QImode, 1);
4600     operands[1] = adjust_address (operands[1], QImode, 0);
4601     operands[3] = gen_lowpart (QImode, operands[0]);
4602     operands[0] = gen_lowpart (SImode, operands[0]);
4603     operands[2] = gen_reg_rtx (SImode);
4604     operands[5] = gen_lowpart (QImode, operands[2]);
4605   }"
4608 (define_expand "storehi_bigend"
4609   [(set (match_dup 4) (match_dup 3))
4610    (set (match_dup 2)
4611         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4612    (set (match_operand 1 "" "") (match_dup 5))]
4613   "TARGET_ARM"
4614   "
4615   {
4616     rtx op1 = operands[1];
4617     rtx addr = XEXP (op1, 0);
4618     enum rtx_code code = GET_CODE (addr);
4620     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4621         || code == MINUS)
4622       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4624     operands[4] = adjust_address (op1, QImode, 1);
4625     operands[1] = adjust_address (operands[1], QImode, 0);
4626     operands[3] = gen_lowpart (QImode, operands[0]);
4627     operands[0] = gen_lowpart (SImode, operands[0]);
4628     operands[2] = gen_reg_rtx (SImode);
4629     operands[5] = gen_lowpart (QImode, operands[2]);
4630   }"
4633 ;; Subroutine to store a half word integer constant into memory.
4634 (define_expand "storeinthi"
4635   [(set (match_operand 0 "" "")
4636         (match_operand 1 "" ""))
4637    (set (match_dup 3) (match_dup 2))]
4638   "TARGET_ARM"
4639   "
4640   {
4641     HOST_WIDE_INT value = INTVAL (operands[1]);
4642     rtx addr = XEXP (operands[0], 0);
4643     rtx op0 = operands[0];
4644     enum rtx_code code = GET_CODE (addr);
4646     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4647         || code == MINUS)
4648       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4650     operands[1] = gen_reg_rtx (SImode);
4651     if (BYTES_BIG_ENDIAN)
4652       {
4653         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4654         if ((value & 255) == ((value >> 8) & 255))
4655           operands[2] = operands[1];
4656         else
4657           {
4658             operands[2] = gen_reg_rtx (SImode);
4659             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4660           }
4661       }
4662     else
4663       {
4664         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4665         if ((value & 255) == ((value >> 8) & 255))
4666           operands[2] = operands[1];
4667         else
4668           {
4669             operands[2] = gen_reg_rtx (SImode);
4670             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4671           }
4672       }
4674     operands[3] = adjust_address (op0, QImode, 1);
4675     operands[0] = adjust_address (operands[0], QImode, 0);
4676     operands[2] = gen_lowpart (QImode, operands[2]);
4677     operands[1] = gen_lowpart (QImode, operands[1]);
4678   }"
4681 (define_expand "storehi_single_op"
4682   [(set (match_operand:HI 0 "memory_operand" "")
4683         (match_operand:HI 1 "general_operand" ""))]
4684   "TARGET_ARM && arm_arch4"
4685   "
4686   if (!s_register_operand (operands[1], HImode))
4687     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4688   "
4691 (define_expand "movhi"
4692   [(set (match_operand:HI 0 "general_operand" "")
4693         (match_operand:HI 1 "general_operand" ""))]
4694   "TARGET_EITHER"
4695   "
4696   if (TARGET_ARM)
4697     {
4698       if (!no_new_pseudos)
4699         {
4700           if (GET_CODE (operands[0]) == MEM)
4701             {
4702               if (arm_arch4)
4703                 {
4704                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4705                   DONE;
4706                 }
4707               if (GET_CODE (operands[1]) == CONST_INT)
4708                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4709               else
4710                 {
4711                   if (GET_CODE (operands[1]) == MEM)
4712                     operands[1] = force_reg (HImode, operands[1]);
4713                   if (BYTES_BIG_ENDIAN)
4714                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4715                   else
4716                    emit_insn (gen_storehi (operands[1], operands[0]));
4717                 }
4718               DONE;
4719             }
4720           /* Sign extend a constant, and keep it in an SImode reg.  */
4721           else if (GET_CODE (operands[1]) == CONST_INT)
4722             {
4723               rtx reg = gen_reg_rtx (SImode);
4724               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4726               /* If the constant is already valid, leave it alone.  */
4727               if (!const_ok_for_arm (val))
4728                 {
4729                   /* If setting all the top bits will make the constant 
4730                      loadable in a single instruction, then set them.  
4731                      Otherwise, sign extend the number.  */
4733                   if (const_ok_for_arm (~(val | ~0xffff)))
4734                     val |= ~0xffff;
4735                   else if (val & 0x8000)
4736                     val |= ~0xffff;
4737                 }
4739               emit_insn (gen_movsi (reg, GEN_INT (val)));
4740               operands[1] = gen_lowpart (HImode, reg);
4741             }
4742           else if (arm_arch4 && optimize && !no_new_pseudos
4743                    && GET_CODE (operands[1]) == MEM)
4744             {
4745               rtx reg = gen_reg_rtx (SImode);
4747               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4748               operands[1] = gen_lowpart (HImode, reg);
4749             }
4750           else if (!arm_arch4)
4751             {
4752               if (GET_CODE (operands[1]) == MEM)
4753                 {
4754                   rtx base;
4755                   rtx offset = const0_rtx;
4756                   rtx reg = gen_reg_rtx (SImode);
4758                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4759                        || (GET_CODE (base) == PLUS
4760                            && (GET_CODE (offset = XEXP (base, 1))
4761                                == CONST_INT)
4762                            && ((INTVAL(offset) & 1) != 1)
4763                            && GET_CODE (base = XEXP (base, 0)) == REG))
4764                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4765                     {
4766                       rtx new;
4768                       new = widen_memory_access (operands[1], SImode,
4769                                                  ((INTVAL (offset) & ~3)
4770                                                   - INTVAL (offset)));
4771                       emit_insn (gen_movsi (reg, new));
4772                       if (((INTVAL (offset) & 2) != 0)
4773                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4774                         {
4775                           rtx reg2 = gen_reg_rtx (SImode);
4777                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4778                           reg = reg2;
4779                         }
4780                     }
4781                   else
4782                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4784                   operands[1] = gen_lowpart (HImode, reg);
4785                }
4786            }
4787         }
4788       /* Handle loading a large integer during reload.  */
4789       else if (GET_CODE (operands[1]) == CONST_INT
4790                && !const_ok_for_arm (INTVAL (operands[1]))
4791                && !const_ok_for_arm (~INTVAL (operands[1])))
4792         {
4793           /* Writing a constant to memory needs a scratch, which should
4794              be handled with SECONDARY_RELOADs.  */
4795           gcc_assert (GET_CODE (operands[0]) == REG);
4797           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4798           emit_insn (gen_movsi (operands[0], operands[1]));
4799           DONE;
4800        }
4801     }
4802   else /* TARGET_THUMB */
4803     {
4804       if (!no_new_pseudos)
4805         {
4806           if (GET_CODE (operands[1]) == CONST_INT)
4807             {
4808               rtx reg = gen_reg_rtx (SImode);
4810               emit_insn (gen_movsi (reg, operands[1]));
4811               operands[1] = gen_lowpart (HImode, reg);
4812             }
4814           /* ??? We shouldn't really get invalid addresses here, but this can
4815              happen if we are passed a SP (never OK for HImode/QImode) or 
4816              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4817              HImode/QImode) relative address.  */
4818           /* ??? This should perhaps be fixed elsewhere, for instance, in
4819              fixup_stack_1, by checking for other kinds of invalid addresses,
4820              e.g. a bare reference to a virtual register.  This may confuse the
4821              alpha though, which must handle this case differently.  */
4822           if (GET_CODE (operands[0]) == MEM
4823               && !memory_address_p (GET_MODE (operands[0]),
4824                                     XEXP (operands[0], 0)))
4825             operands[0]
4826               = replace_equiv_address (operands[0],
4827                                        copy_to_reg (XEXP (operands[0], 0)));
4828    
4829           if (GET_CODE (operands[1]) == MEM
4830               && !memory_address_p (GET_MODE (operands[1]),
4831                                     XEXP (operands[1], 0)))
4832             operands[1]
4833               = replace_equiv_address (operands[1],
4834                                        copy_to_reg (XEXP (operands[1], 0)));
4836           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4837             {
4838               rtx reg = gen_reg_rtx (SImode);
4840               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4841               operands[1] = gen_lowpart (HImode, reg);
4842             }
4844           if (GET_CODE (operands[0]) == MEM)
4845             operands[1] = force_reg (HImode, operands[1]);
4846         }
4847       else if (GET_CODE (operands[1]) == CONST_INT
4848                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4849         {
4850           /* Handle loading a large integer during reload.  */
4852           /* Writing a constant to memory needs a scratch, which should
4853              be handled with SECONDARY_RELOADs.  */
4854           gcc_assert (GET_CODE (operands[0]) == REG);
4856           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4857           emit_insn (gen_movsi (operands[0], operands[1]));
4858           DONE;
4859         }
4860     }
4861   "
4864 (define_insn "*thumb_movhi_insn"
4865   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4866         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4867   "TARGET_THUMB
4868    && (   register_operand (operands[0], HImode)
4869        || register_operand (operands[1], HImode))"
4870   "*
4871   switch (which_alternative)
4872     {
4873     case 0: return \"add        %0, %1, #0\";
4874     case 2: return \"strh       %1, %0\";
4875     case 3: return \"mov        %0, %1\";
4876     case 4: return \"mov        %0, %1\";
4877     case 5: return \"mov        %0, %1\";
4878     default: gcc_unreachable ();
4879     case 1:
4880       /* The stack pointer can end up being taken as an index register.
4881           Catch this case here and deal with it.  */
4882       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4883           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4884           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4885         {
4886           rtx ops[2];
4887           ops[0] = operands[0];
4888           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4889       
4890           output_asm_insn (\"mov        %0, %1\", ops);
4892           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4893     
4894         }
4895       return \"ldrh     %0, %1\";
4896     }"
4897   [(set_attr "length" "2,4,2,2,2,2")
4898    (set_attr "type" "*,load1,store1,*,*,*")]
4902 (define_expand "movhi_bytes"
4903   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4904    (set (match_dup 3)
4905         (zero_extend:SI (match_dup 6)))
4906    (set (match_operand:SI 0 "" "")
4907          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4908   "TARGET_ARM"
4909   "
4910   {
4911     rtx mem1, mem2;
4912     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4914     mem1 = change_address (operands[1], QImode, addr);
4915     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4916     operands[0] = gen_lowpart (SImode, operands[0]);
4917     operands[1] = mem1;
4918     operands[2] = gen_reg_rtx (SImode);
4919     operands[3] = gen_reg_rtx (SImode);
4920     operands[6] = mem2;
4922     if (BYTES_BIG_ENDIAN)
4923       {
4924         operands[4] = operands[2];
4925         operands[5] = operands[3];
4926       }
4927     else
4928       {
4929         operands[4] = operands[3];
4930         operands[5] = operands[2];
4931       }
4932   }"
4935 (define_expand "movhi_bigend"
4936   [(set (match_dup 2)
4937         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4938                    (const_int 16)))
4939    (set (match_dup 3)
4940         (ashiftrt:SI (match_dup 2) (const_int 16)))
4941    (set (match_operand:HI 0 "s_register_operand" "")
4942         (match_dup 4))]
4943   "TARGET_ARM"
4944   "
4945   operands[2] = gen_reg_rtx (SImode);
4946   operands[3] = gen_reg_rtx (SImode);
4947   operands[4] = gen_lowpart (HImode, operands[3]);
4948   "
4951 ;; Pattern to recognize insn generated default case above
4952 (define_insn "*movhi_insn_arch4"
4953   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4954         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4955   "TARGET_ARM
4956    && arm_arch4
4957    && (GET_CODE (operands[1]) != CONST_INT
4958        || const_ok_for_arm (INTVAL (operands[1]))
4959        || const_ok_for_arm (~INTVAL (operands[1])))"
4960   "@
4961    mov%?\\t%0, %1\\t%@ movhi
4962    mvn%?\\t%0, #%B1\\t%@ movhi
4963    str%?h\\t%1, %0\\t%@ movhi
4964    ldr%?h\\t%0, %1\\t%@ movhi"
4965   [(set_attr "type" "*,*,store1,load1")
4966    (set_attr "predicable" "yes")
4967    (set_attr "pool_range" "*,*,*,256")
4968    (set_attr "neg_pool_range" "*,*,*,244")]
4971 (define_insn "*movhi_bytes"
4972   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4973         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4974   "TARGET_ARM"
4975   "@
4976    mov%?\\t%0, %1\\t%@ movhi
4977    mvn%?\\t%0, #%B1\\t%@ movhi"
4978   [(set_attr "predicable" "yes")]
4981 (define_expand "thumb_movhi_clobber"
4982   [(set (match_operand:HI     0 "memory_operand"   "")
4983         (match_operand:HI     1 "register_operand" ""))
4984    (clobber (match_operand:DI 2 "register_operand" ""))]
4985   "TARGET_THUMB"
4986   "
4987   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
4988       && REGNO (operands[1]) <= LAST_LO_REGNUM)
4989     {
4990       emit_insn (gen_movhi (operands[0], operands[1]));
4991       DONE;
4992     }
4993   /* XXX Fixme, need to handle other cases here as well.  */
4994   gcc_unreachable ();
4995   "
4997         
4998 ;; We use a DImode scratch because we may occasionally need an additional
4999 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
5000 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
5001 (define_expand "reload_outhi"
5002   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
5003               (match_operand:HI 1 "s_register_operand"        "r")
5004               (match_operand:DI 2 "s_register_operand"        "=&l")])]
5005   "TARGET_EITHER"
5006   "if (TARGET_ARM)
5007      arm_reload_out_hi (operands);
5008    else
5009      thumb_reload_out_hi (operands);
5010   DONE;
5011   "
5014 (define_expand "reload_inhi"
5015   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5016               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5017               (match_operand:DI 2 "s_register_operand" "=&r")])]
5018   "TARGET_EITHER"
5019   "
5020   if (TARGET_ARM)
5021     arm_reload_in_hi (operands);
5022   else
5023     thumb_reload_out_hi (operands);
5024   DONE;
5027 (define_expand "movqi"
5028   [(set (match_operand:QI 0 "general_operand" "")
5029         (match_operand:QI 1 "general_operand" ""))]
5030   "TARGET_EITHER"
5031   "
5032   /* Everything except mem = const or mem = mem can be done easily */
5034   if (!no_new_pseudos)
5035     {
5036       if (GET_CODE (operands[1]) == CONST_INT)
5037         {
5038           rtx reg = gen_reg_rtx (SImode);
5040           emit_insn (gen_movsi (reg, operands[1]));
5041           operands[1] = gen_lowpart (QImode, reg);
5042         }
5044       if (TARGET_THUMB)
5045         {
5046           /* ??? We shouldn't really get invalid addresses here, but this can
5047              happen if we are passed a SP (never OK for HImode/QImode) or
5048              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5049              HImode/QImode) relative address.  */
5050           /* ??? This should perhaps be fixed elsewhere, for instance, in
5051              fixup_stack_1, by checking for other kinds of invalid addresses,
5052              e.g. a bare reference to a virtual register.  This may confuse the
5053              alpha though, which must handle this case differently.  */
5054           if (GET_CODE (operands[0]) == MEM
5055               && !memory_address_p (GET_MODE (operands[0]),
5056                                      XEXP (operands[0], 0)))
5057             operands[0]
5058               = replace_equiv_address (operands[0],
5059                                        copy_to_reg (XEXP (operands[0], 0)));
5060           if (GET_CODE (operands[1]) == MEM
5061               && !memory_address_p (GET_MODE (operands[1]),
5062                                     XEXP (operands[1], 0)))
5063              operands[1]
5064                = replace_equiv_address (operands[1],
5065                                         copy_to_reg (XEXP (operands[1], 0)));
5066         }
5068       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5069         {
5070           rtx reg = gen_reg_rtx (SImode);
5072           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5073           operands[1] = gen_lowpart (QImode, reg);
5074         }
5076       if (GET_CODE (operands[0]) == MEM)
5077         operands[1] = force_reg (QImode, operands[1]);
5078     }
5079   else if (TARGET_THUMB
5080            && GET_CODE (operands[1]) == CONST_INT
5081            && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5082     {
5083       /* Handle loading a large integer during reload.  */
5085       /* Writing a constant to memory needs a scratch, which should
5086          be handled with SECONDARY_RELOADs.  */
5087       gcc_assert (GET_CODE (operands[0]) == REG);
5089       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5090       emit_insn (gen_movsi (operands[0], operands[1]));
5091       DONE;
5092     }
5093   "
5097 (define_insn "*arm_movqi_insn"
5098   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5099         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5100   "TARGET_ARM
5101    && (   register_operand (operands[0], QImode)
5102        || register_operand (operands[1], QImode))"
5103   "@
5104    mov%?\\t%0, %1
5105    mvn%?\\t%0, #%B1
5106    ldr%?b\\t%0, %1
5107    str%?b\\t%1, %0"
5108   [(set_attr "type" "*,*,load1,store1")
5109    (set_attr "predicable" "yes")]
5112 (define_insn "*thumb_movqi_insn"
5113   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5114         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5115   "TARGET_THUMB
5116    && (   register_operand (operands[0], QImode)
5117        || register_operand (operands[1], QImode))"
5118   "@
5119    add\\t%0, %1, #0
5120    ldrb\\t%0, %1
5121    strb\\t%1, %0
5122    mov\\t%0, %1
5123    mov\\t%0, %1
5124    mov\\t%0, %1"
5125   [(set_attr "length" "2")
5126    (set_attr "type" "*,load1,store1,*,*,*")
5127    (set_attr "pool_range" "*,32,*,*,*,*")]
5130 (define_expand "movsf"
5131   [(set (match_operand:SF 0 "general_operand" "")
5132         (match_operand:SF 1 "general_operand" ""))]
5133   "TARGET_EITHER"
5134   "
5135   if (TARGET_ARM)
5136     {
5137       if (GET_CODE (operands[0]) == MEM)
5138         operands[1] = force_reg (SFmode, operands[1]);
5139     }
5140   else /* TARGET_THUMB */
5141     {
5142       if (!no_new_pseudos)
5143         {
5144            if (GET_CODE (operands[0]) != REG)
5145              operands[1] = force_reg (SFmode, operands[1]);
5146         }
5147     }
5148   "
5151 ;; Transform a floating-point move of a constant into a core register into
5152 ;; an SImode operation.
5153 (define_split
5154   [(set (match_operand:SF 0 "arm_general_register_operand" "")
5155         (match_operand:SF 1 "immediate_operand" ""))]
5156   "TARGET_ARM
5157    && reload_completed
5158    && GET_CODE (operands[1]) == CONST_DOUBLE"
5159   [(set (match_dup 2) (match_dup 3))]
5160   "
5161   operands[2] = gen_lowpart (SImode, operands[0]);
5162   operands[3] = gen_lowpart (SImode, operands[1]);
5163   if (operands[2] == 0 || operands[3] == 0)
5164     FAIL;
5165   "
5168 (define_insn "*arm_movsf_soft_insn"
5169   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5170         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5171   "TARGET_ARM
5172    && TARGET_SOFT_FLOAT
5173    && (GET_CODE (operands[0]) != MEM
5174        || register_operand (operands[1], SFmode))"
5175   "@
5176    mov%?\\t%0, %1
5177    ldr%?\\t%0, %1\\t%@ float
5178    str%?\\t%1, %0\\t%@ float"
5179   [(set_attr "length" "4,4,4")
5180    (set_attr "predicable" "yes")
5181    (set_attr "type" "*,load1,store1")
5182    (set_attr "pool_range" "*,4096,*")
5183    (set_attr "neg_pool_range" "*,4084,*")]
5186 ;;; ??? This should have alternatives for constants.
5187 (define_insn "*thumb_movsf_insn"
5188   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5189         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5190   "TARGET_THUMB
5191    && (   register_operand (operands[0], SFmode) 
5192        || register_operand (operands[1], SFmode))"
5193   "@
5194    add\\t%0, %1, #0
5195    ldmia\\t%1, {%0}
5196    stmia\\t%0, {%1}
5197    ldr\\t%0, %1
5198    str\\t%1, %0
5199    mov\\t%0, %1
5200    mov\\t%0, %1"
5201   [(set_attr "length" "2")
5202    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5203    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5206 (define_expand "movdf"
5207   [(set (match_operand:DF 0 "general_operand" "")
5208         (match_operand:DF 1 "general_operand" ""))]
5209   "TARGET_EITHER"
5210   "
5211   if (TARGET_ARM)
5212     {
5213       if (GET_CODE (operands[0]) == MEM)
5214         operands[1] = force_reg (DFmode, operands[1]);
5215     }
5216   else /* TARGET_THUMB */
5217     {
5218       if (!no_new_pseudos)
5219         {
5220           if (GET_CODE (operands[0]) != REG)
5221             operands[1] = force_reg (DFmode, operands[1]);
5222         }
5223     }
5224   "
5227 ;; Reloading a df mode value stored in integer regs to memory can require a
5228 ;; scratch reg.
5229 (define_expand "reload_outdf"
5230   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5231    (match_operand:DF 1 "s_register_operand" "r")
5232    (match_operand:SI 2 "s_register_operand" "=&r")]
5233   "TARGET_ARM"
5234   "
5235   {
5236     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5238     if (code == REG)
5239       operands[2] = XEXP (operands[0], 0);
5240     else if (code == POST_INC || code == PRE_DEC)
5241       {
5242         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5243         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5244         emit_insn (gen_movdi (operands[0], operands[1]));
5245         DONE;
5246       }
5247     else if (code == PRE_INC)
5248       {
5249         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5251         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5252         operands[2] = reg;
5253       }
5254     else if (code == POST_DEC)
5255       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5256     else
5257       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5258                              XEXP (XEXP (operands[0], 0), 1)));
5260     emit_insn (gen_rtx_SET (VOIDmode,
5261                             replace_equiv_address (operands[0], operands[2]),
5262                             operands[1]));
5264     if (code == POST_DEC)
5265       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5267     DONE;
5268   }"
5271 (define_insn "*movdf_soft_insn"
5272   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5273         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5274   "TARGET_ARM && TARGET_SOFT_FLOAT
5275   "
5276   "*
5277   switch (which_alternative)
5278     {
5279     case 0:
5280     case 1:
5281     case 2:
5282       return \"#\";
5283     default:
5284       return output_move_double (operands);
5285     }
5286   "
5287   [(set_attr "length" "8,12,16,8,8")
5288    (set_attr "type" "*,*,*,load2,store2")
5289    (set_attr "pool_range" "1020")
5290    (set_attr "neg_pool_range" "1008")]
5293 ;;; ??? This should have alternatives for constants.
5294 ;;; ??? This was originally identical to the movdi_insn pattern.
5295 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5296 ;;; thumb_reorg with a memory reference.
5297 (define_insn "*thumb_movdf_insn"
5298   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5299         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5300   "TARGET_THUMB
5301    && (   register_operand (operands[0], DFmode)
5302        || register_operand (operands[1], DFmode))"
5303   "*
5304   switch (which_alternative)
5305     {
5306     default:
5307     case 0:
5308       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5309         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5310       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5311     case 1:
5312       return \"ldmia\\t%1, {%0, %H0}\";
5313     case 2:
5314       return \"stmia\\t%0, {%1, %H1}\";
5315     case 3:
5316       return thumb_load_double_from_address (operands);
5317     case 4:
5318       operands[2] = gen_rtx_MEM (SImode,
5319                                  plus_constant (XEXP (operands[0], 0), 4));
5320       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5321       return \"\";
5322     case 5:
5323       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5324         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5325       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5326     }
5327   "
5328   [(set_attr "length" "4,2,2,6,4,4")
5329    (set_attr "type" "*,load2,store2,load2,store2,*")
5330    (set_attr "pool_range" "*,*,*,1020,*,*")]
5333 (define_expand "movxf"
5334   [(set (match_operand:XF 0 "general_operand" "")
5335         (match_operand:XF 1 "general_operand" ""))]
5336   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5337   "
5338   if (GET_CODE (operands[0]) == MEM)
5339     operands[1] = force_reg (XFmode, operands[1]);
5340   "
5343 ;; Vector Moves
5344 (define_expand "movv2si"
5345   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5346         (match_operand:V2SI 1 "general_operand" ""))]
5347   "TARGET_REALLY_IWMMXT"
5351 (define_expand "movv4hi"
5352   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5353         (match_operand:V4HI 1 "general_operand" ""))]
5354   "TARGET_REALLY_IWMMXT"
5358 (define_expand "movv8qi"
5359   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5360         (match_operand:V8QI 1 "general_operand" ""))]
5361   "TARGET_REALLY_IWMMXT"
5366 ;; load- and store-multiple insns
5367 ;; The arm can load/store any set of registers, provided that they are in
5368 ;; ascending order; but that is beyond GCC so stick with what it knows.
5370 (define_expand "load_multiple"
5371   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5372                           (match_operand:SI 1 "" ""))
5373                      (use (match_operand:SI 2 "" ""))])]
5374   "TARGET_ARM"
5376   HOST_WIDE_INT offset = 0;
5378   /* Support only fixed point registers.  */
5379   if (GET_CODE (operands[2]) != CONST_INT
5380       || INTVAL (operands[2]) > 14
5381       || INTVAL (operands[2]) < 2
5382       || GET_CODE (operands[1]) != MEM
5383       || GET_CODE (operands[0]) != REG
5384       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5385       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5386     FAIL;
5388   operands[3]
5389     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5390                              force_reg (SImode, XEXP (operands[1], 0)),
5391                              TRUE, FALSE, operands[1], &offset);
5394 ;; Load multiple with write-back
5396 (define_insn "*ldmsi_postinc4"
5397   [(match_parallel 0 "load_multiple_operation"
5398     [(set (match_operand:SI 1 "s_register_operand" "=r")
5399           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5400                    (const_int 16)))
5401      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5402           (mem:SI (match_dup 2)))
5403      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5404           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5405      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5406           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5407      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5408           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5409   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5410   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5411   [(set_attr "type" "load4")
5412    (set_attr "predicable" "yes")]
5415 (define_insn "*ldmsi_postinc4_thumb"
5416   [(match_parallel 0 "load_multiple_operation"
5417     [(set (match_operand:SI 1 "s_register_operand" "=l")
5418           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5419                    (const_int 16)))
5420      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5421           (mem:SI (match_dup 2)))
5422      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5423           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5424      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5425           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5426      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5427           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5428   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5429   "ldmia\\t%1!, {%3, %4, %5, %6}"
5430   [(set_attr "type" "load4")]
5433 (define_insn "*ldmsi_postinc3"
5434   [(match_parallel 0 "load_multiple_operation"
5435     [(set (match_operand:SI 1 "s_register_operand" "=r")
5436           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5437                    (const_int 12)))
5438      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5439           (mem:SI (match_dup 2)))
5440      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5441           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5442      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5443           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5444   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5445   "ldm%?ia\\t%1!, {%3, %4, %5}"
5446   [(set_attr "type" "load3")
5447    (set_attr "predicable" "yes")]
5450 (define_insn "*ldmsi_postinc2"
5451   [(match_parallel 0 "load_multiple_operation"
5452     [(set (match_operand:SI 1 "s_register_operand" "=r")
5453           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5454                    (const_int 8)))
5455      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5456           (mem:SI (match_dup 2)))
5457      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5458           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5459   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5460   "ldm%?ia\\t%1!, {%3, %4}"
5461   [(set_attr "type" "load2")
5462    (set_attr "predicable" "yes")]
5465 ;; Ordinary load multiple
5467 (define_insn "*ldmsi4"
5468   [(match_parallel 0 "load_multiple_operation"
5469     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5470           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5471      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5472           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5473      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5474           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5475      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5476           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5477   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5478   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5479   [(set_attr "type" "load4")
5480    (set_attr "predicable" "yes")]
5483 (define_insn "*ldmsi3"
5484   [(match_parallel 0 "load_multiple_operation"
5485     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5486           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5487      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5488           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5489      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5490           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5491   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5492   "ldm%?ia\\t%1, {%2, %3, %4}"
5493   [(set_attr "type" "load3")
5494    (set_attr "predicable" "yes")]
5497 (define_insn "*ldmsi2"
5498   [(match_parallel 0 "load_multiple_operation"
5499     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5500           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5501      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5502           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5503   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5504   "ldm%?ia\\t%1, {%2, %3}"
5505   [(set_attr "type" "load2")
5506    (set_attr "predicable" "yes")]
5509 (define_expand "store_multiple"
5510   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5511                           (match_operand:SI 1 "" ""))
5512                      (use (match_operand:SI 2 "" ""))])]
5513   "TARGET_ARM"
5515   HOST_WIDE_INT offset = 0;
5517   /* Support only fixed point registers.  */
5518   if (GET_CODE (operands[2]) != CONST_INT
5519       || INTVAL (operands[2]) > 14
5520       || INTVAL (operands[2]) < 2
5521       || GET_CODE (operands[1]) != REG
5522       || GET_CODE (operands[0]) != MEM
5523       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5524       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5525     FAIL;
5527   operands[3]
5528     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5529                               force_reg (SImode, XEXP (operands[0], 0)),
5530                               TRUE, FALSE, operands[0], &offset);
5533 ;; Store multiple with write-back
5535 (define_insn "*stmsi_postinc4"
5536   [(match_parallel 0 "store_multiple_operation"
5537     [(set (match_operand:SI 1 "s_register_operand" "=r")
5538           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5539                    (const_int 16)))
5540      (set (mem:SI (match_dup 2))
5541           (match_operand:SI 3 "arm_hard_register_operand" ""))
5542      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5543           (match_operand:SI 4 "arm_hard_register_operand" ""))
5544      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5545           (match_operand:SI 5 "arm_hard_register_operand" ""))
5546      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5547           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5548   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5549   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5550   [(set_attr "predicable" "yes")
5551    (set_attr "type" "store4")]
5554 (define_insn "*stmsi_postinc4_thumb"
5555   [(match_parallel 0 "store_multiple_operation"
5556     [(set (match_operand:SI 1 "s_register_operand" "=l")
5557           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5558                    (const_int 16)))
5559      (set (mem:SI (match_dup 2))
5560           (match_operand:SI 3 "arm_hard_register_operand" ""))
5561      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5562           (match_operand:SI 4 "arm_hard_register_operand" ""))
5563      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5564           (match_operand:SI 5 "arm_hard_register_operand" ""))
5565      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5566           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5567   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5568   "stmia\\t%1!, {%3, %4, %5, %6}"
5569   [(set_attr "type" "store4")]
5572 (define_insn "*stmsi_postinc3"
5573   [(match_parallel 0 "store_multiple_operation"
5574     [(set (match_operand:SI 1 "s_register_operand" "=r")
5575           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5576                    (const_int 12)))
5577      (set (mem:SI (match_dup 2))
5578           (match_operand:SI 3 "arm_hard_register_operand" ""))
5579      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5580           (match_operand:SI 4 "arm_hard_register_operand" ""))
5581      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5582           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5583   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5584   "stm%?ia\\t%1!, {%3, %4, %5}"
5585   [(set_attr "predicable" "yes")
5586    (set_attr "type" "store3")]
5589 (define_insn "*stmsi_postinc2"
5590   [(match_parallel 0 "store_multiple_operation"
5591     [(set (match_operand:SI 1 "s_register_operand" "=r")
5592           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5593                    (const_int 8)))
5594      (set (mem:SI (match_dup 2))
5595           (match_operand:SI 3 "arm_hard_register_operand" ""))
5596      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5597           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5598   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5599   "stm%?ia\\t%1!, {%3, %4}"
5600   [(set_attr "predicable" "yes")
5601    (set_attr "type" "store2")]
5604 ;; Ordinary store multiple
5606 (define_insn "*stmsi4"
5607   [(match_parallel 0 "store_multiple_operation"
5608     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5609           (match_operand:SI 2 "arm_hard_register_operand" ""))
5610      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5611           (match_operand:SI 3 "arm_hard_register_operand" ""))
5612      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5613           (match_operand:SI 4 "arm_hard_register_operand" ""))
5614      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5615           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5616   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5617   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5618   [(set_attr "predicable" "yes")
5619    (set_attr "type" "store4")]
5622 (define_insn "*stmsi3"
5623   [(match_parallel 0 "store_multiple_operation"
5624     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5625           (match_operand:SI 2 "arm_hard_register_operand" ""))
5626      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5627           (match_operand:SI 3 "arm_hard_register_operand" ""))
5628      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5629           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5630   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5631   "stm%?ia\\t%1, {%2, %3, %4}"
5632   [(set_attr "predicable" "yes")
5633    (set_attr "type" "store3")]
5636 (define_insn "*stmsi2"
5637   [(match_parallel 0 "store_multiple_operation"
5638     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5639           (match_operand:SI 2 "arm_hard_register_operand" ""))
5640      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5641           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5642   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5643   "stm%?ia\\t%1, {%2, %3}"
5644   [(set_attr "predicable" "yes")
5645    (set_attr "type" "store2")]
5648 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5649 ;; We could let this apply for blocks of less than this, but it clobbers so
5650 ;; many registers that there is then probably a better way.
5652 (define_expand "movmemqi"
5653   [(match_operand:BLK 0 "general_operand" "")
5654    (match_operand:BLK 1 "general_operand" "")
5655    (match_operand:SI 2 "const_int_operand" "")
5656    (match_operand:SI 3 "const_int_operand" "")]
5657   "TARGET_EITHER"
5658   "
5659   if (TARGET_ARM)
5660     {
5661       if (arm_gen_movmemqi (operands))
5662         DONE;
5663       FAIL;
5664     }
5665   else /* TARGET_THUMB */
5666     {
5667       if (   INTVAL (operands[3]) != 4
5668           || INTVAL (operands[2]) > 48)
5669         FAIL;
5671       thumb_expand_movmemqi (operands);
5672       DONE;
5673     }
5674   "
5677 ;; Thumb block-move insns
5679 (define_insn "movmem12b"
5680   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5681         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5682    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5683         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5684    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5685         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5686    (set (match_operand:SI 0 "register_operand" "=l")
5687         (plus:SI (match_dup 2) (const_int 12)))
5688    (set (match_operand:SI 1 "register_operand" "=l")
5689         (plus:SI (match_dup 3) (const_int 12)))
5690    (clobber (match_scratch:SI 4 "=&l"))
5691    (clobber (match_scratch:SI 5 "=&l"))
5692    (clobber (match_scratch:SI 6 "=&l"))]
5693   "TARGET_THUMB"
5694   "* return thumb_output_move_mem_multiple (3, operands);"
5695   [(set_attr "length" "4")
5696    ; This isn't entirely accurate...  It loads as well, but in terms of
5697    ; scheduling the following insn it is better to consider it as a store
5698    (set_attr "type" "store3")]
5701 (define_insn "movmem8b"
5702   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5703         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5704    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5705         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5706    (set (match_operand:SI 0 "register_operand" "=l")
5707         (plus:SI (match_dup 2) (const_int 8)))
5708    (set (match_operand:SI 1 "register_operand" "=l")
5709         (plus:SI (match_dup 3) (const_int 8)))
5710    (clobber (match_scratch:SI 4 "=&l"))
5711    (clobber (match_scratch:SI 5 "=&l"))]
5712   "TARGET_THUMB"
5713   "* return thumb_output_move_mem_multiple (2, operands);"
5714   [(set_attr "length" "4")
5715    ; This isn't entirely accurate...  It loads as well, but in terms of
5716    ; scheduling the following insn it is better to consider it as a store
5717    (set_attr "type" "store2")]
5722 ;; Compare & branch insns
5723 ;; The range calculations are based as follows:
5724 ;; For forward branches, the address calculation returns the address of
5725 ;; the next instruction.  This is 2 beyond the branch instruction.
5726 ;; For backward branches, the address calculation returns the address of
5727 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5728 ;; instruction for the shortest sequence, and 4 before the branch instruction
5729 ;; if we have to jump around an unconditional branch.
5730 ;; To the basic branch range the PC offset must be added (this is +4).
5731 ;; So for forward branches we have 
5732 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5733 ;; And for backward branches we have 
5734 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5736 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5737 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5739 (define_expand "cbranchsi4"
5740   [(set (pc) (if_then_else
5741               (match_operator 0 "arm_comparison_operator"
5742                [(match_operand:SI 1 "s_register_operand" "")
5743                 (match_operand:SI 2 "nonmemory_operand" "")])
5744               (label_ref (match_operand 3 "" ""))
5745               (pc)))]
5746   "TARGET_THUMB"
5747   "
5748   if (thumb_cmpneg_operand (operands[2], SImode))
5749     {
5750       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5751                                               operands[3], operands[0]));
5752       DONE;
5753     }
5754   if (!thumb_cmp_operand (operands[2], SImode))
5755     operands[2] = force_reg (SImode, operands[2]);
5756   ")
5758 (define_insn "*cbranchsi4_insn"
5759   [(set (pc) (if_then_else
5760               (match_operator 0 "arm_comparison_operator"
5761                [(match_operand:SI 1 "s_register_operand" "l,*h")
5762                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5763               (label_ref (match_operand 3 "" ""))
5764               (pc)))]
5765   "TARGET_THUMB"
5766   "*
5767   output_asm_insn (\"cmp\\t%1, %2\", operands);
5769   switch (get_attr_length (insn))
5770     {
5771     case 4:  return \"b%d0\\t%l3\";
5772     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5773     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5774     }
5775   "
5776   [(set (attr "far_jump")
5777         (if_then_else
5778             (eq_attr "length" "8")
5779             (const_string "yes")
5780             (const_string "no")))
5781    (set (attr "length") 
5782         (if_then_else
5783             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5784                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5785             (const_int 4)
5786             (if_then_else
5787                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5788                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5789                 (const_int 6)
5790                 (const_int 8))))]
5793 (define_insn "cbranchsi4_scratch"
5794   [(set (pc) (if_then_else
5795               (match_operator 4 "arm_comparison_operator"
5796                [(match_operand:SI 1 "s_register_operand" "l,0")
5797                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5798               (label_ref (match_operand 3 "" ""))
5799               (pc)))
5800    (clobber (match_scratch:SI 0 "=l,l"))]
5801   "TARGET_THUMB"
5802   "*
5803   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5805   switch (get_attr_length (insn))
5806     {
5807     case 4:  return \"b%d4\\t%l3\";
5808     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5809     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5810     }
5811   "
5812   [(set (attr "far_jump")
5813         (if_then_else
5814             (eq_attr "length" "8")
5815             (const_string "yes")
5816             (const_string "no")))
5817    (set (attr "length") 
5818         (if_then_else
5819             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5820                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5821             (const_int 4)
5822             (if_then_else
5823                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5824                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5825                 (const_int 6)
5826                 (const_int 8))))]
5828 (define_insn "*movsi_cbranchsi4"
5829   [(set (pc)
5830         (if_then_else
5831          (match_operator 3 "arm_comparison_operator"
5832           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5833            (const_int 0)])
5834          (label_ref (match_operand 2 "" ""))
5835          (pc)))
5836    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5837         (match_dup 1))]
5838   "TARGET_THUMB"
5839   "*{
5840   if (which_alternative == 0)
5841     output_asm_insn (\"cmp\t%0, #0\", operands);
5842   else if (which_alternative == 1)
5843     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5844   else
5845     {
5846       output_asm_insn (\"cmp\t%1, #0\", operands);
5847       if (which_alternative == 2)
5848         output_asm_insn (\"mov\t%0, %1\", operands);
5849       else
5850         output_asm_insn (\"str\t%1, %0\", operands);
5851     }
5852   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5853     {
5854     case 4:  return \"b%d3\\t%l2\";
5855     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5856     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5857     }
5858   }"
5859   [(set (attr "far_jump")
5860         (if_then_else
5861             (ior (and (gt (symbol_ref ("which_alternative"))
5862                           (const_int 1))
5863                       (eq_attr "length" "8"))
5864                  (eq_attr "length" "10"))
5865             (const_string "yes")
5866             (const_string "no")))
5867    (set (attr "length")
5868      (if_then_else
5869        (le (symbol_ref ("which_alternative"))
5870                        (const_int 1))
5871        (if_then_else
5872          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5873               (le (minus (match_dup 2) (pc)) (const_int 256)))
5874          (const_int 4)
5875          (if_then_else
5876            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5877                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5878            (const_int 6)
5879            (const_int 8)))
5880        (if_then_else
5881          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5882               (le (minus (match_dup 2) (pc)) (const_int 256)))
5883          (const_int 6)
5884          (if_then_else
5885            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5886                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5887            (const_int 8)
5888            (const_int 10)))))]
5891 (define_insn "*negated_cbranchsi4"
5892   [(set (pc)
5893         (if_then_else
5894          (match_operator 0 "equality_operator"
5895           [(match_operand:SI 1 "s_register_operand" "l")
5896            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5897          (label_ref (match_operand 3 "" ""))
5898          (pc)))]
5899   "TARGET_THUMB"
5900   "*
5901   output_asm_insn (\"cmn\\t%1, %2\", operands);
5902   switch (get_attr_length (insn))
5903     {
5904     case 4:  return \"b%d0\\t%l3\";
5905     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5906     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5907     }
5908   "
5909   [(set (attr "far_jump")
5910         (if_then_else
5911             (eq_attr "length" "8")
5912             (const_string "yes")
5913             (const_string "no")))
5914    (set (attr "length") 
5915         (if_then_else
5916             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5917                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5918             (const_int 4)
5919             (if_then_else
5920                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5921                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5922                 (const_int 6)
5923                 (const_int 8))))]
5926 (define_insn "*tbit_cbranch"
5927   [(set (pc)
5928         (if_then_else
5929          (match_operator 0 "equality_operator"
5930           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5931                             (const_int 1)
5932                             (match_operand:SI 2 "const_int_operand" "i"))
5933            (const_int 0)])
5934          (label_ref (match_operand 3 "" ""))
5935          (pc)))
5936    (clobber (match_scratch:SI 4 "=l"))]
5937   "TARGET_THUMB"
5938   "*
5939   {
5940   rtx op[3];
5941   op[0] = operands[4];
5942   op[1] = operands[1];
5943   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5945   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5946   switch (get_attr_length (insn))
5947     {
5948     case 4:  return \"b%d0\\t%l3\";
5949     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5950     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5951     }
5952   }"
5953   [(set (attr "far_jump")
5954         (if_then_else
5955             (eq_attr "length" "8")
5956             (const_string "yes")
5957             (const_string "no")))
5958    (set (attr "length") 
5959         (if_then_else
5960             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5961                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5962             (const_int 4)
5963             (if_then_else
5964                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5965                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5966                 (const_int 6)
5967                 (const_int 8))))]
5969   
5970 (define_insn "*tstsi3_cbranch"
5971   [(set (pc)
5972         (if_then_else
5973          (match_operator 3 "equality_operator"
5974           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5975                    (match_operand:SI 1 "s_register_operand" "l"))
5976            (const_int 0)])
5977          (label_ref (match_operand 2 "" ""))
5978          (pc)))]
5979   "TARGET_THUMB"
5980   "*
5981   {
5982   output_asm_insn (\"tst\\t%0, %1\", operands);
5983   switch (get_attr_length (insn))
5984     {
5985     case 4:  return \"b%d3\\t%l2\";
5986     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5987     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5988     }
5989   }"
5990   [(set (attr "far_jump")
5991         (if_then_else
5992             (eq_attr "length" "8")
5993             (const_string "yes")
5994             (const_string "no")))
5995    (set (attr "length") 
5996         (if_then_else
5997             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5998                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5999             (const_int 4)
6000             (if_then_else
6001                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
6002                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
6003                 (const_int 6)
6004                 (const_int 8))))]
6006   
6007 (define_insn "*andsi3_cbranch"
6008   [(set (pc)
6009         (if_then_else
6010          (match_operator 5 "equality_operator"
6011           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6012                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6013            (const_int 0)])
6014          (label_ref (match_operand 4 "" ""))
6015          (pc)))
6016    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6017         (and:SI (match_dup 2) (match_dup 3)))
6018    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6019   "TARGET_THUMB"
6020   "*
6021   {
6022   if (which_alternative == 0)
6023     output_asm_insn (\"and\\t%0, %3\", operands);
6024   else if (which_alternative == 1)
6025     {
6026       output_asm_insn (\"and\\t%1, %3\", operands);
6027       output_asm_insn (\"mov\\t%0, %1\", operands);
6028     }
6029   else
6030     {
6031       output_asm_insn (\"and\\t%1, %3\", operands);
6032       output_asm_insn (\"str\\t%1, %0\", operands);
6033     }
6035   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6036     {
6037     case 4:  return \"b%d5\\t%l4\";
6038     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6039     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6040     }
6041   }"
6042   [(set (attr "far_jump")
6043         (if_then_else
6044             (ior (and (eq (symbol_ref ("which_alternative"))
6045                           (const_int 0))
6046                       (eq_attr "length" "8"))
6047                  (eq_attr "length" "10"))
6048             (const_string "yes")
6049             (const_string "no")))
6050    (set (attr "length")
6051      (if_then_else
6052        (eq (symbol_ref ("which_alternative"))
6053                        (const_int 0))
6054        (if_then_else
6055          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6056               (le (minus (match_dup 4) (pc)) (const_int 256)))
6057          (const_int 4)
6058          (if_then_else
6059            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6060                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6061            (const_int 6)
6062            (const_int 8)))
6063        (if_then_else
6064          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6065               (le (minus (match_dup 4) (pc)) (const_int 256)))
6066          (const_int 6)
6067          (if_then_else
6068            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6069                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6070            (const_int 8)
6071            (const_int 10)))))]
6074 (define_insn "*orrsi3_cbranch_scratch"
6075   [(set (pc)
6076         (if_then_else
6077          (match_operator 4 "equality_operator"
6078           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6079                    (match_operand:SI 2 "s_register_operand" "l"))
6080            (const_int 0)])
6081          (label_ref (match_operand 3 "" ""))
6082          (pc)))
6083    (clobber (match_scratch:SI 0 "=l"))]
6084   "TARGET_THUMB"
6085   "*
6086   {
6087   output_asm_insn (\"orr\\t%0, %2\", operands);
6088   switch (get_attr_length (insn))
6089     {
6090     case 4:  return \"b%d4\\t%l3\";
6091     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6092     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\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 3) (pc)) (const_int -250))
6103                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6104             (const_int 4)
6105             (if_then_else
6106                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6107                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6108                 (const_int 6)
6109                 (const_int 8))))]
6111   
6112 (define_insn "*orrsi3_cbranch"
6113   [(set (pc)
6114         (if_then_else
6115          (match_operator 5 "equality_operator"
6116           [(ior: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         (ior: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 (\"orr\\t%0, %3\", operands);
6129   else if (which_alternative == 1)
6130     {
6131       output_asm_insn (\"orr\\t%1, %3\", operands);
6132       output_asm_insn (\"mov\\t%0, %1\", operands);
6133     }
6134   else
6135     {
6136       output_asm_insn (\"orr\\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 "*xorsi3_cbranch_scratch"
6180   [(set (pc)
6181         (if_then_else
6182          (match_operator 4 "equality_operator"
6183           [(xor: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 (\"eor\\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 "*xorsi3_cbranch"
6218   [(set (pc)
6219         (if_then_else
6220          (match_operator 5 "equality_operator"
6221           [(xor: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         (xor: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 (\"eor\\t%0, %3\", operands);
6234   else if (which_alternative == 1)
6235     {
6236       output_asm_insn (\"eor\\t%1, %3\", operands);
6237       output_asm_insn (\"mov\\t%0, %1\", operands);
6238     }
6239   else
6240     {
6241       output_asm_insn (\"eor\\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 "*bicsi3_cbranch_scratch"
6285   [(set (pc)
6286         (if_then_else
6287          (match_operator 4 "equality_operator"
6288           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6289                    (match_operand:SI 1 "s_register_operand" "0"))
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 (\"bic\\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 "*bicsi3_cbranch"
6323   [(set (pc)
6324         (if_then_else
6325          (match_operator 5 "equality_operator"
6326           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6327                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6328            (const_int 0)])
6329          (label_ref (match_operand 4 "" ""))
6330          (pc)))
6331    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6332         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6333    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6334   "TARGET_THUMB"
6335   "*
6336   {
6337   if (which_alternative == 0)
6338     output_asm_insn (\"bic\\t%0, %3\", operands);
6339   else if (which_alternative <= 2)
6340     {
6341       output_asm_insn (\"bic\\t%1, %3\", operands);
6342       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6343          conditions again, since we're only testing for equality.  */
6344       output_asm_insn (\"mov\\t%0, %1\", operands);
6345     }
6346   else
6347     {
6348       output_asm_insn (\"bic\\t%1, %3\", operands);
6349       output_asm_insn (\"str\\t%1, %0\", operands);
6350     }
6352   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6353     {
6354     case 4:  return \"b%d5\\t%l4\";
6355     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6356     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6357     }
6358   }"
6359   [(set (attr "far_jump")
6360         (if_then_else
6361             (ior (and (eq (symbol_ref ("which_alternative"))
6362                           (const_int 0))
6363                       (eq_attr "length" "8"))
6364                  (eq_attr "length" "10"))
6365             (const_string "yes")
6366             (const_string "no")))
6367    (set (attr "length")
6368      (if_then_else
6369        (eq (symbol_ref ("which_alternative"))
6370                        (const_int 0))
6371        (if_then_else
6372          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6373               (le (minus (match_dup 4) (pc)) (const_int 256)))
6374          (const_int 4)
6375          (if_then_else
6376            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6377                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6378            (const_int 6)
6379            (const_int 8)))
6380        (if_then_else
6381          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6382               (le (minus (match_dup 4) (pc)) (const_int 256)))
6383          (const_int 6)
6384          (if_then_else
6385            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6386                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6387            (const_int 8)
6388            (const_int 10)))))]
6391 (define_insn "*cbranchne_decr1"
6392   [(set (pc)
6393         (if_then_else (match_operator 3 "equality_operator"
6394                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6395                         (const_int 0)])
6396                       (label_ref (match_operand 4 "" ""))
6397                       (pc)))
6398    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6399         (plus:SI (match_dup 2) (const_int -1)))
6400    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6401   "TARGET_THUMB"
6402   "*
6403    {
6404      rtx cond[2];
6405      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6406                                 ? GEU : LTU),
6407                                VOIDmode, operands[2], const1_rtx);
6408      cond[1] = operands[4];
6410      if (which_alternative == 0)
6411        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6412      else if (which_alternative == 1)
6413        {
6414          /* We must provide an alternative for a hi reg because reload 
6415             cannot handle output reloads on a jump instruction, but we
6416             can't subtract into that.  Fortunately a mov from lo to hi
6417             does not clobber the condition codes.  */
6418          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6419          output_asm_insn (\"mov\\t%0, %1\", operands);
6420        }
6421      else
6422        {
6423          /* Similarly, but the target is memory.  */
6424          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6425          output_asm_insn (\"str\\t%1, %0\", operands);
6426        }
6428      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6429        {
6430          case 4:
6431            output_asm_insn (\"b%d0\\t%l1\", cond);
6432            return \"\";
6433          case 6:
6434            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6435            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6436          default:
6437            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6438            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6439        }
6440    }
6441   "
6442   [(set (attr "far_jump")
6443         (if_then_else
6444             (ior (and (eq (symbol_ref ("which_alternative"))
6445                           (const_int 0))
6446                       (eq_attr "length" "8"))
6447                  (eq_attr "length" "10"))
6448             (const_string "yes")
6449             (const_string "no")))
6450    (set_attr_alternative "length"
6451       [
6452        ;; Alternative 0
6453        (if_then_else
6454          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6455               (le (minus (match_dup 4) (pc)) (const_int 256)))
6456          (const_int 4)
6457          (if_then_else
6458            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6459                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6460            (const_int 6)
6461            (const_int 8)))
6462        ;; Alternative 1
6463        (if_then_else
6464          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6465               (le (minus (match_dup 4) (pc)) (const_int 256)))
6466          (const_int 6)
6467          (if_then_else
6468            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6469                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6470            (const_int 8)
6471            (const_int 10)))
6472        ;; Alternative 2
6473        (if_then_else
6474          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6475               (le (minus (match_dup 4) (pc)) (const_int 256)))
6476          (const_int 6)
6477          (if_then_else
6478            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6479                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6480            (const_int 8)
6481            (const_int 10)))
6482        ;; Alternative 3
6483        (if_then_else
6484          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6485               (le (minus (match_dup 4) (pc)) (const_int 256)))
6486          (const_int 6)
6487          (if_then_else
6488            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6489                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6490            (const_int 8)
6491            (const_int 10)))])]
6494 (define_insn "*addsi3_cbranch"
6495   [(set (pc)
6496         (if_then_else
6497          (match_operator 4 "comparison_operator"
6498           [(plus:SI
6499             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6500             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6501            (const_int 0)])
6502          (label_ref (match_operand 5 "" ""))
6503          (pc)))
6504    (set
6505     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6506     (plus:SI (match_dup 2) (match_dup 3)))
6507    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6508   "TARGET_THUMB
6509    && (GET_CODE (operands[4]) == EQ
6510        || GET_CODE (operands[4]) == NE
6511        || GET_CODE (operands[4]) == GE
6512        || GET_CODE (operands[4]) == LT)"
6513   "*
6514    {
6515      rtx cond[3];
6517      
6518      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6519      cond[1] = operands[2];
6520      cond[2] = operands[3];
6522      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6523        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6524      else
6525        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6527      if (which_alternative >= 3
6528          && which_alternative < 4)
6529        output_asm_insn (\"mov\\t%0, %1\", operands);
6530      else if (which_alternative >= 4)
6531        output_asm_insn (\"str\\t%1, %0\", operands);
6533      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6534        {
6535          case 4:
6536            return \"b%d4\\t%l5\";
6537          case 6:
6538            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6539          default:
6540            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6541        }
6542    }
6543   "
6544   [(set (attr "far_jump")
6545         (if_then_else
6546             (ior (and (lt (symbol_ref ("which_alternative"))
6547                           (const_int 3))
6548                       (eq_attr "length" "8"))
6549                  (eq_attr "length" "10"))
6550             (const_string "yes")
6551             (const_string "no")))
6552    (set (attr "length")
6553      (if_then_else
6554        (lt (symbol_ref ("which_alternative"))
6555                        (const_int 3))
6556        (if_then_else
6557          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6558               (le (minus (match_dup 5) (pc)) (const_int 256)))
6559          (const_int 4)
6560          (if_then_else
6561            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6562                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6563            (const_int 6)
6564            (const_int 8)))
6565        (if_then_else
6566          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6567               (le (minus (match_dup 5) (pc)) (const_int 256)))
6568          (const_int 6)
6569          (if_then_else
6570            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6571                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6572            (const_int 8)
6573            (const_int 10)))))]
6576 (define_insn "*addsi3_cbranch_scratch"
6577   [(set (pc)
6578         (if_then_else
6579          (match_operator 3 "comparison_operator"
6580           [(plus:SI
6581             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6582             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6583            (const_int 0)])
6584          (label_ref (match_operand 4 "" ""))
6585          (pc)))
6586    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6587   "TARGET_THUMB
6588    && (GET_CODE (operands[3]) == EQ
6589        || GET_CODE (operands[3]) == NE
6590        || GET_CODE (operands[3]) == GE
6591        || GET_CODE (operands[3]) == LT)"
6592   "*
6593    {
6594      switch (which_alternative)
6595        {
6596        case 0:
6597          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6598          break;
6599        case 1:
6600          output_asm_insn (\"cmn\t%1, %2\", operands);
6601          break;
6602        case 2:
6603          if (INTVAL (operands[2]) < 0)
6604            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6605          else
6606            output_asm_insn (\"add\t%0, %1, %2\", operands);
6607          break;
6608        case 3:
6609          if (INTVAL (operands[2]) < 0)
6610            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6611          else
6612            output_asm_insn (\"add\t%0, %0, %2\", operands);
6613          break;
6614        }
6616      switch (get_attr_length (insn))
6617        {
6618          case 4:
6619            return \"b%d3\\t%l4\";
6620          case 6:
6621            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6622          default:
6623            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6624        }
6625    }
6626   "
6627   [(set (attr "far_jump")
6628         (if_then_else
6629             (eq_attr "length" "8")
6630             (const_string "yes")
6631             (const_string "no")))
6632    (set (attr "length")
6633        (if_then_else
6634          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6635               (le (minus (match_dup 4) (pc)) (const_int 256)))
6636          (const_int 4)
6637          (if_then_else
6638            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6639                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6640            (const_int 6)
6641            (const_int 8))))]
6644 (define_insn "*subsi3_cbranch"
6645   [(set (pc)
6646         (if_then_else
6647          (match_operator 4 "comparison_operator"
6648           [(minus:SI
6649             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6650             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6651            (const_int 0)])
6652          (label_ref (match_operand 5 "" ""))
6653          (pc)))
6654    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6655         (minus:SI (match_dup 2) (match_dup 3)))
6656    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6657   "TARGET_THUMB
6658    && (GET_CODE (operands[4]) == EQ
6659        || GET_CODE (operands[4]) == NE
6660        || GET_CODE (operands[4]) == GE
6661        || GET_CODE (operands[4]) == LT)"
6662   "*
6663    {
6664      if (which_alternative == 0)
6665        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6666      else if (which_alternative == 1)
6667        {
6668          /* We must provide an alternative for a hi reg because reload 
6669             cannot handle output reloads on a jump instruction, but we
6670             can't subtract into that.  Fortunately a mov from lo to hi
6671             does not clobber the condition codes.  */
6672          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6673          output_asm_insn (\"mov\\t%0, %1\", operands);
6674        }
6675      else
6676        {
6677          /* Similarly, but the target is memory.  */
6678          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6679          output_asm_insn (\"str\\t%1, %0\", operands);
6680        }
6682      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6683        {
6684          case 4:
6685            return \"b%d4\\t%l5\";
6686          case 6:
6687            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6688          default:
6689            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6690        }
6691    }
6692   "
6693   [(set (attr "far_jump")
6694         (if_then_else
6695             (ior (and (eq (symbol_ref ("which_alternative"))
6696                           (const_int 0))
6697                       (eq_attr "length" "8"))
6698                  (eq_attr "length" "10"))
6699             (const_string "yes")
6700             (const_string "no")))
6701    (set (attr "length")
6702      (if_then_else
6703        (eq (symbol_ref ("which_alternative"))
6704                        (const_int 0))
6705        (if_then_else
6706          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6707               (le (minus (match_dup 5) (pc)) (const_int 256)))
6708          (const_int 4)
6709          (if_then_else
6710            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6711                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6712            (const_int 6)
6713            (const_int 8)))
6714        (if_then_else
6715          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6716               (le (minus (match_dup 5) (pc)) (const_int 256)))
6717          (const_int 6)
6718          (if_then_else
6719            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6720                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6721            (const_int 8)
6722            (const_int 10)))))]
6725 (define_insn "*subsi3_cbranch_scratch"
6726   [(set (pc)
6727         (if_then_else
6728          (match_operator 0 "arm_comparison_operator"
6729           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6730                      (match_operand:SI 2 "nonmemory_operand" "l"))
6731            (const_int 0)])
6732          (label_ref (match_operand 3 "" ""))
6733          (pc)))]
6734   "TARGET_THUMB
6735    && (GET_CODE (operands[0]) == EQ
6736        || GET_CODE (operands[0]) == NE
6737        || GET_CODE (operands[0]) == GE
6738        || GET_CODE (operands[0]) == LT)"
6739   "*
6740   output_asm_insn (\"cmp\\t%1, %2\", operands);
6741   switch (get_attr_length (insn))
6742     {
6743     case 4:  return \"b%d0\\t%l3\";
6744     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6745     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6746     }
6747   "
6748   [(set (attr "far_jump")
6749         (if_then_else
6750             (eq_attr "length" "8")
6751             (const_string "yes")
6752             (const_string "no")))
6753    (set (attr "length") 
6754         (if_then_else
6755             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6756                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6757             (const_int 4)
6758             (if_then_else
6759                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6760                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6761                 (const_int 6)
6762                 (const_int 8))))]
6765 ;; Comparison and test insns
6767 (define_expand "cmpsi"
6768   [(match_operand:SI 0 "s_register_operand" "")
6769    (match_operand:SI 1 "arm_add_operand" "")]
6770   "TARGET_ARM"
6771   "{
6772     arm_compare_op0 = operands[0];
6773     arm_compare_op1 = operands[1];
6774     DONE;
6775   }"
6778 (define_expand "cmpsf"
6779   [(match_operand:SF 0 "s_register_operand" "")
6780    (match_operand:SF 1 "arm_float_compare_operand" "")]
6781   "TARGET_ARM && TARGET_HARD_FLOAT"
6782   "
6783   arm_compare_op0 = operands[0];
6784   arm_compare_op1 = operands[1];
6785   DONE;
6786   "
6789 (define_expand "cmpdf"
6790   [(match_operand:DF 0 "s_register_operand" "")
6791    (match_operand:DF 1 "arm_float_compare_operand" "")]
6792   "TARGET_ARM && TARGET_HARD_FLOAT"
6793   "
6794   arm_compare_op0 = operands[0];
6795   arm_compare_op1 = operands[1];
6796   DONE;
6797   "
6800 (define_insn "*arm_cmpsi_insn"
6801   [(set (reg:CC CC_REGNUM)
6802         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6803                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6804   "TARGET_ARM"
6805   "@
6806    cmp%?\\t%0, %1
6807    cmn%?\\t%0, #%n1"
6808   [(set_attr "conds" "set")]
6811 (define_insn "*cmpsi_shiftsi"
6812   [(set (reg:CC CC_REGNUM)
6813         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6814                     (match_operator:SI  3 "shift_operator"
6815                      [(match_operand:SI 1 "s_register_operand" "r")
6816                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6817   "TARGET_ARM"
6818   "cmp%?\\t%0, %1%S3"
6819   [(set_attr "conds" "set")
6820    (set_attr "shift" "1")
6821    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6822                       (const_string "alu_shift")
6823                       (const_string "alu_shift_reg")))]
6826 (define_insn "*cmpsi_shiftsi_swp"
6827   [(set (reg:CC_SWP CC_REGNUM)
6828         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6829                          [(match_operand:SI 1 "s_register_operand" "r")
6830                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6831                         (match_operand:SI 0 "s_register_operand" "r")))]
6832   "TARGET_ARM"
6833   "cmp%?\\t%0, %1%S3"
6834   [(set_attr "conds" "set")
6835    (set_attr "shift" "1")
6836    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6837                       (const_string "alu_shift")
6838                       (const_string "alu_shift_reg")))]
6841 (define_insn "*cmpsi_negshiftsi_si"
6842   [(set (reg:CC_Z CC_REGNUM)
6843         (compare:CC_Z
6844          (neg:SI (match_operator:SI 1 "shift_operator"
6845                     [(match_operand:SI 2 "s_register_operand" "r")
6846                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6847          (match_operand:SI 0 "s_register_operand" "r")))]
6848   "TARGET_ARM"
6849   "cmn%?\\t%0, %2%S1"
6850   [(set_attr "conds" "set")
6851    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6852                                     (const_string "alu_shift")
6853                                     (const_string "alu_shift_reg")))]
6856 ;; Cirrus SF compare instruction
6857 (define_insn "*cirrus_cmpsf"
6858   [(set (reg:CCFP CC_REGNUM)
6859         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6860                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6861   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6862   "cfcmps%?\\tr15, %V0, %V1"
6863   [(set_attr "type"   "mav_farith")
6864    (set_attr "cirrus" "compare")]
6867 ;; Cirrus DF compare instruction
6868 (define_insn "*cirrus_cmpdf"
6869   [(set (reg:CCFP CC_REGNUM)
6870         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6871                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6872   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6873   "cfcmpd%?\\tr15, %V0, %V1"
6874   [(set_attr "type"   "mav_farith")
6875    (set_attr "cirrus" "compare")]
6878 ;; Cirrus DI compare instruction
6879 (define_expand "cmpdi"
6880   [(match_operand:DI 0 "cirrus_fp_register" "")
6881    (match_operand:DI 1 "cirrus_fp_register" "")]
6882   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6883   "{
6884      arm_compare_op0 = operands[0];
6885      arm_compare_op1 = operands[1];
6886      DONE;
6887    }")
6889 (define_insn "*cirrus_cmpdi"
6890   [(set (reg:CC CC_REGNUM)
6891         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6892                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6893   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6894   "cfcmp64%?\\tr15, %V0, %V1"
6895   [(set_attr "type"   "mav_farith")
6896    (set_attr "cirrus" "compare")]
6899 ; This insn allows redundant compares to be removed by cse, nothing should
6900 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6901 ; is deleted later on. The match_dup will match the mode here, so that
6902 ; mode changes of the condition codes aren't lost by this even though we don't
6903 ; specify what they are.
6905 (define_insn "*deleted_compare"
6906   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6907   "TARGET_ARM"
6908   "\\t%@ deleted compare"
6909   [(set_attr "conds" "set")
6910    (set_attr "length" "0")]
6914 ;; Conditional branch insns
6916 (define_expand "beq"
6917   [(set (pc)
6918         (if_then_else (eq (match_dup 1) (const_int 0))
6919                       (label_ref (match_operand 0 "" ""))
6920                       (pc)))]
6921   "TARGET_ARM"
6922   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6925 (define_expand "bne"
6926   [(set (pc)
6927         (if_then_else (ne (match_dup 1) (const_int 0))
6928                       (label_ref (match_operand 0 "" ""))
6929                       (pc)))]
6930   "TARGET_ARM"
6931   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6934 (define_expand "bgt"
6935   [(set (pc)
6936         (if_then_else (gt (match_dup 1) (const_int 0))
6937                       (label_ref (match_operand 0 "" ""))
6938                       (pc)))]
6939   "TARGET_ARM"
6940   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6943 (define_expand "ble"
6944   [(set (pc)
6945         (if_then_else (le (match_dup 1) (const_int 0))
6946                       (label_ref (match_operand 0 "" ""))
6947                       (pc)))]
6948   "TARGET_ARM"
6949   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6952 (define_expand "bge"
6953   [(set (pc)
6954         (if_then_else (ge (match_dup 1) (const_int 0))
6955                       (label_ref (match_operand 0 "" ""))
6956                       (pc)))]
6957   "TARGET_ARM"
6958   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6961 (define_expand "blt"
6962   [(set (pc)
6963         (if_then_else (lt (match_dup 1) (const_int 0))
6964                       (label_ref (match_operand 0 "" ""))
6965                       (pc)))]
6966   "TARGET_ARM"
6967   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6970 (define_expand "bgtu"
6971   [(set (pc)
6972         (if_then_else (gtu (match_dup 1) (const_int 0))
6973                       (label_ref (match_operand 0 "" ""))
6974                       (pc)))]
6975   "TARGET_ARM"
6976   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6979 (define_expand "bleu"
6980   [(set (pc)
6981         (if_then_else (leu (match_dup 1) (const_int 0))
6982                       (label_ref (match_operand 0 "" ""))
6983                       (pc)))]
6984   "TARGET_ARM"
6985   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6988 (define_expand "bgeu"
6989   [(set (pc)
6990         (if_then_else (geu (match_dup 1) (const_int 0))
6991                       (label_ref (match_operand 0 "" ""))
6992                       (pc)))]
6993   "TARGET_ARM"
6994   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6997 (define_expand "bltu"
6998   [(set (pc)
6999         (if_then_else (ltu (match_dup 1) (const_int 0))
7000                       (label_ref (match_operand 0 "" ""))
7001                       (pc)))]
7002   "TARGET_ARM"
7003   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7006 (define_expand "bunordered"
7007   [(set (pc)
7008         (if_then_else (unordered (match_dup 1) (const_int 0))
7009                       (label_ref (match_operand 0 "" ""))
7010                       (pc)))]
7011   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7012   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7013                                       arm_compare_op1);"
7016 (define_expand "bordered"
7017   [(set (pc)
7018         (if_then_else (ordered (match_dup 1) (const_int 0))
7019                       (label_ref (match_operand 0 "" ""))
7020                       (pc)))]
7021   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7022   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7023                                       arm_compare_op1);"
7026 (define_expand "bungt"
7027   [(set (pc)
7028         (if_then_else (ungt (match_dup 1) (const_int 0))
7029                       (label_ref (match_operand 0 "" ""))
7030                       (pc)))]
7031   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7032   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7035 (define_expand "bunlt"
7036   [(set (pc)
7037         (if_then_else (unlt (match_dup 1) (const_int 0))
7038                       (label_ref (match_operand 0 "" ""))
7039                       (pc)))]
7040   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7041   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7044 (define_expand "bunge"
7045   [(set (pc)
7046         (if_then_else (unge (match_dup 1) (const_int 0))
7047                       (label_ref (match_operand 0 "" ""))
7048                       (pc)))]
7049   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7050   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7053 (define_expand "bunle"
7054   [(set (pc)
7055         (if_then_else (unle (match_dup 1) (const_int 0))
7056                       (label_ref (match_operand 0 "" ""))
7057                       (pc)))]
7058   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7059   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7062 ;; The following two patterns need two branch instructions, since there is
7063 ;; no single instruction that will handle all cases.
7064 (define_expand "buneq"
7065   [(set (pc)
7066         (if_then_else (uneq (match_dup 1) (const_int 0))
7067                       (label_ref (match_operand 0 "" ""))
7068                       (pc)))]
7069   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7070   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
7073 (define_expand "bltgt"
7074   [(set (pc)
7075         (if_then_else (ltgt (match_dup 1) (const_int 0))
7076                       (label_ref (match_operand 0 "" ""))
7077                       (pc)))]
7078   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7079   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7083 ;; Patterns to match conditional branch insns.
7086 ; Special pattern to match UNEQ.
7087 (define_insn "*arm_buneq"
7088   [(set (pc)
7089         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7090                       (label_ref (match_operand 0 "" ""))
7091                       (pc)))]
7092   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7093   "*
7094   gcc_assert (!arm_ccfsm_state);
7096   return \"bvs\\t%l0\;beq\\t%l0\";
7097   "
7098   [(set_attr "conds" "jump_clob")
7099    (set_attr "length" "8")]
7102 ; Special pattern to match LTGT.
7103 (define_insn "*arm_bltgt"
7104   [(set (pc)
7105         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7106                       (label_ref (match_operand 0 "" ""))
7107                       (pc)))]
7108   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7109   "*
7110   gcc_assert (!arm_ccfsm_state);
7112   return \"bmi\\t%l0\;bgt\\t%l0\";
7113   "
7114   [(set_attr "conds" "jump_clob")
7115    (set_attr "length" "8")]
7118 (define_insn "*arm_cond_branch"
7119   [(set (pc)
7120         (if_then_else (match_operator 1 "arm_comparison_operator"
7121                        [(match_operand 2 "cc_register" "") (const_int 0)])
7122                       (label_ref (match_operand 0 "" ""))
7123                       (pc)))]
7124   "TARGET_ARM"
7125   "*
7126   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7127     {
7128       arm_ccfsm_state += 2;
7129       return \"\";
7130     }
7131   return \"b%d1\\t%l0\";
7132   "
7133   [(set_attr "conds" "use")
7134    (set_attr "type" "branch")]
7137 ; Special pattern to match reversed UNEQ.
7138 (define_insn "*arm_buneq_reversed"
7139   [(set (pc)
7140         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7141                       (pc)
7142                       (label_ref (match_operand 0 "" ""))))]
7143   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7144   "*
7145   gcc_assert (!arm_ccfsm_state);
7147   return \"bmi\\t%l0\;bgt\\t%l0\";
7148   "
7149   [(set_attr "conds" "jump_clob")
7150    (set_attr "length" "8")]
7153 ; Special pattern to match reversed LTGT.
7154 (define_insn "*arm_bltgt_reversed"
7155   [(set (pc)
7156         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7157                       (pc)
7158                       (label_ref (match_operand 0 "" ""))))]
7159   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7160   "*
7161   gcc_assert (!arm_ccfsm_state);
7163   return \"bvs\\t%l0\;beq\\t%l0\";
7164   "
7165   [(set_attr "conds" "jump_clob")
7166    (set_attr "length" "8")]
7169 (define_insn "*arm_cond_branch_reversed"
7170   [(set (pc)
7171         (if_then_else (match_operator 1 "arm_comparison_operator"
7172                        [(match_operand 2 "cc_register" "") (const_int 0)])
7173                       (pc)
7174                       (label_ref (match_operand 0 "" ""))))]
7175   "TARGET_ARM"
7176   "*
7177   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7178     {
7179       arm_ccfsm_state += 2;
7180       return \"\";
7181     }
7182   return \"b%D1\\t%l0\";
7183   "
7184   [(set_attr "conds" "use")
7185    (set_attr "type" "branch")]
7190 ; scc insns
7192 (define_expand "seq"
7193   [(set (match_operand:SI 0 "s_register_operand" "")
7194         (eq:SI (match_dup 1) (const_int 0)))]
7195   "TARGET_ARM"
7196   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7199 (define_expand "sne"
7200   [(set (match_operand:SI 0 "s_register_operand" "")
7201         (ne:SI (match_dup 1) (const_int 0)))]
7202   "TARGET_ARM"
7203   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7206 (define_expand "sgt"
7207   [(set (match_operand:SI 0 "s_register_operand" "")
7208         (gt:SI (match_dup 1) (const_int 0)))]
7209   "TARGET_ARM"
7210   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7213 (define_expand "sle"
7214   [(set (match_operand:SI 0 "s_register_operand" "")
7215         (le:SI (match_dup 1) (const_int 0)))]
7216   "TARGET_ARM"
7217   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7220 (define_expand "sge"
7221   [(set (match_operand:SI 0 "s_register_operand" "")
7222         (ge:SI (match_dup 1) (const_int 0)))]
7223   "TARGET_ARM"
7224   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7227 (define_expand "slt"
7228   [(set (match_operand:SI 0 "s_register_operand" "")
7229         (lt:SI (match_dup 1) (const_int 0)))]
7230   "TARGET_ARM"
7231   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7234 (define_expand "sgtu"
7235   [(set (match_operand:SI 0 "s_register_operand" "")
7236         (gtu:SI (match_dup 1) (const_int 0)))]
7237   "TARGET_ARM"
7238   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7241 (define_expand "sleu"
7242   [(set (match_operand:SI 0 "s_register_operand" "")
7243         (leu:SI (match_dup 1) (const_int 0)))]
7244   "TARGET_ARM"
7245   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7248 (define_expand "sgeu"
7249   [(set (match_operand:SI 0 "s_register_operand" "")
7250         (geu:SI (match_dup 1) (const_int 0)))]
7251   "TARGET_ARM"
7252   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7255 (define_expand "sltu"
7256   [(set (match_operand:SI 0 "s_register_operand" "")
7257         (ltu:SI (match_dup 1) (const_int 0)))]
7258   "TARGET_ARM"
7259   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7262 (define_expand "sunordered"
7263   [(set (match_operand:SI 0 "s_register_operand" "")
7264         (unordered:SI (match_dup 1) (const_int 0)))]
7265   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7266   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7267                                       arm_compare_op1);"
7270 (define_expand "sordered"
7271   [(set (match_operand:SI 0 "s_register_operand" "")
7272         (ordered:SI (match_dup 1) (const_int 0)))]
7273   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7274   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7275                                       arm_compare_op1);"
7278 (define_expand "sungt"
7279   [(set (match_operand:SI 0 "s_register_operand" "")
7280         (ungt:SI (match_dup 1) (const_int 0)))]
7281   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7282   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7283                                       arm_compare_op1);"
7286 (define_expand "sunge"
7287   [(set (match_operand:SI 0 "s_register_operand" "")
7288         (unge:SI (match_dup 1) (const_int 0)))]
7289   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7290   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7291                                       arm_compare_op1);"
7294 (define_expand "sunlt"
7295   [(set (match_operand:SI 0 "s_register_operand" "")
7296         (unlt:SI (match_dup 1) (const_int 0)))]
7297   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7298   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7299                                       arm_compare_op1);"
7302 (define_expand "sunle"
7303   [(set (match_operand:SI 0 "s_register_operand" "")
7304         (unle:SI (match_dup 1) (const_int 0)))]
7305   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7306   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7307                                       arm_compare_op1);"
7310 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7311 ;;; simple ARM instructions. 
7313 ; (define_expand "suneq"
7314 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7315 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7316 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7317 ;   "gcc_unreachable ();"
7318 ; )
7320 ; (define_expand "sltgt"
7321 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7322 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7323 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7324 ;   "gcc_unreachable ();"
7325 ; )
7327 (define_insn "*mov_scc"
7328   [(set (match_operand:SI 0 "s_register_operand" "=r")
7329         (match_operator:SI 1 "arm_comparison_operator"
7330          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7331   "TARGET_ARM"
7332   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7333   [(set_attr "conds" "use")
7334    (set_attr "length" "8")]
7337 (define_insn "*mov_negscc"
7338   [(set (match_operand:SI 0 "s_register_operand" "=r")
7339         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7340                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7341   "TARGET_ARM"
7342   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7343   [(set_attr "conds" "use")
7344    (set_attr "length" "8")]
7347 (define_insn "*mov_notscc"
7348   [(set (match_operand:SI 0 "s_register_operand" "=r")
7349         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7350                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7351   "TARGET_ARM"
7352   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7353   [(set_attr "conds" "use")
7354    (set_attr "length" "8")]
7358 ;; Conditional move insns
7360 (define_expand "movsicc"
7361   [(set (match_operand:SI 0 "s_register_operand" "")
7362         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7363                          (match_operand:SI 2 "arm_not_operand" "")
7364                          (match_operand:SI 3 "arm_not_operand" "")))]
7365   "TARGET_ARM"
7366   "
7367   {
7368     enum rtx_code code = GET_CODE (operands[1]);
7369     rtx ccreg;
7371     if (code == UNEQ || code == LTGT)
7372       FAIL;
7374     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7375     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7376   }"
7379 (define_expand "movsfcc"
7380   [(set (match_operand:SF 0 "s_register_operand" "")
7381         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7382                          (match_operand:SF 2 "s_register_operand" "")
7383                          (match_operand:SF 3 "nonmemory_operand" "")))]
7384   "TARGET_ARM"
7385   "
7386   {
7387     enum rtx_code code = GET_CODE (operands[1]);
7388     rtx ccreg;
7390     if (code == UNEQ || code == LTGT)
7391       FAIL;
7393     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7394        Otherwise, ensure it is a valid FP add operand */
7395     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7396         || (!arm_float_add_operand (operands[3], SFmode)))
7397       operands[3] = force_reg (SFmode, operands[3]);
7399     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7400     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7401   }"
7404 (define_expand "movdfcc"
7405   [(set (match_operand:DF 0 "s_register_operand" "")
7406         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7407                          (match_operand:DF 2 "s_register_operand" "")
7408                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7409   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7410   "
7411   {
7412     enum rtx_code code = GET_CODE (operands[1]);
7413     rtx ccreg;
7415     if (code == UNEQ || code == LTGT)
7416       FAIL;
7418     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7419     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7420   }"
7423 (define_insn "*movsicc_insn"
7424   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7425         (if_then_else:SI
7426          (match_operator 3 "arm_comparison_operator"
7427           [(match_operand 4 "cc_register" "") (const_int 0)])
7428          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7429          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7430   "TARGET_ARM"
7431   "@
7432    mov%D3\\t%0, %2
7433    mvn%D3\\t%0, #%B2
7434    mov%d3\\t%0, %1
7435    mvn%d3\\t%0, #%B1
7436    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7437    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7438    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7439    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7440   [(set_attr "length" "4,4,4,4,8,8,8,8")
7441    (set_attr "conds" "use")]
7444 (define_insn "*movsfcc_soft_insn"
7445   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7446         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7447                           [(match_operand 4 "cc_register" "") (const_int 0)])
7448                          (match_operand:SF 1 "s_register_operand" "0,r")
7449                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7450   "TARGET_ARM && TARGET_SOFT_FLOAT"
7451   "@
7452    mov%D3\\t%0, %2
7453    mov%d3\\t%0, %1"
7454   [(set_attr "conds" "use")]
7458 ;; Jump and linkage insns
7460 (define_expand "jump"
7461   [(set (pc)
7462         (label_ref (match_operand 0 "" "")))]
7463   "TARGET_EITHER"
7464   ""
7467 (define_insn "*arm_jump"
7468   [(set (pc)
7469         (label_ref (match_operand 0 "" "")))]
7470   "TARGET_ARM"
7471   "*
7472   {
7473     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7474       {
7475         arm_ccfsm_state += 2;
7476         return \"\";
7477       }
7478     return \"b%?\\t%l0\";
7479   }
7480   "
7481   [(set_attr "predicable" "yes")]
7484 (define_insn "*thumb_jump"
7485   [(set (pc)
7486         (label_ref (match_operand 0 "" "")))]
7487   "TARGET_THUMB"
7488   "*
7489   if (get_attr_length (insn) == 2)
7490     return \"b\\t%l0\";
7491   return \"bl\\t%l0\\t%@ far jump\";
7492   "
7493   [(set (attr "far_jump")
7494         (if_then_else
7495             (eq_attr "length" "4")
7496             (const_string "yes")
7497             (const_string "no")))
7498    (set (attr "length") 
7499         (if_then_else
7500             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7501                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7502             (const_int 2)
7503             (const_int 4)))]
7506 (define_expand "call"
7507   [(parallel [(call (match_operand 0 "memory_operand" "")
7508                     (match_operand 1 "general_operand" ""))
7509               (use (match_operand 2 "" ""))
7510               (clobber (reg:SI LR_REGNUM))])]
7511   "TARGET_EITHER"
7512   "
7513   {
7514     rtx callee;
7515     
7516     /* In an untyped call, we can get NULL for operand 2.  */
7517     if (operands[2] == NULL_RTX)
7518       operands[2] = const0_rtx;
7519       
7520     /* This is to decide if we should generate indirect calls by loading the
7521        32 bit address of the callee into a register before performing the
7522        branch and link.  operand[2] encodes the long_call/short_call
7523        attribute of the function being called.  This attribute is set whenever
7524        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7525        is used, and the short_call attribute can also be set if function is
7526        declared as static or if it has already been defined in the current
7527        compilation unit.  See arm.c and arm.h for info about this.  The third
7528        parameter to arm_is_longcall_p is used to tell it which pattern
7529        invoked it.  */
7530     callee  = XEXP (operands[0], 0);
7531     
7532     if ((GET_CODE (callee) == SYMBOL_REF
7533          && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7534         || (GET_CODE (callee) != SYMBOL_REF
7535             && GET_CODE (callee) != REG))
7536       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7537   }"
7540 (define_insn "*call_reg_armv5"
7541   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7542          (match_operand 1 "" ""))
7543    (use (match_operand 2 "" ""))
7544    (clobber (reg:SI LR_REGNUM))]
7545   "TARGET_ARM && arm_arch5"
7546   "blx%?\\t%0"
7547   [(set_attr "type" "call")]
7550 (define_insn "*call_reg_arm"
7551   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7552          (match_operand 1 "" ""))
7553    (use (match_operand 2 "" ""))
7554    (clobber (reg:SI LR_REGNUM))]
7555   "TARGET_ARM && !arm_arch5"
7556   "*
7557   return output_call (operands);
7558   "
7559   ;; length is worst case, normally it is only two
7560   [(set_attr "length" "12")
7561    (set_attr "type" "call")]
7564 (define_insn "*call_mem"
7565   [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
7566          (match_operand 1 "" ""))
7567    (use (match_operand 2 "" ""))
7568    (clobber (reg:SI LR_REGNUM))]
7569   "TARGET_ARM"
7570   "*
7571   return output_call_mem (operands);
7572   "
7573   [(set_attr "length" "12")
7574    (set_attr "type" "call")]
7577 (define_insn "*call_reg_thumb_v5"
7578   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7579          (match_operand 1 "" ""))
7580    (use (match_operand 2 "" ""))
7581    (clobber (reg:SI LR_REGNUM))]
7582   "TARGET_THUMB && arm_arch5"
7583   "blx\\t%0"
7584   [(set_attr "length" "2")
7585    (set_attr "type" "call")]
7588 (define_insn "*call_reg_thumb"
7589   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7590          (match_operand 1 "" ""))
7591    (use (match_operand 2 "" ""))
7592    (clobber (reg:SI LR_REGNUM))]
7593   "TARGET_THUMB && !arm_arch5"
7594   "*
7595   {
7596     if (!TARGET_CALLER_INTERWORKING)
7597       return thumb_call_via_reg (operands[0]);
7598     else if (operands[1] == const0_rtx)
7599       return \"bl\\t%__interwork_call_via_%0\";
7600     else if (frame_pointer_needed)
7601       return \"bl\\t%__interwork_r7_call_via_%0\";
7602     else
7603       return \"bl\\t%__interwork_r11_call_via_%0\";
7604   }"
7605   [(set_attr "type" "call")]
7608 (define_expand "call_value"
7609   [(parallel [(set (match_operand       0 "" "")
7610                    (call (match_operand 1 "memory_operand" "")
7611                          (match_operand 2 "general_operand" "")))
7612               (use (match_operand 3 "" ""))
7613               (clobber (reg:SI LR_REGNUM))])]
7614   "TARGET_EITHER"
7615   "
7616   {
7617     rtx callee = XEXP (operands[1], 0);
7618     
7619     /* In an untyped call, we can get NULL for operand 2.  */
7620     if (operands[3] == 0)
7621       operands[3] = const0_rtx;
7622       
7623     /* See the comment in define_expand \"call\".  */
7624     if ((GET_CODE (callee) == SYMBOL_REF
7625          && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7626         || (GET_CODE (callee) != SYMBOL_REF
7627             && GET_CODE (callee) != REG))
7628       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7629   }"
7632 (define_insn "*call_value_reg_armv5"
7633   [(set (match_operand 0 "" "")
7634         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7635               (match_operand 2 "" "")))
7636    (use (match_operand 3 "" ""))
7637    (clobber (reg:SI LR_REGNUM))]
7638   "TARGET_ARM && arm_arch5"
7639   "blx%?\\t%1"
7640   [(set_attr "type" "call")]
7643 (define_insn "*call_value_reg_arm"
7644   [(set (match_operand 0 "" "")
7645         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7646               (match_operand 2 "" "")))
7647    (use (match_operand 3 "" ""))
7648    (clobber (reg:SI LR_REGNUM))]
7649   "TARGET_ARM && !arm_arch5"
7650   "*
7651   return output_call (&operands[1]);
7652   "
7653   [(set_attr "length" "12")
7654    (set_attr "type" "call")]
7657 (define_insn "*call_value_mem"
7658   [(set (match_operand 0 "" "")
7659         (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
7660               (match_operand 2 "" "")))
7661    (use (match_operand 3 "" ""))
7662    (clobber (reg:SI LR_REGNUM))]
7663   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7664   "*
7665   return output_call_mem (&operands[1]);
7666   "
7667   [(set_attr "length" "12")
7668    (set_attr "type" "call")]
7671 (define_insn "*call_value_reg_thumb_v5"
7672   [(set (match_operand 0 "" "")
7673         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7674               (match_operand 2 "" "")))
7675    (use (match_operand 3 "" ""))
7676    (clobber (reg:SI LR_REGNUM))]
7677   "TARGET_THUMB && arm_arch5"
7678   "blx\\t%1"
7679   [(set_attr "length" "2")
7680    (set_attr "type" "call")]
7683 (define_insn "*call_value_reg_thumb"
7684   [(set (match_operand 0 "" "")
7685         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7686               (match_operand 2 "" "")))
7687    (use (match_operand 3 "" ""))
7688    (clobber (reg:SI LR_REGNUM))]
7689   "TARGET_THUMB && !arm_arch5"
7690   "*
7691   {
7692     if (!TARGET_CALLER_INTERWORKING)
7693       return thumb_call_via_reg (operands[1]);
7694     else if (operands[2] == const0_rtx)
7695       return \"bl\\t%__interwork_call_via_%1\";
7696     else if (frame_pointer_needed)
7697       return \"bl\\t%__interwork_r7_call_via_%1\";
7698     else
7699       return \"bl\\t%__interwork_r11_call_via_%1\";
7700   }"
7701   [(set_attr "type" "call")]
7704 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7705 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7707 (define_insn "*call_symbol"
7708   [(call (mem:SI (match_operand:SI 0 "" ""))
7709          (match_operand 1 "" ""))
7710    (use (match_operand 2 "" ""))
7711    (clobber (reg:SI LR_REGNUM))]
7712   "TARGET_ARM
7713    && (GET_CODE (operands[0]) == SYMBOL_REF)
7714    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7715   "*
7716   {
7717     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7718   }"
7719   [(set_attr "type" "call")]
7722 (define_insn "*call_value_symbol"
7723   [(set (match_operand 0 "" "")
7724         (call (mem:SI (match_operand:SI 1 "" ""))
7725         (match_operand:SI 2 "" "")))
7726    (use (match_operand 3 "" ""))
7727    (clobber (reg:SI LR_REGNUM))]
7728   "TARGET_ARM
7729    && (GET_CODE (operands[1]) == SYMBOL_REF)
7730    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7731   "*
7732   {
7733     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7734   }"
7735   [(set_attr "type" "call")]
7738 (define_insn "*call_insn"
7739   [(call (mem:SI (match_operand:SI 0 "" ""))
7740          (match_operand:SI 1 "" ""))
7741    (use (match_operand 2 "" ""))
7742    (clobber (reg:SI LR_REGNUM))]
7743   "TARGET_THUMB
7744    && GET_CODE (operands[0]) == SYMBOL_REF
7745    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7746   "bl\\t%a0"
7747   [(set_attr "length" "4")
7748    (set_attr "type" "call")]
7751 (define_insn "*call_value_insn"
7752   [(set (match_operand 0 "" "")
7753         (call (mem:SI (match_operand 1 "" ""))
7754               (match_operand 2 "" "")))
7755    (use (match_operand 3 "" ""))
7756    (clobber (reg:SI LR_REGNUM))]
7757   "TARGET_THUMB
7758    && GET_CODE (operands[1]) == SYMBOL_REF
7759    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7760   "bl\\t%a1"
7761   [(set_attr "length" "4")
7762    (set_attr "type" "call")]
7765 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7766 (define_expand "sibcall"
7767   [(parallel [(call (match_operand 0 "memory_operand" "")
7768                     (match_operand 1 "general_operand" ""))
7769               (return)
7770               (use (match_operand 2 "" ""))])]
7771   "TARGET_ARM"
7772   "
7773   {
7774     if (operands[2] == NULL_RTX)
7775       operands[2] = const0_rtx;
7776   }"
7779 (define_expand "sibcall_value"
7780   [(parallel [(set (match_operand 0 "" "")
7781                    (call (match_operand 1 "memory_operand" "")
7782                          (match_operand 2 "general_operand" "")))
7783               (return)
7784               (use (match_operand 3 "" ""))])]
7785   "TARGET_ARM"
7786   "
7787   {
7788     if (operands[3] == NULL_RTX)
7789       operands[3] = const0_rtx;
7790   }"
7793 (define_insn "*sibcall_insn"
7794  [(call (mem:SI (match_operand:SI 0 "" "X"))
7795         (match_operand 1 "" ""))
7796   (return)
7797   (use (match_operand 2 "" ""))]
7798   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7799   "*
7800   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7801   "
7802   [(set_attr "type" "call")]
7805 (define_insn "*sibcall_value_insn"
7806  [(set (match_operand 0 "" "")
7807        (call (mem:SI (match_operand:SI 1 "" "X"))
7808              (match_operand 2 "" "")))
7809   (return)
7810   (use (match_operand 3 "" ""))]
7811   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7812   "*
7813   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7814   "
7815   [(set_attr "type" "call")]
7818 ;; Often the return insn will be the same as loading from memory, so set attr
7819 (define_insn "return"
7820   [(return)]
7821   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7822   "*
7823   {
7824     if (arm_ccfsm_state == 2)
7825       {
7826         arm_ccfsm_state += 2;
7827         return \"\";
7828       }
7829     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7830   }"
7831   [(set_attr "type" "load1")
7832    (set_attr "length" "12")
7833    (set_attr "predicable" "yes")]
7836 (define_insn "*cond_return"
7837   [(set (pc)
7838         (if_then_else (match_operator 0 "arm_comparison_operator"
7839                        [(match_operand 1 "cc_register" "") (const_int 0)])
7840                       (return)
7841                       (pc)))]
7842   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7843   "*
7844   {
7845     if (arm_ccfsm_state == 2)
7846       {
7847         arm_ccfsm_state += 2;
7848         return \"\";
7849       }
7850     return output_return_instruction (operands[0], TRUE, FALSE);
7851   }"
7852   [(set_attr "conds" "use")
7853    (set_attr "length" "12")
7854    (set_attr "type" "load1")]
7857 (define_insn "*cond_return_inverted"
7858   [(set (pc)
7859         (if_then_else (match_operator 0 "arm_comparison_operator"
7860                        [(match_operand 1 "cc_register" "") (const_int 0)])
7861                       (pc)
7862                       (return)))]
7863   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7864   "*
7865   {
7866     if (arm_ccfsm_state == 2)
7867       {
7868         arm_ccfsm_state += 2;
7869         return \"\";
7870       }
7871     return output_return_instruction (operands[0], TRUE, TRUE);
7872   }"
7873   [(set_attr "conds" "use")
7874    (set_attr "length" "12")
7875    (set_attr "type" "load1")]
7878 ;; Generate a sequence of instructions to determine if the processor is
7879 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7880 ;; mask.
7882 (define_expand "return_addr_mask"
7883   [(set (match_dup 1)
7884       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7885                        (const_int 0)))
7886    (set (match_operand:SI 0 "s_register_operand" "")
7887       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7888                        (const_int -1)
7889                        (const_int 67108860)))] ; 0x03fffffc
7890   "TARGET_ARM"
7891   "
7892   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7893   ")
7895 (define_insn "*check_arch2"
7896   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7897       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7898                        (const_int 0)))]
7899   "TARGET_ARM"
7900   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7901   [(set_attr "length" "8")
7902    (set_attr "conds" "set")]
7905 ;; Call subroutine returning any type.
7907 (define_expand "untyped_call"
7908   [(parallel [(call (match_operand 0 "" "")
7909                     (const_int 0))
7910               (match_operand 1 "" "")
7911               (match_operand 2 "" "")])]
7912   "TARGET_EITHER"
7913   "
7914   {
7915     int i;
7916     rtx par = gen_rtx_PARALLEL (VOIDmode,
7917                                 rtvec_alloc (XVECLEN (operands[2], 0)));
7918     rtx addr = gen_reg_rtx (Pmode);
7919     rtx mem;
7920     int size = 0;
7922     emit_move_insn (addr, XEXP (operands[1], 0));
7923     mem = change_address (operands[1], BLKmode, addr);
7925     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7926       {
7927         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7929         /* Default code only uses r0 as a return value, but we could
7930            be using anything up to 4 registers.  */
7931         if (REGNO (src) == R0_REGNUM)
7932           src = gen_rtx_REG (TImode, R0_REGNUM);
7934         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7935                                                  GEN_INT (size));
7936         size += GET_MODE_SIZE (GET_MODE (src));
7937       }
7939     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7940                                     const0_rtx));
7942     size = 0;
7944     for (i = 0; i < XVECLEN (par, 0); i++)
7945       {
7946         HOST_WIDE_INT offset = 0;
7947         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7949         if (size != 0)
7950           emit_move_insn (addr, plus_constant (addr, size));
7952         mem = change_address (mem, GET_MODE (reg), NULL);
7953         if (REGNO (reg) == R0_REGNUM)
7954           {
7955             /* On thumb we have to use a write-back instruction.  */
7956             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7957                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7958             size = TARGET_ARM ? 16 : 0;
7959           }
7960         else
7961           {
7962             emit_move_insn (mem, reg);
7963             size = GET_MODE_SIZE (GET_MODE (reg));
7964           }
7965       }
7967     /* The optimizer does not know that the call sets the function value
7968        registers we stored in the result block.  We avoid problems by
7969        claiming that all hard registers are used and clobbered at this
7970        point.  */
7971     emit_insn (gen_blockage ());
7973     DONE;
7974   }"
7977 (define_expand "untyped_return"
7978   [(match_operand:BLK 0 "memory_operand" "")
7979    (match_operand 1 "" "")]
7980   "TARGET_EITHER"
7981   "
7982   {
7983     int i;
7984     rtx addr = gen_reg_rtx (Pmode);
7985     rtx mem;
7986     int size = 0;
7988     emit_move_insn (addr, XEXP (operands[0], 0));
7989     mem = change_address (operands[0], BLKmode, addr);
7991     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7992       {
7993         HOST_WIDE_INT offset = 0;
7994         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7996         if (size != 0)
7997           emit_move_insn (addr, plus_constant (addr, size));
7999         mem = change_address (mem, GET_MODE (reg), NULL);
8000         if (REGNO (reg) == R0_REGNUM)
8001           {
8002             /* On thumb we have to use a write-back instruction.  */
8003             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
8004                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
8005             size = TARGET_ARM ? 16 : 0;
8006           }
8007         else
8008           {
8009             emit_move_insn (reg, mem);
8010             size = GET_MODE_SIZE (GET_MODE (reg));
8011           }
8012       }
8014     /* Emit USE insns before the return.  */
8015     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8016       emit_insn (gen_rtx_USE (VOIDmode,
8017                               SET_DEST (XVECEXP (operands[1], 0, i))));
8019     /* Construct the return.  */
8020     expand_naked_return ();
8022     DONE;
8023   }"
8026 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8027 ;; all of memory.  This blocks insns from being moved across this point.
8029 (define_insn "blockage"
8030   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8031   "TARGET_EITHER"
8032   ""
8033   [(set_attr "length" "0")
8034    (set_attr "type" "block")]
8037 (define_expand "casesi"
8038   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8039    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8040    (match_operand:SI 2 "const_int_operand" "")  ; total range
8041    (match_operand:SI 3 "" "")                   ; table label
8042    (match_operand:SI 4 "" "")]                  ; Out of range label
8043   "TARGET_ARM"
8044   "
8045   {
8046     rtx reg;
8047     if (operands[1] != const0_rtx)
8048       {
8049         reg = gen_reg_rtx (SImode);
8051         emit_insn (gen_addsi3 (reg, operands[0],
8052                                GEN_INT (-INTVAL (operands[1]))));
8053         operands[0] = reg;
8054       }
8056     if (!const_ok_for_arm (INTVAL (operands[2])))
8057       operands[2] = force_reg (SImode, operands[2]);
8059     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8060                                          operands[4]));
8061     DONE;
8062   }"
8065 ;; The USE in this pattern is needed to tell flow analysis that this is
8066 ;; a CASESI insn.  It has no other purpose.
8067 (define_insn "casesi_internal"
8068   [(parallel [(set (pc)
8069                (if_then_else
8070                 (leu (match_operand:SI 0 "s_register_operand" "r")
8071                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8072                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8073                                  (label_ref (match_operand 2 "" ""))))
8074                 (label_ref (match_operand 3 "" ""))))
8075               (clobber (reg:CC CC_REGNUM))
8076               (use (label_ref (match_dup 2)))])]
8077   "TARGET_ARM"
8078   "*
8079     if (flag_pic)
8080       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8081     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8082   "
8083   [(set_attr "conds" "clob")
8084    (set_attr "length" "12")]
8087 (define_expand "indirect_jump"
8088   [(set (pc)
8089         (match_operand:SI 0 "s_register_operand" ""))]
8090   "TARGET_EITHER"
8091   ""
8094 ;; NB Never uses BX.
8095 (define_insn "*arm_indirect_jump"
8096   [(set (pc)
8097         (match_operand:SI 0 "s_register_operand" "r"))]
8098   "TARGET_ARM"
8099   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8100   [(set_attr "predicable" "yes")]
8103 (define_insn "*load_indirect_jump"
8104   [(set (pc)
8105         (match_operand:SI 0 "memory_operand" "m"))]
8106   "TARGET_ARM"
8107   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8108   [(set_attr "type" "load1")
8109    (set_attr "pool_range" "4096")
8110    (set_attr "neg_pool_range" "4084")
8111    (set_attr "predicable" "yes")]
8114 ;; NB Never uses BX.
8115 (define_insn "*thumb_indirect_jump"
8116   [(set (pc)
8117         (match_operand:SI 0 "register_operand" "l*r"))]
8118   "TARGET_THUMB"
8119   "mov\\tpc, %0"
8120   [(set_attr "conds" "clob")
8121    (set_attr "length" "2")]
8125 ;; Misc insns
8127 (define_insn "nop"
8128   [(const_int 0)]
8129   "TARGET_EITHER"
8130   "*
8131   if (TARGET_ARM)
8132     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8133   return  \"mov\\tr8, r8\";
8134   "
8135   [(set (attr "length")
8136         (if_then_else (eq_attr "is_thumb" "yes")
8137                       (const_int 2)
8138                       (const_int 4)))]
8142 ;; Patterns to allow combination of arithmetic, cond code and shifts
8144 (define_insn "*arith_shiftsi"
8145   [(set (match_operand:SI 0 "s_register_operand" "=r")
8146         (match_operator:SI 1 "shiftable_operator"
8147           [(match_operator:SI 3 "shift_operator"
8148              [(match_operand:SI 4 "s_register_operand" "r")
8149               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8150            (match_operand:SI 2 "s_register_operand" "r")]))]
8151   "TARGET_ARM"
8152   "%i1%?\\t%0, %2, %4%S3"
8153   [(set_attr "predicable" "yes")
8154    (set_attr "shift" "4")
8155    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8156                       (const_string "alu_shift")
8157                       (const_string "alu_shift_reg")))]
8160 (define_split
8161   [(set (match_operand:SI 0 "s_register_operand" "")
8162         (match_operator:SI 1 "shiftable_operator"
8163          [(match_operator:SI 2 "shiftable_operator"
8164            [(match_operator:SI 3 "shift_operator"
8165              [(match_operand:SI 4 "s_register_operand" "")
8166               (match_operand:SI 5 "reg_or_int_operand" "")])
8167             (match_operand:SI 6 "s_register_operand" "")])
8168           (match_operand:SI 7 "arm_rhs_operand" "")]))
8169    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8170   "TARGET_ARM"
8171   [(set (match_dup 8)
8172         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8173                          (match_dup 6)]))
8174    (set (match_dup 0)
8175         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8176   "")
8178 (define_insn "*arith_shiftsi_compare0"
8179   [(set (reg:CC_NOOV CC_REGNUM)
8180         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8181                           [(match_operator:SI 3 "shift_operator"
8182                             [(match_operand:SI 4 "s_register_operand" "r")
8183                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8184                            (match_operand:SI 2 "s_register_operand" "r")])
8185                          (const_int 0)))
8186    (set (match_operand:SI 0 "s_register_operand" "=r")
8187         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8188                          (match_dup 2)]))]
8189   "TARGET_ARM"
8190   "%i1%?s\\t%0, %2, %4%S3"
8191   [(set_attr "conds" "set")
8192    (set_attr "shift" "4")
8193    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8194                       (const_string "alu_shift")
8195                       (const_string "alu_shift_reg")))]
8198 (define_insn "*arith_shiftsi_compare0_scratch"
8199   [(set (reg:CC_NOOV CC_REGNUM)
8200         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8201                           [(match_operator:SI 3 "shift_operator"
8202                             [(match_operand:SI 4 "s_register_operand" "r")
8203                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8204                            (match_operand:SI 2 "s_register_operand" "r")])
8205                          (const_int 0)))
8206    (clobber (match_scratch:SI 0 "=r"))]
8207   "TARGET_ARM"
8208   "%i1%?s\\t%0, %2, %4%S3"
8209   [(set_attr "conds" "set")
8210    (set_attr "shift" "4")
8211    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8212                       (const_string "alu_shift")
8213                       (const_string "alu_shift_reg")))]
8216 (define_insn "*sub_shiftsi"
8217   [(set (match_operand:SI 0 "s_register_operand" "=r")
8218         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8219                   (match_operator:SI 2 "shift_operator"
8220                    [(match_operand:SI 3 "s_register_operand" "r")
8221                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8222   "TARGET_ARM"
8223   "sub%?\\t%0, %1, %3%S2"
8224   [(set_attr "predicable" "yes")
8225    (set_attr "shift" "3")
8226    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8227                       (const_string "alu_shift")
8228                       (const_string "alu_shift_reg")))]
8231 (define_insn "*sub_shiftsi_compare0"
8232   [(set (reg:CC_NOOV CC_REGNUM)
8233         (compare:CC_NOOV
8234          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8235                    (match_operator:SI 2 "shift_operator"
8236                     [(match_operand:SI 3 "s_register_operand" "r")
8237                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8238          (const_int 0)))
8239    (set (match_operand:SI 0 "s_register_operand" "=r")
8240         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8241                                                  (match_dup 4)])))]
8242   "TARGET_ARM"
8243   "sub%?s\\t%0, %1, %3%S2"
8244   [(set_attr "conds" "set")
8245    (set_attr "shift" "3")
8246    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8247                       (const_string "alu_shift")
8248                       (const_string "alu_shift_reg")))]
8251 (define_insn "*sub_shiftsi_compare0_scratch"
8252   [(set (reg:CC_NOOV CC_REGNUM)
8253         (compare:CC_NOOV
8254          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8255                    (match_operator:SI 2 "shift_operator"
8256                     [(match_operand:SI 3 "s_register_operand" "r")
8257                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8258          (const_int 0)))
8259    (clobber (match_scratch:SI 0 "=r"))]
8260   "TARGET_ARM"
8261   "sub%?s\\t%0, %1, %3%S2"
8262   [(set_attr "conds" "set")
8263    (set_attr "shift" "3")
8264    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8265                       (const_string "alu_shift")
8266                       (const_string "alu_shift_reg")))]
8271 (define_insn "*and_scc"
8272   [(set (match_operand:SI 0 "s_register_operand" "=r")
8273         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8274                  [(match_operand 3 "cc_register" "") (const_int 0)])
8275                 (match_operand:SI 2 "s_register_operand" "r")))]
8276   "TARGET_ARM"
8277   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8278   [(set_attr "conds" "use")
8279    (set_attr "length" "8")]
8282 (define_insn "*ior_scc"
8283   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8284         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8285                  [(match_operand 3 "cc_register" "") (const_int 0)])
8286                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8287   "TARGET_ARM"
8288   "@
8289    orr%d2\\t%0, %1, #1
8290    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8291   [(set_attr "conds" "use")
8292    (set_attr "length" "4,8")]
8295 (define_insn "*compare_scc"
8296   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8297         (match_operator:SI 1 "arm_comparison_operator"
8298          [(match_operand:SI 2 "s_register_operand" "r,r")
8299           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8300    (clobber (reg:CC CC_REGNUM))]
8301   "TARGET_ARM"
8302   "*
8303     if (operands[3] == const0_rtx)
8304       {
8305         if (GET_CODE (operands[1]) == LT)
8306           return \"mov\\t%0, %2, lsr #31\";
8308         if (GET_CODE (operands[1]) == GE)
8309           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8311         if (GET_CODE (operands[1]) == EQ)
8312           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8313       }
8315     if (GET_CODE (operands[1]) == NE)
8316       {
8317         if (which_alternative == 1)
8318           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8319         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8320       }
8321     if (which_alternative == 1)
8322       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8323     else
8324       output_asm_insn (\"cmp\\t%2, %3\", operands);
8325     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8326   "
8327   [(set_attr "conds" "clob")
8328    (set_attr "length" "12")]
8331 (define_insn "*cond_move"
8332   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8333         (if_then_else:SI (match_operator 3 "equality_operator"
8334                           [(match_operator 4 "arm_comparison_operator"
8335                             [(match_operand 5 "cc_register" "") (const_int 0)])
8336                            (const_int 0)])
8337                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8338                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8339   "TARGET_ARM"
8340   "*
8341     if (GET_CODE (operands[3]) == NE)
8342       {
8343         if (which_alternative != 1)
8344           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8345         if (which_alternative != 0)
8346           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8347         return \"\";
8348       }
8349     if (which_alternative != 0)
8350       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8351     if (which_alternative != 1)
8352       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8353     return \"\";
8354   "
8355   [(set_attr "conds" "use")
8356    (set_attr "length" "4,4,8")]
8359 (define_insn "*cond_arith"
8360   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8361         (match_operator:SI 5 "shiftable_operator" 
8362          [(match_operator:SI 4 "arm_comparison_operator"
8363            [(match_operand:SI 2 "s_register_operand" "r,r")
8364             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8365           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8366    (clobber (reg:CC CC_REGNUM))]
8367   "TARGET_ARM"
8368   "*
8369     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8370       return \"%i5\\t%0, %1, %2, lsr #31\";
8372     output_asm_insn (\"cmp\\t%2, %3\", operands);
8373     if (GET_CODE (operands[5]) == AND)
8374       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8375     else if (GET_CODE (operands[5]) == MINUS)
8376       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8377     else if (which_alternative != 0)
8378       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8379     return \"%i5%d4\\t%0, %1, #1\";
8380   "
8381   [(set_attr "conds" "clob")
8382    (set_attr "length" "12")]
8385 (define_insn "*cond_sub"
8386   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8387         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8388                   (match_operator:SI 4 "arm_comparison_operator"
8389                    [(match_operand:SI 2 "s_register_operand" "r,r")
8390                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8391    (clobber (reg:CC CC_REGNUM))]
8392   "TARGET_ARM"
8393   "*
8394     output_asm_insn (\"cmp\\t%2, %3\", operands);
8395     if (which_alternative != 0)
8396       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8397     return \"sub%d4\\t%0, %1, #1\";
8398   "
8399   [(set_attr "conds" "clob")
8400    (set_attr "length" "8,12")]
8403 (define_insn "*cmp_ite0"
8404   [(set (match_operand 6 "dominant_cc_register" "")
8405         (compare
8406          (if_then_else:SI
8407           (match_operator 4 "arm_comparison_operator"
8408            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8409             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8410           (match_operator:SI 5 "arm_comparison_operator"
8411            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8412             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8413           (const_int 0))
8414          (const_int 0)))]
8415   "TARGET_ARM"
8416   "*
8417   {
8418     static const char * const opcodes[4][2] =
8419     {
8420       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8421        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8422       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8423        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8424       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8425        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8426       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8427        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8428     };
8429     int swap =
8430       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8432     return opcodes[which_alternative][swap];
8433   }"
8434   [(set_attr "conds" "set")
8435    (set_attr "length" "8")]
8438 (define_insn "*cmp_ite1"
8439   [(set (match_operand 6 "dominant_cc_register" "")
8440         (compare
8441          (if_then_else:SI
8442           (match_operator 4 "arm_comparison_operator"
8443            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8444             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8445           (match_operator:SI 5 "arm_comparison_operator"
8446            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8447             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8448           (const_int 1))
8449          (const_int 0)))]
8450   "TARGET_ARM"
8451   "*
8452   {
8453     static const char * const opcodes[4][2] =
8454     {
8455       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8456        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8457       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8458        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8459       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8460        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8461       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8462        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8463     };
8464     int swap =
8465       comparison_dominates_p (GET_CODE (operands[5]),
8466                               reverse_condition (GET_CODE (operands[4])));
8468     return opcodes[which_alternative][swap];
8469   }"
8470   [(set_attr "conds" "set")
8471    (set_attr "length" "8")]
8474 (define_insn "*cmp_and"
8475   [(set (match_operand 6 "dominant_cc_register" "")
8476         (compare
8477          (and:SI
8478           (match_operator 4 "arm_comparison_operator"
8479            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8480             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8481           (match_operator:SI 5 "arm_comparison_operator"
8482            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8483             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8484          (const_int 0)))]
8485   "TARGET_ARM"
8486   "*
8487   {
8488     static const char *const opcodes[4][2] =
8489     {
8490       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8491        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8492       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8493        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8494       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8495        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8496       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8497        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8498     };
8499     int swap =
8500       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8502     return opcodes[which_alternative][swap];
8503   }"
8504   [(set_attr "conds" "set")
8505    (set_attr "predicable" "no")
8506    (set_attr "length" "8")]
8509 (define_insn "*cmp_ior"
8510   [(set (match_operand 6 "dominant_cc_register" "")
8511         (compare
8512          (ior:SI
8513           (match_operator 4 "arm_comparison_operator"
8514            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8515             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8516           (match_operator:SI 5 "arm_comparison_operator"
8517            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8518             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8519          (const_int 0)))]
8520   "TARGET_ARM"
8521   "*
8523   static const char *const opcodes[4][2] =
8524   {
8525     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8526      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8527     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8528      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8529     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8530      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8531     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8532      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8533   };
8534   int swap =
8535     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8537   return opcodes[which_alternative][swap];
8540   [(set_attr "conds" "set")
8541    (set_attr "length" "8")]
8544 (define_insn_and_split "*ior_scc_scc"
8545   [(set (match_operand:SI 0 "s_register_operand" "=r")
8546         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8547                  [(match_operand:SI 1 "s_register_operand" "r")
8548                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8549                 (match_operator:SI 6 "arm_comparison_operator"
8550                  [(match_operand:SI 4 "s_register_operand" "r")
8551                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8552    (clobber (reg:CC CC_REGNUM))]
8553   "TARGET_ARM
8554    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8555        != CCmode)"
8556   "#"
8557   "TARGET_ARM && reload_completed"
8558   [(set (match_dup 7)
8559         (compare
8560          (ior:SI
8561           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8562           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8563          (const_int 0)))
8564    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8565   "operands[7]
8566      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8567                                                   DOM_CC_X_OR_Y),
8568                     CC_REGNUM);"
8569   [(set_attr "conds" "clob")
8570    (set_attr "length" "16")])
8572 ; If the above pattern is followed by a CMP insn, then the compare is 
8573 ; redundant, since we can rework the conditional instruction that follows.
8574 (define_insn_and_split "*ior_scc_scc_cmp"
8575   [(set (match_operand 0 "dominant_cc_register" "")
8576         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8577                           [(match_operand:SI 1 "s_register_operand" "r")
8578                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8579                          (match_operator:SI 6 "arm_comparison_operator"
8580                           [(match_operand:SI 4 "s_register_operand" "r")
8581                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8582                  (const_int 0)))
8583    (set (match_operand:SI 7 "s_register_operand" "=r")
8584         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8585                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8586   "TARGET_ARM"
8587   "#"
8588   "TARGET_ARM && reload_completed"
8589   [(set (match_dup 0)
8590         (compare
8591          (ior:SI
8592           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8593           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8594          (const_int 0)))
8595    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8596   ""
8597   [(set_attr "conds" "set")
8598    (set_attr "length" "16")])
8600 (define_insn_and_split "*and_scc_scc"
8601   [(set (match_operand:SI 0 "s_register_operand" "=r")
8602         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8603                  [(match_operand:SI 1 "s_register_operand" "r")
8604                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8605                 (match_operator:SI 6 "arm_comparison_operator"
8606                  [(match_operand:SI 4 "s_register_operand" "r")
8607                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8608    (clobber (reg:CC CC_REGNUM))]
8609   "TARGET_ARM
8610    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8611        != CCmode)"
8612   "#"
8613   "TARGET_ARM && reload_completed
8614    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8615        != CCmode)"
8616   [(set (match_dup 7)
8617         (compare
8618          (and:SI
8619           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8620           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8621          (const_int 0)))
8622    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8623   "operands[7]
8624      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8625                                                   DOM_CC_X_AND_Y),
8626                     CC_REGNUM);"
8627   [(set_attr "conds" "clob")
8628    (set_attr "length" "16")])
8630 ; If the above pattern is followed by a CMP insn, then the compare is 
8631 ; redundant, since we can rework the conditional instruction that follows.
8632 (define_insn_and_split "*and_scc_scc_cmp"
8633   [(set (match_operand 0 "dominant_cc_register" "")
8634         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8635                           [(match_operand:SI 1 "s_register_operand" "r")
8636                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8637                          (match_operator:SI 6 "arm_comparison_operator"
8638                           [(match_operand:SI 4 "s_register_operand" "r")
8639                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8640                  (const_int 0)))
8641    (set (match_operand:SI 7 "s_register_operand" "=r")
8642         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8643                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8644   "TARGET_ARM"
8645   "#"
8646   "TARGET_ARM && reload_completed"
8647   [(set (match_dup 0)
8648         (compare
8649          (and:SI
8650           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8651           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8652          (const_int 0)))
8653    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8654   ""
8655   [(set_attr "conds" "set")
8656    (set_attr "length" "16")])
8658 ;; If there is no dominance in the comparison, then we can still save an
8659 ;; instruction in the AND case, since we can know that the second compare
8660 ;; need only zero the value if false (if true, then the value is already
8661 ;; correct).
8662 (define_insn_and_split "*and_scc_scc_nodom"
8663   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8664         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8665                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8666                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8667                 (match_operator:SI 6 "arm_comparison_operator"
8668                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8669                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8670    (clobber (reg:CC CC_REGNUM))]
8671   "TARGET_ARM
8672    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8673        == CCmode)"
8674   "#"
8675   "TARGET_ARM && reload_completed"
8676   [(parallel [(set (match_dup 0)
8677                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8678               (clobber (reg:CC CC_REGNUM))])
8679    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8680    (set (match_dup 0)
8681         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8682                          (match_dup 0)
8683                          (const_int 0)))]
8684   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8685                                               operands[4], operands[5]),
8686                               CC_REGNUM);
8687    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8688                                   operands[5]);"
8689   [(set_attr "conds" "clob")
8690    (set_attr "length" "20")])
8692 (define_split
8693   [(set (reg:CC_NOOV CC_REGNUM)
8694         (compare:CC_NOOV (ior:SI
8695                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8696                                   (const_int 1))
8697                           (match_operator:SI 1 "comparison_operator"
8698                            [(match_operand:SI 2 "s_register_operand" "")
8699                             (match_operand:SI 3 "arm_add_operand" "")]))
8700                          (const_int 0)))
8701    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8702   "TARGET_ARM"
8703   [(set (match_dup 4)
8704         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8705                 (match_dup 0)))
8706    (set (reg:CC_NOOV CC_REGNUM)
8707         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8708                          (const_int 0)))]
8709   "")
8711 (define_split
8712   [(set (reg:CC_NOOV CC_REGNUM)
8713         (compare:CC_NOOV (ior:SI
8714                           (match_operator:SI 1 "comparison_operator"
8715                            [(match_operand:SI 2 "s_register_operand" "")
8716                             (match_operand:SI 3 "arm_add_operand" "")])
8717                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8718                                   (const_int 1)))
8719                          (const_int 0)))
8720    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8721   "TARGET_ARM"
8722   [(set (match_dup 4)
8723         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8724                 (match_dup 0)))
8725    (set (reg:CC_NOOV CC_REGNUM)
8726         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8727                          (const_int 0)))]
8728   "")
8730 (define_insn "*negscc"
8731   [(set (match_operand:SI 0 "s_register_operand" "=r")
8732         (neg:SI (match_operator 3 "arm_comparison_operator"
8733                  [(match_operand:SI 1 "s_register_operand" "r")
8734                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8735    (clobber (reg:CC CC_REGNUM))]
8736   "TARGET_ARM"
8737   "*
8738   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8739     return \"mov\\t%0, %1, asr #31\";
8741   if (GET_CODE (operands[3]) == NE)
8742     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8744   if (GET_CODE (operands[3]) == GT)
8745     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8747   output_asm_insn (\"cmp\\t%1, %2\", operands);
8748   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8749   return \"mvn%d3\\t%0, #0\";
8750   "
8751   [(set_attr "conds" "clob")
8752    (set_attr "length" "12")]
8755 (define_insn "movcond"
8756   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8757         (if_then_else:SI
8758          (match_operator 5 "arm_comparison_operator"
8759           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8760            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8761          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8762          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8763    (clobber (reg:CC CC_REGNUM))]
8764   "TARGET_ARM"
8765   "*
8766   if (GET_CODE (operands[5]) == LT
8767       && (operands[4] == const0_rtx))
8768     {
8769       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8770         {
8771           if (operands[2] == const0_rtx)
8772             return \"and\\t%0, %1, %3, asr #31\";
8773           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8774         }
8775       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8776         {
8777           if (operands[1] == const0_rtx)
8778             return \"bic\\t%0, %2, %3, asr #31\";
8779           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8780         }
8781       /* The only case that falls through to here is when both ops 1 & 2
8782          are constants.  */
8783     }
8785   if (GET_CODE (operands[5]) == GE
8786       && (operands[4] == const0_rtx))
8787     {
8788       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8789         {
8790           if (operands[2] == const0_rtx)
8791             return \"bic\\t%0, %1, %3, asr #31\";
8792           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8793         }
8794       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8795         {
8796           if (operands[1] == const0_rtx)
8797             return \"and\\t%0, %2, %3, asr #31\";
8798           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8799         }
8800       /* The only case that falls through to here is when both ops 1 & 2
8801          are constants.  */
8802     }
8803   if (GET_CODE (operands[4]) == CONST_INT
8804       && !const_ok_for_arm (INTVAL (operands[4])))
8805     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8806   else
8807     output_asm_insn (\"cmp\\t%3, %4\", operands);
8808   if (which_alternative != 0)
8809     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8810   if (which_alternative != 1)
8811     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8812   return \"\";
8813   "
8814   [(set_attr "conds" "clob")
8815    (set_attr "length" "8,8,12")]
8818 (define_insn "*ifcompare_plus_move"
8819   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8820         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8821                           [(match_operand:SI 4 "s_register_operand" "r,r")
8822                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8823                          (plus:SI
8824                           (match_operand:SI 2 "s_register_operand" "r,r")
8825                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8826                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8827    (clobber (reg:CC CC_REGNUM))]
8828   "TARGET_ARM"
8829   "#"
8830   [(set_attr "conds" "clob")
8831    (set_attr "length" "8,12")]
8834 (define_insn "*if_plus_move"
8835   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8836         (if_then_else:SI
8837          (match_operator 4 "arm_comparison_operator"
8838           [(match_operand 5 "cc_register" "") (const_int 0)])
8839          (plus:SI
8840           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8841           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8842          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8843   "TARGET_ARM"
8844   "@
8845    add%d4\\t%0, %2, %3
8846    sub%d4\\t%0, %2, #%n3
8847    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8848    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8849   [(set_attr "conds" "use")
8850    (set_attr "length" "4,4,8,8")
8851    (set_attr "type" "*,*,*,*")]
8854 (define_insn "*ifcompare_move_plus"
8855   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8856         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8857                           [(match_operand:SI 4 "s_register_operand" "r,r")
8858                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8859                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8860                          (plus:SI
8861                           (match_operand:SI 2 "s_register_operand" "r,r")
8862                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8863    (clobber (reg:CC CC_REGNUM))]
8864   "TARGET_ARM"
8865   "#"
8866   [(set_attr "conds" "clob")
8867    (set_attr "length" "8,12")]
8870 (define_insn "*if_move_plus"
8871   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8872         (if_then_else:SI
8873          (match_operator 4 "arm_comparison_operator"
8874           [(match_operand 5 "cc_register" "") (const_int 0)])
8875          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8876          (plus:SI
8877           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8878           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8879   "TARGET_ARM"
8880   "@
8881    add%D4\\t%0, %2, %3
8882    sub%D4\\t%0, %2, #%n3
8883    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8884    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8885   [(set_attr "conds" "use")
8886    (set_attr "length" "4,4,8,8")
8887    (set_attr "type" "*,*,*,*")]
8890 (define_insn "*ifcompare_arith_arith"
8891   [(set (match_operand:SI 0 "s_register_operand" "=r")
8892         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8893                           [(match_operand:SI 5 "s_register_operand" "r")
8894                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8895                          (match_operator:SI 8 "shiftable_operator"
8896                           [(match_operand:SI 1 "s_register_operand" "r")
8897                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8898                          (match_operator:SI 7 "shiftable_operator"
8899                           [(match_operand:SI 3 "s_register_operand" "r")
8900                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8901    (clobber (reg:CC CC_REGNUM))]
8902   "TARGET_ARM"
8903   "#"
8904   [(set_attr "conds" "clob")
8905    (set_attr "length" "12")]
8908 (define_insn "*if_arith_arith"
8909   [(set (match_operand:SI 0 "s_register_operand" "=r")
8910         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8911                           [(match_operand 8 "cc_register" "") (const_int 0)])
8912                          (match_operator:SI 6 "shiftable_operator"
8913                           [(match_operand:SI 1 "s_register_operand" "r")
8914                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8915                          (match_operator:SI 7 "shiftable_operator"
8916                           [(match_operand:SI 3 "s_register_operand" "r")
8917                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8918   "TARGET_ARM"
8919   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8920   [(set_attr "conds" "use")
8921    (set_attr "length" "8")]
8924 (define_insn "*ifcompare_arith_move"
8925   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8926         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8927                           [(match_operand:SI 2 "s_register_operand" "r,r")
8928                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8929                          (match_operator:SI 7 "shiftable_operator"
8930                           [(match_operand:SI 4 "s_register_operand" "r,r")
8931                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8932                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8933    (clobber (reg:CC CC_REGNUM))]
8934   "TARGET_ARM"
8935   "*
8936   /* If we have an operation where (op x 0) is the identity operation and
8937      the conditional operator is LT or GE and we are comparing against zero and
8938      everything is in registers then we can do this in two instructions.  */
8939   if (operands[3] == const0_rtx
8940       && GET_CODE (operands[7]) != AND
8941       && GET_CODE (operands[5]) == REG
8942       && GET_CODE (operands[1]) == REG 
8943       && REGNO (operands[1]) == REGNO (operands[4])
8944       && REGNO (operands[4]) != REGNO (operands[0]))
8945     {
8946       if (GET_CODE (operands[6]) == LT)
8947         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8948       else if (GET_CODE (operands[6]) == GE)
8949         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8950     }
8951   if (GET_CODE (operands[3]) == CONST_INT
8952       && !const_ok_for_arm (INTVAL (operands[3])))
8953     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8954   else
8955     output_asm_insn (\"cmp\\t%2, %3\", operands);
8956   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8957   if (which_alternative != 0)
8958     return \"mov%D6\\t%0, %1\";
8959   return \"\";
8960   "
8961   [(set_attr "conds" "clob")
8962    (set_attr "length" "8,12")]
8965 (define_insn "*if_arith_move"
8966   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8967         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8968                           [(match_operand 6 "cc_register" "") (const_int 0)])
8969                          (match_operator:SI 5 "shiftable_operator"
8970                           [(match_operand:SI 2 "s_register_operand" "r,r")
8971                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8972                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8973   "TARGET_ARM"
8974   "@
8975    %I5%d4\\t%0, %2, %3
8976    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8977   [(set_attr "conds" "use")
8978    (set_attr "length" "4,8")
8979    (set_attr "type" "*,*")]
8982 (define_insn "*ifcompare_move_arith"
8983   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8984         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8985                           [(match_operand:SI 4 "s_register_operand" "r,r")
8986                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8987                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8988                          (match_operator:SI 7 "shiftable_operator"
8989                           [(match_operand:SI 2 "s_register_operand" "r,r")
8990                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8991    (clobber (reg:CC CC_REGNUM))]
8992   "TARGET_ARM"
8993   "*
8994   /* If we have an operation where (op x 0) is the identity operation and
8995      the conditional operator is LT or GE and we are comparing against zero and
8996      everything is in registers then we can do this in two instructions */
8997   if (operands[5] == const0_rtx
8998       && GET_CODE (operands[7]) != AND
8999       && GET_CODE (operands[3]) == REG
9000       && GET_CODE (operands[1]) == REG 
9001       && REGNO (operands[1]) == REGNO (operands[2])
9002       && REGNO (operands[2]) != REGNO (operands[0]))
9003     {
9004       if (GET_CODE (operands[6]) == GE)
9005         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9006       else if (GET_CODE (operands[6]) == LT)
9007         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
9008     }
9010   if (GET_CODE (operands[5]) == CONST_INT
9011       && !const_ok_for_arm (INTVAL (operands[5])))
9012     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9013   else
9014     output_asm_insn (\"cmp\\t%4, %5\", operands);
9016   if (which_alternative != 0)
9017     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9018   return \"%I7%D6\\t%0, %2, %3\";
9019   "
9020   [(set_attr "conds" "clob")
9021    (set_attr "length" "8,12")]
9024 (define_insn "*if_move_arith"
9025   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9026         (if_then_else:SI
9027          (match_operator 4 "arm_comparison_operator"
9028           [(match_operand 6 "cc_register" "") (const_int 0)])
9029          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9030          (match_operator:SI 5 "shiftable_operator"
9031           [(match_operand:SI 2 "s_register_operand" "r,r")
9032            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9033   "TARGET_ARM"
9034   "@
9035    %I5%D4\\t%0, %2, %3
9036    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9037   [(set_attr "conds" "use")
9038    (set_attr "length" "4,8")
9039    (set_attr "type" "*,*")]
9042 (define_insn "*ifcompare_move_not"
9043   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9044         (if_then_else:SI
9045          (match_operator 5 "arm_comparison_operator"
9046           [(match_operand:SI 3 "s_register_operand" "r,r")
9047            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9048          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9049          (not:SI
9050           (match_operand:SI 2 "s_register_operand" "r,r"))))
9051    (clobber (reg:CC CC_REGNUM))]
9052   "TARGET_ARM"
9053   "#"
9054   [(set_attr "conds" "clob")
9055    (set_attr "length" "8,12")]
9058 (define_insn "*if_move_not"
9059   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9060         (if_then_else:SI
9061          (match_operator 4 "arm_comparison_operator"
9062           [(match_operand 3 "cc_register" "") (const_int 0)])
9063          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9064          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9065   "TARGET_ARM"
9066   "@
9067    mvn%D4\\t%0, %2
9068    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9069    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9070   [(set_attr "conds" "use")
9071    (set_attr "length" "4,8,8")]
9074 (define_insn "*ifcompare_not_move"
9075   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9076         (if_then_else:SI 
9077          (match_operator 5 "arm_comparison_operator"
9078           [(match_operand:SI 3 "s_register_operand" "r,r")
9079            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9080          (not:SI
9081           (match_operand:SI 2 "s_register_operand" "r,r"))
9082          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9083    (clobber (reg:CC CC_REGNUM))]
9084   "TARGET_ARM"
9085   "#"
9086   [(set_attr "conds" "clob")
9087    (set_attr "length" "8,12")]
9090 (define_insn "*if_not_move"
9091   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9092         (if_then_else:SI
9093          (match_operator 4 "arm_comparison_operator"
9094           [(match_operand 3 "cc_register" "") (const_int 0)])
9095          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9096          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9097   "TARGET_ARM"
9098   "@
9099    mvn%d4\\t%0, %2
9100    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9101    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9102   [(set_attr "conds" "use")
9103    (set_attr "length" "4,8,8")]
9106 (define_insn "*ifcompare_shift_move"
9107   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9108         (if_then_else:SI
9109          (match_operator 6 "arm_comparison_operator"
9110           [(match_operand:SI 4 "s_register_operand" "r,r")
9111            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9112          (match_operator:SI 7 "shift_operator"
9113           [(match_operand:SI 2 "s_register_operand" "r,r")
9114            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9115          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9116    (clobber (reg:CC CC_REGNUM))]
9117   "TARGET_ARM"
9118   "#"
9119   [(set_attr "conds" "clob")
9120    (set_attr "length" "8,12")]
9123 (define_insn "*if_shift_move"
9124   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9125         (if_then_else:SI
9126          (match_operator 5 "arm_comparison_operator"
9127           [(match_operand 6 "cc_register" "") (const_int 0)])
9128          (match_operator:SI 4 "shift_operator"
9129           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9130            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9131          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9132   "TARGET_ARM"
9133   "@
9134    mov%d5\\t%0, %2%S4
9135    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9136    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9137   [(set_attr "conds" "use")
9138    (set_attr "shift" "2")
9139    (set_attr "length" "4,8,8")
9140    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9141                       (const_string "alu_shift")
9142                       (const_string "alu_shift_reg")))]
9145 (define_insn "*ifcompare_move_shift"
9146   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9147         (if_then_else:SI
9148          (match_operator 6 "arm_comparison_operator"
9149           [(match_operand:SI 4 "s_register_operand" "r,r")
9150            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9151          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9152          (match_operator:SI 7 "shift_operator"
9153           [(match_operand:SI 2 "s_register_operand" "r,r")
9154            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9155    (clobber (reg:CC CC_REGNUM))]
9156   "TARGET_ARM"
9157   "#"
9158   [(set_attr "conds" "clob")
9159    (set_attr "length" "8,12")]
9162 (define_insn "*if_move_shift"
9163   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9164         (if_then_else:SI
9165          (match_operator 5 "arm_comparison_operator"
9166           [(match_operand 6 "cc_register" "") (const_int 0)])
9167          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9168          (match_operator:SI 4 "shift_operator"
9169           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9170            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9171   "TARGET_ARM"
9172   "@
9173    mov%D5\\t%0, %2%S4
9174    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9175    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9176   [(set_attr "conds" "use")
9177    (set_attr "shift" "2")
9178    (set_attr "length" "4,8,8")
9179    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9180                       (const_string "alu_shift")
9181                       (const_string "alu_shift_reg")))]
9184 (define_insn "*ifcompare_shift_shift"
9185   [(set (match_operand:SI 0 "s_register_operand" "=r")
9186         (if_then_else:SI
9187          (match_operator 7 "arm_comparison_operator"
9188           [(match_operand:SI 5 "s_register_operand" "r")
9189            (match_operand:SI 6 "arm_add_operand" "rIL")])
9190          (match_operator:SI 8 "shift_operator"
9191           [(match_operand:SI 1 "s_register_operand" "r")
9192            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9193          (match_operator:SI 9 "shift_operator"
9194           [(match_operand:SI 3 "s_register_operand" "r")
9195            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9196    (clobber (reg:CC CC_REGNUM))]
9197   "TARGET_ARM"
9198   "#"
9199   [(set_attr "conds" "clob")
9200    (set_attr "length" "12")]
9203 (define_insn "*if_shift_shift"
9204   [(set (match_operand:SI 0 "s_register_operand" "=r")
9205         (if_then_else:SI
9206          (match_operator 5 "arm_comparison_operator"
9207           [(match_operand 8 "cc_register" "") (const_int 0)])
9208          (match_operator:SI 6 "shift_operator"
9209           [(match_operand:SI 1 "s_register_operand" "r")
9210            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9211          (match_operator:SI 7 "shift_operator"
9212           [(match_operand:SI 3 "s_register_operand" "r")
9213            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9214   "TARGET_ARM"
9215   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9216   [(set_attr "conds" "use")
9217    (set_attr "shift" "1")
9218    (set_attr "length" "8")
9219    (set (attr "type") (if_then_else
9220                         (and (match_operand 2 "const_int_operand" "")
9221                              (match_operand 4 "const_int_operand" ""))
9222                       (const_string "alu_shift")
9223                       (const_string "alu_shift_reg")))]
9226 (define_insn "*ifcompare_not_arith"
9227   [(set (match_operand:SI 0 "s_register_operand" "=r")
9228         (if_then_else:SI
9229          (match_operator 6 "arm_comparison_operator"
9230           [(match_operand:SI 4 "s_register_operand" "r")
9231            (match_operand:SI 5 "arm_add_operand" "rIL")])
9232          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9233          (match_operator:SI 7 "shiftable_operator"
9234           [(match_operand:SI 2 "s_register_operand" "r")
9235            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9236    (clobber (reg:CC CC_REGNUM))]
9237   "TARGET_ARM"
9238   "#"
9239   [(set_attr "conds" "clob")
9240    (set_attr "length" "12")]
9243 (define_insn "*if_not_arith"
9244   [(set (match_operand:SI 0 "s_register_operand" "=r")
9245         (if_then_else:SI
9246          (match_operator 5 "arm_comparison_operator"
9247           [(match_operand 4 "cc_register" "") (const_int 0)])
9248          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9249          (match_operator:SI 6 "shiftable_operator"
9250           [(match_operand:SI 2 "s_register_operand" "r")
9251            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9252   "TARGET_ARM"
9253   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9254   [(set_attr "conds" "use")
9255    (set_attr "length" "8")]
9258 (define_insn "*ifcompare_arith_not"
9259   [(set (match_operand:SI 0 "s_register_operand" "=r")
9260         (if_then_else:SI
9261          (match_operator 6 "arm_comparison_operator"
9262           [(match_operand:SI 4 "s_register_operand" "r")
9263            (match_operand:SI 5 "arm_add_operand" "rIL")])
9264          (match_operator:SI 7 "shiftable_operator"
9265           [(match_operand:SI 2 "s_register_operand" "r")
9266            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9267          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9268    (clobber (reg:CC CC_REGNUM))]
9269   "TARGET_ARM"
9270   "#"
9271   [(set_attr "conds" "clob")
9272    (set_attr "length" "12")]
9275 (define_insn "*if_arith_not"
9276   [(set (match_operand:SI 0 "s_register_operand" "=r")
9277         (if_then_else:SI
9278          (match_operator 5 "arm_comparison_operator"
9279           [(match_operand 4 "cc_register" "") (const_int 0)])
9280          (match_operator:SI 6 "shiftable_operator"
9281           [(match_operand:SI 2 "s_register_operand" "r")
9282            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9283          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9284   "TARGET_ARM"
9285   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9286   [(set_attr "conds" "use")
9287    (set_attr "length" "8")]
9290 (define_insn "*ifcompare_neg_move"
9291   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9292         (if_then_else:SI
9293          (match_operator 5 "arm_comparison_operator"
9294           [(match_operand:SI 3 "s_register_operand" "r,r")
9295            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9296          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9297          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9298    (clobber (reg:CC CC_REGNUM))]
9299   "TARGET_ARM"
9300   "#"
9301   [(set_attr "conds" "clob")
9302    (set_attr "length" "8,12")]
9305 (define_insn "*if_neg_move"
9306   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9307         (if_then_else:SI
9308          (match_operator 4 "arm_comparison_operator"
9309           [(match_operand 3 "cc_register" "") (const_int 0)])
9310          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9311          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9312   "TARGET_ARM"
9313   "@
9314    rsb%d4\\t%0, %2, #0
9315    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9316    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9317   [(set_attr "conds" "use")
9318    (set_attr "length" "4,8,8")]
9321 (define_insn "*ifcompare_move_neg"
9322   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9323         (if_then_else:SI
9324          (match_operator 5 "arm_comparison_operator"
9325           [(match_operand:SI 3 "s_register_operand" "r,r")
9326            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9327          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9328          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9329    (clobber (reg:CC CC_REGNUM))]
9330   "TARGET_ARM"
9331   "#"
9332   [(set_attr "conds" "clob")
9333    (set_attr "length" "8,12")]
9336 (define_insn "*if_move_neg"
9337   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9338         (if_then_else:SI
9339          (match_operator 4 "arm_comparison_operator"
9340           [(match_operand 3 "cc_register" "") (const_int 0)])
9341          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9342          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9343   "TARGET_ARM"
9344   "@
9345    rsb%D4\\t%0, %2, #0
9346    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9347    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9348   [(set_attr "conds" "use")
9349    (set_attr "length" "4,8,8")]
9352 (define_insn "*arith_adjacentmem"
9353   [(set (match_operand:SI 0 "s_register_operand" "=r")
9354         (match_operator:SI 1 "shiftable_operator"
9355          [(match_operand:SI 2 "memory_operand" "m")
9356           (match_operand:SI 3 "memory_operand" "m")]))
9357    (clobber (match_scratch:SI 4 "=r"))]
9358   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9359   "*
9360   {
9361     rtx ldm[3];
9362     rtx arith[4];
9363     rtx base_reg;
9364     HOST_WIDE_INT val1 = 0, val2 = 0;
9366     if (REGNO (operands[0]) > REGNO (operands[4]))
9367       {
9368         ldm[1] = operands[4];
9369         ldm[2] = operands[0];
9370       }
9371     else
9372       {
9373         ldm[1] = operands[0];
9374         ldm[2] = operands[4];
9375       }
9377     base_reg = XEXP (operands[2], 0);
9379     if (!REG_P (base_reg))
9380       {
9381         val1 = INTVAL (XEXP (base_reg, 1));
9382         base_reg = XEXP (base_reg, 0);
9383       }
9385     if (!REG_P (XEXP (operands[3], 0)))
9386       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9388     arith[0] = operands[0];
9389     arith[3] = operands[1];
9391     if (val1 < val2)
9392       {
9393         arith[1] = ldm[1];
9394         arith[2] = ldm[2];
9395       }
9396     else
9397       {
9398         arith[1] = ldm[2];
9399         arith[2] = ldm[1];
9400       }
9402     ldm[0] = base_reg;
9403     if (val1 !=0 && val2 != 0)
9404       {
9405         if (val1 == 4 || val2 == 4)
9406           /* Other val must be 8, since we know they are adjacent and neither
9407              is zero.  */
9408           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9409         else
9410           {
9411             rtx ops[3];
9413             ldm[0] = ops[0] = operands[4];
9414             ops[1] = base_reg;
9415             ops[2] = GEN_INT (val1);
9416             output_add_immediate (ops);
9417             if (val1 < val2)
9418               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9419             else
9420               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9421           }
9422       }
9423     else if (val1 != 0)
9424       {
9425         if (val1 < val2)
9426           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9427         else
9428           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9429       }
9430     else
9431       {
9432         if (val1 < val2)
9433           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9434         else
9435           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9436       }
9437     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9438     return \"\";
9439   }"
9440   [(set_attr "length" "12")
9441    (set_attr "predicable" "yes")
9442    (set_attr "type" "load1")]
9445 ; This pattern is never tried by combine, so do it as a peephole
9447 (define_peephole2
9448   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9449         (match_operand:SI 1 "arm_general_register_operand" ""))
9450    (set (reg:CC CC_REGNUM)
9451         (compare:CC (match_dup 1) (const_int 0)))]
9452   "TARGET_ARM"
9453   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9454               (set (match_dup 0) (match_dup 1))])]
9455   ""
9458 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9459 ; reversed, check that the memory references aren't volatile.
9461 (define_peephole
9462   [(set (match_operand:SI 0 "s_register_operand" "=r")
9463         (match_operand:SI 4 "memory_operand" "m"))
9464    (set (match_operand:SI 1 "s_register_operand" "=r")
9465         (match_operand:SI 5 "memory_operand" "m"))
9466    (set (match_operand:SI 2 "s_register_operand" "=r")
9467         (match_operand:SI 6 "memory_operand" "m"))
9468    (set (match_operand:SI 3 "s_register_operand" "=r")
9469         (match_operand:SI 7 "memory_operand" "m"))]
9470   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9471   "*
9472   return emit_ldm_seq (operands, 4);
9473   "
9476 (define_peephole
9477   [(set (match_operand:SI 0 "s_register_operand" "=r")
9478         (match_operand:SI 3 "memory_operand" "m"))
9479    (set (match_operand:SI 1 "s_register_operand" "=r")
9480         (match_operand:SI 4 "memory_operand" "m"))
9481    (set (match_operand:SI 2 "s_register_operand" "=r")
9482         (match_operand:SI 5 "memory_operand" "m"))]
9483   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9484   "*
9485   return emit_ldm_seq (operands, 3);
9486   "
9489 (define_peephole
9490   [(set (match_operand:SI 0 "s_register_operand" "=r")
9491         (match_operand:SI 2 "memory_operand" "m"))
9492    (set (match_operand:SI 1 "s_register_operand" "=r")
9493         (match_operand:SI 3 "memory_operand" "m"))]
9494   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9495   "*
9496   return emit_ldm_seq (operands, 2);
9497   "
9500 (define_peephole
9501   [(set (match_operand:SI 4 "memory_operand" "=m")
9502         (match_operand:SI 0 "s_register_operand" "r"))
9503    (set (match_operand:SI 5 "memory_operand" "=m")
9504         (match_operand:SI 1 "s_register_operand" "r"))
9505    (set (match_operand:SI 6 "memory_operand" "=m")
9506         (match_operand:SI 2 "s_register_operand" "r"))
9507    (set (match_operand:SI 7 "memory_operand" "=m")
9508         (match_operand:SI 3 "s_register_operand" "r"))]
9509   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9510   "*
9511   return emit_stm_seq (operands, 4);
9512   "
9515 (define_peephole
9516   [(set (match_operand:SI 3 "memory_operand" "=m")
9517         (match_operand:SI 0 "s_register_operand" "r"))
9518    (set (match_operand:SI 4 "memory_operand" "=m")
9519         (match_operand:SI 1 "s_register_operand" "r"))
9520    (set (match_operand:SI 5 "memory_operand" "=m")
9521         (match_operand:SI 2 "s_register_operand" "r"))]
9522   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9523   "*
9524   return emit_stm_seq (operands, 3);
9525   "
9528 (define_peephole
9529   [(set (match_operand:SI 2 "memory_operand" "=m")
9530         (match_operand:SI 0 "s_register_operand" "r"))
9531    (set (match_operand:SI 3 "memory_operand" "=m")
9532         (match_operand:SI 1 "s_register_operand" "r"))]
9533   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9534   "*
9535   return emit_stm_seq (operands, 2);
9536   "
9539 (define_split
9540   [(set (match_operand:SI 0 "s_register_operand" "")
9541         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9542                        (const_int 0))
9543                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9544                          [(match_operand:SI 3 "s_register_operand" "")
9545                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9546    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9547   "TARGET_ARM"
9548   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9549    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9550                               (match_dup 5)))]
9551   ""
9554 ;; This split can be used because CC_Z mode implies that the following
9555 ;; branch will be an equality, or an unsigned inequality, so the sign
9556 ;; extension is not needed.
9558 (define_split
9559   [(set (reg:CC_Z CC_REGNUM)
9560         (compare:CC_Z
9561          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9562                     (const_int 24))
9563          (match_operand 1 "const_int_operand" "")))
9564    (clobber (match_scratch:SI 2 ""))]
9565   "TARGET_ARM
9566    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9567        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9568   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9569    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9570   "
9571   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9572   "
9575 (define_expand "prologue"
9576   [(clobber (const_int 0))]
9577   "TARGET_EITHER"
9578   "if (TARGET_ARM)
9579      arm_expand_prologue ();
9580    else
9581      thumb_expand_prologue ();
9582   DONE;
9583   "
9586 (define_expand "epilogue"
9587   [(clobber (const_int 0))]
9588   "TARGET_EITHER"
9589   "
9590   if (current_function_calls_eh_return)
9591     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9592   if (TARGET_THUMB)
9593     thumb_expand_epilogue ();
9594   else if (USE_RETURN_INSN (FALSE))
9595     {
9596       emit_jump_insn (gen_return ());
9597       DONE;
9598     }
9599   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9600         gen_rtvec (1,
9601                 gen_rtx_RETURN (VOIDmode)),
9602         VUNSPEC_EPILOGUE));
9603   DONE;
9604   "
9607 ;; Note - although unspec_volatile's USE all hard registers,
9608 ;; USEs are ignored after relaod has completed.  Thus we need
9609 ;; to add an unspec of the link register to ensure that flow
9610 ;; does not think that it is unused by the sibcall branch that
9611 ;; will replace the standard function epilogue.
9612 (define_insn "sibcall_epilogue"
9613   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9614               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9615   "TARGET_ARM"
9616   "*
9617   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9618     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9619   return arm_output_epilogue (next_nonnote_insn (insn));
9620   "
9621 ;; Length is absolute worst case
9622   [(set_attr "length" "44")
9623    (set_attr "type" "block")
9624    ;; We don't clobber the conditions, but the potential length of this
9625    ;; operation is sufficient to make conditionalizing the sequence 
9626    ;; unlikely to be profitable.
9627    (set_attr "conds" "clob")]
9630 (define_insn "*epilogue_insns"
9631   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9632   "TARGET_EITHER"
9633   "*
9634   if (TARGET_ARM)
9635     return arm_output_epilogue (NULL);
9636   else /* TARGET_THUMB */
9637     return thumb_unexpanded_epilogue ();
9638   "
9639   ; Length is absolute worst case
9640   [(set_attr "length" "44")
9641    (set_attr "type" "block")
9642    ;; We don't clobber the conditions, but the potential length of this
9643    ;; operation is sufficient to make conditionalizing the sequence 
9644    ;; unlikely to be profitable.
9645    (set_attr "conds" "clob")]
9648 (define_expand "eh_epilogue"
9649   [(use (match_operand:SI 0 "register_operand" ""))
9650    (use (match_operand:SI 1 "register_operand" ""))
9651    (use (match_operand:SI 2 "register_operand" ""))]
9652   "TARGET_EITHER"
9653   "
9654   {
9655     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9656     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9657       {
9658         rtx ra = gen_rtx_REG (Pmode, 2);
9660         emit_move_insn (ra, operands[2]);
9661         operands[2] = ra;
9662       }
9663     /* This is a hack -- we may have crystalized the function type too
9664        early.  */
9665     cfun->machine->func_type = 0;
9666   }"
9669 ;; This split is only used during output to reduce the number of patterns
9670 ;; that need assembler instructions adding to them.  We allowed the setting
9671 ;; of the conditions to be implicit during rtl generation so that
9672 ;; the conditional compare patterns would work.  However this conflicts to
9673 ;; some extent with the conditional data operations, so we have to split them
9674 ;; up again here.
9676 (define_split
9677   [(set (match_operand:SI 0 "s_register_operand" "")
9678         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9679                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9680                          (match_dup 0)
9681                          (match_operand 4 "" "")))
9682    (clobber (reg:CC CC_REGNUM))]
9683   "TARGET_ARM && reload_completed"
9684   [(set (match_dup 5) (match_dup 6))
9685    (cond_exec (match_dup 7)
9686               (set (match_dup 0) (match_dup 4)))]
9687   "
9688   {
9689     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9690                                              operands[2], operands[3]);
9691     enum rtx_code rc = GET_CODE (operands[1]);
9693     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9694     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9695     if (mode == CCFPmode || mode == CCFPEmode)
9696       rc = reverse_condition_maybe_unordered (rc);
9697     else
9698       rc = reverse_condition (rc);
9700     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9701   }"
9704 (define_split
9705   [(set (match_operand:SI 0 "s_register_operand" "")
9706         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9707                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9708                          (match_operand 4 "" "")
9709                          (match_dup 0)))
9710    (clobber (reg:CC CC_REGNUM))]
9711   "TARGET_ARM && reload_completed"
9712   [(set (match_dup 5) (match_dup 6))
9713    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9714               (set (match_dup 0) (match_dup 4)))]
9715   "
9716   {
9717     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9718                                              operands[2], operands[3]);
9720     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9721     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9722   }"
9725 (define_split
9726   [(set (match_operand:SI 0 "s_register_operand" "")
9727         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9728                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9729                          (match_operand 4 "" "")
9730                          (match_operand 5 "" "")))
9731    (clobber (reg:CC CC_REGNUM))]
9732   "TARGET_ARM && reload_completed"
9733   [(set (match_dup 6) (match_dup 7))
9734    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9735               (set (match_dup 0) (match_dup 4)))
9736    (cond_exec (match_dup 8)
9737               (set (match_dup 0) (match_dup 5)))]
9738   "
9739   {
9740     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9741                                              operands[2], operands[3]);
9742     enum rtx_code rc = GET_CODE (operands[1]);
9744     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9745     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9746     if (mode == CCFPmode || mode == CCFPEmode)
9747       rc = reverse_condition_maybe_unordered (rc);
9748     else
9749       rc = reverse_condition (rc);
9751     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9752   }"
9755 (define_split
9756   [(set (match_operand:SI 0 "s_register_operand" "")
9757         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9758                           [(match_operand:SI 2 "s_register_operand" "")
9759                            (match_operand:SI 3 "arm_add_operand" "")])
9760                          (match_operand:SI 4 "arm_rhs_operand" "")
9761                          (not:SI
9762                           (match_operand:SI 5 "s_register_operand" ""))))
9763    (clobber (reg:CC CC_REGNUM))]
9764   "TARGET_ARM && reload_completed"
9765   [(set (match_dup 6) (match_dup 7))
9766    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9767               (set (match_dup 0) (match_dup 4)))
9768    (cond_exec (match_dup 8)
9769               (set (match_dup 0) (not:SI (match_dup 5))))]
9770   "
9771   {
9772     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9773                                              operands[2], operands[3]);
9774     enum rtx_code rc = GET_CODE (operands[1]);
9776     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9777     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9778     if (mode == CCFPmode || mode == CCFPEmode)
9779       rc = reverse_condition_maybe_unordered (rc);
9780     else
9781       rc = reverse_condition (rc);
9783     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9784   }"
9787 (define_insn "*cond_move_not"
9788   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9789         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9790                           [(match_operand 3 "cc_register" "") (const_int 0)])
9791                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9792                          (not:SI
9793                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9794   "TARGET_ARM"
9795   "@
9796    mvn%D4\\t%0, %2
9797    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9798   [(set_attr "conds" "use")
9799    (set_attr "length" "4,8")]
9802 ;; The next two patterns occur when an AND operation is followed by a
9803 ;; scc insn sequence 
9805 (define_insn "*sign_extract_onebit"
9806   [(set (match_operand:SI 0 "s_register_operand" "=r")
9807         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9808                          (const_int 1)
9809                          (match_operand:SI 2 "const_int_operand" "n")))
9810     (clobber (reg:CC CC_REGNUM))]
9811   "TARGET_ARM"
9812   "*
9813     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9814     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9815     return \"mvnne\\t%0, #0\";
9816   "
9817   [(set_attr "conds" "clob")
9818    (set_attr "length" "8")]
9821 (define_insn "*not_signextract_onebit"
9822   [(set (match_operand:SI 0 "s_register_operand" "=r")
9823         (not:SI
9824          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9825                           (const_int 1)
9826                           (match_operand:SI 2 "const_int_operand" "n"))))
9827    (clobber (reg:CC CC_REGNUM))]
9828   "TARGET_ARM"
9829   "*
9830     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9831     output_asm_insn (\"tst\\t%1, %2\", operands);
9832     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9833     return \"movne\\t%0, #0\";
9834   "
9835   [(set_attr "conds" "clob")
9836    (set_attr "length" "12")]
9839 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9840 ;; expressions.  For simplicity, the first register is also in the unspec
9841 ;; part.
9842 (define_insn "*push_multi"
9843   [(match_parallel 2 "multi_register_push"
9844     [(set (match_operand:BLK 0 "memory_operand" "=m")
9845           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9846                       UNSPEC_PUSH_MULT))])]
9847   "TARGET_ARM"
9848   "*
9849   {
9850     int num_saves = XVECLEN (operands[2], 0);
9851      
9852     /* For the StrongARM at least it is faster to
9853        use STR to store only a single register.  */
9854     if (num_saves == 1)
9855       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9856     else
9857       {
9858         int i;
9859         char pattern[100];
9861         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9863         for (i = 1; i < num_saves; i++)
9864           {
9865             strcat (pattern, \", %|\");
9866             strcat (pattern,
9867                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9868           }
9870         strcat (pattern, \"}\");
9871         output_asm_insn (pattern, operands);
9872       }
9874     return \"\";
9875   }"
9876   [(set_attr "type" "store4")]
9879 (define_insn "stack_tie"
9880   [(set (mem:BLK (scratch))
9881         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9882                      (match_operand:SI 1 "s_register_operand" "r")]
9883                     UNSPEC_PRLG_STK))]
9884   ""
9885   ""
9886   [(set_attr "length" "0")]
9889 ;; Similarly for the floating point registers
9890 (define_insn "*push_fp_multi"
9891   [(match_parallel 2 "multi_register_push"
9892     [(set (match_operand:BLK 0 "memory_operand" "=m")
9893           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9894                       UNSPEC_PUSH_MULT))])]
9895   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
9896   "*
9897   {
9898     char pattern[100];
9900     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9901     output_asm_insn (pattern, operands);
9902     return \"\";
9903   }"
9904   [(set_attr "type" "f_store")]
9907 ;; Special patterns for dealing with the constant pool
9909 (define_insn "align_4"
9910   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9911   "TARGET_EITHER"
9912   "*
9913   assemble_align (32);
9914   return \"\";
9915   "
9918 (define_insn "align_8"
9919   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9920   "TARGET_EITHER"
9921   "*
9922   assemble_align (64);
9923   return \"\";
9924   "
9927 (define_insn "consttable_end"
9928   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9929   "TARGET_EITHER"
9930   "*
9931   making_const_table = FALSE;
9932   return \"\";
9933   "
9936 (define_insn "consttable_1"
9937   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9938   "TARGET_THUMB"
9939   "*
9940   making_const_table = TRUE;
9941   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9942   assemble_zeros (3);
9943   return \"\";
9944   "
9945   [(set_attr "length" "4")]
9948 (define_insn "consttable_2"
9949   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9950   "TARGET_THUMB"
9951   "*
9952   making_const_table = TRUE;
9953   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9954   assemble_zeros (2);
9955   return \"\";
9956   "
9957   [(set_attr "length" "4")]
9960 (define_insn "consttable_4"
9961   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9962   "TARGET_EITHER"
9963   "*
9964   {
9965     making_const_table = TRUE;
9966     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9967       {
9968       case MODE_FLOAT:
9969       {
9970         REAL_VALUE_TYPE r;
9971         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9972         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9973         break;
9974       }
9975       default:
9976         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9977         break;
9978       }
9979     return \"\";
9980   }"
9981   [(set_attr "length" "4")]
9984 (define_insn "consttable_8"
9985   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9986   "TARGET_EITHER"
9987   "*
9988   {
9989     making_const_table = TRUE;
9990     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9991       {
9992        case MODE_FLOAT:
9993         {
9994           REAL_VALUE_TYPE r;
9995           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9996           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9997           break;
9998         }
9999       default:
10000         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10001         break;
10002       }
10003     return \"\";
10004   }"
10005   [(set_attr "length" "8")]
10008 ;; Miscellaneous Thumb patterns
10010 (define_expand "tablejump"
10011   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10012               (use (label_ref (match_operand 1 "" "")))])]
10013   "TARGET_THUMB"
10014   "
10015   if (flag_pic)
10016     {
10017       /* Hopefully, CSE will eliminate this copy.  */
10018       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10019       rtx reg2 = gen_reg_rtx (SImode);
10021       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10022       operands[0] = reg2;
10023     }
10024   "
10027 ;; NB never uses BX.
10028 (define_insn "*thumb_tablejump"
10029   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10030    (use (label_ref (match_operand 1 "" "")))]
10031   "TARGET_THUMB"
10032   "mov\\t%|pc, %0"
10033   [(set_attr "length" "2")]
10036 ;; V5 Instructions,
10038 (define_insn "clzsi2"
10039   [(set (match_operand:SI 0 "s_register_operand" "=r")
10040         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10041   "TARGET_ARM && arm_arch5"
10042   "clz%?\\t%0, %1"
10043   [(set_attr "predicable" "yes")])
10045 (define_expand "ffssi2"
10046   [(set (match_operand:SI 0 "s_register_operand" "")
10047         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10048   "TARGET_ARM && arm_arch5"
10049   "
10050   {
10051     rtx t1, t2, t3;
10053     t1 = gen_reg_rtx (SImode);
10054     t2 = gen_reg_rtx (SImode);
10055     t3 = gen_reg_rtx (SImode);
10057     emit_insn (gen_negsi2 (t1, operands[1]));
10058     emit_insn (gen_andsi3 (t2, operands[1], t1));
10059     emit_insn (gen_clzsi2 (t3, t2));
10060     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10061     DONE;
10062   }"
10065 (define_expand "ctzsi2"
10066   [(set (match_operand:SI 0 "s_register_operand" "")
10067         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10068   "TARGET_ARM && arm_arch5"
10069   "
10070   {
10071     rtx t1, t2, t3;
10073     t1 = gen_reg_rtx (SImode);
10074     t2 = gen_reg_rtx (SImode);
10075     t3 = gen_reg_rtx (SImode);
10077     emit_insn (gen_negsi2 (t1, operands[1]));
10078     emit_insn (gen_andsi3 (t2, operands[1], t1));
10079     emit_insn (gen_clzsi2 (t3, t2));
10080     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10081     DONE;
10082   }"
10085 ;; V5E instructions.
10087 (define_insn "prefetch"
10088   [(prefetch (match_operand:SI 0 "address_operand" "p")
10089              (match_operand:SI 1 "" "")
10090              (match_operand:SI 2 "" ""))]
10091   "TARGET_ARM && arm_arch5e"
10092   "pld\\t%a0")
10094 ;; General predication pattern
10096 (define_cond_exec
10097   [(match_operator 0 "arm_comparison_operator"
10098     [(match_operand 1 "cc_register" "")
10099      (const_int 0)])]
10100   "TARGET_ARM"
10101   ""
10104 (define_insn "prologue_use"
10105   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10106   ""
10107   "%@ %0 needed for prologue"
10111 ;; Patterns for exception handling
10113 (define_expand "eh_return"
10114   [(use (match_operand 0 "general_operand" ""))]
10115   "TARGET_EITHER"
10116   "
10117   {
10118     if (TARGET_ARM)
10119       emit_insn (gen_arm_eh_return (operands[0]));
10120     else
10121       emit_insn (gen_thumb_eh_return (operands[0]));
10122     DONE;
10123   }"
10125                                    
10126 ;; We can't expand this before we know where the link register is stored.
10127 (define_insn_and_split "arm_eh_return"
10128   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10129                     VUNSPEC_EH_RETURN)
10130    (clobber (match_scratch:SI 1 "=&r"))]
10131   "TARGET_ARM"
10132   "#"
10133   "&& reload_completed"
10134   [(const_int 0)]
10135   "
10136   {
10137     arm_set_return_address (operands[0], operands[1]);
10138     DONE;
10139   }"
10142 (define_insn_and_split "thumb_eh_return"
10143   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10144                     VUNSPEC_EH_RETURN)
10145    (clobber (match_scratch:SI 1 "=&l"))]
10146   "TARGET_THUMB"
10147   "#"
10148   "&& reload_completed"
10149   [(const_int 0)]
10150   "
10151   {
10152     thumb_set_return_address (operands[0], operands[1]);
10153     DONE;
10154   }"
10158 ;; TLS support
10160 (define_insn "load_tp_hard"
10161   [(set (match_operand:SI 0 "register_operand" "=r")
10162         (unspec:SI [(const_int 0)] UNSPEC_TLS))]
10163   "TARGET_HARD_TP"
10164   "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
10165   [(set_attr "predicable" "yes")]
10168 ;; Doesn't clobber R1-R3.  Must use r0 for the first operand.
10169 (define_insn "load_tp_soft"
10170   [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
10171    (clobber (reg:SI LR_REGNUM))
10172    (clobber (reg:SI IP_REGNUM))
10173    (clobber (reg:CC CC_REGNUM))]
10174   "TARGET_SOFT_TP"
10175   "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
10176   [(set_attr "conds" "clob")]
10179 ;; Load the FPA co-processor patterns
10180 (include "fpa.md")
10181 ;; Load the Maverick co-processor patterns
10182 (include "cirrus.md")
10183 ;; Load the Intel Wireless Multimedia Extension patterns
10184 (include "iwmmxt.md")
10185 ;; Load the VFP co-processor patterns
10186 (include "vfp.md")