2005-03-29 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / config / arm / arm.md
blobf25846675eeed696dbf5e15d119ad15fde97124c
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
29 ;; Constants
31 ;; Register numbers
32 (define_constants
33   [(R0_REGNUM        0)         ; First CORE register
34    (IP_REGNUM       12)         ; Scratch register
35    (SP_REGNUM       13)         ; Stack pointer
36    (LR_REGNUM       14)         ; Return address register
37    (PC_REGNUM       15)         ; Program counter
38    (CC_REGNUM       24)         ; Condition code pseudo register
39    (LAST_ARM_REGNUM 15)         ;
40    (FPA_F0_REGNUM   16)         ; FIRST_FPA_REGNUM
41    (FPA_F7_REGNUM   23)         ; LAST_FPA_REGNUM
42   ]
44 ;; 3rd operand to select_dominance_cc_mode
45 (define_constants
46   [(DOM_CC_X_AND_Y  0)
47    (DOM_CC_NX_OR_Y  1)
48    (DOM_CC_X_OR_Y   2)
49   ]
52 ;; UNSPEC Usage:
53 ;; Note: sin and cos are no-longer used.
55 (define_constants
56   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
60                         ;   operand 0 is the result,
61                         ;   operand 1 the parameter.
62    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
63                         ;   operand 0 is the first register,
64                         ;   subsequent registers are in parallel (use ...)
65                         ;   expressions.
66    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
67                         ;   usage, that is, we will add the pic_register
68                         ;   value to it before trying to dereference it.
69    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
70                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
71                         ;   described by the RTL but must be wrapped to
72                         ;   prevent combine from trying to rip it apart.
73    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
74                         ;   being scheduled before the stack adjustment insn.
75    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
76                         ; this unspec is used to prevent the deletion of
77                         ; instructions setting registers for EH handling
78                         ; and stack frame generation.  Operand 0 is the
79                         ; register to "use".
80    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
81    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
82    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
83    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
84    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
85    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
86    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
87    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
88    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
89    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
90    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
91    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
92    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93   ]
96 ;; UNSPEC_VOLATILE Usage:
98 (define_constants
99   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
100                         ;   insn in the code.
101    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
102                         ;   instruction epilogue sequence that isn't expanded
103                         ;   into normal RTL.  Used for both normal and sibcall
104                         ;   epilogues.
105    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
106                         ;   for inlined constants.
107    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
108                         ;   table.
109    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
110                         ;   an 8-bit object.
111    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
112                         ;   a 16-bit object.
113    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
114                         ;   a 32-bit object.
115    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
116                         ;   a 64-bit object.
117    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
118    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
119    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
120    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
121    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
122    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
123    (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
124                          ; handling.
125   ]
128 ;;---------------------------------------------------------------------------
129 ;; Attributes
131 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
132 ; generating ARM code.  This is used to control the length of some insn
133 ; patterns that share the same RTL in both ARM and Thumb code.
134 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
140 ; IS_XSCALE is set to 'yes' when compiling for XScale.
141 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 ;; Operand number of an input operand that is shifted.  Zero if the
144 ;; given instruction does not shift one of its input operands.
145 (define_attr "shift" "" (const_int 0))
147 ; Floating Point Unit.  If we only have floating point emulation, then there
148 ; is no point in scheduling the floating point insns.  (Well, for best
149 ; performance we should try and group them together).
150 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
151   (const (symbol_ref "arm_fpu_attr")))
153 ; LENGTH of an instruction (in bytes)
154 (define_attr "length" "" (const_int 4))
156 ; POOL_RANGE is how far away from a constant pool entry that this insn
157 ; can be placed.  If the distance is zero, then this insn will never
158 ; reference the pool.
159 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
160 ; before its address.
161 (define_attr "pool_range" "" (const_int 0))
162 (define_attr "neg_pool_range" "" (const_int 0))
164 ; An assembler sequence may clobber the condition codes without us knowing.
165 ; If such an insn references the pool, then we have no way of knowing how,
166 ; so use the most conservative value for pool_range.
167 (define_asm_attributes
168  [(set_attr "conds" "clob")
169   (set_attr "length" "4")
170   (set_attr "pool_range" "250")])
172 ;; The instruction used to implement a particular pattern.  This
173 ;; information is used by pipeline descriptions to provide accurate
174 ;; scheduling information.
176 (define_attr "insn"
177         "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
178         (const_string "other"))
180 ; TYPE attribute is used to detect floating point instructions which, if
181 ; running on a co-processor can run in parallel with other, basic instructions
182 ; If write-buffer scheduling is enabled then it can also be used in the
183 ; scheduling of writes.
185 ; Classification of each insn
186 ; alu           any alu  instruction that doesn't hit memory or fp
187 ;               regs or have a shifted source operand
188 ; alu_shift     any data instruction that doesn't hit memory or fp
189 ;               regs, but has a source operand shifted by a constant
190 ; alu_shift_reg any data instruction that doesn't hit memory or fp
191 ;               regs, but has a source operand shifted by a register value
192 ; mult          a multiply instruction
193 ; block         blockage insn, this blocks all functional units
194 ; float         a floating point arithmetic operation (subject to expansion)
195 ; fdivd         DFmode floating point division
196 ; fdivs         SFmode floating point division
197 ; fmul          Floating point multiply
198 ; ffmul         Fast floating point multiply
199 ; farith        Floating point arithmetic (4 cycle)
200 ; ffarith       Fast floating point arithmetic (2 cycle)
201 ; float_em      a floating point arithmetic operation that is normally emulated
202 ;               even on a machine with an fpa.
203 ; f_load        a floating point load from memory
204 ; f_store       a floating point store to memory
205 ; f_mem_r       a transfer of a floating point register to a real reg via mem
206 ; r_mem_f       the reverse of f_mem_r
207 ; f_2_r         fast transfer float to arm (no memory needed)
208 ; r_2_f         fast transfer arm to float
209 ; branch        a branch
210 ; call          a subroutine call
211 ; load_byte     load byte(s) from memory to arm registers
212 ; load1         load 1 word from memory to arm registers
213 ; load2         load 2 words from memory to arm registers
214 ; load3         load 3 words from memory to arm registers
215 ; load4         load 4 words from memory to arm registers
216 ; store         store 1 word to memory from arm registers
217 ; store2        store 2 words
218 ; store3        store 3 words
219 ; store4        store 4 (or more) words
220 ;  Additions for Cirrus Maverick co-processor:
221 ; mav_farith    Floating point arithmetic (4 cycle)
222 ; mav_dmult     Double multiplies (7 cycle)
224 (define_attr "type"
225         "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult" 
226         (if_then_else 
227          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
228          (const_string "mult")
229          (const_string "alu")))
231 ; Load scheduling, set from the arm_ld_sched variable
232 ; initialized by arm_override_options() 
233 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
235 ; condition codes: this one is used by final_prescan_insn to speed up
236 ; conditionalizing instructions.  It saves having to scan the rtl to see if
237 ; it uses or alters the condition codes.
239 ; USE means that the condition codes are used by the insn in the process of
240 ;   outputting code, this means (at present) that we can't use the insn in
241 ;   inlined branches
243 ; SET means that the purpose of the insn is to set the condition codes in a
244 ;   well defined manner.
246 ; CLOB means that the condition codes are altered in an undefined manner, if
247 ;   they are altered at all
249 ; JUMP_CLOB is used when the condition cannot be represented by a single
250 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
252 ; NOCOND means that the condition codes are neither altered nor affect the
253 ;   output of this insn
255 (define_attr "conds" "use,set,clob,jump_clob,nocond"
256         (if_then_else (eq_attr "type" "call")
257          (const_string "clob")
258          (const_string "nocond")))
260 ; Predicable means that the insn can be conditionally executed based on
261 ; an automatically added predicate (additional patterns are generated by 
262 ; gen...).  We default to 'no' because no Thumb patterns match this rule
263 ; and not all ARM patterns do.
264 (define_attr "predicable" "no,yes" (const_string "no"))
266 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
267 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
268 ; suffer blockages enough to warrant modelling this (and it can adversely
269 ; affect the schedule).
270 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
272 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
273 ; to stall the processor.  Used with model_wbuf above.
274 (define_attr "write_conflict" "no,yes"
275   (if_then_else (eq_attr "type"
276                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
277                 (const_string "yes")
278                 (const_string "no")))
280 ; Classify the insns into those that take one cycle and those that take more
281 ; than one on the main cpu execution unit.
282 (define_attr "core_cycles" "single,multi"
283   (if_then_else (eq_attr "type"
284                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
285                 (const_string "single")
286                 (const_string "multi")))
288 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
289 ;; distant label.  Only applicable to Thumb code.
290 (define_attr "far_jump" "yes,no" (const_string "no"))
292 (include "predicates.md")
294 ;;---------------------------------------------------------------------------
295 ;; Pipeline descriptions
297 ;; Processor type.  This is created automatically from arm-cores.def.
298 (include "arm-tune.md")
300 ;; True if the generic scheduling description should be used.
302 (define_attr "generic_sched" "yes,no"
303   (const (if_then_else 
304           (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
305           (const_string "no")
306           (const_string "yes"))))
308 (include "arm-generic.md")
309 (include "arm926ejs.md")
310 (include "arm1026ejs.md")
311 (include "arm1136jfs.md")
314 ;;---------------------------------------------------------------------------
315 ;; Insn patterns
317 ;; Addition insns.
319 ;; Note: For DImode insns, there is normally no reason why operands should
320 ;; not be in the same register, what we don't want is for something being
321 ;; written to partially overlap something that is an input.
322 ;; Cirrus 64bit additions should not be split because we have a native
323 ;; 64bit addition instructions.
325 (define_expand "adddi3"
326  [(parallel
327    [(set (match_operand:DI           0 "s_register_operand" "")
328           (plus:DI (match_operand:DI 1 "s_register_operand" "")
329                    (match_operand:DI 2 "s_register_operand" "")))
330     (clobber (reg:CC CC_REGNUM))])]
331   "TARGET_EITHER"
332   "
333   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
334     {
335       if (!cirrus_fp_register (operands[0], DImode))
336         operands[0] = force_reg (DImode, operands[0]);
337       if (!cirrus_fp_register (operands[1], DImode))
338         operands[1] = force_reg (DImode, operands[1]);
339       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
340       DONE;
341     }
343   if (TARGET_THUMB)
344     {
345       if (GET_CODE (operands[1]) != REG)
346         operands[1] = force_reg (SImode, operands[1]);
347       if (GET_CODE (operands[2]) != REG)
348         operands[2] = force_reg (SImode, operands[2]);
349      }
350   "
353 (define_insn "*thumb_adddi3"
354   [(set (match_operand:DI          0 "register_operand" "=l")
355         (plus:DI (match_operand:DI 1 "register_operand" "%0")
356                  (match_operand:DI 2 "register_operand" "l")))
357    (clobber (reg:CC CC_REGNUM))
358   ]
359   "TARGET_THUMB"
360   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
361   [(set_attr "length" "4")]
364 (define_insn_and_split "*arm_adddi3"
365   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
366         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
367                  (match_operand:DI 2 "s_register_operand" "r,  0")))
368    (clobber (reg:CC CC_REGNUM))]
369   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
370   "#"
371   "TARGET_ARM && reload_completed"
372   [(parallel [(set (reg:CC_C CC_REGNUM)
373                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
374                                  (match_dup 1)))
375               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
376    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
377                                (plus:SI (match_dup 4) (match_dup 5))))]
378   "
379   {
380     operands[3] = gen_highpart (SImode, operands[0]);
381     operands[0] = gen_lowpart (SImode, operands[0]);
382     operands[4] = gen_highpart (SImode, operands[1]);
383     operands[1] = gen_lowpart (SImode, operands[1]);
384     operands[5] = gen_highpart (SImode, operands[2]);
385     operands[2] = gen_lowpart (SImode, operands[2]);
386   }"
387   [(set_attr "conds" "clob")
388    (set_attr "length" "8")]
391 (define_insn_and_split "*adddi_sesidi_di"
392   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
393         (plus:DI (sign_extend:DI
394                   (match_operand:SI 2 "s_register_operand" "r,r"))
395                  (match_operand:DI 1 "s_register_operand" "r,0")))
396    (clobber (reg:CC CC_REGNUM))]
397   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
398   "#"
399   "TARGET_ARM && reload_completed"
400   [(parallel [(set (reg:CC_C CC_REGNUM)
401                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
402                                  (match_dup 1)))
403               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
404    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
405                                (plus:SI (ashiftrt:SI (match_dup 2)
406                                                      (const_int 31))
407                                         (match_dup 4))))]
408   "
409   {
410     operands[3] = gen_highpart (SImode, operands[0]);
411     operands[0] = gen_lowpart (SImode, operands[0]);
412     operands[4] = gen_highpart (SImode, operands[1]);
413     operands[1] = gen_lowpart (SImode, operands[1]);
414     operands[2] = gen_lowpart (SImode, operands[2]);
415   }"
416   [(set_attr "conds" "clob")
417    (set_attr "length" "8")]
420 (define_insn_and_split "*adddi_zesidi_di"
421   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
422         (plus:DI (zero_extend:DI
423                   (match_operand:SI 2 "s_register_operand" "r,r"))
424                  (match_operand:DI 1 "s_register_operand" "r,0")))
425    (clobber (reg:CC CC_REGNUM))]
426   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
427   "#"
428   "TARGET_ARM && reload_completed"
429   [(parallel [(set (reg:CC_C CC_REGNUM)
430                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
431                                  (match_dup 1)))
432               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
433    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
434                                (plus:SI (match_dup 4) (const_int 0))))]
435   "
436   {
437     operands[3] = gen_highpart (SImode, operands[0]);
438     operands[0] = gen_lowpart (SImode, operands[0]);
439     operands[4] = gen_highpart (SImode, operands[1]);
440     operands[1] = gen_lowpart (SImode, operands[1]);
441     operands[2] = gen_lowpart (SImode, operands[2]);
442   }"
443   [(set_attr "conds" "clob")
444    (set_attr "length" "8")]
447 (define_expand "addsi3"
448   [(set (match_operand:SI          0 "s_register_operand" "")
449         (plus:SI (match_operand:SI 1 "s_register_operand" "")
450                  (match_operand:SI 2 "reg_or_int_operand" "")))]
451   "TARGET_EITHER"
452   "
453   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
454     {
455       arm_split_constant (PLUS, SImode, NULL_RTX,
456                           INTVAL (operands[2]), operands[0], operands[1],
457                           optimize && !no_new_pseudos);
458       DONE;
459     }
460   "
463 ; If there is a scratch available, this will be faster than synthesizing the
464 ; addition.
465 (define_peephole2
466   [(match_scratch:SI 3 "r")
467    (set (match_operand:SI          0 "arm_general_register_operand" "")
468         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
469                  (match_operand:SI 2 "const_int_operand"  "")))]
470   "TARGET_ARM &&
471    !(const_ok_for_arm (INTVAL (operands[2]))
472      || const_ok_for_arm (-INTVAL (operands[2])))
473     && const_ok_for_arm (~INTVAL (operands[2]))"
474   [(set (match_dup 3) (match_dup 2))
475    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
476   ""
479 (define_insn_and_split "*arm_addsi3"
480   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
481         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
482                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
483   "TARGET_ARM"
484   "@
485    add%?\\t%0, %1, %2
486    sub%?\\t%0, %1, #%n2
487    #"
488   "TARGET_ARM &&
489    GET_CODE (operands[2]) == CONST_INT
490    && !(const_ok_for_arm (INTVAL (operands[2]))
491         || const_ok_for_arm (-INTVAL (operands[2])))"
492   [(clobber (const_int 0))]
493   "
494   arm_split_constant (PLUS, SImode, curr_insn,
495                       INTVAL (operands[2]), operands[0],
496                       operands[1], 0);
497   DONE;
498   "
499   [(set_attr "length" "4,4,16")
500    (set_attr "predicable" "yes")]
503 ;; Register group 'k' is a single register group containing only the stack
504 ;; register.  Trying to reload it will always fail catastrophically,
505 ;; so never allow those alternatives to match if reloading is needed.
507 (define_insn "*thumb_addsi3"
508   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
509         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
510                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
511   "TARGET_THUMB"
512   "*
513    static const char * const asms[] = 
514    {
515      \"add\\t%0, %0, %2\",
516      \"sub\\t%0, %0, #%n2\",
517      \"add\\t%0, %1, %2\",
518      \"add\\t%0, %0, %2\",
519      \"add\\t%0, %0, %2\",
520      \"add\\t%0, %1, %2\",
521      \"add\\t%0, %1, %2\"
522    };
523    if ((which_alternative == 2 || which_alternative == 6)
524        && GET_CODE (operands[2]) == CONST_INT
525        && INTVAL (operands[2]) < 0)
526      return \"sub\\t%0, %1, #%n2\";
527    return asms[which_alternative];
528   "
529   [(set_attr "length" "2")]
532 ;; Reloading and elimination of the frame pointer can
533 ;; sometimes cause this optimization to be missed.
534 (define_peephole2
535   [(set (match_operand:SI 0 "arm_general_register_operand" "")
536         (match_operand:SI 1 "const_int_operand" ""))
537    (set (match_dup 0)
538         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
539   "TARGET_THUMB
540    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
541    && (INTVAL (operands[1]) & 3) == 0"
542   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
543   ""
546 (define_insn "*addsi3_compare0"
547   [(set (reg:CC_NOOV CC_REGNUM)
548         (compare:CC_NOOV
549          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
550                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
551          (const_int 0)))
552    (set (match_operand:SI 0 "s_register_operand" "=r,r")
553         (plus:SI (match_dup 1) (match_dup 2)))]
554   "TARGET_ARM"
555   "@
556    add%?s\\t%0, %1, %2
557    sub%?s\\t%0, %1, #%n2"
558   [(set_attr "conds" "set")]
561 (define_insn "*addsi3_compare0_scratch"
562   [(set (reg:CC_NOOV CC_REGNUM)
563         (compare:CC_NOOV
564          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
565                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
566          (const_int 0)))]
567   "TARGET_ARM"
568   "@
569    cmn%?\\t%0, %1
570    cmp%?\\t%0, #%n1"
571   [(set_attr "conds" "set")]
574 ;; These patterns are the same ones as the two regular addsi3_compare0
575 ;; patterns, except we write them slightly different - the combiner
576 ;; tends to generate them this way.
577 (define_insn "*addsi3_compare0_for_combiner"
578   [(set (reg:CC CC_REGNUM)
579         (compare:CC
580          (match_operand:SI 1 "s_register_operand" "r,r")
581          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
582    (set (match_operand:SI 0 "s_register_operand" "=r,r")
583         (plus:SI (match_dup 1) (match_dup 2)))]
584   "TARGET_ARM"
585   "@
586    add%?s\\t%0, %1, %2
587    sub%?s\\t%0, %1, #%n2"
588   [(set_attr "conds" "set")]
591 (define_insn "*addsi3_compare0_scratch_for_combiner"
592   [(set (reg:CC CC_REGNUM)
593         (compare:CC
594          (match_operand:SI 0 "s_register_operand" "r,r")
595          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
596   "TARGET_ARM"
597   "@
598    cmn%?\\t%0, %1
599    cmp%?\\t%0, #%n1"
600   [(set_attr "conds" "set")]
603 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
604 ;; addend is a constant.
605 (define_insn "*cmpsi2_addneg"
606   [(set (reg:CC CC_REGNUM)
607         (compare:CC
608          (match_operand:SI 1 "s_register_operand" "r,r")
609          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
610    (set (match_operand:SI 0 "s_register_operand" "=r,r")
611         (plus:SI (match_dup 1)
612                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
613   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
614   "@
615    sub%?s\\t%0, %1, %2
616    add%?s\\t%0, %1, #%n2"
617   [(set_attr "conds" "set")]
620 ;; Convert the sequence
621 ;;  sub  rd, rn, #1
622 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
623 ;;  bne  dest
624 ;; into
625 ;;  subs rd, rn, #1
626 ;;  bcs  dest   ((unsigned)rn >= 1)
627 ;; similarly for the beq variant using bcc.
628 ;; This is a common looping idiom (while (n--))
629 (define_peephole2
630   [(set (match_operand:SI 0 "arm_general_register_operand" "")
631         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
632                  (const_int -1)))
633    (set (match_operand 2 "cc_register" "")
634         (compare (match_dup 0) (const_int -1)))
635    (set (pc)
636         (if_then_else (match_operator 3 "equality_operator"
637                        [(match_dup 2) (const_int 0)])
638                       (match_operand 4 "" "")
639                       (match_operand 5 "" "")))]
640   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
641   [(parallel[
642     (set (match_dup 2)
643          (compare:CC
644           (match_dup 1) (const_int 1)))
645     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
646    (set (pc)
647         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
648                       (match_dup 4)
649                       (match_dup 5)))]
650   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
651    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
652                                   ? GEU : LTU),
653                                  VOIDmode, 
654                                  operands[2], const0_rtx);"
657 ;; The next four insns work because they compare the result with one of
658 ;; the operands, and we know that the use of the condition code is
659 ;; either GEU or LTU, so we can use the carry flag from the addition
660 ;; instead of doing the compare a second time.
661 (define_insn "*addsi3_compare_op1"
662   [(set (reg:CC_C CC_REGNUM)
663         (compare:CC_C
664          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
665                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
666          (match_dup 1)))
667    (set (match_operand:SI 0 "s_register_operand" "=r,r")
668         (plus:SI (match_dup 1) (match_dup 2)))]
669   "TARGET_ARM"
670   "@
671    add%?s\\t%0, %1, %2
672    sub%?s\\t%0, %1, #%n2"
673   [(set_attr "conds" "set")]
676 (define_insn "*addsi3_compare_op2"
677   [(set (reg:CC_C CC_REGNUM)
678         (compare:CC_C
679          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
680                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
681          (match_dup 2)))
682    (set (match_operand:SI 0 "s_register_operand" "=r,r")
683         (plus:SI (match_dup 1) (match_dup 2)))]
684   "TARGET_ARM"
685   "@
686    add%?s\\t%0, %1, %2
687    sub%?s\\t%0, %1, #%n2"
688   [(set_attr "conds" "set")]
691 (define_insn "*compare_addsi2_op0"
692   [(set (reg:CC_C CC_REGNUM)
693         (compare:CC_C
694          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
695                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
696          (match_dup 0)))]
697   "TARGET_ARM"
698   "@
699    cmn%?\\t%0, %1
700    cmp%?\\t%0, #%n1"
701   [(set_attr "conds" "set")]
704 (define_insn "*compare_addsi2_op1"
705   [(set (reg:CC_C CC_REGNUM)
706         (compare:CC_C
707          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
708                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
709          (match_dup 1)))]
710   "TARGET_ARM"
711   "@
712    cmn%?\\t%0, %1
713    cmp%?\\t%0, #%n1"
714   [(set_attr "conds" "set")]
717 (define_insn "*addsi3_carryin"
718   [(set (match_operand:SI 0 "s_register_operand" "=r")
719         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
720                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
721                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
722   "TARGET_ARM"
723   "adc%?\\t%0, %1, %2"
724   [(set_attr "conds" "use")]
727 (define_insn "*addsi3_carryin_shift"
728   [(set (match_operand:SI 0 "s_register_operand" "=r")
729         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
730                  (plus:SI
731                    (match_operator:SI 2 "shift_operator"
732                       [(match_operand:SI 3 "s_register_operand" "r")
733                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
734                     (match_operand:SI 1 "s_register_operand" "r"))))]
735   "TARGET_ARM"
736   "adc%?\\t%0, %1, %3%S2"
737   [(set_attr "conds" "use")
738    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
739                       (const_string "alu_shift")
740                       (const_string "alu_shift_reg")))]
743 (define_insn "*addsi3_carryin_alt1"
744   [(set (match_operand:SI 0 "s_register_operand" "=r")
745         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
746                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
747                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
748   "TARGET_ARM"
749   "adc%?\\t%0, %1, %2"
750   [(set_attr "conds" "use")]
753 (define_insn "*addsi3_carryin_alt2"
754   [(set (match_operand:SI 0 "s_register_operand" "=r")
755         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
756                           (match_operand:SI 1 "s_register_operand" "r"))
757                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
758   "TARGET_ARM"
759   "adc%?\\t%0, %1, %2"
760   [(set_attr "conds" "use")]
763 (define_insn "*addsi3_carryin_alt3"
764   [(set (match_operand:SI 0 "s_register_operand" "=r")
765         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
766                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
767                  (match_operand:SI 1 "s_register_operand" "r")))]
768   "TARGET_ARM"
769   "adc%?\\t%0, %1, %2"
770   [(set_attr "conds" "use")]
773 (define_insn "incscc"
774   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
775         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
776                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
777                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
778   "TARGET_ARM"
779   "@
780   add%d2\\t%0, %1, #1
781   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
782   [(set_attr "conds" "use")
783    (set_attr "length" "4,8")]
786 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
787 (define_split
788   [(set (match_operand:SI 0 "s_register_operand" "")
789         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
790                             (match_operand:SI 2 "s_register_operand" ""))
791                  (const_int -1)))
792    (clobber (match_operand:SI 3 "s_register_operand" ""))]
793   "TARGET_ARM"
794   [(set (match_dup 3) (match_dup 1))
795    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
796   "
797   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
800 (define_expand "addsf3"
801   [(set (match_operand:SF          0 "s_register_operand" "")
802         (plus:SF (match_operand:SF 1 "s_register_operand" "")
803                  (match_operand:SF 2 "arm_float_add_operand" "")))]
804   "TARGET_ARM && TARGET_HARD_FLOAT"
805   "
806   if (TARGET_MAVERICK
807       && !cirrus_fp_register (operands[2], SFmode))
808     operands[2] = force_reg (SFmode, operands[2]);
811 (define_expand "adddf3"
812   [(set (match_operand:DF          0 "s_register_operand" "")
813         (plus:DF (match_operand:DF 1 "s_register_operand" "")
814                  (match_operand:DF 2 "arm_float_add_operand" "")))]
815   "TARGET_ARM && TARGET_HARD_FLOAT"
816   "
817   if (TARGET_MAVERICK
818       && !cirrus_fp_register (operands[2], DFmode))
819     operands[2] = force_reg (DFmode, operands[2]);
822 (define_expand "subdi3"
823  [(parallel
824    [(set (match_operand:DI            0 "s_register_operand" "")
825           (minus:DI (match_operand:DI 1 "s_register_operand" "")
826                     (match_operand:DI 2 "s_register_operand" "")))
827     (clobber (reg:CC CC_REGNUM))])]
828   "TARGET_EITHER"
829   "
830   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
831       && TARGET_ARM
832       && cirrus_fp_register (operands[0], DImode)
833       && cirrus_fp_register (operands[1], DImode))
834     {
835       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
836       DONE;
837     }
839   if (TARGET_THUMB)
840     {
841       if (GET_CODE (operands[1]) != REG)
842         operands[1] = force_reg (SImode, operands[1]);
843       if (GET_CODE (operands[2]) != REG)
844         operands[2] = force_reg (SImode, operands[2]);
845      }  
846   "
849 (define_insn "*arm_subdi3"
850   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
851         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
852                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
853    (clobber (reg:CC CC_REGNUM))]
854   "TARGET_ARM"
855   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
856   [(set_attr "conds" "clob")
857    (set_attr "length" "8")]
860 (define_insn "*thumb_subdi3"
861   [(set (match_operand:DI           0 "register_operand" "=l")
862         (minus:DI (match_operand:DI 1 "register_operand"  "0")
863                   (match_operand:DI 2 "register_operand"  "l")))
864    (clobber (reg:CC CC_REGNUM))]
865   "TARGET_THUMB"
866   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
867   [(set_attr "length" "4")]
870 (define_insn "*subdi_di_zesidi"
871   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
872         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
873                   (zero_extend:DI
874                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
875    (clobber (reg:CC CC_REGNUM))]
876   "TARGET_ARM"
877   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
878   [(set_attr "conds" "clob")
879    (set_attr "length" "8")]
882 (define_insn "*subdi_di_sesidi"
883   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
884         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
885                   (sign_extend:DI
886                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
887    (clobber (reg:CC CC_REGNUM))]
888   "TARGET_ARM"
889   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
890   [(set_attr "conds" "clob")
891    (set_attr "length" "8")]
894 (define_insn "*subdi_zesidi_di"
895   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
896         (minus:DI (zero_extend:DI
897                    (match_operand:SI 2 "s_register_operand"  "r,r"))
898                   (match_operand:DI  1 "s_register_operand" "?r,0")))
899    (clobber (reg:CC CC_REGNUM))]
900   "TARGET_ARM"
901   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
902   [(set_attr "conds" "clob")
903    (set_attr "length" "8")]
906 (define_insn "*subdi_sesidi_di"
907   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
908         (minus:DI (sign_extend:DI
909                    (match_operand:SI 2 "s_register_operand"   "r,r"))
910                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
911    (clobber (reg:CC CC_REGNUM))]
912   "TARGET_ARM"
913   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
914   [(set_attr "conds" "clob")
915    (set_attr "length" "8")]
918 (define_insn "*subdi_zesidi_zesidi"
919   [(set (match_operand:DI            0 "s_register_operand" "=r")
920         (minus:DI (zero_extend:DI
921                    (match_operand:SI 1 "s_register_operand"  "r"))
922                   (zero_extend:DI
923                    (match_operand:SI 2 "s_register_operand"  "r"))))
924    (clobber (reg:CC CC_REGNUM))]
925   "TARGET_ARM"
926   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
927   [(set_attr "conds" "clob")
928    (set_attr "length" "8")]
931 (define_expand "subsi3"
932   [(set (match_operand:SI           0 "s_register_operand" "")
933         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
934                   (match_operand:SI 2 "s_register_operand" "")))]
935   "TARGET_EITHER"
936   "
937   if (GET_CODE (operands[1]) == CONST_INT)
938     {
939       if (TARGET_ARM)
940         {
941           arm_split_constant (MINUS, SImode, NULL_RTX,
942                               INTVAL (operands[1]), operands[0],
943                               operands[2], optimize && !no_new_pseudos);
944           DONE;
945         }
946       else /* TARGET_THUMB */
947         operands[1] = force_reg (SImode, operands[1]);
948     }
949   "
952 (define_insn "*thumb_subsi3_insn"
953   [(set (match_operand:SI           0 "register_operand" "=l")
954         (minus:SI (match_operand:SI 1 "register_operand" "l")
955                   (match_operand:SI 2 "register_operand" "l")))]
956   "TARGET_THUMB"
957   "sub\\t%0, %1, %2"
958   [(set_attr "length" "2")]
961 (define_insn_and_split "*arm_subsi3_insn"
962   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
963         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
964                   (match_operand:SI 2 "s_register_operand" "r,r")))]
965   "TARGET_ARM"
966   "@
967    rsb%?\\t%0, %2, %1
968    #"
969   "TARGET_ARM
970    && GET_CODE (operands[1]) == CONST_INT
971    && !const_ok_for_arm (INTVAL (operands[1]))"
972   [(clobber (const_int 0))]
973   "
974   arm_split_constant (MINUS, SImode, curr_insn,
975                       INTVAL (operands[1]), operands[0], operands[2], 0);
976   DONE;
977   "
978   [(set_attr "length" "4,16")
979    (set_attr "predicable" "yes")]
982 (define_peephole2
983   [(match_scratch:SI 3 "r")
984    (set (match_operand:SI 0 "arm_general_register_operand" "")
985         (minus:SI (match_operand:SI 1 "const_int_operand" "")
986                   (match_operand:SI 2 "arm_general_register_operand" "")))]
987   "TARGET_ARM
988    && !const_ok_for_arm (INTVAL (operands[1]))
989    && const_ok_for_arm (~INTVAL (operands[1]))"
990   [(set (match_dup 3) (match_dup 1))
991    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
992   ""
995 (define_insn "*subsi3_compare0"
996   [(set (reg:CC_NOOV CC_REGNUM)
997         (compare:CC_NOOV
998          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
999                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1000          (const_int 0)))
1001    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1002         (minus:SI (match_dup 1) (match_dup 2)))]
1003   "TARGET_ARM"
1004   "@
1005    sub%?s\\t%0, %1, %2
1006    rsb%?s\\t%0, %2, %1"
1007   [(set_attr "conds" "set")]
1010 (define_insn "decscc"
1011   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1012         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1013                   (match_operator:SI 2 "arm_comparison_operator"
1014                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1015   "TARGET_ARM"
1016   "@
1017    sub%d2\\t%0, %1, #1
1018    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1019   [(set_attr "conds" "use")
1020    (set_attr "length" "*,8")]
1023 (define_expand "subsf3"
1024   [(set (match_operand:SF           0 "s_register_operand" "")
1025         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1026                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1027   "TARGET_ARM && TARGET_HARD_FLOAT"
1028   "
1029   if (TARGET_MAVERICK)
1030     {
1031       if (!cirrus_fp_register (operands[1], SFmode))
1032         operands[1] = force_reg (SFmode, operands[1]);
1033       if (!cirrus_fp_register (operands[2], SFmode))
1034         operands[2] = force_reg (SFmode, operands[2]);
1035     }
1038 (define_expand "subdf3"
1039   [(set (match_operand:DF           0 "s_register_operand" "")
1040         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1041                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1042   "TARGET_ARM && TARGET_HARD_FLOAT"
1043   "
1044   if (TARGET_MAVERICK)
1045     {
1046        if (!cirrus_fp_register (operands[1], DFmode))
1047          operands[1] = force_reg (DFmode, operands[1]);
1048        if (!cirrus_fp_register (operands[2], DFmode))
1049          operands[2] = force_reg (DFmode, operands[2]);
1050     }
1054 ;; Multiplication insns
1056 (define_expand "mulsi3"
1057   [(set (match_operand:SI          0 "s_register_operand" "")
1058         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1059                  (match_operand:SI 1 "s_register_operand" "")))]
1060   "TARGET_EITHER"
1061   ""
1064 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1065 (define_insn "*arm_mulsi3"
1066   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1067         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1068                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1069   "TARGET_ARM"
1070   "mul%?\\t%0, %2, %1"
1071   [(set_attr "insn" "mul")
1072    (set_attr "predicable" "yes")]
1075 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1076 ; 1 and 2; are the same, because reload will make operand 0 match 
1077 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1078 ; this by adding another alternative to match this case, and then `reload' 
1079 ; it ourselves.  This alternative must come first.
1080 (define_insn "*thumb_mulsi3"
1081   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1082         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1083                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1084   "TARGET_THUMB"
1085   "*
1086   if (which_alternative < 2)
1087     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1088   else
1089     return \"mul\\t%0, %0, %2\";
1090   "
1091   [(set_attr "length" "4,4,2")
1092    (set_attr "insn" "mul")]
1095 (define_insn "*mulsi3_compare0"
1096   [(set (reg:CC_NOOV CC_REGNUM)
1097         (compare:CC_NOOV (mult:SI
1098                           (match_operand:SI 2 "s_register_operand" "r,r")
1099                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1100                          (const_int 0)))
1101    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1102         (mult:SI (match_dup 2) (match_dup 1)))]
1103   "TARGET_ARM"
1104   "mul%?s\\t%0, %2, %1"
1105   [(set_attr "conds" "set")
1106    (set_attr "insn" "muls")]
1109 (define_insn "*mulsi_compare0_scratch"
1110   [(set (reg:CC_NOOV CC_REGNUM)
1111         (compare:CC_NOOV (mult:SI
1112                           (match_operand:SI 2 "s_register_operand" "r,r")
1113                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1114                          (const_int 0)))
1115    (clobber (match_scratch:SI 0 "=&r,&r"))]
1116   "TARGET_ARM"
1117   "mul%?s\\t%0, %2, %1"
1118   [(set_attr "conds" "set")
1119    (set_attr "insn" "muls")]
1122 ;; Unnamed templates to match MLA instruction.
1124 (define_insn "*mulsi3addsi"
1125   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1126         (plus:SI
1127           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1128                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1129           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1130   "TARGET_ARM"
1131   "mla%?\\t%0, %2, %1, %3"
1132   [(set_attr "insn" "mla")
1133    (set_attr "predicable" "yes")]
1136 (define_insn "*mulsi3addsi_compare0"
1137   [(set (reg:CC_NOOV CC_REGNUM)
1138         (compare:CC_NOOV
1139          (plus:SI (mult:SI
1140                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1141                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1142                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1143          (const_int 0)))
1144    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1145         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1146                  (match_dup 3)))]
1147   "TARGET_ARM"
1148   "mla%?s\\t%0, %2, %1, %3"
1149   [(set_attr "conds" "set")
1150    (set_attr "insn" "mlas")]
1153 (define_insn "*mulsi3addsi_compare0_scratch"
1154   [(set (reg:CC_NOOV CC_REGNUM)
1155         (compare:CC_NOOV
1156          (plus:SI (mult:SI
1157                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1158                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1159                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1160          (const_int 0)))
1161    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1162   "TARGET_ARM"
1163   "mla%?s\\t%0, %2, %1, %3"
1164   [(set_attr "conds" "set")
1165    (set_attr "insn" "mlas")]
1168 ;; Unnamed template to match long long multiply-accumulate (smlal)
1170 (define_insn "*mulsidi3adddi"
1171   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1172         (plus:DI
1173          (mult:DI
1174           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1175           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1176          (match_operand:DI 1 "s_register_operand" "0")))]
1177   "TARGET_ARM && arm_arch3m"
1178   "smlal%?\\t%Q0, %R0, %3, %2"
1179   [(set_attr "insn" "smlal")
1180    (set_attr "predicable" "yes")]
1183 (define_insn "mulsidi3"
1184   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1185         (mult:DI
1186          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1187          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1188   "TARGET_ARM && arm_arch3m"
1189   "smull%?\\t%Q0, %R0, %1, %2"
1190   [(set_attr "insn" "smull")
1191    (set_attr "predicable" "yes")]
1194 (define_insn "umulsidi3"
1195   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1196         (mult:DI
1197          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1198          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1199   "TARGET_ARM && arm_arch3m"
1200   "umull%?\\t%Q0, %R0, %1, %2"
1201   [(set_attr "insn" "umull")
1202    (set_attr "predicable" "yes")]
1205 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1207 (define_insn "*umulsidi3adddi"
1208   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1209         (plus:DI
1210          (mult:DI
1211           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1212           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1213          (match_operand:DI 1 "s_register_operand" "0")))]
1214   "TARGET_ARM && arm_arch3m"
1215   "umlal%?\\t%Q0, %R0, %3, %2"
1216   [(set_attr "insn" "umlal")
1217    (set_attr "predicable" "yes")]
1220 (define_insn "smulsi3_highpart"
1221   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1222         (truncate:SI
1223          (lshiftrt:DI
1224           (mult:DI
1225            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1226            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1227           (const_int 32))))
1228    (clobber (match_scratch:SI 3 "=&r,&r"))]
1229   "TARGET_ARM && arm_arch3m"
1230   "smull%?\\t%3, %0, %2, %1"
1231   [(set_attr "insn" "smull")
1232    (set_attr "predicable" "yes")]
1235 (define_insn "umulsi3_highpart"
1236   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1237         (truncate:SI
1238          (lshiftrt:DI
1239           (mult:DI
1240            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1241            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1242           (const_int 32))))
1243    (clobber (match_scratch:SI 3 "=&r,&r"))]
1244   "TARGET_ARM && arm_arch3m"
1245   "umull%?\\t%3, %0, %2, %1"
1246   [(set_attr "insn" "umull")
1247    (set_attr "predicable" "yes")]
1250 (define_insn "mulhisi3"
1251   [(set (match_operand:SI 0 "s_register_operand" "=r")
1252         (mult:SI (sign_extend:SI
1253                   (match_operand:HI 1 "s_register_operand" "%r"))
1254                  (sign_extend:SI
1255                   (match_operand:HI 2 "s_register_operand" "r"))))]
1256   "TARGET_ARM && arm_arch5e"
1257   "smulbb%?\\t%0, %1, %2"
1258   [(set_attr "insn" "smulxy")
1259    (set_attr "predicable" "yes")]
1262 (define_insn "*mulhisi3tb"
1263   [(set (match_operand:SI 0 "s_register_operand" "=r")
1264         (mult:SI (ashiftrt:SI
1265                   (match_operand:SI 1 "s_register_operand" "r")
1266                   (const_int 16))
1267                  (sign_extend:SI
1268                   (match_operand:HI 2 "s_register_operand" "r"))))]
1269   "TARGET_ARM && arm_arch5e"
1270   "smultb%?\\t%0, %1, %2"
1271   [(set_attr "insn" "smulxy")
1272    (set_attr "predicable" "yes")]
1275 (define_insn "*mulhisi3bt"
1276   [(set (match_operand:SI 0 "s_register_operand" "=r")
1277         (mult:SI (sign_extend:SI
1278                   (match_operand:HI 1 "s_register_operand" "r"))
1279                  (ashiftrt:SI
1280                   (match_operand:SI 2 "s_register_operand" "r")
1281                   (const_int 16))))]
1282   "TARGET_ARM && arm_arch5e"
1283   "smulbt%?\\t%0, %1, %2"
1284   [(set_attr "insn" "smulxy")
1285    (set_attr "predicable" "yes")]
1288 (define_insn "*mulhisi3tt"
1289   [(set (match_operand:SI 0 "s_register_operand" "=r")
1290         (mult:SI (ashiftrt:SI
1291                   (match_operand:SI 1 "s_register_operand" "r")
1292                   (const_int 16))
1293                  (ashiftrt:SI
1294                   (match_operand:SI 2 "s_register_operand" "r")
1295                   (const_int 16))))]
1296   "TARGET_ARM && arm_arch5e"
1297   "smultt%?\\t%0, %1, %2"
1298   [(set_attr "insn" "smulxy")
1299    (set_attr "predicable" "yes")]
1302 (define_insn "*mulhisi3addsi"
1303   [(set (match_operand:SI 0 "s_register_operand" "=r")
1304         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1305                  (mult:SI (sign_extend:SI
1306                            (match_operand:HI 2 "s_register_operand" "%r"))
1307                           (sign_extend:SI
1308                            (match_operand:HI 3 "s_register_operand" "r")))))]
1309   "TARGET_ARM && arm_arch5e"
1310   "smlabb%?\\t%0, %2, %3, %1"
1311   [(set_attr "insn" "smlaxy")
1312    (set_attr "predicable" "yes")]
1315 (define_insn "*mulhidi3adddi"
1316   [(set (match_operand:DI 0 "s_register_operand" "=r")
1317         (plus:DI
1318           (match_operand:DI 1 "s_register_operand" "0")
1319           (mult:DI (sign_extend:DI
1320                     (match_operand:HI 2 "s_register_operand" "%r"))
1321                    (sign_extend:DI
1322                     (match_operand:HI 3 "s_register_operand" "r")))))]
1323   "TARGET_ARM && arm_arch5e"
1324   "smlalbb%?\\t%Q0, %R0, %2, %3"
1325   [(set_attr "insn" "smlalxy")
1326    (set_attr "predicable" "yes")])
1328 (define_expand "mulsf3"
1329   [(set (match_operand:SF          0 "s_register_operand" "")
1330         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1331                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1332   "TARGET_ARM && TARGET_HARD_FLOAT"
1333   "
1334   if (TARGET_MAVERICK
1335       && !cirrus_fp_register (operands[2], SFmode))
1336     operands[2] = force_reg (SFmode, operands[2]);
1339 (define_expand "muldf3"
1340   [(set (match_operand:DF          0 "s_register_operand" "")
1341         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1342                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1343   "TARGET_ARM && TARGET_HARD_FLOAT"
1344   "
1345   if (TARGET_MAVERICK
1346       && !cirrus_fp_register (operands[2], DFmode))
1347     operands[2] = force_reg (DFmode, operands[2]);
1350 ;; Division insns
1352 (define_expand "divsf3"
1353   [(set (match_operand:SF 0 "s_register_operand" "")
1354         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1355                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1356   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1357   "")
1359 (define_expand "divdf3"
1360   [(set (match_operand:DF 0 "s_register_operand" "")
1361         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1362                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1363   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1364   "")
1366 ;; Modulo insns
1368 (define_expand "modsf3"
1369   [(set (match_operand:SF 0 "s_register_operand" "")
1370         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1371                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1372   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1373   "")
1375 (define_expand "moddf3"
1376   [(set (match_operand:DF 0 "s_register_operand" "")
1377         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1378                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1379   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1380   "")
1382 ;; Boolean and,ior,xor insns
1384 ;; Split up double word logical operations
1386 ;; Split up simple DImode logical operations.  Simply perform the logical
1387 ;; operation on the upper and lower halves of the registers.
1388 (define_split
1389   [(set (match_operand:DI 0 "s_register_operand" "")
1390         (match_operator:DI 6 "logical_binary_operator"
1391           [(match_operand:DI 1 "s_register_operand" "")
1392            (match_operand:DI 2 "s_register_operand" "")]))]
1393   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1394   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1395    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1396   "
1397   {
1398     operands[3] = gen_highpart (SImode, operands[0]);
1399     operands[0] = gen_lowpart (SImode, operands[0]);
1400     operands[4] = gen_highpart (SImode, operands[1]);
1401     operands[1] = gen_lowpart (SImode, operands[1]);
1402     operands[5] = gen_highpart (SImode, operands[2]);
1403     operands[2] = gen_lowpart (SImode, operands[2]);
1404   }"
1407 (define_split
1408   [(set (match_operand:DI 0 "s_register_operand" "")
1409         (match_operator:DI 6 "logical_binary_operator"
1410           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1411            (match_operand:DI 1 "s_register_operand" "")]))]
1412   "TARGET_ARM && reload_completed"
1413   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1414    (set (match_dup 3) (match_op_dup:SI 6
1415                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1416                          (match_dup 4)]))]
1417   "
1418   {
1419     operands[3] = gen_highpart (SImode, operands[0]);
1420     operands[0] = gen_lowpart (SImode, operands[0]);
1421     operands[4] = gen_highpart (SImode, operands[1]);
1422     operands[1] = gen_lowpart (SImode, operands[1]);
1423     operands[5] = gen_highpart (SImode, operands[2]);
1424     operands[2] = gen_lowpart (SImode, operands[2]);
1425   }"
1428 ;; The zero extend of operand 2 means we can just copy the high part of
1429 ;; operand1 into operand0.
1430 (define_split
1431   [(set (match_operand:DI 0 "s_register_operand" "")
1432         (ior:DI
1433           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1434           (match_operand:DI 1 "s_register_operand" "")))]
1435   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1436   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1437    (set (match_dup 3) (match_dup 4))]
1438   "
1439   {
1440     operands[4] = gen_highpart (SImode, operands[1]);
1441     operands[3] = gen_highpart (SImode, operands[0]);
1442     operands[0] = gen_lowpart (SImode, operands[0]);
1443     operands[1] = gen_lowpart (SImode, operands[1]);
1444   }"
1447 ;; The zero extend of operand 2 means we can just copy the high part of
1448 ;; operand1 into operand0.
1449 (define_split
1450   [(set (match_operand:DI 0 "s_register_operand" "")
1451         (xor:DI
1452           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1453           (match_operand:DI 1 "s_register_operand" "")))]
1454   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1455   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1456    (set (match_dup 3) (match_dup 4))]
1457   "
1458   {
1459     operands[4] = gen_highpart (SImode, operands[1]);
1460     operands[3] = gen_highpart (SImode, operands[0]);
1461     operands[0] = gen_lowpart (SImode, operands[0]);
1462     operands[1] = gen_lowpart (SImode, operands[1]);
1463   }"
1466 (define_insn "anddi3"
1467   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1468         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1469                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1470   "TARGET_ARM && ! TARGET_IWMMXT"
1471   "#"
1472   [(set_attr "length" "8")]
1475 (define_insn_and_split "*anddi_zesidi_di"
1476   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1477         (and:DI (zero_extend:DI
1478                  (match_operand:SI 2 "s_register_operand" "r,r"))
1479                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1480   "TARGET_ARM"
1481   "#"
1482   "TARGET_ARM && reload_completed"
1483   ; The zero extend of operand 2 clears the high word of the output
1484   ; operand.
1485   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1486    (set (match_dup 3) (const_int 0))]
1487   "
1488   {
1489     operands[3] = gen_highpart (SImode, operands[0]);
1490     operands[0] = gen_lowpart (SImode, operands[0]);
1491     operands[1] = gen_lowpart (SImode, operands[1]);
1492   }"
1493   [(set_attr "length" "8")]
1496 (define_insn "*anddi_sesdi_di"
1497   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1498         (and:DI (sign_extend:DI
1499                  (match_operand:SI 2 "s_register_operand" "r,r"))
1500                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1501   "TARGET_ARM"
1502   "#"
1503   [(set_attr "length" "8")]
1506 (define_expand "andsi3"
1507   [(set (match_operand:SI         0 "s_register_operand" "")
1508         (and:SI (match_operand:SI 1 "s_register_operand" "")
1509                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1510   "TARGET_EITHER"
1511   "
1512   if (TARGET_ARM)
1513     {
1514       if (GET_CODE (operands[2]) == CONST_INT)
1515         {
1516           arm_split_constant (AND, SImode, NULL_RTX,
1517                               INTVAL (operands[2]), operands[0],
1518                               operands[1], optimize && !no_new_pseudos);
1520           DONE;
1521         }
1522     }
1523   else /* TARGET_THUMB */
1524     {
1525       if (GET_CODE (operands[2]) != CONST_INT)
1526         operands[2] = force_reg (SImode, operands[2]);
1527       else
1528         {
1529           int i;
1530           
1531           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1532             {
1533               operands[2] = force_reg (SImode,
1534                                        GEN_INT (~INTVAL (operands[2])));
1535               
1536               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1537               
1538               DONE;
1539             }
1541           for (i = 9; i <= 31; i++)
1542             {
1543               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1544                 {
1545                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1546                                         const0_rtx));
1547                   DONE;
1548                 }
1549               else if ((((HOST_WIDE_INT) 1) << i) - 1
1550                        == ~INTVAL (operands[2]))
1551                 {
1552                   rtx shift = GEN_INT (i);
1553                   rtx reg = gen_reg_rtx (SImode);
1554                 
1555                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1556                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1557                   
1558                   DONE;
1559                 }
1560             }
1562           operands[2] = force_reg (SImode, operands[2]);
1563         }
1564     }
1565   "
1568 (define_insn_and_split "*arm_andsi3_insn"
1569   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1570         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1571                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1572   "TARGET_ARM"
1573   "@
1574    and%?\\t%0, %1, %2
1575    bic%?\\t%0, %1, #%B2
1576    #"
1577   "TARGET_ARM
1578    && GET_CODE (operands[2]) == CONST_INT
1579    && !(const_ok_for_arm (INTVAL (operands[2]))
1580         || const_ok_for_arm (~INTVAL (operands[2])))"
1581   [(clobber (const_int 0))]
1582   "
1583   arm_split_constant  (AND, SImode, curr_insn, 
1584                        INTVAL (operands[2]), operands[0], operands[1], 0);
1585   DONE;
1586   "
1587   [(set_attr "length" "4,4,16")
1588    (set_attr "predicable" "yes")]
1591 (define_insn "*thumb_andsi3_insn"
1592   [(set (match_operand:SI         0 "register_operand" "=l")
1593         (and:SI (match_operand:SI 1 "register_operand" "%0")
1594                 (match_operand:SI 2 "register_operand" "l")))]
1595   "TARGET_THUMB"
1596   "and\\t%0, %0, %2"
1597   [(set_attr "length" "2")]
1600 (define_insn "*andsi3_compare0"
1601   [(set (reg:CC_NOOV CC_REGNUM)
1602         (compare:CC_NOOV
1603          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1604                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1605          (const_int 0)))
1606    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1607         (and:SI (match_dup 1) (match_dup 2)))]
1608   "TARGET_ARM"
1609   "@
1610    and%?s\\t%0, %1, %2
1611    bic%?s\\t%0, %1, #%B2"
1612   [(set_attr "conds" "set")]
1615 (define_insn "*andsi3_compare0_scratch"
1616   [(set (reg:CC_NOOV CC_REGNUM)
1617         (compare:CC_NOOV
1618          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1619                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1620          (const_int 0)))
1621    (clobber (match_scratch:SI 2 "=X,r"))]
1622   "TARGET_ARM"
1623   "@
1624    tst%?\\t%0, %1
1625    bic%?s\\t%2, %0, #%B1"
1626   [(set_attr "conds" "set")]
1629 (define_insn "*zeroextractsi_compare0_scratch"
1630   [(set (reg:CC_NOOV CC_REGNUM)
1631         (compare:CC_NOOV (zero_extract:SI
1632                           (match_operand:SI 0 "s_register_operand" "r")
1633                           (match_operand 1 "const_int_operand" "n")
1634                           (match_operand 2 "const_int_operand" "n"))
1635                          (const_int 0)))]
1636   "TARGET_ARM
1637   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1638       && INTVAL (operands[1]) > 0 
1639       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1640       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1641   "*
1642   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1643                          << INTVAL (operands[2]));
1644   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1645   return \"\";
1646   "
1647   [(set_attr "conds" "set")]
1650 (define_insn_and_split "*ne_zeroextractsi"
1651   [(set (match_operand:SI 0 "s_register_operand" "=r")
1652         (ne:SI (zero_extract:SI
1653                 (match_operand:SI 1 "s_register_operand" "r")
1654                 (match_operand:SI 2 "const_int_operand" "n")
1655                 (match_operand:SI 3 "const_int_operand" "n"))
1656                (const_int 0)))
1657    (clobber (reg:CC CC_REGNUM))]
1658   "TARGET_ARM
1659    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1660        && INTVAL (operands[2]) > 0 
1661        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1662        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1663   "#"
1664   "TARGET_ARM
1665    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1666        && INTVAL (operands[2]) > 0 
1667        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1668        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1669   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1670                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1671                                     (const_int 0)))
1672               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1673    (set (match_dup 0)
1674         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1675                          (match_dup 0) (const_int 1)))]
1676   "
1677   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1678                          << INTVAL (operands[3])); 
1679   "
1680   [(set_attr "conds" "clob")
1681    (set_attr "length" "8")]
1684 (define_insn_and_split "*ne_zeroextractsi_shifted"
1685   [(set (match_operand:SI 0 "s_register_operand" "=r")
1686         (ne:SI (zero_extract:SI
1687                 (match_operand:SI 1 "s_register_operand" "r")
1688                 (match_operand:SI 2 "const_int_operand" "n")
1689                 (const_int 0))
1690                (const_int 0)))
1691    (clobber (reg:CC CC_REGNUM))]
1692   "TARGET_ARM"
1693   "#"
1694   "TARGET_ARM"
1695   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1696                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1697                                     (const_int 0)))
1698               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1699    (set (match_dup 0)
1700         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1701                          (match_dup 0) (const_int 1)))]
1702   "
1703   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1704   "
1705   [(set_attr "conds" "clob")
1706    (set_attr "length" "8")]
1709 (define_insn_and_split "*ite_ne_zeroextractsi"
1710   [(set (match_operand:SI 0 "s_register_operand" "=r")
1711         (if_then_else:SI (ne (zero_extract:SI
1712                               (match_operand:SI 1 "s_register_operand" "r")
1713                               (match_operand:SI 2 "const_int_operand" "n")
1714                               (match_operand:SI 3 "const_int_operand" "n"))
1715                              (const_int 0))
1716                          (match_operand:SI 4 "arm_not_operand" "rIK")
1717                          (const_int 0)))
1718    (clobber (reg:CC CC_REGNUM))]
1719   "TARGET_ARM
1720    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1721        && INTVAL (operands[2]) > 0 
1722        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1723        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1724    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1725   "#"
1726   "TARGET_ARM
1727    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1728        && INTVAL (operands[2]) > 0 
1729        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1730        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
1731    && !reg_overlap_mentioned_p (operands[0], operands[4])"
1732   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1733                    (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
1734                                     (const_int 0)))
1735               (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
1736    (set (match_dup 0)
1737         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1738                          (match_dup 0) (match_dup 4)))]
1739   "
1740   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1741                          << INTVAL (operands[3])); 
1742   "
1743   [(set_attr "conds" "clob")
1744    (set_attr "length" "8")]
1747 (define_insn_and_split "*ite_ne_zeroextractsi_shifted"
1748   [(set (match_operand:SI 0 "s_register_operand" "=r")
1749         (if_then_else:SI (ne (zero_extract:SI
1750                               (match_operand:SI 1 "s_register_operand" "r")
1751                               (match_operand:SI 2 "const_int_operand" "n")
1752                               (const_int 0))
1753                              (const_int 0))
1754                          (match_operand:SI 3 "arm_not_operand" "rIK")
1755                          (const_int 0)))
1756    (clobber (reg:CC CC_REGNUM))]
1757   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1758   "#"
1759   "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
1760   [(parallel [(set (reg:CC_NOOV CC_REGNUM)
1761                    (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
1762                                     (const_int 0)))
1763               (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
1764    (set (match_dup 0)
1765         (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
1766                          (match_dup 0) (match_dup 3)))]
1767   "
1768   operands[2] = GEN_INT (32 - INTVAL (operands[2]));
1769   "
1770   [(set_attr "conds" "clob")
1771    (set_attr "length" "8")]
1774 (define_split
1775   [(set (match_operand:SI 0 "s_register_operand" "")
1776         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1777                          (match_operand:SI 2 "const_int_operand" "")
1778                          (match_operand:SI 3 "const_int_operand" "")))
1779    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1780   "TARGET_THUMB"
1781   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1782    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1783   "{
1784      HOST_WIDE_INT temp = INTVAL (operands[2]);
1786      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1787      operands[3] = GEN_INT (32 - temp);
1788    }"
1791 (define_split
1792   [(set (match_operand:SI 0 "s_register_operand" "")
1793         (match_operator:SI 1 "shiftable_operator"
1794          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1795                            (match_operand:SI 3 "const_int_operand" "")
1796                            (match_operand:SI 4 "const_int_operand" ""))
1797           (match_operand:SI 5 "s_register_operand" "")]))
1798    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1799   "TARGET_ARM"
1800   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1801    (set (match_dup 0)
1802         (match_op_dup 1
1803          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1804           (match_dup 5)]))]
1805   "{
1806      HOST_WIDE_INT temp = INTVAL (operands[3]);
1808      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1809      operands[4] = GEN_INT (32 - temp);
1810    }"
1812   
1813 (define_split
1814   [(set (match_operand:SI 0 "s_register_operand" "")
1815         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1816                          (match_operand:SI 2 "const_int_operand" "")
1817                          (match_operand:SI 3 "const_int_operand" "")))]
1818   "TARGET_THUMB"
1819   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1820    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1821   "{
1822      HOST_WIDE_INT temp = INTVAL (operands[2]);
1824      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1825      operands[3] = GEN_INT (32 - temp);
1826    }"
1829 (define_split
1830   [(set (match_operand:SI 0 "s_register_operand" "")
1831         (match_operator:SI 1 "shiftable_operator"
1832          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1833                            (match_operand:SI 3 "const_int_operand" "")
1834                            (match_operand:SI 4 "const_int_operand" ""))
1835           (match_operand:SI 5 "s_register_operand" "")]))
1836    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1837   "TARGET_ARM"
1838   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1839    (set (match_dup 0)
1840         (match_op_dup 1
1841          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1842           (match_dup 5)]))]
1843   "{
1844      HOST_WIDE_INT temp = INTVAL (operands[3]);
1846      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1847      operands[4] = GEN_INT (32 - temp);
1848    }"
1850   
1851 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1852 ;;; represented by the bitfield, then this will produce incorrect results.
1853 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1854 ;;; which have a real bit-field insert instruction, the truncation happens
1855 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1856 ;;; bit-field insert instruction, we would have to emit code here to truncate
1857 ;;; the value before we insert.  This loses some of the advantage of having
1858 ;;; this insv pattern, so this pattern needs to be reevalutated.
1860 (define_expand "insv"
1861   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1862                          (match_operand:SI 1 "general_operand" "")
1863                          (match_operand:SI 2 "general_operand" ""))
1864         (match_operand:SI 3 "reg_or_int_operand" ""))]
1865   "TARGET_ARM"
1866   "
1867   {
1868     int start_bit = INTVAL (operands[2]);
1869     int width = INTVAL (operands[1]);
1870     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1871     rtx target, subtarget;
1873     target = operands[0];
1874     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1875        subreg as the final target.  */
1876     if (GET_CODE (target) == SUBREG)
1877       {
1878         subtarget = gen_reg_rtx (SImode);
1879         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1880             < GET_MODE_SIZE (SImode))
1881           target = SUBREG_REG (target);
1882       }
1883     else
1884       subtarget = target;    
1886     if (GET_CODE (operands[3]) == CONST_INT)
1887       {
1888         /* Since we are inserting a known constant, we may be able to
1889            reduce the number of bits that we have to clear so that
1890            the mask becomes simple.  */
1891         /* ??? This code does not check to see if the new mask is actually
1892            simpler.  It may not be.  */
1893         rtx op1 = gen_reg_rtx (SImode);
1894         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1895            start of this pattern.  */
1896         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1897         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1899         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1900         emit_insn (gen_iorsi3 (subtarget, op1,
1901                                gen_int_mode (op3_value << start_bit, SImode)));
1902       }
1903     else if (start_bit == 0
1904              && !(const_ok_for_arm (mask)
1905                   || const_ok_for_arm (~mask)))
1906       {
1907         /* A Trick, since we are setting the bottom bits in the word,
1908            we can shift operand[3] up, operand[0] down, OR them together
1909            and rotate the result back again.  This takes 3 insns, and
1910            the third might be mergeable into another op.  */
1911         /* The shift up copes with the possibility that operand[3] is
1912            wider than the bitfield.  */
1913         rtx op0 = gen_reg_rtx (SImode);
1914         rtx op1 = gen_reg_rtx (SImode);
1916         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1917         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1918         emit_insn (gen_iorsi3  (op1, op1, op0));
1919         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1920       }
1921     else if ((width + start_bit == 32)
1922              && !(const_ok_for_arm (mask)
1923                   || const_ok_for_arm (~mask)))
1924       {
1925         /* Similar trick, but slightly less efficient.  */
1927         rtx op0 = gen_reg_rtx (SImode);
1928         rtx op1 = gen_reg_rtx (SImode);
1930         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1931         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1932         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1933         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1934       }
1935     else
1936       {
1937         rtx op0 = GEN_INT (mask);
1938         rtx op1 = gen_reg_rtx (SImode);
1939         rtx op2 = gen_reg_rtx (SImode);
1941         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1942           {
1943             rtx tmp = gen_reg_rtx (SImode);
1945             emit_insn (gen_movsi (tmp, op0));
1946             op0 = tmp;
1947           }
1949         /* Mask out any bits in operand[3] that are not needed.  */
1950            emit_insn (gen_andsi3 (op1, operands[3], op0));
1952         if (GET_CODE (op0) == CONST_INT
1953             && (const_ok_for_arm (mask << start_bit)
1954                 || const_ok_for_arm (~(mask << start_bit))))
1955           {
1956             op0 = GEN_INT (~(mask << start_bit));
1957             emit_insn (gen_andsi3 (op2, operands[0], op0));
1958           }
1959         else
1960           {
1961             if (GET_CODE (op0) == CONST_INT)
1962               {
1963                 rtx tmp = gen_reg_rtx (SImode);
1965                 emit_insn (gen_movsi (tmp, op0));
1966                 op0 = tmp;
1967               }
1969             if (start_bit != 0)
1970               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1971             
1972             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1973           }
1975         if (start_bit != 0)
1976           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1978         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1979       }
1981     if (subtarget != target)
1982       {
1983         /* If TARGET is still a SUBREG, then it must be wider than a word,
1984            so we must be careful only to set the subword we were asked to.  */
1985         if (GET_CODE (target) == SUBREG)
1986           emit_move_insn (target, subtarget);
1987         else
1988           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1989       }
1991     DONE;
1992   }"
1995 ; constants for op 2 will never be given to these patterns.
1996 (define_insn_and_split "*anddi_notdi_di"
1997   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1998         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1999                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2000   "TARGET_ARM"
2001   "#"
2002   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
2003   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2004    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2005   "
2006   {
2007     operands[3] = gen_highpart (SImode, operands[0]);
2008     operands[0] = gen_lowpart (SImode, operands[0]);
2009     operands[4] = gen_highpart (SImode, operands[1]);
2010     operands[1] = gen_lowpart (SImode, operands[1]);
2011     operands[5] = gen_highpart (SImode, operands[2]);
2012     operands[2] = gen_lowpart (SImode, operands[2]);
2013   }"
2014   [(set_attr "length" "8")
2015    (set_attr "predicable" "yes")]
2017   
2018 (define_insn_and_split "*anddi_notzesidi_di"
2019   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2020         (and:DI (not:DI (zero_extend:DI
2021                          (match_operand:SI 2 "s_register_operand" "r,r")))
2022                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2023   "TARGET_ARM"
2024   "@
2025    bic%?\\t%Q0, %Q1, %2
2026    #"
2027   ; (not (zero_extend ...)) allows us to just copy the high word from
2028   ; operand1 to operand0.
2029   "TARGET_ARM
2030    && reload_completed
2031    && operands[0] != operands[1]"
2032   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2033    (set (match_dup 3) (match_dup 4))]
2034   "
2035   {
2036     operands[3] = gen_highpart (SImode, operands[0]);
2037     operands[0] = gen_lowpart (SImode, operands[0]);
2038     operands[4] = gen_highpart (SImode, operands[1]);
2039     operands[1] = gen_lowpart (SImode, operands[1]);
2040   }"
2041   [(set_attr "length" "4,8")
2042    (set_attr "predicable" "yes")]
2044   
2045 (define_insn_and_split "*anddi_notsesidi_di"
2046   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2047         (and:DI (not:DI (sign_extend:DI
2048                          (match_operand:SI 2 "s_register_operand" "r,r")))
2049                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2050   "TARGET_ARM"
2051   "#"
2052   "TARGET_ARM && reload_completed"
2053   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2054    (set (match_dup 3) (and:SI (not:SI
2055                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2056                                (match_dup 4)))]
2057   "
2058   {
2059     operands[3] = gen_highpart (SImode, operands[0]);
2060     operands[0] = gen_lowpart (SImode, operands[0]);
2061     operands[4] = gen_highpart (SImode, operands[1]);
2062     operands[1] = gen_lowpart (SImode, operands[1]);
2063   }"
2064   [(set_attr "length" "8")
2065    (set_attr "predicable" "yes")]
2067   
2068 (define_insn "andsi_notsi_si"
2069   [(set (match_operand:SI 0 "s_register_operand" "=r")
2070         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2071                 (match_operand:SI 1 "s_register_operand" "r")))]
2072   "TARGET_ARM"
2073   "bic%?\\t%0, %1, %2"
2074   [(set_attr "predicable" "yes")]
2077 (define_insn "bicsi3"
2078   [(set (match_operand:SI                 0 "register_operand" "=l")
2079         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2080                 (match_operand:SI         2 "register_operand" "0")))]
2081   "TARGET_THUMB"
2082   "bic\\t%0, %0, %1"
2083   [(set_attr "length" "2")]
2086 (define_insn "andsi_not_shiftsi_si"
2087   [(set (match_operand:SI 0 "s_register_operand" "=r")
2088         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2089                          [(match_operand:SI 2 "s_register_operand" "r")
2090                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2091                 (match_operand:SI 1 "s_register_operand" "r")))]
2092   "TARGET_ARM"
2093   "bic%?\\t%0, %1, %2%S4"
2094   [(set_attr "predicable" "yes")
2095    (set_attr "shift" "2")
2096    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
2097                       (const_string "alu_shift")
2098                       (const_string "alu_shift_reg")))]
2101 (define_insn "*andsi_notsi_si_compare0"
2102   [(set (reg:CC_NOOV CC_REGNUM)
2103         (compare:CC_NOOV
2104          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2105                  (match_operand:SI 1 "s_register_operand" "r"))
2106          (const_int 0)))
2107    (set (match_operand:SI 0 "s_register_operand" "=r")
2108         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2109   "TARGET_ARM"
2110   "bic%?s\\t%0, %1, %2"
2111   [(set_attr "conds" "set")]
2114 (define_insn "*andsi_notsi_si_compare0_scratch"
2115   [(set (reg:CC_NOOV CC_REGNUM)
2116         (compare:CC_NOOV
2117          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2118                  (match_operand:SI 1 "s_register_operand" "r"))
2119          (const_int 0)))
2120    (clobber (match_scratch:SI 0 "=r"))]
2121   "TARGET_ARM"
2122   "bic%?s\\t%0, %1, %2"
2123   [(set_attr "conds" "set")]
2126 (define_insn "iordi3"
2127   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2128         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2129                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2130   "TARGET_ARM && ! TARGET_IWMMXT"
2131   "#"
2132   [(set_attr "length" "8")
2133    (set_attr "predicable" "yes")]
2136 (define_insn "*iordi_zesidi_di"
2137   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2138         (ior:DI (zero_extend:DI
2139                  (match_operand:SI 2 "s_register_operand" "r,r"))
2140                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2141   "TARGET_ARM"
2142   "@
2143    orr%?\\t%Q0, %Q1, %2
2144    #"
2145   [(set_attr "length" "4,8")
2146    (set_attr "predicable" "yes")]
2149 (define_insn "*iordi_sesidi_di"
2150   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2151         (ior:DI (sign_extend:DI
2152                  (match_operand:SI 2 "s_register_operand" "r,r"))
2153                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2154   "TARGET_ARM"
2155   "#"
2156   [(set_attr "length" "8")
2157    (set_attr "predicable" "yes")]
2160 (define_expand "iorsi3"
2161   [(set (match_operand:SI         0 "s_register_operand" "")
2162         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2163                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2164   "TARGET_EITHER"
2165   "
2166   if (GET_CODE (operands[2]) == CONST_INT)
2167     {
2168       if (TARGET_ARM)
2169         {
2170           arm_split_constant (IOR, SImode, NULL_RTX,
2171                               INTVAL (operands[2]), operands[0], operands[1],
2172                               optimize && !no_new_pseudos);
2173           DONE;
2174         }
2175       else /* TARGET_THUMB */
2176         operands [2] = force_reg (SImode, operands [2]);
2177     }
2178   "
2181 (define_insn_and_split "*arm_iorsi3"
2182   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2183         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2184                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2185   "TARGET_ARM"
2186   "@
2187    orr%?\\t%0, %1, %2
2188    #"
2189   "TARGET_ARM
2190    && GET_CODE (operands[2]) == CONST_INT
2191    && !const_ok_for_arm (INTVAL (operands[2]))"
2192   [(clobber (const_int 0))]
2193   "
2194   arm_split_constant (IOR, SImode, curr_insn, 
2195                       INTVAL (operands[2]), operands[0], operands[1], 0);
2196   DONE;
2197   "
2198   [(set_attr "length" "4,16")
2199    (set_attr "predicable" "yes")]
2202 (define_insn "*thumb_iorsi3"
2203   [(set (match_operand:SI         0 "register_operand" "=l")
2204         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2205                 (match_operand:SI 2 "register_operand" "l")))]
2206   "TARGET_THUMB"
2207   "orr\\t%0, %0, %2"
2208   [(set_attr "length" "2")]
2211 (define_peephole2
2212   [(match_scratch:SI 3 "r")
2213    (set (match_operand:SI 0 "arm_general_register_operand" "")
2214         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2215                 (match_operand:SI 2 "const_int_operand" "")))]
2216   "TARGET_ARM
2217    && !const_ok_for_arm (INTVAL (operands[2]))
2218    && const_ok_for_arm (~INTVAL (operands[2]))"
2219   [(set (match_dup 3) (match_dup 2))
2220    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2221   ""
2224 (define_insn "*iorsi3_compare0"
2225   [(set (reg:CC_NOOV CC_REGNUM)
2226         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2227                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2228                          (const_int 0)))
2229    (set (match_operand:SI 0 "s_register_operand" "=r")
2230         (ior:SI (match_dup 1) (match_dup 2)))]
2231   "TARGET_ARM"
2232   "orr%?s\\t%0, %1, %2"
2233   [(set_attr "conds" "set")]
2236 (define_insn "*iorsi3_compare0_scratch"
2237   [(set (reg:CC_NOOV CC_REGNUM)
2238         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2239                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2240                          (const_int 0)))
2241    (clobber (match_scratch:SI 0 "=r"))]
2242   "TARGET_ARM"
2243   "orr%?s\\t%0, %1, %2"
2244   [(set_attr "conds" "set")]
2247 (define_insn "xordi3"
2248   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2249         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2250                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2251   "TARGET_ARM && !TARGET_IWMMXT"
2252   "#"
2253   [(set_attr "length" "8")
2254    (set_attr "predicable" "yes")]
2257 (define_insn "*xordi_zesidi_di"
2258   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2259         (xor:DI (zero_extend:DI
2260                  (match_operand:SI 2 "s_register_operand" "r,r"))
2261                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2262   "TARGET_ARM"
2263   "@
2264    eor%?\\t%Q0, %Q1, %2
2265    #"
2266   [(set_attr "length" "4,8")
2267    (set_attr "predicable" "yes")]
2270 (define_insn "*xordi_sesidi_di"
2271   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2272         (xor:DI (sign_extend:DI
2273                  (match_operand:SI 2 "s_register_operand" "r,r"))
2274                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2275   "TARGET_ARM"
2276   "#"
2277   [(set_attr "length" "8")
2278    (set_attr "predicable" "yes")]
2281 (define_expand "xorsi3"
2282   [(set (match_operand:SI         0 "s_register_operand" "")
2283         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2284                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2285   "TARGET_EITHER"
2286   "if (TARGET_THUMB)
2287      if (GET_CODE (operands[2]) == CONST_INT)
2288        operands[2] = force_reg (SImode, operands[2]);
2289   "
2292 (define_insn "*arm_xorsi3"
2293   [(set (match_operand:SI         0 "s_register_operand" "=r")
2294         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2295                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2296   "TARGET_ARM"
2297   "eor%?\\t%0, %1, %2"
2298   [(set_attr "predicable" "yes")]
2301 (define_insn "*thumb_xorsi3"
2302   [(set (match_operand:SI         0 "register_operand" "=l")
2303         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2304                 (match_operand:SI 2 "register_operand" "l")))]
2305   "TARGET_THUMB"
2306   "eor\\t%0, %0, %2"
2307   [(set_attr "length" "2")]
2310 (define_insn "*xorsi3_compare0"
2311   [(set (reg:CC_NOOV CC_REGNUM)
2312         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2313                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2314                          (const_int 0)))
2315    (set (match_operand:SI 0 "s_register_operand" "=r")
2316         (xor:SI (match_dup 1) (match_dup 2)))]
2317   "TARGET_ARM"
2318   "eor%?s\\t%0, %1, %2"
2319   [(set_attr "conds" "set")]
2322 (define_insn "*xorsi3_compare0_scratch"
2323   [(set (reg:CC_NOOV CC_REGNUM)
2324         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2325                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2326                          (const_int 0)))]
2327   "TARGET_ARM"
2328   "teq%?\\t%0, %1"
2329   [(set_attr "conds" "set")]
2332 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2333 ; (NOT D) we can sometimes merge the final NOT into one of the following
2334 ; insns.
2336 (define_split
2337   [(set (match_operand:SI 0 "s_register_operand" "")
2338         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2339                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2340                 (match_operand:SI 3 "arm_rhs_operand" "")))
2341    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2342   "TARGET_ARM"
2343   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2344                               (not:SI (match_dup 3))))
2345    (set (match_dup 0) (not:SI (match_dup 4)))]
2346   ""
2349 (define_insn "*andsi_iorsi3_notsi"
2350   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2351         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2352                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2353                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2354   "TARGET_ARM"
2355   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2356   [(set_attr "length" "8")
2357    (set_attr "predicable" "yes")]
2360 (define_split
2361   [(set (match_operand:SI 0 "s_register_operand" "")
2362         (match_operator:SI 1 "logical_binary_operator"
2363          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2364                            (match_operand:SI 3 "const_int_operand" "")
2365                            (match_operand:SI 4 "const_int_operand" ""))
2366           (match_operator:SI 9 "logical_binary_operator"
2367            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2368                          (match_operand:SI 6 "const_int_operand" ""))
2369             (match_operand:SI 7 "s_register_operand" "")])]))
2370    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2371   "TARGET_ARM
2372    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2373    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2374   [(set (match_dup 8)
2375         (match_op_dup 1
2376          [(ashift:SI (match_dup 2) (match_dup 4))
2377           (match_dup 5)]))
2378    (set (match_dup 0)
2379         (match_op_dup 1
2380          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2381           (match_dup 7)]))]
2382   "
2383   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2386 (define_split
2387   [(set (match_operand:SI 0 "s_register_operand" "")
2388         (match_operator:SI 1 "logical_binary_operator"
2389          [(match_operator:SI 9 "logical_binary_operator"
2390            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2391                          (match_operand:SI 6 "const_int_operand" ""))
2392             (match_operand:SI 7 "s_register_operand" "")])
2393           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2394                            (match_operand:SI 3 "const_int_operand" "")
2395                            (match_operand:SI 4 "const_int_operand" ""))]))
2396    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2397   "TARGET_ARM
2398    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2399    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2400   [(set (match_dup 8)
2401         (match_op_dup 1
2402          [(ashift:SI (match_dup 2) (match_dup 4))
2403           (match_dup 5)]))
2404    (set (match_dup 0)
2405         (match_op_dup 1
2406          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2407           (match_dup 7)]))]
2408   "
2409   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2412 (define_split
2413   [(set (match_operand:SI 0 "s_register_operand" "")
2414         (match_operator:SI 1 "logical_binary_operator"
2415          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2416                            (match_operand:SI 3 "const_int_operand" "")
2417                            (match_operand:SI 4 "const_int_operand" ""))
2418           (match_operator:SI 9 "logical_binary_operator"
2419            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2420                          (match_operand:SI 6 "const_int_operand" ""))
2421             (match_operand:SI 7 "s_register_operand" "")])]))
2422    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2423   "TARGET_ARM
2424    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2425    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2426   [(set (match_dup 8)
2427         (match_op_dup 1
2428          [(ashift:SI (match_dup 2) (match_dup 4))
2429           (match_dup 5)]))
2430    (set (match_dup 0)
2431         (match_op_dup 1
2432          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2433           (match_dup 7)]))]
2434   "
2435   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2438 (define_split
2439   [(set (match_operand:SI 0 "s_register_operand" "")
2440         (match_operator:SI 1 "logical_binary_operator"
2441          [(match_operator:SI 9 "logical_binary_operator"
2442            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2443                          (match_operand:SI 6 "const_int_operand" ""))
2444             (match_operand:SI 7 "s_register_operand" "")])
2445           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2446                            (match_operand:SI 3 "const_int_operand" "")
2447                            (match_operand:SI 4 "const_int_operand" ""))]))
2448    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2449   "TARGET_ARM
2450    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2451    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2452   [(set (match_dup 8)
2453         (match_op_dup 1
2454          [(ashift:SI (match_dup 2) (match_dup 4))
2455           (match_dup 5)]))
2456    (set (match_dup 0)
2457         (match_op_dup 1
2458          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2459           (match_dup 7)]))]
2460   "
2461   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2465 ;; Minimum and maximum insns
2467 (define_insn "smaxsi3"
2468   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2469         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2470                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2471    (clobber (reg:CC CC_REGNUM))]
2472   "TARGET_ARM"
2473   "@
2474    cmp\\t%1, %2\;movlt\\t%0, %2
2475    cmp\\t%1, %2\;movge\\t%0, %1
2476    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2477   [(set_attr "conds" "clob")
2478    (set_attr "length" "8,8,12")]
2481 (define_insn "sminsi3"
2482   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2483         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2484                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2485    (clobber (reg:CC CC_REGNUM))]
2486   "TARGET_ARM"
2487   "@
2488    cmp\\t%1, %2\;movge\\t%0, %2
2489    cmp\\t%1, %2\;movlt\\t%0, %1
2490    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2491   [(set_attr "conds" "clob")
2492    (set_attr "length" "8,8,12")]
2495 (define_insn "umaxsi3"
2496   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2497         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2498                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2499    (clobber (reg:CC CC_REGNUM))]
2500   "TARGET_ARM"
2501   "@
2502    cmp\\t%1, %2\;movcc\\t%0, %2
2503    cmp\\t%1, %2\;movcs\\t%0, %1
2504    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2505   [(set_attr "conds" "clob")
2506    (set_attr "length" "8,8,12")]
2509 (define_insn "uminsi3"
2510   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2511         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2512                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2513    (clobber (reg:CC CC_REGNUM))]
2514   "TARGET_ARM"
2515   "@
2516    cmp\\t%1, %2\;movcs\\t%0, %2
2517    cmp\\t%1, %2\;movcc\\t%0, %1
2518    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2519   [(set_attr "conds" "clob")
2520    (set_attr "length" "8,8,12")]
2523 (define_insn "*store_minmaxsi"
2524   [(set (match_operand:SI 0 "memory_operand" "=m")
2525         (match_operator:SI 3 "minmax_operator"
2526          [(match_operand:SI 1 "s_register_operand" "r")
2527           (match_operand:SI 2 "s_register_operand" "r")]))
2528    (clobber (reg:CC CC_REGNUM))]
2529   "TARGET_ARM"
2530   "*
2531   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2532                                 operands[1], operands[2]);
2533   output_asm_insn (\"cmp\\t%1, %2\", operands);
2534   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2535   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2536   return \"\";
2537   "
2538   [(set_attr "conds" "clob")
2539    (set_attr "length" "12")
2540    (set_attr "type" "store1")]
2543 ; Reject the frame pointer in operand[1], since reloading this after
2544 ; it has been eliminated can cause carnage.
2545 (define_insn "*minmax_arithsi"
2546   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2547         (match_operator:SI 4 "shiftable_operator"
2548          [(match_operator:SI 5 "minmax_operator"
2549            [(match_operand:SI 2 "s_register_operand" "r,r")
2550             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2551           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2552    (clobber (reg:CC CC_REGNUM))]
2553   "TARGET_ARM
2554    && (GET_CODE (operands[1]) != REG
2555        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2556            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2557   "*
2558   {
2559     enum rtx_code code = GET_CODE (operands[4]);
2561     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2562                                   operands[2], operands[3]);
2563     output_asm_insn (\"cmp\\t%2, %3\", operands);
2564     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2565     if (which_alternative != 0 || operands[3] != const0_rtx
2566         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2567       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2568     return \"\";
2569   }"
2570   [(set_attr "conds" "clob")
2571    (set_attr "length" "12")]
2575 ;; Shift and rotation insns
2577 (define_expand "ashldi3"
2578   [(set (match_operand:DI            0 "s_register_operand" "")
2579         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2580                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2581   "TARGET_ARM"
2582   "
2583   if (GET_CODE (operands[2]) == CONST_INT)
2584     {
2585       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2586         {
2587           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2588           DONE;
2589         }
2590         /* Ideally we shouldn't fail here if we could know that operands[1] 
2591            ends up already living in an iwmmxt register. Otherwise it's
2592            cheaper to have the alternate code being generated than moving
2593            values to iwmmxt regs and back.  */
2594         FAIL;
2595     }
2596   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2597     FAIL;
2598   "
2601 (define_insn "arm_ashldi3_1bit"
2602   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2603         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2604                    (const_int 1)))
2605    (clobber (reg:CC CC_REGNUM))]
2606   "TARGET_ARM"
2607   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2608   [(set_attr "conds" "clob")
2609    (set_attr "length" "8")]
2612 (define_expand "ashlsi3"
2613   [(set (match_operand:SI            0 "s_register_operand" "")
2614         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2615                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2616   "TARGET_EITHER"
2617   "
2618   if (GET_CODE (operands[2]) == CONST_INT
2619       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2620     {
2621       emit_insn (gen_movsi (operands[0], const0_rtx));
2622       DONE;
2623     }
2624   "
2627 (define_insn "*thumb_ashlsi3"
2628   [(set (match_operand:SI            0 "register_operand" "=l,l")
2629         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2630                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2631   "TARGET_THUMB"
2632   "lsl\\t%0, %1, %2"
2633   [(set_attr "length" "2")]
2636 (define_expand "ashrdi3"
2637   [(set (match_operand:DI              0 "s_register_operand" "")
2638         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2639                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2640   "TARGET_ARM"
2641   "
2642   if (GET_CODE (operands[2]) == CONST_INT)
2643     {
2644       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2645         {
2646           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2647           DONE;
2648         }
2649         /* Ideally we shouldn't fail here if we could know that operands[1] 
2650            ends up already living in an iwmmxt register. Otherwise it's
2651            cheaper to have the alternate code being generated than moving
2652            values to iwmmxt regs and back.  */
2653         FAIL;
2654     }
2655   else if (!TARGET_REALLY_IWMMXT)
2656     FAIL;
2657   "
2660 (define_insn "arm_ashrdi3_1bit"
2661   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2662         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2663                      (const_int 1)))
2664    (clobber (reg:CC CC_REGNUM))]
2665   "TARGET_ARM"
2666   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2667   [(set_attr "conds" "clob")
2668    (set_attr "length" "8")]
2671 (define_expand "ashrsi3"
2672   [(set (match_operand:SI              0 "s_register_operand" "")
2673         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2674                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2675   "TARGET_EITHER"
2676   "
2677   if (GET_CODE (operands[2]) == CONST_INT
2678       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2679     operands[2] = GEN_INT (31);
2680   "
2683 (define_insn "*thumb_ashrsi3"
2684   [(set (match_operand:SI              0 "register_operand" "=l,l")
2685         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2686                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2687   "TARGET_THUMB"
2688   "asr\\t%0, %1, %2"
2689   [(set_attr "length" "2")]
2692 (define_expand "lshrdi3"
2693   [(set (match_operand:DI              0 "s_register_operand" "")
2694         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2695                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2696   "TARGET_ARM"
2697   "
2698   if (GET_CODE (operands[2]) == CONST_INT)
2699     {
2700       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2701         {
2702           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2703           DONE;
2704         }
2705         /* Ideally we shouldn't fail here if we could know that operands[1] 
2706            ends up already living in an iwmmxt register. Otherwise it's
2707            cheaper to have the alternate code being generated than moving
2708            values to iwmmxt regs and back.  */
2709         FAIL;
2710     }
2711   else if (!TARGET_REALLY_IWMMXT)
2712     FAIL;
2713   "
2716 (define_insn "arm_lshrdi3_1bit"
2717   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2718         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2719                      (const_int 1)))
2720    (clobber (reg:CC CC_REGNUM))]
2721   "TARGET_ARM"
2722   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2723   [(set_attr "conds" "clob")
2724    (set_attr "length" "8")]
2727 (define_expand "lshrsi3"
2728   [(set (match_operand:SI              0 "s_register_operand" "")
2729         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2730                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2731   "TARGET_EITHER"
2732   "
2733   if (GET_CODE (operands[2]) == CONST_INT
2734       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2735     {
2736       emit_insn (gen_movsi (operands[0], const0_rtx));
2737       DONE;
2738     }
2739   "
2742 (define_insn "*thumb_lshrsi3"
2743   [(set (match_operand:SI              0 "register_operand" "=l,l")
2744         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2745                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2746   "TARGET_THUMB"
2747   "lsr\\t%0, %1, %2"
2748   [(set_attr "length" "2")]
2751 (define_expand "rotlsi3"
2752   [(set (match_operand:SI              0 "s_register_operand" "")
2753         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2754                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2755   "TARGET_ARM"
2756   "
2757   if (GET_CODE (operands[2]) == CONST_INT)
2758     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2759   else
2760     {
2761       rtx reg = gen_reg_rtx (SImode);
2762       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2763       operands[2] = reg;
2764     }
2765   "
2768 (define_expand "rotrsi3"
2769   [(set (match_operand:SI              0 "s_register_operand" "")
2770         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2771                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2772   "TARGET_EITHER"
2773   "
2774   if (TARGET_ARM)
2775     {
2776       if (GET_CODE (operands[2]) == CONST_INT
2777           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2778         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2779     }
2780   else /* TARGET_THUMB */
2781     {
2782       if (GET_CODE (operands [2]) == CONST_INT)
2783         operands [2] = force_reg (SImode, operands[2]);
2784     }
2785   "
2788 (define_insn "*thumb_rotrsi3"
2789   [(set (match_operand:SI              0 "register_operand" "=l")
2790         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2791                      (match_operand:SI 2 "register_operand" "l")))]
2792   "TARGET_THUMB"
2793   "ror\\t%0, %0, %2"
2794   [(set_attr "length" "2")]
2797 (define_insn "*arm_shiftsi3"
2798   [(set (match_operand:SI   0 "s_register_operand" "=r")
2799         (match_operator:SI  3 "shift_operator"
2800          [(match_operand:SI 1 "s_register_operand"  "r")
2801           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2802   "TARGET_ARM"
2803   "mov%?\\t%0, %1%S3"
2804   [(set_attr "predicable" "yes")
2805    (set_attr "shift" "1")
2806    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2807                       (const_string "alu_shift")
2808                       (const_string "alu_shift_reg")))]
2811 (define_insn "*shiftsi3_compare0"
2812   [(set (reg:CC_NOOV CC_REGNUM)
2813         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2814                           [(match_operand:SI 1 "s_register_operand" "r")
2815                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2816                          (const_int 0)))
2817    (set (match_operand:SI 0 "s_register_operand" "=r")
2818         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2819   "TARGET_ARM"
2820   "mov%?s\\t%0, %1%S3"
2821   [(set_attr "conds" "set")
2822    (set_attr "shift" "1")
2823    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2824                       (const_string "alu_shift")
2825                       (const_string "alu_shift_reg")))]
2828 (define_insn "*shiftsi3_compare0_scratch"
2829   [(set (reg:CC_NOOV CC_REGNUM)
2830         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2831                           [(match_operand:SI 1 "s_register_operand" "r")
2832                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2833                          (const_int 0)))
2834    (clobber (match_scratch:SI 0 "=r"))]
2835   "TARGET_ARM"
2836   "mov%?s\\t%0, %1%S3"
2837   [(set_attr "conds" "set")
2838    (set_attr "shift" "1")]
2841 (define_insn "*notsi_shiftsi"
2842   [(set (match_operand:SI 0 "s_register_operand" "=r")
2843         (not:SI (match_operator:SI 3 "shift_operator"
2844                  [(match_operand:SI 1 "s_register_operand" "r")
2845                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2846   "TARGET_ARM"
2847   "mvn%?\\t%0, %1%S3"
2848   [(set_attr "predicable" "yes")
2849    (set_attr "shift" "1")
2850    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2851                       (const_string "alu_shift")
2852                       (const_string "alu_shift_reg")))]
2855 (define_insn "*notsi_shiftsi_compare0"
2856   [(set (reg:CC_NOOV CC_REGNUM)
2857         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2858                           [(match_operand:SI 1 "s_register_operand" "r")
2859                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2860                          (const_int 0)))
2861    (set (match_operand:SI 0 "s_register_operand" "=r")
2862         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2863   "TARGET_ARM"
2864   "mvn%?s\\t%0, %1%S3"
2865   [(set_attr "conds" "set")
2866    (set_attr "shift" "1")
2867    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2868                       (const_string "alu_shift")
2869                       (const_string "alu_shift_reg")))]
2872 (define_insn "*not_shiftsi_compare0_scratch"
2873   [(set (reg:CC_NOOV CC_REGNUM)
2874         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2875                           [(match_operand:SI 1 "s_register_operand" "r")
2876                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2877                          (const_int 0)))
2878    (clobber (match_scratch:SI 0 "=r"))]
2879   "TARGET_ARM"
2880   "mvn%?s\\t%0, %1%S3"
2881   [(set_attr "conds" "set")
2882    (set_attr "shift" "1")
2883    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2884                       (const_string "alu_shift")
2885                       (const_string "alu_shift_reg")))]
2888 ;; We don't really have extzv, but defining this using shifts helps
2889 ;; to reduce register pressure later on.
2891 (define_expand "extzv"
2892   [(set (match_dup 4)
2893         (ashift:SI (match_operand:SI   1 "register_operand" "")
2894                    (match_operand:SI   2 "const_int_operand" "")))
2895    (set (match_operand:SI              0 "register_operand" "")
2896         (lshiftrt:SI (match_dup 4)
2897                      (match_operand:SI 3 "const_int_operand" "")))]
2898   "TARGET_THUMB"
2899   "
2900   {
2901     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2902     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2903     
2904     operands[3] = GEN_INT (rshift);
2905     
2906     if (lshift == 0)
2907       {
2908         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2909         DONE;
2910       }
2911       
2912     operands[2] = GEN_INT (lshift);
2913     operands[4] = gen_reg_rtx (SImode);
2914   }"
2918 ;; Unary arithmetic insns
2920 (define_expand "negdi2"
2921  [(parallel
2922    [(set (match_operand:DI          0 "s_register_operand" "")
2923           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2924     (clobber (reg:CC CC_REGNUM))])]
2925   "TARGET_EITHER"
2926   "
2927   if (TARGET_THUMB)
2928     {
2929       if (GET_CODE (operands[1]) != REG)
2930         operands[1] = force_reg (SImode, operands[1]);
2931      }
2932   "
2935 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2936 ;; The second alternative is to allow the common case of a *full* overlap.
2937 (define_insn "*arm_negdi2"
2938   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2939         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2940    (clobber (reg:CC CC_REGNUM))]
2941   "TARGET_ARM"
2942   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2943   [(set_attr "conds" "clob")
2944    (set_attr "length" "8")]
2947 (define_insn "*thumb_negdi2"
2948   [(set (match_operand:DI         0 "register_operand" "=&l")
2949         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2950    (clobber (reg:CC CC_REGNUM))]
2951   "TARGET_THUMB"
2952   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2953   [(set_attr "length" "6")]
2956 (define_expand "negsi2"
2957   [(set (match_operand:SI         0 "s_register_operand" "")
2958         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2959   "TARGET_EITHER"
2960   ""
2963 (define_insn "*arm_negsi2"
2964   [(set (match_operand:SI         0 "s_register_operand" "=r")
2965         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2966   "TARGET_ARM"
2967   "rsb%?\\t%0, %1, #0"
2968   [(set_attr "predicable" "yes")]
2971 (define_insn "*thumb_negsi2"
2972   [(set (match_operand:SI         0 "register_operand" "=l")
2973         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2974   "TARGET_THUMB"
2975   "neg\\t%0, %1"
2976   [(set_attr "length" "2")]
2979 (define_expand "negsf2"
2980   [(set (match_operand:SF         0 "s_register_operand" "")
2981         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2982   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2983   ""
2986 (define_expand "negdf2"
2987   [(set (match_operand:DF         0 "s_register_operand" "")
2988         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2989   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2990   "")
2992 ;; abssi2 doesn't really clobber the condition codes if a different register
2993 ;; is being set.  To keep things simple, assume during rtl manipulations that
2994 ;; it does, but tell the final scan operator the truth.  Similarly for
2995 ;; (neg (abs...))
2997 (define_expand "abssi2"
2998   [(parallel
2999     [(set (match_operand:SI         0 "s_register_operand" "")
3000           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
3001      (clobber (reg:CC CC_REGNUM))])]
3002   "TARGET_ARM"
3003   "")
3005 (define_insn "*arm_abssi2"
3006   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
3007         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
3008    (clobber (reg:CC CC_REGNUM))]
3009   "TARGET_ARM"
3010   "@
3011    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
3012    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
3013   [(set_attr "conds" "clob,*")
3014    (set_attr "shift" "1")
3015    ;; predicable can't be set based on the variant, so left as no
3016    (set_attr "length" "8")]
3019 (define_insn "*neg_abssi2"
3020   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
3021         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
3022    (clobber (reg:CC CC_REGNUM))]
3023   "TARGET_ARM"
3024   "@
3025    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
3026    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
3027   [(set_attr "conds" "clob,*")
3028    (set_attr "shift" "1")
3029    ;; predicable can't be set based on the variant, so left as no
3030    (set_attr "length" "8")]
3033 (define_expand "abssf2"
3034   [(set (match_operand:SF         0 "s_register_operand" "")
3035         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
3036   "TARGET_ARM && TARGET_HARD_FLOAT"
3037   "")
3039 (define_expand "absdf2"
3040   [(set (match_operand:DF         0 "s_register_operand" "")
3041         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
3042   "TARGET_ARM && TARGET_HARD_FLOAT"
3043   "")
3045 (define_expand "sqrtsf2"
3046   [(set (match_operand:SF 0 "s_register_operand" "")
3047         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
3048   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3049   "")
3051 (define_expand "sqrtdf2"
3052   [(set (match_operand:DF 0 "s_register_operand" "")
3053         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
3054   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
3055   "")
3057 (define_insn_and_split "one_cmpldi2"
3058   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
3059         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
3060   "TARGET_ARM"
3061   "#"
3062   "TARGET_ARM && reload_completed"
3063   [(set (match_dup 0) (not:SI (match_dup 1)))
3064    (set (match_dup 2) (not:SI (match_dup 3)))]
3065   "
3066   {
3067     operands[2] = gen_highpart (SImode, operands[0]);
3068     operands[0] = gen_lowpart (SImode, operands[0]);
3069     operands[3] = gen_highpart (SImode, operands[1]);
3070     operands[1] = gen_lowpart (SImode, operands[1]);
3071   }"
3072   [(set_attr "length" "8")
3073    (set_attr "predicable" "yes")]
3076 (define_expand "one_cmplsi2"
3077   [(set (match_operand:SI         0 "s_register_operand" "")
3078         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3079   "TARGET_EITHER"
3080   ""
3083 (define_insn "*arm_one_cmplsi2"
3084   [(set (match_operand:SI         0 "s_register_operand" "=r")
3085         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3086   "TARGET_ARM"
3087   "mvn%?\\t%0, %1"
3088   [(set_attr "predicable" "yes")]
3091 (define_insn "*thumb_one_cmplsi2"
3092   [(set (match_operand:SI         0 "register_operand" "=l")
3093         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3094   "TARGET_THUMB"
3095   "mvn\\t%0, %1"
3096   [(set_attr "length" "2")]
3099 (define_insn "*notsi_compare0"
3100   [(set (reg:CC_NOOV CC_REGNUM)
3101         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3102                          (const_int 0)))
3103    (set (match_operand:SI 0 "s_register_operand" "=r")
3104         (not:SI (match_dup 1)))]
3105   "TARGET_ARM"
3106   "mvn%?s\\t%0, %1"
3107   [(set_attr "conds" "set")]
3110 (define_insn "*notsi_compare0_scratch"
3111   [(set (reg:CC_NOOV CC_REGNUM)
3112         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3113                          (const_int 0)))
3114    (clobber (match_scratch:SI 0 "=r"))]
3115   "TARGET_ARM"
3116   "mvn%?s\\t%0, %1"
3117   [(set_attr "conds" "set")]
3120 ;; Fixed <--> Floating conversion insns
3122 (define_expand "floatsisf2"
3123   [(set (match_operand:SF           0 "s_register_operand" "")
3124         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3125   "TARGET_ARM && TARGET_HARD_FLOAT"
3126   "
3127   if (TARGET_MAVERICK)
3128     {
3129       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3130       DONE;
3131     }
3134 (define_expand "floatsidf2"
3135   [(set (match_operand:DF           0 "s_register_operand" "")
3136         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3137   "TARGET_ARM && TARGET_HARD_FLOAT"
3138   "
3139   if (TARGET_MAVERICK)
3140     {
3141       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3142       DONE;
3143     }
3146 (define_expand "fix_truncsfsi2"
3147   [(set (match_operand:SI         0 "s_register_operand" "")
3148         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3149   "TARGET_ARM && TARGET_HARD_FLOAT"
3150   "
3151   if (TARGET_MAVERICK)
3152     {
3153       if (!cirrus_fp_register (operands[0], SImode))
3154         operands[0] = force_reg (SImode, operands[0]);
3155       if (!cirrus_fp_register (operands[1], SFmode))
3156         operands[1] = force_reg (SFmode, operands[0]);
3157       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3158       DONE;
3159     }
3162 (define_expand "fix_truncdfsi2"
3163   [(set (match_operand:SI         0 "s_register_operand" "")
3164         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3165   "TARGET_ARM && TARGET_HARD_FLOAT"
3166   "
3167   if (TARGET_MAVERICK)
3168     {
3169       if (!cirrus_fp_register (operands[1], DFmode))
3170         operands[1] = force_reg (DFmode, operands[0]);
3171       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3172       DONE;
3173     }
3176 ;; Truncation insns
3178 (define_expand "truncdfsf2"
3179   [(set (match_operand:SF  0 "s_register_operand" "")
3180         (float_truncate:SF
3181          (match_operand:DF 1 "s_register_operand" "")))]
3182   "TARGET_ARM && TARGET_HARD_FLOAT"
3183   ""
3186 ;; Zero and sign extension instructions.
3188 (define_insn "zero_extendsidi2"
3189   [(set (match_operand:DI 0 "s_register_operand" "=r")
3190         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3191   "TARGET_ARM"
3192   "*
3193     if (REGNO (operands[1])
3194         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3195       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3196     return \"mov%?\\t%R0, #0\";
3197   "
3198   [(set_attr "length" "8")
3199    (set_attr "predicable" "yes")]
3202 (define_insn "zero_extendqidi2"
3203   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3204         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3205   "TARGET_ARM"
3206   "@
3207    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3208    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3209   [(set_attr "length" "8")
3210    (set_attr "predicable" "yes")
3211    (set_attr "type" "*,load_byte")
3212    (set_attr "pool_range" "*,4092")
3213    (set_attr "neg_pool_range" "*,4084")]
3216 (define_insn "extendsidi2"
3217   [(set (match_operand:DI 0 "s_register_operand" "=r")
3218         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3219   "TARGET_ARM"
3220   "*
3221     if (REGNO (operands[1])
3222         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3223       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3224     return \"mov%?\\t%R0, %Q0, asr #31\";
3225   "
3226   [(set_attr "length" "8")
3227    (set_attr "shift" "1")
3228    (set_attr "predicable" "yes")]
3231 (define_expand "zero_extendhisi2"
3232   [(set (match_dup 2)
3233         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3234                    (const_int 16)))
3235    (set (match_operand:SI 0 "s_register_operand" "")
3236         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3237   "TARGET_EITHER"
3238   "
3239   {
3240     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3241       {
3242         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3243                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3244         DONE;
3245       }
3247     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3248       {
3249         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3250         DONE;
3251       }
3253     if (!s_register_operand (operands[1], HImode))
3254       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3256     if (arm_arch6)
3257       {
3258         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3259                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3260         DONE;
3261       }
3263     operands[1] = gen_lowpart (SImode, operands[1]);
3264     operands[2] = gen_reg_rtx (SImode);
3265   }"
3268 (define_insn "*thumb_zero_extendhisi2"
3269   [(set (match_operand:SI 0 "register_operand" "=l")
3270         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3271   "TARGET_THUMB && !arm_arch6"
3272   "*
3273   rtx mem = XEXP (operands[1], 0);
3275   if (GET_CODE (mem) == CONST)
3276     mem = XEXP (mem, 0);
3277     
3278   if (GET_CODE (mem) == LABEL_REF)
3279     return \"ldr\\t%0, %1\";
3280     
3281   if (GET_CODE (mem) == PLUS)
3282     {
3283       rtx a = XEXP (mem, 0);
3284       rtx b = XEXP (mem, 1);
3286       /* This can happen due to bugs in reload.  */
3287       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3288         {
3289           rtx ops[2];
3290           ops[0] = operands[0];
3291           ops[1] = a;
3292       
3293           output_asm_insn (\"mov        %0, %1\", ops);
3295           XEXP (mem, 0) = operands[0];
3296        }
3298       else if (   GET_CODE (a) == LABEL_REF
3299                && GET_CODE (b) == CONST_INT)
3300         return \"ldr\\t%0, %1\";
3301     }
3302     
3303   return \"ldrh\\t%0, %1\";
3304   "
3305   [(set_attr "length" "4")
3306    (set_attr "type" "load_byte")
3307    (set_attr "pool_range" "60")]
3310 (define_insn "*thumb_zero_extendhisi2_v6"
3311   [(set (match_operand:SI 0 "register_operand" "=l,l")
3312         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3313   "TARGET_THUMB && arm_arch6"
3314   "*
3315   rtx mem;
3317   if (which_alternative == 0)
3318     return \"uxth\\t%0, %1\";
3320   mem = XEXP (operands[1], 0);
3322   if (GET_CODE (mem) == CONST)
3323     mem = XEXP (mem, 0);
3324     
3325   if (GET_CODE (mem) == LABEL_REF)
3326     return \"ldr\\t%0, %1\";
3327     
3328   if (GET_CODE (mem) == PLUS)
3329     {
3330       rtx a = XEXP (mem, 0);
3331       rtx b = XEXP (mem, 1);
3333       /* This can happen due to bugs in reload.  */
3334       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3335         {
3336           rtx ops[2];
3337           ops[0] = operands[0];
3338           ops[1] = a;
3339       
3340           output_asm_insn (\"mov        %0, %1\", ops);
3342           XEXP (mem, 0) = operands[0];
3343        }
3345       else if (   GET_CODE (a) == LABEL_REF
3346                && GET_CODE (b) == CONST_INT)
3347         return \"ldr\\t%0, %1\";
3348     }
3349     
3350   return \"ldrh\\t%0, %1\";
3351   "
3352   [(set_attr "length" "2,4")
3353    (set_attr "type" "alu_shift,load_byte")
3354    (set_attr "pool_range" "*,60")]
3357 (define_insn "*arm_zero_extendhisi2"
3358   [(set (match_operand:SI 0 "s_register_operand" "=r")
3359         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3360   "TARGET_ARM && arm_arch4 && !arm_arch6"
3361   "ldr%?h\\t%0, %1"
3362   [(set_attr "type" "load_byte")
3363    (set_attr "predicable" "yes")
3364    (set_attr "pool_range" "256")
3365    (set_attr "neg_pool_range" "244")]
3368 (define_insn "*arm_zero_extendhisi2_v6"
3369   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3370         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3371   "TARGET_ARM && arm_arch6"
3372   "@
3373    uxth%?\\t%0, %1
3374    ldr%?h\\t%0, %1"
3375   [(set_attr "type" "alu_shift,load_byte")
3376    (set_attr "predicable" "yes")
3377    (set_attr "pool_range" "*,256")
3378    (set_attr "neg_pool_range" "*,244")]
3381 (define_insn "*arm_zero_extendhisi2addsi"
3382   [(set (match_operand:SI 0 "s_register_operand" "=r")
3383         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3384                  (match_operand:SI 2 "s_register_operand" "r")))]
3385   "TARGET_ARM && arm_arch6"
3386   "uxtah%?\\t%0, %2, %1"
3387   [(set_attr "type" "alu_shift")
3388    (set_attr "predicable" "yes")]
3391 (define_split
3392   [(set (match_operand:SI 0 "s_register_operand" "")
3393         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3394    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3395   "TARGET_ARM && (!arm_arch4)"
3396   [(set (match_dup 2) (match_dup 1))
3397    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3398   "
3399   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3400     FAIL;
3401   "
3404 (define_split
3405   [(set (match_operand:SI 0 "s_register_operand" "")
3406         (match_operator:SI 3 "shiftable_operator"
3407          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3408           (match_operand:SI 4 "s_register_operand" "")]))
3409    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3410   "TARGET_ARM && (!arm_arch4)"
3411   [(set (match_dup 2) (match_dup 1))
3412    (set (match_dup 0)
3413         (match_op_dup 3
3414          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3415   "
3416   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3417     FAIL;
3418   "
3421 (define_expand "zero_extendqisi2"
3422   [(set (match_operand:SI 0 "s_register_operand" "")
3423         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3424   "TARGET_EITHER"
3425   "
3426   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3427     {
3428       if (TARGET_ARM)
3429         {
3430           emit_insn (gen_andsi3 (operands[0],
3431                                  gen_lowpart (SImode, operands[1]),
3432                                  GEN_INT (255)));
3433         }
3434       else /* TARGET_THUMB */
3435         {
3436           rtx temp = gen_reg_rtx (SImode);
3437           rtx ops[3];
3438           
3439           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3440           operands[1] = gen_lowpart (SImode, operands[1]);
3442           ops[0] = temp;
3443           ops[1] = operands[1];
3444           ops[2] = GEN_INT (24);
3446           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3447                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3448           
3449           ops[0] = operands[0];
3450           ops[1] = temp;
3451           ops[2] = GEN_INT (24);
3453           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3454                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3455         }
3456       DONE;
3457     }
3458   "
3461 (define_insn "*thumb_zero_extendqisi2"
3462   [(set (match_operand:SI 0 "register_operand" "=l")
3463         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3464   "TARGET_THUMB && !arm_arch6"
3465   "ldrb\\t%0, %1"
3466   [(set_attr "length" "2")
3467    (set_attr "type" "load_byte")
3468    (set_attr "pool_range" "32")]
3471 (define_insn "*thumb_zero_extendqisi2_v6"
3472   [(set (match_operand:SI 0 "register_operand" "=l,l")
3473         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3474   "TARGET_THUMB && arm_arch6"
3475   "@
3476    uxtb\\t%0, %1
3477    ldrb\\t%0, %1"
3478   [(set_attr "length" "2,2")
3479    (set_attr "type" "alu_shift,load_byte")
3480    (set_attr "pool_range" "*,32")]
3483 (define_insn "*arm_zero_extendqisi2"
3484   [(set (match_operand:SI 0 "s_register_operand" "=r")
3485         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3486   "TARGET_ARM && !arm_arch6"
3487   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3488   [(set_attr "type" "load_byte")
3489    (set_attr "predicable" "yes")
3490    (set_attr "pool_range" "4096")
3491    (set_attr "neg_pool_range" "4084")]
3494 (define_insn "*arm_zero_extendqisi2_v6"
3495   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3496         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3497   "TARGET_ARM && arm_arch6"
3498   "@
3499    uxtb%?\\t%0, %1
3500    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3501   [(set_attr "type" "alu_shift,load_byte")
3502    (set_attr "predicable" "yes")
3503    (set_attr "pool_range" "*,4096")
3504    (set_attr "neg_pool_range" "*,4084")]
3507 (define_insn "*arm_zero_extendqisi2addsi"
3508   [(set (match_operand:SI 0 "s_register_operand" "=r")
3509         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3510                  (match_operand:SI 2 "s_register_operand" "r")))]
3511   "TARGET_ARM && arm_arch6"
3512   "uxtab%?\\t%0, %2, %1"
3513   [(set_attr "predicable" "yes")
3514    (set_attr "type" "alu_shift")]
3517 (define_split
3518   [(set (match_operand:SI 0 "s_register_operand" "")
3519         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3520    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3521   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3522   [(set (match_dup 2) (match_dup 1))
3523    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3524   ""
3527 (define_insn "*compareqi_eq0"
3528   [(set (reg:CC_Z CC_REGNUM)
3529         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3530                          (const_int 0)))]
3531   "TARGET_ARM"
3532   "tst\\t%0, #255"
3533   [(set_attr "conds" "set")]
3536 (define_expand "extendhisi2"
3537   [(set (match_dup 2)
3538         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3539                    (const_int 16)))
3540    (set (match_operand:SI 0 "s_register_operand" "")
3541         (ashiftrt:SI (match_dup 2)
3542                      (const_int 16)))]
3543   "TARGET_EITHER"
3544   "
3545   {
3546     if (GET_CODE (operands[1]) == MEM)
3547       {
3548         if (TARGET_THUMB)
3549           {
3550             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3551             DONE;
3552           }
3553         else if (arm_arch4)
3554           {
3555             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3556                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3557             DONE;
3558           }
3559       }
3561     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3562       {
3563         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3564         DONE;
3565       }
3567     if (!s_register_operand (operands[1], HImode))
3568       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3570     if (arm_arch6)
3571       {
3572         if (TARGET_THUMB)
3573           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3574         else
3575           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3576                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3578         DONE;
3579       }
3581     operands[1] = gen_lowpart (SImode, operands[1]);
3582     operands[2] = gen_reg_rtx (SImode);
3583   }"
3586 (define_insn "thumb_extendhisi2"
3587   [(set (match_operand:SI 0 "register_operand" "=l")
3588         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3589    (clobber (match_scratch:SI 2 "=&l"))]
3590   "TARGET_THUMB && !arm_arch6"
3591   "*
3592   {
3593     rtx ops[4];
3594     rtx mem = XEXP (operands[1], 0);
3596     /* This code used to try to use 'V', and fix the address only if it was
3597        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3598        range of QImode offsets, and offsettable_address_p does a QImode
3599        address check.  */
3600        
3601     if (GET_CODE (mem) == CONST)
3602       mem = XEXP (mem, 0);
3603     
3604     if (GET_CODE (mem) == LABEL_REF)
3605       return \"ldr\\t%0, %1\";
3606     
3607     if (GET_CODE (mem) == PLUS)
3608       {
3609         rtx a = XEXP (mem, 0);
3610         rtx b = XEXP (mem, 1);
3612         if (GET_CODE (a) == LABEL_REF
3613             && GET_CODE (b) == CONST_INT)
3614           return \"ldr\\t%0, %1\";
3616         if (GET_CODE (b) == REG)
3617           return \"ldrsh\\t%0, %1\";
3618           
3619         ops[1] = a;
3620         ops[2] = b;
3621       }
3622     else
3623       {
3624         ops[1] = mem;
3625         ops[2] = const0_rtx;
3626       }
3627       
3628     if (GET_CODE (ops[1]) != REG)
3629       {
3630         debug_rtx (ops[1]);
3631         abort ();
3632       }
3634     ops[0] = operands[0];
3635     ops[3] = operands[2];
3636     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3637     return \"\";
3638   }"
3639   [(set_attr "length" "4")
3640    (set_attr "type" "load_byte")
3641    (set_attr "pool_range" "1020")]
3644 ;; We used to have an early-clobber on the scratch register here.
3645 ;; However, there's a bug somewhere in reload which means that this
3646 ;; can be partially ignored during spill allocation if the memory
3647 ;; address also needs reloading; this causes an abort later on when
3648 ;; we try to verify the operands.  Fortunately, we don't really need
3649 ;; the early-clobber: we can always use operand 0 if operand 2
3650 ;; overlaps the address.
3651 (define_insn "*thumb_extendhisi2_insn_v6"
3652   [(set (match_operand:SI 0 "register_operand" "=l,l")
3653         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3654    (clobber (match_scratch:SI 2 "=X,l"))]
3655   "TARGET_THUMB && arm_arch6"
3656   "*
3657   {
3658     rtx ops[4];
3659     rtx mem;
3661     if (which_alternative == 0)
3662       return \"sxth\\t%0, %1\";
3664     mem = XEXP (operands[1], 0);
3666     /* This code used to try to use 'V', and fix the address only if it was
3667        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3668        range of QImode offsets, and offsettable_address_p does a QImode
3669        address check.  */
3670        
3671     if (GET_CODE (mem) == CONST)
3672       mem = XEXP (mem, 0);
3673     
3674     if (GET_CODE (mem) == LABEL_REF)
3675       return \"ldr\\t%0, %1\";
3676     
3677     if (GET_CODE (mem) == PLUS)
3678       {
3679         rtx a = XEXP (mem, 0);
3680         rtx b = XEXP (mem, 1);
3682         if (GET_CODE (a) == LABEL_REF
3683             && GET_CODE (b) == CONST_INT)
3684           return \"ldr\\t%0, %1\";
3686         if (GET_CODE (b) == REG)
3687           return \"ldrsh\\t%0, %1\";
3688           
3689         ops[1] = a;
3690         ops[2] = b;
3691       }
3692     else
3693       {
3694         ops[1] = mem;
3695         ops[2] = const0_rtx;
3696       }
3697       
3698     if (GET_CODE (ops[1]) != REG)
3699       {
3700         debug_rtx (ops[1]);
3701         abort ();
3702       }
3704     ops[0] = operands[0];
3705     if (reg_mentioned_p (operands[2], ops[1]))
3706       ops[3] = ops[0];
3707     else
3708       ops[3] = operands[2];
3709     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3710     return \"\";
3711   }"
3712   [(set_attr "length" "2,4")
3713    (set_attr "type" "alu_shift,load_byte")
3714    (set_attr "pool_range" "*,1020")]
3717 (define_expand "extendhisi2_mem"
3718   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3719    (set (match_dup 3)
3720         (zero_extend:SI (match_dup 7)))
3721    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3722    (set (match_operand:SI 0 "" "")
3723         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3724   "TARGET_ARM"
3725   "
3726   {
3727     rtx mem1, mem2;
3728     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3730     mem1 = gen_rtx_MEM (QImode, addr);
3731     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3732     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3733     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3734     operands[0] = gen_lowpart (SImode, operands[0]);
3735     operands[1] = mem1;
3736     operands[2] = gen_reg_rtx (SImode);
3737     operands[3] = gen_reg_rtx (SImode);
3738     operands[6] = gen_reg_rtx (SImode);
3739     operands[7] = mem2;
3741     if (BYTES_BIG_ENDIAN)
3742       {
3743         operands[4] = operands[2];
3744         operands[5] = operands[3];
3745       }
3746     else
3747       {
3748         operands[4] = operands[3];
3749         operands[5] = operands[2];
3750       }
3751   }"
3754 (define_insn "*arm_extendhisi2"
3755   [(set (match_operand:SI 0 "s_register_operand" "=r")
3756         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3757   "TARGET_ARM && arm_arch4 && !arm_arch6"
3758   "ldr%?sh\\t%0, %1"
3759   [(set_attr "type" "load_byte")
3760    (set_attr "predicable" "yes")
3761    (set_attr "pool_range" "256")
3762    (set_attr "neg_pool_range" "244")]
3765 (define_insn "*arm_extendhisi2_v6"
3766   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3767         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3768   "TARGET_ARM && arm_arch6"
3769   "@
3770    sxth%?\\t%0, %1
3771    ldr%?sh\\t%0, %1"
3772   [(set_attr "type" "alu_shift,load_byte")
3773    (set_attr "predicable" "yes")
3774    (set_attr "pool_range" "*,256")
3775    (set_attr "neg_pool_range" "*,244")]
3778 (define_insn "*arm_extendhisi2addsi"
3779   [(set (match_operand:SI 0 "s_register_operand" "=r")
3780         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3781                  (match_operand:SI 2 "s_register_operand" "r")))]
3782   "TARGET_ARM && arm_arch6"
3783   "sxtah%?\\t%0, %2, %1"
3786 (define_split
3787   [(set (match_operand:SI                 0 "s_register_operand" "")
3788         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3789    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3790   "TARGET_ARM && (!arm_arch4)"
3791   [(set (match_dup 2) (match_dup 1))
3792    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3793   "
3794   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3795     FAIL;
3796   "
3799 (define_split
3800   [(set (match_operand:SI                   0 "s_register_operand" "")
3801         (match_operator:SI                  3 "shiftable_operator"
3802          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3803           (match_operand:SI                 4 "s_register_operand" "")]))
3804    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3805   "TARGET_ARM && (!arm_arch4)"
3806   [(set (match_dup 2) (match_dup 1))
3807    (set (match_dup 0)
3808         (match_op_dup 3
3809          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3810   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3811      FAIL;
3812   "
3815 (define_expand "extendqihi2"
3816   [(set (match_dup 2)
3817         (ashift:SI (match_operand:QI 1 "general_operand" "")
3818                    (const_int 24)))
3819    (set (match_operand:HI 0 "s_register_operand" "")
3820         (ashiftrt:SI (match_dup 2)
3821                      (const_int 24)))]
3822   "TARGET_ARM"
3823   "
3824   {
3825     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3826       {
3827         emit_insn (gen_rtx_SET (VOIDmode,
3828                                 operands[0],
3829                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3830         DONE;
3831       }
3832     if (!s_register_operand (operands[1], QImode))
3833       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3834     operands[0] = gen_lowpart (SImode, operands[0]);
3835     operands[1] = gen_lowpart (SImode, operands[1]);
3836     operands[2] = gen_reg_rtx (SImode);
3837   }"
3840 (define_insn "*extendqihi_insn"
3841   [(set (match_operand:HI 0 "s_register_operand" "=r")
3842         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3843   "TARGET_ARM && arm_arch4"
3844   "ldr%?sb\\t%0, %1"
3845   [(set_attr "type" "load_byte")
3846    (set_attr "predicable" "yes")
3847    (set_attr "pool_range" "256")
3848    (set_attr "neg_pool_range" "244")]
3851 (define_expand "extendqisi2"
3852   [(set (match_dup 2)
3853         (ashift:SI (match_operand:QI 1 "general_operand" "")
3854                    (const_int 24)))
3855    (set (match_operand:SI 0 "s_register_operand" "")
3856         (ashiftrt:SI (match_dup 2)
3857                      (const_int 24)))]
3858   "TARGET_EITHER"
3859   "
3860   {
3861     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3862       {
3863         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3864                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3865         DONE;
3866       }
3868     if (!s_register_operand (operands[1], QImode))
3869       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3871     if (arm_arch6)
3872       {
3873         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3874                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3875         DONE;
3876       }
3878     operands[1] = gen_lowpart (SImode, operands[1]);
3879     operands[2] = gen_reg_rtx (SImode);
3880   }"
3883 (define_insn "*arm_extendqisi"
3884   [(set (match_operand:SI 0 "s_register_operand" "=r")
3885         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3886   "TARGET_ARM && arm_arch4 && !arm_arch6"
3887   "ldr%?sb\\t%0, %1"
3888   [(set_attr "type" "load_byte")
3889    (set_attr "predicable" "yes")
3890    (set_attr "pool_range" "256")
3891    (set_attr "neg_pool_range" "244")]
3894 (define_insn "*arm_extendqisi_v6"
3895   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3896         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3897   "TARGET_ARM && arm_arch6"
3898   "@
3899    sxtb%?\\t%0, %1
3900    ldr%?sb\\t%0, %1"
3901   [(set_attr "type" "alu_shift,load_byte")
3902    (set_attr "predicable" "yes")
3903    (set_attr "pool_range" "*,256")
3904    (set_attr "neg_pool_range" "*,244")]
3907 (define_insn "*arm_extendqisi2addsi"
3908   [(set (match_operand:SI 0 "s_register_operand" "=r")
3909         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3910                  (match_operand:SI 2 "s_register_operand" "r")))]
3911   "TARGET_ARM && arm_arch6"
3912   "sxtab%?\\t%0, %2, %1"
3913   [(set_attr "type" "alu_shift")
3914    (set_attr "predicable" "yes")]
3917 (define_insn "*thumb_extendqisi2"
3918   [(set (match_operand:SI 0 "register_operand" "=l,l")
3919         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3920   "TARGET_THUMB && !arm_arch6"
3921   "*
3922   {
3923     rtx ops[3];
3924     rtx mem = XEXP (operands[1], 0);
3925     
3926     if (GET_CODE (mem) == CONST)
3927       mem = XEXP (mem, 0);
3928     
3929     if (GET_CODE (mem) == LABEL_REF)
3930       return \"ldr\\t%0, %1\";
3932     if (GET_CODE (mem) == PLUS
3933         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3934       return \"ldr\\t%0, %1\";
3935       
3936     if (which_alternative == 0)
3937       return \"ldrsb\\t%0, %1\";
3938       
3939     ops[0] = operands[0];
3940     
3941     if (GET_CODE (mem) == PLUS)
3942       {
3943         rtx a = XEXP (mem, 0);
3944         rtx b = XEXP (mem, 1);
3945         
3946         ops[1] = a;
3947         ops[2] = b;
3949         if (GET_CODE (a) == REG)
3950           {
3951             if (GET_CODE (b) == REG)
3952               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3953             else if (REGNO (a) == REGNO (ops[0]))
3954               {
3955                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3956                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3957                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3958               }
3959             else
3960               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3961           }
3962         else if (GET_CODE (b) != REG)
3963           abort ();
3964         else
3965           {
3966             if (REGNO (b) == REGNO (ops[0]))
3967               {
3968                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3969                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3970                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3971               }
3972             else
3973               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3974           }
3975       }
3976     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3977       {
3978         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3979         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3980         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3981       }
3982     else
3983       {
3984         ops[1] = mem;
3985         ops[2] = const0_rtx;
3986         
3987         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3988       }
3989     return \"\";
3990   }"
3991   [(set_attr "length" "2,6")
3992    (set_attr "type" "load_byte,load_byte")
3993    (set_attr "pool_range" "32,32")]
3996 (define_insn "*thumb_extendqisi2_v6"
3997   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3998         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3999   "TARGET_THUMB && arm_arch6"
4000   "*
4001   {
4002     rtx ops[3];
4003     rtx mem;
4005     if (which_alternative == 0)
4006       return \"sxtb\\t%0, %1\";
4008     mem = XEXP (operands[1], 0);
4009     
4010     if (GET_CODE (mem) == CONST)
4011       mem = XEXP (mem, 0);
4012     
4013     if (GET_CODE (mem) == LABEL_REF)
4014       return \"ldr\\t%0, %1\";
4016     if (GET_CODE (mem) == PLUS
4017         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
4018       return \"ldr\\t%0, %1\";
4019       
4020     if (which_alternative == 0)
4021       return \"ldrsb\\t%0, %1\";
4022       
4023     ops[0] = operands[0];
4024     
4025     if (GET_CODE (mem) == PLUS)
4026       {
4027         rtx a = XEXP (mem, 0);
4028         rtx b = XEXP (mem, 1);
4029         
4030         ops[1] = a;
4031         ops[2] = b;
4033         if (GET_CODE (a) == REG)
4034           {
4035             if (GET_CODE (b) == REG)
4036               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
4037             else if (REGNO (a) == REGNO (ops[0]))
4038               {
4039                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
4040                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4041               }
4042             else
4043               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4044           }
4045         else if (GET_CODE (b) != REG)
4046           abort ();
4047         else
4048           {
4049             if (REGNO (b) == REGNO (ops[0]))
4050               {
4051                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
4052                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
4053               }
4054             else
4055               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4056           }
4057       }
4058     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
4059       {
4060         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
4061         output_asm_insn (\"sxtb\\t%0, %0\", ops);
4062       }
4063     else
4064       {
4065         ops[1] = mem;
4066         ops[2] = const0_rtx;
4067         
4068         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
4069       }
4070     return \"\";
4071   }"
4072   [(set_attr "length" "2,2,4")
4073    (set_attr "type" "alu_shift,load_byte,load_byte")
4074    (set_attr "pool_range" "*,32,32")]
4077 (define_expand "extendsfdf2"
4078   [(set (match_operand:DF                  0 "s_register_operand" "")
4079         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
4080   "TARGET_ARM && TARGET_HARD_FLOAT"
4081   ""
4084 ;; Move insns (including loads and stores)
4086 ;; XXX Just some ideas about movti.
4087 ;; I don't think these are a good idea on the arm, there just aren't enough
4088 ;; registers
4089 ;;(define_expand "loadti"
4090 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
4091 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
4092 ;;  "" "")
4094 ;;(define_expand "storeti"
4095 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
4096 ;;      (match_operand:TI 1 "s_register_operand" ""))]
4097 ;;  "" "")
4099 ;;(define_expand "movti"
4100 ;;  [(set (match_operand:TI 0 "general_operand" "")
4101 ;;      (match_operand:TI 1 "general_operand" ""))]
4102 ;;  ""
4103 ;;  "
4105 ;;  rtx insn;
4107 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4108 ;;    operands[1] = copy_to_reg (operands[1]);
4109 ;;  if (GET_CODE (operands[0]) == MEM)
4110 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4111 ;;  else if (GET_CODE (operands[1]) == MEM)
4112 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4113 ;;  else
4114 ;;    FAIL;
4116 ;;  emit_insn (insn);
4117 ;;  DONE;
4118 ;;}")
4120 ;; Recognize garbage generated above.
4122 ;;(define_insn ""
4123 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4124 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4125 ;;  ""
4126 ;;  "*
4127 ;;  {
4128 ;;    register mem = (which_alternative < 3);
4129 ;;    register const char *template;
4131 ;;    operands[mem] = XEXP (operands[mem], 0);
4132 ;;    switch (which_alternative)
4133 ;;      {
4134 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4135 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4136 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4137 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4138 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4139 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4140 ;;      }
4141 ;;    output_asm_insn (template, operands);
4142 ;;    return \"\";
4143 ;;  }")
4145 (define_expand "movdi"
4146   [(set (match_operand:DI 0 "general_operand" "")
4147         (match_operand:DI 1 "general_operand" ""))]
4148   "TARGET_EITHER"
4149   "
4150   if (TARGET_THUMB)
4151     {
4152       if (!no_new_pseudos)
4153         {
4154           if (GET_CODE (operands[0]) != REG)
4155             operands[1] = force_reg (DImode, operands[1]);
4156         }
4157     }
4158   "
4161 (define_insn "*arm_movdi"
4162   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,   r, r, r, m")
4163         (match_operand:DI 1 "di_operand"              "rIKDa,Db,Dc,mi,r"))]
4164   "TARGET_ARM
4165   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4166   && !TARGET_IWMMXT"
4167   "*
4168   return (output_move_double (operands));
4169   "
4170   [(set_attr "length" "8,12,16,8,8")
4171    (set_attr "type" "*,*,*,load2,store2")
4172    (set_attr "pool_range" "*,*,*,1020,*")
4173    (set_attr "neg_pool_range" "*,*,*,1008,*")]
4176 ;; We can't actually do base+index doubleword loads if the index and
4177 ;; destination overlap.  Split here so that we at least have chance to
4178 ;; schedule.
4179 (define_split
4180   [(set (match_operand:DI 0 "s_register_operand" "")
4181         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4182                          (match_operand:SI 2 "s_register_operand" ""))))]
4183   "TARGET_LDRD
4184   && reg_overlap_mentioned_p (operands[0], operands[1])
4185   && reg_overlap_mentioned_p (operands[0], operands[2])"
4186   [(set (match_dup 4)
4187         (plus:SI (match_dup 1)
4188                  (match_dup 2)))
4189    (set (match_dup 0)
4190         (mem:DI (match_dup 4)))]
4191   "
4192   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4193   "
4196 ;;; ??? This should have alternatives for constants.
4197 ;;; ??? This was originally identical to the movdf_insn pattern.
4198 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4199 ;;; thumb_reorg with a memory reference.
4200 (define_insn "*thumb_movdi_insn"
4201   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4202         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4203   "TARGET_THUMB
4204    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4205    && (   register_operand (operands[0], DImode)
4206        || register_operand (operands[1], DImode))"
4207   "*
4208   {
4209   switch (which_alternative)
4210     {
4211     default:
4212     case 0:
4213       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4214         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4215       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4216     case 1:
4217       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4218     case 2:
4219       operands[1] = GEN_INT (- INTVAL (operands[1]));
4220       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4221     case 3:
4222       return \"ldmia\\t%1, {%0, %H0}\";
4223     case 4:
4224       return \"stmia\\t%0, {%1, %H1}\";
4225     case 5:
4226       return thumb_load_double_from_address (operands);
4227     case 6:
4228       operands[2] = gen_rtx_MEM (SImode,
4229                              plus_constant (XEXP (operands[0], 0), 4));
4230       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4231       return \"\";
4232     case 7:
4233       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4234         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4235       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4236     }
4237   }"
4238   [(set_attr "length" "4,4,6,2,2,6,4,4")
4239    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4240    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4243 (define_expand "movsi"
4244   [(set (match_operand:SI 0 "general_operand" "")
4245         (match_operand:SI 1 "general_operand" ""))]
4246   "TARGET_EITHER"
4247   "
4248   if (TARGET_ARM)
4249     {
4250       /* Everything except mem = const or mem = mem can be done easily.  */
4251       if (GET_CODE (operands[0]) == MEM)
4252         operands[1] = force_reg (SImode, operands[1]);
4253       if (arm_general_register_operand (operands[0], SImode)
4254           && GET_CODE (operands[1]) == CONST_INT
4255           && !(const_ok_for_arm (INTVAL (operands[1]))
4256                || const_ok_for_arm (~INTVAL (operands[1]))))
4257         {
4258            arm_split_constant (SET, SImode, NULL_RTX,
4259                                INTVAL (operands[1]), operands[0], NULL_RTX,
4260                                optimize && !no_new_pseudos);
4261           DONE;
4262         }
4263     }
4264   else /* TARGET_THUMB....  */
4265     {
4266       if (!no_new_pseudos)
4267         {
4268           if (GET_CODE (operands[0]) != REG)
4269             operands[1] = force_reg (SImode, operands[1]);
4270         }
4271     }
4272     
4273   if (flag_pic
4274       && (CONSTANT_P (operands[1])
4275          || symbol_mentioned_p (operands[1])
4276          || label_mentioned_p (operands[1])))
4277     operands[1] = legitimize_pic_address (operands[1], SImode,
4278                                           (no_new_pseudos ? operands[0] : 0));
4279   "
4282 (define_insn "*arm_movsi_insn"
4283   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4284         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4285   "TARGET_ARM && ! TARGET_IWMMXT
4286    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4287    && (   register_operand (operands[0], SImode)
4288        || register_operand (operands[1], SImode))"
4289   "@
4290    mov%?\\t%0, %1
4291    mvn%?\\t%0, #%B1
4292    ldr%?\\t%0, %1
4293    str%?\\t%1, %0"
4294   [(set_attr "type" "*,*,load1,store1")
4295    (set_attr "predicable" "yes")
4296    (set_attr "pool_range" "*,*,4096,*")
4297    (set_attr "neg_pool_range" "*,*,4084,*")]
4300 (define_split
4301   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4302         (match_operand:SI 1 "const_int_operand" ""))]
4303   "TARGET_ARM
4304   && (!(const_ok_for_arm (INTVAL (operands[1]))
4305         || const_ok_for_arm (~INTVAL (operands[1]))))"
4306   [(clobber (const_int 0))]
4307   "
4308   arm_split_constant (SET, SImode, NULL_RTX, 
4309                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4310   DONE;
4311   "
4314 (define_insn "*thumb_movsi_insn"
4315   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4316         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4317   "TARGET_THUMB
4318    && (   register_operand (operands[0], SImode) 
4319        || register_operand (operands[1], SImode))"
4320   "@
4321    mov  %0, %1
4322    mov  %0, %1
4323    #
4324    #
4325    ldmia\\t%1, {%0}
4326    stmia\\t%0, {%1}
4327    ldr\\t%0, %1
4328    str\\t%1, %0
4329    mov\\t%0, %1"
4330   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4331    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4332    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4335 (define_split 
4336   [(set (match_operand:SI 0 "register_operand" "")
4337         (match_operand:SI 1 "const_int_operand" ""))]
4338   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4339   [(set (match_dup 0) (match_dup 1))
4340    (set (match_dup 0) (neg:SI (match_dup 0)))]
4341   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4344 (define_split 
4345   [(set (match_operand:SI 0 "register_operand" "")
4346         (match_operand:SI 1 "const_int_operand" ""))]
4347   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4348   [(set (match_dup 0) (match_dup 1))
4349    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4350   "
4351   {
4352     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4353     unsigned HOST_WIDE_INT mask = 0xff;
4354     int i;
4355     
4356     for (i = 0; i < 25; i++)
4357       if ((val & (mask << i)) == val)
4358         break;
4360     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4361     if (i == 0)
4362       FAIL;
4364     operands[1] = GEN_INT (val >> i);
4365     operands[2] = GEN_INT (i);
4366   }"
4369 ;; When generating pic, we need to load the symbol offset into a register.
4370 ;; So that the optimizer does not confuse this with a normal symbol load
4371 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4372 ;; since that is the only type of relocation we can use.
4374 ;; The rather odd constraints on the following are to force reload to leave
4375 ;; the insn alone, and to force the minipool generation pass to then move
4376 ;; the GOT symbol to memory.
4378 (define_insn "pic_load_addr_arm"
4379   [(set (match_operand:SI 0 "s_register_operand" "=r")
4380         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4381   "TARGET_ARM && flag_pic"
4382   "ldr%?\\t%0, %1"
4383   [(set_attr "type" "load1")
4384    (set (attr "pool_range")     (const_int 4096))
4385    (set (attr "neg_pool_range") (const_int 4084))]
4388 (define_insn "pic_load_addr_thumb"
4389   [(set (match_operand:SI 0 "s_register_operand" "=l")
4390         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4391   "TARGET_THUMB && flag_pic"
4392   "ldr\\t%0, %1"
4393   [(set_attr "type" "load1")
4394    (set (attr "pool_range") (const_int 1024))]
4397 ;; This variant is used for AOF assembly, since it needs to mention the
4398 ;; pic register in the rtl.
4399 (define_expand "pic_load_addr_based"
4400   [(set (match_operand:SI 0 "s_register_operand" "")
4401         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4402   "TARGET_ARM && flag_pic"
4403   "operands[2] = pic_offset_table_rtx;"
4406 (define_insn "*pic_load_addr_based_insn"
4407   [(set (match_operand:SI 0 "s_register_operand" "=r")
4408         (unspec:SI [(match_operand 1 "" "")
4409                     (match_operand 2 "s_register_operand" "r")]
4410                    UNSPEC_PIC_SYM))]
4411   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4412   "*
4413 #ifdef AOF_ASSEMBLER
4414   operands[1] = aof_pic_entry (operands[1]);
4415 #endif
4416   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4417   return \"\";
4418   "
4419   [(set_attr "type" "load1")
4420    (set (attr "pool_range")
4421         (if_then_else (eq_attr "is_thumb" "yes")
4422                       (const_int 1024)
4423                       (const_int 4096)))
4424    (set (attr "neg_pool_range")
4425         (if_then_else (eq_attr "is_thumb" "yes")
4426                       (const_int 0)
4427                       (const_int 4084)))]
4430 (define_insn "pic_add_dot_plus_four"
4431   [(set (match_operand:SI 0 "register_operand" "+r")
4432         (unspec:SI [(plus:SI (match_dup 0)
4433                              (const (plus:SI (pc) (const_int 4))))]
4434                    UNSPEC_PIC_BASE))
4435    (use (label_ref (match_operand 1 "" "")))]
4436   "TARGET_THUMB && flag_pic"
4437   "*
4438   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4439                              CODE_LABEL_NUMBER (operands[1]));
4440   return \"add\\t%0, %|pc\";
4441   "
4442   [(set_attr "length" "2")]
4445 (define_insn "pic_add_dot_plus_eight"
4446   [(set (match_operand:SI 0 "register_operand" "+r")
4447         (unspec:SI [(plus:SI (match_dup 0)
4448                              (const (plus:SI (pc) (const_int 8))))]
4449                    UNSPEC_PIC_BASE))
4450    (use (label_ref (match_operand 1 "" "")))]
4451   "TARGET_ARM && flag_pic"
4452   "*
4453     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4454                                CODE_LABEL_NUMBER (operands[1]));
4455     return \"add%?\\t%0, %|pc, %0\";
4456   "
4457   [(set_attr "predicable" "yes")]
4460 (define_expand "builtin_setjmp_receiver"
4461   [(label_ref (match_operand 0 "" ""))]
4462   "flag_pic"
4463   "
4465   /* r3 is clobbered by set/longjmp, so we can use it as a scratch
4466      register.  */
4467   arm_load_pic_register (3);
4468   DONE;
4471 ;; If copying one reg to another we can set the condition codes according to
4472 ;; its value.  Such a move is common after a return from subroutine and the
4473 ;; result is being tested against zero.
4475 (define_insn "*movsi_compare0"
4476   [(set (reg:CC CC_REGNUM)
4477         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4478                     (const_int 0)))
4479    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4480         (match_dup 1))]
4481   "TARGET_ARM"
4482   "@
4483    cmp%?\\t%0, #0
4484    sub%?s\\t%0, %1, #0"
4485   [(set_attr "conds" "set")]
4488 ;; Subroutine to store a half word from a register into memory.
4489 ;; Operand 0 is the source register (HImode)
4490 ;; Operand 1 is the destination address in a register (SImode)
4492 ;; In both this routine and the next, we must be careful not to spill
4493 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4494 ;; can generate unrecognizable rtl.
4496 (define_expand "storehi"
4497   [;; store the low byte
4498    (set (match_operand 1 "" "") (match_dup 3))
4499    ;; extract the high byte
4500    (set (match_dup 2)
4501         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4502    ;; store the high byte
4503    (set (match_dup 4) (match_dup 5))]
4504   "TARGET_ARM"
4505   "
4506   {
4507     rtx op1 = operands[1];
4508     rtx addr = XEXP (op1, 0);
4509     enum rtx_code code = GET_CODE (addr);
4511     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4512         || code == MINUS)
4513       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4515     operands[4] = adjust_address (op1, QImode, 1);
4516     operands[1] = adjust_address (operands[1], QImode, 0);
4517     operands[3] = gen_lowpart (QImode, operands[0]);
4518     operands[0] = gen_lowpart (SImode, operands[0]);
4519     operands[2] = gen_reg_rtx (SImode);
4520     operands[5] = gen_lowpart (QImode, operands[2]);
4521   }"
4524 (define_expand "storehi_bigend"
4525   [(set (match_dup 4) (match_dup 3))
4526    (set (match_dup 2)
4527         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4528    (set (match_operand 1 "" "") (match_dup 5))]
4529   "TARGET_ARM"
4530   "
4531   {
4532     rtx op1 = operands[1];
4533     rtx addr = XEXP (op1, 0);
4534     enum rtx_code code = GET_CODE (addr);
4536     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4537         || code == MINUS)
4538       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4540     operands[4] = adjust_address (op1, QImode, 1);
4541     operands[1] = adjust_address (operands[1], QImode, 0);
4542     operands[3] = gen_lowpart (QImode, operands[0]);
4543     operands[0] = gen_lowpart (SImode, operands[0]);
4544     operands[2] = gen_reg_rtx (SImode);
4545     operands[5] = gen_lowpart (QImode, operands[2]);
4546   }"
4549 ;; Subroutine to store a half word integer constant into memory.
4550 (define_expand "storeinthi"
4551   [(set (match_operand 0 "" "")
4552         (match_operand 1 "" ""))
4553    (set (match_dup 3) (match_dup 2))]
4554   "TARGET_ARM"
4555   "
4556   {
4557     HOST_WIDE_INT value = INTVAL (operands[1]);
4558     rtx addr = XEXP (operands[0], 0);
4559     rtx op0 = operands[0];
4560     enum rtx_code code = GET_CODE (addr);
4562     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4563         || code == MINUS)
4564       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4566     operands[1] = gen_reg_rtx (SImode);
4567     if (BYTES_BIG_ENDIAN)
4568       {
4569         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4570         if ((value & 255) == ((value >> 8) & 255))
4571           operands[2] = operands[1];
4572         else
4573           {
4574             operands[2] = gen_reg_rtx (SImode);
4575             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4576           }
4577       }
4578     else
4579       {
4580         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4581         if ((value & 255) == ((value >> 8) & 255))
4582           operands[2] = operands[1];
4583         else
4584           {
4585             operands[2] = gen_reg_rtx (SImode);
4586             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4587           }
4588       }
4590     operands[3] = adjust_address (op0, QImode, 1);
4591     operands[0] = adjust_address (operands[0], QImode, 0);
4592     operands[2] = gen_lowpart (QImode, operands[2]);
4593     operands[1] = gen_lowpart (QImode, operands[1]);
4594   }"
4597 (define_expand "storehi_single_op"
4598   [(set (match_operand:HI 0 "memory_operand" "")
4599         (match_operand:HI 1 "general_operand" ""))]
4600   "TARGET_ARM && arm_arch4"
4601   "
4602   if (!s_register_operand (operands[1], HImode))
4603     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4604   "
4607 (define_expand "movhi"
4608   [(set (match_operand:HI 0 "general_operand" "")
4609         (match_operand:HI 1 "general_operand" ""))]
4610   "TARGET_EITHER"
4611   "
4612   if (TARGET_ARM)
4613     {
4614       if (!no_new_pseudos)
4615         {
4616           if (GET_CODE (operands[0]) == MEM)
4617             {
4618               if (arm_arch4)
4619                 {
4620                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4621                   DONE;
4622                 }
4623               if (GET_CODE (operands[1]) == CONST_INT)
4624                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4625               else
4626                 {
4627                   if (GET_CODE (operands[1]) == MEM)
4628                     operands[1] = force_reg (HImode, operands[1]);
4629                   if (BYTES_BIG_ENDIAN)
4630                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4631                   else
4632                    emit_insn (gen_storehi (operands[1], operands[0]));
4633                 }
4634               DONE;
4635             }
4636           /* Sign extend a constant, and keep it in an SImode reg.  */
4637           else if (GET_CODE (operands[1]) == CONST_INT)
4638             {
4639               rtx reg = gen_reg_rtx (SImode);
4640               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4642               /* If the constant is already valid, leave it alone.  */
4643               if (!const_ok_for_arm (val))
4644                 {
4645                   /* If setting all the top bits will make the constant 
4646                      loadable in a single instruction, then set them.  
4647                      Otherwise, sign extend the number.  */
4649                   if (const_ok_for_arm (~(val | ~0xffff)))
4650                     val |= ~0xffff;
4651                   else if (val & 0x8000)
4652                     val |= ~0xffff;
4653                 }
4655               emit_insn (gen_movsi (reg, GEN_INT (val)));
4656               operands[1] = gen_lowpart (HImode, reg);
4657             }
4658           else if (arm_arch4 && optimize && !no_new_pseudos
4659                    && GET_CODE (operands[1]) == MEM)
4660             {
4661               rtx reg = gen_reg_rtx (SImode);
4663               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4664               operands[1] = gen_lowpart (HImode, reg);
4665             }
4666           else if (!arm_arch4)
4667             {
4668               if (GET_CODE (operands[1]) == MEM)
4669                 {
4670                   rtx base;
4671                   rtx offset = const0_rtx;
4672                   rtx reg = gen_reg_rtx (SImode);
4674                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4675                        || (GET_CODE (base) == PLUS
4676                            && (GET_CODE (offset = XEXP (base, 1))
4677                                == CONST_INT)
4678                            && ((INTVAL(offset) & 1) != 1)
4679                            && GET_CODE (base = XEXP (base, 0)) == REG))
4680                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4681                     {
4682                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4683                       rtx new;
4685                       new = gen_rtx_MEM (SImode,
4686                                          plus_constant (base, new_offset));
4687                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4688                       emit_insn (gen_movsi (reg, new));
4689                       if (((INTVAL (offset) & 2) != 0)
4690                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4691                         {
4692                           rtx reg2 = gen_reg_rtx (SImode);
4694                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4695                           reg = reg2;
4696                         }
4697                     }
4698                   else
4699                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4701                   operands[1] = gen_lowpart (HImode, reg);
4702                }
4703            }
4704         }
4705       /* Handle loading a large integer during reload.  */
4706       else if (GET_CODE (operands[1]) == CONST_INT
4707                && !const_ok_for_arm (INTVAL (operands[1]))
4708                && !const_ok_for_arm (~INTVAL (operands[1])))
4709         {
4710           /* Writing a constant to memory needs a scratch, which should
4711              be handled with SECONDARY_RELOADs.  */
4712           if (GET_CODE (operands[0]) != REG)
4713             abort ();
4715           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4716           emit_insn (gen_movsi (operands[0], operands[1]));
4717           DONE;
4718        }
4719     }
4720   else /* TARGET_THUMB */
4721     {
4722       if (!no_new_pseudos)
4723         {
4724           if (GET_CODE (operands[0]) != REG)
4725             operands[1] = force_reg (HImode, operands[1]);
4727           /* ??? We shouldn't really get invalid addresses here, but this can
4728              happen if we are passed a SP (never OK for HImode/QImode) or 
4729              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4730              HImode/QImode) relative address.  */
4731           /* ??? This should perhaps be fixed elsewhere, for instance, in
4732              fixup_stack_1, by checking for other kinds of invalid addresses,
4733              e.g. a bare reference to a virtual register.  This may confuse the
4734              alpha though, which must handle this case differently.  */
4735           if (GET_CODE (operands[0]) == MEM
4736               && !memory_address_p (GET_MODE (operands[0]),
4737                                     XEXP (operands[0], 0)))
4738             operands[0]
4739               = replace_equiv_address (operands[0],
4740                                        copy_to_reg (XEXP (operands[0], 0)));
4741    
4742           if (GET_CODE (operands[1]) == MEM
4743               && !memory_address_p (GET_MODE (operands[1]),
4744                                     XEXP (operands[1], 0)))
4745             operands[1]
4746               = replace_equiv_address (operands[1],
4747                                        copy_to_reg (XEXP (operands[1], 0)));
4748         }
4749       /* Handle loading a large integer during reload.  */
4750       else if (GET_CODE (operands[1]) == CONST_INT
4751                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4752         {
4753           /* Writing a constant to memory needs a scratch, which should
4754              be handled with SECONDARY_RELOADs.  */
4755           if (GET_CODE (operands[0]) != REG)
4756             abort ();
4758           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4759           emit_insn (gen_movsi (operands[0], operands[1]));
4760           DONE;
4761         }
4762     }
4763   "
4766 (define_insn "*thumb_movhi_insn"
4767   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4768         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4769   "TARGET_THUMB
4770    && (   register_operand (operands[0], HImode)
4771        || register_operand (operands[1], HImode))"
4772   "*
4773   switch (which_alternative)
4774     {
4775     case 0: return \"add        %0, %1, #0\";
4776     case 2: return \"strh       %1, %0\";
4777     case 3: return \"mov        %0, %1\";
4778     case 4: return \"mov        %0, %1\";
4779     case 5: return \"mov        %0, %1\";
4780     default: abort ();
4781     case 1:
4782       /* The stack pointer can end up being taken as an index register.
4783           Catch this case here and deal with it.  */
4784       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4785           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4786           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4787         {
4788           rtx ops[2];
4789           ops[0] = operands[0];
4790           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4791       
4792           output_asm_insn (\"mov        %0, %1\", ops);
4794           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4795     
4796         }
4797       return \"ldrh     %0, %1\";
4798     }"
4799   [(set_attr "length" "2,4,2,2,2,2")
4800    (set_attr "type" "*,load1,store1,*,*,*")]
4804 (define_expand "movhi_bytes"
4805   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4806    (set (match_dup 3)
4807         (zero_extend:SI (match_dup 6)))
4808    (set (match_operand:SI 0 "" "")
4809          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4810   "TARGET_ARM"
4811   "
4812   {
4813     rtx mem1, mem2;
4814     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4816     mem1 = gen_rtx_MEM (QImode, addr);
4817     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4818     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4819     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4820     operands[0] = gen_lowpart (SImode, operands[0]);
4821     operands[1] = mem1;
4822     operands[2] = gen_reg_rtx (SImode);
4823     operands[3] = gen_reg_rtx (SImode);
4824     operands[6] = mem2;
4826     if (BYTES_BIG_ENDIAN)
4827       {
4828         operands[4] = operands[2];
4829         operands[5] = operands[3];
4830       }
4831     else
4832       {
4833         operands[4] = operands[3];
4834         operands[5] = operands[2];
4835       }
4836   }"
4839 (define_expand "movhi_bigend"
4840   [(set (match_dup 2)
4841         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4842                    (const_int 16)))
4843    (set (match_dup 3)
4844         (ashiftrt:SI (match_dup 2) (const_int 16)))
4845    (set (match_operand:HI 0 "s_register_operand" "")
4846         (match_dup 4))]
4847   "TARGET_ARM"
4848   "
4849   operands[2] = gen_reg_rtx (SImode);
4850   operands[3] = gen_reg_rtx (SImode);
4851   operands[4] = gen_lowpart (HImode, operands[3]);
4852   "
4855 ;; Pattern to recognize insn generated default case above
4856 (define_insn "*movhi_insn_arch4"
4857   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4858         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4859   "TARGET_ARM
4860    && arm_arch4
4861    && (GET_CODE (operands[1]) != CONST_INT
4862        || const_ok_for_arm (INTVAL (operands[1]))
4863        || const_ok_for_arm (~INTVAL (operands[1])))"
4864   "@
4865    mov%?\\t%0, %1\\t%@ movhi
4866    mvn%?\\t%0, #%B1\\t%@ movhi
4867    str%?h\\t%1, %0\\t%@ movhi 
4868    ldr%?h\\t%0, %1\\t%@ movhi"
4869   [(set_attr "type" "*,*,store1,load1")
4870    (set_attr "predicable" "yes")
4871    (set_attr "pool_range" "*,*,*,256")
4872    (set_attr "neg_pool_range" "*,*,*,244")]
4875 (define_insn "*movhi_bytes"
4876   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4877         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4878   "TARGET_ARM"
4879   "@
4880    mov%?\\t%0, %1\\t%@ movhi
4881    mvn%?\\t%0, #%B1\\t%@ movhi"
4882   [(set_attr "predicable" "yes")]
4885 (define_insn "thumb_movhi_clobber"
4886   [(set (match_operand:HI     0 "memory_operand"   "=m")
4887         (match_operand:HI     1 "register_operand" "l"))
4888    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4889   "TARGET_THUMB"
4890   "*
4891   abort ();"
4893         
4894 ;; We use a DImode scratch because we may occasionally need an additional
4895 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4896 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4897 (define_expand "reload_outhi"
4898   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4899               (match_operand:HI 1 "s_register_operand"        "r")
4900               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4901   "TARGET_EITHER"
4902   "if (TARGET_ARM)
4903      arm_reload_out_hi (operands);
4904    else
4905      thumb_reload_out_hi (operands);
4906   DONE;
4907   "
4910 (define_expand "reload_inhi"
4911   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4912               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4913               (match_operand:DI 2 "s_register_operand" "=&r")])]
4914   "TARGET_EITHER"
4915   "
4916   if (TARGET_ARM)
4917     arm_reload_in_hi (operands);
4918   else
4919     thumb_reload_out_hi (operands);
4920   DONE;
4923 (define_expand "movqi"
4924   [(set (match_operand:QI 0 "general_operand" "")
4925         (match_operand:QI 1 "general_operand" ""))]
4926   "TARGET_EITHER"
4927   "
4928   if (TARGET_ARM)
4929     {
4930       /* Everything except mem = const or mem = mem can be done easily */
4932       if (!no_new_pseudos)
4933         {
4934           if (GET_CODE (operands[1]) == CONST_INT)
4935             {
4936               rtx reg = gen_reg_rtx (SImode);
4938               emit_insn (gen_movsi (reg, operands[1]));
4939               operands[1] = gen_lowpart (QImode, reg);
4940             }
4941           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4942             {
4943               rtx reg = gen_reg_rtx (SImode);
4945               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4946               operands[1] = gen_lowpart (QImode, reg);
4947             }
4948           if (GET_CODE (operands[0]) == MEM)
4949             operands[1] = force_reg (QImode, operands[1]);
4950         }
4951     }
4952   else /* TARGET_THUMB */
4953     {
4954       if (!no_new_pseudos)
4955         {
4956           if (GET_CODE (operands[0]) != REG)
4957             operands[1] = force_reg (QImode, operands[1]);
4959           /* ??? We shouldn't really get invalid addresses here, but this can
4960              happen if we are passed a SP (never OK for HImode/QImode) or
4961              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4962              HImode/QImode) relative address.  */
4963           /* ??? This should perhaps be fixed elsewhere, for instance, in
4964              fixup_stack_1, by checking for other kinds of invalid addresses,
4965              e.g. a bare reference to a virtual register.  This may confuse the
4966              alpha though, which must handle this case differently.  */
4967           if (GET_CODE (operands[0]) == MEM
4968               && !memory_address_p (GET_MODE (operands[0]),
4969                                      XEXP (operands[0], 0)))
4970             operands[0]
4971               = replace_equiv_address (operands[0],
4972                                        copy_to_reg (XEXP (operands[0], 0)));
4973           if (GET_CODE (operands[1]) == MEM
4974               && !memory_address_p (GET_MODE (operands[1]),
4975                                     XEXP (operands[1], 0)))
4976              operands[1]
4977                = replace_equiv_address (operands[1],
4978                                         copy_to_reg (XEXP (operands[1], 0)));
4979         }
4980       /* Handle loading a large integer during reload.  */
4981       else if (GET_CODE (operands[1]) == CONST_INT
4982                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4983         {
4984           /* Writing a constant to memory needs a scratch, which should
4985              be handled with SECONDARY_RELOADs.  */
4986           if (GET_CODE (operands[0]) != REG)
4987             abort ();
4989           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4990           emit_insn (gen_movsi (operands[0], operands[1]));
4991           DONE;
4992        }
4993     }
4994   "
4998 (define_insn "*arm_movqi_insn"
4999   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
5000         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
5001   "TARGET_ARM
5002    && (   register_operand (operands[0], QImode)
5003        || register_operand (operands[1], QImode))"
5004   "@
5005    mov%?\\t%0, %1
5006    mvn%?\\t%0, #%B1
5007    ldr%?b\\t%0, %1
5008    str%?b\\t%1, %0"
5009   [(set_attr "type" "*,*,load1,store1")
5010    (set_attr "predicable" "yes")]
5013 (define_insn "*thumb_movqi_insn"
5014   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
5015         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
5016   "TARGET_THUMB
5017    && (   register_operand (operands[0], QImode)
5018        || register_operand (operands[1], QImode))"
5019   "@
5020    add\\t%0, %1, #0
5021    ldrb\\t%0, %1
5022    strb\\t%1, %0
5023    mov\\t%0, %1
5024    mov\\t%0, %1
5025    mov\\t%0, %1"
5026   [(set_attr "length" "2")
5027    (set_attr "type" "*,load1,store1,*,*,*")
5028    (set_attr "pool_range" "*,32,*,*,*,*")]
5031 (define_expand "movsf"
5032   [(set (match_operand:SF 0 "general_operand" "")
5033         (match_operand:SF 1 "general_operand" ""))]
5034   "TARGET_EITHER"
5035   "
5036   if (TARGET_ARM)
5037     {
5038       if (GET_CODE (operands[0]) == MEM)
5039         operands[1] = force_reg (SFmode, operands[1]);
5040     }
5041   else /* TARGET_THUMB */
5042     {
5043       if (!no_new_pseudos)
5044         {
5045            if (GET_CODE (operands[0]) != REG)
5046              operands[1] = force_reg (SFmode, operands[1]);
5047         }
5048     }
5049   "
5052 (define_split
5053   [(set (match_operand:SF 0 "nonimmediate_operand" "")
5054         (match_operand:SF 1 "immediate_operand" ""))]
5055   "TARGET_ARM
5056    && !(TARGET_HARD_FLOAT && TARGET_FPA)
5057    && reload_completed
5058    && GET_CODE (operands[1]) == CONST_DOUBLE"
5059   [(set (match_dup 2) (match_dup 3))]
5060   "
5061   operands[2] = gen_lowpart (SImode, operands[0]);
5062   operands[3] = gen_lowpart (SImode, operands[1]);
5063   if (operands[2] == 0 || operands[3] == 0)
5064     FAIL;
5065   "
5068 (define_insn "*arm_movsf_soft_insn"
5069   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
5070         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
5071   "TARGET_ARM
5072    && TARGET_SOFT_FLOAT
5073    && (GET_CODE (operands[0]) != MEM
5074        || register_operand (operands[1], SFmode))"
5075   "@
5076    mov%?\\t%0, %1
5077    ldr%?\\t%0, %1\\t%@ float
5078    str%?\\t%1, %0\\t%@ float"
5079   [(set_attr "length" "4,4,4")
5080    (set_attr "predicable" "yes")
5081    (set_attr "type" "*,load1,store1")
5082    (set_attr "pool_range" "*,4096,*")
5083    (set_attr "neg_pool_range" "*,4084,*")]
5086 ;;; ??? This should have alternatives for constants.
5087 (define_insn "*thumb_movsf_insn"
5088   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5089         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5090   "TARGET_THUMB
5091    && (   register_operand (operands[0], SFmode) 
5092        || register_operand (operands[1], SFmode))"
5093   "@
5094    add\\t%0, %1, #0
5095    ldmia\\t%1, {%0}
5096    stmia\\t%0, {%1}
5097    ldr\\t%0, %1
5098    str\\t%1, %0
5099    mov\\t%0, %1
5100    mov\\t%0, %1"
5101   [(set_attr "length" "2")
5102    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5103    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5106 (define_expand "movdf"
5107   [(set (match_operand:DF 0 "general_operand" "")
5108         (match_operand:DF 1 "general_operand" ""))]
5109   "TARGET_EITHER"
5110   "
5111   if (TARGET_ARM)
5112     {
5113       if (GET_CODE (operands[0]) == MEM)
5114         operands[1] = force_reg (DFmode, operands[1]);
5115     }
5116   else /* TARGET_THUMB */
5117     {
5118       if (!no_new_pseudos)
5119         {
5120           if (GET_CODE (operands[0]) != REG)
5121             operands[1] = force_reg (DFmode, operands[1]);
5122         }
5123     }
5124   "
5127 ;; Reloading a df mode value stored in integer regs to memory can require a
5128 ;; scratch reg.
5129 (define_expand "reload_outdf"
5130   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5131    (match_operand:DF 1 "s_register_operand" "r")
5132    (match_operand:SI 2 "s_register_operand" "=&r")]
5133   "TARGET_ARM"
5134   "
5135   {
5136     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5138     if (code == REG)
5139       operands[2] = XEXP (operands[0], 0);
5140     else if (code == POST_INC || code == PRE_DEC)
5141       {
5142         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5143         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5144         emit_insn (gen_movdi (operands[0], operands[1]));
5145         DONE;
5146       }
5147     else if (code == PRE_INC)
5148       {
5149         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5151         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5152         operands[2] = reg;
5153       }
5154     else if (code == POST_DEC)
5155       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5156     else
5157       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5158                              XEXP (XEXP (operands[0], 0), 1)));
5160     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5161                             operands[1]));
5163     if (code == POST_DEC)
5164       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5166     DONE;
5167   }"
5170 (define_insn "*movdf_soft_insn"
5171   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
5172         (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
5173   "TARGET_ARM && TARGET_SOFT_FLOAT
5174   "
5175   "* return output_move_double (operands);"
5176   [(set_attr "length" "8,12,16,8,8")
5177    (set_attr "type" "*,*,*,load2,store2")
5178    (set_attr "pool_range" "1020")
5179    (set_attr "neg_pool_range" "1008")]
5182 ;;; ??? This should have alternatives for constants.
5183 ;;; ??? This was originally identical to the movdi_insn pattern.
5184 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5185 ;;; thumb_reorg with a memory reference.
5186 (define_insn "*thumb_movdf_insn"
5187   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5188         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5189   "TARGET_THUMB
5190    && (   register_operand (operands[0], DFmode)
5191        || register_operand (operands[1], DFmode))"
5192   "*
5193   switch (which_alternative)
5194     {
5195     default:
5196     case 0:
5197       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5198         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5199       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5200     case 1:
5201       return \"ldmia\\t%1, {%0, %H0}\";
5202     case 2:
5203       return \"stmia\\t%0, {%1, %H1}\";
5204     case 3:
5205       return thumb_load_double_from_address (operands);
5206     case 4:
5207       operands[2] = gen_rtx_MEM (SImode,
5208                                  plus_constant (XEXP (operands[0], 0), 4));
5209       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5210       return \"\";
5211     case 5:
5212       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5213         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5214       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5215     }
5216   "
5217   [(set_attr "length" "4,2,2,6,4,4")
5218    (set_attr "type" "*,load2,store2,load2,store2,*")
5219    (set_attr "pool_range" "*,*,*,1020,*,*")]
5222 (define_expand "movxf"
5223   [(set (match_operand:XF 0 "general_operand" "")
5224         (match_operand:XF 1 "general_operand" ""))]
5225   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
5226   "
5227   if (GET_CODE (operands[0]) == MEM)
5228     operands[1] = force_reg (XFmode, operands[1]);
5229   "
5232 ;; Vector Moves
5233 (define_expand "movv2si"
5234   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5235         (match_operand:V2SI 1 "general_operand" ""))]
5236   "TARGET_REALLY_IWMMXT"
5240 (define_expand "movv4hi"
5241   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5242         (match_operand:V4HI 1 "general_operand" ""))]
5243   "TARGET_REALLY_IWMMXT"
5247 (define_expand "movv8qi"
5248   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5249         (match_operand:V8QI 1 "general_operand" ""))]
5250   "TARGET_REALLY_IWMMXT"
5255 ;; load- and store-multiple insns
5256 ;; The arm can load/store any set of registers, provided that they are in
5257 ;; ascending order; but that is beyond GCC so stick with what it knows.
5259 (define_expand "load_multiple"
5260   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5261                           (match_operand:SI 1 "" ""))
5262                      (use (match_operand:SI 2 "" ""))])]
5263   "TARGET_ARM"
5265   HOST_WIDE_INT offset = 0;
5267   /* Support only fixed point registers.  */
5268   if (GET_CODE (operands[2]) != CONST_INT
5269       || INTVAL (operands[2]) > 14
5270       || INTVAL (operands[2]) < 2
5271       || GET_CODE (operands[1]) != MEM
5272       || GET_CODE (operands[0]) != REG
5273       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5274       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5275     FAIL;
5277   operands[3]
5278     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5279                              force_reg (SImode, XEXP (operands[1], 0)),
5280                              TRUE, FALSE, operands[1], &offset);
5283 ;; Load multiple with write-back
5285 (define_insn "*ldmsi_postinc4"
5286   [(match_parallel 0 "load_multiple_operation"
5287     [(set (match_operand:SI 1 "s_register_operand" "=r")
5288           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5289                    (const_int 16)))
5290      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5291           (mem:SI (match_dup 2)))
5292      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5293           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5294      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5295           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5296      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5297           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5298   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5299   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5300   [(set_attr "type" "load4")
5301    (set_attr "predicable" "yes")]
5304 (define_insn "*ldmsi_postinc4_thumb"
5305   [(match_parallel 0 "load_multiple_operation"
5306     [(set (match_operand:SI 1 "s_register_operand" "=l")
5307           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5308                    (const_int 16)))
5309      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5310           (mem:SI (match_dup 2)))
5311      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5312           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5313      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5314           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5315      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5316           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5317   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5318   "ldmia\\t%1!, {%3, %4, %5, %6}"
5319   [(set_attr "type" "load4")]
5322 (define_insn "*ldmsi_postinc3"
5323   [(match_parallel 0 "load_multiple_operation"
5324     [(set (match_operand:SI 1 "s_register_operand" "=r")
5325           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5326                    (const_int 12)))
5327      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5328           (mem:SI (match_dup 2)))
5329      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5330           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5331      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5332           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5333   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5334   "ldm%?ia\\t%1!, {%3, %4, %5}"
5335   [(set_attr "type" "load3")
5336    (set_attr "predicable" "yes")]
5339 (define_insn "*ldmsi_postinc2"
5340   [(match_parallel 0 "load_multiple_operation"
5341     [(set (match_operand:SI 1 "s_register_operand" "=r")
5342           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5343                    (const_int 8)))
5344      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5345           (mem:SI (match_dup 2)))
5346      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5347           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5348   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5349   "ldm%?ia\\t%1!, {%3, %4}"
5350   [(set_attr "type" "load2")
5351    (set_attr "predicable" "yes")]
5354 ;; Ordinary load multiple
5356 (define_insn "*ldmsi4"
5357   [(match_parallel 0 "load_multiple_operation"
5358     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5359           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5360      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5361           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5362      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5363           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5364      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5365           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5366   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5367   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5368   [(set_attr "type" "load4")
5369    (set_attr "predicable" "yes")]
5372 (define_insn "*ldmsi3"
5373   [(match_parallel 0 "load_multiple_operation"
5374     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5375           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5376      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5377           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5378      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5379           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5380   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5381   "ldm%?ia\\t%1, {%2, %3, %4}"
5382   [(set_attr "type" "load3")
5383    (set_attr "predicable" "yes")]
5386 (define_insn "*ldmsi2"
5387   [(match_parallel 0 "load_multiple_operation"
5388     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5389           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5390      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5391           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5392   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5393   "ldm%?ia\\t%1, {%2, %3}"
5394   [(set_attr "type" "load2")
5395    (set_attr "predicable" "yes")]
5398 (define_expand "store_multiple"
5399   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5400                           (match_operand:SI 1 "" ""))
5401                      (use (match_operand:SI 2 "" ""))])]
5402   "TARGET_ARM"
5404   HOST_WIDE_INT offset = 0;
5406   /* Support only fixed point registers.  */
5407   if (GET_CODE (operands[2]) != CONST_INT
5408       || INTVAL (operands[2]) > 14
5409       || INTVAL (operands[2]) < 2
5410       || GET_CODE (operands[1]) != REG
5411       || GET_CODE (operands[0]) != MEM
5412       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5413       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5414     FAIL;
5416   operands[3]
5417     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5418                               force_reg (SImode, XEXP (operands[0], 0)),
5419                               TRUE, FALSE, operands[0], &offset);
5422 ;; Store multiple with write-back
5424 (define_insn "*stmsi_postinc4"
5425   [(match_parallel 0 "store_multiple_operation"
5426     [(set (match_operand:SI 1 "s_register_operand" "=r")
5427           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5428                    (const_int 16)))
5429      (set (mem:SI (match_dup 2))
5430           (match_operand:SI 3 "arm_hard_register_operand" ""))
5431      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5432           (match_operand:SI 4 "arm_hard_register_operand" ""))
5433      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5434           (match_operand:SI 5 "arm_hard_register_operand" ""))
5435      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5436           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5437   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5438   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5439   [(set_attr "predicable" "yes")
5440    (set_attr "type" "store4")]
5443 (define_insn "*stmsi_postinc4_thumb"
5444   [(match_parallel 0 "store_multiple_operation"
5445     [(set (match_operand:SI 1 "s_register_operand" "=l")
5446           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5447                    (const_int 16)))
5448      (set (mem:SI (match_dup 2))
5449           (match_operand:SI 3 "arm_hard_register_operand" ""))
5450      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5451           (match_operand:SI 4 "arm_hard_register_operand" ""))
5452      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5453           (match_operand:SI 5 "arm_hard_register_operand" ""))
5454      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5455           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5456   "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
5457   "stmia\\t%1!, {%3, %4, %5, %6}"
5458   [(set_attr "type" "store4")]
5461 (define_insn "*stmsi_postinc3"
5462   [(match_parallel 0 "store_multiple_operation"
5463     [(set (match_operand:SI 1 "s_register_operand" "=r")
5464           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5465                    (const_int 12)))
5466      (set (mem:SI (match_dup 2))
5467           (match_operand:SI 3 "arm_hard_register_operand" ""))
5468      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5469           (match_operand:SI 4 "arm_hard_register_operand" ""))
5470      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5471           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5472   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5473   "stm%?ia\\t%1!, {%3, %4, %5}"
5474   [(set_attr "predicable" "yes")
5475    (set_attr "type" "store3")]
5478 (define_insn "*stmsi_postinc2"
5479   [(match_parallel 0 "store_multiple_operation"
5480     [(set (match_operand:SI 1 "s_register_operand" "=r")
5481           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5482                    (const_int 8)))
5483      (set (mem:SI (match_dup 2))
5484           (match_operand:SI 3 "arm_hard_register_operand" ""))
5485      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5486           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5487   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5488   "stm%?ia\\t%1!, {%3, %4}"
5489   [(set_attr "predicable" "yes")
5490    (set_attr "type" "store2")]
5493 ;; Ordinary store multiple
5495 (define_insn "*stmsi4"
5496   [(match_parallel 0 "store_multiple_operation"
5497     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5498           (match_operand:SI 2 "arm_hard_register_operand" ""))
5499      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5500           (match_operand:SI 3 "arm_hard_register_operand" ""))
5501      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5502           (match_operand:SI 4 "arm_hard_register_operand" ""))
5503      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5504           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5505   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5506   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5507   [(set_attr "predicable" "yes")
5508    (set_attr "type" "store4")]
5511 (define_insn "*stmsi3"
5512   [(match_parallel 0 "store_multiple_operation"
5513     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5514           (match_operand:SI 2 "arm_hard_register_operand" ""))
5515      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5516           (match_operand:SI 3 "arm_hard_register_operand" ""))
5517      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5518           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5519   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5520   "stm%?ia\\t%1, {%2, %3, %4}"
5521   [(set_attr "predicable" "yes")
5522    (set_attr "type" "store3")]
5525 (define_insn "*stmsi2"
5526   [(match_parallel 0 "store_multiple_operation"
5527     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5528           (match_operand:SI 2 "arm_hard_register_operand" ""))
5529      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5530           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5531   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5532   "stm%?ia\\t%1, {%2, %3}"
5533   [(set_attr "predicable" "yes")
5534    (set_attr "type" "store2")]
5537 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5538 ;; We could let this apply for blocks of less than this, but it clobbers so
5539 ;; many registers that there is then probably a better way.
5541 (define_expand "movmemqi"
5542   [(match_operand:BLK 0 "general_operand" "")
5543    (match_operand:BLK 1 "general_operand" "")
5544    (match_operand:SI 2 "const_int_operand" "")
5545    (match_operand:SI 3 "const_int_operand" "")]
5546   "TARGET_EITHER"
5547   "
5548   if (TARGET_ARM)
5549     {
5550       if (arm_gen_movmemqi (operands))
5551         DONE;
5552       FAIL;
5553     }
5554   else /* TARGET_THUMB */
5555     {
5556       if (   INTVAL (operands[3]) != 4
5557           || INTVAL (operands[2]) > 48)
5558         FAIL;
5560       thumb_expand_movmemqi (operands);
5561       DONE;
5562     }
5563   "
5566 ;; Thumb block-move insns
5568 (define_insn "movmem12b"
5569   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5570         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5571    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5572         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5573    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5574         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5575    (set (match_operand:SI 0 "register_operand" "=l")
5576         (plus:SI (match_dup 2) (const_int 12)))
5577    (set (match_operand:SI 1 "register_operand" "=l")
5578         (plus:SI (match_dup 3) (const_int 12)))
5579    (clobber (match_scratch:SI 4 "=&l"))
5580    (clobber (match_scratch:SI 5 "=&l"))
5581    (clobber (match_scratch:SI 6 "=&l"))]
5582   "TARGET_THUMB"
5583   "* return thumb_output_move_mem_multiple (3, operands);"
5584   [(set_attr "length" "4")
5585    ; This isn't entirely accurate...  It loads as well, but in terms of
5586    ; scheduling the following insn it is better to consider it as a store
5587    (set_attr "type" "store3")]
5590 (define_insn "movmem8b"
5591   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5592         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5593    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5594         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5595    (set (match_operand:SI 0 "register_operand" "=l")
5596         (plus:SI (match_dup 2) (const_int 8)))
5597    (set (match_operand:SI 1 "register_operand" "=l")
5598         (plus:SI (match_dup 3) (const_int 8)))
5599    (clobber (match_scratch:SI 4 "=&l"))
5600    (clobber (match_scratch:SI 5 "=&l"))]
5601   "TARGET_THUMB"
5602   "* return thumb_output_move_mem_multiple (2, operands);"
5603   [(set_attr "length" "4")
5604    ; This isn't entirely accurate...  It loads as well, but in terms of
5605    ; scheduling the following insn it is better to consider it as a store
5606    (set_attr "type" "store2")]
5611 ;; Compare & branch insns
5612 ;; The range calculations are based as follows:
5613 ;; For forward branches, the address calculation returns the address of
5614 ;; the next instruction.  This is 2 beyond the branch instruction.
5615 ;; For backward branches, the address calculation returns the address of
5616 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5617 ;; instruction for the shortest sequence, and 4 before the branch instruction
5618 ;; if we have to jump around an unconditional branch.
5619 ;; To the basic branch range the PC offset must be added (this is +4).
5620 ;; So for forward branches we have 
5621 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5622 ;; And for backward branches we have 
5623 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5625 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5626 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5628 (define_expand "cbranchsi4"
5629   [(set (pc) (if_then_else
5630               (match_operator 0 "arm_comparison_operator"
5631                [(match_operand:SI 1 "s_register_operand" "")
5632                 (match_operand:SI 2 "nonmemory_operand" "")])
5633               (label_ref (match_operand 3 "" ""))
5634               (pc)))]
5635   "TARGET_THUMB"
5636   "
5637   if (thumb_cmpneg_operand (operands[2], SImode))
5638     {
5639       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5640                                               operands[3], operands[0]));
5641       DONE;
5642     }
5643   if (!thumb_cmp_operand (operands[2], SImode))
5644     operands[2] = force_reg (SImode, operands[2]);
5645   ")
5647 (define_insn "*cbranchsi4_insn"
5648   [(set (pc) (if_then_else
5649               (match_operator 0 "arm_comparison_operator"
5650                [(match_operand:SI 1 "s_register_operand" "l,*h")
5651                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5652               (label_ref (match_operand 3 "" ""))
5653               (pc)))]
5654   "TARGET_THUMB"
5655   "*
5656   output_asm_insn (\"cmp\\t%1, %2\", operands);
5658   switch (get_attr_length (insn))
5659     {
5660     case 4:  return \"b%d0\\t%l3\";
5661     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5662     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5663     }
5664   "
5665   [(set (attr "far_jump")
5666         (if_then_else
5667             (eq_attr "length" "8")
5668             (const_string "yes")
5669             (const_string "no")))
5670    (set (attr "length") 
5671         (if_then_else
5672             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5673                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5674             (const_int 4)
5675             (if_then_else
5676                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5677                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5678                 (const_int 6)
5679                 (const_int 8))))]
5682 (define_insn "cbranchsi4_scratch"
5683   [(set (pc) (if_then_else
5684               (match_operator 4 "arm_comparison_operator"
5685                [(match_operand:SI 1 "s_register_operand" "l,0")
5686                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5687               (label_ref (match_operand 3 "" ""))
5688               (pc)))
5689    (clobber (match_scratch:SI 0 "=l,l"))]
5690   "TARGET_THUMB"
5691   "*
5692   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5694   switch (get_attr_length (insn))
5695     {
5696     case 4:  return \"b%d4\\t%l3\";
5697     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5698     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5699     }
5700   "
5701   [(set (attr "far_jump")
5702         (if_then_else
5703             (eq_attr "length" "8")
5704             (const_string "yes")
5705             (const_string "no")))
5706    (set (attr "length") 
5707         (if_then_else
5708             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5709                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5710             (const_int 4)
5711             (if_then_else
5712                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5713                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5714                 (const_int 6)
5715                 (const_int 8))))]
5717 (define_insn "*movsi_cbranchsi4"
5718   [(set (pc)
5719         (if_then_else
5720          (match_operator 3 "arm_comparison_operator"
5721           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5722            (const_int 0)])
5723          (label_ref (match_operand 2 "" ""))
5724          (pc)))
5725    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5726         (match_dup 1))]
5727   "TARGET_THUMB"
5728   "*{
5729   if (which_alternative == 0)
5730     output_asm_insn (\"cmp\t%0, #0\", operands);
5731   else if (which_alternative == 1)
5732     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5733   else
5734     {
5735       output_asm_insn (\"cmp\t%1, #0\", operands);
5736       if (which_alternative == 2)
5737         output_asm_insn (\"mov\t%0, %1\", operands);
5738       else
5739         output_asm_insn (\"str\t%1, %0\", operands);
5740     }
5741   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5742     {
5743     case 4:  return \"b%d3\\t%l2\";
5744     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5745     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5746     }
5747   }"
5748   [(set (attr "far_jump")
5749         (if_then_else
5750             (ior (and (gt (symbol_ref ("which_alternative"))
5751                           (const_int 1))
5752                       (eq_attr "length" "8"))
5753                  (eq_attr "length" "10"))
5754             (const_string "yes")
5755             (const_string "no")))
5756    (set (attr "length")
5757      (if_then_else
5758        (le (symbol_ref ("which_alternative"))
5759                        (const_int 1))
5760        (if_then_else
5761          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5762               (le (minus (match_dup 2) (pc)) (const_int 256)))
5763          (const_int 4)
5764          (if_then_else
5765            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5766                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5767            (const_int 6)
5768            (const_int 8)))
5769        (if_then_else
5770          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5771               (le (minus (match_dup 2) (pc)) (const_int 256)))
5772          (const_int 6)
5773          (if_then_else
5774            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5775                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5776            (const_int 8)
5777            (const_int 10)))))]
5780 (define_insn "*negated_cbranchsi4"
5781   [(set (pc)
5782         (if_then_else
5783          (match_operator 0 "arm_comparison_operator"
5784           [(match_operand:SI 1 "s_register_operand" "l")
5785            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5786          (label_ref (match_operand 3 "" ""))
5787          (pc)))]
5788   "TARGET_THUMB"
5789   "*
5790   output_asm_insn (\"cmn\\t%1, %2\", operands);
5791   switch (get_attr_length (insn))
5792     {
5793     case 4:  return \"b%d0\\t%l3\";
5794     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5795     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5796     }
5797   "
5798   [(set (attr "far_jump")
5799         (if_then_else
5800             (eq_attr "length" "8")
5801             (const_string "yes")
5802             (const_string "no")))
5803    (set (attr "length") 
5804         (if_then_else
5805             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5806                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5807             (const_int 4)
5808             (if_then_else
5809                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5810                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5811                 (const_int 6)
5812                 (const_int 8))))]
5815 (define_insn "*tbit_cbranch"
5816   [(set (pc)
5817         (if_then_else
5818          (match_operator 0 "equality_operator"
5819           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5820                             (const_int 1)
5821                             (match_operand:SI 2 "const_int_operand" "i"))
5822            (const_int 0)])
5823          (label_ref (match_operand 3 "" ""))
5824          (pc)))
5825    (clobber (match_scratch:SI 4 "=l"))]
5826   "TARGET_THUMB"
5827   "*
5828   {
5829   rtx op[3];
5830   op[0] = operands[4];
5831   op[1] = operands[1];
5832   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5834   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5835   switch (get_attr_length (insn))
5836     {
5837     case 4:  return \"b%d0\\t%l3\";
5838     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5839     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5840     }
5841   }"
5842   [(set (attr "far_jump")
5843         (if_then_else
5844             (eq_attr "length" "8")
5845             (const_string "yes")
5846             (const_string "no")))
5847    (set (attr "length") 
5848         (if_then_else
5849             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5850                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5851             (const_int 4)
5852             (if_then_else
5853                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5854                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5855                 (const_int 6)
5856                 (const_int 8))))]
5858   
5859 (define_insn "*tstsi3_cbranch"
5860   [(set (pc)
5861         (if_then_else
5862          (match_operator 3 "equality_operator"
5863           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5864                    (match_operand:SI 1 "s_register_operand" "l"))
5865            (const_int 0)])
5866          (label_ref (match_operand 2 "" ""))
5867          (pc)))]
5868   "TARGET_THUMB"
5869   "*
5870   {
5871   output_asm_insn (\"tst\\t%0, %1\", operands);
5872   switch (get_attr_length (insn))
5873     {
5874     case 4:  return \"b%d3\\t%l2\";
5875     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5876     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5877     }
5878   }"
5879   [(set (attr "far_jump")
5880         (if_then_else
5881             (eq_attr "length" "8")
5882             (const_string "yes")
5883             (const_string "no")))
5884    (set (attr "length") 
5885         (if_then_else
5886             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5887                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5888             (const_int 4)
5889             (if_then_else
5890                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5891                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5892                 (const_int 6)
5893                 (const_int 8))))]
5895   
5896 (define_insn "*andsi3_cbranch"
5897   [(set (pc)
5898         (if_then_else
5899          (match_operator 5 "equality_operator"
5900           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5901                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5902            (const_int 0)])
5903          (label_ref (match_operand 4 "" ""))
5904          (pc)))
5905    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5906         (and:SI (match_dup 2) (match_dup 3)))
5907    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5908   "TARGET_THUMB"
5909   "*
5910   {
5911   if (which_alternative == 0)
5912     output_asm_insn (\"and\\t%0, %3\", operands);
5913   else if (which_alternative == 1)
5914     {
5915       output_asm_insn (\"and\\t%1, %3\", operands);
5916       output_asm_insn (\"mov\\t%0, %1\", operands);
5917     }
5918   else
5919     {
5920       output_asm_insn (\"and\\t%1, %3\", operands);
5921       output_asm_insn (\"str\\t%1, %0\", operands);
5922     }
5924   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5925     {
5926     case 4:  return \"b%d5\\t%l4\";
5927     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5928     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5929     }
5930   }"
5931   [(set (attr "far_jump")
5932         (if_then_else
5933             (ior (and (eq (symbol_ref ("which_alternative"))
5934                           (const_int 0))
5935                       (eq_attr "length" "8"))
5936                  (eq_attr "length" "10"))
5937             (const_string "yes")
5938             (const_string "no")))
5939    (set (attr "length")
5940      (if_then_else
5941        (eq (symbol_ref ("which_alternative"))
5942                        (const_int 0))
5943        (if_then_else
5944          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5945               (le (minus (match_dup 4) (pc)) (const_int 256)))
5946          (const_int 4)
5947          (if_then_else
5948            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5949                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5950            (const_int 6)
5951            (const_int 8)))
5952        (if_then_else
5953          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5954               (le (minus (match_dup 4) (pc)) (const_int 256)))
5955          (const_int 6)
5956          (if_then_else
5957            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5958                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5959            (const_int 8)
5960            (const_int 10)))))]
5963 (define_insn "*orrsi3_cbranch_scratch"
5964   [(set (pc)
5965         (if_then_else
5966          (match_operator 4 "equality_operator"
5967           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5968                    (match_operand:SI 2 "s_register_operand" "l"))
5969            (const_int 0)])
5970          (label_ref (match_operand 3 "" ""))
5971          (pc)))
5972    (clobber (match_scratch:SI 0 "=l"))]
5973   "TARGET_THUMB"
5974   "*
5975   {
5976   output_asm_insn (\"orr\\t%0, %2\", operands);
5977   switch (get_attr_length (insn))
5978     {
5979     case 4:  return \"b%d4\\t%l3\";
5980     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5981     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5982     }
5983   }"
5984   [(set (attr "far_jump")
5985         (if_then_else
5986             (eq_attr "length" "8")
5987             (const_string "yes")
5988             (const_string "no")))
5989    (set (attr "length") 
5990         (if_then_else
5991             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5992                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5993             (const_int 4)
5994             (if_then_else
5995                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5996                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5997                 (const_int 6)
5998                 (const_int 8))))]
6000   
6001 (define_insn "*orrsi3_cbranch"
6002   [(set (pc)
6003         (if_then_else
6004          (match_operator 5 "equality_operator"
6005           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6006                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6007            (const_int 0)])
6008          (label_ref (match_operand 4 "" ""))
6009          (pc)))
6010    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6011         (ior:SI (match_dup 2) (match_dup 3)))
6012    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6013   "TARGET_THUMB"
6014   "*
6015   {
6016   if (which_alternative == 0)
6017     output_asm_insn (\"orr\\t%0, %3\", operands);
6018   else if (which_alternative == 1)
6019     {
6020       output_asm_insn (\"orr\\t%1, %3\", operands);
6021       output_asm_insn (\"mov\\t%0, %1\", operands);
6022     }
6023   else
6024     {
6025       output_asm_insn (\"orr\\t%1, %3\", operands);
6026       output_asm_insn (\"str\\t%1, %0\", operands);
6027     }
6029   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6030     {
6031     case 4:  return \"b%d5\\t%l4\";
6032     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6033     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6034     }
6035   }"
6036   [(set (attr "far_jump")
6037         (if_then_else
6038             (ior (and (eq (symbol_ref ("which_alternative"))
6039                           (const_int 0))
6040                       (eq_attr "length" "8"))
6041                  (eq_attr "length" "10"))
6042             (const_string "yes")
6043             (const_string "no")))
6044    (set (attr "length")
6045      (if_then_else
6046        (eq (symbol_ref ("which_alternative"))
6047                        (const_int 0))
6048        (if_then_else
6049          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6050               (le (minus (match_dup 4) (pc)) (const_int 256)))
6051          (const_int 4)
6052          (if_then_else
6053            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6054                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6055            (const_int 6)
6056            (const_int 8)))
6057        (if_then_else
6058          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6059               (le (minus (match_dup 4) (pc)) (const_int 256)))
6060          (const_int 6)
6061          (if_then_else
6062            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6063                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6064            (const_int 8)
6065            (const_int 10)))))]
6068 (define_insn "*xorsi3_cbranch_scratch"
6069   [(set (pc)
6070         (if_then_else
6071          (match_operator 4 "equality_operator"
6072           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
6073                    (match_operand:SI 2 "s_register_operand" "l"))
6074            (const_int 0)])
6075          (label_ref (match_operand 3 "" ""))
6076          (pc)))
6077    (clobber (match_scratch:SI 0 "=l"))]
6078   "TARGET_THUMB"
6079   "*
6080   {
6081   output_asm_insn (\"eor\\t%0, %2\", operands);
6082   switch (get_attr_length (insn))
6083     {
6084     case 4:  return \"b%d4\\t%l3\";
6085     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6086     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6087     }
6088   }"
6089   [(set (attr "far_jump")
6090         (if_then_else
6091             (eq_attr "length" "8")
6092             (const_string "yes")
6093             (const_string "no")))
6094    (set (attr "length") 
6095         (if_then_else
6096             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6097                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6098             (const_int 4)
6099             (if_then_else
6100                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6101                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6102                 (const_int 6)
6103                 (const_int 8))))]
6105   
6106 (define_insn "*xorsi3_cbranch"
6107   [(set (pc)
6108         (if_then_else
6109          (match_operator 5 "equality_operator"
6110           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
6111                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6112            (const_int 0)])
6113          (label_ref (match_operand 4 "" ""))
6114          (pc)))
6115    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6116         (xor:SI (match_dup 2) (match_dup 3)))
6117    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6118   "TARGET_THUMB"
6119   "*
6120   {
6121   if (which_alternative == 0)
6122     output_asm_insn (\"eor\\t%0, %3\", operands);
6123   else if (which_alternative == 1)
6124     {
6125       output_asm_insn (\"eor\\t%1, %3\", operands);
6126       output_asm_insn (\"mov\\t%0, %1\", operands);
6127     }
6128   else
6129     {
6130       output_asm_insn (\"eor\\t%1, %3\", operands);
6131       output_asm_insn (\"str\\t%1, %0\", operands);
6132     }
6134   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6135     {
6136     case 4:  return \"b%d5\\t%l4\";
6137     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6138     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6139     }
6140   }"
6141   [(set (attr "far_jump")
6142         (if_then_else
6143             (ior (and (eq (symbol_ref ("which_alternative"))
6144                           (const_int 0))
6145                       (eq_attr "length" "8"))
6146                  (eq_attr "length" "10"))
6147             (const_string "yes")
6148             (const_string "no")))
6149    (set (attr "length")
6150      (if_then_else
6151        (eq (symbol_ref ("which_alternative"))
6152                        (const_int 0))
6153        (if_then_else
6154          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6155               (le (minus (match_dup 4) (pc)) (const_int 256)))
6156          (const_int 4)
6157          (if_then_else
6158            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6159                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6160            (const_int 6)
6161            (const_int 8)))
6162        (if_then_else
6163          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6164               (le (minus (match_dup 4) (pc)) (const_int 256)))
6165          (const_int 6)
6166          (if_then_else
6167            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6168                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6169            (const_int 8)
6170            (const_int 10)))))]
6173 (define_insn "*bicsi3_cbranch_scratch"
6174   [(set (pc)
6175         (if_then_else
6176          (match_operator 4 "equality_operator"
6177           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6178                    (match_operand:SI 1 "s_register_operand" "0"))
6179            (const_int 0)])
6180          (label_ref (match_operand 3 "" ""))
6181          (pc)))
6182    (clobber (match_scratch:SI 0 "=l"))]
6183   "TARGET_THUMB"
6184   "*
6185   {
6186   output_asm_insn (\"bic\\t%0, %2\", operands);
6187   switch (get_attr_length (insn))
6188     {
6189     case 4:  return \"b%d4\\t%l3\";
6190     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6191     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6192     }
6193   }"
6194   [(set (attr "far_jump")
6195         (if_then_else
6196             (eq_attr "length" "8")
6197             (const_string "yes")
6198             (const_string "no")))
6199    (set (attr "length") 
6200         (if_then_else
6201             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6202                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6203             (const_int 4)
6204             (if_then_else
6205                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6206                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6207                 (const_int 6)
6208                 (const_int 8))))]
6210   
6211 (define_insn "*bicsi3_cbranch"
6212   [(set (pc)
6213         (if_then_else
6214          (match_operator 5 "equality_operator"
6215           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l,l"))
6216                    (match_operand:SI 2 "s_register_operand" "0,1,1,1,1"))
6217            (const_int 0)])
6218          (label_ref (match_operand 4 "" ""))
6219          (pc)))
6220    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=!l,l,*?h,*?m,*?m")
6221         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6222    (clobber (match_scratch:SI 1 "=X,l,l,&l,&l"))]
6223   "TARGET_THUMB"
6224   "*
6225   {
6226   if (which_alternative == 0)
6227     output_asm_insn (\"bic\\t%0, %3\", operands);
6228   else if (which_alternative <= 2)
6229     {
6230       output_asm_insn (\"bic\\t%1, %3\", operands);
6231       /* It's ok if OP0 is a lo-reg, even though the mov will set the
6232          conditions again, since we're only testing for equality.  */
6233       output_asm_insn (\"mov\\t%0, %1\", operands);
6234     }
6235   else
6236     {
6237       output_asm_insn (\"bic\\t%1, %3\", operands);
6238       output_asm_insn (\"str\\t%1, %0\", operands);
6239     }
6241   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6242     {
6243     case 4:  return \"b%d5\\t%l4\";
6244     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6245     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6246     }
6247   }"
6248   [(set (attr "far_jump")
6249         (if_then_else
6250             (ior (and (eq (symbol_ref ("which_alternative"))
6251                           (const_int 0))
6252                       (eq_attr "length" "8"))
6253                  (eq_attr "length" "10"))
6254             (const_string "yes")
6255             (const_string "no")))
6256    (set (attr "length")
6257      (if_then_else
6258        (eq (symbol_ref ("which_alternative"))
6259                        (const_int 0))
6260        (if_then_else
6261          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6262               (le (minus (match_dup 4) (pc)) (const_int 256)))
6263          (const_int 4)
6264          (if_then_else
6265            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6266                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6267            (const_int 6)
6268            (const_int 8)))
6269        (if_then_else
6270          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6271               (le (minus (match_dup 4) (pc)) (const_int 256)))
6272          (const_int 6)
6273          (if_then_else
6274            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6275                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6276            (const_int 8)
6277            (const_int 10)))))]
6280 (define_insn "*cbranchne_decr1"
6281   [(set (pc)
6282         (if_then_else (match_operator 3 "equality_operator"
6283                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6284                         (const_int 0)])
6285                       (label_ref (match_operand 4 "" ""))
6286                       (pc)))
6287    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6288         (plus:SI (match_dup 2) (const_int -1)))
6289    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6290   "TARGET_THUMB"
6291   "*
6292    {
6293      rtx cond[2];
6294      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6295                                 ? GEU : LTU),
6296                                VOIDmode, operands[2], const1_rtx);
6297      cond[1] = operands[4];
6299      if (which_alternative == 0)
6300        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6301      else if (which_alternative == 1)
6302        {
6303          /* We must provide an alternative for a hi reg because reload 
6304             cannot handle output reloads on a jump instruction, but we
6305             can't subtract into that.  Fortunately a mov from lo to hi
6306             does not clobber the condition codes.  */
6307          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6308          output_asm_insn (\"mov\\t%0, %1\", operands);
6309        }
6310      else
6311        {
6312          /* Similarly, but the target is memory.  */
6313          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6314          output_asm_insn (\"str\\t%1, %0\", operands);
6315        }
6317      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6318        {
6319          case 4:
6320            output_asm_insn (\"b%d0\\t%l1\", cond);
6321            return \"\";
6322          case 6:
6323            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6324            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6325          default:
6326            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6327            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6328        }
6329    }
6330   "
6331   [(set (attr "far_jump")
6332         (if_then_else
6333             (ior (and (eq (symbol_ref ("which_alternative"))
6334                           (const_int 0))
6335                       (eq_attr "length" "8"))
6336                  (eq_attr "length" "10"))
6337             (const_string "yes")
6338             (const_string "no")))
6339    (set_attr_alternative "length"
6340       [
6341        ;; Alternative 0
6342        (if_then_else
6343          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6344               (le (minus (match_dup 4) (pc)) (const_int 256)))
6345          (const_int 4)
6346          (if_then_else
6347            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6348                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6349            (const_int 6)
6350            (const_int 8)))
6351        ;; Alternative 1
6352        (if_then_else
6353          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6354               (le (minus (match_dup 4) (pc)) (const_int 256)))
6355          (const_int 6)
6356          (if_then_else
6357            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6358                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6359            (const_int 8)
6360            (const_int 10)))
6361        ;; Alternative 2
6362        (if_then_else
6363          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6364               (le (minus (match_dup 4) (pc)) (const_int 256)))
6365          (const_int 6)
6366          (if_then_else
6367            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6368                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6369            (const_int 8)
6370            (const_int 10)))
6371        ;; Alternative 3
6372        (if_then_else
6373          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6374               (le (minus (match_dup 4) (pc)) (const_int 256)))
6375          (const_int 6)
6376          (if_then_else
6377            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6378                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6379            (const_int 8)
6380            (const_int 10)))])]
6383 (define_insn "*addsi3_cbranch"
6384   [(set (pc)
6385         (if_then_else
6386          (match_operator 4 "comparison_operator"
6387           [(plus:SI
6388             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6389             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6390            (const_int 0)])
6391          (label_ref (match_operand 5 "" ""))
6392          (pc)))
6393    (set
6394     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6395     (plus:SI (match_dup 2) (match_dup 3)))
6396    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6397   "TARGET_THUMB
6398    && (GET_CODE (operands[4]) == EQ
6399        || GET_CODE (operands[4]) == NE
6400        || GET_CODE (operands[4]) == GE
6401        || GET_CODE (operands[4]) == LT)"
6402   "*
6403    {
6404      rtx cond[3];
6406      
6407      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6408      cond[1] = operands[2];
6409      cond[2] = operands[3];
6411      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6412        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6413      else
6414        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6416      if (which_alternative >= 3
6417          && which_alternative < 4)
6418        output_asm_insn (\"mov\\t%0, %1\", operands);
6419      else if (which_alternative >= 4)
6420        output_asm_insn (\"str\\t%1, %0\", operands);
6422      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6423        {
6424          case 4:
6425            return \"b%d4\\t%l5\";
6426          case 6:
6427            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6428          default:
6429            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6430        }
6431    }
6432   "
6433   [(set (attr "far_jump")
6434         (if_then_else
6435             (ior (and (lt (symbol_ref ("which_alternative"))
6436                           (const_int 3))
6437                       (eq_attr "length" "8"))
6438                  (eq_attr "length" "10"))
6439             (const_string "yes")
6440             (const_string "no")))
6441    (set (attr "length")
6442      (if_then_else
6443        (lt (symbol_ref ("which_alternative"))
6444                        (const_int 3))
6445        (if_then_else
6446          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6447               (le (minus (match_dup 5) (pc)) (const_int 256)))
6448          (const_int 4)
6449          (if_then_else
6450            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6451                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6452            (const_int 6)
6453            (const_int 8)))
6454        (if_then_else
6455          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6456               (le (minus (match_dup 5) (pc)) (const_int 256)))
6457          (const_int 6)
6458          (if_then_else
6459            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6460                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6461            (const_int 8)
6462            (const_int 10)))))]
6465 (define_insn "*addsi3_cbranch_scratch"
6466   [(set (pc)
6467         (if_then_else
6468          (match_operator 3 "comparison_operator"
6469           [(plus:SI
6470             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6471             (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
6472            (const_int 0)])
6473          (label_ref (match_operand 4 "" ""))
6474          (pc)))
6475    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6476   "TARGET_THUMB
6477    && (GET_CODE (operands[3]) == EQ
6478        || GET_CODE (operands[3]) == NE
6479        || GET_CODE (operands[3]) == GE
6480        || GET_CODE (operands[3]) == LT)"
6481   "*
6482    {
6483      switch (which_alternative)
6484        {
6485        case 0:
6486          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6487          break;
6488        case 1:
6489          output_asm_insn (\"cmn\t%1, %2\", operands);
6490          break;
6491        case 2:
6492          if (INTVAL (operands[2]) < 0)
6493            output_asm_insn (\"sub\t%0, %1, %2\", operands);
6494          else
6495            output_asm_insn (\"add\t%0, %1, %2\", operands);
6496          break;
6497        case 3:
6498          if (INTVAL (operands[2]) < 0)
6499            output_asm_insn (\"sub\t%0, %0, %2\", operands);
6500          else
6501            output_asm_insn (\"add\t%0, %0, %2\", operands);
6502          break;
6503        }
6505      switch (get_attr_length (insn))
6506        {
6507          case 4:
6508            return \"b%d3\\t%l4\";
6509          case 6:
6510            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6511          default:
6512            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6513        }
6514    }
6515   "
6516   [(set (attr "far_jump")
6517         (if_then_else
6518             (eq_attr "length" "8")
6519             (const_string "yes")
6520             (const_string "no")))
6521    (set (attr "length")
6522        (if_then_else
6523          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6524               (le (minus (match_dup 4) (pc)) (const_int 256)))
6525          (const_int 4)
6526          (if_then_else
6527            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6528                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6529            (const_int 6)
6530            (const_int 8))))]
6533 (define_insn "*subsi3_cbranch"
6534   [(set (pc)
6535         (if_then_else
6536          (match_operator 4 "comparison_operator"
6537           [(minus:SI
6538             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6539             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6540            (const_int 0)])
6541          (label_ref (match_operand 5 "" ""))
6542          (pc)))
6543    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6544         (minus:SI (match_dup 2) (match_dup 3)))
6545    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6546   "TARGET_THUMB
6547    && (GET_CODE (operands[4]) == EQ
6548        || GET_CODE (operands[4]) == NE
6549        || GET_CODE (operands[4]) == GE
6550        || GET_CODE (operands[4]) == LT)"
6551   "*
6552    {
6553      if (which_alternative == 0)
6554        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6555      else if (which_alternative == 1)
6556        {
6557          /* We must provide an alternative for a hi reg because reload 
6558             cannot handle output reloads on a jump instruction, but we
6559             can't subtract into that.  Fortunately a mov from lo to hi
6560             does not clobber the condition codes.  */
6561          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6562          output_asm_insn (\"mov\\t%0, %1\", operands);
6563        }
6564      else
6565        {
6566          /* Similarly, but the target is memory.  */
6567          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6568          output_asm_insn (\"str\\t%1, %0\", operands);
6569        }
6571      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6572        {
6573          case 4:
6574            return \"b%d4\\t%l5\";
6575          case 6:
6576            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6577          default:
6578            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6579        }
6580    }
6581   "
6582   [(set (attr "far_jump")
6583         (if_then_else
6584             (ior (and (eq (symbol_ref ("which_alternative"))
6585                           (const_int 0))
6586                       (eq_attr "length" "8"))
6587                  (eq_attr "length" "10"))
6588             (const_string "yes")
6589             (const_string "no")))
6590    (set (attr "length")
6591      (if_then_else
6592        (eq (symbol_ref ("which_alternative"))
6593                        (const_int 0))
6594        (if_then_else
6595          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6596               (le (minus (match_dup 5) (pc)) (const_int 256)))
6597          (const_int 4)
6598          (if_then_else
6599            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6600                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6601            (const_int 6)
6602            (const_int 8)))
6603        (if_then_else
6604          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6605               (le (minus (match_dup 5) (pc)) (const_int 256)))
6606          (const_int 6)
6607          (if_then_else
6608            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6609                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6610            (const_int 8)
6611            (const_int 10)))))]
6614 (define_insn "*subsi3_cbranch_scratch"
6615   [(set (pc)
6616         (if_then_else
6617          (match_operator 0 "arm_comparison_operator"
6618           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6619                      (match_operand:SI 2 "nonmemory_operand" "l"))
6620            (const_int 0)])
6621          (label_ref (match_operand 3 "" ""))
6622          (pc)))]
6623   "TARGET_THUMB
6624    && (GET_CODE (operands[0]) == EQ
6625        || GET_CODE (operands[0]) == NE
6626        || GET_CODE (operands[0]) == GE
6627        || GET_CODE (operands[0]) == LT)"
6628   "*
6629   output_asm_insn (\"cmp\\t%1, %2\", operands);
6630   switch (get_attr_length (insn))
6631     {
6632     case 4:  return \"b%d0\\t%l3\";
6633     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6634     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6635     }
6636   "
6637   [(set (attr "far_jump")
6638         (if_then_else
6639             (eq_attr "length" "8")
6640             (const_string "yes")
6641             (const_string "no")))
6642    (set (attr "length") 
6643         (if_then_else
6644             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6645                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6646             (const_int 4)
6647             (if_then_else
6648                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6649                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6650                 (const_int 6)
6651                 (const_int 8))))]
6654 ;; Comparison and test insns
6656 (define_expand "cmpsi"
6657   [(match_operand:SI 0 "s_register_operand" "")
6658    (match_operand:SI 1 "arm_add_operand" "")]
6659   "TARGET_ARM"
6660   "{
6661     arm_compare_op0 = operands[0];
6662     arm_compare_op1 = operands[1];
6663     DONE;
6664   }"
6667 (define_expand "cmpsf"
6668   [(match_operand:SF 0 "s_register_operand" "")
6669    (match_operand:SF 1 "arm_float_compare_operand" "")]
6670   "TARGET_ARM && TARGET_HARD_FLOAT"
6671   "
6672   arm_compare_op0 = operands[0];
6673   arm_compare_op1 = operands[1];
6674   DONE;
6675   "
6678 (define_expand "cmpdf"
6679   [(match_operand:DF 0 "s_register_operand" "")
6680    (match_operand:DF 1 "arm_float_compare_operand" "")]
6681   "TARGET_ARM && TARGET_HARD_FLOAT"
6682   "
6683   arm_compare_op0 = operands[0];
6684   arm_compare_op1 = operands[1];
6685   DONE;
6686   "
6689 (define_insn "*arm_cmpsi_insn"
6690   [(set (reg:CC CC_REGNUM)
6691         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6692                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6693   "TARGET_ARM"
6694   "@
6695    cmp%?\\t%0, %1
6696    cmn%?\\t%0, #%n1"
6697   [(set_attr "conds" "set")]
6700 (define_insn "*cmpsi_shiftsi"
6701   [(set (reg:CC CC_REGNUM)
6702         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6703                     (match_operator:SI  3 "shift_operator"
6704                      [(match_operand:SI 1 "s_register_operand" "r")
6705                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6706   "TARGET_ARM"
6707   "cmp%?\\t%0, %1%S3"
6708   [(set_attr "conds" "set")
6709    (set_attr "shift" "1")
6710    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6711                       (const_string "alu_shift")
6712                       (const_string "alu_shift_reg")))]
6715 (define_insn "*cmpsi_shiftsi_swp"
6716   [(set (reg:CC_SWP CC_REGNUM)
6717         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6718                          [(match_operand:SI 1 "s_register_operand" "r")
6719                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6720                         (match_operand:SI 0 "s_register_operand" "r")))]
6721   "TARGET_ARM"
6722   "cmp%?\\t%0, %1%S3"
6723   [(set_attr "conds" "set")
6724    (set_attr "shift" "1")
6725    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6726                       (const_string "alu_shift")
6727                       (const_string "alu_shift_reg")))]
6730 (define_insn "*cmpsi_neg_shiftsi"
6731   [(set (reg:CC CC_REGNUM)
6732         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6733                     (neg:SI (match_operator:SI 3 "shift_operator"
6734                              [(match_operand:SI 1 "s_register_operand" "r")
6735                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6736   "TARGET_ARM"
6737   "cmn%?\\t%0, %1%S3"
6738   [(set_attr "conds" "set")
6739    (set_attr "shift" "1")
6740    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6741                       (const_string "alu_shift")
6742                       (const_string "alu_shift_reg")))]
6745 ;; Cirrus SF compare instruction
6746 (define_insn "*cirrus_cmpsf"
6747   [(set (reg:CCFP CC_REGNUM)
6748         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6749                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6750   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6751   "cfcmps%?\\tr15, %V0, %V1"
6752   [(set_attr "type"   "mav_farith")
6753    (set_attr "cirrus" "compare")]
6756 ;; Cirrus DF compare instruction
6757 (define_insn "*cirrus_cmpdf"
6758   [(set (reg:CCFP CC_REGNUM)
6759         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6760                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6761   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6762   "cfcmpd%?\\tr15, %V0, %V1"
6763   [(set_attr "type"   "mav_farith")
6764    (set_attr "cirrus" "compare")]
6767 ;; Cirrus DI compare instruction
6768 (define_expand "cmpdi"
6769   [(match_operand:DI 0 "cirrus_fp_register" "")
6770    (match_operand:DI 1 "cirrus_fp_register" "")]
6771   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6772   "{
6773      arm_compare_op0 = operands[0];
6774      arm_compare_op1 = operands[1];
6775      DONE;
6776    }")
6778 (define_insn "*cirrus_cmpdi"
6779   [(set (reg:CC CC_REGNUM)
6780         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6781                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6782   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6783   "cfcmp64%?\\tr15, %V0, %V1"
6784   [(set_attr "type"   "mav_farith")
6785    (set_attr "cirrus" "compare")]
6788 ; This insn allows redundant compares to be removed by cse, nothing should
6789 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6790 ; is deleted later on. The match_dup will match the mode here, so that
6791 ; mode changes of the condition codes aren't lost by this even though we don't
6792 ; specify what they are.
6794 (define_insn "*deleted_compare"
6795   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6796   "TARGET_ARM"
6797   "\\t%@ deleted compare"
6798   [(set_attr "conds" "set")
6799    (set_attr "length" "0")]
6803 ;; Conditional branch insns
6805 (define_expand "beq"
6806   [(set (pc)
6807         (if_then_else (eq (match_dup 1) (const_int 0))
6808                       (label_ref (match_operand 0 "" ""))
6809                       (pc)))]
6810   "TARGET_ARM"
6811   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6814 (define_expand "bne"
6815   [(set (pc)
6816         (if_then_else (ne (match_dup 1) (const_int 0))
6817                       (label_ref (match_operand 0 "" ""))
6818                       (pc)))]
6819   "TARGET_ARM"
6820   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6823 (define_expand "bgt"
6824   [(set (pc)
6825         (if_then_else (gt (match_dup 1) (const_int 0))
6826                       (label_ref (match_operand 0 "" ""))
6827                       (pc)))]
6828   "TARGET_ARM"
6829   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6832 (define_expand "ble"
6833   [(set (pc)
6834         (if_then_else (le (match_dup 1) (const_int 0))
6835                       (label_ref (match_operand 0 "" ""))
6836                       (pc)))]
6837   "TARGET_ARM"
6838   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6841 (define_expand "bge"
6842   [(set (pc)
6843         (if_then_else (ge (match_dup 1) (const_int 0))
6844                       (label_ref (match_operand 0 "" ""))
6845                       (pc)))]
6846   "TARGET_ARM"
6847   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6850 (define_expand "blt"
6851   [(set (pc)
6852         (if_then_else (lt (match_dup 1) (const_int 0))
6853                       (label_ref (match_operand 0 "" ""))
6854                       (pc)))]
6855   "TARGET_ARM"
6856   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6859 (define_expand "bgtu"
6860   [(set (pc)
6861         (if_then_else (gtu (match_dup 1) (const_int 0))
6862                       (label_ref (match_operand 0 "" ""))
6863                       (pc)))]
6864   "TARGET_ARM"
6865   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6868 (define_expand "bleu"
6869   [(set (pc)
6870         (if_then_else (leu (match_dup 1) (const_int 0))
6871                       (label_ref (match_operand 0 "" ""))
6872                       (pc)))]
6873   "TARGET_ARM"
6874   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6877 (define_expand "bgeu"
6878   [(set (pc)
6879         (if_then_else (geu (match_dup 1) (const_int 0))
6880                       (label_ref (match_operand 0 "" ""))
6881                       (pc)))]
6882   "TARGET_ARM"
6883   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6886 (define_expand "bltu"
6887   [(set (pc)
6888         (if_then_else (ltu (match_dup 1) (const_int 0))
6889                       (label_ref (match_operand 0 "" ""))
6890                       (pc)))]
6891   "TARGET_ARM"
6892   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6895 (define_expand "bunordered"
6896   [(set (pc)
6897         (if_then_else (unordered (match_dup 1) (const_int 0))
6898                       (label_ref (match_operand 0 "" ""))
6899                       (pc)))]
6900   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6901   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6902                                       arm_compare_op1);"
6905 (define_expand "bordered"
6906   [(set (pc)
6907         (if_then_else (ordered (match_dup 1) (const_int 0))
6908                       (label_ref (match_operand 0 "" ""))
6909                       (pc)))]
6910   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6911   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6912                                       arm_compare_op1);"
6915 (define_expand "bungt"
6916   [(set (pc)
6917         (if_then_else (ungt (match_dup 1) (const_int 0))
6918                       (label_ref (match_operand 0 "" ""))
6919                       (pc)))]
6920   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6921   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6924 (define_expand "bunlt"
6925   [(set (pc)
6926         (if_then_else (unlt (match_dup 1) (const_int 0))
6927                       (label_ref (match_operand 0 "" ""))
6928                       (pc)))]
6929   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6930   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6933 (define_expand "bunge"
6934   [(set (pc)
6935         (if_then_else (unge (match_dup 1) (const_int 0))
6936                       (label_ref (match_operand 0 "" ""))
6937                       (pc)))]
6938   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6939   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6942 (define_expand "bunle"
6943   [(set (pc)
6944         (if_then_else (unle (match_dup 1) (const_int 0))
6945                       (label_ref (match_operand 0 "" ""))
6946                       (pc)))]
6947   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6948   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6951 ;; The following two patterns need two branch instructions, since there is
6952 ;; no single instruction that will handle all cases.
6953 (define_expand "buneq"
6954   [(set (pc)
6955         (if_then_else (uneq (match_dup 1) (const_int 0))
6956                       (label_ref (match_operand 0 "" ""))
6957                       (pc)))]
6958   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6959   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6962 (define_expand "bltgt"
6963   [(set (pc)
6964         (if_then_else (ltgt (match_dup 1) (const_int 0))
6965                       (label_ref (match_operand 0 "" ""))
6966                       (pc)))]
6967   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6968   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6972 ;; Patterns to match conditional branch insns.
6975 ; Special pattern to match UNEQ.
6976 (define_insn "*arm_buneq"
6977   [(set (pc)
6978         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6979                       (label_ref (match_operand 0 "" ""))
6980                       (pc)))]
6981   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6982   "*
6983   if (arm_ccfsm_state != 0)
6984     abort ();
6986   return \"bvs\\t%l0\;beq\\t%l0\";
6987   "
6988   [(set_attr "conds" "jump_clob")
6989    (set_attr "length" "8")]
6992 ; Special pattern to match LTGT.
6993 (define_insn "*arm_bltgt"
6994   [(set (pc)
6995         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6996                       (label_ref (match_operand 0 "" ""))
6997                       (pc)))]
6998   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6999   "*
7000   if (arm_ccfsm_state != 0)
7001     abort ();
7003   return \"bmi\\t%l0\;bgt\\t%l0\";
7004   "
7005   [(set_attr "conds" "jump_clob")
7006    (set_attr "length" "8")]
7009 (define_insn "*arm_cond_branch"
7010   [(set (pc)
7011         (if_then_else (match_operator 1 "arm_comparison_operator"
7012                        [(match_operand 2 "cc_register" "") (const_int 0)])
7013                       (label_ref (match_operand 0 "" ""))
7014                       (pc)))]
7015   "TARGET_ARM"
7016   "*
7017   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7018     {
7019       arm_ccfsm_state += 2;
7020       return \"\";
7021     }
7022   return \"b%d1\\t%l0\";
7023   "
7024   [(set_attr "conds" "use")
7025    (set_attr "type" "branch")]
7028 ; Special pattern to match reversed UNEQ.
7029 (define_insn "*arm_buneq_reversed"
7030   [(set (pc)
7031         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
7032                       (pc)
7033                       (label_ref (match_operand 0 "" ""))))]
7034   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7035   "*
7036   if (arm_ccfsm_state != 0)
7037     abort ();
7039   return \"bmi\\t%l0\;bgt\\t%l0\";
7040   "
7041   [(set_attr "conds" "jump_clob")
7042    (set_attr "length" "8")]
7045 ; Special pattern to match reversed LTGT.
7046 (define_insn "*arm_bltgt_reversed"
7047   [(set (pc)
7048         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
7049                       (pc)
7050                       (label_ref (match_operand 0 "" ""))))]
7051   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7052   "*
7053   if (arm_ccfsm_state != 0)
7054     abort ();
7056   return \"bvs\\t%l0\;beq\\t%l0\";
7057   "
7058   [(set_attr "conds" "jump_clob")
7059    (set_attr "length" "8")]
7062 (define_insn "*arm_cond_branch_reversed"
7063   [(set (pc)
7064         (if_then_else (match_operator 1 "arm_comparison_operator"
7065                        [(match_operand 2 "cc_register" "") (const_int 0)])
7066                       (pc)
7067                       (label_ref (match_operand 0 "" ""))))]
7068   "TARGET_ARM"
7069   "*
7070   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7071     {
7072       arm_ccfsm_state += 2;
7073       return \"\";
7074     }
7075   return \"b%D1\\t%l0\";
7076   "
7077   [(set_attr "conds" "use")
7078    (set_attr "type" "branch")]
7083 ; scc insns
7085 (define_expand "seq"
7086   [(set (match_operand:SI 0 "s_register_operand" "")
7087         (eq:SI (match_dup 1) (const_int 0)))]
7088   "TARGET_ARM"
7089   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
7092 (define_expand "sne"
7093   [(set (match_operand:SI 0 "s_register_operand" "")
7094         (ne:SI (match_dup 1) (const_int 0)))]
7095   "TARGET_ARM"
7096   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
7099 (define_expand "sgt"
7100   [(set (match_operand:SI 0 "s_register_operand" "")
7101         (gt:SI (match_dup 1) (const_int 0)))]
7102   "TARGET_ARM"
7103   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
7106 (define_expand "sle"
7107   [(set (match_operand:SI 0 "s_register_operand" "")
7108         (le:SI (match_dup 1) (const_int 0)))]
7109   "TARGET_ARM"
7110   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
7113 (define_expand "sge"
7114   [(set (match_operand:SI 0 "s_register_operand" "")
7115         (ge:SI (match_dup 1) (const_int 0)))]
7116   "TARGET_ARM"
7117   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
7120 (define_expand "slt"
7121   [(set (match_operand:SI 0 "s_register_operand" "")
7122         (lt:SI (match_dup 1) (const_int 0)))]
7123   "TARGET_ARM"
7124   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
7127 (define_expand "sgtu"
7128   [(set (match_operand:SI 0 "s_register_operand" "")
7129         (gtu:SI (match_dup 1) (const_int 0)))]
7130   "TARGET_ARM"
7131   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
7134 (define_expand "sleu"
7135   [(set (match_operand:SI 0 "s_register_operand" "")
7136         (leu:SI (match_dup 1) (const_int 0)))]
7137   "TARGET_ARM"
7138   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
7141 (define_expand "sgeu"
7142   [(set (match_operand:SI 0 "s_register_operand" "")
7143         (geu:SI (match_dup 1) (const_int 0)))]
7144   "TARGET_ARM"
7145   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
7148 (define_expand "sltu"
7149   [(set (match_operand:SI 0 "s_register_operand" "")
7150         (ltu:SI (match_dup 1) (const_int 0)))]
7151   "TARGET_ARM"
7152   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
7155 (define_expand "sunordered"
7156   [(set (match_operand:SI 0 "s_register_operand" "")
7157         (unordered:SI (match_dup 1) (const_int 0)))]
7158   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7159   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7160                                       arm_compare_op1);"
7163 (define_expand "sordered"
7164   [(set (match_operand:SI 0 "s_register_operand" "")
7165         (ordered:SI (match_dup 1) (const_int 0)))]
7166   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7167   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7168                                       arm_compare_op1);"
7171 (define_expand "sungt"
7172   [(set (match_operand:SI 0 "s_register_operand" "")
7173         (ungt:SI (match_dup 1) (const_int 0)))]
7174   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7175   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7176                                       arm_compare_op1);"
7179 (define_expand "sunge"
7180   [(set (match_operand:SI 0 "s_register_operand" "")
7181         (unge:SI (match_dup 1) (const_int 0)))]
7182   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7183   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7184                                       arm_compare_op1);"
7187 (define_expand "sunlt"
7188   [(set (match_operand:SI 0 "s_register_operand" "")
7189         (unlt:SI (match_dup 1) (const_int 0)))]
7190   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7191   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7192                                       arm_compare_op1);"
7195 (define_expand "sunle"
7196   [(set (match_operand:SI 0 "s_register_operand" "")
7197         (unle:SI (match_dup 1) (const_int 0)))]
7198   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7199   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7200                                       arm_compare_op1);"
7203 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7204 ;;; simple ARM instructions. 
7206 ; (define_expand "suneq"
7207 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7208 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7209 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7210 ;   "abort ();"
7211 ; )
7213 ; (define_expand "sltgt"
7214 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7215 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7216 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7217 ;   "abort ();"
7218 ; )
7220 (define_insn "*mov_scc"
7221   [(set (match_operand:SI 0 "s_register_operand" "=r")
7222         (match_operator:SI 1 "arm_comparison_operator"
7223          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7224   "TARGET_ARM"
7225   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7226   [(set_attr "conds" "use")
7227    (set_attr "length" "8")]
7230 (define_insn "*mov_negscc"
7231   [(set (match_operand:SI 0 "s_register_operand" "=r")
7232         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7233                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7234   "TARGET_ARM"
7235   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7236   [(set_attr "conds" "use")
7237    (set_attr "length" "8")]
7240 (define_insn "*mov_notscc"
7241   [(set (match_operand:SI 0 "s_register_operand" "=r")
7242         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7243                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7244   "TARGET_ARM"
7245   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7246   [(set_attr "conds" "use")
7247    (set_attr "length" "8")]
7251 ;; Conditional move insns
7253 (define_expand "movsicc"
7254   [(set (match_operand:SI 0 "s_register_operand" "")
7255         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7256                          (match_operand:SI 2 "arm_not_operand" "")
7257                          (match_operand:SI 3 "arm_not_operand" "")))]
7258   "TARGET_ARM"
7259   "
7260   {
7261     enum rtx_code code = GET_CODE (operands[1]);
7262     rtx ccreg;
7264     if (code == UNEQ || code == LTGT)
7265       FAIL;
7267     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7268     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7269   }"
7272 (define_expand "movsfcc"
7273   [(set (match_operand:SF 0 "s_register_operand" "")
7274         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7275                          (match_operand:SF 2 "s_register_operand" "")
7276                          (match_operand:SF 3 "nonmemory_operand" "")))]
7277   "TARGET_ARM"
7278   "
7279   {
7280     enum rtx_code code = GET_CODE (operands[1]);
7281     rtx ccreg;
7283     if (code == UNEQ || code == LTGT)
7284       FAIL;
7286     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7287        Otherwise, ensure it is a valid FP add operand */
7288     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7289         || (!arm_float_add_operand (operands[3], SFmode)))
7290       operands[3] = force_reg (SFmode, operands[3]);
7292     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7293     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7294   }"
7297 (define_expand "movdfcc"
7298   [(set (match_operand:DF 0 "s_register_operand" "")
7299         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7300                          (match_operand:DF 2 "s_register_operand" "")
7301                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7302   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7303   "
7304   {
7305     enum rtx_code code = GET_CODE (operands[1]);
7306     rtx ccreg;
7308     if (code == UNEQ || code == LTGT)
7309       FAIL;
7311     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7312     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7313   }"
7316 (define_insn "*movsicc_insn"
7317   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7318         (if_then_else:SI
7319          (match_operator 3 "arm_comparison_operator"
7320           [(match_operand 4 "cc_register" "") (const_int 0)])
7321          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7322          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7323   "TARGET_ARM"
7324   "@
7325    mov%D3\\t%0, %2
7326    mvn%D3\\t%0, #%B2
7327    mov%d3\\t%0, %1
7328    mvn%d3\\t%0, #%B1
7329    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7330    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7331    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7332    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7333   [(set_attr "length" "4,4,4,4,8,8,8,8")
7334    (set_attr "conds" "use")]
7337 (define_insn "*movsfcc_soft_insn"
7338   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7339         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7340                           [(match_operand 4 "cc_register" "") (const_int 0)])
7341                          (match_operand:SF 1 "s_register_operand" "0,r")
7342                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7343   "TARGET_ARM && TARGET_SOFT_FLOAT"
7344   "@
7345    mov%D3\\t%0, %2
7346    mov%d3\\t%0, %1"
7347   [(set_attr "conds" "use")]
7351 ;; Jump and linkage insns
7353 (define_expand "jump"
7354   [(set (pc)
7355         (label_ref (match_operand 0 "" "")))]
7356   "TARGET_EITHER"
7357   ""
7360 (define_insn "*arm_jump"
7361   [(set (pc)
7362         (label_ref (match_operand 0 "" "")))]
7363   "TARGET_ARM"
7364   "*
7365   {
7366     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7367       {
7368         arm_ccfsm_state += 2;
7369         return \"\";
7370       }
7371     return \"b%?\\t%l0\";
7372   }
7373   "
7374   [(set_attr "predicable" "yes")]
7377 (define_insn "*thumb_jump"
7378   [(set (pc)
7379         (label_ref (match_operand 0 "" "")))]
7380   "TARGET_THUMB"
7381   "*
7382   if (get_attr_length (insn) == 2)
7383     return \"b\\t%l0\";
7384   return \"bl\\t%l0\\t%@ far jump\";
7385   "
7386   [(set (attr "far_jump")
7387         (if_then_else
7388             (eq_attr "length" "4")
7389             (const_string "yes")
7390             (const_string "no")))
7391    (set (attr "length") 
7392         (if_then_else
7393             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7394                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7395             (const_int 2)
7396             (const_int 4)))]
7399 (define_expand "call"
7400   [(parallel [(call (match_operand 0 "memory_operand" "")
7401                     (match_operand 1 "general_operand" ""))
7402               (use (match_operand 2 "" ""))
7403               (clobber (reg:SI LR_REGNUM))])]
7404   "TARGET_EITHER"
7405   "
7406   {
7407     rtx callee;
7408     
7409     /* In an untyped call, we can get NULL for operand 2.  */
7410     if (operands[2] == NULL_RTX)
7411       operands[2] = const0_rtx;
7412       
7413     /* This is to decide if we should generate indirect calls by loading the
7414        32 bit address of the callee into a register before performing the
7415        branch and link.  operand[2] encodes the long_call/short_call
7416        attribute of the function being called.  This attribute is set whenever
7417        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7418        is used, and the short_call attribute can also be set if function is
7419        declared as static or if it has already been defined in the current
7420        compilation unit.  See arm.c and arm.h for info about this.  The third
7421        parameter to arm_is_longcall_p is used to tell it which pattern
7422        invoked it.  */
7423     callee  = XEXP (operands[0], 0);
7424     
7425     if (GET_CODE (callee) != REG
7426        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7427       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7428   }"
7431 (define_insn "*call_reg_armv5"
7432   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7433          (match_operand 1 "" ""))
7434    (use (match_operand 2 "" ""))
7435    (clobber (reg:SI LR_REGNUM))]
7436   "TARGET_ARM && arm_arch5"
7437   "blx%?\\t%0"
7438   [(set_attr "type" "call")]
7441 (define_insn "*call_reg_arm"
7442   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7443          (match_operand 1 "" ""))
7444    (use (match_operand 2 "" ""))
7445    (clobber (reg:SI LR_REGNUM))]
7446   "TARGET_ARM && !arm_arch5"
7447   "*
7448   return output_call (operands);
7449   "
7450   ;; length is worst case, normally it is only two
7451   [(set_attr "length" "12")
7452    (set_attr "type" "call")]
7455 (define_insn "*call_mem"
7456   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7457          (match_operand 1 "" ""))
7458    (use (match_operand 2 "" ""))
7459    (clobber (reg:SI LR_REGNUM))]
7460   "TARGET_ARM"
7461   "*
7462   return output_call_mem (operands);
7463   "
7464   [(set_attr "length" "12")
7465    (set_attr "type" "call")]
7468 (define_insn "*call_reg_thumb_v5"
7469   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7470          (match_operand 1 "" ""))
7471    (use (match_operand 2 "" ""))
7472    (clobber (reg:SI LR_REGNUM))]
7473   "TARGET_THUMB && arm_arch5"
7474   "blx\\t%0"
7475   [(set_attr "length" "2")
7476    (set_attr "type" "call")]
7479 (define_insn "*call_reg_thumb"
7480   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7481          (match_operand 1 "" ""))
7482    (use (match_operand 2 "" ""))
7483    (clobber (reg:SI LR_REGNUM))]
7484   "TARGET_THUMB && !arm_arch5"
7485   "*
7486   {
7487     if (!TARGET_CALLER_INTERWORKING)
7488       return thumb_call_via_reg (operands[0]);
7489     else if (operands[1] == const0_rtx)
7490       return \"bl\\t%__interwork_call_via_%0\";
7491     else if (frame_pointer_needed)
7492       return \"bl\\t%__interwork_r7_call_via_%0\";
7493     else
7494       return \"bl\\t%__interwork_r11_call_via_%0\";
7495   }"
7496   [(set_attr "type" "call")]
7499 (define_expand "call_value"
7500   [(parallel [(set (match_operand       0 "" "")
7501                    (call (match_operand 1 "memory_operand" "")
7502                          (match_operand 2 "general_operand" "")))
7503               (use (match_operand 3 "" ""))
7504               (clobber (reg:SI LR_REGNUM))])]
7505   "TARGET_EITHER"
7506   "
7507   {
7508     rtx callee = XEXP (operands[1], 0);
7509     
7510     /* In an untyped call, we can get NULL for operand 2.  */
7511     if (operands[3] == 0)
7512       operands[3] = const0_rtx;
7513       
7514     /* See the comment in define_expand \"call\".  */
7515     if (GET_CODE (callee) != REG
7516         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7517       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7518   }"
7521 (define_insn "*call_value_reg_armv5"
7522   [(set (match_operand 0 "" "")
7523         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7524               (match_operand 2 "" "")))
7525    (use (match_operand 3 "" ""))
7526    (clobber (reg:SI LR_REGNUM))]
7527   "TARGET_ARM && arm_arch5"
7528   "blx%?\\t%1"
7529   [(set_attr "type" "call")]
7532 (define_insn "*call_value_reg_arm"
7533   [(set (match_operand 0 "" "")
7534         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7535               (match_operand 2 "" "")))
7536    (use (match_operand 3 "" ""))
7537    (clobber (reg:SI LR_REGNUM))]
7538   "TARGET_ARM && !arm_arch5"
7539   "*
7540   return output_call (&operands[1]);
7541   "
7542   [(set_attr "length" "12")
7543    (set_attr "type" "call")]
7546 (define_insn "*call_value_mem"
7547   [(set (match_operand 0 "" "")
7548         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7549               (match_operand 2 "" "")))
7550    (use (match_operand 3 "" ""))
7551    (clobber (reg:SI LR_REGNUM))]
7552   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7553   "*
7554   return output_call_mem (&operands[1]);
7555   "
7556   [(set_attr "length" "12")
7557    (set_attr "type" "call")]
7560 (define_insn "*call_value_reg_thumb_v5"
7561   [(set (match_operand 0 "" "")
7562         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7563               (match_operand 2 "" "")))
7564    (use (match_operand 3 "" ""))
7565    (clobber (reg:SI LR_REGNUM))]
7566   "TARGET_THUMB && arm_arch5"
7567   "blx\\t%1"
7568   [(set_attr "length" "2")
7569    (set_attr "type" "call")]
7572 (define_insn "*call_value_reg_thumb"
7573   [(set (match_operand 0 "" "")
7574         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7575               (match_operand 2 "" "")))
7576    (use (match_operand 3 "" ""))
7577    (clobber (reg:SI LR_REGNUM))]
7578   "TARGET_THUMB && !arm_arch5"
7579   "*
7580   {
7581     if (!TARGET_CALLER_INTERWORKING)
7582       return thumb_call_via_reg (operands[1]);
7583     else if (operands[2] == const0_rtx)
7584       return \"bl\\t%__interwork_call_via_%1\";
7585     else if (frame_pointer_needed)
7586       return \"bl\\t%__interwork_r7_call_via_%1\";
7587     else
7588       return \"bl\\t%__interwork_r11_call_via_%1\";
7589   }"
7590   [(set_attr "type" "call")]
7593 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7594 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7596 (define_insn "*call_symbol"
7597   [(call (mem:SI (match_operand:SI 0 "" ""))
7598          (match_operand 1 "" ""))
7599    (use (match_operand 2 "" ""))
7600    (clobber (reg:SI LR_REGNUM))]
7601   "TARGET_ARM
7602    && (GET_CODE (operands[0]) == SYMBOL_REF)
7603    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7604   "*
7605   {
7606     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7607   }"
7608   [(set_attr "type" "call")]
7611 (define_insn "*call_value_symbol"
7612   [(set (match_operand 0 "" "")
7613         (call (mem:SI (match_operand:SI 1 "" ""))
7614         (match_operand:SI 2 "" "")))
7615    (use (match_operand 3 "" ""))
7616    (clobber (reg:SI LR_REGNUM))]
7617   "TARGET_ARM
7618    && (GET_CODE (operands[1]) == SYMBOL_REF)
7619    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7620   "*
7621   {
7622     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7623   }"
7624   [(set_attr "type" "call")]
7627 (define_insn "*call_insn"
7628   [(call (mem:SI (match_operand:SI 0 "" ""))
7629          (match_operand:SI 1 "" ""))
7630    (use (match_operand 2 "" ""))
7631    (clobber (reg:SI LR_REGNUM))]
7632   "TARGET_THUMB
7633    && GET_CODE (operands[0]) == SYMBOL_REF
7634    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7635   "bl\\t%a0"
7636   [(set_attr "length" "4")
7637    (set_attr "type" "call")]
7640 (define_insn "*call_value_insn"
7641   [(set (match_operand 0 "" "")
7642         (call (mem:SI (match_operand 1 "" ""))
7643               (match_operand 2 "" "")))
7644    (use (match_operand 3 "" ""))
7645    (clobber (reg:SI LR_REGNUM))]
7646   "TARGET_THUMB
7647    && GET_CODE (operands[1]) == SYMBOL_REF
7648    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7649   "bl\\t%a1"
7650   [(set_attr "length" "4")
7651    (set_attr "type" "call")]
7654 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7655 (define_expand "sibcall"
7656   [(parallel [(call (match_operand 0 "memory_operand" "")
7657                     (match_operand 1 "general_operand" ""))
7658               (return)
7659               (use (match_operand 2 "" ""))])]
7660   "TARGET_ARM"
7661   "
7662   {
7663     if (operands[2] == NULL_RTX)
7664       operands[2] = const0_rtx;
7665   }"
7668 (define_expand "sibcall_value"
7669   [(parallel [(set (match_operand 0 "" "")
7670                    (call (match_operand 1 "memory_operand" "")
7671                          (match_operand 2 "general_operand" "")))
7672               (return)
7673               (use (match_operand 3 "" ""))])]
7674   "TARGET_ARM"
7675   "
7676   {
7677     if (operands[3] == NULL_RTX)
7678       operands[3] = const0_rtx;
7679   }"
7682 (define_insn "*sibcall_insn"
7683  [(call (mem:SI (match_operand:SI 0 "" "X"))
7684         (match_operand 1 "" ""))
7685   (return)
7686   (use (match_operand 2 "" ""))]
7687   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7688   "*
7689   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7690   "
7691   [(set_attr "type" "call")]
7694 (define_insn "*sibcall_value_insn"
7695  [(set (match_operand 0 "" "")
7696        (call (mem:SI (match_operand:SI 1 "" "X"))
7697              (match_operand 2 "" "")))
7698   (return)
7699   (use (match_operand 3 "" ""))]
7700   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7701   "*
7702   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7703   "
7704   [(set_attr "type" "call")]
7707 ;; Often the return insn will be the same as loading from memory, so set attr
7708 (define_insn "return"
7709   [(return)]
7710   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7711   "*
7712   {
7713     if (arm_ccfsm_state == 2)
7714       {
7715         arm_ccfsm_state += 2;
7716         return \"\";
7717       }
7718     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7719   }"
7720   [(set_attr "type" "load1")
7721    (set_attr "length" "12")
7722    (set_attr "predicable" "yes")]
7725 (define_insn "*cond_return"
7726   [(set (pc)
7727         (if_then_else (match_operator 0 "arm_comparison_operator"
7728                        [(match_operand 1 "cc_register" "") (const_int 0)])
7729                       (return)
7730                       (pc)))]
7731   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7732   "*
7733   {
7734     if (arm_ccfsm_state == 2)
7735       {
7736         arm_ccfsm_state += 2;
7737         return \"\";
7738       }
7739     return output_return_instruction (operands[0], TRUE, FALSE);
7740   }"
7741   [(set_attr "conds" "use")
7742    (set_attr "length" "12")
7743    (set_attr "type" "load1")]
7746 (define_insn "*cond_return_inverted"
7747   [(set (pc)
7748         (if_then_else (match_operator 0 "arm_comparison_operator"
7749                        [(match_operand 1 "cc_register" "") (const_int 0)])
7750                       (pc)
7751                       (return)))]
7752   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7753   "*
7754   {
7755     if (arm_ccfsm_state == 2)
7756       {
7757         arm_ccfsm_state += 2;
7758         return \"\";
7759       }
7760     return output_return_instruction (operands[0], TRUE, TRUE);
7761   }"
7762   [(set_attr "conds" "use")
7763    (set_attr "length" "12")
7764    (set_attr "type" "load1")]
7767 ;; Generate a sequence of instructions to determine if the processor is
7768 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7769 ;; mask.
7771 (define_expand "return_addr_mask"
7772   [(set (match_dup 1)
7773       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7774                        (const_int 0)))
7775    (set (match_operand:SI 0 "s_register_operand" "")
7776       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7777                        (const_int -1)
7778                        (const_int 67108860)))] ; 0x03fffffc
7779   "TARGET_ARM"
7780   "
7781   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7782   ")
7784 (define_insn "*check_arch2"
7785   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7786       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7787                        (const_int 0)))]
7788   "TARGET_ARM"
7789   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7790   [(set_attr "length" "8")
7791    (set_attr "conds" "set")]
7794 ;; Call subroutine returning any type.
7796 (define_expand "untyped_call"
7797   [(parallel [(call (match_operand 0 "" "")
7798                     (const_int 0))
7799               (match_operand 1 "" "")
7800               (match_operand 2 "" "")])]
7801   "TARGET_EITHER"
7802   "
7803   {
7804     int i;
7805     rtx par = gen_rtx_PARALLEL (VOIDmode,
7806                                 rtvec_alloc (XVECLEN (operands[2], 0)));
7807     rtx addr = gen_reg_rtx (Pmode);
7808     rtx mem;
7809     int size = 0;
7811     emit_move_insn (addr, XEXP (operands[1], 0));
7812     mem = change_address (operands[1], BLKmode, addr);
7814     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7815       {
7816         rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
7818         /* Default code only uses r0 as a return value, but we could
7819            be using anything up to 4 registers.  */
7820         if (REGNO (src) == R0_REGNUM)
7821           src = gen_rtx_REG (TImode, R0_REGNUM);
7823         XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
7824                                                  GEN_INT (size));
7825         size += GET_MODE_SIZE (GET_MODE (src));
7826       }
7828     emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
7829                                     const0_rtx));
7831     size = 0;
7833     for (i = 0; i < XVECLEN (par, 0); i++)
7834       {
7835         HOST_WIDE_INT offset = 0;
7836         rtx reg = XEXP (XVECEXP (par, 0, i), 0);
7838         if (size != 0)
7839           emit_move_insn (addr, plus_constant (addr, size));
7841         mem = change_address (mem, GET_MODE (reg), NULL);
7842         if (REGNO (reg) == R0_REGNUM)
7843           {
7844             /* On thumb we have to use a write-back instruction.  */
7845             emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
7846                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7847             size = TARGET_ARM ? 16 : 0;
7848           }
7849         else
7850           {
7851             emit_move_insn (mem, reg);
7852             size = GET_MODE_SIZE (GET_MODE (reg));
7853           }
7854       }
7856     /* The optimizer does not know that the call sets the function value
7857        registers we stored in the result block.  We avoid problems by
7858        claiming that all hard registers are used and clobbered at this
7859        point.  */
7860     emit_insn (gen_blockage ());
7862     DONE;
7863   }"
7866 (define_expand "untyped_return"
7867   [(match_operand:BLK 0 "memory_operand" "")
7868    (match_operand 1 "" "")]
7869   "TARGET_EITHER"
7870   "
7871   {
7872     int i;
7873     rtx addr = gen_reg_rtx (Pmode);
7874     rtx mem;
7875     int size = 0;
7877     emit_move_insn (addr, XEXP (operands[0], 0));
7878     mem = change_address (operands[0], BLKmode, addr);
7880     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7881       {
7882         HOST_WIDE_INT offset = 0;
7883         rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
7885         if (size != 0)
7886           emit_move_insn (addr, plus_constant (addr, size));
7888         mem = change_address (mem, GET_MODE (reg), NULL);
7889         if (REGNO (reg) == R0_REGNUM)
7890           {
7891             /* On thumb we have to use a write-back instruction.  */
7892             emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
7893                         TARGET_THUMB ? TRUE : FALSE, mem, &offset));
7894             size = TARGET_ARM ? 16 : 0;
7895           }
7896         else
7897           {
7898             emit_move_insn (reg, mem);
7899             size = GET_MODE_SIZE (GET_MODE (reg));
7900           }
7901       }
7903     /* Emit USE insns before the return.  */
7904     for (i = 0; i < XVECLEN (operands[1], 0); i++)
7905       emit_insn (gen_rtx_USE (VOIDmode,
7906                               SET_DEST (XVECEXP (operands[1], 0, i))));
7908     /* Construct the return.  */
7909     expand_naked_return ();
7911     DONE;
7912   }"
7915 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7916 ;; all of memory.  This blocks insns from being moved across this point.
7918 (define_insn "blockage"
7919   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7920   "TARGET_EITHER"
7921   ""
7922   [(set_attr "length" "0")
7923    (set_attr "type" "block")]
7926 (define_expand "casesi"
7927   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7928    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7929    (match_operand:SI 2 "const_int_operand" "")  ; total range
7930    (match_operand:SI 3 "" "")                   ; table label
7931    (match_operand:SI 4 "" "")]                  ; Out of range label
7932   "TARGET_ARM"
7933   "
7934   {
7935     rtx reg;
7936     if (operands[1] != const0_rtx)
7937       {
7938         reg = gen_reg_rtx (SImode);
7940         emit_insn (gen_addsi3 (reg, operands[0],
7941                                GEN_INT (-INTVAL (operands[1]))));
7942         operands[0] = reg;
7943       }
7945     if (!const_ok_for_arm (INTVAL (operands[2])))
7946       operands[2] = force_reg (SImode, operands[2]);
7948     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7949                                          operands[4]));
7950     DONE;
7951   }"
7954 ;; The USE in this pattern is needed to tell flow analysis that this is
7955 ;; a CASESI insn.  It has no other purpose.
7956 (define_insn "casesi_internal"
7957   [(parallel [(set (pc)
7958                (if_then_else
7959                 (leu (match_operand:SI 0 "s_register_operand" "r")
7960                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7961                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7962                                  (label_ref (match_operand 2 "" ""))))
7963                 (label_ref (match_operand 3 "" ""))))
7964               (clobber (reg:CC CC_REGNUM))
7965               (use (label_ref (match_dup 2)))])]
7966   "TARGET_ARM"
7967   "*
7968     if (flag_pic)
7969       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7970     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7971   "
7972   [(set_attr "conds" "clob")
7973    (set_attr "length" "12")]
7976 (define_expand "indirect_jump"
7977   [(set (pc)
7978         (match_operand:SI 0 "s_register_operand" ""))]
7979   "TARGET_EITHER"
7980   ""
7983 ;; NB Never uses BX.
7984 (define_insn "*arm_indirect_jump"
7985   [(set (pc)
7986         (match_operand:SI 0 "s_register_operand" "r"))]
7987   "TARGET_ARM"
7988   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7989   [(set_attr "predicable" "yes")]
7992 (define_insn "*load_indirect_jump"
7993   [(set (pc)
7994         (match_operand:SI 0 "memory_operand" "m"))]
7995   "TARGET_ARM"
7996   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7997   [(set_attr "type" "load1")
7998    (set_attr "pool_range" "4096")
7999    (set_attr "neg_pool_range" "4084")
8000    (set_attr "predicable" "yes")]
8003 ;; NB Never uses BX.
8004 (define_insn "*thumb_indirect_jump"
8005   [(set (pc)
8006         (match_operand:SI 0 "register_operand" "l*r"))]
8007   "TARGET_THUMB"
8008   "mov\\tpc, %0"
8009   [(set_attr "conds" "clob")
8010    (set_attr "length" "2")]
8014 ;; Misc insns
8016 (define_insn "nop"
8017   [(const_int 0)]
8018   "TARGET_EITHER"
8019   "*
8020   if (TARGET_ARM)
8021     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
8022   return  \"mov\\tr8, r8\";
8023   "
8024   [(set (attr "length")
8025         (if_then_else (eq_attr "is_thumb" "yes")
8026                       (const_int 2)
8027                       (const_int 4)))]
8031 ;; Patterns to allow combination of arithmetic, cond code and shifts
8033 (define_insn "*arith_shiftsi"
8034   [(set (match_operand:SI 0 "s_register_operand" "=r")
8035         (match_operator:SI 1 "shiftable_operator"
8036           [(match_operator:SI 3 "shift_operator"
8037              [(match_operand:SI 4 "s_register_operand" "r")
8038               (match_operand:SI 5 "reg_or_int_operand" "rI")])
8039            (match_operand:SI 2 "s_register_operand" "r")]))]
8040   "TARGET_ARM"
8041   "%i1%?\\t%0, %2, %4%S3"
8042   [(set_attr "predicable" "yes")
8043    (set_attr "shift" "4")
8044    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8045                       (const_string "alu_shift")
8046                       (const_string "alu_shift_reg")))]
8049 (define_split
8050   [(set (match_operand:SI 0 "s_register_operand" "")
8051         (match_operator:SI 1 "shiftable_operator"
8052          [(match_operator:SI 2 "shiftable_operator"
8053            [(match_operator:SI 3 "shift_operator"
8054              [(match_operand:SI 4 "s_register_operand" "")
8055               (match_operand:SI 5 "reg_or_int_operand" "")])
8056             (match_operand:SI 6 "s_register_operand" "")])
8057           (match_operand:SI 7 "arm_rhs_operand" "")]))
8058    (clobber (match_operand:SI 8 "s_register_operand" ""))]
8059   "TARGET_ARM"
8060   [(set (match_dup 8)
8061         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8062                          (match_dup 6)]))
8063    (set (match_dup 0)
8064         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
8065   "")
8067 (define_insn "*arith_shiftsi_compare0"
8068   [(set (reg:CC_NOOV CC_REGNUM)
8069         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8070                           [(match_operator:SI 3 "shift_operator"
8071                             [(match_operand:SI 4 "s_register_operand" "r")
8072                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8073                            (match_operand:SI 2 "s_register_operand" "r")])
8074                          (const_int 0)))
8075    (set (match_operand:SI 0 "s_register_operand" "=r")
8076         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
8077                          (match_dup 2)]))]
8078   "TARGET_ARM"
8079   "%i1%?s\\t%0, %2, %4%S3"
8080   [(set_attr "conds" "set")
8081    (set_attr "shift" "4")
8082    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8083                       (const_string "alu_shift")
8084                       (const_string "alu_shift_reg")))]
8087 (define_insn "*arith_shiftsi_compare0_scratch"
8088   [(set (reg:CC_NOOV CC_REGNUM)
8089         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
8090                           [(match_operator:SI 3 "shift_operator"
8091                             [(match_operand:SI 4 "s_register_operand" "r")
8092                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
8093                            (match_operand:SI 2 "s_register_operand" "r")])
8094                          (const_int 0)))
8095    (clobber (match_scratch:SI 0 "=r"))]
8096   "TARGET_ARM"
8097   "%i1%?s\\t%0, %2, %4%S3"
8098   [(set_attr "conds" "set")
8099    (set_attr "shift" "4")
8100    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
8101                       (const_string "alu_shift")
8102                       (const_string "alu_shift_reg")))]
8105 (define_insn "*sub_shiftsi"
8106   [(set (match_operand:SI 0 "s_register_operand" "=r")
8107         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8108                   (match_operator:SI 2 "shift_operator"
8109                    [(match_operand:SI 3 "s_register_operand" "r")
8110                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
8111   "TARGET_ARM"
8112   "sub%?\\t%0, %1, %3%S2"
8113   [(set_attr "predicable" "yes")
8114    (set_attr "shift" "3")
8115    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8116                       (const_string "alu_shift")
8117                       (const_string "alu_shift_reg")))]
8120 (define_insn "*sub_shiftsi_compare0"
8121   [(set (reg:CC_NOOV CC_REGNUM)
8122         (compare:CC_NOOV
8123          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8124                    (match_operator:SI 2 "shift_operator"
8125                     [(match_operand:SI 3 "s_register_operand" "r")
8126                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8127          (const_int 0)))
8128    (set (match_operand:SI 0 "s_register_operand" "=r")
8129         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8130                                                  (match_dup 4)])))]
8131   "TARGET_ARM"
8132   "sub%?s\\t%0, %1, %3%S2"
8133   [(set_attr "conds" "set")
8134    (set_attr "shift" "3")
8135    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8136                       (const_string "alu_shift")
8137                       (const_string "alu_shift_reg")))]
8140 (define_insn "*sub_shiftsi_compare0_scratch"
8141   [(set (reg:CC_NOOV CC_REGNUM)
8142         (compare:CC_NOOV
8143          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
8144                    (match_operator:SI 2 "shift_operator"
8145                     [(match_operand:SI 3 "s_register_operand" "r")
8146                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
8147          (const_int 0)))
8148    (clobber (match_scratch:SI 0 "=r"))]
8149   "TARGET_ARM"
8150   "sub%?s\\t%0, %1, %3%S2"
8151   [(set_attr "conds" "set")
8152    (set_attr "shift" "3")
8153    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
8154                       (const_string "alu_shift")
8155                       (const_string "alu_shift_reg")))]
8160 (define_insn "*and_scc"
8161   [(set (match_operand:SI 0 "s_register_operand" "=r")
8162         (and:SI (match_operator:SI 1 "arm_comparison_operator"
8163                  [(match_operand 3 "cc_register" "") (const_int 0)])
8164                 (match_operand:SI 2 "s_register_operand" "r")))]
8165   "TARGET_ARM"
8166   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
8167   [(set_attr "conds" "use")
8168    (set_attr "length" "8")]
8171 (define_insn "*ior_scc"
8172   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8173         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
8174                  [(match_operand 3 "cc_register" "") (const_int 0)])
8175                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
8176   "TARGET_ARM"
8177   "@
8178    orr%d2\\t%0, %1, #1
8179    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
8180   [(set_attr "conds" "use")
8181    (set_attr "length" "4,8")]
8184 (define_insn "*compare_scc"
8185   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8186         (match_operator:SI 1 "arm_comparison_operator"
8187          [(match_operand:SI 2 "s_register_operand" "r,r")
8188           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
8189    (clobber (reg:CC CC_REGNUM))]
8190   "TARGET_ARM"
8191   "*
8192     if (operands[3] == const0_rtx)
8193       {
8194         if (GET_CODE (operands[1]) == LT)
8195           return \"mov\\t%0, %2, lsr #31\";
8197         if (GET_CODE (operands[1]) == GE)
8198           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
8200         if (GET_CODE (operands[1]) == EQ)
8201           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
8202       }
8204     if (GET_CODE (operands[1]) == NE)
8205       {
8206         if (which_alternative == 1)
8207           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
8208         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
8209       }
8210     if (which_alternative == 1)
8211       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8212     else
8213       output_asm_insn (\"cmp\\t%2, %3\", operands);
8214     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
8215   "
8216   [(set_attr "conds" "clob")
8217    (set_attr "length" "12")]
8220 (define_insn "*cond_move"
8221   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8222         (if_then_else:SI (match_operator 3 "equality_operator"
8223                           [(match_operator 4 "arm_comparison_operator"
8224                             [(match_operand 5 "cc_register" "") (const_int 0)])
8225                            (const_int 0)])
8226                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8227                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
8228   "TARGET_ARM"
8229   "*
8230     if (GET_CODE (operands[3]) == NE)
8231       {
8232         if (which_alternative != 1)
8233           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
8234         if (which_alternative != 0)
8235           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
8236         return \"\";
8237       }
8238     if (which_alternative != 0)
8239       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8240     if (which_alternative != 1)
8241       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
8242     return \"\";
8243   "
8244   [(set_attr "conds" "use")
8245    (set_attr "length" "4,4,8")]
8248 (define_insn "*cond_arith"
8249   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8250         (match_operator:SI 5 "shiftable_operator" 
8251          [(match_operator:SI 4 "arm_comparison_operator"
8252            [(match_operand:SI 2 "s_register_operand" "r,r")
8253             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8254           (match_operand:SI 1 "s_register_operand" "0,?r")]))
8255    (clobber (reg:CC CC_REGNUM))]
8256   "TARGET_ARM"
8257   "*
8258     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
8259       return \"%i5\\t%0, %1, %2, lsr #31\";
8261     output_asm_insn (\"cmp\\t%2, %3\", operands);
8262     if (GET_CODE (operands[5]) == AND)
8263       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
8264     else if (GET_CODE (operands[5]) == MINUS)
8265       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
8266     else if (which_alternative != 0)
8267       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8268     return \"%i5%d4\\t%0, %1, #1\";
8269   "
8270   [(set_attr "conds" "clob")
8271    (set_attr "length" "12")]
8274 (define_insn "*cond_sub"
8275   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8276         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
8277                   (match_operator:SI 4 "arm_comparison_operator"
8278                    [(match_operand:SI 2 "s_register_operand" "r,r")
8279                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8280    (clobber (reg:CC CC_REGNUM))]
8281   "TARGET_ARM"
8282   "*
8283     output_asm_insn (\"cmp\\t%2, %3\", operands);
8284     if (which_alternative != 0)
8285       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
8286     return \"sub%d4\\t%0, %1, #1\";
8287   "
8288   [(set_attr "conds" "clob")
8289    (set_attr "length" "8,12")]
8292 (define_insn "*cmp_ite0"
8293   [(set (match_operand 6 "dominant_cc_register" "")
8294         (compare
8295          (if_then_else:SI
8296           (match_operator 4 "arm_comparison_operator"
8297            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8298             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8299           (match_operator:SI 5 "arm_comparison_operator"
8300            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8301             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8302           (const_int 0))
8303          (const_int 0)))]
8304   "TARGET_ARM"
8305   "*
8306   {
8307     static const char * const opcodes[4][2] =
8308     {
8309       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8310        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8311       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8312        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8313       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8314        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8315       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8316        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8317     };
8318     int swap =
8319       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8321     return opcodes[which_alternative][swap];
8322   }"
8323   [(set_attr "conds" "set")
8324    (set_attr "length" "8")]
8327 (define_insn "*cmp_ite1"
8328   [(set (match_operand 6 "dominant_cc_register" "")
8329         (compare
8330          (if_then_else:SI
8331           (match_operator 4 "arm_comparison_operator"
8332            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8333             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8334           (match_operator:SI 5 "arm_comparison_operator"
8335            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8336             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8337           (const_int 1))
8338          (const_int 0)))]
8339   "TARGET_ARM"
8340   "*
8341   {
8342     static const char * const opcodes[4][2] =
8343     {
8344       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8345        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8346       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8347        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8348       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8349        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8350       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8351        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8352     };
8353     int swap =
8354       comparison_dominates_p (GET_CODE (operands[5]),
8355                               reverse_condition (GET_CODE (operands[4])));
8357     return opcodes[which_alternative][swap];
8358   }"
8359   [(set_attr "conds" "set")
8360    (set_attr "length" "8")]
8363 (define_insn "*cmp_and"
8364   [(set (match_operand 6 "dominant_cc_register" "")
8365         (compare
8366          (and:SI
8367           (match_operator 4 "arm_comparison_operator"
8368            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8369             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8370           (match_operator:SI 5 "arm_comparison_operator"
8371            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8372             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8373          (const_int 0)))]
8374   "TARGET_ARM"
8375   "*
8376   {
8377     static const char *const opcodes[4][2] =
8378     {
8379       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8380        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8381       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8382        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8383       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8384        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8385       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8386        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8387     };
8388     int swap =
8389       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8391     return opcodes[which_alternative][swap];
8392   }"
8393   [(set_attr "conds" "set")
8394    (set_attr "predicable" "no")
8395    (set_attr "length" "8")]
8398 (define_insn "*cmp_ior"
8399   [(set (match_operand 6 "dominant_cc_register" "")
8400         (compare
8401          (ior:SI
8402           (match_operator 4 "arm_comparison_operator"
8403            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8404             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8405           (match_operator:SI 5 "arm_comparison_operator"
8406            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8407             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8408          (const_int 0)))]
8409   "TARGET_ARM"
8410   "*
8412   static const char *const opcodes[4][2] =
8413   {
8414     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8415      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8416     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8417      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8418     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8419      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8420     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8421      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8422   };
8423   int swap =
8424     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8426   return opcodes[which_alternative][swap];
8429   [(set_attr "conds" "set")
8430    (set_attr "length" "8")]
8433 (define_insn_and_split "*ior_scc_scc"
8434   [(set (match_operand:SI 0 "s_register_operand" "=r")
8435         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8436                  [(match_operand:SI 1 "s_register_operand" "r")
8437                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8438                 (match_operator:SI 6 "arm_comparison_operator"
8439                  [(match_operand:SI 4 "s_register_operand" "r")
8440                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8441    (clobber (reg:CC CC_REGNUM))]
8442   "TARGET_ARM
8443    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8444        != CCmode)"
8445   "#"
8446   "TARGET_ARM && reload_completed"
8447   [(set (match_dup 7)
8448         (compare
8449          (ior:SI
8450           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8451           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8452          (const_int 0)))
8453    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8454   "operands[7]
8455      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8456                                                   DOM_CC_X_OR_Y),
8457                     CC_REGNUM);"
8458   [(set_attr "conds" "clob")
8459    (set_attr "length" "16")])
8461 ; If the above pattern is followed by a CMP insn, then the compare is 
8462 ; redundant, since we can rework the conditional instruction that follows.
8463 (define_insn_and_split "*ior_scc_scc_cmp"
8464   [(set (match_operand 0 "dominant_cc_register" "")
8465         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8466                           [(match_operand:SI 1 "s_register_operand" "r")
8467                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8468                          (match_operator:SI 6 "arm_comparison_operator"
8469                           [(match_operand:SI 4 "s_register_operand" "r")
8470                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8471                  (const_int 0)))
8472    (set (match_operand:SI 7 "s_register_operand" "=r")
8473         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8474                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8475   "TARGET_ARM"
8476   "#"
8477   "TARGET_ARM && reload_completed"
8478   [(set (match_dup 0)
8479         (compare
8480          (ior:SI
8481           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8482           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8483          (const_int 0)))
8484    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8485   ""
8486   [(set_attr "conds" "set")
8487    (set_attr "length" "16")])
8489 (define_insn_and_split "*and_scc_scc"
8490   [(set (match_operand:SI 0 "s_register_operand" "=r")
8491         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8492                  [(match_operand:SI 1 "s_register_operand" "r")
8493                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8494                 (match_operator:SI 6 "arm_comparison_operator"
8495                  [(match_operand:SI 4 "s_register_operand" "r")
8496                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8497    (clobber (reg:CC CC_REGNUM))]
8498   "TARGET_ARM
8499    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8500        != CCmode)"
8501   "#"
8502   "TARGET_ARM && reload_completed
8503    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8504        != CCmode)"
8505   [(set (match_dup 7)
8506         (compare
8507          (and:SI
8508           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8509           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8510          (const_int 0)))
8511    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8512   "operands[7]
8513      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8514                                                   DOM_CC_X_AND_Y),
8515                     CC_REGNUM);"
8516   [(set_attr "conds" "clob")
8517    (set_attr "length" "16")])
8519 ; If the above pattern is followed by a CMP insn, then the compare is 
8520 ; redundant, since we can rework the conditional instruction that follows.
8521 (define_insn_and_split "*and_scc_scc_cmp"
8522   [(set (match_operand 0 "dominant_cc_register" "")
8523         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8524                           [(match_operand:SI 1 "s_register_operand" "r")
8525                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8526                          (match_operator:SI 6 "arm_comparison_operator"
8527                           [(match_operand:SI 4 "s_register_operand" "r")
8528                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8529                  (const_int 0)))
8530    (set (match_operand:SI 7 "s_register_operand" "=r")
8531         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8532                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8533   "TARGET_ARM"
8534   "#"
8535   "TARGET_ARM && reload_completed"
8536   [(set (match_dup 0)
8537         (compare
8538          (and:SI
8539           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8540           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8541          (const_int 0)))
8542    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8543   ""
8544   [(set_attr "conds" "set")
8545    (set_attr "length" "16")])
8547 ;; If there is no dominance in the comparison, then we can still save an
8548 ;; instruction in the AND case, since we can know that the second compare
8549 ;; need only zero the value if false (if true, then the value is already
8550 ;; correct).
8551 (define_insn_and_split "*and_scc_scc_nodom"
8552   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8553         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8554                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8555                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8556                 (match_operator:SI 6 "arm_comparison_operator"
8557                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8558                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8559    (clobber (reg:CC CC_REGNUM))]
8560   "TARGET_ARM
8561    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8562        == CCmode)"
8563   "#"
8564   "TARGET_ARM && reload_completed"
8565   [(parallel [(set (match_dup 0)
8566                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8567               (clobber (reg:CC CC_REGNUM))])
8568    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8569    (set (match_dup 0)
8570         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8571                          (match_dup 0)
8572                          (const_int 0)))]
8573   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8574                                               operands[4], operands[5]),
8575                               CC_REGNUM);
8576    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8577                                   operands[5]);"
8578   [(set_attr "conds" "clob")
8579    (set_attr "length" "20")])
8581 (define_split
8582   [(set (reg:CC_NOOV CC_REGNUM)
8583         (compare:CC_NOOV (ior:SI
8584                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8585                                   (const_int 1))
8586                           (match_operator:SI 1 "comparison_operator"
8587                            [(match_operand:SI 2 "s_register_operand" "")
8588                             (match_operand:SI 3 "arm_add_operand" "")]))
8589                          (const_int 0)))
8590    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8591   "TARGET_ARM"
8592   [(set (match_dup 4)
8593         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8594                 (match_dup 0)))
8595    (set (reg:CC_NOOV CC_REGNUM)
8596         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8597                          (const_int 0)))]
8598   "")
8600 (define_split
8601   [(set (reg:CC_NOOV CC_REGNUM)
8602         (compare:CC_NOOV (ior:SI
8603                           (match_operator:SI 1 "comparison_operator"
8604                            [(match_operand:SI 2 "s_register_operand" "")
8605                             (match_operand:SI 3 "arm_add_operand" "")])
8606                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8607                                   (const_int 1)))
8608                          (const_int 0)))
8609    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8610   "TARGET_ARM"
8611   [(set (match_dup 4)
8612         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8613                 (match_dup 0)))
8614    (set (reg:CC_NOOV CC_REGNUM)
8615         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8616                          (const_int 0)))]
8617   "")
8619 (define_insn "*negscc"
8620   [(set (match_operand:SI 0 "s_register_operand" "=r")
8621         (neg:SI (match_operator 3 "arm_comparison_operator"
8622                  [(match_operand:SI 1 "s_register_operand" "r")
8623                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8624    (clobber (reg:CC CC_REGNUM))]
8625   "TARGET_ARM"
8626   "*
8627   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8628     return \"mov\\t%0, %1, asr #31\";
8630   if (GET_CODE (operands[3]) == NE)
8631     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8633   if (GET_CODE (operands[3]) == GT)
8634     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8636   output_asm_insn (\"cmp\\t%1, %2\", operands);
8637   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8638   return \"mvn%d3\\t%0, #0\";
8639   "
8640   [(set_attr "conds" "clob")
8641    (set_attr "length" "12")]
8644 (define_insn "movcond"
8645   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8646         (if_then_else:SI
8647          (match_operator 5 "arm_comparison_operator"
8648           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8649            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8650          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8651          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8652    (clobber (reg:CC CC_REGNUM))]
8653   "TARGET_ARM"
8654   "*
8655   if (GET_CODE (operands[5]) == LT
8656       && (operands[4] == const0_rtx))
8657     {
8658       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8659         {
8660           if (operands[2] == const0_rtx)
8661             return \"and\\t%0, %1, %3, asr #31\";
8662           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8663         }
8664       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8665         {
8666           if (operands[1] == const0_rtx)
8667             return \"bic\\t%0, %2, %3, asr #31\";
8668           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8669         }
8670       /* The only case that falls through to here is when both ops 1 & 2
8671          are constants.  */
8672     }
8674   if (GET_CODE (operands[5]) == GE
8675       && (operands[4] == const0_rtx))
8676     {
8677       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8678         {
8679           if (operands[2] == const0_rtx)
8680             return \"bic\\t%0, %1, %3, asr #31\";
8681           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8682         }
8683       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8684         {
8685           if (operands[1] == const0_rtx)
8686             return \"and\\t%0, %2, %3, asr #31\";
8687           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8688         }
8689       /* The only case that falls through to here is when both ops 1 & 2
8690          are constants.  */
8691     }
8692   if (GET_CODE (operands[4]) == CONST_INT
8693       && !const_ok_for_arm (INTVAL (operands[4])))
8694     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8695   else
8696     output_asm_insn (\"cmp\\t%3, %4\", operands);
8697   if (which_alternative != 0)
8698     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8699   if (which_alternative != 1)
8700     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8701   return \"\";
8702   "
8703   [(set_attr "conds" "clob")
8704    (set_attr "length" "8,8,12")]
8707 (define_insn "*ifcompare_plus_move"
8708   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8709         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8710                           [(match_operand:SI 4 "s_register_operand" "r,r")
8711                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8712                          (plus:SI
8713                           (match_operand:SI 2 "s_register_operand" "r,r")
8714                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8715                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8716    (clobber (reg:CC CC_REGNUM))]
8717   "TARGET_ARM"
8718   "#"
8719   [(set_attr "conds" "clob")
8720    (set_attr "length" "8,12")]
8723 (define_insn "*if_plus_move"
8724   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8725         (if_then_else:SI
8726          (match_operator 4 "arm_comparison_operator"
8727           [(match_operand 5 "cc_register" "") (const_int 0)])
8728          (plus:SI
8729           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8730           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8731          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8732   "TARGET_ARM"
8733   "@
8734    add%d4\\t%0, %2, %3
8735    sub%d4\\t%0, %2, #%n3
8736    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8737    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8738   [(set_attr "conds" "use")
8739    (set_attr "length" "4,4,8,8")
8740    (set_attr "type" "*,*,*,*")]
8743 (define_insn "*ifcompare_move_plus"
8744   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8745         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8746                           [(match_operand:SI 4 "s_register_operand" "r,r")
8747                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8748                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8749                          (plus:SI
8750                           (match_operand:SI 2 "s_register_operand" "r,r")
8751                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8752    (clobber (reg:CC CC_REGNUM))]
8753   "TARGET_ARM"
8754   "#"
8755   [(set_attr "conds" "clob")
8756    (set_attr "length" "8,12")]
8759 (define_insn "*if_move_plus"
8760   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8761         (if_then_else:SI
8762          (match_operator 4 "arm_comparison_operator"
8763           [(match_operand 5 "cc_register" "") (const_int 0)])
8764          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8765          (plus:SI
8766           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8767           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8768   "TARGET_ARM"
8769   "@
8770    add%D4\\t%0, %2, %3
8771    sub%D4\\t%0, %2, #%n3
8772    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8773    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8774   [(set_attr "conds" "use")
8775    (set_attr "length" "4,4,8,8")
8776    (set_attr "type" "*,*,*,*")]
8779 (define_insn "*ifcompare_arith_arith"
8780   [(set (match_operand:SI 0 "s_register_operand" "=r")
8781         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8782                           [(match_operand:SI 5 "s_register_operand" "r")
8783                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8784                          (match_operator:SI 8 "shiftable_operator"
8785                           [(match_operand:SI 1 "s_register_operand" "r")
8786                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8787                          (match_operator:SI 7 "shiftable_operator"
8788                           [(match_operand:SI 3 "s_register_operand" "r")
8789                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8790    (clobber (reg:CC CC_REGNUM))]
8791   "TARGET_ARM"
8792   "#"
8793   [(set_attr "conds" "clob")
8794    (set_attr "length" "12")]
8797 (define_insn "*if_arith_arith"
8798   [(set (match_operand:SI 0 "s_register_operand" "=r")
8799         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8800                           [(match_operand 8 "cc_register" "") (const_int 0)])
8801                          (match_operator:SI 6 "shiftable_operator"
8802                           [(match_operand:SI 1 "s_register_operand" "r")
8803                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8804                          (match_operator:SI 7 "shiftable_operator"
8805                           [(match_operand:SI 3 "s_register_operand" "r")
8806                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8807   "TARGET_ARM"
8808   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8809   [(set_attr "conds" "use")
8810    (set_attr "length" "8")]
8813 (define_insn "*ifcompare_arith_move"
8814   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8815         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8816                           [(match_operand:SI 2 "s_register_operand" "r,r")
8817                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8818                          (match_operator:SI 7 "shiftable_operator"
8819                           [(match_operand:SI 4 "s_register_operand" "r,r")
8820                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8821                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8822    (clobber (reg:CC CC_REGNUM))]
8823   "TARGET_ARM"
8824   "*
8825   /* If we have an operation where (op x 0) is the identity operation and
8826      the conditional operator is LT or GE and we are comparing against zero and
8827      everything is in registers then we can do this in two instructions.  */
8828   if (operands[3] == const0_rtx
8829       && GET_CODE (operands[7]) != AND
8830       && GET_CODE (operands[5]) == REG
8831       && GET_CODE (operands[1]) == REG 
8832       && REGNO (operands[1]) == REGNO (operands[4])
8833       && REGNO (operands[4]) != REGNO (operands[0]))
8834     {
8835       if (GET_CODE (operands[6]) == LT)
8836         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8837       else if (GET_CODE (operands[6]) == GE)
8838         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8839     }
8840   if (GET_CODE (operands[3]) == CONST_INT
8841       && !const_ok_for_arm (INTVAL (operands[3])))
8842     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8843   else
8844     output_asm_insn (\"cmp\\t%2, %3\", operands);
8845   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8846   if (which_alternative != 0)
8847     return \"mov%D6\\t%0, %1\";
8848   return \"\";
8849   "
8850   [(set_attr "conds" "clob")
8851    (set_attr "length" "8,12")]
8854 (define_insn "*if_arith_move"
8855   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8856         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8857                           [(match_operand 6 "cc_register" "") (const_int 0)])
8858                          (match_operator:SI 5 "shiftable_operator"
8859                           [(match_operand:SI 2 "s_register_operand" "r,r")
8860                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8861                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8862   "TARGET_ARM"
8863   "@
8864    %I5%d4\\t%0, %2, %3
8865    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8866   [(set_attr "conds" "use")
8867    (set_attr "length" "4,8")
8868    (set_attr "type" "*,*")]
8871 (define_insn "*ifcompare_move_arith"
8872   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8873         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8874                           [(match_operand:SI 4 "s_register_operand" "r,r")
8875                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8876                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8877                          (match_operator:SI 7 "shiftable_operator"
8878                           [(match_operand:SI 2 "s_register_operand" "r,r")
8879                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8880    (clobber (reg:CC CC_REGNUM))]
8881   "TARGET_ARM"
8882   "*
8883   /* If we have an operation where (op x 0) is the identity operation and
8884      the conditional operator is LT or GE and we are comparing against zero and
8885      everything is in registers then we can do this in two instructions */
8886   if (operands[5] == const0_rtx
8887       && GET_CODE (operands[7]) != AND
8888       && GET_CODE (operands[3]) == REG
8889       && GET_CODE (operands[1]) == REG 
8890       && REGNO (operands[1]) == REGNO (operands[2])
8891       && REGNO (operands[2]) != REGNO (operands[0]))
8892     {
8893       if (GET_CODE (operands[6]) == GE)
8894         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8895       else if (GET_CODE (operands[6]) == LT)
8896         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8897     }
8899   if (GET_CODE (operands[5]) == CONST_INT
8900       && !const_ok_for_arm (INTVAL (operands[5])))
8901     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8902   else
8903     output_asm_insn (\"cmp\\t%4, %5\", operands);
8905   if (which_alternative != 0)
8906     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8907   return \"%I7%D6\\t%0, %2, %3\";
8908   "
8909   [(set_attr "conds" "clob")
8910    (set_attr "length" "8,12")]
8913 (define_insn "*if_move_arith"
8914   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8915         (if_then_else:SI
8916          (match_operator 4 "arm_comparison_operator"
8917           [(match_operand 6 "cc_register" "") (const_int 0)])
8918          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8919          (match_operator:SI 5 "shiftable_operator"
8920           [(match_operand:SI 2 "s_register_operand" "r,r")
8921            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8922   "TARGET_ARM"
8923   "@
8924    %I5%D4\\t%0, %2, %3
8925    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8926   [(set_attr "conds" "use")
8927    (set_attr "length" "4,8")
8928    (set_attr "type" "*,*")]
8931 (define_insn "*ifcompare_move_not"
8932   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8933         (if_then_else:SI
8934          (match_operator 5 "arm_comparison_operator"
8935           [(match_operand:SI 3 "s_register_operand" "r,r")
8936            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8937          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8938          (not:SI
8939           (match_operand:SI 2 "s_register_operand" "r,r"))))
8940    (clobber (reg:CC CC_REGNUM))]
8941   "TARGET_ARM"
8942   "#"
8943   [(set_attr "conds" "clob")
8944    (set_attr "length" "8,12")]
8947 (define_insn "*if_move_not"
8948   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8949         (if_then_else:SI
8950          (match_operator 4 "arm_comparison_operator"
8951           [(match_operand 3 "cc_register" "") (const_int 0)])
8952          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8953          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8954   "TARGET_ARM"
8955   "@
8956    mvn%D4\\t%0, %2
8957    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8958    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8959   [(set_attr "conds" "use")
8960    (set_attr "length" "4,8,8")]
8963 (define_insn "*ifcompare_not_move"
8964   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8965         (if_then_else:SI 
8966          (match_operator 5 "arm_comparison_operator"
8967           [(match_operand:SI 3 "s_register_operand" "r,r")
8968            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8969          (not:SI
8970           (match_operand:SI 2 "s_register_operand" "r,r"))
8971          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8972    (clobber (reg:CC CC_REGNUM))]
8973   "TARGET_ARM"
8974   "#"
8975   [(set_attr "conds" "clob")
8976    (set_attr "length" "8,12")]
8979 (define_insn "*if_not_move"
8980   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8981         (if_then_else:SI
8982          (match_operator 4 "arm_comparison_operator"
8983           [(match_operand 3 "cc_register" "") (const_int 0)])
8984          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8985          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8986   "TARGET_ARM"
8987   "@
8988    mvn%d4\\t%0, %2
8989    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8990    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8991   [(set_attr "conds" "use")
8992    (set_attr "length" "4,8,8")]
8995 (define_insn "*ifcompare_shift_move"
8996   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8997         (if_then_else:SI
8998          (match_operator 6 "arm_comparison_operator"
8999           [(match_operand:SI 4 "s_register_operand" "r,r")
9000            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9001          (match_operator:SI 7 "shift_operator"
9002           [(match_operand:SI 2 "s_register_operand" "r,r")
9003            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
9004          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9005    (clobber (reg:CC CC_REGNUM))]
9006   "TARGET_ARM"
9007   "#"
9008   [(set_attr "conds" "clob")
9009    (set_attr "length" "8,12")]
9012 (define_insn "*if_shift_move"
9013   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9014         (if_then_else:SI
9015          (match_operator 5 "arm_comparison_operator"
9016           [(match_operand 6 "cc_register" "") (const_int 0)])
9017          (match_operator:SI 4 "shift_operator"
9018           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9019            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
9020          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9021   "TARGET_ARM"
9022   "@
9023    mov%d5\\t%0, %2%S4
9024    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
9025    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
9026   [(set_attr "conds" "use")
9027    (set_attr "shift" "2")
9028    (set_attr "length" "4,8,8")
9029    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9030                       (const_string "alu_shift")
9031                       (const_string "alu_shift_reg")))]
9034 (define_insn "*ifcompare_move_shift"
9035   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9036         (if_then_else:SI
9037          (match_operator 6 "arm_comparison_operator"
9038           [(match_operand:SI 4 "s_register_operand" "r,r")
9039            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
9040          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9041          (match_operator:SI 7 "shift_operator"
9042           [(match_operand:SI 2 "s_register_operand" "r,r")
9043            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
9044    (clobber (reg:CC CC_REGNUM))]
9045   "TARGET_ARM"
9046   "#"
9047   [(set_attr "conds" "clob")
9048    (set_attr "length" "8,12")]
9051 (define_insn "*if_move_shift"
9052   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9053         (if_then_else:SI
9054          (match_operator 5 "arm_comparison_operator"
9055           [(match_operand 6 "cc_register" "") (const_int 0)])
9056          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9057          (match_operator:SI 4 "shift_operator"
9058           [(match_operand:SI 2 "s_register_operand" "r,r,r")
9059            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
9060   "TARGET_ARM"
9061   "@
9062    mov%D5\\t%0, %2%S4
9063    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
9064    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
9065   [(set_attr "conds" "use")
9066    (set_attr "shift" "2")
9067    (set_attr "length" "4,8,8")
9068    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
9069                       (const_string "alu_shift")
9070                       (const_string "alu_shift_reg")))]
9073 (define_insn "*ifcompare_shift_shift"
9074   [(set (match_operand:SI 0 "s_register_operand" "=r")
9075         (if_then_else:SI
9076          (match_operator 7 "arm_comparison_operator"
9077           [(match_operand:SI 5 "s_register_operand" "r")
9078            (match_operand:SI 6 "arm_add_operand" "rIL")])
9079          (match_operator:SI 8 "shift_operator"
9080           [(match_operand:SI 1 "s_register_operand" "r")
9081            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9082          (match_operator:SI 9 "shift_operator"
9083           [(match_operand:SI 3 "s_register_operand" "r")
9084            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
9085    (clobber (reg:CC CC_REGNUM))]
9086   "TARGET_ARM"
9087   "#"
9088   [(set_attr "conds" "clob")
9089    (set_attr "length" "12")]
9092 (define_insn "*if_shift_shift"
9093   [(set (match_operand:SI 0 "s_register_operand" "=r")
9094         (if_then_else:SI
9095          (match_operator 5 "arm_comparison_operator"
9096           [(match_operand 8 "cc_register" "") (const_int 0)])
9097          (match_operator:SI 6 "shift_operator"
9098           [(match_operand:SI 1 "s_register_operand" "r")
9099            (match_operand:SI 2 "arm_rhs_operand" "rM")])
9100          (match_operator:SI 7 "shift_operator"
9101           [(match_operand:SI 3 "s_register_operand" "r")
9102            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
9103   "TARGET_ARM"
9104   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
9105   [(set_attr "conds" "use")
9106    (set_attr "shift" "1")
9107    (set_attr "length" "8")
9108    (set (attr "type") (if_then_else
9109                         (and (match_operand 2 "const_int_operand" "")
9110                              (match_operand 4 "const_int_operand" ""))
9111                       (const_string "alu_shift")
9112                       (const_string "alu_shift_reg")))]
9115 (define_insn "*ifcompare_not_arith"
9116   [(set (match_operand:SI 0 "s_register_operand" "=r")
9117         (if_then_else:SI
9118          (match_operator 6 "arm_comparison_operator"
9119           [(match_operand:SI 4 "s_register_operand" "r")
9120            (match_operand:SI 5 "arm_add_operand" "rIL")])
9121          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9122          (match_operator:SI 7 "shiftable_operator"
9123           [(match_operand:SI 2 "s_register_operand" "r")
9124            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
9125    (clobber (reg:CC CC_REGNUM))]
9126   "TARGET_ARM"
9127   "#"
9128   [(set_attr "conds" "clob")
9129    (set_attr "length" "12")]
9132 (define_insn "*if_not_arith"
9133   [(set (match_operand:SI 0 "s_register_operand" "=r")
9134         (if_then_else:SI
9135          (match_operator 5 "arm_comparison_operator"
9136           [(match_operand 4 "cc_register" "") (const_int 0)])
9137          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
9138          (match_operator:SI 6 "shiftable_operator"
9139           [(match_operand:SI 2 "s_register_operand" "r")
9140            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
9141   "TARGET_ARM"
9142   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
9143   [(set_attr "conds" "use")
9144    (set_attr "length" "8")]
9147 (define_insn "*ifcompare_arith_not"
9148   [(set (match_operand:SI 0 "s_register_operand" "=r")
9149         (if_then_else:SI
9150          (match_operator 6 "arm_comparison_operator"
9151           [(match_operand:SI 4 "s_register_operand" "r")
9152            (match_operand:SI 5 "arm_add_operand" "rIL")])
9153          (match_operator:SI 7 "shiftable_operator"
9154           [(match_operand:SI 2 "s_register_operand" "r")
9155            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9156          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
9157    (clobber (reg:CC CC_REGNUM))]
9158   "TARGET_ARM"
9159   "#"
9160   [(set_attr "conds" "clob")
9161    (set_attr "length" "12")]
9164 (define_insn "*if_arith_not"
9165   [(set (match_operand:SI 0 "s_register_operand" "=r")
9166         (if_then_else:SI
9167          (match_operator 5 "arm_comparison_operator"
9168           [(match_operand 4 "cc_register" "") (const_int 0)])
9169          (match_operator:SI 6 "shiftable_operator"
9170           [(match_operand:SI 2 "s_register_operand" "r")
9171            (match_operand:SI 3 "arm_rhs_operand" "rI")])
9172          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
9173   "TARGET_ARM"
9174   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
9175   [(set_attr "conds" "use")
9176    (set_attr "length" "8")]
9179 (define_insn "*ifcompare_neg_move"
9180   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9181         (if_then_else:SI
9182          (match_operator 5 "arm_comparison_operator"
9183           [(match_operand:SI 3 "s_register_operand" "r,r")
9184            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9185          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
9186          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
9187    (clobber (reg:CC CC_REGNUM))]
9188   "TARGET_ARM"
9189   "#"
9190   [(set_attr "conds" "clob")
9191    (set_attr "length" "8,12")]
9194 (define_insn "*if_neg_move"
9195   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9196         (if_then_else:SI
9197          (match_operator 4 "arm_comparison_operator"
9198           [(match_operand 3 "cc_register" "") (const_int 0)])
9199          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
9200          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
9201   "TARGET_ARM"
9202   "@
9203    rsb%d4\\t%0, %2, #0
9204    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
9205    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
9206   [(set_attr "conds" "use")
9207    (set_attr "length" "4,8,8")]
9210 (define_insn "*ifcompare_move_neg"
9211   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9212         (if_then_else:SI
9213          (match_operator 5 "arm_comparison_operator"
9214           [(match_operand:SI 3 "s_register_operand" "r,r")
9215            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
9216          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
9217          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
9218    (clobber (reg:CC CC_REGNUM))]
9219   "TARGET_ARM"
9220   "#"
9221   [(set_attr "conds" "clob")
9222    (set_attr "length" "8,12")]
9225 (define_insn "*if_move_neg"
9226   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
9227         (if_then_else:SI
9228          (match_operator 4 "arm_comparison_operator"
9229           [(match_operand 3 "cc_register" "") (const_int 0)])
9230          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
9231          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
9232   "TARGET_ARM"
9233   "@
9234    rsb%D4\\t%0, %2, #0
9235    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
9236    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
9237   [(set_attr "conds" "use")
9238    (set_attr "length" "4,8,8")]
9241 (define_insn "*arith_adjacentmem"
9242   [(set (match_operand:SI 0 "s_register_operand" "=r")
9243         (match_operator:SI 1 "shiftable_operator"
9244          [(match_operand:SI 2 "memory_operand" "m")
9245           (match_operand:SI 3 "memory_operand" "m")]))
9246    (clobber (match_scratch:SI 4 "=r"))]
9247   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
9248   "*
9249   {
9250     rtx ldm[3];
9251     rtx arith[4];
9252     int val1 = 0, val2 = 0;
9254     if (REGNO (operands[0]) > REGNO (operands[4]))
9255       {
9256         ldm[1] = operands[4];
9257         ldm[2] = operands[0];
9258       }
9259     else
9260       {
9261         ldm[1] = operands[0];
9262         ldm[2] = operands[4];
9263       }
9264     if (GET_CODE (XEXP (operands[2], 0)) != REG)
9265       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
9266     if (GET_CODE (XEXP (operands[3], 0)) != REG)
9267       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
9268     arith[0] = operands[0];
9269     arith[3] = operands[1];
9270     if (val1 < val2)
9271       {
9272         arith[1] = ldm[1];
9273         arith[2] = ldm[2];
9274       }
9275     else
9276       {
9277         arith[1] = ldm[2];
9278         arith[2] = ldm[1];
9279       }
9280    if (val1 && val2)
9281       {
9282         rtx ops[3];
9283         ldm[0] = ops[0] = operands[4];
9284         ops[1] = XEXP (XEXP (operands[2], 0), 0);
9285         ops[2] = XEXP (XEXP (operands[2], 0), 1);
9286         output_add_immediate (ops);
9287         if (val1 < val2)
9288           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9289         else
9290           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9291       }
9292     else if (val1)
9293       {
9294         ldm[0] = XEXP (operands[3], 0);
9295         if (val1 < val2)
9296           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9297         else
9298           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9299       }
9300     else
9301       {
9302         ldm[0] = XEXP (operands[2], 0);
9303         if (val1 < val2)
9304           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9305         else
9306           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9307       }
9308     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9309     return \"\";
9310   }"
9311   [(set_attr "length" "12")
9312    (set_attr "predicable" "yes")
9313    (set_attr "type" "load1")]
9316 ;; the arm can support extended pre-inc instructions
9318 ;; In all these cases, we use operands 0 and 1 for the register being
9319 ;; incremented because those are the operands that local-alloc will
9320 ;; tie and these are the pair most likely to be tieable (and the ones
9321 ;; that will benefit the most).
9323 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9324 ;; elimination will cause too many headaches.
9326 (define_insn "*strqi_preinc"
9327   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9328                          (match_operand:SI 2 "index_operand" "rJ")))
9329         (match_operand:QI 3 "s_register_operand" "r"))
9330    (set (match_operand:SI 0 "s_register_operand" "=r")
9331         (plus:SI (match_dup 1) (match_dup 2)))]
9332   "TARGET_ARM
9333    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9334    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9335    && (GET_CODE (operands[2]) != REG
9336        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9337   "str%?b\\t%3, [%0, %2]!"
9338   [(set_attr "type" "store1")
9339    (set_attr "predicable" "yes")]
9342 (define_insn "*strqi_predec"
9343   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9344                           (match_operand:SI 2 "s_register_operand" "r")))
9345         (match_operand:QI 3 "s_register_operand" "r"))
9346    (set (match_operand:SI 0 "s_register_operand" "=r")
9347         (minus:SI (match_dup 1) (match_dup 2)))]
9348   "TARGET_ARM
9349    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9350    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9351    && (GET_CODE (operands[2]) != REG
9352        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9353   "str%?b\\t%3, [%0, -%2]!"
9354   [(set_attr "type" "store1")
9355    (set_attr "predicable" "yes")]
9358 (define_insn "*loadqi_preinc"
9359   [(set (match_operand:QI 3 "s_register_operand" "=r")
9360         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9361                          (match_operand:SI 2 "index_operand" "rJ"))))
9362    (set (match_operand:SI 0 "s_register_operand" "=r")
9363         (plus:SI (match_dup 1) (match_dup 2)))]
9364   "TARGET_ARM
9365    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9366    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9367    && (GET_CODE (operands[2]) != REG
9368        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9369   "ldr%?b\\t%3, [%0, %2]!"
9370   [(set_attr "type" "load_byte")
9371    (set_attr "predicable" "yes")]
9374 (define_insn "*loadqi_predec"
9375   [(set (match_operand:QI 3 "s_register_operand" "=r")
9376         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9377                           (match_operand:SI 2 "s_register_operand" "r"))))
9378    (set (match_operand:SI 0 "s_register_operand" "=r")
9379         (minus:SI (match_dup 1) (match_dup 2)))]
9380   "TARGET_ARM
9381    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9382    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9383    && (GET_CODE (operands[2]) != REG
9384        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9385   "ldr%?b\\t%3, [%0, -%2]!"
9386   [(set_attr "type" "load_byte")
9387    (set_attr "predicable" "yes")]
9390 (define_insn "*loadqisi_preinc"
9391   [(set (match_operand:SI 3 "s_register_operand" "=r")
9392         (zero_extend:SI
9393          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9394                           (match_operand:SI 2 "index_operand" "rJ")))))
9395    (set (match_operand:SI 0 "s_register_operand" "=r")
9396         (plus:SI (match_dup 1) (match_dup 2)))]
9397   "TARGET_ARM
9398    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9399    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9400    && (GET_CODE (operands[2]) != REG
9401        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9402   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9403   [(set_attr "type" "load_byte")
9404    (set_attr "predicable" "yes")]
9407 (define_insn "*loadqisi_predec"
9408   [(set (match_operand:SI 3 "s_register_operand" "=r")
9409         (zero_extend:SI
9410          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9411                            (match_operand:SI 2 "s_register_operand" "r")))))
9412    (set (match_operand:SI 0 "s_register_operand" "=r")
9413         (minus:SI (match_dup 1) (match_dup 2)))]
9414   "TARGET_ARM
9415    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9416    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9417    && (GET_CODE (operands[2]) != REG
9418        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9419   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9420   [(set_attr "type" "load_byte")
9421    (set_attr "predicable" "yes")]
9424 (define_insn "*strsi_preinc"
9425   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9426                          (match_operand:SI 2 "index_operand" "rJ")))
9427         (match_operand:SI 3 "s_register_operand" "r"))
9428    (set (match_operand:SI 0 "s_register_operand" "=r")
9429         (plus:SI (match_dup 1) (match_dup 2)))]
9430   "TARGET_ARM
9431    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9432    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9433    && (GET_CODE (operands[2]) != REG
9434        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9435   "str%?\\t%3, [%0, %2]!"
9436   [(set_attr "type" "store1")
9437    (set_attr "predicable" "yes")]
9440 (define_insn "*strsi_predec"
9441   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9442                           (match_operand:SI 2 "s_register_operand" "r")))
9443         (match_operand:SI 3 "s_register_operand" "r"))
9444    (set (match_operand:SI 0 "s_register_operand" "=r")
9445         (minus:SI (match_dup 1) (match_dup 2)))]
9446   "TARGET_ARM
9447    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9448    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9449    && (GET_CODE (operands[2]) != REG
9450        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9451   "str%?\\t%3, [%0, -%2]!"
9452   [(set_attr "type" "store1")
9453    (set_attr "predicable" "yes")]
9456 (define_insn "*loadsi_preinc"
9457   [(set (match_operand:SI 3 "s_register_operand" "=r")
9458         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9459                          (match_operand:SI 2 "index_operand" "rJ"))))
9460    (set (match_operand:SI 0 "s_register_operand" "=r")
9461         (plus:SI (match_dup 1) (match_dup 2)))]
9462   "TARGET_ARM
9463    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9464    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9465    && (GET_CODE (operands[2]) != REG
9466        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9467   "ldr%?\\t%3, [%0, %2]!"
9468   [(set_attr "type" "load1")
9469    (set_attr "predicable" "yes")]
9472 (define_insn "*loadsi_predec"
9473   [(set (match_operand:SI 3 "s_register_operand" "=r")
9474         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9475                           (match_operand:SI 2 "s_register_operand" "r"))))
9476    (set (match_operand:SI 0 "s_register_operand" "=r")
9477         (minus:SI (match_dup 1) (match_dup 2)))]
9478   "TARGET_ARM
9479    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9480    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9481    && (GET_CODE (operands[2]) != REG
9482        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9483   "ldr%?\\t%3, [%0, -%2]!"
9484   [(set_attr "type" "load1")
9485    (set_attr "predicable" "yes")]
9488 (define_insn "*strqi_shiftpreinc"
9489   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9490                           [(match_operand:SI 3 "s_register_operand" "r")
9491                            (match_operand:SI 4 "const_shift_operand" "n")])
9492                          (match_operand:SI 1 "s_register_operand" "0")))
9493         (match_operand:QI 5 "s_register_operand" "r"))
9494    (set (match_operand:SI 0 "s_register_operand" "=r")
9495         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9496                  (match_dup 1)))]
9497   "TARGET_ARM
9498    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9499    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9500    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9501   "str%?b\\t%5, [%0, %3%S2]!"
9502   [(set_attr "type" "store1")
9503    (set_attr "predicable" "yes")]
9506 (define_insn "*strqi_shiftpredec"
9507   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9508                           (match_operator:SI 2 "shift_operator"
9509                            [(match_operand:SI 3 "s_register_operand" "r")
9510                             (match_operand:SI 4 "const_shift_operand" "n")])))
9511         (match_operand:QI 5 "s_register_operand" "r"))
9512    (set (match_operand:SI 0 "s_register_operand" "=r")
9513         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9514                                                  (match_dup 4)])))]
9515   "TARGET_ARM
9516    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9517    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9518    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9519   "str%?b\\t%5, [%0, -%3%S2]!"
9520   [(set_attr "type" "store1")
9521    (set_attr "predicable" "yes")]
9524 (define_insn "*loadqi_shiftpreinc"
9525   [(set (match_operand:QI 5 "s_register_operand" "=r")
9526         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9527                           [(match_operand:SI 3 "s_register_operand" "r")
9528                            (match_operand:SI 4 "const_shift_operand" "n")])
9529                          (match_operand:SI 1 "s_register_operand" "0"))))
9530    (set (match_operand:SI 0 "s_register_operand" "=r")
9531         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9532                  (match_dup 1)))]
9533   "TARGET_ARM
9534    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9535    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9536    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9537   "ldr%?b\\t%5, [%0, %3%S2]!"
9538   [(set_attr "type" "load_byte")
9539    (set_attr "predicable" "yes")]
9542 (define_insn "*loadqi_shiftpredec"
9543   [(set (match_operand:QI 5 "s_register_operand" "=r")
9544         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9545                           (match_operator:SI 2 "shift_operator"
9546                            [(match_operand:SI 3 "s_register_operand" "r")
9547                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9548    (set (match_operand:SI 0 "s_register_operand" "=r")
9549         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9550                                                  (match_dup 4)])))]
9551   "TARGET_ARM
9552    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9553    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9554    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9555   "ldr%?b\\t%5, [%0, -%3%S2]!"
9556   [(set_attr "type" "load_byte")
9557    (set_attr "predicable" "yes")]
9560 (define_insn "*strsi_shiftpreinc"
9561   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9562                           [(match_operand:SI 3 "s_register_operand" "r")
9563                            (match_operand:SI 4 "const_shift_operand" "n")])
9564                          (match_operand:SI 1 "s_register_operand" "0")))
9565         (match_operand:SI 5 "s_register_operand" "r"))
9566    (set (match_operand:SI 0 "s_register_operand" "=r")
9567         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9568                  (match_dup 1)))]
9569   "TARGET_ARM
9570    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9571    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9572    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9573   "str%?\\t%5, [%0, %3%S2]!"
9574   [(set_attr "type" "store1")
9575    (set_attr "predicable" "yes")]
9578 (define_insn "*strsi_shiftpredec"
9579   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9580                           (match_operator:SI 2 "shift_operator"
9581                            [(match_operand:SI 3 "s_register_operand" "r")
9582                             (match_operand:SI 4 "const_shift_operand" "n")])))
9583         (match_operand:SI 5 "s_register_operand" "r"))
9584    (set (match_operand:SI 0 "s_register_operand" "=r")
9585         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9586                                                  (match_dup 4)])))]
9587   "TARGET_ARM
9588    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9589    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9590    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9591   "str%?\\t%5, [%0, -%3%S2]!"
9592   [(set_attr "type" "store1")
9593    (set_attr "predicable" "yes")]
9596 (define_insn "*loadsi_shiftpreinc"
9597   [(set (match_operand:SI 5 "s_register_operand" "=r")
9598         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9599                           [(match_operand:SI 3 "s_register_operand" "r")
9600                            (match_operand:SI 4 "const_shift_operand" "n")])
9601                          (match_operand:SI 1 "s_register_operand" "0"))))
9602    (set (match_operand:SI 0 "s_register_operand" "=r")
9603         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9604                  (match_dup 1)))]
9605   "TARGET_ARM
9606    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9607    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9608    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9609   "ldr%?\\t%5, [%0, %3%S2]!"
9610   [(set_attr "type" "load1")
9611    (set_attr "predicable" "yes")]
9614 (define_insn "*loadsi_shiftpredec"
9615   [(set (match_operand:SI 5 "s_register_operand" "=r")
9616         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9617                           (match_operator:SI 2 "shift_operator"
9618                            [(match_operand:SI 3 "s_register_operand" "r")
9619                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9620    (set (match_operand:SI 0 "s_register_operand" "=r")
9621         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9622                                                  (match_dup 4)])))]
9623   "TARGET_ARM
9624    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9625    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9626    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9627   "ldr%?\\t%5, [%0, -%3%S2]!"
9628   [(set_attr "type" "load1")
9629    (set_attr "predicable" "yes")])
9631 ; It can also support extended post-inc expressions, but combine doesn't
9632 ; try these....
9633 ; It doesn't seem worth adding peepholes for anything but the most common
9634 ; cases since, unlike combine, the increment must immediately follow the load
9635 ; for this pattern to match.
9636 ; We must watch to see that the source/destination register isn't also the
9637 ; same as the base address register, and that if the index is a register,
9638 ; that it is not the same as the base address register.  In such cases the
9639 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9640 ; we cannot use it.
9642 (define_peephole
9643   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9644         (match_operand:QI 2 "s_register_operand" "r"))
9645    (set (match_dup 0)
9646         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9647   "TARGET_ARM
9648    && (REGNO (operands[2]) != REGNO (operands[0]))
9649    && (GET_CODE (operands[1]) != REG
9650        || (REGNO (operands[1]) != REGNO (operands[0])))"
9651   "str%?b\\t%2, [%0], %1"
9654 (define_peephole
9655   [(set (match_operand:QI 0 "s_register_operand" "=r")
9656         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9657    (set (match_dup 1)
9658         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9659   "TARGET_ARM
9660    && REGNO (operands[0]) != REGNO(operands[1])
9661    && (GET_CODE (operands[2]) != REG
9662        || REGNO(operands[0]) != REGNO (operands[2]))"
9663   "ldr%?b\\t%0, [%1], %2"
9666 (define_peephole
9667   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9668         (match_operand:SI 2 "s_register_operand" "r"))
9669    (set (match_dup 0)
9670         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9671   "TARGET_ARM
9672    && (REGNO (operands[2]) != REGNO (operands[0]))
9673    && (GET_CODE (operands[1]) != REG
9674        || (REGNO (operands[1]) != REGNO (operands[0])))"
9675   "str%?\\t%2, [%0], %1"
9678 (define_peephole
9679   [(set (match_operand:SI 0 "s_register_operand" "=r")
9680         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9681    (set (match_dup 1)
9682         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9683   "TARGET_ARM
9684    && REGNO (operands[0]) != REGNO(operands[1])
9685    && (GET_CODE (operands[2]) != REG
9686        || REGNO(operands[0]) != REGNO (operands[2]))"
9687   "ldr%?\\t%0, [%1], %2"
9690 (define_peephole
9691   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9692                          (match_operand:SI 1 "index_operand" "rJ")))
9693         (match_operand:QI 2 "s_register_operand" "r"))
9694    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9695   "TARGET_ARM
9696    && (REGNO (operands[2]) != REGNO (operands[0]))
9697    && (GET_CODE (operands[1]) != REG
9698        || (REGNO (operands[1]) != REGNO (operands[0])))"
9699   "str%?b\\t%2, [%0, %1]!"
9702 (define_peephole
9703   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9704                           [(match_operand:SI 0 "s_register_operand" "r")
9705                            (match_operand:SI 1 "const_int_operand" "n")])
9706                          (match_operand:SI 2 "s_register_operand" "+r")))
9707         (match_operand:QI 3 "s_register_operand" "r"))
9708    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9709                                (match_dup 2)))]
9710   "TARGET_ARM
9711    && (REGNO (operands[3]) != REGNO (operands[2]))
9712    && (REGNO (operands[0]) != REGNO (operands[2]))"
9713   "str%?b\\t%3, [%2, %0%S4]!"
9716 ; This pattern is never tried by combine, so do it as a peephole
9718 (define_peephole2
9719   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9720         (match_operand:SI 1 "arm_general_register_operand" ""))
9721    (set (reg:CC CC_REGNUM)
9722         (compare:CC (match_dup 1) (const_int 0)))]
9723   "TARGET_ARM"
9724   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9725               (set (match_dup 0) (match_dup 1))])]
9726   ""
9729 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9730 ; reversed, check that the memory references aren't volatile.
9732 (define_peephole
9733   [(set (match_operand:SI 0 "s_register_operand" "=r")
9734         (match_operand:SI 4 "memory_operand" "m"))
9735    (set (match_operand:SI 1 "s_register_operand" "=r")
9736         (match_operand:SI 5 "memory_operand" "m"))
9737    (set (match_operand:SI 2 "s_register_operand" "=r")
9738         (match_operand:SI 6 "memory_operand" "m"))
9739    (set (match_operand:SI 3 "s_register_operand" "=r")
9740         (match_operand:SI 7 "memory_operand" "m"))]
9741   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9742   "*
9743   return emit_ldm_seq (operands, 4);
9744   "
9747 (define_peephole
9748   [(set (match_operand:SI 0 "s_register_operand" "=r")
9749         (match_operand:SI 3 "memory_operand" "m"))
9750    (set (match_operand:SI 1 "s_register_operand" "=r")
9751         (match_operand:SI 4 "memory_operand" "m"))
9752    (set (match_operand:SI 2 "s_register_operand" "=r")
9753         (match_operand:SI 5 "memory_operand" "m"))]
9754   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9755   "*
9756   return emit_ldm_seq (operands, 3);
9757   "
9760 (define_peephole
9761   [(set (match_operand:SI 0 "s_register_operand" "=r")
9762         (match_operand:SI 2 "memory_operand" "m"))
9763    (set (match_operand:SI 1 "s_register_operand" "=r")
9764         (match_operand:SI 3 "memory_operand" "m"))]
9765   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9766   "*
9767   return emit_ldm_seq (operands, 2);
9768   "
9771 (define_peephole
9772   [(set (match_operand:SI 4 "memory_operand" "=m")
9773         (match_operand:SI 0 "s_register_operand" "r"))
9774    (set (match_operand:SI 5 "memory_operand" "=m")
9775         (match_operand:SI 1 "s_register_operand" "r"))
9776    (set (match_operand:SI 6 "memory_operand" "=m")
9777         (match_operand:SI 2 "s_register_operand" "r"))
9778    (set (match_operand:SI 7 "memory_operand" "=m")
9779         (match_operand:SI 3 "s_register_operand" "r"))]
9780   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9781   "*
9782   return emit_stm_seq (operands, 4);
9783   "
9786 (define_peephole
9787   [(set (match_operand:SI 3 "memory_operand" "=m")
9788         (match_operand:SI 0 "s_register_operand" "r"))
9789    (set (match_operand:SI 4 "memory_operand" "=m")
9790         (match_operand:SI 1 "s_register_operand" "r"))
9791    (set (match_operand:SI 5 "memory_operand" "=m")
9792         (match_operand:SI 2 "s_register_operand" "r"))]
9793   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9794   "*
9795   return emit_stm_seq (operands, 3);
9796   "
9799 (define_peephole
9800   [(set (match_operand:SI 2 "memory_operand" "=m")
9801         (match_operand:SI 0 "s_register_operand" "r"))
9802    (set (match_operand:SI 3 "memory_operand" "=m")
9803         (match_operand:SI 1 "s_register_operand" "r"))]
9804   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9805   "*
9806   return emit_stm_seq (operands, 2);
9807   "
9810 (define_split
9811   [(set (match_operand:SI 0 "s_register_operand" "")
9812         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9813                        (const_int 0))
9814                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9815                          [(match_operand:SI 3 "s_register_operand" "")
9816                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9817    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9818   "TARGET_ARM"
9819   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9820    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9821                               (match_dup 5)))]
9822   ""
9825 ;; This split can be used because CC_Z mode implies that the following
9826 ;; branch will be an equality, or an unsigned inequality, so the sign
9827 ;; extension is not needed.
9829 (define_split
9830   [(set (reg:CC_Z CC_REGNUM)
9831         (compare:CC_Z
9832          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9833                     (const_int 24))
9834          (match_operand 1 "const_int_operand" "")))
9835    (clobber (match_scratch:SI 2 ""))]
9836   "TARGET_ARM
9837    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9838        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9839   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9840    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9841   "
9842   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9843   "
9846 (define_expand "prologue"
9847   [(clobber (const_int 0))]
9848   "TARGET_EITHER"
9849   "if (TARGET_ARM)
9850      arm_expand_prologue ();
9851    else
9852      thumb_expand_prologue ();
9853   DONE;
9854   "
9857 (define_expand "epilogue"
9858   [(clobber (const_int 0))]
9859   "TARGET_EITHER"
9860   "
9861   if (current_function_calls_eh_return)
9862     emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
9863   if (TARGET_THUMB)
9864     thumb_expand_epilogue ();
9865   else if (USE_RETURN_INSN (FALSE))
9866     {
9867       emit_jump_insn (gen_return ());
9868       DONE;
9869     }
9870   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9871         gen_rtvec (1,
9872                 gen_rtx_RETURN (VOIDmode)),
9873         VUNSPEC_EPILOGUE));
9874   DONE;
9875   "
9878 ;; Note - although unspec_volatile's USE all hard registers,
9879 ;; USEs are ignored after relaod has completed.  Thus we need
9880 ;; to add an unspec of the link register to ensure that flow
9881 ;; does not think that it is unused by the sibcall branch that
9882 ;; will replace the standard function epilogue.
9883 (define_insn "sibcall_epilogue"
9884   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9885               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9886   "TARGET_ARM"
9887   "*
9888   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9889     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9890   return arm_output_epilogue (next_nonnote_insn (insn));
9891   "
9892 ;; Length is absolute worst case
9893   [(set_attr "length" "44")
9894    (set_attr "type" "block")
9895    ;; We don't clobber the conditions, but the potential length of this
9896    ;; operation is sufficient to make conditionalizing the sequence 
9897    ;; unlikely to be profitable.
9898    (set_attr "conds" "clob")]
9901 (define_insn "*epilogue_insns"
9902   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9903   "TARGET_EITHER"
9904   "*
9905   if (TARGET_ARM)
9906     return arm_output_epilogue (NULL);
9907   else /* TARGET_THUMB */
9908     return thumb_unexpanded_epilogue ();
9909   "
9910   ; Length is absolute worst case
9911   [(set_attr "length" "44")
9912    (set_attr "type" "block")
9913    ;; We don't clobber the conditions, but the potential length of this
9914    ;; operation is sufficient to make conditionalizing the sequence 
9915    ;; unlikely to be profitable.
9916    (set_attr "conds" "clob")]
9919 (define_expand "eh_epilogue"
9920   [(use (match_operand:SI 0 "register_operand" ""))
9921    (use (match_operand:SI 1 "register_operand" ""))
9922    (use (match_operand:SI 2 "register_operand" ""))]
9923   "TARGET_EITHER"
9924   "
9925   {
9926     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9927     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9928       {
9929         rtx ra = gen_rtx_REG (Pmode, 2);
9931         emit_move_insn (ra, operands[2]);
9932         operands[2] = ra;
9933       }
9934     /* This is a hack -- we may have crystalized the function type too
9935        early.  */
9936     cfun->machine->func_type = 0;
9937   }"
9940 ;; This split is only used during output to reduce the number of patterns
9941 ;; that need assembler instructions adding to them.  We allowed the setting
9942 ;; of the conditions to be implicit during rtl generation so that
9943 ;; the conditional compare patterns would work.  However this conflicts to
9944 ;; some extent with the conditional data operations, so we have to split them
9945 ;; up again here.
9947 (define_split
9948   [(set (match_operand:SI 0 "s_register_operand" "")
9949         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9950                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9951                          (match_dup 0)
9952                          (match_operand 4 "" "")))
9953    (clobber (reg:CC CC_REGNUM))]
9954   "TARGET_ARM && reload_completed"
9955   [(set (match_dup 5) (match_dup 6))
9956    (cond_exec (match_dup 7)
9957               (set (match_dup 0) (match_dup 4)))]
9958   "
9959   {
9960     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9961                                              operands[2], operands[3]);
9962     enum rtx_code rc = GET_CODE (operands[1]);
9964     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9965     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9966     if (mode == CCFPmode || mode == CCFPEmode)
9967       rc = reverse_condition_maybe_unordered (rc);
9968     else
9969       rc = reverse_condition (rc);
9971     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9972   }"
9975 (define_split
9976   [(set (match_operand:SI 0 "s_register_operand" "")
9977         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9978                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9979                          (match_operand 4 "" "")
9980                          (match_dup 0)))
9981    (clobber (reg:CC CC_REGNUM))]
9982   "TARGET_ARM && reload_completed"
9983   [(set (match_dup 5) (match_dup 6))
9984    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9985               (set (match_dup 0) (match_dup 4)))]
9986   "
9987   {
9988     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9989                                              operands[2], operands[3]);
9991     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9992     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9993   }"
9996 (define_split
9997   [(set (match_operand:SI 0 "s_register_operand" "")
9998         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9999                           [(match_operand 2 "" "") (match_operand 3 "" "")])
10000                          (match_operand 4 "" "")
10001                          (match_operand 5 "" "")))
10002    (clobber (reg:CC CC_REGNUM))]
10003   "TARGET_ARM && reload_completed"
10004   [(set (match_dup 6) (match_dup 7))
10005    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10006               (set (match_dup 0) (match_dup 4)))
10007    (cond_exec (match_dup 8)
10008               (set (match_dup 0) (match_dup 5)))]
10009   "
10010   {
10011     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10012                                              operands[2], operands[3]);
10013     enum rtx_code rc = GET_CODE (operands[1]);
10015     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10016     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10017     if (mode == CCFPmode || mode == CCFPEmode)
10018       rc = reverse_condition_maybe_unordered (rc);
10019     else
10020       rc = reverse_condition (rc);
10022     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10023   }"
10026 (define_split
10027   [(set (match_operand:SI 0 "s_register_operand" "")
10028         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
10029                           [(match_operand:SI 2 "s_register_operand" "")
10030                            (match_operand:SI 3 "arm_add_operand" "")])
10031                          (match_operand:SI 4 "arm_rhs_operand" "")
10032                          (not:SI
10033                           (match_operand:SI 5 "s_register_operand" ""))))
10034    (clobber (reg:CC CC_REGNUM))]
10035   "TARGET_ARM && reload_completed"
10036   [(set (match_dup 6) (match_dup 7))
10037    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
10038               (set (match_dup 0) (match_dup 4)))
10039    (cond_exec (match_dup 8)
10040               (set (match_dup 0) (not:SI (match_dup 5))))]
10041   "
10042   {
10043     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
10044                                              operands[2], operands[3]);
10045     enum rtx_code rc = GET_CODE (operands[1]);
10047     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
10048     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
10049     if (mode == CCFPmode || mode == CCFPEmode)
10050       rc = reverse_condition_maybe_unordered (rc);
10051     else
10052       rc = reverse_condition (rc);
10054     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
10055   }"
10058 (define_insn "*cond_move_not"
10059   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
10060         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
10061                           [(match_operand 3 "cc_register" "") (const_int 0)])
10062                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
10063                          (not:SI
10064                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
10065   "TARGET_ARM"
10066   "@
10067    mvn%D4\\t%0, %2
10068    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
10069   [(set_attr "conds" "use")
10070    (set_attr "length" "4,8")]
10073 ;; The next two patterns occur when an AND operation is followed by a
10074 ;; scc insn sequence 
10076 (define_insn "*sign_extract_onebit"
10077   [(set (match_operand:SI 0 "s_register_operand" "=r")
10078         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10079                          (const_int 1)
10080                          (match_operand:SI 2 "const_int_operand" "n")))
10081     (clobber (reg:CC CC_REGNUM))]
10082   "TARGET_ARM"
10083   "*
10084     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10085     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
10086     return \"mvnne\\t%0, #0\";
10087   "
10088   [(set_attr "conds" "clob")
10089    (set_attr "length" "8")]
10092 (define_insn "*not_signextract_onebit"
10093   [(set (match_operand:SI 0 "s_register_operand" "=r")
10094         (not:SI
10095          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
10096                           (const_int 1)
10097                           (match_operand:SI 2 "const_int_operand" "n"))))
10098    (clobber (reg:CC CC_REGNUM))]
10099   "TARGET_ARM"
10100   "*
10101     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
10102     output_asm_insn (\"tst\\t%1, %2\", operands);
10103     output_asm_insn (\"mvneq\\t%0, #0\", operands);
10104     return \"movne\\t%0, #0\";
10105   "
10106   [(set_attr "conds" "clob")
10107    (set_attr "length" "12")]
10110 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
10111 ;; expressions.  For simplicity, the first register is also in the unspec
10112 ;; part.
10113 (define_insn "*push_multi"
10114   [(match_parallel 2 "multi_register_push"
10115     [(set (match_operand:BLK 0 "memory_operand" "=m")
10116           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
10117                       UNSPEC_PUSH_MULT))])]
10118   "TARGET_ARM"
10119   "*
10120   {
10121     int num_saves = XVECLEN (operands[2], 0);
10122      
10123     /* For the StrongARM at least it is faster to
10124        use STR to store only a single register.  */
10125     if (num_saves == 1)
10126       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
10127     else
10128       {
10129         int i;
10130         char pattern[100];
10132         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
10134         for (i = 1; i < num_saves; i++)
10135           {
10136             strcat (pattern, \", %|\");
10137             strcat (pattern,
10138                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
10139           }
10141         strcat (pattern, \"}\");
10142         output_asm_insn (pattern, operands);
10143       }
10145     return \"\";
10146   }"
10147   [(set_attr "type" "store4")]
10150 (define_insn "stack_tie"
10151   [(set (mem:BLK (scratch))
10152         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
10153                      (match_operand:SI 1 "s_register_operand" "r")]
10154                     UNSPEC_PRLG_STK))]
10155   ""
10156   ""
10157   [(set_attr "length" "0")]
10160 ;; Similarly for the floating point registers
10161 (define_insn "*push_fp_multi"
10162   [(match_parallel 2 "multi_register_push"
10163     [(set (match_operand:BLK 0 "memory_operand" "=m")
10164           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
10165                       UNSPEC_PUSH_MULT))])]
10166   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
10167   "*
10168   {
10169     char pattern[100];
10171     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
10172     output_asm_insn (pattern, operands);
10173     return \"\";
10174   }"
10175   [(set_attr "type" "f_store")]
10178 ;; Special patterns for dealing with the constant pool
10180 (define_insn "align_4"
10181   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
10182   "TARGET_EITHER"
10183   "*
10184   assemble_align (32);
10185   return \"\";
10186   "
10189 (define_insn "align_8"
10190   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
10191   "TARGET_EITHER"
10192   "*
10193   assemble_align (64);
10194   return \"\";
10195   "
10198 (define_insn "consttable_end"
10199   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
10200   "TARGET_EITHER"
10201   "*
10202   making_const_table = FALSE;
10203   return \"\";
10204   "
10207 (define_insn "consttable_1"
10208   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
10209   "TARGET_THUMB"
10210   "*
10211   making_const_table = TRUE;
10212   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
10213   assemble_zeros (3);
10214   return \"\";
10215   "
10216   [(set_attr "length" "4")]
10219 (define_insn "consttable_2"
10220   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
10221   "TARGET_THUMB"
10222   "*
10223   making_const_table = TRUE;
10224   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
10225   assemble_zeros (2);
10226   return \"\";
10227   "
10228   [(set_attr "length" "4")]
10231 (define_insn "consttable_4"
10232   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
10233   "TARGET_EITHER"
10234   "*
10235   {
10236     making_const_table = TRUE;
10237     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10238       {
10239       case MODE_FLOAT:
10240       {
10241         REAL_VALUE_TYPE r;
10242         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10243         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10244         break;
10245       }
10246       default:
10247         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
10248         break;
10249       }
10250     return \"\";
10251   }"
10252   [(set_attr "length" "4")]
10255 (define_insn "consttable_8"
10256   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
10257   "TARGET_EITHER"
10258   "*
10259   {
10260     making_const_table = TRUE;
10261     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
10262       {
10263        case MODE_FLOAT:
10264         {
10265           REAL_VALUE_TYPE r;
10266           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
10267           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
10268           break;
10269         }
10270       default:
10271         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
10272         break;
10273       }
10274     return \"\";
10275   }"
10276   [(set_attr "length" "8")]
10279 ;; Miscellaneous Thumb patterns
10281 (define_expand "tablejump"
10282   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
10283               (use (label_ref (match_operand 1 "" "")))])]
10284   "TARGET_THUMB"
10285   "
10286   if (flag_pic)
10287     {
10288       /* Hopefully, CSE will eliminate this copy.  */
10289       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
10290       rtx reg2 = gen_reg_rtx (SImode);
10292       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
10293       operands[0] = reg2;
10294     }
10295   "
10298 ;; NB never uses BX.
10299 (define_insn "*thumb_tablejump"
10300   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10301    (use (label_ref (match_operand 1 "" "")))]
10302   "TARGET_THUMB"
10303   "mov\\t%|pc, %0"
10304   [(set_attr "length" "2")]
10307 ;; V5 Instructions,
10309 (define_insn "clzsi2"
10310   [(set (match_operand:SI 0 "s_register_operand" "=r")
10311         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10312   "TARGET_ARM && arm_arch5"
10313   "clz%?\\t%0, %1"
10314   [(set_attr "predicable" "yes")])
10316 (define_expand "ffssi2"
10317   [(set (match_operand:SI 0 "s_register_operand" "")
10318         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10319   "TARGET_ARM && arm_arch5"
10320   "
10321   {
10322     rtx t1, t2, t3;
10324     t1 = gen_reg_rtx (SImode);
10325     t2 = gen_reg_rtx (SImode);
10326     t3 = gen_reg_rtx (SImode);
10328     emit_insn (gen_negsi2 (t1, operands[1]));
10329     emit_insn (gen_andsi3 (t2, operands[1], t1));
10330     emit_insn (gen_clzsi2 (t3, t2));
10331     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10332     DONE;
10333   }"
10336 (define_expand "ctzsi2"
10337   [(set (match_operand:SI 0 "s_register_operand" "")
10338         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10339   "TARGET_ARM && arm_arch5"
10340   "
10341   {
10342     rtx t1, t2, t3;
10344     t1 = gen_reg_rtx (SImode);
10345     t2 = gen_reg_rtx (SImode);
10346     t3 = gen_reg_rtx (SImode);
10348     emit_insn (gen_negsi2 (t1, operands[1]));
10349     emit_insn (gen_andsi3 (t2, operands[1], t1));
10350     emit_insn (gen_clzsi2 (t3, t2));
10351     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10352     DONE;
10353   }"
10356 ;; V5E instructions.
10358 (define_insn "prefetch"
10359   [(prefetch (match_operand:SI 0 "address_operand" "p")
10360              (match_operand:SI 1 "" "")
10361              (match_operand:SI 2 "" ""))]
10362   "TARGET_ARM && arm_arch5e"
10363   "pld\\t%a0")
10365 ;; General predication pattern
10367 (define_cond_exec
10368   [(match_operator 0 "arm_comparison_operator"
10369     [(match_operand 1 "cc_register" "")
10370      (const_int 0)])]
10371   "TARGET_ARM"
10372   ""
10375 (define_insn "prologue_use"
10376   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10377   ""
10378   "%@ %0 needed for prologue"
10382 ;; Patterns for exception handling
10384 (define_expand "eh_return"
10385   [(use (match_operand 0 "general_operand" ""))]
10386   "TARGET_EITHER"
10387   "
10388   {
10389     if (TARGET_ARM)
10390       emit_insn (gen_arm_eh_return (operands[0]));
10391     else
10392       emit_insn (gen_thumb_eh_return (operands[0]));
10393     DONE;
10394   }"
10396                                    
10397 ;; We can't expand this before we know where the link register is stored.
10398 (define_insn_and_split "arm_eh_return"
10399   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
10400                     VUNSPEC_EH_RETURN)
10401    (clobber (match_scratch:SI 1 "=&r"))]
10402   "TARGET_ARM"
10403   "#"
10404   "&& reload_completed"
10405   [(const_int 0)]
10406   "
10407   {
10408     arm_set_return_address (operands[0], operands[1]);
10409     DONE;
10410   }"
10413 (define_insn_and_split "thumb_eh_return"
10414   [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
10415                     VUNSPEC_EH_RETURN)
10416    (clobber (match_scratch:SI 1 "=&l"))]
10417   "TARGET_THUMB"
10418   "#"
10419   "&& reload_completed"
10420   [(const_int 0)]
10421   "
10422   {
10423     thumb_set_return_address (operands[0], operands[1]);
10424     DONE;
10425   }"
10428 ;; Load the FPA co-processor patterns
10429 (include "fpa.md")
10430 ;; Load the Maverick co-processor patterns
10431 (include "cirrus.md")
10432 ;; Load the Intel Wireless Multimedia Extension patterns
10433 (include "iwmmxt.md")
10434 ;; Load the VFP co-processor patterns
10435 (include "vfp.md")