Sync usage with man page.
[netbsd-mini2440.git] / gnu / dist / gcc4 / gcc / config / arm / arm.md
blob3d8004d05edbe1f879d56e05475866d9590e63c2
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 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_insn "*compareqi_eq0"
3504   [(set (reg:CC_Z CC_REGNUM)
3505         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3506                          (const_int 0)))]
3507   "TARGET_ARM"
3508   "tst\\t%0, #255"
3509   [(set_attr "conds" "set")]
3512 (define_expand "extendhisi2"
3513   [(set (match_dup 2)
3514         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3515                    (const_int 16)))
3516    (set (match_operand:SI 0 "s_register_operand" "")
3517         (ashiftrt:SI (match_dup 2)
3518                      (const_int 16)))]
3519   "TARGET_EITHER"
3520   "
3521   {
3522     if (GET_CODE (operands[1]) == MEM)
3523       {
3524         if (TARGET_THUMB)
3525           {
3526             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3527             DONE;
3528           }
3529         else if (arm_arch4)
3530           {
3531             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3532                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3533             DONE;
3534           }
3535       }
3537     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3538       {
3539         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3540         DONE;
3541       }
3543     if (!s_register_operand (operands[1], HImode))
3544       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3546     if (arm_arch6)
3547       {
3548         if (TARGET_THUMB)
3549           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3550         else
3551           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3552                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3554         DONE;
3555       }
3557     operands[1] = gen_lowpart (SImode, operands[1]);
3558     operands[2] = gen_reg_rtx (SImode);
3559   }"
3562 (define_insn "thumb_extendhisi2"
3563   [(set (match_operand:SI 0 "register_operand" "=l")
3564         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3565    (clobber (match_scratch:SI 2 "=&l"))]
3566   "TARGET_THUMB && !arm_arch6"
3567   "*
3568   {
3569     rtx ops[4];
3570     rtx mem = XEXP (operands[1], 0);
3572     /* This code used to try to use 'V', and fix the address only if it was
3573        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3574        range of QImode offsets, and offsettable_address_p does a QImode
3575        address check.  */
3576        
3577     if (GET_CODE (mem) == CONST)
3578       mem = XEXP (mem, 0);
3579     
3580     if (GET_CODE (mem) == LABEL_REF)
3581       return \"ldr\\t%0, %1\";
3582     
3583     if (GET_CODE (mem) == PLUS)
3584       {
3585         rtx a = XEXP (mem, 0);
3586         rtx b = XEXP (mem, 1);
3588         if (GET_CODE (a) == LABEL_REF
3589             && GET_CODE (b) == CONST_INT)
3590           return \"ldr\\t%0, %1\";
3592         if (GET_CODE (b) == REG)
3593           return \"ldrsh\\t%0, %1\";
3594           
3595         ops[1] = a;
3596         ops[2] = b;
3597       }
3598     else
3599       {
3600         ops[1] = mem;
3601         ops[2] = const0_rtx;
3602       }
3604     gcc_assert (GET_CODE (ops[1]) == REG);
3606     ops[0] = operands[0];
3607     ops[3] = operands[2];
3608     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3609     return \"\";
3610   }"
3611   [(set_attr "length" "4")
3612    (set_attr "type" "load_byte")
3613    (set_attr "pool_range" "1020")]
3616 ;; We used to have an early-clobber on the scratch register here.
3617 ;; However, there's a bug somewhere in reload which means that this
3618 ;; can be partially ignored during spill allocation if the memory
3619 ;; address also needs reloading; this causes us to die later on when
3620 ;; we try to verify the operands.  Fortunately, we don't really need
3621 ;; the early-clobber: we can always use operand 0 if operand 2
3622 ;; overlaps the address.
3623 (define_insn "*thumb_extendhisi2_insn_v6"
3624   [(set (match_operand:SI 0 "register_operand" "=l,l")
3625         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3626    (clobber (match_scratch:SI 2 "=X,l"))]
3627   "TARGET_THUMB && arm_arch6"
3628   "*
3629   {
3630     rtx ops[4];
3631     rtx mem;
3633     if (which_alternative == 0)
3634       return \"sxth\\t%0, %1\";
3636     mem = XEXP (operands[1], 0);
3638     /* This code used to try to use 'V', and fix the address only if it was
3639        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3640        range of QImode offsets, and offsettable_address_p does a QImode
3641        address check.  */
3642        
3643     if (GET_CODE (mem) == CONST)
3644       mem = XEXP (mem, 0);
3645     
3646     if (GET_CODE (mem) == LABEL_REF)
3647       return \"ldr\\t%0, %1\";
3648     
3649     if (GET_CODE (mem) == PLUS)
3650       {
3651         rtx a = XEXP (mem, 0);
3652         rtx b = XEXP (mem, 1);
3654         if (GET_CODE (a) == LABEL_REF
3655             && GET_CODE (b) == CONST_INT)
3656           return \"ldr\\t%0, %1\";
3658         if (GET_CODE (b) == REG)
3659           return \"ldrsh\\t%0, %1\";
3660           
3661         ops[1] = a;
3662         ops[2] = b;
3663       }
3664     else
3665       {
3666         ops[1] = mem;
3667         ops[2] = const0_rtx;
3668       }
3669       
3670     gcc_assert (GET_CODE (ops[1]) == REG);
3672     ops[0] = operands[0];
3673     if (reg_mentioned_p (operands[2], ops[1]))
3674       ops[3] = ops[0];
3675     else
3676       ops[3] = operands[2];
3677     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3678     return \"\";
3679   }"
3680   [(set_attr "length" "2,4")
3681    (set_attr "type" "alu_shift,load_byte")
3682    (set_attr "pool_range" "*,1020")]
3685 (define_expand "extendhisi2_mem"
3686   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3687    (set (match_dup 3)
3688         (zero_extend:SI (match_dup 7)))
3689    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3690    (set (match_operand:SI 0 "" "")
3691         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3692   "TARGET_ARM"
3693   "
3694   {
3695     rtx mem1, mem2;
3696     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3698     mem1 = change_address (operands[1], QImode, addr);
3699     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
3700     operands[0] = gen_lowpart (SImode, operands[0]);
3701     operands[1] = mem1;
3702     operands[2] = gen_reg_rtx (SImode);
3703     operands[3] = gen_reg_rtx (SImode);
3704     operands[6] = gen_reg_rtx (SImode);
3705     operands[7] = mem2;
3707     if (BYTES_BIG_ENDIAN)
3708       {
3709         operands[4] = operands[2];
3710         operands[5] = operands[3];
3711       }
3712     else
3713       {
3714         operands[4] = operands[3];
3715         operands[5] = operands[2];
3716       }
3717   }"
3720 (define_insn "*arm_extendhisi2"
3721   [(set (match_operand:SI 0 "s_register_operand" "=r")
3722         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3723   "TARGET_ARM && arm_arch4 && !arm_arch6"
3724   "ldr%?sh\\t%0, %1"
3725   [(set_attr "type" "load_byte")
3726    (set_attr "predicable" "yes")
3727    (set_attr "pool_range" "256")
3728    (set_attr "neg_pool_range" "244")]
3731 (define_insn "*arm_extendhisi2_v6"
3732   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3733         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3734   "TARGET_ARM && arm_arch6"
3735   "@
3736    sxth%?\\t%0, %1
3737    ldr%?sh\\t%0, %1"
3738   [(set_attr "type" "alu_shift,load_byte")
3739    (set_attr "predicable" "yes")
3740    (set_attr "pool_range" "*,256")
3741    (set_attr "neg_pool_range" "*,244")]
3744 (define_insn "*arm_extendhisi2addsi"
3745   [(set (match_operand:SI 0 "s_register_operand" "=r")
3746         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3747                  (match_operand:SI 2 "s_register_operand" "r")))]
3748   "TARGET_ARM && arm_arch6"
3749   "sxtah%?\\t%0, %2, %1"
3752 (define_expand "extendqihi2"
3753   [(set (match_dup 2)
3754         (ashift:SI (match_operand:QI 1 "general_operand" "")
3755                    (const_int 24)))
3756    (set (match_operand:HI 0 "s_register_operand" "")
3757         (ashiftrt:SI (match_dup 2)
3758                      (const_int 24)))]
3759   "TARGET_ARM"
3760   "
3761   {
3762     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3763       {
3764         emit_insn (gen_rtx_SET (VOIDmode,
3765                                 operands[0],
3766                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3767         DONE;
3768       }
3769     if (!s_register_operand (operands[1], QImode))
3770       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3771     operands[0] = gen_lowpart (SImode, operands[0]);
3772     operands[1] = gen_lowpart (SImode, operands[1]);
3773     operands[2] = gen_reg_rtx (SImode);
3774   }"
3777 (define_insn "*extendqihi_insn"
3778   [(set (match_operand:HI 0 "s_register_operand" "=r")
3779         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3780   "TARGET_ARM && arm_arch4"
3781   "ldr%?sb\\t%0, %1"
3782   [(set_attr "type" "load_byte")
3783    (set_attr "predicable" "yes")
3784    (set_attr "pool_range" "256")
3785    (set_attr "neg_pool_range" "244")]
3788 (define_expand "extendqisi2"
3789   [(set (match_dup 2)
3790         (ashift:SI (match_operand:QI 1 "general_operand" "")
3791                    (const_int 24)))
3792    (set (match_operand:SI 0 "s_register_operand" "")
3793         (ashiftrt:SI (match_dup 2)
3794                      (const_int 24)))]
3795   "TARGET_EITHER"
3796   "
3797   {
3798     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3799       {
3800         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3801                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3802         DONE;
3803       }
3805     if (!s_register_operand (operands[1], QImode))
3806       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3808     if (arm_arch6)
3809       {
3810         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3811                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3812         DONE;
3813       }
3815     operands[1] = gen_lowpart (SImode, operands[1]);
3816     operands[2] = gen_reg_rtx (SImode);
3817   }"
3820 (define_insn "*arm_extendqisi"
3821   [(set (match_operand:SI 0 "s_register_operand" "=r")
3822         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3823   "TARGET_ARM && arm_arch4 && !arm_arch6"
3824   "ldr%?sb\\t%0, %1"
3825   [(set_attr "type" "load_byte")
3826    (set_attr "predicable" "yes")
3827    (set_attr "pool_range" "256")
3828    (set_attr "neg_pool_range" "244")]
3831 (define_insn "*arm_extendqisi_v6"
3832   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3833         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3834   "TARGET_ARM && arm_arch6"
3835   "@
3836    sxtb%?\\t%0, %1
3837    ldr%?sb\\t%0, %1"
3838   [(set_attr "type" "alu_shift,load_byte")
3839    (set_attr "predicable" "yes")
3840    (set_attr "pool_range" "*,256")
3841    (set_attr "neg_pool_range" "*,244")]
3844 (define_insn "*arm_extendqisi2addsi"
3845   [(set (match_operand:SI 0 "s_register_operand" "=r")
3846         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3847                  (match_operand:SI 2 "s_register_operand" "r")))]
3848   "TARGET_ARM && arm_arch6"
3849   "sxtab%?\\t%0, %2, %1"
3850   [(set_attr "type" "alu_shift")
3851    (set_attr "predicable" "yes")]
3854 (define_insn "*thumb_extendqisi2"
3855   [(set (match_operand:SI 0 "register_operand" "=l,l")
3856         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3857   "TARGET_THUMB && !arm_arch6"
3858   "*
3859   {
3860     rtx ops[3];
3861     rtx mem = XEXP (operands[1], 0);
3862     
3863     if (GET_CODE (mem) == CONST)
3864       mem = XEXP (mem, 0);
3865     
3866     if (GET_CODE (mem) == LABEL_REF)
3867       return \"ldr\\t%0, %1\";
3869     if (GET_CODE (mem) == PLUS
3870         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3871       return \"ldr\\t%0, %1\";
3872       
3873     if (which_alternative == 0)
3874       return \"ldrsb\\t%0, %1\";
3875       
3876     ops[0] = operands[0];
3877     
3878     if (GET_CODE (mem) == PLUS)
3879       {
3880         rtx a = XEXP (mem, 0);
3881         rtx b = XEXP (mem, 1);
3882         
3883         ops[1] = a;
3884         ops[2] = b;
3886         if (GET_CODE (a) == REG)
3887           {
3888             if (GET_CODE (b) == REG)
3889               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3890             else if (REGNO (a) == REGNO (ops[0]))
3891               {
3892                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3893                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3894                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3895               }
3896             else
3897               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3898           }
3899         else
3900           {
3901             gcc_assert (GET_CODE (b) == REG);
3902             if (REGNO (b) == REGNO (ops[0]))
3903               {
3904                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3905                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3906                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3907               }
3908             else
3909               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3910           }
3911       }
3912     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3913       {
3914         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", 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       {
3920         ops[1] = mem;
3921         ops[2] = const0_rtx;
3922         
3923         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3924       }
3925     return \"\";
3926   }"
3927   [(set_attr "length" "2,6")
3928    (set_attr "type" "load_byte,load_byte")
3929    (set_attr "pool_range" "32,32")]
3932 (define_insn "*thumb_extendqisi2_v6"
3933   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3934         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3935   "TARGET_THUMB && arm_arch6"
3936   "*
3937   {
3938     rtx ops[3];
3939     rtx mem;
3941     if (which_alternative == 0)
3942       return \"sxtb\\t%0, %1\";
3944     mem = XEXP (operands[1], 0);
3945     
3946     if (GET_CODE (mem) == CONST)
3947       mem = XEXP (mem, 0);
3948     
3949     if (GET_CODE (mem) == LABEL_REF)
3950       return \"ldr\\t%0, %1\";
3952     if (GET_CODE (mem) == PLUS
3953         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3954       return \"ldr\\t%0, %1\";
3955       
3956     if (which_alternative == 0)
3957       return \"ldrsb\\t%0, %1\";
3958       
3959     ops[0] = operands[0];
3960     
3961     if (GET_CODE (mem) == PLUS)
3962       {
3963         rtx a = XEXP (mem, 0);
3964         rtx b = XEXP (mem, 1);
3965         
3966         ops[1] = a;
3967         ops[2] = b;
3969         if (GET_CODE (a) == REG)
3970           {
3971             if (GET_CODE (b) == REG)
3972               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3973             else if (REGNO (a) == REGNO (ops[0]))
3974               {
3975                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3976                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3977               }
3978             else
3979               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3980           }
3981         else
3982           {
3983             gcc_assert (GET_CODE (b) == REG);
3984             if (REGNO (b) == REGNO (ops[0]))
3985               {
3986                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3987                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3988               }
3989             else
3990               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3991           }
3992       }
3993     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3994       {
3995         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3996         output_asm_insn (\"sxtb\\t%0, %0\", ops);
3997       }
3998     else
3999       {
4000         ops[1] = mem;
4001         ops[2] = const0_rtx;
4002         
4003         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4004       }
4005     return \"\";
4006   }"
4007   [(set_attr "length" "2,2,4")
4008    (set_attr "type" "alu_shift,load_byte,load_byte")
4009    (set_attr "pool_range" "*,32,32")]
4012 (define_expand "extendsfdf2"
4013   [(set (match_operand:DF                  0 "s_register_operand" "")
4014         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4015   "TARGET_ARM && TARGET_HARD_FLOAT"
4016   ""
4019 ;; Move insns (including loads and stores)
4021 ;; XXX Just some ideas about movti.
4022 ;; I don't think these are a good idea on the arm, there just aren't enough
4023 ;; registers
4024 ;;(define_expand "loadti"
4025 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4026 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4027 ;;  "" "")
4029 ;;(define_expand "storeti"
4030 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4031 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4032 ;;  "" "")
4034 ;;(define_expand "movti"
4035 ;;  [(set (match_operand:TI 0 "general_operand" "")
4036 ;;      (match_operand:TI 1 "general_operand" ""))]
4037 ;;  ""
4038 ;;  "
4040 ;;  rtx insn;
4042 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4043 ;;    operands[1] = copy_to_reg (operands[1]);
4044 ;;  if (GET_CODE (operands[0]) == MEM)
4045 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4046 ;;  else if (GET_CODE (operands[1]) == MEM)
4047 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4048 ;;  else
4049 ;;    FAIL;
4051 ;;  emit_insn (insn);
4052 ;;  DONE;
4053 ;;}")
4055 ;; Recognize garbage generated above.
4057 ;;(define_insn ""
4058 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4059 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4060 ;;  ""
4061 ;;  "*
4062 ;;  {
4063 ;;    register mem = (which_alternative < 3);
4064 ;;    register const char *template;
4066 ;;    operands[mem] = XEXP (operands[mem], 0);
4067 ;;    switch (which_alternative)
4068 ;;      {
4069 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4070 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4071 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4072 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4073 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4074 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4075 ;;      }
4076 ;;    output_asm_insn (template, operands);
4077 ;;    return \"\";
4078 ;;  }")
4080 (define_expand "movdi"
4081   [(set (match_operand:DI 0 "general_operand" "")
4082         (match_operand:DI 1 "general_operand" ""))]
4083   "TARGET_EITHER"
4084   "
4085   if (TARGET_THUMB)
4086     {
4087       if (!no_new_pseudos)
4088         {
4089           if (GET_CODE (operands[0]) != REG)
4090             operands[1] = force_reg (DImode, operands[1]);
4091         }
4092     }
4093   "
4096 (define_insn "*arm_movdi"
4097   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
4098         (match_operand:DI 1 "di_operand"              "rDa,Db,Dc,mi,r"))]
4099   "TARGET_ARM
4100   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4101   && !TARGET_IWMMXT"
4102   "*
4103   switch (which_alternative)
4104     {
4105     case 0:
4106     case 1:
4107     case 2:
4108       return \"#\";
4109     default:
4110       return output_move_double (operands);
4111     }
4112   "
4113   [(set_attr "length" "8,12,16,8,8")
4114    (set_attr "type" "*,*,*,load2,store2")
4115    (set_attr "pool_range" "*,*,*,1020,*")
4116    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4119 (define_split
4120   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4121         (match_operand:ANY64 1 "const_double_operand" ""))]
4122   "TARGET_ARM
4123    && reload_completed
4124    && (arm_const_double_inline_cost (operands[1])
4125        <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
4126   [(const_int 0)]
4127   "
4128   arm_split_constant (SET, SImode, curr_insn,
4129                       INTVAL (gen_lowpart (SImode, operands[1])),
4130                       gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
4131   arm_split_constant (SET, SImode, curr_insn,
4132                       INTVAL (gen_highpart_mode (SImode,
4133                                                  GET_MODE (operands[0]),
4134                                                  operands[1])),
4135                       gen_highpart (SImode, operands[0]), NULL_RTX, 0);
4136   DONE;
4137   "
4140 ; If optimizing for size, or if we have load delay slots, then 
4141 ; we want to split the constant into two separate operations. 
4142 ; In both cases this may split a trivial part into a single data op
4143 ; leaving a single complex constant to load.  We can also get longer
4144 ; offsets in a LDR which means we get better chances of sharing the pool
4145 ; entries.  Finally, we can normally do a better job of scheduling
4146 ; LDR instructions than we can with LDM.
4147 ; This pattern will only match if the one above did not.
4148 (define_split
4149   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4150         (match_operand:ANY64 1 "const_double_operand" ""))]
4151   "TARGET_ARM && reload_completed
4152    && arm_const_double_by_parts (operands[1])"
4153   [(set (match_dup 0) (match_dup 1))
4154    (set (match_dup 2) (match_dup 3))]
4155   "
4156   operands[2] = gen_highpart (SImode, operands[0]);
4157   operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
4158                                    operands[1]);
4159   operands[0] = gen_lowpart (SImode, operands[0]);
4160   operands[1] = gen_lowpart (SImode, operands[1]);
4161   "
4164 (define_split
4165   [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
4166         (match_operand:ANY64 1 "arm_general_register_operand" ""))]
4167   "TARGET_EITHER && reload_completed"
4168   [(set (match_dup 0) (match_dup 1))
4169    (set (match_dup 2) (match_dup 3))]
4170   "
4171   operands[2] = gen_highpart (SImode, operands[0]);
4172   operands[3] = gen_highpart (SImode, operands[1]);
4173   operands[0] = gen_lowpart (SImode, operands[0]);
4174   operands[1] = gen_lowpart (SImode, operands[1]);
4176   /* Handle a partial overlap.  */
4177   if (rtx_equal_p (operands[0], operands[3]))
4178     {
4179       rtx tmp0 = operands[0];
4180       rtx tmp1 = operands[1];
4182       operands[0] = operands[2];
4183       operands[1] = operands[3];
4184       operands[2] = tmp0;
4185       operands[3] = tmp1;
4186     }
4187   "
4190 ;; We can't actually do base+index doubleword loads if the index and
4191 ;; destination overlap.  Split here so that we at least have chance to
4192 ;; schedule.
4193 (define_split
4194   [(set (match_operand:DI 0 "s_register_operand" "")
4195         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4196                          (match_operand:SI 2 "s_register_operand" ""))))]
4197   "TARGET_LDRD
4198   && reg_overlap_mentioned_p (operands[0], operands[1])
4199   && reg_overlap_mentioned_p (operands[0], operands[2])"
4200   [(set (match_dup 4)
4201         (plus:SI (match_dup 1)
4202                  (match_dup 2)))
4203    (set (match_dup 0)
4204         (mem:DI (match_dup 4)))]
4205   "
4206   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4207   "
4210 ;;; ??? This should have alternatives for constants.
4211 ;;; ??? This was originally identical to the movdf_insn pattern.
4212 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4213 ;;; thumb_reorg with a memory reference.
4214 (define_insn "*thumb_movdi_insn"
4215   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4216         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4217   "TARGET_THUMB
4218    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4219    && (   register_operand (operands[0], DImode)
4220        || register_operand (operands[1], DImode))"
4221   "*
4222   {
4223   switch (which_alternative)
4224     {
4225     default:
4226     case 0:
4227       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4228         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4229       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4230     case 1:
4231       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4232     case 2:
4233       operands[1] = GEN_INT (- INTVAL (operands[1]));
4234       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4235     case 3:
4236       return \"ldmia\\t%1, {%0, %H0}\";
4237     case 4:
4238       return \"stmia\\t%0, {%1, %H1}\";
4239     case 5:
4240       return thumb_load_double_from_address (operands);
4241     case 6:
4242       operands[2] = gen_rtx_MEM (SImode,
4243                              plus_constant (XEXP (operands[0], 0), 4));
4244       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4245       return \"\";
4246     case 7:
4247       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4248         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4249       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4250     }
4251   }"
4252   [(set_attr "length" "4,4,6,2,2,6,4,4")
4253    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4254    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4257 (define_expand "movsi"
4258   [(set (match_operand:SI 0 "general_operand" "")
4259         (match_operand:SI 1 "general_operand" ""))]
4260   "TARGET_EITHER"
4261   "
4262   if (TARGET_ARM)
4263     {
4264       /* Everything except mem = const or mem = mem can be done easily.  */
4265       if (GET_CODE (operands[0]) == MEM)
4266         operands[1] = force_reg (SImode, operands[1]);
4267       if (arm_general_register_operand (operands[0], SImode)
4268           && GET_CODE (operands[1]) == CONST_INT
4269           && !(const_ok_for_arm (INTVAL (operands[1]))
4270                || const_ok_for_arm (~INTVAL (operands[1]))))
4271         {
4272            arm_split_constant (SET, SImode, NULL_RTX,
4273                                INTVAL (operands[1]), operands[0], NULL_RTX,
4274                                optimize && !no_new_pseudos);
4275           DONE;
4276         }
4277     }
4278   else /* TARGET_THUMB....  */
4279     {
4280       if (!no_new_pseudos)
4281         {
4282           if (GET_CODE (operands[0]) != REG)
4283             operands[1] = force_reg (SImode, operands[1]);
4284         }
4285     }
4287   /* Recognize the case where operand[1] is a reference to thread-local
4288      data and load its address to a register.  */
4289   if (arm_tls_referenced_p (operands[1]))
4290     {
4291       rtx tmp = operands[1];
4292       rtx addend = NULL;
4294       if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
4295         {
4296           addend = XEXP (XEXP (tmp, 0), 1);
4297           tmp = XEXP (XEXP (tmp, 0), 0);
4298         }
4300       gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
4301       gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
4303       tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
4304       if (addend)
4305         {
4306           tmp = gen_rtx_PLUS (SImode, tmp, addend);
4307           tmp = force_operand (tmp, operands[0]);
4308         }
4309       operands[1] = tmp;
4310     }
4311   else if (flag_pic
4312            && (CONSTANT_P (operands[1])
4313                || symbol_mentioned_p (operands[1])
4314                || label_mentioned_p (operands[1])))
4315       operands[1] = legitimize_pic_address (operands[1], SImode,
4316                                             (no_new_pseudos ? operands[0] : 0));
4317   "
4320 (define_insn "*arm_movsi_insn"
4321   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4322         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4323   "TARGET_ARM && ! TARGET_IWMMXT
4324    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4325    && (   register_operand (operands[0], SImode)
4326        || register_operand (operands[1], SImode))"
4327   "@
4328    mov%?\\t%0, %1
4329    mvn%?\\t%0, #%B1
4330    ldr%?\\t%0, %1
4331    str%?\\t%1, %0"
4332   [(set_attr "type" "*,*,load1,store1")
4333    (set_attr "predicable" "yes")
4334    (set_attr "pool_range" "*,*,4096,*")
4335    (set_attr "neg_pool_range" "*,*,4084,*")]
4338 (define_split
4339   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4340         (match_operand:SI 1 "const_int_operand" ""))]
4341   "TARGET_ARM
4342   && (!(const_ok_for_arm (INTVAL (operands[1]))
4343         || const_ok_for_arm (~INTVAL (operands[1]))))"
4344   [(clobber (const_int 0))]
4345   "
4346   arm_split_constant (SET, SImode, NULL_RTX, 
4347                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4348   DONE;
4349   "
4352 (define_insn "*thumb_movsi_insn"
4353   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4354         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4355   "TARGET_THUMB
4356    && (   register_operand (operands[0], SImode) 
4357        || register_operand (operands[1], SImode))"
4358   "@
4359    mov  %0, %1
4360    mov  %0, %1
4361    #
4362    #
4363    ldmia\\t%1, {%0}
4364    stmia\\t%0, {%1}
4365    ldr\\t%0, %1
4366    str\\t%1, %0
4367    mov\\t%0, %1"
4368   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4369    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4370    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4373 (define_split 
4374   [(set (match_operand:SI 0 "register_operand" "")
4375         (match_operand:SI 1 "const_int_operand" ""))]
4376   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4377   [(set (match_dup 0) (match_dup 1))
4378    (set (match_dup 0) (neg:SI (match_dup 0)))]
4379   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4382 (define_split 
4383   [(set (match_operand:SI 0 "register_operand" "")
4384         (match_operand:SI 1 "const_int_operand" ""))]
4385   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4386   [(set (match_dup 0) (match_dup 1))
4387    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4388   "
4389   {
4390     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4391     unsigned HOST_WIDE_INT mask = 0xff;
4392     int i;
4393     
4394     for (i = 0; i < 25; i++)
4395       if ((val & (mask << i)) == val)
4396         break;
4398     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4399     if (i == 0)
4400       FAIL;
4402     operands[1] = GEN_INT (val >> i);
4403     operands[2] = GEN_INT (i);
4404   }"
4407 ;; When generating pic, we need to load the symbol offset into a register.
4408 ;; So that the optimizer does not confuse this with a normal symbol load
4409 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4410 ;; since that is the only type of relocation we can use.
4412 ;; The rather odd constraints on the following are to force reload to leave
4413 ;; the insn alone, and to force the minipool generation pass to then move
4414 ;; the GOT symbol to memory.
4416 (define_insn "pic_load_addr_arm"
4417   [(set (match_operand:SI 0 "s_register_operand" "=r")
4418         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4419   "TARGET_ARM && flag_pic"
4420   "ldr%?\\t%0, %1"
4421   [(set_attr "type" "load1")
4422    (set (attr "pool_range")     (const_int 4096))
4423    (set (attr "neg_pool_range") (const_int 4084))]
4426 (define_insn "pic_load_addr_thumb"
4427   [(set (match_operand:SI 0 "s_register_operand" "=l")
4428         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4429   "TARGET_THUMB && flag_pic"
4430   "ldr\\t%0, %1"
4431   [(set_attr "type" "load1")
4432    (set (attr "pool_range") (const_int 1024))]
4435 ;; This variant is used for AOF assembly, since it needs to mention the
4436 ;; pic register in the rtl.
4437 (define_expand "pic_load_addr_based"
4438   [(set (match_operand:SI 0 "s_register_operand" "")
4439         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4440   "TARGET_ARM && flag_pic"
4441   "operands[2] = pic_offset_table_rtx;"
4444 (define_insn "*pic_load_addr_based_insn"
4445   [(set (match_operand:SI 0 "s_register_operand" "=r")
4446         (unspec:SI [(match_operand 1 "" "")
4447                     (match_operand 2 "s_register_operand" "r")]
4448                    UNSPEC_PIC_SYM))]
4449   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4450   "*
4451 #ifdef AOF_ASSEMBLER
4452   operands[1] = aof_pic_entry (operands[1]);
4453 #endif
4454   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4455   return \"\";
4456   "
4457   [(set_attr "type" "load1")
4458    (set (attr "pool_range")
4459         (if_then_else (eq_attr "is_thumb" "yes")
4460                       (const_int 1024)
4461                       (const_int 4096)))
4462    (set (attr "neg_pool_range")
4463         (if_then_else (eq_attr "is_thumb" "yes")
4464                       (const_int 0)
4465                       (const_int 4084)))]
4468 (define_insn "pic_add_dot_plus_four"
4469   [(set (match_operand:SI 0 "register_operand" "=r")
4470         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
4471                              (const (plus:SI (pc) (const_int 4))))]
4472                    UNSPEC_PIC_BASE))
4473    (use (match_operand 2 "" ""))]
4474   "TARGET_THUMB"
4475   "*
4476   (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4477                                      INTVAL (operands[2]));
4478   return \"add\\t%0, %|pc\";
4479   "
4480   [(set_attr "length" "2")]
4483 (define_insn "pic_add_dot_plus_eight"
4484   [(set (match_operand:SI 0 "register_operand" "=r")
4485         (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4486                              (const (plus:SI (pc) (const_int 8))))]
4487                    UNSPEC_PIC_BASE))
4488    (use (match_operand 2 "" ""))]
4489   "TARGET_ARM"
4490   "*
4491     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4492                                        INTVAL (operands[2]));
4493     return \"add%?\\t%0, %|pc, %1\";
4494   "
4495   [(set_attr "predicable" "yes")]
4498 (define_insn "tls_load_dot_plus_eight"
4499   [(set (match_operand:SI 0 "register_operand" "+r")
4500         (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
4501                                      (const (plus:SI (pc) (const_int 8))))]
4502                            UNSPEC_PIC_BASE)))
4503    (use (match_operand 2 "" ""))]
4504   "TARGET_ARM"
4505   "*
4506     (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
4507                                        INTVAL (operands[2]));
4508     return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
4509   "
4510   [(set_attr "predicable" "yes")]
4513 ;; PIC references to local variables can generate pic_add_dot_plus_eight
4514 ;; followed by a load.  These sequences can be crunched down to
4515 ;; tls_load_dot_plus_eight by a peephole.
4517 (define_peephole2
4518   [(parallel [(set (match_operand:SI 0 "register_operand" "")
4519                    (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
4520                                         (const (plus:SI (pc) (const_int 8))))]
4521                               UNSPEC_PIC_BASE))
4522               (use (label_ref (match_operand 1 "" "")))])
4523    (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
4524   "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
4525   [(parallel [(set (match_dup 2)
4526                    (mem:SI (unspec:SI [(plus:SI (match_dup 3)
4527                                                 (const (plus:SI (pc) (const_int 8))))]
4528                                       UNSPEC_PIC_BASE)))
4529               (use (label_ref (match_dup 1)))])]
4530   ""
4533 (define_expand "builtin_setjmp_receiver"
4534   [(label_ref (match_operand 0 "" ""))]
4535   "flag_pic"
4536   "
4538   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4539      register.  */
4540   arm_load_pic_register (3);
4541   DONE;
4544 ;; If copying one reg to another we can set the condition codes according to
4545 ;; its value.  Such a move is common after a return from subroutine and the
4546 ;; result is being tested against zero.
4548 (define_insn "*movsi_compare0"
4549   [(set (reg:CC CC_REGNUM)
4550         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4551                     (const_int 0)))
4552    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4553         (match_dup 1))]
4554   "TARGET_ARM"
4555   "@
4556    cmp%?\\t%0, #0
4557    sub%?s\\t%0, %1, #0"
4558   [(set_attr "conds" "set")]
4561 ;; Subroutine to store a half word from a register into memory.
4562 ;; Operand 0 is the source register (HImode)
4563 ;; Operand 1 is the destination address in a register (SImode)
4565 ;; In both this routine and the next, we must be careful not to spill
4566 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4567 ;; can generate unrecognizable rtl.
4569 (define_expand "storehi"
4570   [;; store the low byte
4571    (set (match_operand 1 "" "") (match_dup 3))
4572    ;; extract the high byte
4573    (set (match_dup 2)
4574         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4575    ;; store the high byte
4576    (set (match_dup 4) (match_dup 5))]
4577   "TARGET_ARM"
4578   "
4579   {
4580     rtx op1 = operands[1];
4581     rtx addr = XEXP (op1, 0);
4582     enum rtx_code code = GET_CODE (addr);
4584     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4585         || code == MINUS)
4586       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4588     operands[4] = adjust_address (op1, QImode, 1);
4589     operands[1] = adjust_address (operands[1], QImode, 0);
4590     operands[3] = gen_lowpart (QImode, operands[0]);
4591     operands[0] = gen_lowpart (SImode, operands[0]);
4592     operands[2] = gen_reg_rtx (SImode);
4593     operands[5] = gen_lowpart (QImode, operands[2]);
4594   }"
4597 (define_expand "storehi_bigend"
4598   [(set (match_dup 4) (match_dup 3))
4599    (set (match_dup 2)
4600         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4601    (set (match_operand 1 "" "") (match_dup 5))]
4602   "TARGET_ARM"
4603   "
4604   {
4605     rtx op1 = operands[1];
4606     rtx addr = XEXP (op1, 0);
4607     enum rtx_code code = GET_CODE (addr);
4609     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4610         || code == MINUS)
4611       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4613     operands[4] = adjust_address (op1, QImode, 1);
4614     operands[1] = adjust_address (operands[1], QImode, 0);
4615     operands[3] = gen_lowpart (QImode, operands[0]);
4616     operands[0] = gen_lowpart (SImode, operands[0]);
4617     operands[2] = gen_reg_rtx (SImode);
4618     operands[5] = gen_lowpart (QImode, operands[2]);
4619   }"
4622 ;; Subroutine to store a half word integer constant into memory.
4623 (define_expand "storeinthi"
4624   [(set (match_operand 0 "" "")
4625         (match_operand 1 "" ""))
4626    (set (match_dup 3) (match_dup 2))]
4627   "TARGET_ARM"
4628   "
4629   {
4630     HOST_WIDE_INT value = INTVAL (operands[1]);
4631     rtx addr = XEXP (operands[0], 0);
4632     rtx op0 = operands[0];
4633     enum rtx_code code = GET_CODE (addr);
4635     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4636         || code == MINUS)
4637       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4639     operands[1] = gen_reg_rtx (SImode);
4640     if (BYTES_BIG_ENDIAN)
4641       {
4642         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4643         if ((value & 255) == ((value >> 8) & 255))
4644           operands[2] = operands[1];
4645         else
4646           {
4647             operands[2] = gen_reg_rtx (SImode);
4648             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4649           }
4650       }
4651     else
4652       {
4653         emit_insn (gen_movsi (operands[1], GEN_INT (value & 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 >> 8) & 255)));
4660           }
4661       }
4663     operands[3] = adjust_address (op0, QImode, 1);
4664     operands[0] = adjust_address (operands[0], QImode, 0);
4665     operands[2] = gen_lowpart (QImode, operands[2]);
4666     operands[1] = gen_lowpart (QImode, operands[1]);
4667   }"
4670 (define_expand "storehi_single_op"
4671   [(set (match_operand:HI 0 "memory_operand" "")
4672         (match_operand:HI 1 "general_operand" ""))]
4673   "TARGET_ARM && arm_arch4"
4674   "
4675   if (!s_register_operand (operands[1], HImode))
4676     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4677   "
4680 (define_expand "movhi"
4681   [(set (match_operand:HI 0 "general_operand" "")
4682         (match_operand:HI 1 "general_operand" ""))]
4683   "TARGET_EITHER"
4684   "
4685   if (TARGET_ARM)
4686     {
4687       if (!no_new_pseudos)
4688         {
4689           if (GET_CODE (operands[0]) == MEM)
4690             {
4691               if (arm_arch4)
4692                 {
4693                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4694                   DONE;
4695                 }
4696               if (GET_CODE (operands[1]) == CONST_INT)
4697                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4698               else
4699                 {
4700                   if (GET_CODE (operands[1]) == MEM)
4701                     operands[1] = force_reg (HImode, operands[1]);
4702                   if (BYTES_BIG_ENDIAN)
4703                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4704                   else
4705                    emit_insn (gen_storehi (operands[1], operands[0]));
4706                 }
4707               DONE;
4708             }
4709           /* Sign extend a constant, and keep it in an SImode reg.  */
4710           else if (GET_CODE (operands[1]) == CONST_INT)
4711             {
4712               rtx reg = gen_reg_rtx (SImode);
4713               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4715               /* If the constant is already valid, leave it alone.  */
4716               if (!const_ok_for_arm (val))
4717                 {
4718                   /* If setting all the top bits will make the constant 
4719                      loadable in a single instruction, then set them.  
4720                      Otherwise, sign extend the number.  */
4722                   if (const_ok_for_arm (~(val | ~0xffff)))
4723                     val |= ~0xffff;
4724                   else if (val & 0x8000)
4725                     val |= ~0xffff;
4726                 }
4728               emit_insn (gen_movsi (reg, GEN_INT (val)));
4729               operands[1] = gen_lowpart (HImode, reg);
4730             }
4731           else if (arm_arch4 && optimize && !no_new_pseudos
4732                    && GET_CODE (operands[1]) == MEM)
4733             {
4734               rtx reg = gen_reg_rtx (SImode);
4736               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4737               operands[1] = gen_lowpart (HImode, reg);
4738             }
4739           else if (!arm_arch4)
4740             {
4741               if (GET_CODE (operands[1]) == MEM)
4742                 {
4743                   rtx base;
4744                   rtx offset = const0_rtx;
4745                   rtx reg = gen_reg_rtx (SImode);
4747                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4748                        || (GET_CODE (base) == PLUS
4749                            && (GET_CODE (offset = XEXP (base, 1))
4750                                == CONST_INT)
4751                            && ((INTVAL(offset) & 1) != 1)
4752                            && GET_CODE (base = XEXP (base, 0)) == REG))
4753                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4754                     {
4755                       rtx new;
4757                       new = widen_memory_access (operands[1], SImode,
4758                                                  ((INTVAL (offset) & ~3)
4759                                                   - INTVAL (offset)));
4760                       emit_insn (gen_movsi (reg, new));
4761                       if (((INTVAL (offset) & 2) != 0)
4762                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4763                         {
4764                           rtx reg2 = gen_reg_rtx (SImode);
4766                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4767                           reg = reg2;
4768                         }
4769                     }
4770                   else
4771                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4773                   operands[1] = gen_lowpart (HImode, reg);
4774                }
4775            }
4776         }
4777       /* Handle loading a large integer during reload.  */
4778       else if (GET_CODE (operands[1]) == CONST_INT
4779                && !const_ok_for_arm (INTVAL (operands[1]))
4780                && !const_ok_for_arm (~INTVAL (operands[1])))
4781         {
4782           /* Writing a constant to memory needs a scratch, which should
4783              be handled with SECONDARY_RELOADs.  */
4784           gcc_assert (GET_CODE (operands[0]) == REG);
4786           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4787           emit_insn (gen_movsi (operands[0], operands[1]));
4788           DONE;
4789        }
4790     }
4791   else /* TARGET_THUMB */
4792     {
4793       if (!no_new_pseudos)
4794         {
4795           if (GET_CODE (operands[1]) == CONST_INT)
4796             {
4797               rtx reg = gen_reg_rtx (SImode);
4799               emit_insn (gen_movsi (reg, operands[1]));
4800               operands[1] = gen_lowpart (HImode, reg);
4801             }
4803           /* ??? We shouldn't really get invalid addresses here, but this can
4804              happen if we are passed a SP (never OK for HImode/QImode) or 
4805              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4806              HImode/QImode) relative address.  */
4807           /* ??? This should perhaps be fixed elsewhere, for instance, in
4808              fixup_stack_1, by checking for other kinds of invalid addresses,
4809              e.g. a bare reference to a virtual register.  This may confuse the
4810              alpha though, which must handle this case differently.  */
4811           if (GET_CODE (operands[0]) == MEM
4812               && !memory_address_p (GET_MODE (operands[0]),
4813                                     XEXP (operands[0], 0)))
4814             operands[0]
4815               = replace_equiv_address (operands[0],
4816                                        copy_to_reg (XEXP (operands[0], 0)));
4817    
4818           if (GET_CODE (operands[1]) == MEM
4819               && !memory_address_p (GET_MODE (operands[1]),
4820                                     XEXP (operands[1], 0)))
4821             operands[1]
4822               = replace_equiv_address (operands[1],
4823                                        copy_to_reg (XEXP (operands[1], 0)));
4825           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4826             {
4827               rtx reg = gen_reg_rtx (SImode);
4829               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4830               operands[1] = gen_lowpart (HImode, reg);
4831             }
4833           if (GET_CODE (operands[0]) == MEM)
4834             operands[1] = force_reg (HImode, operands[1]);
4835         }
4836       else if (GET_CODE (operands[1]) == CONST_INT
4837                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4838         {
4839           /* Handle loading a large integer during reload.  */
4841           /* Writing a constant to memory needs a scratch, which should
4842              be handled with SECONDARY_RELOADs.  */
4843           gcc_assert (GET_CODE (operands[0]) == REG);
4845           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4846           emit_insn (gen_movsi (operands[0], operands[1]));
4847           DONE;
4848         }
4849     }
4850   "
4853 (define_insn "*thumb_movhi_insn"
4854   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4855         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4856   "TARGET_THUMB
4857    && (   register_operand (operands[0], HImode)
4858        || register_operand (operands[1], HImode))"
4859   "*
4860   switch (which_alternative)
4861     {
4862     case 0: return \"add        %0, %1, #0\";
4863     case 2: return \"strh       %1, %0\";
4864     case 3: return \"mov        %0, %1\";
4865     case 4: return \"mov        %0, %1\";
4866     case 5: return \"mov        %0, %1\";
4867     default: gcc_unreachable ();
4868     case 1:
4869       /* The stack pointer can end up being taken as an index register.
4870           Catch this case here and deal with it.  */
4871       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4872           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4873           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4874         {
4875           rtx ops[2];
4876           ops[0] = operands[0];
4877           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4878       
4879           output_asm_insn (\"mov        %0, %1\", ops);
4881           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4882     
4883         }
4884       return \"ldrh     %0, %1\";
4885     }"
4886   [(set_attr "length" "2,4,2,2,2,2")
4887    (set_attr "type" "*,load1,store1,*,*,*")]
4891 (define_expand "movhi_bytes"
4892   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4893    (set (match_dup 3)
4894         (zero_extend:SI (match_dup 6)))
4895    (set (match_operand:SI 0 "" "")
4896          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4897   "TARGET_ARM"
4898   "
4899   {
4900     rtx mem1, mem2;
4901     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4903     mem1 = change_address (operands[1], QImode, addr);
4904     mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
4905     operands[0] = gen_lowpart (SImode, operands[0]);
4906     operands[1] = mem1;
4907     operands[2] = gen_reg_rtx (SImode);
4908     operands[3] = gen_reg_rtx (SImode);
4909     operands[6] = mem2;
4911     if (BYTES_BIG_ENDIAN)
4912       {
4913         operands[4] = operands[2];
4914         operands[5] = operands[3];
4915       }
4916     else
4917       {
4918         operands[4] = operands[3];
4919         operands[5] = operands[2];
4920       }
4921   }"
4924 (define_expand "movhi_bigend"
4925   [(set (match_dup 2)
4926         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4927                    (const_int 16)))
4928    (set (match_dup 3)
4929         (ashiftrt:SI (match_dup 2) (const_int 16)))
4930    (set (match_operand:HI 0 "s_register_operand" "")
4931         (match_dup 4))]
4932   "TARGET_ARM"
4933   "
4934   operands[2] = gen_reg_rtx (SImode);
4935   operands[3] = gen_reg_rtx (SImode);
4936   operands[4] = gen_lowpart (HImode, operands[3]);
4937   "
4940 ;; Pattern to recognize insn generated default case above
4941 (define_insn "*movhi_insn_arch4"
4942   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4943         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4944   "TARGET_ARM
4945    && arm_arch4
4946    && (GET_CODE (operands[1]) != CONST_INT
4947        || const_ok_for_arm (INTVAL (operands[1]))
4948        || const_ok_for_arm (~INTVAL (operands[1])))"
4949   "@
4950    mov%?\\t%0, %1\\t%@ movhi
4951    mvn%?\\t%0, #%B1\\t%@ movhi
4952    str%?h\\t%1, %0\\t%@ movhi
4953    ldr%?h\\t%0, %1\\t%@ movhi"
4954   [(set_attr "type" "*,*,store1,load1")
4955    (set_attr "predicable" "yes")
4956    (set_attr "pool_range" "*,*,*,256")
4957    (set_attr "neg_pool_range" "*,*,*,244")]
4960 (define_insn "*movhi_bytes"
4961   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4962         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4963   "TARGET_ARM"
4964   "@
4965    mov%?\\t%0, %1\\t%@ movhi
4966    mvn%?\\t%0, #%B1\\t%@ movhi"
4967   [(set_attr "predicable" "yes")]
4970 (define_expand "thumb_movhi_clobber"
4971   [(set (match_operand:HI     0 "memory_operand"   "")
4972         (match_operand:HI     1 "register_operand" ""))
4973    (clobber (match_operand:DI 2 "register_operand" ""))]
4974   "TARGET_THUMB"
4975   "
4976   if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
4977       && REGNO (operands[1]) <= LAST_LO_REGNUM)
4978     {
4979       emit_insn (gen_movhi (operands[0], operands[1]));
4980       DONE;
4981     }
4982   /* XXX Fixme, need to handle other cases here as well.  */
4983   gcc_unreachable ();
4984   "
4986         
4987 ;; We use a DImode scratch because we may occasionally need an additional
4988 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4989 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4990 (define_expand "reload_outhi"
4991   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4992               (match_operand:HI 1 "s_register_operand"        "r")
4993               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4994   "TARGET_EITHER"
4995   "if (TARGET_ARM)
4996      arm_reload_out_hi (operands);
4997    else
4998      thumb_reload_out_hi (operands);
4999   DONE;
5000   "
5003 (define_expand "reload_inhi"
5004   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
5005               (match_operand:HI 1 "arm_reload_memory_operand" "o")
5006               (match_operand:DI 2 "s_register_operand" "=&r")])]
5007   "TARGET_EITHER"
5008   "
5009   if (TARGET_ARM)
5010     arm_reload_in_hi (operands);
5011   else
5012     thumb_reload_out_hi (operands);
5013   DONE;
5016 (define_expand "movqi"
5017   [(set (match_operand:QI 0 "general_operand" "")
5018         (match_operand:QI 1 "general_operand" ""))]
5019   "TARGET_EITHER"
5020   "
5021   /* Everything except mem = const or mem = mem can be done easily */
5023   if (!no_new_pseudos)
5024     {
5025       if (GET_CODE (operands[1]) == CONST_INT)
5026         {
5027           rtx reg = gen_reg_rtx (SImode);
5029           emit_insn (gen_movsi (reg, operands[1]));
5030           operands[1] = gen_lowpart (QImode, reg);
5031         }
5033       if (TARGET_THUMB)
5034         {
5035           /* ??? We shouldn't really get invalid addresses here, but this can
5036              happen if we are passed a SP (never OK for HImode/QImode) or
5037              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
5038              HImode/QImode) relative address.  */
5039           /* ??? This should perhaps be fixed elsewhere, for instance, in
5040              fixup_stack_1, by checking for other kinds of invalid addresses,
5041              e.g. a bare reference to a virtual register.  This may confuse the
5042              alpha though, which must handle this case differently.  */
5043           if (GET_CODE (operands[0]) == MEM
5044               && !memory_address_p (GET_MODE (operands[0]),
5045                                      XEXP (operands[0], 0)))
5046             operands[0]
5047               = replace_equiv_address (operands[0],
5048                                        copy_to_reg (XEXP (operands[0], 0)));
5049           if (GET_CODE (operands[1]) == MEM
5050               && !memory_address_p (GET_MODE (operands[1]),
5051                                     XEXP (operands[1], 0)))
5052              operands[1]
5053                = replace_equiv_address (operands[1],
5054                                         copy_to_reg (XEXP (operands[1], 0)));
5055         }
5057       if (GET_CODE (operands[1]) == MEM && optimize > 0)
5058         {
5059           rtx reg = gen_reg_rtx (SImode);
5061           emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
5062           operands[1] = gen_lowpart (QImode, reg);
5063         }
5065       if (GET_CODE (operands[0]) == MEM)
5066         operands[1] = force_reg (QImode, operands[1]);
5067     }
5068   else if (TARGET_THUMB
5069            && GET_CODE (operands[1]) == CONST_INT
5070            && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
5071     {
5072       /* Handle loading a large integer during reload.  */
5074       /* Writing a constant to memory needs a scratch, which should
5075          be handled with SECONDARY_RELOADs.  */
5076       gcc_assert (GET_CODE (operands[0]) == REG);
5078       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
5079       emit_insn (gen_movsi (operands[0], operands[1]));
5080       DONE;
5081     }
5082   "
5086 (define_insn "*arm_movqi_insn"
5087   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5088         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5089   "TARGET_ARM
5090    && (   register_operand (operands[0], QImode)
5091        || register_operand (operands[1], QImode))"
5092   "@
5093    mov%?\\t%0, %1
5094    mvn%?\\t%0, #%B1
5095    ldr%?b\\t%0, %1
5096    str%?b\\t%1, %0"
5097   [(set_attr "type" "*,*,load1,store1")
5098    (set_attr "predicable" "yes")]
5101 (define_insn "*thumb_movqi_insn"
5102   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5103         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5104   "TARGET_THUMB
5105    && (   register_operand (operands[0], QImode)
5106        || register_operand (operands[1], QImode))"
5107   "@
5108    add\\t%0, %1, #0
5109    ldrb\\t%0, %1
5110    strb\\t%1, %0
5111    mov\\t%0, %1
5112    mov\\t%0, %1
5113    mov\\t%0, %1"
5114   [(set_attr "length" "2")
5115    (set_attr "type" "*,load1,store1,*,*,*")
5116    (set_attr "pool_range" "*,32,*,*,*,*")]
5119 (define_expand "movsf"
5120   [(set (match_operand:SF 0 "general_operand" "")
5121         (match_operand:SF 1 "general_operand" ""))]
5122   "TARGET_EITHER"
5123   "
5124   if (TARGET_ARM)
5125     {
5126       if (GET_CODE (operands[0]) == MEM)
5127         operands[1] = force_reg (SFmode, operands[1]);
5128     }
5129   else /* TARGET_THUMB */
5130     {
5131       if (!no_new_pseudos)
5132         {
5133            if (GET_CODE (operands[0]) != REG)
5134              operands[1] = force_reg (SFmode, operands[1]);
5135         }
5136     }
5137   "
5140 ;; Transform a floating-point move of a constant into a core register into
5141 ;; an SImode operation.
5142 (define_split
5143   [(set (match_operand:SF 0 "arm_general_register_operand" "")
5144         (match_operand:SF 1 "immediate_operand" ""))]
5145   "TARGET_ARM
5146    && reload_completed
5147    && GET_CODE (operands[1]) == CONST_DOUBLE"
5148   [(set (match_dup 2) (match_dup 3))]
5149   "
5150   operands[2] = gen_lowpart (SImode, operands[0]);
5151   operands[3] = gen_lowpart (SImode, operands[1]);
5152   if (operands[2] == 0 || operands[3] == 0)
5153     FAIL;
5154   "
5157 (define_insn "*arm_movsf_soft_insn"
5158   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5159         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5160   "TARGET_ARM
5161    && TARGET_SOFT_FLOAT
5162    && (GET_CODE (operands[0]) != MEM
5163        || register_operand (operands[1], SFmode))"
5164   "@
5165    mov%?\\t%0, %1
5166    ldr%?\\t%0, %1\\t%@ float
5167    str%?\\t%1, %0\\t%@ float"
5168   [(set_attr "length" "4,4,4")
5169    (set_attr "predicable" "yes")
5170    (set_attr "type" "*,load1,store1")
5171    (set_attr "pool_range" "*,4096,*")
5172    (set_attr "neg_pool_range" "*,4084,*")]
5175 ;;; ??? This should have alternatives for constants.
5176 (define_insn "*thumb_movsf_insn"
5177   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5178         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5179   "TARGET_THUMB
5180    && (   register_operand (operands[0], SFmode) 
5181        || register_operand (operands[1], SFmode))"
5182   "@
5183    add\\t%0, %1, #0
5184    ldmia\\t%1, {%0}
5185    stmia\\t%0, {%1}
5186    ldr\\t%0, %1
5187    str\\t%1, %0
5188    mov\\t%0, %1
5189    mov\\t%0, %1"
5190   [(set_attr "length" "2")
5191    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5192    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5195 (define_expand "movdf"
5196   [(set (match_operand:DF 0 "general_operand" "")
5197         (match_operand:DF 1 "general_operand" ""))]
5198   "TARGET_EITHER"
5199   "
5200   if (TARGET_ARM)
5201     {
5202       if (GET_CODE (operands[0]) == MEM)
5203         operands[1] = force_reg (DFmode, operands[1]);
5204     }
5205   else /* TARGET_THUMB */
5206     {
5207       if (!no_new_pseudos)
5208         {
5209           if (GET_CODE (operands[0]) != REG)
5210             operands[1] = force_reg (DFmode, operands[1]);
5211         }
5212     }
5213   "
5216 ;; Reloading a df mode value stored in integer regs to memory can require a
5217 ;; scratch reg.
5218 (define_expand "reload_outdf"
5219   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5220    (match_operand:DF 1 "s_register_operand" "r")
5221    (match_operand:SI 2 "s_register_operand" "=&r")]
5222   "TARGET_ARM"
5223   "
5224   {
5225     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5227     if (code == REG)
5228       operands[2] = XEXP (operands[0], 0);
5229     else if (code == POST_INC || code == PRE_DEC)
5230       {
5231         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5232         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5233         emit_insn (gen_movdi (operands[0], operands[1]));
5234         DONE;
5235       }
5236     else if (code == PRE_INC)
5237       {
5238         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5240         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5241         operands[2] = reg;
5242       }
5243     else if (code == POST_DEC)
5244       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5245     else
5246       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5247                              XEXP (XEXP (operands[0], 0), 1)));
5249     emit_insn (gen_rtx_SET (VOIDmode,
5250                             replace_equiv_address (operands[0], operands[2]),
5251                             operands[1]));
5253     if (code == POST_DEC)
5254       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5256     DONE;
5257   }"
5260 (define_insn "*movdf_soft_insn"
5261   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5262         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5263   "TARGET_ARM && TARGET_SOFT_FLOAT
5264   "
5265   "*
5266   switch (which_alternative)
5267     {
5268     case 0:
5269     case 1:
5270     case 2:
5271       return \"#\";
5272     default:
5273       return output_move_double (operands);
5274     }
5275   "
5276   [(set_attr "length" "8,12,16,8,8")
5277    (set_attr "type" "*,*,*,load2,store2")
5278    (set_attr "pool_range" "1020")
5279    (set_attr "neg_pool_range" "1008")]
5282 ;;; ??? This should have alternatives for constants.
5283 ;;; ??? This was originally identical to the movdi_insn pattern.
5284 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5285 ;;; thumb_reorg with a memory reference.
5286 (define_insn "*thumb_movdf_insn"
5287   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5288         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5289   "TARGET_THUMB
5290    && (   register_operand (operands[0], DFmode)
5291        || register_operand (operands[1], DFmode))"
5292   "*
5293   switch (which_alternative)
5294     {
5295     default:
5296     case 0:
5297       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5298         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5299       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5300     case 1:
5301       return \"ldmia\\t%1, {%0, %H0}\";
5302     case 2:
5303       return \"stmia\\t%0, {%1, %H1}\";
5304     case 3:
5305       return thumb_load_double_from_address (operands);
5306     case 4:
5307       operands[2] = gen_rtx_MEM (SImode,
5308                                  plus_constant (XEXP (operands[0], 0), 4));
5309       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5310       return \"\";
5311     case 5:
5312       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5313         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5314       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5315     }
5316   "
5317   [(set_attr "length" "4,2,2,6,4,4")
5318    (set_attr "type" "*,load2,store2,load2,store2,*")
5319    (set_attr "pool_range" "*,*,*,1020,*,*")]
5322 (define_expand "movxf"
5323   [(set (match_operand:XF 0 "general_operand" "")
5324         (match_operand:XF 1 "general_operand" ""))]
5325   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5326   "
5327   if (GET_CODE (operands[0]) == MEM)
5328     operands[1] = force_reg (XFmode, operands[1]);
5329   "
5332 ;; Vector Moves
5333 (define_expand "movv2si"
5334   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5335         (match_operand:V2SI 1 "general_operand" ""))]
5336   "TARGET_REALLY_IWMMXT"
5340 (define_expand "movv4hi"
5341   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5342         (match_operand:V4HI 1 "general_operand" ""))]
5343   "TARGET_REALLY_IWMMXT"
5347 (define_expand "movv8qi"
5348   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5349         (match_operand:V8QI 1 "general_operand" ""))]
5350   "TARGET_REALLY_IWMMXT"
5355 ;; load- and store-multiple insns
5356 ;; The arm can load/store any set of registers, provided that they are in
5357 ;; ascending order; but that is beyond GCC so stick with what it knows.
5359 (define_expand "load_multiple"
5360   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5361                           (match_operand:SI 1 "" ""))
5362                      (use (match_operand:SI 2 "" ""))])]
5363   "TARGET_ARM"
5365   HOST_WIDE_INT offset = 0;
5367   /* Support only fixed point registers.  */
5368   if (GET_CODE (operands[2]) != CONST_INT
5369       || INTVAL (operands[2]) > 14
5370       || INTVAL (operands[2]) < 2
5371       || GET_CODE (operands[1]) != MEM
5372       || GET_CODE (operands[0]) != REG
5373       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5374       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5375     FAIL;
5377   operands[3]
5378     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5379                              force_reg (SImode, XEXP (operands[1], 0)),
5380                              TRUE, FALSE, operands[1], &offset);
5383 ;; Load multiple with write-back
5385 (define_insn "*ldmsi_postinc4"
5386   [(match_parallel 0 "load_multiple_operation"
5387     [(set (match_operand:SI 1 "s_register_operand" "=r")
5388           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5389                    (const_int 16)))
5390      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5391           (mem:SI (match_dup 2)))
5392      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5393           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5394      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5395           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5396      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5397           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5398   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5399   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5400   [(set_attr "type" "load4")
5401    (set_attr "predicable" "yes")]
5404 (define_insn "*ldmsi_postinc4_thumb"
5405   [(match_parallel 0 "load_multiple_operation"
5406     [(set (match_operand:SI 1 "s_register_operand" "=l")
5407           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5408                    (const_int 16)))
5409      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5410           (mem:SI (match_dup 2)))
5411      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5412           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5413      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5414           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5415      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5416           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5417   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5418   "ldmia\\t%1!, {%3, %4, %5, %6}"
5419   [(set_attr "type" "load4")]
5422 (define_insn "*ldmsi_postinc3"
5423   [(match_parallel 0 "load_multiple_operation"
5424     [(set (match_operand:SI 1 "s_register_operand" "=r")
5425           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5426                    (const_int 12)))
5427      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5428           (mem:SI (match_dup 2)))
5429      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5430           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5431      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5432           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5433   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5434   "ldm%?ia\\t%1!, {%3, %4, %5}"
5435   [(set_attr "type" "load3")
5436    (set_attr "predicable" "yes")]
5439 (define_insn "*ldmsi_postinc2"
5440   [(match_parallel 0 "load_multiple_operation"
5441     [(set (match_operand:SI 1 "s_register_operand" "=r")
5442           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5443                    (const_int 8)))
5444      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5445           (mem:SI (match_dup 2)))
5446      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5447           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5448   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5449   "ldm%?ia\\t%1!, {%3, %4}"
5450   [(set_attr "type" "load2")
5451    (set_attr "predicable" "yes")]
5454 ;; Ordinary load multiple
5456 (define_insn "*ldmsi4"
5457   [(match_parallel 0 "load_multiple_operation"
5458     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5459           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5460      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5461           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5462      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5463           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5464      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5465           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5466   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5467   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5468   [(set_attr "type" "load4")
5469    (set_attr "predicable" "yes")]
5472 (define_insn "*ldmsi3"
5473   [(match_parallel 0 "load_multiple_operation"
5474     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5475           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5476      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5477           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5478      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5479           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5480   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5481   "ldm%?ia\\t%1, {%2, %3, %4}"
5482   [(set_attr "type" "load3")
5483    (set_attr "predicable" "yes")]
5486 (define_insn "*ldmsi2"
5487   [(match_parallel 0 "load_multiple_operation"
5488     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5489           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5490      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5491           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5492   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5493   "ldm%?ia\\t%1, {%2, %3}"
5494   [(set_attr "type" "load2")
5495    (set_attr "predicable" "yes")]
5498 (define_expand "store_multiple"
5499   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5500                           (match_operand:SI 1 "" ""))
5501                      (use (match_operand:SI 2 "" ""))])]
5502   "TARGET_ARM"
5504   HOST_WIDE_INT offset = 0;
5506   /* Support only fixed point registers.  */
5507   if (GET_CODE (operands[2]) != CONST_INT
5508       || INTVAL (operands[2]) > 14
5509       || INTVAL (operands[2]) < 2
5510       || GET_CODE (operands[1]) != REG
5511       || GET_CODE (operands[0]) != MEM
5512       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5513       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5514     FAIL;
5516   operands[3]
5517     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5518                               force_reg (SImode, XEXP (operands[0], 0)),
5519                               TRUE, FALSE, operands[0], &offset);
5522 ;; Store multiple with write-back
5524 (define_insn "*stmsi_postinc4"
5525   [(match_parallel 0 "store_multiple_operation"
5526     [(set (match_operand:SI 1 "s_register_operand" "=r")
5527           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5528                    (const_int 16)))
5529      (set (mem:SI (match_dup 2))
5530           (match_operand:SI 3 "arm_hard_register_operand" ""))
5531      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5532           (match_operand:SI 4 "arm_hard_register_operand" ""))
5533      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5534           (match_operand:SI 5 "arm_hard_register_operand" ""))
5535      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5536           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5537   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5538   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5539   [(set_attr "predicable" "yes")
5540    (set_attr "type" "store4")]
5543 (define_insn "*stmsi_postinc4_thumb"
5544   [(match_parallel 0 "store_multiple_operation"
5545     [(set (match_operand:SI 1 "s_register_operand" "=l")
5546           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5547                    (const_int 16)))
5548      (set (mem:SI (match_dup 2))
5549           (match_operand:SI 3 "arm_hard_register_operand" ""))
5550      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5551           (match_operand:SI 4 "arm_hard_register_operand" ""))
5552      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5553           (match_operand:SI 5 "arm_hard_register_operand" ""))
5554      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5555           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5556   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5557   "stmia\\t%1!, {%3, %4, %5, %6}"
5558   [(set_attr "type" "store4")]
5561 (define_insn "*stmsi_postinc3"
5562   [(match_parallel 0 "store_multiple_operation"
5563     [(set (match_operand:SI 1 "s_register_operand" "=r")
5564           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5565                    (const_int 12)))
5566      (set (mem:SI (match_dup 2))
5567           (match_operand:SI 3 "arm_hard_register_operand" ""))
5568      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5569           (match_operand:SI 4 "arm_hard_register_operand" ""))
5570      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5571           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5572   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5573   "stm%?ia\\t%1!, {%3, %4, %5}"
5574   [(set_attr "predicable" "yes")
5575    (set_attr "type" "store3")]
5578 (define_insn "*stmsi_postinc2"
5579   [(match_parallel 0 "store_multiple_operation"
5580     [(set (match_operand:SI 1 "s_register_operand" "=r")
5581           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5582                    (const_int 8)))
5583      (set (mem:SI (match_dup 2))
5584           (match_operand:SI 3 "arm_hard_register_operand" ""))
5585      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5586           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5587   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5588   "stm%?ia\\t%1!, {%3, %4}"
5589   [(set_attr "predicable" "yes")
5590    (set_attr "type" "store2")]
5593 ;; Ordinary store multiple
5595 (define_insn "*stmsi4"
5596   [(match_parallel 0 "store_multiple_operation"
5597     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5598           (match_operand:SI 2 "arm_hard_register_operand" ""))
5599      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5600           (match_operand:SI 3 "arm_hard_register_operand" ""))
5601      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5602           (match_operand:SI 4 "arm_hard_register_operand" ""))
5603      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5604           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5605   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5606   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5607   [(set_attr "predicable" "yes")
5608    (set_attr "type" "store4")]
5611 (define_insn "*stmsi3"
5612   [(match_parallel 0 "store_multiple_operation"
5613     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5614           (match_operand:SI 2 "arm_hard_register_operand" ""))
5615      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5616           (match_operand:SI 3 "arm_hard_register_operand" ""))
5617      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5618           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5619   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5620   "stm%?ia\\t%1, {%2, %3, %4}"
5621   [(set_attr "predicable" "yes")
5622    (set_attr "type" "store3")]
5625 (define_insn "*stmsi2"
5626   [(match_parallel 0 "store_multiple_operation"
5627     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5628           (match_operand:SI 2 "arm_hard_register_operand" ""))
5629      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5630           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5631   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5632   "stm%?ia\\t%1, {%2, %3}"
5633   [(set_attr "predicable" "yes")
5634    (set_attr "type" "store2")]
5637 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5638 ;; We could let this apply for blocks of less than this, but it clobbers so
5639 ;; many registers that there is then probably a better way.
5641 (define_expand "movmemqi"
5642   [(match_operand:BLK 0 "general_operand" "")
5643    (match_operand:BLK 1 "general_operand" "")
5644    (match_operand:SI 2 "const_int_operand" "")
5645    (match_operand:SI 3 "const_int_operand" "")]
5646   "TARGET_EITHER"
5647   "
5648   if (TARGET_ARM)
5649     {
5650       if (arm_gen_movmemqi (operands))
5651         DONE;
5652       FAIL;
5653     }
5654   else /* TARGET_THUMB */
5655     {
5656       if (   INTVAL (operands[3]) != 4
5657           || INTVAL (operands[2]) > 48)
5658         FAIL;
5660       thumb_expand_movmemqi (operands);
5661       DONE;
5662     }
5663   "
5666 ;; Thumb block-move insns
5668 (define_insn "movmem12b"
5669   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5670         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5671    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5672         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5673    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5674         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5675    (set (match_operand:SI 0 "register_operand" "=l")
5676         (plus:SI (match_dup 2) (const_int 12)))
5677    (set (match_operand:SI 1 "register_operand" "=l")
5678         (plus:SI (match_dup 3) (const_int 12)))
5679    (clobber (match_scratch:SI 4 "=&l"))
5680    (clobber (match_scratch:SI 5 "=&l"))
5681    (clobber (match_scratch:SI 6 "=&l"))]
5682   "TARGET_THUMB"
5683   "* return thumb_output_move_mem_multiple (3, operands);"
5684   [(set_attr "length" "4")
5685    ; This isn't entirely accurate...  It loads as well, but in terms of
5686    ; scheduling the following insn it is better to consider it as a store
5687    (set_attr "type" "store3")]
5690 (define_insn "movmem8b"
5691   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5692         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5693    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5694         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5695    (set (match_operand:SI 0 "register_operand" "=l")
5696         (plus:SI (match_dup 2) (const_int 8)))
5697    (set (match_operand:SI 1 "register_operand" "=l")
5698         (plus:SI (match_dup 3) (const_int 8)))
5699    (clobber (match_scratch:SI 4 "=&l"))
5700    (clobber (match_scratch:SI 5 "=&l"))]
5701   "TARGET_THUMB"
5702   "* return thumb_output_move_mem_multiple (2, operands);"
5703   [(set_attr "length" "4")
5704    ; This isn't entirely accurate...  It loads as well, but in terms of
5705    ; scheduling the following insn it is better to consider it as a store
5706    (set_attr "type" "store2")]
5711 ;; Compare & branch insns
5712 ;; The range calculations are based as follows:
5713 ;; For forward branches, the address calculation returns the address of
5714 ;; the next instruction.  This is 2 beyond the branch instruction.
5715 ;; For backward branches, the address calculation returns the address of
5716 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5717 ;; instruction for the shortest sequence, and 4 before the branch instruction
5718 ;; if we have to jump around an unconditional branch.
5719 ;; To the basic branch range the PC offset must be added (this is +4).
5720 ;; So for forward branches we have 
5721 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5722 ;; And for backward branches we have 
5723 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5725 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5726 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5728 (define_expand "cbranchsi4"
5729   [(set (pc) (if_then_else
5730               (match_operator 0 "arm_comparison_operator"
5731                [(match_operand:SI 1 "s_register_operand" "")
5732                 (match_operand:SI 2 "nonmemory_operand" "")])
5733               (label_ref (match_operand 3 "" ""))
5734               (pc)))]
5735   "TARGET_THUMB"
5736   "
5737   if (thumb_cmpneg_operand (operands[2], SImode))
5738     {
5739       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5740                                               operands[3], operands[0]));
5741       DONE;
5742     }
5743   if (!thumb_cmp_operand (operands[2], SImode))
5744     operands[2] = force_reg (SImode, operands[2]);
5745   ")
5747 (define_insn "*cbranchsi4_insn"
5748   [(set (pc) (if_then_else
5749               (match_operator 0 "arm_comparison_operator"
5750                [(match_operand:SI 1 "s_register_operand" "l,*h")
5751                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5752               (label_ref (match_operand 3 "" ""))
5753               (pc)))]
5754   "TARGET_THUMB"
5755   "*
5756   output_asm_insn (\"cmp\\t%1, %2\", operands);
5758   switch (get_attr_length (insn))
5759     {
5760     case 4:  return \"b%d0\\t%l3\";
5761     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5762     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5763     }
5764   "
5765   [(set (attr "far_jump")
5766         (if_then_else
5767             (eq_attr "length" "8")
5768             (const_string "yes")
5769             (const_string "no")))
5770    (set (attr "length") 
5771         (if_then_else
5772             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5773                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5774             (const_int 4)
5775             (if_then_else
5776                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5777                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5778                 (const_int 6)
5779                 (const_int 8))))]
5782 (define_insn "cbranchsi4_scratch"
5783   [(set (pc) (if_then_else
5784               (match_operator 4 "arm_comparison_operator"
5785                [(match_operand:SI 1 "s_register_operand" "l,0")
5786                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5787               (label_ref (match_operand 3 "" ""))
5788               (pc)))
5789    (clobber (match_scratch:SI 0 "=l,l"))]
5790   "TARGET_THUMB"
5791   "*
5792   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5794   switch (get_attr_length (insn))
5795     {
5796     case 4:  return \"b%d4\\t%l3\";
5797     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5798     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5799     }
5800   "
5801   [(set (attr "far_jump")
5802         (if_then_else
5803             (eq_attr "length" "8")
5804             (const_string "yes")
5805             (const_string "no")))
5806    (set (attr "length") 
5807         (if_then_else
5808             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5809                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5810             (const_int 4)
5811             (if_then_else
5812                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5813                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5814                 (const_int 6)
5815                 (const_int 8))))]
5817 (define_insn "*movsi_cbranchsi4"
5818   [(set (pc)
5819         (if_then_else
5820          (match_operator 3 "arm_comparison_operator"
5821           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5822            (const_int 0)])
5823          (label_ref (match_operand 2 "" ""))
5824          (pc)))
5825    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5826         (match_dup 1))]
5827   "TARGET_THUMB"
5828   "*{
5829   if (which_alternative == 0)
5830     output_asm_insn (\"cmp\t%0, #0\", operands);
5831   else if (which_alternative == 1)
5832     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5833   else
5834     {
5835       output_asm_insn (\"cmp\t%1, #0\", operands);
5836       if (which_alternative == 2)
5837         output_asm_insn (\"mov\t%0, %1\", operands);
5838       else
5839         output_asm_insn (\"str\t%1, %0\", operands);
5840     }
5841   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5842     {
5843     case 4:  return \"b%d3\\t%l2\";
5844     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5845     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5846     }
5847   }"
5848   [(set (attr "far_jump")
5849         (if_then_else
5850             (ior (and (gt (symbol_ref ("which_alternative"))
5851                           (const_int 1))
5852                       (eq_attr "length" "8"))
5853                  (eq_attr "length" "10"))
5854             (const_string "yes")
5855             (const_string "no")))
5856    (set (attr "length")
5857      (if_then_else
5858        (le (symbol_ref ("which_alternative"))
5859                        (const_int 1))
5860        (if_then_else
5861          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5862               (le (minus (match_dup 2) (pc)) (const_int 256)))
5863          (const_int 4)
5864          (if_then_else
5865            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5866                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5867            (const_int 6)
5868            (const_int 8)))
5869        (if_then_else
5870          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5871               (le (minus (match_dup 2) (pc)) (const_int 256)))
5872          (const_int 6)
5873          (if_then_else
5874            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5875                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5876            (const_int 8)
5877            (const_int 10)))))]
5880 (define_insn "*negated_cbranchsi4"
5881   [(set (pc)
5882         (if_then_else
5883          (match_operator 0 "equality_operator"
5884           [(match_operand:SI 1 "s_register_operand" "l")
5885            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5886          (label_ref (match_operand 3 "" ""))
5887          (pc)))]
5888   "TARGET_THUMB"
5889   "*
5890   output_asm_insn (\"cmn\\t%1, %2\", operands);
5891   switch (get_attr_length (insn))
5892     {
5893     case 4:  return \"b%d0\\t%l3\";
5894     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5895     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5896     }
5897   "
5898   [(set (attr "far_jump")
5899         (if_then_else
5900             (eq_attr "length" "8")
5901             (const_string "yes")
5902             (const_string "no")))
5903    (set (attr "length") 
5904         (if_then_else
5905             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5906                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5907             (const_int 4)
5908             (if_then_else
5909                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5910                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5911                 (const_int 6)
5912                 (const_int 8))))]
5915 (define_insn "*tbit_cbranch"
5916   [(set (pc)
5917         (if_then_else
5918          (match_operator 0 "equality_operator"
5919           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5920                             (const_int 1)
5921                             (match_operand:SI 2 "const_int_operand" "i"))
5922            (const_int 0)])
5923          (label_ref (match_operand 3 "" ""))
5924          (pc)))
5925    (clobber (match_scratch:SI 4 "=l"))]
5926   "TARGET_THUMB"
5927   "*
5928   {
5929   rtx op[3];
5930   op[0] = operands[4];
5931   op[1] = operands[1];
5932   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5934   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5935   switch (get_attr_length (insn))
5936     {
5937     case 4:  return \"b%d0\\t%l3\";
5938     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5939     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5940     }
5941   }"
5942   [(set (attr "far_jump")
5943         (if_then_else
5944             (eq_attr "length" "8")
5945             (const_string "yes")
5946             (const_string "no")))
5947    (set (attr "length") 
5948         (if_then_else
5949             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5950                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5951             (const_int 4)
5952             (if_then_else
5953                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5954                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5955                 (const_int 6)
5956                 (const_int 8))))]
5958   
5959 (define_insn "*tstsi3_cbranch"
5960   [(set (pc)
5961         (if_then_else
5962          (match_operator 3 "equality_operator"
5963           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5964                    (match_operand:SI 1 "s_register_operand" "l"))
5965            (const_int 0)])
5966          (label_ref (match_operand 2 "" ""))
5967          (pc)))]
5968   "TARGET_THUMB"
5969   "*
5970   {
5971   output_asm_insn (\"tst\\t%0, %1\", operands);
5972   switch (get_attr_length (insn))
5973     {
5974     case 4:  return \"b%d3\\t%l2\";
5975     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5976     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5977     }
5978   }"
5979   [(set (attr "far_jump")
5980         (if_then_else
5981             (eq_attr "length" "8")
5982             (const_string "yes")
5983             (const_string "no")))
5984    (set (attr "length") 
5985         (if_then_else
5986             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5987                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5988             (const_int 4)
5989             (if_then_else
5990                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5991                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5992                 (const_int 6)
5993                 (const_int 8))))]
5995   
5996 (define_insn "*andsi3_cbranch"
5997   [(set (pc)
5998         (if_then_else
5999          (match_operator 5 "equality_operator"
6000           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6001                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6002            (const_int 0)])
6003          (label_ref (match_operand 4 "" ""))
6004          (pc)))
6005    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6006         (and:SI (match_dup 2) (match_dup 3)))
6007    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6008   "TARGET_THUMB"
6009   "*
6010   {
6011   if (which_alternative == 0)
6012     output_asm_insn (\"and\\t%0, %3\", operands);
6013   else if (which_alternative == 1)
6014     {
6015       output_asm_insn (\"and\\t%1, %3\", operands);
6016       output_asm_insn (\"mov\\t%0, %1\", operands);
6017     }
6018   else
6019     {
6020       output_asm_insn (\"and\\t%1, %3\", operands);
6021       output_asm_insn (\"str\\t%1, %0\", operands);
6022     }
6024   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6025     {
6026     case 4:  return \"b%d5\\t%l4\";
6027     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6028     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6029     }
6030   }"
6031   [(set (attr "far_jump")
6032         (if_then_else
6033             (ior (and (eq (symbol_ref ("which_alternative"))
6034                           (const_int 0))
6035                       (eq_attr "length" "8"))
6036                  (eq_attr "length" "10"))
6037             (const_string "yes")
6038             (const_string "no")))
6039    (set (attr "length")
6040      (if_then_else
6041        (eq (symbol_ref ("which_alternative"))
6042                        (const_int 0))
6043        (if_then_else
6044          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6045               (le (minus (match_dup 4) (pc)) (const_int 256)))
6046          (const_int 4)
6047          (if_then_else
6048            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6049                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6050            (const_int 6)
6051            (const_int 8)))
6052        (if_then_else
6053          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6054               (le (minus (match_dup 4) (pc)) (const_int 256)))
6055          (const_int 6)
6056          (if_then_else
6057            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6058                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6059            (const_int 8)
6060            (const_int 10)))))]
6063 (define_insn "*orrsi3_cbranch_scratch"
6064   [(set (pc)
6065         (if_then_else
6066          (match_operator 4 "equality_operator"
6067           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
6068                    (match_operand:SI 2 "s_register_operand" "l"))
6069            (const_int 0)])
6070          (label_ref (match_operand 3 "" ""))
6071          (pc)))
6072    (clobber (match_scratch:SI 0 "=l"))]
6073   "TARGET_THUMB"
6074   "*
6075   {
6076   output_asm_insn (\"orr\\t%0, %2\", operands);
6077   switch (get_attr_length (insn))
6078     {
6079     case 4:  return \"b%d4\\t%l3\";
6080     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6081     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6082     }
6083   }"
6084   [(set (attr "far_jump")
6085         (if_then_else
6086             (eq_attr "length" "8")
6087             (const_string "yes")
6088             (const_string "no")))
6089    (set (attr "length") 
6090         (if_then_else
6091             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6092                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6093             (const_int 4)
6094             (if_then_else
6095                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6096                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6097                 (const_int 6)
6098                 (const_int 8))))]
6100   
6101 (define_insn "*orrsi3_cbranch"
6102   [(set (pc)
6103         (if_then_else
6104          (match_operator 5 "equality_operator"
6105           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6106                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6107            (const_int 0)])
6108          (label_ref (match_operand 4 "" ""))
6109          (pc)))
6110    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6111         (ior:SI (match_dup 2) (match_dup 3)))
6112    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6113   "TARGET_THUMB"
6114   "*
6115   {
6116   if (which_alternative == 0)
6117     output_asm_insn (\"orr\\t%0, %3\", operands);
6118   else if (which_alternative == 1)
6119     {
6120       output_asm_insn (\"orr\\t%1, %3\", operands);
6121       output_asm_insn (\"mov\\t%0, %1\", operands);
6122     }
6123   else
6124     {
6125       output_asm_insn (\"orr\\t%1, %3\", operands);
6126       output_asm_insn (\"str\\t%1, %0\", operands);
6127     }
6129   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6130     {
6131     case 4:  return \"b%d5\\t%l4\";
6132     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6133     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6134     }
6135   }"
6136   [(set (attr "far_jump")
6137         (if_then_else
6138             (ior (and (eq (symbol_ref ("which_alternative"))
6139                           (const_int 0))
6140                       (eq_attr "length" "8"))
6141                  (eq_attr "length" "10"))
6142             (const_string "yes")
6143             (const_string "no")))
6144    (set (attr "length")
6145      (if_then_else
6146        (eq (symbol_ref ("which_alternative"))
6147                        (const_int 0))
6148        (if_then_else
6149          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6150               (le (minus (match_dup 4) (pc)) (const_int 256)))
6151          (const_int 4)
6152          (if_then_else
6153            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6154                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6155            (const_int 6)
6156            (const_int 8)))
6157        (if_then_else
6158          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6159               (le (minus (match_dup 4) (pc)) (const_int 256)))
6160          (const_int 6)
6161          (if_then_else
6162            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6163                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6164            (const_int 8)
6165            (const_int 10)))))]
6168 (define_insn "*xorsi3_cbranch_scratch"
6169   [(set (pc)
6170         (if_then_else
6171          (match_operator 4 "equality_operator"
6172           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6173                    (match_operand:SI 2 "s_register_operand" "l"))
6174            (const_int 0)])
6175          (label_ref (match_operand 3 "" ""))
6176          (pc)))
6177    (clobber (match_scratch:SI 0 "=l"))]
6178   "TARGET_THUMB"
6179   "*
6180   {
6181   output_asm_insn (\"eor\\t%0, %2\", operands);
6182   switch (get_attr_length (insn))
6183     {
6184     case 4:  return \"b%d4\\t%l3\";
6185     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6186     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6187     }
6188   }"
6189   [(set (attr "far_jump")
6190         (if_then_else
6191             (eq_attr "length" "8")
6192             (const_string "yes")
6193             (const_string "no")))
6194    (set (attr "length") 
6195         (if_then_else
6196             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6197                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6198             (const_int 4)
6199             (if_then_else
6200                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6201                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6202                 (const_int 6)
6203                 (const_int 8))))]
6205   
6206 (define_insn "*xorsi3_cbranch"
6207   [(set (pc)
6208         (if_then_else
6209          (match_operator 5 "equality_operator"
6210           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6211                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6212            (const_int 0)])
6213          (label_ref (match_operand 4 "" ""))
6214          (pc)))
6215    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6216         (xor:SI (match_dup 2) (match_dup 3)))
6217    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6218   "TARGET_THUMB"
6219   "*
6220   {
6221   if (which_alternative == 0)
6222     output_asm_insn (\"eor\\t%0, %3\", operands);
6223   else if (which_alternative == 1)
6224     {
6225       output_asm_insn (\"eor\\t%1, %3\", operands);
6226       output_asm_insn (\"mov\\t%0, %1\", operands);
6227     }
6228   else
6229     {
6230       output_asm_insn (\"eor\\t%1, %3\", operands);
6231       output_asm_insn (\"str\\t%1, %0\", operands);
6232     }
6234   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6235     {
6236     case 4:  return \"b%d5\\t%l4\";
6237     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6238     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6239     }
6240   }"
6241   [(set (attr "far_jump")
6242         (if_then_else
6243             (ior (and (eq (symbol_ref ("which_alternative"))
6244                           (const_int 0))
6245                       (eq_attr "length" "8"))
6246                  (eq_attr "length" "10"))
6247             (const_string "yes")
6248             (const_string "no")))
6249    (set (attr "length")
6250      (if_then_else
6251        (eq (symbol_ref ("which_alternative"))
6252                        (const_int 0))
6253        (if_then_else
6254          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6255               (le (minus (match_dup 4) (pc)) (const_int 256)))
6256          (const_int 4)
6257          (if_then_else
6258            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6259                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6260            (const_int 6)
6261            (const_int 8)))
6262        (if_then_else
6263          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6264               (le (minus (match_dup 4) (pc)) (const_int 256)))
6265          (const_int 6)
6266          (if_then_else
6267            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6268                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6269            (const_int 8)
6270            (const_int 10)))))]
6273 (define_insn "*bicsi3_cbranch_scratch"
6274   [(set (pc)
6275         (if_then_else
6276          (match_operator 4 "equality_operator"
6277           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6278                    (match_operand:SI 1 "s_register_operand" "0"))
6279            (const_int 0)])
6280          (label_ref (match_operand 3 "" ""))
6281          (pc)))
6282    (clobber (match_scratch:SI 0 "=l"))]
6283   "TARGET_THUMB"
6284   "*
6285   {
6286   output_asm_insn (\"bic\\t%0, %2\", operands);
6287   switch (get_attr_length (insn))
6288     {
6289     case 4:  return \"b%d4\\t%l3\";
6290     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6291     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6292     }
6293   }"
6294   [(set (attr "far_jump")
6295         (if_then_else
6296             (eq_attr "length" "8")
6297             (const_string "yes")
6298             (const_string "no")))
6299    (set (attr "length") 
6300         (if_then_else
6301             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6302                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6303             (const_int 4)
6304             (if_then_else
6305                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6306                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6307                 (const_int 6)
6308                 (const_int 8))))]
6310   
6311 (define_insn "*bicsi3_cbranch"
6312   [(set (pc)
6313         (if_then_else
6314          (match_operator 5 "equality_operator"
6315           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6316                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6317            (const_int 0)])
6318          (label_ref (match_operand 4 "" ""))
6319          (pc)))
6320    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6321         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6322    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6323   "TARGET_THUMB"
6324   "*
6325   {
6326   if (which_alternative == 0)
6327     output_asm_insn (\"bic\\t%0, %3\", operands);
6328   else if (which_alternative <= 2)
6329     {
6330       output_asm_insn (\"bic\\t%1, %3\", operands);
6331       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6332          conditions again, since we're only testing for equality.  */
6333       output_asm_insn (\"mov\\t%0, %1\", operands);
6334     }
6335   else
6336     {
6337       output_asm_insn (\"bic\\t%1, %3\", operands);
6338       output_asm_insn (\"str\\t%1, %0\", operands);
6339     }
6341   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6342     {
6343     case 4:  return \"b%d5\\t%l4\";
6344     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6345     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6346     }
6347   }"
6348   [(set (attr "far_jump")
6349         (if_then_else
6350             (ior (and (eq (symbol_ref ("which_alternative"))
6351                           (const_int 0))
6352                       (eq_attr "length" "8"))
6353                  (eq_attr "length" "10"))
6354             (const_string "yes")
6355             (const_string "no")))
6356    (set (attr "length")
6357      (if_then_else
6358        (eq (symbol_ref ("which_alternative"))
6359                        (const_int 0))
6360        (if_then_else
6361          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6362               (le (minus (match_dup 4) (pc)) (const_int 256)))
6363          (const_int 4)
6364          (if_then_else
6365            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6366                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6367            (const_int 6)
6368            (const_int 8)))
6369        (if_then_else
6370          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6371               (le (minus (match_dup 4) (pc)) (const_int 256)))
6372          (const_int 6)
6373          (if_then_else
6374            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6375                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6376            (const_int 8)
6377            (const_int 10)))))]
6380 (define_insn "*cbranchne_decr1"
6381   [(set (pc)
6382         (if_then_else (match_operator 3 "equality_operator"
6383                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6384                         (const_int 0)])
6385                       (label_ref (match_operand 4 "" ""))
6386                       (pc)))
6387    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6388         (plus:SI (match_dup 2) (const_int -1)))
6389    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6390   "TARGET_THUMB"
6391   "*
6392    {
6393      rtx cond[2];
6394      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6395                                 ? GEU : LTU),
6396                                VOIDmode, operands[2], const1_rtx);
6397      cond[1] = operands[4];
6399      if (which_alternative == 0)
6400        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6401      else if (which_alternative == 1)
6402        {
6403          /* We must provide an alternative for a hi reg because reload 
6404             cannot handle output reloads on a jump instruction, but we
6405             can't subtract into that.  Fortunately a mov from lo to hi
6406             does not clobber the condition codes.  */
6407          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6408          output_asm_insn (\"mov\\t%0, %1\", operands);
6409        }
6410      else
6411        {
6412          /* Similarly, but the target is memory.  */
6413          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6414          output_asm_insn (\"str\\t%1, %0\", operands);
6415        }
6417      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6418        {
6419          case 4:
6420            output_asm_insn (\"b%d0\\t%l1\", cond);
6421            return \"\";
6422          case 6:
6423            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6424            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6425          default:
6426            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6427            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6428        }
6429    }
6430   "
6431   [(set (attr "far_jump")
6432         (if_then_else
6433             (ior (and (eq (symbol_ref ("which_alternative"))
6434                           (const_int 0))
6435                       (eq_attr "length" "8"))
6436                  (eq_attr "length" "10"))
6437             (const_string "yes")
6438             (const_string "no")))
6439    (set_attr_alternative "length"
6440       [
6441        ;; Alternative 0
6442        (if_then_else
6443          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6444               (le (minus (match_dup 4) (pc)) (const_int 256)))
6445          (const_int 4)
6446          (if_then_else
6447            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6448                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6449            (const_int 6)
6450            (const_int 8)))
6451        ;; Alternative 1
6452        (if_then_else
6453          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6454               (le (minus (match_dup 4) (pc)) (const_int 256)))
6455          (const_int 6)
6456          (if_then_else
6457            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6458                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6459            (const_int 8)
6460            (const_int 10)))
6461        ;; Alternative 2
6462        (if_then_else
6463          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6464               (le (minus (match_dup 4) (pc)) (const_int 256)))
6465          (const_int 6)
6466          (if_then_else
6467            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6468                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6469            (const_int 8)
6470            (const_int 10)))
6471        ;; Alternative 3
6472        (if_then_else
6473          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6474               (le (minus (match_dup 4) (pc)) (const_int 256)))
6475          (const_int 6)
6476          (if_then_else
6477            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6478                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6479            (const_int 8)
6480            (const_int 10)))])]
6483 (define_insn "*addsi3_cbranch"
6484   [(set (pc)
6485         (if_then_else
6486          (match_operator 4 "comparison_operator"
6487           [(plus:SI
6488             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6489             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6490            (const_int 0)])
6491          (label_ref (match_operand 5 "" ""))
6492          (pc)))
6493    (set
6494     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6495     (plus:SI (match_dup 2) (match_dup 3)))
6496    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6497   "TARGET_THUMB
6498    && (GET_CODE (operands[4]) == EQ
6499        || GET_CODE (operands[4]) == NE
6500        || GET_CODE (operands[4]) == GE
6501        || GET_CODE (operands[4]) == LT)"
6502   "*
6503    {
6504      rtx cond[3];
6506      
6507      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6508      cond[1] = operands[2];
6509      cond[2] = operands[3];
6511      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6512        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6513      else
6514        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6516      if (which_alternative >= 3
6517          && which_alternative < 4)
6518        output_asm_insn (\"mov\\t%0, %1\", operands);
6519      else if (which_alternative >= 4)
6520        output_asm_insn (\"str\\t%1, %0\", operands);
6522      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6523        {
6524          case 4:
6525            return \"b%d4\\t%l5\";
6526          case 6:
6527            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6528          default:
6529            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6530        }
6531    }
6532   "
6533   [(set (attr "far_jump")
6534         (if_then_else
6535             (ior (and (lt (symbol_ref ("which_alternative"))
6536                           (const_int 3))
6537                       (eq_attr "length" "8"))
6538                  (eq_attr "length" "10"))
6539             (const_string "yes")
6540             (const_string "no")))
6541    (set (attr "length")
6542      (if_then_else
6543        (lt (symbol_ref ("which_alternative"))
6544                        (const_int 3))
6545        (if_then_else
6546          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6547               (le (minus (match_dup 5) (pc)) (const_int 256)))
6548          (const_int 4)
6549          (if_then_else
6550            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6551                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6552            (const_int 6)
6553            (const_int 8)))
6554        (if_then_else
6555          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6556               (le (minus (match_dup 5) (pc)) (const_int 256)))
6557          (const_int 6)
6558          (if_then_else
6559            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6560                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6561            (const_int 8)
6562            (const_int 10)))))]
6565 (define_insn "*addsi3_cbranch_scratch"
6566   [(set (pc)
6567         (if_then_else
6568          (match_operator 3 "comparison_operator"
6569           [(plus:SI
6570             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6571             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6572            (const_int 0)])
6573          (label_ref (match_operand 4 "" ""))
6574          (pc)))
6575    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6576   "TARGET_THUMB
6577    && (GET_CODE (operands[3]) == EQ
6578        || GET_CODE (operands[3]) == NE
6579        || GET_CODE (operands[3]) == GE
6580        || GET_CODE (operands[3]) == LT)"
6581   "*
6582    {
6583      switch (which_alternative)
6584        {
6585        case 0:
6586          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6587          break;
6588        case 1:
6589          output_asm_insn (\"cmn\t%1, %2\", operands);
6590          break;
6591        case 2:
6592          if (INTVAL (operands[2]) < 0)
6593            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6594          else
6595            output_asm_insn (\"add\t%0, %1, %2\", operands);
6596          break;
6597        case 3:
6598          if (INTVAL (operands[2]) < 0)
6599            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6600          else
6601            output_asm_insn (\"add\t%0, %0, %2\", operands);
6602          break;
6603        }
6605      switch (get_attr_length (insn))
6606        {
6607          case 4:
6608            return \"b%d3\\t%l4\";
6609          case 6:
6610            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6611          default:
6612            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6613        }
6614    }
6615   "
6616   [(set (attr "far_jump")
6617         (if_then_else
6618             (eq_attr "length" "8")
6619             (const_string "yes")
6620             (const_string "no")))
6621    (set (attr "length")
6622        (if_then_else
6623          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6624               (le (minus (match_dup 4) (pc)) (const_int 256)))
6625          (const_int 4)
6626          (if_then_else
6627            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6628                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6629            (const_int 6)
6630            (const_int 8))))]
6633 (define_insn "*subsi3_cbranch"
6634   [(set (pc)
6635         (if_then_else
6636          (match_operator 4 "comparison_operator"
6637           [(minus:SI
6638             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6639             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6640            (const_int 0)])
6641          (label_ref (match_operand 5 "" ""))
6642          (pc)))
6643    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6644         (minus:SI (match_dup 2) (match_dup 3)))
6645    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6646   "TARGET_THUMB
6647    && (GET_CODE (operands[4]) == EQ
6648        || GET_CODE (operands[4]) == NE
6649        || GET_CODE (operands[4]) == GE
6650        || GET_CODE (operands[4]) == LT)"
6651   "*
6652    {
6653      if (which_alternative == 0)
6654        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6655      else if (which_alternative == 1)
6656        {
6657          /* We must provide an alternative for a hi reg because reload 
6658             cannot handle output reloads on a jump instruction, but we
6659             can't subtract into that.  Fortunately a mov from lo to hi
6660             does not clobber the condition codes.  */
6661          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6662          output_asm_insn (\"mov\\t%0, %1\", operands);
6663        }
6664      else
6665        {
6666          /* Similarly, but the target is memory.  */
6667          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6668          output_asm_insn (\"str\\t%1, %0\", operands);
6669        }
6671      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6672        {
6673          case 4:
6674            return \"b%d4\\t%l5\";
6675          case 6:
6676            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6677          default:
6678            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6679        }
6680    }
6681   "
6682   [(set (attr "far_jump")
6683         (if_then_else
6684             (ior (and (eq (symbol_ref ("which_alternative"))
6685                           (const_int 0))
6686                       (eq_attr "length" "8"))
6687                  (eq_attr "length" "10"))
6688             (const_string "yes")
6689             (const_string "no")))
6690    (set (attr "length")
6691      (if_then_else
6692        (eq (symbol_ref ("which_alternative"))
6693                        (const_int 0))
6694        (if_then_else
6695          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6696               (le (minus (match_dup 5) (pc)) (const_int 256)))
6697          (const_int 4)
6698          (if_then_else
6699            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6700                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6701            (const_int 6)
6702            (const_int 8)))
6703        (if_then_else
6704          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6705               (le (minus (match_dup 5) (pc)) (const_int 256)))
6706          (const_int 6)
6707          (if_then_else
6708            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6709                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6710            (const_int 8)
6711            (const_int 10)))))]
6714 (define_insn "*subsi3_cbranch_scratch"
6715   [(set (pc)
6716         (if_then_else
6717          (match_operator 0 "arm_comparison_operator"
6718           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6719                      (match_operand:SI 2 "nonmemory_operand" "l"))
6720            (const_int 0)])
6721          (label_ref (match_operand 3 "" ""))
6722          (pc)))]
6723   "TARGET_THUMB
6724    && (GET_CODE (operands[0]) == EQ
6725        || GET_CODE (operands[0]) == NE
6726        || GET_CODE (operands[0]) == GE
6727        || GET_CODE (operands[0]) == LT)"
6728   "*
6729   output_asm_insn (\"cmp\\t%1, %2\", operands);
6730   switch (get_attr_length (insn))
6731     {
6732     case 4:  return \"b%d0\\t%l3\";
6733     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6734     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6735     }
6736   "
6737   [(set (attr "far_jump")
6738         (if_then_else
6739             (eq_attr "length" "8")
6740             (const_string "yes")
6741             (const_string "no")))
6742    (set (attr "length") 
6743         (if_then_else
6744             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6745                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6746             (const_int 4)
6747             (if_then_else
6748                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6749                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6750                 (const_int 6)
6751                 (const_int 8))))]
6754 ;; Comparison and test insns
6756 (define_expand "cmpsi"
6757   [(match_operand:SI 0 "s_register_operand" "")
6758    (match_operand:SI 1 "arm_add_operand" "")]
6759   "TARGET_ARM"
6760   "{
6761     arm_compare_op0 = operands[0];
6762     arm_compare_op1 = operands[1];
6763     DONE;
6764   }"
6767 (define_expand "cmpsf"
6768   [(match_operand:SF 0 "s_register_operand" "")
6769    (match_operand:SF 1 "arm_float_compare_operand" "")]
6770   "TARGET_ARM && TARGET_HARD_FLOAT"
6771   "
6772   arm_compare_op0 = operands[0];
6773   arm_compare_op1 = operands[1];
6774   DONE;
6775   "
6778 (define_expand "cmpdf"
6779   [(match_operand:DF 0 "s_register_operand" "")
6780    (match_operand:DF 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_insn "*arm_cmpsi_insn"
6790   [(set (reg:CC CC_REGNUM)
6791         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6792                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6793   "TARGET_ARM"
6794   "@
6795    cmp%?\\t%0, %1
6796    cmn%?\\t%0, #%n1"
6797   [(set_attr "conds" "set")]
6800 (define_insn "*cmpsi_shiftsi"
6801   [(set (reg:CC CC_REGNUM)
6802         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6803                     (match_operator:SI  3 "shift_operator"
6804                      [(match_operand:SI 1 "s_register_operand" "r")
6805                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6806   "TARGET_ARM"
6807   "cmp%?\\t%0, %1%S3"
6808   [(set_attr "conds" "set")
6809    (set_attr "shift" "1")
6810    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6811                       (const_string "alu_shift")
6812                       (const_string "alu_shift_reg")))]
6815 (define_insn "*cmpsi_shiftsi_swp"
6816   [(set (reg:CC_SWP CC_REGNUM)
6817         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6818                          [(match_operand:SI 1 "s_register_operand" "r")
6819                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6820                         (match_operand:SI 0 "s_register_operand" "r")))]
6821   "TARGET_ARM"
6822   "cmp%?\\t%0, %1%S3"
6823   [(set_attr "conds" "set")
6824    (set_attr "shift" "1")
6825    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6826                       (const_string "alu_shift")
6827                       (const_string "alu_shift_reg")))]
6830 (define_insn "*cmpsi_negshiftsi_si"
6831   [(set (reg:CC_Z CC_REGNUM)
6832         (compare:CC_Z
6833          (neg:SI (match_operator:SI 1 "shift_operator"
6834                     [(match_operand:SI 2 "s_register_operand" "r")
6835                      (match_operand:SI 3 "reg_or_int_operand" "rM")]))
6836          (match_operand:SI 0 "s_register_operand" "r")))]
6837   "TARGET_ARM"
6838   "cmn%?\\t%0, %2%S1"
6839   [(set_attr "conds" "set")
6840    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
6841                                     (const_string "alu_shift")
6842                                     (const_string "alu_shift_reg")))]
6845 ;; Cirrus SF compare instruction
6846 (define_insn "*cirrus_cmpsf"
6847   [(set (reg:CCFP CC_REGNUM)
6848         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6849                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6850   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6851   "cfcmps%?\\tr15, %V0, %V1"
6852   [(set_attr "type"   "mav_farith")
6853    (set_attr "cirrus" "compare")]
6856 ;; Cirrus DF compare instruction
6857 (define_insn "*cirrus_cmpdf"
6858   [(set (reg:CCFP CC_REGNUM)
6859         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6860                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6861   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6862   "cfcmpd%?\\tr15, %V0, %V1"
6863   [(set_attr "type"   "mav_farith")
6864    (set_attr "cirrus" "compare")]
6867 ;; Cirrus DI compare instruction
6868 (define_expand "cmpdi"
6869   [(match_operand:DI 0 "cirrus_fp_register" "")
6870    (match_operand:DI 1 "cirrus_fp_register" "")]
6871   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6872   "{
6873      arm_compare_op0 = operands[0];
6874      arm_compare_op1 = operands[1];
6875      DONE;
6876    }")
6878 (define_insn "*cirrus_cmpdi"
6879   [(set (reg:CC CC_REGNUM)
6880         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6881                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6882   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6883   "cfcmp64%?\\tr15, %V0, %V1"
6884   [(set_attr "type"   "mav_farith")
6885    (set_attr "cirrus" "compare")]
6888 ; This insn allows redundant compares to be removed by cse, nothing should
6889 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6890 ; is deleted later on. The match_dup will match the mode here, so that
6891 ; mode changes of the condition codes aren't lost by this even though we don't
6892 ; specify what they are.
6894 (define_insn "*deleted_compare"
6895   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6896   "TARGET_ARM"
6897   "\\t%@ deleted compare"
6898   [(set_attr "conds" "set")
6899    (set_attr "length" "0")]
6903 ;; Conditional branch insns
6905 (define_expand "beq"
6906   [(set (pc)
6907         (if_then_else (eq (match_dup 1) (const_int 0))
6908                       (label_ref (match_operand 0 "" ""))
6909                       (pc)))]
6910   "TARGET_ARM"
6911   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6914 (define_expand "bne"
6915   [(set (pc)
6916         (if_then_else (ne (match_dup 1) (const_int 0))
6917                       (label_ref (match_operand 0 "" ""))
6918                       (pc)))]
6919   "TARGET_ARM"
6920   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6923 (define_expand "bgt"
6924   [(set (pc)
6925         (if_then_else (gt (match_dup 1) (const_int 0))
6926                       (label_ref (match_operand 0 "" ""))
6927                       (pc)))]
6928   "TARGET_ARM"
6929   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6932 (define_expand "ble"
6933   [(set (pc)
6934         (if_then_else (le (match_dup 1) (const_int 0))
6935                       (label_ref (match_operand 0 "" ""))
6936                       (pc)))]
6937   "TARGET_ARM"
6938   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6941 (define_expand "bge"
6942   [(set (pc)
6943         (if_then_else (ge (match_dup 1) (const_int 0))
6944                       (label_ref (match_operand 0 "" ""))
6945                       (pc)))]
6946   "TARGET_ARM"
6947   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6950 (define_expand "blt"
6951   [(set (pc)
6952         (if_then_else (lt (match_dup 1) (const_int 0))
6953                       (label_ref (match_operand 0 "" ""))
6954                       (pc)))]
6955   "TARGET_ARM"
6956   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6959 (define_expand "bgtu"
6960   [(set (pc)
6961         (if_then_else (gtu (match_dup 1) (const_int 0))
6962                       (label_ref (match_operand 0 "" ""))
6963                       (pc)))]
6964   "TARGET_ARM"
6965   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6968 (define_expand "bleu"
6969   [(set (pc)
6970         (if_then_else (leu (match_dup 1) (const_int 0))
6971                       (label_ref (match_operand 0 "" ""))
6972                       (pc)))]
6973   "TARGET_ARM"
6974   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6977 (define_expand "bgeu"
6978   [(set (pc)
6979         (if_then_else (geu (match_dup 1) (const_int 0))
6980                       (label_ref (match_operand 0 "" ""))
6981                       (pc)))]
6982   "TARGET_ARM"
6983   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6986 (define_expand "bltu"
6987   [(set (pc)
6988         (if_then_else (ltu (match_dup 1) (const_int 0))
6989                       (label_ref (match_operand 0 "" ""))
6990                       (pc)))]
6991   "TARGET_ARM"
6992   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6995 (define_expand "bunordered"
6996   [(set (pc)
6997         (if_then_else (unordered (match_dup 1) (const_int 0))
6998                       (label_ref (match_operand 0 "" ""))
6999                       (pc)))]
7000   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7001   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7002                                       arm_compare_op1);"
7005 (define_expand "bordered"
7006   [(set (pc)
7007         (if_then_else (ordered (match_dup 1) (const_int 0))
7008                       (label_ref (match_operand 0 "" ""))
7009                       (pc)))]
7010   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7011   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7012                                       arm_compare_op1);"
7015 (define_expand "bungt"
7016   [(set (pc)
7017         (if_then_else (ungt (match_dup 1) (const_int 0))
7018                       (label_ref (match_operand 0 "" ""))
7019                       (pc)))]
7020   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7021   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
7024 (define_expand "bunlt"
7025   [(set (pc)
7026         (if_then_else (unlt (match_dup 1) (const_int 0))
7027                       (label_ref (match_operand 0 "" ""))
7028                       (pc)))]
7029   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7030   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
7033 (define_expand "bunge"
7034   [(set (pc)
7035         (if_then_else (unge (match_dup 1) (const_int 0))
7036                       (label_ref (match_operand 0 "" ""))
7037                       (pc)))]
7038   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7039   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
7042 (define_expand "bunle"
7043   [(set (pc)
7044         (if_then_else (unle (match_dup 1) (const_int 0))
7045                       (label_ref (match_operand 0 "" ""))
7046                       (pc)))]
7047   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7048   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
7051 ;; The following two patterns need two branch instructions, since there is
7052 ;; no single instruction that will handle all cases.
7053 (define_expand "buneq"
7054   [(set (pc)
7055         (if_then_else (uneq (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 (UNEQ, arm_compare_op0, arm_compare_op1);"
7062 (define_expand "bltgt"
7063   [(set (pc)
7064         (if_then_else (ltgt (match_dup 1) (const_int 0))
7065                       (label_ref (match_operand 0 "" ""))
7066                       (pc)))]
7067   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7068   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
7072 ;; Patterns to match conditional branch insns.
7075 ; Special pattern to match UNEQ.
7076 (define_insn "*arm_buneq"
7077   [(set (pc)
7078         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7079                       (label_ref (match_operand 0 "" ""))
7080                       (pc)))]
7081   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7082   "*
7083   gcc_assert (!arm_ccfsm_state);
7085   return \"bvs\\t%l0\;beq\\t%l0\";
7086   "
7087   [(set_attr "conds" "jump_clob")
7088    (set_attr "length" "8")]
7091 ; Special pattern to match LTGT.
7092 (define_insn "*arm_bltgt"
7093   [(set (pc)
7094         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7095                       (label_ref (match_operand 0 "" ""))
7096                       (pc)))]
7097   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7098   "*
7099   gcc_assert (!arm_ccfsm_state);
7101   return \"bmi\\t%l0\;bgt\\t%l0\";
7102   "
7103   [(set_attr "conds" "jump_clob")
7104    (set_attr "length" "8")]
7107 (define_insn "*arm_cond_branch"
7108   [(set (pc)
7109         (if_then_else (match_operator 1 "arm_comparison_operator"
7110                        [(match_operand 2 "cc_register" "") (const_int 0)])
7111                       (label_ref (match_operand 0 "" ""))
7112                       (pc)))]
7113   "TARGET_ARM"
7114   "*
7115   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7116     {
7117       arm_ccfsm_state += 2;
7118       return \"\";
7119     }
7120   return \"b%d1\\t%l0\";
7121   "
7122   [(set_attr "conds" "use")
7123    (set_attr "type" "branch")]
7126 ; Special pattern to match reversed UNEQ.
7127 (define_insn "*arm_buneq_reversed"
7128   [(set (pc)
7129         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7130                       (pc)
7131                       (label_ref (match_operand 0 "" ""))))]
7132   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7133   "*
7134   gcc_assert (!arm_ccfsm_state);
7136   return \"bmi\\t%l0\;bgt\\t%l0\";
7137   "
7138   [(set_attr "conds" "jump_clob")
7139    (set_attr "length" "8")]
7142 ; Special pattern to match reversed LTGT.
7143 (define_insn "*arm_bltgt_reversed"
7144   [(set (pc)
7145         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7146                       (pc)
7147                       (label_ref (match_operand 0 "" ""))))]
7148   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7149   "*
7150   gcc_assert (!arm_ccfsm_state);
7152   return \"bvs\\t%l0\;beq\\t%l0\";
7153   "
7154   [(set_attr "conds" "jump_clob")
7155    (set_attr "length" "8")]
7158 (define_insn "*arm_cond_branch_reversed"
7159   [(set (pc)
7160         (if_then_else (match_operator 1 "arm_comparison_operator"
7161                        [(match_operand 2 "cc_register" "") (const_int 0)])
7162                       (pc)
7163                       (label_ref (match_operand 0 "" ""))))]
7164   "TARGET_ARM"
7165   "*
7166   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7167     {
7168       arm_ccfsm_state += 2;
7169       return \"\";
7170     }
7171   return \"b%D1\\t%l0\";
7172   "
7173   [(set_attr "conds" "use")
7174    (set_attr "type" "branch")]
7179 ; scc insns
7181 (define_expand "seq"
7182   [(set (match_operand:SI 0 "s_register_operand" "")
7183         (eq:SI (match_dup 1) (const_int 0)))]
7184   "TARGET_ARM"
7185   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7188 (define_expand "sne"
7189   [(set (match_operand:SI 0 "s_register_operand" "")
7190         (ne:SI (match_dup 1) (const_int 0)))]
7191   "TARGET_ARM"
7192   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7195 (define_expand "sgt"
7196   [(set (match_operand:SI 0 "s_register_operand" "")
7197         (gt:SI (match_dup 1) (const_int 0)))]
7198   "TARGET_ARM"
7199   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7202 (define_expand "sle"
7203   [(set (match_operand:SI 0 "s_register_operand" "")
7204         (le:SI (match_dup 1) (const_int 0)))]
7205   "TARGET_ARM"
7206   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7209 (define_expand "sge"
7210   [(set (match_operand:SI 0 "s_register_operand" "")
7211         (ge:SI (match_dup 1) (const_int 0)))]
7212   "TARGET_ARM"
7213   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7216 (define_expand "slt"
7217   [(set (match_operand:SI 0 "s_register_operand" "")
7218         (lt:SI (match_dup 1) (const_int 0)))]
7219   "TARGET_ARM"
7220   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7223 (define_expand "sgtu"
7224   [(set (match_operand:SI 0 "s_register_operand" "")
7225         (gtu:SI (match_dup 1) (const_int 0)))]
7226   "TARGET_ARM"
7227   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7230 (define_expand "sleu"
7231   [(set (match_operand:SI 0 "s_register_operand" "")
7232         (leu:SI (match_dup 1) (const_int 0)))]
7233   "TARGET_ARM"
7234   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7237 (define_expand "sgeu"
7238   [(set (match_operand:SI 0 "s_register_operand" "")
7239         (geu:SI (match_dup 1) (const_int 0)))]
7240   "TARGET_ARM"
7241   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7244 (define_expand "sltu"
7245   [(set (match_operand:SI 0 "s_register_operand" "")
7246         (ltu:SI (match_dup 1) (const_int 0)))]
7247   "TARGET_ARM"
7248   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7251 (define_expand "sunordered"
7252   [(set (match_operand:SI 0 "s_register_operand" "")
7253         (unordered:SI (match_dup 1) (const_int 0)))]
7254   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7255   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7256                                       arm_compare_op1);"
7259 (define_expand "sordered"
7260   [(set (match_operand:SI 0 "s_register_operand" "")
7261         (ordered:SI (match_dup 1) (const_int 0)))]
7262   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7263   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7264                                       arm_compare_op1);"
7267 (define_expand "sungt"
7268   [(set (match_operand:SI 0 "s_register_operand" "")
7269         (ungt:SI (match_dup 1) (const_int 0)))]
7270   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7271   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7272                                       arm_compare_op1);"
7275 (define_expand "sunge"
7276   [(set (match_operand:SI 0 "s_register_operand" "")
7277         (unge:SI (match_dup 1) (const_int 0)))]
7278   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7279   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7280                                       arm_compare_op1);"
7283 (define_expand "sunlt"
7284   [(set (match_operand:SI 0 "s_register_operand" "")
7285         (unlt:SI (match_dup 1) (const_int 0)))]
7286   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7287   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7288                                       arm_compare_op1);"
7291 (define_expand "sunle"
7292   [(set (match_operand:SI 0 "s_register_operand" "")
7293         (unle:SI (match_dup 1) (const_int 0)))]
7294   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7295   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7296                                       arm_compare_op1);"
7299 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7300 ;;; simple ARM instructions. 
7302 ; (define_expand "suneq"
7303 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7304 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7305 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7306 ;   "gcc_unreachable ();"
7307 ; )
7309 ; (define_expand "sltgt"
7310 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7311 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7312 ;   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7313 ;   "gcc_unreachable ();"
7314 ; )
7316 (define_insn "*mov_scc"
7317   [(set (match_operand:SI 0 "s_register_operand" "=r")
7318         (match_operator:SI 1 "arm_comparison_operator"
7319          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7320   "TARGET_ARM"
7321   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7322   [(set_attr "conds" "use")
7323    (set_attr "length" "8")]
7326 (define_insn "*mov_negscc"
7327   [(set (match_operand:SI 0 "s_register_operand" "=r")
7328         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7329                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7330   "TARGET_ARM"
7331   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7332   [(set_attr "conds" "use")
7333    (set_attr "length" "8")]
7336 (define_insn "*mov_notscc"
7337   [(set (match_operand:SI 0 "s_register_operand" "=r")
7338         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7339                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7340   "TARGET_ARM"
7341   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7342   [(set_attr "conds" "use")
7343    (set_attr "length" "8")]
7347 ;; Conditional move insns
7349 (define_expand "movsicc"
7350   [(set (match_operand:SI 0 "s_register_operand" "")
7351         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7352                          (match_operand:SI 2 "arm_not_operand" "")
7353                          (match_operand:SI 3 "arm_not_operand" "")))]
7354   "TARGET_ARM"
7355   "
7356   {
7357     enum rtx_code code = GET_CODE (operands[1]);
7358     rtx ccreg;
7360     if (code == UNEQ || code == LTGT)
7361       FAIL;
7363     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7364     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7365   }"
7368 (define_expand "movsfcc"
7369   [(set (match_operand:SF 0 "s_register_operand" "")
7370         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7371                          (match_operand:SF 2 "s_register_operand" "")
7372                          (match_operand:SF 3 "nonmemory_operand" "")))]
7373   "TARGET_ARM"
7374   "
7375   {
7376     enum rtx_code code = GET_CODE (operands[1]);
7377     rtx ccreg;
7379     if (code == UNEQ || code == LTGT)
7380       FAIL;
7382     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7383        Otherwise, ensure it is a valid FP add operand */
7384     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7385         || (!arm_float_add_operand (operands[3], SFmode)))
7386       operands[3] = force_reg (SFmode, operands[3]);
7388     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7389     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7390   }"
7393 (define_expand "movdfcc"
7394   [(set (match_operand:DF 0 "s_register_operand" "")
7395         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7396                          (match_operand:DF 2 "s_register_operand" "")
7397                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7398   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7399   "
7400   {
7401     enum rtx_code code = GET_CODE (operands[1]);
7402     rtx ccreg;
7404     if (code == UNEQ || code == LTGT)
7405       FAIL;
7407     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7408     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7409   }"
7412 (define_insn "*movsicc_insn"
7413   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7414         (if_then_else:SI
7415          (match_operator 3 "arm_comparison_operator"
7416           [(match_operand 4 "cc_register" "") (const_int 0)])
7417          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7418          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7419   "TARGET_ARM"
7420   "@
7421    mov%D3\\t%0, %2
7422    mvn%D3\\t%0, #%B2
7423    mov%d3\\t%0, %1
7424    mvn%d3\\t%0, #%B1
7425    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7426    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7427    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7428    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7429   [(set_attr "length" "4,4,4,4,8,8,8,8")
7430    (set_attr "conds" "use")]
7433 (define_insn "*movsfcc_soft_insn"
7434   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7435         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7436                           [(match_operand 4 "cc_register" "") (const_int 0)])
7437                          (match_operand:SF 1 "s_register_operand" "0,r")
7438                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7439   "TARGET_ARM && TARGET_SOFT_FLOAT"
7440   "@
7441    mov%D3\\t%0, %2
7442    mov%d3\\t%0, %1"
7443   [(set_attr "conds" "use")]
7447 ;; Jump and linkage insns
7449 (define_expand "jump"
7450   [(set (pc)
7451         (label_ref (match_operand 0 "" "")))]
7452   "TARGET_EITHER"
7453   ""
7456 (define_insn "*arm_jump"
7457   [(set (pc)
7458         (label_ref (match_operand 0 "" "")))]
7459   "TARGET_ARM"
7460   "*
7461   {
7462     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7463       {
7464         arm_ccfsm_state += 2;
7465         return \"\";
7466       }
7467     return \"b%?\\t%l0\";
7468   }
7469   "
7470   [(set_attr "predicable" "yes")]
7473 (define_insn "*thumb_jump"
7474   [(set (pc)
7475         (label_ref (match_operand 0 "" "")))]
7476   "TARGET_THUMB"
7477   "*
7478   if (get_attr_length (insn) == 2)
7479     return \"b\\t%l0\";
7480   return \"bl\\t%l0\\t%@ far jump\";
7481   "
7482   [(set (attr "far_jump")
7483         (if_then_else
7484             (eq_attr "length" "4")
7485             (const_string "yes")
7486             (const_string "no")))
7487    (set (attr "length") 
7488         (if_then_else
7489             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7490                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7491             (const_int 2)
7492             (const_int 4)))]
7495 (define_expand "call"
7496   [(parallel [(call (match_operand 0 "memory_operand" "")
7497                     (match_operand 1 "general_operand" ""))
7498               (use (match_operand 2 "" ""))
7499               (clobber (reg:SI LR_REGNUM))])]
7500   "TARGET_EITHER"
7501   "
7502   {
7503     rtx callee;
7504     
7505     /* In an untyped call, we can get NULL for operand 2.  */
7506     if (operands[2] == NULL_RTX)
7507       operands[2] = const0_rtx;
7508       
7509     /* This is to decide if we should generate indirect calls by loading the
7510        32 bit address of the callee into a register before performing the
7511        branch and link.  operand[2] encodes the long_call/short_call
7512        attribute of the function being called.  This attribute is set whenever
7513        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7514        is used, and the short_call attribute can also be set if function is
7515        declared as static or if it has already been defined in the current
7516        compilation unit.  See arm.c and arm.h for info about this.  The third
7517        parameter to arm_is_longcall_p is used to tell it which pattern
7518        invoked it.  */
7519     callee  = XEXP (operands[0], 0);
7520     
7521     if ((GET_CODE (callee) == SYMBOL_REF
7522          && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7523         || (GET_CODE (callee) != SYMBOL_REF
7524             && GET_CODE (callee) != REG))
7525       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7526   }"
7529 (define_insn "*call_reg_armv5"
7530   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7531          (match_operand 1 "" ""))
7532    (use (match_operand 2 "" ""))
7533    (clobber (reg:SI LR_REGNUM))]
7534   "TARGET_ARM && arm_arch5"
7535   "blx%?\\t%0"
7536   [(set_attr "type" "call")]
7539 (define_insn "*call_reg_arm"
7540   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7541          (match_operand 1 "" ""))
7542    (use (match_operand 2 "" ""))
7543    (clobber (reg:SI LR_REGNUM))]
7544   "TARGET_ARM && !arm_arch5"
7545   "*
7546   return output_call (operands);
7547   "
7548   ;; length is worst case, normally it is only two
7549   [(set_attr "length" "12")
7550    (set_attr "type" "call")]
7553 (define_insn "*call_mem"
7554   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7555          (match_operand 1 "" ""))
7556    (use (match_operand 2 "" ""))
7557    (clobber (reg:SI LR_REGNUM))]
7558   "TARGET_ARM"
7559   "*
7560   return output_call_mem (operands);
7561   "
7562   [(set_attr "length" "12")
7563    (set_attr "type" "call")]
7566 (define_insn "*call_reg_thumb_v5"
7567   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7568          (match_operand 1 "" ""))
7569    (use (match_operand 2 "" ""))
7570    (clobber (reg:SI LR_REGNUM))]
7571   "TARGET_THUMB && arm_arch5"
7572   "blx\\t%0"
7573   [(set_attr "length" "2")
7574    (set_attr "type" "call")]
7577 (define_insn "*call_reg_thumb"
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   "*
7584   {
7585     if (!TARGET_CALLER_INTERWORKING)
7586       return thumb_call_via_reg (operands[0]);
7587     else if (operands[1] == const0_rtx)
7588       return \"bl\\t%__interwork_call_via_%0\";
7589     else if (frame_pointer_needed)
7590       return \"bl\\t%__interwork_r7_call_via_%0\";
7591     else
7592       return \"bl\\t%__interwork_r11_call_via_%0\";
7593   }"
7594   [(set_attr "type" "call")]
7597 (define_expand "call_value"
7598   [(parallel [(set (match_operand       0 "" "")
7599                    (call (match_operand 1 "memory_operand" "")
7600                          (match_operand 2 "general_operand" "")))
7601               (use (match_operand 3 "" ""))
7602               (clobber (reg:SI LR_REGNUM))])]
7603   "TARGET_EITHER"
7604   "
7605   {
7606     rtx callee = XEXP (operands[1], 0);
7607     
7608     /* In an untyped call, we can get NULL for operand 2.  */
7609     if (operands[3] == 0)
7610       operands[3] = const0_rtx;
7611       
7612     /* See the comment in define_expand \"call\".  */
7613     if ((GET_CODE (callee) == SYMBOL_REF
7614          && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7615         || (GET_CODE (callee) != SYMBOL_REF
7616             && GET_CODE (callee) != REG))
7617       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7618   }"
7621 (define_insn "*call_value_reg_armv5"
7622   [(set (match_operand 0 "" "")
7623         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7624               (match_operand 2 "" "")))
7625    (use (match_operand 3 "" ""))
7626    (clobber (reg:SI LR_REGNUM))]
7627   "TARGET_ARM && arm_arch5"
7628   "blx%?\\t%1"
7629   [(set_attr "type" "call")]
7632 (define_insn "*call_value_reg_arm"
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   "*
7640   return output_call (&operands[1]);
7641   "
7642   [(set_attr "length" "12")
7643    (set_attr "type" "call")]
7646 (define_insn "*call_value_mem"
7647   [(set (match_operand 0 "" "")
7648         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7649               (match_operand 2 "" "")))
7650    (use (match_operand 3 "" ""))
7651    (clobber (reg:SI LR_REGNUM))]
7652   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7653   "*
7654   return output_call_mem (&operands[1]);
7655   "
7656   [(set_attr "length" "12")
7657    (set_attr "type" "call")]
7660 (define_insn "*call_value_reg_thumb_v5"
7661   [(set (match_operand 0 "" "")
7662         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7663               (match_operand 2 "" "")))
7664    (use (match_operand 3 "" ""))
7665    (clobber (reg:SI LR_REGNUM))]
7666   "TARGET_THUMB && arm_arch5"
7667   "blx\\t%1"
7668   [(set_attr "length" "2")
7669    (set_attr "type" "call")]
7672 (define_insn "*call_value_reg_thumb"
7673   [(set (match_operand 0 "" "")
7674         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7675               (match_operand 2 "" "")))
7676    (use (match_operand 3 "" ""))
7677    (clobber (reg:SI LR_REGNUM))]
7678   "TARGET_THUMB && !arm_arch5"
7679   "*
7680   {
7681     if (!TARGET_CALLER_INTERWORKING)
7682       return thumb_call_via_reg (operands[1]);
7683     else if (operands[2] == const0_rtx)
7684       return \"bl\\t%__interwork_call_via_%1\";
7685     else if (frame_pointer_needed)
7686       return \"bl\\t%__interwork_r7_call_via_%1\";
7687     else
7688       return \"bl\\t%__interwork_r11_call_via_%1\";
7689   }"
7690   [(set_attr "type" "call")]
7693 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7694 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7696 (define_insn "*call_symbol"
7697   [(call (mem:SI (match_operand:SI 0 "" ""))
7698          (match_operand 1 "" ""))
7699    (use (match_operand 2 "" ""))
7700    (clobber (reg:SI LR_REGNUM))]
7701   "TARGET_ARM
7702    && (GET_CODE (operands[0]) == SYMBOL_REF)
7703    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7704   "*
7705   {
7706     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7707   }"
7708   [(set_attr "type" "call")]
7711 (define_insn "*call_value_symbol"
7712   [(set (match_operand 0 "" "")
7713         (call (mem:SI (match_operand:SI 1 "" ""))
7714         (match_operand:SI 2 "" "")))
7715    (use (match_operand 3 "" ""))
7716    (clobber (reg:SI LR_REGNUM))]
7717   "TARGET_ARM
7718    && (GET_CODE (operands[1]) == SYMBOL_REF)
7719    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7720   "*
7721   {
7722     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7723   }"
7724   [(set_attr "type" "call")]
7727 (define_insn "*call_insn"
7728   [(call (mem:SI (match_operand:SI 0 "" ""))
7729          (match_operand:SI 1 "" ""))
7730    (use (match_operand 2 "" ""))
7731    (clobber (reg:SI LR_REGNUM))]
7732   "TARGET_THUMB
7733    && GET_CODE (operands[0]) == SYMBOL_REF
7734    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7735   "bl\\t%a0"
7736   [(set_attr "length" "4")
7737    (set_attr "type" "call")]
7740 (define_insn "*call_value_insn"
7741   [(set (match_operand 0 "" "")
7742         (call (mem:SI (match_operand 1 "" ""))
7743               (match_operand 2 "" "")))
7744    (use (match_operand 3 "" ""))
7745    (clobber (reg:SI LR_REGNUM))]
7746   "TARGET_THUMB
7747    && GET_CODE (operands[1]) == SYMBOL_REF
7748    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7749   "bl\\t%a1"
7750   [(set_attr "length" "4")
7751    (set_attr "type" "call")]
7754 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7755 (define_expand "sibcall"
7756   [(parallel [(call (match_operand 0 "memory_operand" "")
7757                     (match_operand 1 "general_operand" ""))
7758               (return)
7759               (use (match_operand 2 "" ""))])]
7760   "TARGET_ARM"
7761   "
7762   {
7763     if (operands[2] == NULL_RTX)
7764       operands[2] = const0_rtx;
7765   }"
7768 (define_expand "sibcall_value"
7769   [(parallel [(set (match_operand 0 "" "")
7770                    (call (match_operand 1 "memory_operand" "")
7771                          (match_operand 2 "general_operand" "")))
7772               (return)
7773               (use (match_operand 3 "" ""))])]
7774   "TARGET_ARM"
7775   "
7776   {
7777     if (operands[3] == NULL_RTX)
7778       operands[3] = const0_rtx;
7779   }"
7782 (define_insn "*sibcall_insn"
7783  [(call (mem:SI (match_operand:SI 0 "" "X"))
7784         (match_operand 1 "" ""))
7785   (return)
7786   (use (match_operand 2 "" ""))]
7787   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7788   "*
7789   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7790   "
7791   [(set_attr "type" "call")]
7794 (define_insn "*sibcall_value_insn"
7795  [(set (match_operand 0 "" "")
7796        (call (mem:SI (match_operand:SI 1 "" "X"))
7797              (match_operand 2 "" "")))
7798   (return)
7799   (use (match_operand 3 "" ""))]
7800   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7801   "*
7802   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7803   "
7804   [(set_attr "type" "call")]
7807 ;; Often the return insn will be the same as loading from memory, so set attr
7808 (define_insn "return"
7809   [(return)]
7810   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7811   "*
7812   {
7813     if (arm_ccfsm_state == 2)
7814       {
7815         arm_ccfsm_state += 2;
7816         return \"\";
7817       }
7818     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7819   }"
7820   [(set_attr "type" "load1")
7821    (set_attr "length" "12")
7822    (set_attr "predicable" "yes")]
7825 (define_insn "*cond_return"
7826   [(set (pc)
7827         (if_then_else (match_operator 0 "arm_comparison_operator"
7828                        [(match_operand 1 "cc_register" "") (const_int 0)])
7829                       (return)
7830                       (pc)))]
7831   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7832   "*
7833   {
7834     if (arm_ccfsm_state == 2)
7835       {
7836         arm_ccfsm_state += 2;
7837         return \"\";
7838       }
7839     return output_return_instruction (operands[0], TRUE, FALSE);
7840   }"
7841   [(set_attr "conds" "use")
7842    (set_attr "length" "12")
7843    (set_attr "type" "load1")]
7846 (define_insn "*cond_return_inverted"
7847   [(set (pc)
7848         (if_then_else (match_operator 0 "arm_comparison_operator"
7849                        [(match_operand 1 "cc_register" "") (const_int 0)])
7850                       (pc)
7851                       (return)))]
7852   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7853   "*
7854   {
7855     if (arm_ccfsm_state == 2)
7856       {
7857         arm_ccfsm_state += 2;
7858         return \"\";
7859       }
7860     return output_return_instruction (operands[0], TRUE, TRUE);
7861   }"
7862   [(set_attr "conds" "use")
7863    (set_attr "length" "12")
7864    (set_attr "type" "load1")]
7867 ;; Generate a sequence of instructions to determine if the processor is
7868 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7869 ;; mask.
7871 (define_expand "return_addr_mask"
7872   [(set (match_dup 1)
7873       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7874                        (const_int 0)))
7875    (set (match_operand:SI 0 "s_register_operand" "")
7876       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7877                        (const_int -1)
7878                        (const_int 67108860)))] ; 0x03fffffc
7879   "TARGET_ARM"
7880   "
7881   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7882   ")
7884 (define_insn "*check_arch2"
7885   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7886       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7887                        (const_int 0)))]
7888   "TARGET_ARM"
7889   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7890   [(set_attr "length" "8")
7891    (set_attr "conds" "set")]
7894 ;; Call subroutine returning any type.
7896 (define_expand "untyped_call"
7897   [(parallel [(call (match_operand 0 "" "")
7898                     (const_int 0))
7899               (match_operand 1 "" "")
7900               (match_operand 2 "" "")])]
7901   "TARGET_EITHER"
7902   "
7903   {
7904     int i;
7905     rtx par = gen_rtx_PARALLEL (VOIDmode,
7906                                 rtvec_alloc (XVECLEN (operands[2], 0)));
7907     rtx addr = gen_reg_rtx (Pmode);
7908     rtx mem;
7909     int size = 0;
7911     emit_move_insn (addr, XEXP (operands[1], 0));
7912     mem = change_address (operands[1], BLKmode, addr);
7914     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7915       {
7916         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7918         /* Default code only uses r0 as a return value, but we could
7919            be using anything up to 4 registers.  */
7920         if (REGNO (src) == R0_REGNUM)
7921           src = gen_rtx_REG (TImode, R0_REGNUM);
7923         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7924                                                  GEN_INT (size));
7925         size += GET_MODE_SIZE (GET_MODE (src));
7926       }
7928     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7929                                     const0_rtx));
7931     size = 0;
7933     for (i = 0; i < XVECLEN (par, 0); i++)
7934       {
7935         HOST_WIDE_INT offset = 0;
7936         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7938         if (size != 0)
7939           emit_move_insn (addr, plus_constant (addr, size));
7941         mem = change_address (mem, GET_MODE (reg), NULL);
7942         if (REGNO (reg) == R0_REGNUM)
7943           {
7944             /* On thumb we have to use a write-back instruction.  */
7945             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7946                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7947             size = TARGET_ARM ? 16 : 0;
7948           }
7949         else
7950           {
7951             emit_move_insn (mem, reg);
7952             size = GET_MODE_SIZE (GET_MODE (reg));
7953           }
7954       }
7956     /* The optimizer does not know that the call sets the function value
7957        registers we stored in the result block.  We avoid problems by
7958        claiming that all hard registers are used and clobbered at this
7959        point.  */
7960     emit_insn (gen_blockage ());
7962     DONE;
7963   }"
7966 (define_expand "untyped_return"
7967   [(match_operand:BLK 0 "memory_operand" "")
7968    (match_operand 1 "" "")]
7969   "TARGET_EITHER"
7970   "
7971   {
7972     int i;
7973     rtx addr = gen_reg_rtx (Pmode);
7974     rtx mem;
7975     int size = 0;
7977     emit_move_insn (addr, XEXP (operands[0], 0));
7978     mem = change_address (operands[0], BLKmode, addr);
7980     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7981       {
7982         HOST_WIDE_INT offset = 0;
7983         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7985         if (size != 0)
7986           emit_move_insn (addr, plus_constant (addr, size));
7988         mem = change_address (mem, GET_MODE (reg), NULL);
7989         if (REGNO (reg) == R0_REGNUM)
7990           {
7991             /* On thumb we have to use a write-back instruction.  */
7992             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7993                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7994             size = TARGET_ARM ? 16 : 0;
7995           }
7996         else
7997           {
7998             emit_move_insn (reg, mem);
7999             size = GET_MODE_SIZE (GET_MODE (reg));
8000           }
8001       }
8003     /* Emit USE insns before the return.  */
8004     for (i = 0; i < XVECLEN (operands[1], 0); i++)
8005       emit_insn (gen_rtx_USE (VOIDmode,
8006                               SET_DEST (XVECEXP (operands[1], 0, i))));
8008     /* Construct the return.  */
8009     expand_naked_return ();
8011     DONE;
8012   }"
8015 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
8016 ;; all of memory.  This blocks insns from being moved across this point.
8018 (define_insn "blockage"
8019   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
8020   "TARGET_EITHER"
8021   ""
8022   [(set_attr "length" "0")
8023    (set_attr "type" "block")]
8026 (define_expand "casesi"
8027   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
8028    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
8029    (match_operand:SI 2 "const_int_operand" "")  ; total range
8030    (match_operand:SI 3 "" "")                   ; table label
8031    (match_operand:SI 4 "" "")]                  ; Out of range label
8032   "TARGET_ARM"
8033   "
8034   {
8035     rtx reg;
8036     if (operands[1] != const0_rtx)
8037       {
8038         reg = gen_reg_rtx (SImode);
8040         emit_insn (gen_addsi3 (reg, operands[0],
8041                                GEN_INT (-INTVAL (operands[1]))));
8042         operands[0] = reg;
8043       }
8045     if (!const_ok_for_arm (INTVAL (operands[2])))
8046       operands[2] = force_reg (SImode, operands[2]);
8048     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
8049                                          operands[4]));
8050     DONE;
8051   }"
8054 ;; The USE in this pattern is needed to tell flow analysis that this is
8055 ;; a CASESI insn.  It has no other purpose.
8056 (define_insn "casesi_internal"
8057   [(parallel [(set (pc)
8058                (if_then_else
8059                 (leu (match_operand:SI 0 "s_register_operand" "r")
8060                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
8061                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
8062                                  (label_ref (match_operand 2 "" ""))))
8063                 (label_ref (match_operand 3 "" ""))))
8064               (clobber (reg:CC CC_REGNUM))
8065               (use (label_ref (match_dup 2)))])]
8066   "TARGET_ARM"
8067   "*
8068     if (flag_pic)
8069       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
8070     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
8071   "
8072   [(set_attr "conds" "clob")
8073    (set_attr "length" "12")]
8076 (define_expand "indirect_jump"
8077   [(set (pc)
8078         (match_operand:SI 0 "s_register_operand" ""))]
8079   "TARGET_EITHER"
8080   ""
8083 ;; NB Never uses BX.
8084 (define_insn "*arm_indirect_jump"
8085   [(set (pc)
8086         (match_operand:SI 0 "s_register_operand" "r"))]
8087   "TARGET_ARM"
8088   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
8089   [(set_attr "predicable" "yes")]
8092 (define_insn "*load_indirect_jump"
8093   [(set (pc)
8094         (match_operand:SI 0 "memory_operand" "m"))]
8095   "TARGET_ARM"
8096   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
8097   [(set_attr "type" "load1")
8098    (set_attr "pool_range" "4096")
8099    (set_attr "neg_pool_range" "4084")
8100    (set_attr "predicable" "yes")]
8103 ;; NB Never uses BX.
8104 (define_insn "*thumb_indirect_jump"
8105   [(set (pc)
8106         (match_operand:SI 0 "register_operand" "l*r"))]
8107   "TARGET_THUMB"
8108   "mov\\tpc, %0"
8109   [(set_attr "conds" "clob")
8110    (set_attr "length" "2")]
8114 ;; Misc insns
8116 (define_insn "nop"
8117   [(const_int 0)]
8118   "TARGET_EITHER"
8119   "*
8120   if (TARGET_ARM)
8121     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8122   return  \"mov\\tr8, r8\";
8123   "
8124   [(set (attr "length")
8125         (if_then_else (eq_attr "is_thumb" "yes")
8126                       (const_int 2)
8127                       (const_int 4)))]
8131 ;; Patterns to allow combination of arithmetic, cond code and shifts
8133 (define_insn "*arith_shiftsi"
8134   [(set (match_operand:SI 0 "s_register_operand" "=r")
8135         (match_operator:SI 1 "shiftable_operator"
8136           [(match_operator:SI 3 "shift_operator"
8137              [(match_operand:SI 4 "s_register_operand" "r")
8138               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8139            (match_operand:SI 2 "s_register_operand" "r")]))]
8140   "TARGET_ARM"
8141   "%i1%?\\t%0, %2, %4%S3"
8142   [(set_attr "predicable" "yes")
8143    (set_attr "shift" "4")
8144    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8145                       (const_string "alu_shift")
8146                       (const_string "alu_shift_reg")))]
8149 (define_split
8150   [(set (match_operand:SI 0 "s_register_operand" "")
8151         (match_operator:SI 1 "shiftable_operator"
8152          [(match_operator:SI 2 "shiftable_operator"
8153            [(match_operator:SI 3 "shift_operator"
8154              [(match_operand:SI 4 "s_register_operand" "")
8155               (match_operand:SI 5 "reg_or_int_operand" "")])
8156             (match_operand:SI 6 "s_register_operand" "")])
8157           (match_operand:SI 7 "arm_rhs_operand" "")]))
8158    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8159   "TARGET_ARM"
8160   [(set (match_dup 8)
8161         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8162                          (match_dup 6)]))
8163    (set (match_dup 0)
8164         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8165   "")
8167 (define_insn "*arith_shiftsi_compare0"
8168   [(set (reg:CC_NOOV CC_REGNUM)
8169         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8170                           [(match_operator:SI 3 "shift_operator"
8171                             [(match_operand:SI 4 "s_register_operand" "r")
8172                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8173                            (match_operand:SI 2 "s_register_operand" "r")])
8174                          (const_int 0)))
8175    (set (match_operand:SI 0 "s_register_operand" "=r")
8176         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8177                          (match_dup 2)]))]
8178   "TARGET_ARM"
8179   "%i1%?s\\t%0, %2, %4%S3"
8180   [(set_attr "conds" "set")
8181    (set_attr "shift" "4")
8182    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8183                       (const_string "alu_shift")
8184                       (const_string "alu_shift_reg")))]
8187 (define_insn "*arith_shiftsi_compare0_scratch"
8188   [(set (reg:CC_NOOV CC_REGNUM)
8189         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8190                           [(match_operator:SI 3 "shift_operator"
8191                             [(match_operand:SI 4 "s_register_operand" "r")
8192                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8193                            (match_operand:SI 2 "s_register_operand" "r")])
8194                          (const_int 0)))
8195    (clobber (match_scratch:SI 0 "=r"))]
8196   "TARGET_ARM"
8197   "%i1%?s\\t%0, %2, %4%S3"
8198   [(set_attr "conds" "set")
8199    (set_attr "shift" "4")
8200    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8201                       (const_string "alu_shift")
8202                       (const_string "alu_shift_reg")))]
8205 (define_insn "*sub_shiftsi"
8206   [(set (match_operand:SI 0 "s_register_operand" "=r")
8207         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8208                   (match_operator:SI 2 "shift_operator"
8209                    [(match_operand:SI 3 "s_register_operand" "r")
8210                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8211   "TARGET_ARM"
8212   "sub%?\\t%0, %1, %3%S2"
8213   [(set_attr "predicable" "yes")
8214    (set_attr "shift" "3")
8215    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8216                       (const_string "alu_shift")
8217                       (const_string "alu_shift_reg")))]
8220 (define_insn "*sub_shiftsi_compare0"
8221   [(set (reg:CC_NOOV CC_REGNUM)
8222         (compare:CC_NOOV
8223          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8224                    (match_operator:SI 2 "shift_operator"
8225                     [(match_operand:SI 3 "s_register_operand" "r")
8226                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8227          (const_int 0)))
8228    (set (match_operand:SI 0 "s_register_operand" "=r")
8229         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8230                                                  (match_dup 4)])))]
8231   "TARGET_ARM"
8232   "sub%?s\\t%0, %1, %3%S2"
8233   [(set_attr "conds" "set")
8234    (set_attr "shift" "3")
8235    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8236                       (const_string "alu_shift")
8237                       (const_string "alu_shift_reg")))]
8240 (define_insn "*sub_shiftsi_compare0_scratch"
8241   [(set (reg:CC_NOOV CC_REGNUM)
8242         (compare:CC_NOOV
8243          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8244                    (match_operator:SI 2 "shift_operator"
8245                     [(match_operand:SI 3 "s_register_operand" "r")
8246                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8247          (const_int 0)))
8248    (clobber (match_scratch:SI 0 "=r"))]
8249   "TARGET_ARM"
8250   "sub%?s\\t%0, %1, %3%S2"
8251   [(set_attr "conds" "set")
8252    (set_attr "shift" "3")
8253    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8254                       (const_string "alu_shift")
8255                       (const_string "alu_shift_reg")))]
8260 (define_insn "*and_scc"
8261   [(set (match_operand:SI 0 "s_register_operand" "=r")
8262         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8263                  [(match_operand 3 "cc_register" "") (const_int 0)])
8264                 (match_operand:SI 2 "s_register_operand" "r")))]
8265   "TARGET_ARM"
8266   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8267   [(set_attr "conds" "use")
8268    (set_attr "length" "8")]
8271 (define_insn "*ior_scc"
8272   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8273         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8274                  [(match_operand 3 "cc_register" "") (const_int 0)])
8275                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8276   "TARGET_ARM"
8277   "@
8278    orr%d2\\t%0, %1, #1
8279    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8280   [(set_attr "conds" "use")
8281    (set_attr "length" "4,8")]
8284 (define_insn "*compare_scc"
8285   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8286         (match_operator:SI 1 "arm_comparison_operator"
8287          [(match_operand:SI 2 "s_register_operand" "r,r")
8288           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8289    (clobber (reg:CC CC_REGNUM))]
8290   "TARGET_ARM"
8291   "*
8292     if (operands[3] == const0_rtx)
8293       {
8294         if (GET_CODE (operands[1]) == LT)
8295           return \"mov\\t%0, %2, lsr #31\";
8297         if (GET_CODE (operands[1]) == GE)
8298           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8300         if (GET_CODE (operands[1]) == EQ)
8301           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8302       }
8304     if (GET_CODE (operands[1]) == NE)
8305       {
8306         if (which_alternative == 1)
8307           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8308         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8309       }
8310     if (which_alternative == 1)
8311       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8312     else
8313       output_asm_insn (\"cmp\\t%2, %3\", operands);
8314     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8315   "
8316   [(set_attr "conds" "clob")
8317    (set_attr "length" "12")]
8320 (define_insn "*cond_move"
8321   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8322         (if_then_else:SI (match_operator 3 "equality_operator"
8323                           [(match_operator 4 "arm_comparison_operator"
8324                             [(match_operand 5 "cc_register" "") (const_int 0)])
8325                            (const_int 0)])
8326                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8327                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8328   "TARGET_ARM"
8329   "*
8330     if (GET_CODE (operands[3]) == NE)
8331       {
8332         if (which_alternative != 1)
8333           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8334         if (which_alternative != 0)
8335           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8336         return \"\";
8337       }
8338     if (which_alternative != 0)
8339       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8340     if (which_alternative != 1)
8341       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8342     return \"\";
8343   "
8344   [(set_attr "conds" "use")
8345    (set_attr "length" "4,4,8")]
8348 (define_insn "*cond_arith"
8349   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8350         (match_operator:SI 5 "shiftable_operator" 
8351          [(match_operator:SI 4 "arm_comparison_operator"
8352            [(match_operand:SI 2 "s_register_operand" "r,r")
8353             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8354           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8355    (clobber (reg:CC CC_REGNUM))]
8356   "TARGET_ARM"
8357   "*
8358     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8359       return \"%i5\\t%0, %1, %2, lsr #31\";
8361     output_asm_insn (\"cmp\\t%2, %3\", operands);
8362     if (GET_CODE (operands[5]) == AND)
8363       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8364     else if (GET_CODE (operands[5]) == MINUS)
8365       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8366     else if (which_alternative != 0)
8367       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8368     return \"%i5%d4\\t%0, %1, #1\";
8369   "
8370   [(set_attr "conds" "clob")
8371    (set_attr "length" "12")]
8374 (define_insn "*cond_sub"
8375   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8376         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8377                   (match_operator:SI 4 "arm_comparison_operator"
8378                    [(match_operand:SI 2 "s_register_operand" "r,r")
8379                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8380    (clobber (reg:CC CC_REGNUM))]
8381   "TARGET_ARM"
8382   "*
8383     output_asm_insn (\"cmp\\t%2, %3\", operands);
8384     if (which_alternative != 0)
8385       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8386     return \"sub%d4\\t%0, %1, #1\";
8387   "
8388   [(set_attr "conds" "clob")
8389    (set_attr "length" "8,12")]
8392 (define_insn "*cmp_ite0"
8393   [(set (match_operand 6 "dominant_cc_register" "")
8394         (compare
8395          (if_then_else:SI
8396           (match_operator 4 "arm_comparison_operator"
8397            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8398             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8399           (match_operator:SI 5 "arm_comparison_operator"
8400            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8401             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8402           (const_int 0))
8403          (const_int 0)))]
8404   "TARGET_ARM"
8405   "*
8406   {
8407     static const char * const opcodes[4][2] =
8408     {
8409       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8410        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8411       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8412        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8413       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8414        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8415       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8416        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8417     };
8418     int swap =
8419       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8421     return opcodes[which_alternative][swap];
8422   }"
8423   [(set_attr "conds" "set")
8424    (set_attr "length" "8")]
8427 (define_insn "*cmp_ite1"
8428   [(set (match_operand 6 "dominant_cc_register" "")
8429         (compare
8430          (if_then_else:SI
8431           (match_operator 4 "arm_comparison_operator"
8432            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8433             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8434           (match_operator:SI 5 "arm_comparison_operator"
8435            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8436             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8437           (const_int 1))
8438          (const_int 0)))]
8439   "TARGET_ARM"
8440   "*
8441   {
8442     static const char * const opcodes[4][2] =
8443     {
8444       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8445        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8446       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8447        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8448       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8449        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8450       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8451        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8452     };
8453     int swap =
8454       comparison_dominates_p (GET_CODE (operands[5]),
8455                               reverse_condition (GET_CODE (operands[4])));
8457     return opcodes[which_alternative][swap];
8458   }"
8459   [(set_attr "conds" "set")
8460    (set_attr "length" "8")]
8463 (define_insn "*cmp_and"
8464   [(set (match_operand 6 "dominant_cc_register" "")
8465         (compare
8466          (and:SI
8467           (match_operator 4 "arm_comparison_operator"
8468            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8469             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8470           (match_operator:SI 5 "arm_comparison_operator"
8471            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8472             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8473          (const_int 0)))]
8474   "TARGET_ARM"
8475   "*
8476   {
8477     static const char *const opcodes[4][2] =
8478     {
8479       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8480        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8481       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8482        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8483       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8484        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8485       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8486        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8487     };
8488     int swap =
8489       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8491     return opcodes[which_alternative][swap];
8492   }"
8493   [(set_attr "conds" "set")
8494    (set_attr "predicable" "no")
8495    (set_attr "length" "8")]
8498 (define_insn "*cmp_ior"
8499   [(set (match_operand 6 "dominant_cc_register" "")
8500         (compare
8501          (ior:SI
8502           (match_operator 4 "arm_comparison_operator"
8503            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8504             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8505           (match_operator:SI 5 "arm_comparison_operator"
8506            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8507             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8508          (const_int 0)))]
8509   "TARGET_ARM"
8510   "*
8512   static const char *const opcodes[4][2] =
8513   {
8514     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8515      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8516     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8517      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8518     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8519      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8520     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8521      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8522   };
8523   int swap =
8524     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8526   return opcodes[which_alternative][swap];
8529   [(set_attr "conds" "set")
8530    (set_attr "length" "8")]
8533 (define_insn_and_split "*ior_scc_scc"
8534   [(set (match_operand:SI 0 "s_register_operand" "=r")
8535         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8536                  [(match_operand:SI 1 "s_register_operand" "r")
8537                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8538                 (match_operator:SI 6 "arm_comparison_operator"
8539                  [(match_operand:SI 4 "s_register_operand" "r")
8540                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8541    (clobber (reg:CC CC_REGNUM))]
8542   "TARGET_ARM
8543    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8544        != CCmode)"
8545   "#"
8546   "TARGET_ARM && reload_completed"
8547   [(set (match_dup 7)
8548         (compare
8549          (ior:SI
8550           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8551           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8552          (const_int 0)))
8553    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8554   "operands[7]
8555      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8556                                                   DOM_CC_X_OR_Y),
8557                     CC_REGNUM);"
8558   [(set_attr "conds" "clob")
8559    (set_attr "length" "16")])
8561 ; If the above pattern is followed by a CMP insn, then the compare is 
8562 ; redundant, since we can rework the conditional instruction that follows.
8563 (define_insn_and_split "*ior_scc_scc_cmp"
8564   [(set (match_operand 0 "dominant_cc_register" "")
8565         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8566                           [(match_operand:SI 1 "s_register_operand" "r")
8567                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8568                          (match_operator:SI 6 "arm_comparison_operator"
8569                           [(match_operand:SI 4 "s_register_operand" "r")
8570                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8571                  (const_int 0)))
8572    (set (match_operand:SI 7 "s_register_operand" "=r")
8573         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8574                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8575   "TARGET_ARM"
8576   "#"
8577   "TARGET_ARM && reload_completed"
8578   [(set (match_dup 0)
8579         (compare
8580          (ior:SI
8581           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8582           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8583          (const_int 0)))
8584    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8585   ""
8586   [(set_attr "conds" "set")
8587    (set_attr "length" "16")])
8589 (define_insn_and_split "*and_scc_scc"
8590   [(set (match_operand:SI 0 "s_register_operand" "=r")
8591         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8592                  [(match_operand:SI 1 "s_register_operand" "r")
8593                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8594                 (match_operator:SI 6 "arm_comparison_operator"
8595                  [(match_operand:SI 4 "s_register_operand" "r")
8596                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8597    (clobber (reg:CC CC_REGNUM))]
8598   "TARGET_ARM
8599    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8600        != CCmode)"
8601   "#"
8602   "TARGET_ARM && reload_completed
8603    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8604        != CCmode)"
8605   [(set (match_dup 7)
8606         (compare
8607          (and:SI
8608           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8609           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8610          (const_int 0)))
8611    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8612   "operands[7]
8613      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8614                                                   DOM_CC_X_AND_Y),
8615                     CC_REGNUM);"
8616   [(set_attr "conds" "clob")
8617    (set_attr "length" "16")])
8619 ; If the above pattern is followed by a CMP insn, then the compare is 
8620 ; redundant, since we can rework the conditional instruction that follows.
8621 (define_insn_and_split "*and_scc_scc_cmp"
8622   [(set (match_operand 0 "dominant_cc_register" "")
8623         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8624                           [(match_operand:SI 1 "s_register_operand" "r")
8625                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8626                          (match_operator:SI 6 "arm_comparison_operator"
8627                           [(match_operand:SI 4 "s_register_operand" "r")
8628                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8629                  (const_int 0)))
8630    (set (match_operand:SI 7 "s_register_operand" "=r")
8631         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8632                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8633   "TARGET_ARM"
8634   "#"
8635   "TARGET_ARM && reload_completed"
8636   [(set (match_dup 0)
8637         (compare
8638          (and:SI
8639           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8640           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8641          (const_int 0)))
8642    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8643   ""
8644   [(set_attr "conds" "set")
8645    (set_attr "length" "16")])
8647 ;; If there is no dominance in the comparison, then we can still save an
8648 ;; instruction in the AND case, since we can know that the second compare
8649 ;; need only zero the value if false (if true, then the value is already
8650 ;; correct).
8651 (define_insn_and_split "*and_scc_scc_nodom"
8652   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8653         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8654                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8655                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8656                 (match_operator:SI 6 "arm_comparison_operator"
8657                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8658                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8659    (clobber (reg:CC CC_REGNUM))]
8660   "TARGET_ARM
8661    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8662        == CCmode)"
8663   "#"
8664   "TARGET_ARM && reload_completed"
8665   [(parallel [(set (match_dup 0)
8666                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8667               (clobber (reg:CC CC_REGNUM))])
8668    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8669    (set (match_dup 0)
8670         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8671                          (match_dup 0)
8672                          (const_int 0)))]
8673   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8674                                               operands[4], operands[5]),
8675                               CC_REGNUM);
8676    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8677                                   operands[5]);"
8678   [(set_attr "conds" "clob")
8679    (set_attr "length" "20")])
8681 (define_split
8682   [(set (reg:CC_NOOV CC_REGNUM)
8683         (compare:CC_NOOV (ior:SI
8684                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8685                                   (const_int 1))
8686                           (match_operator:SI 1 "comparison_operator"
8687                            [(match_operand:SI 2 "s_register_operand" "")
8688                             (match_operand:SI 3 "arm_add_operand" "")]))
8689                          (const_int 0)))
8690    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8691   "TARGET_ARM"
8692   [(set (match_dup 4)
8693         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8694                 (match_dup 0)))
8695    (set (reg:CC_NOOV CC_REGNUM)
8696         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8697                          (const_int 0)))]
8698   "")
8700 (define_split
8701   [(set (reg:CC_NOOV CC_REGNUM)
8702         (compare:CC_NOOV (ior:SI
8703                           (match_operator:SI 1 "comparison_operator"
8704                            [(match_operand:SI 2 "s_register_operand" "")
8705                             (match_operand:SI 3 "arm_add_operand" "")])
8706                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8707                                   (const_int 1)))
8708                          (const_int 0)))
8709    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8710   "TARGET_ARM"
8711   [(set (match_dup 4)
8712         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8713                 (match_dup 0)))
8714    (set (reg:CC_NOOV CC_REGNUM)
8715         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8716                          (const_int 0)))]
8717   "")
8719 (define_insn "*negscc"
8720   [(set (match_operand:SI 0 "s_register_operand" "=r")
8721         (neg:SI (match_operator 3 "arm_comparison_operator"
8722                  [(match_operand:SI 1 "s_register_operand" "r")
8723                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8724    (clobber (reg:CC CC_REGNUM))]
8725   "TARGET_ARM"
8726   "*
8727   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8728     return \"mov\\t%0, %1, asr #31\";
8730   if (GET_CODE (operands[3]) == NE)
8731     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8733   if (GET_CODE (operands[3]) == GT)
8734     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8736   output_asm_insn (\"cmp\\t%1, %2\", operands);
8737   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8738   return \"mvn%d3\\t%0, #0\";
8739   "
8740   [(set_attr "conds" "clob")
8741    (set_attr "length" "12")]
8744 (define_insn "movcond"
8745   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8746         (if_then_else:SI
8747          (match_operator 5 "arm_comparison_operator"
8748           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8749            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8750          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8751          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8752    (clobber (reg:CC CC_REGNUM))]
8753   "TARGET_ARM"
8754   "*
8755   if (GET_CODE (operands[5]) == LT
8756       && (operands[4] == const0_rtx))
8757     {
8758       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8759         {
8760           if (operands[2] == const0_rtx)
8761             return \"and\\t%0, %1, %3, asr #31\";
8762           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8763         }
8764       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8765         {
8766           if (operands[1] == const0_rtx)
8767             return \"bic\\t%0, %2, %3, asr #31\";
8768           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8769         }
8770       /* The only case that falls through to here is when both ops 1 & 2
8771          are constants.  */
8772     }
8774   if (GET_CODE (operands[5]) == GE
8775       && (operands[4] == const0_rtx))
8776     {
8777       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8778         {
8779           if (operands[2] == const0_rtx)
8780             return \"bic\\t%0, %1, %3, asr #31\";
8781           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8782         }
8783       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8784         {
8785           if (operands[1] == const0_rtx)
8786             return \"and\\t%0, %2, %3, asr #31\";
8787           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8788         }
8789       /* The only case that falls through to here is when both ops 1 & 2
8790          are constants.  */
8791     }
8792   if (GET_CODE (operands[4]) == CONST_INT
8793       && !const_ok_for_arm (INTVAL (operands[4])))
8794     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8795   else
8796     output_asm_insn (\"cmp\\t%3, %4\", operands);
8797   if (which_alternative != 0)
8798     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8799   if (which_alternative != 1)
8800     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8801   return \"\";
8802   "
8803   [(set_attr "conds" "clob")
8804    (set_attr "length" "8,8,12")]
8807 (define_insn "*ifcompare_plus_move"
8808   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8809         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8810                           [(match_operand:SI 4 "s_register_operand" "r,r")
8811                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8812                          (plus:SI
8813                           (match_operand:SI 2 "s_register_operand" "r,r")
8814                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8815                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8816    (clobber (reg:CC CC_REGNUM))]
8817   "TARGET_ARM"
8818   "#"
8819   [(set_attr "conds" "clob")
8820    (set_attr "length" "8,12")]
8823 (define_insn "*if_plus_move"
8824   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8825         (if_then_else:SI
8826          (match_operator 4 "arm_comparison_operator"
8827           [(match_operand 5 "cc_register" "") (const_int 0)])
8828          (plus:SI
8829           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8830           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8831          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8832   "TARGET_ARM"
8833   "@
8834    add%d4\\t%0, %2, %3
8835    sub%d4\\t%0, %2, #%n3
8836    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8837    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8838   [(set_attr "conds" "use")
8839    (set_attr "length" "4,4,8,8")
8840    (set_attr "type" "*,*,*,*")]
8843 (define_insn "*ifcompare_move_plus"
8844   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8845         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8846                           [(match_operand:SI 4 "s_register_operand" "r,r")
8847                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8848                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8849                          (plus:SI
8850                           (match_operand:SI 2 "s_register_operand" "r,r")
8851                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8852    (clobber (reg:CC CC_REGNUM))]
8853   "TARGET_ARM"
8854   "#"
8855   [(set_attr "conds" "clob")
8856    (set_attr "length" "8,12")]
8859 (define_insn "*if_move_plus"
8860   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8861         (if_then_else:SI
8862          (match_operator 4 "arm_comparison_operator"
8863           [(match_operand 5 "cc_register" "") (const_int 0)])
8864          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8865          (plus:SI
8866           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8867           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8868   "TARGET_ARM"
8869   "@
8870    add%D4\\t%0, %2, %3
8871    sub%D4\\t%0, %2, #%n3
8872    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8873    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8874   [(set_attr "conds" "use")
8875    (set_attr "length" "4,4,8,8")
8876    (set_attr "type" "*,*,*,*")]
8879 (define_insn "*ifcompare_arith_arith"
8880   [(set (match_operand:SI 0 "s_register_operand" "=r")
8881         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8882                           [(match_operand:SI 5 "s_register_operand" "r")
8883                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8884                          (match_operator:SI 8 "shiftable_operator"
8885                           [(match_operand:SI 1 "s_register_operand" "r")
8886                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8887                          (match_operator:SI 7 "shiftable_operator"
8888                           [(match_operand:SI 3 "s_register_operand" "r")
8889                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8890    (clobber (reg:CC CC_REGNUM))]
8891   "TARGET_ARM"
8892   "#"
8893   [(set_attr "conds" "clob")
8894    (set_attr "length" "12")]
8897 (define_insn "*if_arith_arith"
8898   [(set (match_operand:SI 0 "s_register_operand" "=r")
8899         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8900                           [(match_operand 8 "cc_register" "") (const_int 0)])
8901                          (match_operator:SI 6 "shiftable_operator"
8902                           [(match_operand:SI 1 "s_register_operand" "r")
8903                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8904                          (match_operator:SI 7 "shiftable_operator"
8905                           [(match_operand:SI 3 "s_register_operand" "r")
8906                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8907   "TARGET_ARM"
8908   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8909   [(set_attr "conds" "use")
8910    (set_attr "length" "8")]
8913 (define_insn "*ifcompare_arith_move"
8914   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8915         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8916                           [(match_operand:SI 2 "s_register_operand" "r,r")
8917                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8918                          (match_operator:SI 7 "shiftable_operator"
8919                           [(match_operand:SI 4 "s_register_operand" "r,r")
8920                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8921                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8922    (clobber (reg:CC CC_REGNUM))]
8923   "TARGET_ARM"
8924   "*
8925   /* If we have an operation where (op x 0) is the identity operation and
8926      the conditional operator is LT or GE and we are comparing against zero and
8927      everything is in registers then we can do this in two instructions.  */
8928   if (operands[3] == const0_rtx
8929       && GET_CODE (operands[7]) != AND
8930       && GET_CODE (operands[5]) == REG
8931       && GET_CODE (operands[1]) == REG 
8932       && REGNO (operands[1]) == REGNO (operands[4])
8933       && REGNO (operands[4]) != REGNO (operands[0]))
8934     {
8935       if (GET_CODE (operands[6]) == LT)
8936         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8937       else if (GET_CODE (operands[6]) == GE)
8938         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8939     }
8940   if (GET_CODE (operands[3]) == CONST_INT
8941       && !const_ok_for_arm (INTVAL (operands[3])))
8942     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8943   else
8944     output_asm_insn (\"cmp\\t%2, %3\", operands);
8945   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8946   if (which_alternative != 0)
8947     return \"mov%D6\\t%0, %1\";
8948   return \"\";
8949   "
8950   [(set_attr "conds" "clob")
8951    (set_attr "length" "8,12")]
8954 (define_insn "*if_arith_move"
8955   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8956         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8957                           [(match_operand 6 "cc_register" "") (const_int 0)])
8958                          (match_operator:SI 5 "shiftable_operator"
8959                           [(match_operand:SI 2 "s_register_operand" "r,r")
8960                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8961                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8962   "TARGET_ARM"
8963   "@
8964    %I5%d4\\t%0, %2, %3
8965    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8966   [(set_attr "conds" "use")
8967    (set_attr "length" "4,8")
8968    (set_attr "type" "*,*")]
8971 (define_insn "*ifcompare_move_arith"
8972   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8973         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8974                           [(match_operand:SI 4 "s_register_operand" "r,r")
8975                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8976                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8977                          (match_operator:SI 7 "shiftable_operator"
8978                           [(match_operand:SI 2 "s_register_operand" "r,r")
8979                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8980    (clobber (reg:CC CC_REGNUM))]
8981   "TARGET_ARM"
8982   "*
8983   /* If we have an operation where (op x 0) is the identity operation and
8984      the conditional operator is LT or GE and we are comparing against zero and
8985      everything is in registers then we can do this in two instructions */
8986   if (operands[5] == const0_rtx
8987       && GET_CODE (operands[7]) != AND
8988       && GET_CODE (operands[3]) == REG
8989       && GET_CODE (operands[1]) == REG 
8990       && REGNO (operands[1]) == REGNO (operands[2])
8991       && REGNO (operands[2]) != REGNO (operands[0]))
8992     {
8993       if (GET_CODE (operands[6]) == GE)
8994         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8995       else if (GET_CODE (operands[6]) == LT)
8996         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8997     }
8999   if (GET_CODE (operands[5]) == CONST_INT
9000       && !const_ok_for_arm (INTVAL (operands[5])))
9001     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
9002   else
9003     output_asm_insn (\"cmp\\t%4, %5\", operands);
9005   if (which_alternative != 0)
9006     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
9007   return \"%I7%D6\\t%0, %2, %3\";
9008   "
9009   [(set_attr "conds" "clob")
9010    (set_attr "length" "8,12")]
9013 (define_insn "*if_move_arith"
9014   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9015         (if_then_else:SI
9016          (match_operator 4 "arm_comparison_operator"
9017           [(match_operand 6 "cc_register" "") (const_int 0)])
9018          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9019          (match_operator:SI 5 "shiftable_operator"
9020           [(match_operand:SI 2 "s_register_operand" "r,r")
9021            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
9022   "TARGET_ARM"
9023   "@
9024    %I5%D4\\t%0, %2, %3
9025    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
9026   [(set_attr "conds" "use")
9027    (set_attr "length" "4,8")
9028    (set_attr "type" "*,*")]
9031 (define_insn "*ifcompare_move_not"
9032   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9033         (if_then_else:SI
9034          (match_operator 5 "arm_comparison_operator"
9035           [(match_operand:SI 3 "s_register_operand" "r,r")
9036            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9037          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9038          (not:SI
9039           (match_operand:SI 2 "s_register_operand" "r,r"))))
9040    (clobber (reg:CC CC_REGNUM))]
9041   "TARGET_ARM"
9042   "#"
9043   [(set_attr "conds" "clob")
9044    (set_attr "length" "8,12")]
9047 (define_insn "*if_move_not"
9048   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9049         (if_then_else:SI
9050          (match_operator 4 "arm_comparison_operator"
9051           [(match_operand 3 "cc_register" "") (const_int 0)])
9052          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9053          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9054   "TARGET_ARM"
9055   "@
9056    mvn%D4\\t%0, %2
9057    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
9058    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
9059   [(set_attr "conds" "use")
9060    (set_attr "length" "4,8,8")]
9063 (define_insn "*ifcompare_not_move"
9064   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9065         (if_then_else:SI 
9066          (match_operator 5 "arm_comparison_operator"
9067           [(match_operand:SI 3 "s_register_operand" "r,r")
9068            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9069          (not:SI
9070           (match_operand:SI 2 "s_register_operand" "r,r"))
9071          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9072    (clobber (reg:CC CC_REGNUM))]
9073   "TARGET_ARM"
9074   "#"
9075   [(set_attr "conds" "clob")
9076    (set_attr "length" "8,12")]
9079 (define_insn "*if_not_move"
9080   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9081         (if_then_else:SI
9082          (match_operator 4 "arm_comparison_operator"
9083           [(match_operand 3 "cc_register" "") (const_int 0)])
9084          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9085          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9086   "TARGET_ARM"
9087   "@
9088    mvn%d4\\t%0, %2
9089    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
9090    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
9091   [(set_attr "conds" "use")
9092    (set_attr "length" "4,8,8")]
9095 (define_insn "*ifcompare_shift_move"
9096   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9097         (if_then_else:SI
9098          (match_operator 6 "arm_comparison_operator"
9099           [(match_operand:SI 4 "s_register_operand" "r,r")
9100            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9101          (match_operator:SI 7 "shift_operator"
9102           [(match_operand:SI 2 "s_register_operand" "r,r")
9103            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9104          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9105    (clobber (reg:CC CC_REGNUM))]
9106   "TARGET_ARM"
9107   "#"
9108   [(set_attr "conds" "clob")
9109    (set_attr "length" "8,12")]
9112 (define_insn "*if_shift_move"
9113   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9114         (if_then_else:SI
9115          (match_operator 5 "arm_comparison_operator"
9116           [(match_operand 6 "cc_register" "") (const_int 0)])
9117          (match_operator:SI 4 "shift_operator"
9118           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9119            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9120          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9121   "TARGET_ARM"
9122   "@
9123    mov%d5\\t%0, %2%S4
9124    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9125    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9126   [(set_attr "conds" "use")
9127    (set_attr "shift" "2")
9128    (set_attr "length" "4,8,8")
9129    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9130                       (const_string "alu_shift")
9131                       (const_string "alu_shift_reg")))]
9134 (define_insn "*ifcompare_move_shift"
9135   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9136         (if_then_else:SI
9137          (match_operator 6 "arm_comparison_operator"
9138           [(match_operand:SI 4 "s_register_operand" "r,r")
9139            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9140          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9141          (match_operator:SI 7 "shift_operator"
9142           [(match_operand:SI 2 "s_register_operand" "r,r")
9143            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9144    (clobber (reg:CC CC_REGNUM))]
9145   "TARGET_ARM"
9146   "#"
9147   [(set_attr "conds" "clob")
9148    (set_attr "length" "8,12")]
9151 (define_insn "*if_move_shift"
9152   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9153         (if_then_else:SI
9154          (match_operator 5 "arm_comparison_operator"
9155           [(match_operand 6 "cc_register" "") (const_int 0)])
9156          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9157          (match_operator:SI 4 "shift_operator"
9158           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9159            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9160   "TARGET_ARM"
9161   "@
9162    mov%D5\\t%0, %2%S4
9163    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9164    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9165   [(set_attr "conds" "use")
9166    (set_attr "shift" "2")
9167    (set_attr "length" "4,8,8")
9168    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9169                       (const_string "alu_shift")
9170                       (const_string "alu_shift_reg")))]
9173 (define_insn "*ifcompare_shift_shift"
9174   [(set (match_operand:SI 0 "s_register_operand" "=r")
9175         (if_then_else:SI
9176          (match_operator 7 "arm_comparison_operator"
9177           [(match_operand:SI 5 "s_register_operand" "r")
9178            (match_operand:SI 6 "arm_add_operand" "rIL")])
9179          (match_operator:SI 8 "shift_operator"
9180           [(match_operand:SI 1 "s_register_operand" "r")
9181            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9182          (match_operator:SI 9 "shift_operator"
9183           [(match_operand:SI 3 "s_register_operand" "r")
9184            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9185    (clobber (reg:CC CC_REGNUM))]
9186   "TARGET_ARM"
9187   "#"
9188   [(set_attr "conds" "clob")
9189    (set_attr "length" "12")]
9192 (define_insn "*if_shift_shift"
9193   [(set (match_operand:SI 0 "s_register_operand" "=r")
9194         (if_then_else:SI
9195          (match_operator 5 "arm_comparison_operator"
9196           [(match_operand 8 "cc_register" "") (const_int 0)])
9197          (match_operator:SI 6 "shift_operator"
9198           [(match_operand:SI 1 "s_register_operand" "r")
9199            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9200          (match_operator:SI 7 "shift_operator"
9201           [(match_operand:SI 3 "s_register_operand" "r")
9202            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9203   "TARGET_ARM"
9204   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9205   [(set_attr "conds" "use")
9206    (set_attr "shift" "1")
9207    (set_attr "length" "8")
9208    (set (attr "type") (if_then_else
9209                         (and (match_operand 2 "const_int_operand" "")
9210                              (match_operand 4 "const_int_operand" ""))
9211                       (const_string "alu_shift")
9212                       (const_string "alu_shift_reg")))]
9215 (define_insn "*ifcompare_not_arith"
9216   [(set (match_operand:SI 0 "s_register_operand" "=r")
9217         (if_then_else:SI
9218          (match_operator 6 "arm_comparison_operator"
9219           [(match_operand:SI 4 "s_register_operand" "r")
9220            (match_operand:SI 5 "arm_add_operand" "rIL")])
9221          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9222          (match_operator:SI 7 "shiftable_operator"
9223           [(match_operand:SI 2 "s_register_operand" "r")
9224            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9225    (clobber (reg:CC CC_REGNUM))]
9226   "TARGET_ARM"
9227   "#"
9228   [(set_attr "conds" "clob")
9229    (set_attr "length" "12")]
9232 (define_insn "*if_not_arith"
9233   [(set (match_operand:SI 0 "s_register_operand" "=r")
9234         (if_then_else:SI
9235          (match_operator 5 "arm_comparison_operator"
9236           [(match_operand 4 "cc_register" "") (const_int 0)])
9237          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9238          (match_operator:SI 6 "shiftable_operator"
9239           [(match_operand:SI 2 "s_register_operand" "r")
9240            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9241   "TARGET_ARM"
9242   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9243   [(set_attr "conds" "use")
9244    (set_attr "length" "8")]
9247 (define_insn "*ifcompare_arith_not"
9248   [(set (match_operand:SI 0 "s_register_operand" "=r")
9249         (if_then_else:SI
9250          (match_operator 6 "arm_comparison_operator"
9251           [(match_operand:SI 4 "s_register_operand" "r")
9252            (match_operand:SI 5 "arm_add_operand" "rIL")])
9253          (match_operator:SI 7 "shiftable_operator"
9254           [(match_operand:SI 2 "s_register_operand" "r")
9255            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9256          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9257    (clobber (reg:CC CC_REGNUM))]
9258   "TARGET_ARM"
9259   "#"
9260   [(set_attr "conds" "clob")
9261    (set_attr "length" "12")]
9264 (define_insn "*if_arith_not"
9265   [(set (match_operand:SI 0 "s_register_operand" "=r")
9266         (if_then_else:SI
9267          (match_operator 5 "arm_comparison_operator"
9268           [(match_operand 4 "cc_register" "") (const_int 0)])
9269          (match_operator:SI 6 "shiftable_operator"
9270           [(match_operand:SI 2 "s_register_operand" "r")
9271            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9272          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9273   "TARGET_ARM"
9274   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9275   [(set_attr "conds" "use")
9276    (set_attr "length" "8")]
9279 (define_insn "*ifcompare_neg_move"
9280   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9281         (if_then_else:SI
9282          (match_operator 5 "arm_comparison_operator"
9283           [(match_operand:SI 3 "s_register_operand" "r,r")
9284            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9285          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9286          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9287    (clobber (reg:CC CC_REGNUM))]
9288   "TARGET_ARM"
9289   "#"
9290   [(set_attr "conds" "clob")
9291    (set_attr "length" "8,12")]
9294 (define_insn "*if_neg_move"
9295   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9296         (if_then_else:SI
9297          (match_operator 4 "arm_comparison_operator"
9298           [(match_operand 3 "cc_register" "") (const_int 0)])
9299          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9300          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9301   "TARGET_ARM"
9302   "@
9303    rsb%d4\\t%0, %2, #0
9304    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9305    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9306   [(set_attr "conds" "use")
9307    (set_attr "length" "4,8,8")]
9310 (define_insn "*ifcompare_move_neg"
9311   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9312         (if_then_else:SI
9313          (match_operator 5 "arm_comparison_operator"
9314           [(match_operand:SI 3 "s_register_operand" "r,r")
9315            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9316          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9317          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9318    (clobber (reg:CC CC_REGNUM))]
9319   "TARGET_ARM"
9320   "#"
9321   [(set_attr "conds" "clob")
9322    (set_attr "length" "8,12")]
9325 (define_insn "*if_move_neg"
9326   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9327         (if_then_else:SI
9328          (match_operator 4 "arm_comparison_operator"
9329           [(match_operand 3 "cc_register" "") (const_int 0)])
9330          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9331          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9332   "TARGET_ARM"
9333   "@
9334    rsb%D4\\t%0, %2, #0
9335    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9336    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9337   [(set_attr "conds" "use")
9338    (set_attr "length" "4,8,8")]
9341 (define_insn "*arith_adjacentmem"
9342   [(set (match_operand:SI 0 "s_register_operand" "=r")
9343         (match_operator:SI 1 "shiftable_operator"
9344          [(match_operand:SI 2 "memory_operand" "m")
9345           (match_operand:SI 3 "memory_operand" "m")]))
9346    (clobber (match_scratch:SI 4 "=r"))]
9347   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9348   "*
9349   {
9350     rtx ldm[3];
9351     rtx arith[4];
9352     rtx base_reg;
9353     HOST_WIDE_INT val1 = 0, val2 = 0;
9355     if (REGNO (operands[0]) > REGNO (operands[4]))
9356       {
9357         ldm[1] = operands[4];
9358         ldm[2] = operands[0];
9359       }
9360     else
9361       {
9362         ldm[1] = operands[0];
9363         ldm[2] = operands[4];
9364       }
9366     base_reg = XEXP (operands[2], 0);
9368     if (!REG_P (base_reg))
9369       {
9370         val1 = INTVAL (XEXP (base_reg, 1));
9371         base_reg = XEXP (base_reg, 0);
9372       }
9374     if (!REG_P (XEXP (operands[3], 0)))
9375       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9377     arith[0] = operands[0];
9378     arith[3] = operands[1];
9380     if (val1 < val2)
9381       {
9382         arith[1] = ldm[1];
9383         arith[2] = ldm[2];
9384       }
9385     else
9386       {
9387         arith[1] = ldm[2];
9388         arith[2] = ldm[1];
9389       }
9391     ldm[0] = base_reg;
9392     if (val1 !=0 && val2 != 0)
9393       {
9394         rtx ops[3];
9396         if (val1 == 4 || val2 == 4)
9397           /* Other val must be 8, since we know they are adjacent and neither
9398              is zero.  */
9399           output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
9400         else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
9401           {
9402             ldm[0] = ops[0] = operands[4];
9403             ops[1] = base_reg;
9404             ops[2] = GEN_INT (val1);
9405             output_add_immediate (ops);
9406             if (val1 < val2)
9407               output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9408             else
9409               output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9410           }
9411         else
9412           {
9413             /* Offset is out of range for a single add, so use two ldr.  */
9414             ops[0] = ldm[1];
9415             ops[1] = base_reg;
9416             ops[2] = GEN_INT (val1);
9417             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
9418             ops[0] = ldm[2];
9419             ops[2] = GEN_INT (val2);
9420             output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
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")