OSDN Git Service

* arm.h (TARGET_APCS_32): Delete.
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm.md
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  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).
7
8 ;; This file is part of GCC.
9
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.
14
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.
19
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.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 \f
28 ;;---------------------------------------------------------------------------
29 ;; Constants
30
31 ;; Register numbers
32 (define_constants
33   [(IP_REGNUM       12)         ; Scratch register
34    (SP_REGNUM       13)         ; Stack pointer
35    (LR_REGNUM       14)         ; Return address register
36    (PC_REGNUM       15)         ; Program counter
37    (CC_REGNUM       24)         ; Condition code pseudo register
38    (LAST_ARM_REGNUM 15)
39   ]
40 )
41 ;; 3rd operand to select_dominance_cc_mode
42 (define_constants
43   [(DOM_CC_X_AND_Y  0)
44    (DOM_CC_NX_OR_Y  1)
45    (DOM_CC_X_OR_Y   2)
46   ]
47 )
48
49 ;; UNSPEC Usage:
50 ;; Note: sin and cos are no-longer used.
51
52 (define_constants
53   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
54                         ;   operand 0 is the result,
55                         ;   operand 1 the parameter.
56    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60                         ;   operand 0 is the first register,
61                         ;   subsequent registers are in parallel (use ...)
62                         ;   expressions.
63    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
64                         ;   usage, that is, we will add the pic_register
65                         ;   value to it before trying to dereference it.
66    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
67                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
68                         ;   described by the RTL but must be wrapped to
69                         ;   prevent combine from trying to rip it apart.
70    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
71                         ;   being scheduled before the stack adjustment insn.
72    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73                         ; this unspec is used to prevent the deletion of
74                         ; instructions setting registers for EH handling
75                         ; and stack frame generation.  Operand 0 is the
76                         ; register to "use".
77    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
90   ]
91 )
92
93 ;; UNSPEC_VOLATILE Usage:
94
95 (define_constants
96   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
97                         ;   insn in the code.
98    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99                         ;   instruction epilogue sequence that isn't expanded
100                         ;   into normal RTL.  Used for both normal and sibcall
101                         ;   epilogues.
102    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
103                         ;   for inlined constants.
104    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
105                         ;   table.
106    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
107                         ;   an 8-bit object.
108    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
109                         ;   a 16-bit object.
110    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
111                         ;   a 32-bit object.
112    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
113                         ;   a 64-bit object.
114    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
115    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
116    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
117    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
118    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
120   ]
121 )
122 \f
123 ;;---------------------------------------------------------------------------
124 ;; Attributes
125
126 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127 ; generating ARM code.  This is used to control the length of some insn
128 ; patterns that share the same RTL in both ARM and Thumb code.
129 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
130
131 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
132 ; scheduling decisions for the load unit and the multiplier.
133 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
134
135 ; IS_XSCALE is set to 'yes' when compiling for XScale.
136 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
137
138 ;; Operand number of an input operand that is shifted.  Zero if the
139 ;; given instruction does not shift one of its input operands.
140 (define_attr "shift" "" (const_int 0))
141
142 ; Floating Point Unit.  If we only have floating point emulation, then there
143 ; is no point in scheduling the floating point insns.  (Well, for best
144 ; performance we should try and group them together).
145 (define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
146   (const (symbol_ref "arm_fpu_attr")))
147
148 ; LENGTH of an instruction (in bytes)
149 (define_attr "length" "" (const_int 4))
150
151 ; POOL_RANGE is how far away from a constant pool entry that this insn
152 ; can be placed.  If the distance is zero, then this insn will never
153 ; reference the pool.
154 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
155 ; before its address.
156 (define_attr "pool_range" "" (const_int 0))
157 (define_attr "neg_pool_range" "" (const_int 0))
158
159 ; An assembler sequence may clobber the condition codes without us knowing.
160 ; If such an insn references the pool, then we have no way of knowing how,
161 ; so use the most conservative value for pool_range.
162 (define_asm_attributes
163  [(set_attr "conds" "clob")
164   (set_attr "length" "4")
165   (set_attr "pool_range" "250")])
166
167 ;; The instruction used to implement a particular pattern.  This
168 ;; information is used by pipeline descriptions to provide accurate
169 ;; scheduling information.
170
171 (define_attr "insn"
172         "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"
173         (const_string "other"))
174
175 ; TYPE attribute is used to detect floating point instructions which, if
176 ; running on a co-processor can run in parallel with other, basic instructions
177 ; If write-buffer scheduling is enabled then it can also be used in the
178 ; scheduling of writes.
179
180 ; Classification of each insn
181 ; alu           any alu  instruction that doesn't hit memory or fp
182 ;               regs or have a shifted source operand
183 ; alu_shift     any data instruction that doesn't hit memory or fp
184 ;               regs, but has a source operand shifted by a constant
185 ; alu_shift_reg any data instruction that doesn't hit memory or fp
186 ;               regs, but has a source operand shifted by a register value
187 ; mult          a multiply instruction
188 ; block         blockage insn, this blocks all functional units
189 ; float         a floating point arithmetic operation (subject to expansion)
190 ; fdivd         DFmode floating point division
191 ; fdivs         SFmode floating point division
192 ; fmul          Floating point multiply
193 ; ffmul         Fast floating point multiply
194 ; farith        Floating point arithmetic (4 cycle)
195 ; ffarith       Fast floating point arithmetic (2 cycle)
196 ; float_em      a floating point arithmetic operation that is normally emulated
197 ;               even on a machine with an fpa.
198 ; f_load        a floating point load from memory
199 ; f_store       a floating point store to memory
200 ; f_mem_r       a transfer of a floating point register to a real reg via mem
201 ; r_mem_f       the reverse of f_mem_r
202 ; f_2_r         fast transfer float to arm (no memory needed)
203 ; r_2_f         fast transfer arm to float
204 ; branch        a branch
205 ; call          a subroutine call
206 ; load_byte     load byte(s) from memory to arm registers
207 ; load1         load 1 word from memory to arm registers
208 ; load2         load 2 words from memory to arm registers
209 ; load3         load 3 words from memory to arm registers
210 ; load4         load 4 words from memory to arm registers
211 ; store         store 1 word to memory from arm registers
212 ; store2        store 2 words
213 ; store3        store 3 words
214 ; store4        store 4 (or more) words
215 ;  Additions for Cirrus Maverick co-processor:
216 ; mav_farith    Floating point arithmetic (4 cycle)
217 ; mav_dmult     Double multiplies (7 cycle)
218 ;
219 (define_attr "type"
220         "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" 
221         (if_then_else 
222          (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
223          (const_string "mult")
224          (const_string "alu")))
225
226 ; Load scheduling, set from the arm_ld_sched variable
227 ; initialized by arm_override_options() 
228 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
229
230 ; condition codes: this one is used by final_prescan_insn to speed up
231 ; conditionalizing instructions.  It saves having to scan the rtl to see if
232 ; it uses or alters the condition codes.
233
234 ; USE means that the condition codes are used by the insn in the process of
235 ;   outputting code, this means (at present) that we can't use the insn in
236 ;   inlined branches
237 ;
238 ; SET means that the purpose of the insn is to set the condition codes in a
239 ;   well defined manner.
240 ;
241 ; CLOB means that the condition codes are altered in an undefined manner, if
242 ;   they are altered at all
243 ;
244 ; JUMP_CLOB is used when the condition cannot be represented by a single
245 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
246 ;
247 ; NOCOND means that the condition codes are neither altered nor affect the
248 ;   output of this insn
249
250 (define_attr "conds" "use,set,clob,jump_clob,nocond"
251         (if_then_else (eq_attr "type" "call")
252          (const_string "clob")
253          (const_string "nocond")))
254
255 ; Predicable means that the insn can be conditionally executed based on
256 ; an automatically added predicate (additional patterns are generated by 
257 ; gen...).  We default to 'no' because no Thumb patterns match this rule
258 ; and not all ARM patterns do.
259 (define_attr "predicable" "no,yes" (const_string "no"))
260
261 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
262 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
263 ; suffer blockages enough to warrant modelling this (and it can adversely
264 ; affect the schedule).
265 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
266
267 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
268 ; to stall the processor.  Used with model_wbuf above.
269 (define_attr "write_conflict" "no,yes"
270   (if_then_else (eq_attr "type"
271                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
272                 (const_string "yes")
273                 (const_string "no")))
274
275 ; Classify the insns into those that take one cycle and those that take more
276 ; than one on the main cpu execution unit.
277 (define_attr "core_cycles" "single,multi"
278   (if_then_else (eq_attr "type"
279                  "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
280                 (const_string "single")
281                 (const_string "multi")))
282
283 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
284 ;; distant label.  Only applicable to Thumb code.
285 (define_attr "far_jump" "yes,no" (const_string "no"))
286
287 ;;---------------------------------------------------------------------------
288 ;; Pipeline descriptions
289
290 ;; Processor type.  This attribute must exactly match the table in 
291 ;; arm-cores.def.
292 (define_attr "tune" 
293              "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7m,arm7d,arm7dm,arm7di,arm7dmi,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7tdmi,arm710t,arm720t,arm740t,arm8,arm810,arm9,arm920,arm920t,arm940t,arm9tdmi,arm9e,ep9312,strongarm,strongarm110,strongarm1100,strongarm1110,arm10tdmi,arm1020t,arm926ejs,arm1026ejs,xscale,iwmmxt,arm1136js,arm1136jfs"
294              (const (symbol_ref "arm_tune")))
295
296 ;; True if the generic scheduling description should be used.
297
298 (define_attr "generic_sched" "yes,no"
299         (if_then_else 
300          (eq_attr "tune" "arm926ejs,arm1026ejs,arm1136js,arm1136jfs") 
301          (const_string "no")
302          (const_string "yes")))
303         
304 (include "arm-generic.md")
305 (include "arm926ejs.md")
306 (include "arm1026ejs.md")
307 (include "arm1136jfs.md")
308
309 \f
310 ;;---------------------------------------------------------------------------
311 ;; Insn patterns
312 ;;
313 ;; Addition insns.
314
315 ;; Note: For DImode insns, there is normally no reason why operands should
316 ;; not be in the same register, what we don't want is for something being
317 ;; written to partially overlap something that is an input.
318 ;; Cirrus 64bit additions should not be split because we have a native
319 ;; 64bit addition instructions.
320
321 (define_expand "adddi3"
322  [(parallel
323    [(set (match_operand:DI           0 "s_register_operand" "")
324           (plus:DI (match_operand:DI 1 "s_register_operand" "")
325                    (match_operand:DI 2 "s_register_operand" "")))
326     (clobber (reg:CC CC_REGNUM))])]
327   "TARGET_EITHER"
328   "
329   if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
330     {
331       if (!cirrus_fp_register (operands[0], DImode))
332         operands[0] = force_reg (DImode, operands[0]);
333       if (!cirrus_fp_register (operands[1], DImode))
334         operands[1] = force_reg (DImode, operands[1]);
335       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
336       DONE;
337     }
338
339   if (TARGET_THUMB)
340     {
341       if (GET_CODE (operands[1]) != REG)
342         operands[1] = force_reg (SImode, operands[1]);
343       if (GET_CODE (operands[2]) != REG)
344         operands[2] = force_reg (SImode, operands[2]);
345      }
346   "
347 )
348
349 (define_insn "*thumb_adddi3"
350   [(set (match_operand:DI          0 "register_operand" "=l")
351         (plus:DI (match_operand:DI 1 "register_operand" "%0")
352                  (match_operand:DI 2 "register_operand" "l")))
353    (clobber (reg:CC CC_REGNUM))
354   ]
355   "TARGET_THUMB"
356   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
357   [(set_attr "length" "4")]
358 )
359
360 (define_insn_and_split "*arm_adddi3"
361   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
362         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
363                  (match_operand:DI 2 "s_register_operand" "r,  0")))
364    (clobber (reg:CC CC_REGNUM))]
365   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
366   "#"
367   "TARGET_ARM && reload_completed"
368   [(parallel [(set (reg:CC_C CC_REGNUM)
369                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
370                                  (match_dup 1)))
371               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
372    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
373                                (plus:SI (match_dup 4) (match_dup 5))))]
374   "
375   {
376     operands[3] = gen_highpart (SImode, operands[0]);
377     operands[0] = gen_lowpart (SImode, operands[0]);
378     operands[4] = gen_highpart (SImode, operands[1]);
379     operands[1] = gen_lowpart (SImode, operands[1]);
380     operands[5] = gen_highpart (SImode, operands[2]);
381     operands[2] = gen_lowpart (SImode, operands[2]);
382   }"
383   [(set_attr "conds" "clob")
384    (set_attr "length" "8")]
385 )
386
387 (define_insn_and_split "*adddi_sesidi_di"
388   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
389         (plus:DI (sign_extend:DI
390                   (match_operand:SI 2 "s_register_operand" "r,r"))
391                  (match_operand:DI 1 "s_register_operand" "r,0")))
392    (clobber (reg:CC CC_REGNUM))]
393   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
394   "#"
395   "TARGET_ARM && reload_completed"
396   [(parallel [(set (reg:CC_C CC_REGNUM)
397                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
398                                  (match_dup 1)))
399               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
400    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
401                                (plus:SI (ashiftrt:SI (match_dup 2)
402                                                      (const_int 31))
403                                         (match_dup 4))))]
404   "
405   {
406     operands[3] = gen_highpart (SImode, operands[0]);
407     operands[0] = gen_lowpart (SImode, operands[0]);
408     operands[4] = gen_highpart (SImode, operands[1]);
409     operands[1] = gen_lowpart (SImode, operands[1]);
410     operands[2] = gen_lowpart (SImode, operands[2]);
411   }"
412   [(set_attr "conds" "clob")
413    (set_attr "length" "8")]
414 )
415
416 (define_insn_and_split "*adddi_zesidi_di"
417   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
418         (plus:DI (zero_extend:DI
419                   (match_operand:SI 2 "s_register_operand" "r,r"))
420                  (match_operand:DI 1 "s_register_operand" "r,0")))
421    (clobber (reg:CC CC_REGNUM))]
422   "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
423   "#"
424   "TARGET_ARM && reload_completed"
425   [(parallel [(set (reg:CC_C CC_REGNUM)
426                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
427                                  (match_dup 1)))
428               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
429    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
430                                (plus:SI (match_dup 4) (const_int 0))))]
431   "
432   {
433     operands[3] = gen_highpart (SImode, operands[0]);
434     operands[0] = gen_lowpart (SImode, operands[0]);
435     operands[4] = gen_highpart (SImode, operands[1]);
436     operands[1] = gen_lowpart (SImode, operands[1]);
437     operands[2] = gen_lowpart (SImode, operands[2]);
438   }"
439   [(set_attr "conds" "clob")
440    (set_attr "length" "8")]
441 )
442
443 (define_expand "addsi3"
444   [(set (match_operand:SI          0 "s_register_operand" "")
445         (plus:SI (match_operand:SI 1 "s_register_operand" "")
446                  (match_operand:SI 2 "reg_or_int_operand" "")))]
447   "TARGET_EITHER"
448   "
449   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
450     {
451       arm_split_constant (PLUS, SImode, NULL_RTX,
452                           INTVAL (operands[2]), operands[0], operands[1],
453                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
454       DONE;
455     }
456   "
457 )
458
459 ; If there is a scratch available, this will be faster than synthesizing the
460 ; addition.
461 (define_peephole2
462   [(match_scratch:SI 3 "r")
463    (set (match_operand:SI          0 "arm_general_register_operand" "")
464         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
465                  (match_operand:SI 2 "const_int_operand"  "")))]
466   "TARGET_ARM &&
467    !(const_ok_for_arm (INTVAL (operands[2]))
468      || const_ok_for_arm (-INTVAL (operands[2])))
469     && const_ok_for_arm (~INTVAL (operands[2]))"
470   [(set (match_dup 3) (match_dup 2))
471    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
472   ""
473 )
474
475 (define_insn_and_split "*arm_addsi3"
476   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
477         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
478                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
479   "TARGET_ARM"
480   "@
481    add%?\\t%0, %1, %2
482    sub%?\\t%0, %1, #%n2
483    #"
484   "TARGET_ARM &&
485    GET_CODE (operands[2]) == CONST_INT
486    && !(const_ok_for_arm (INTVAL (operands[2]))
487         || const_ok_for_arm (-INTVAL (operands[2])))"
488   [(clobber (const_int 0))]
489   "
490   arm_split_constant (PLUS, SImode, curr_insn,
491                       INTVAL (operands[2]), operands[0],
492                       operands[1], 0);
493   DONE;
494   "
495   [(set_attr "length" "4,4,16")
496    (set_attr "predicable" "yes")]
497 )
498
499 ;; Register group 'k' is a single register group containing only the stack
500 ;; register.  Trying to reload it will always fail catastrophically,
501 ;; so never allow those alternatives to match if reloading is needed.
502
503 (define_insn "*thumb_addsi3"
504   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
505         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
506                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
507   "TARGET_THUMB"
508   "*
509    static const char * const asms[] = 
510    {
511      \"add\\t%0, %0, %2\",
512      \"sub\\t%0, %0, #%n2\",
513      \"add\\t%0, %1, %2\",
514      \"add\\t%0, %0, %2\",
515      \"add\\t%0, %0, %2\",
516      \"add\\t%0, %1, %2\",
517      \"add\\t%0, %1, %2\"
518    };
519    if ((which_alternative == 2 || which_alternative == 6)
520        && GET_CODE (operands[2]) == CONST_INT
521        && INTVAL (operands[2]) < 0)
522      return \"sub\\t%0, %1, #%n2\";
523    return asms[which_alternative];
524   "
525   [(set_attr "length" "2")]
526 )
527
528 ;; Reloading and elimination of the frame pointer can
529 ;; sometimes cause this optimization to be missed.
530 (define_peephole2
531   [(set (match_operand:SI 0 "arm_general_register_operand" "")
532         (match_operand:SI 1 "const_int_operand" ""))
533    (set (match_dup 0)
534         (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
535   "TARGET_THUMB
536    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
537    && (INTVAL (operands[1]) & 3) == 0"
538   [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
539   ""
540 )
541
542 (define_insn "*addsi3_compare0"
543   [(set (reg:CC_NOOV CC_REGNUM)
544         (compare:CC_NOOV
545          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
546                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
547          (const_int 0)))
548    (set (match_operand:SI 0 "s_register_operand" "=r,r")
549         (plus:SI (match_dup 1) (match_dup 2)))]
550   "TARGET_ARM"
551   "@
552    add%?s\\t%0, %1, %2
553    sub%?s\\t%0, %1, #%n2"
554   [(set_attr "conds" "set")]
555 )
556
557 (define_insn "*addsi3_compare0_scratch"
558   [(set (reg:CC_NOOV CC_REGNUM)
559         (compare:CC_NOOV
560          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
561                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
562          (const_int 0)))]
563   "TARGET_ARM"
564   "@
565    cmn%?\\t%0, %1
566    cmp%?\\t%0, #%n1"
567   [(set_attr "conds" "set")]
568 )
569
570 ;; These patterns are the same ones as the two regular addsi3_compare0
571 ;; patterns, except we write them slightly different - the combiner
572 ;; tends to generate them this way.
573 (define_insn "*addsi3_compare0_for_combiner"
574   [(set (reg:CC CC_REGNUM)
575         (compare:CC
576          (match_operand:SI 1 "s_register_operand" "r,r")
577          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
578    (set (match_operand:SI 0 "s_register_operand" "=r,r")
579         (plus:SI (match_dup 1) (match_dup 2)))]
580   "TARGET_ARM"
581   "@
582    add%?s\\t%0, %1, %2
583    sub%?s\\t%0, %1, #%n2"
584   [(set_attr "conds" "set")]
585 )
586
587 (define_insn "*addsi3_compare0_scratch_for_combiner"
588   [(set (reg:CC CC_REGNUM)
589         (compare:CC
590          (match_operand:SI 0 "s_register_operand" "r,r")
591          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
592   "TARGET_ARM"
593   "@
594    cmn%?\\t%0, %1
595    cmp%?\\t%0, #%n1"
596   [(set_attr "conds" "set")]
597 )
598
599 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
600 ;; addend is a constant.
601 (define_insn "*cmpsi2_addneg"
602   [(set (reg:CC CC_REGNUM)
603         (compare:CC
604          (match_operand:SI 1 "s_register_operand" "r,r")
605          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
606    (set (match_operand:SI 0 "s_register_operand" "=r,r")
607         (plus:SI (match_dup 1)
608                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
609   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
610   "@
611    sub%?s\\t%0, %1, %2
612    add%?s\\t%0, %1, #%n2"
613   [(set_attr "conds" "set")]
614 )
615
616 ;; Convert the sequence
617 ;;  sub  rd, rn, #1
618 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
619 ;;  bne  dest
620 ;; into
621 ;;  subs rd, rn, #1
622 ;;  bcs  dest   ((unsigned)rn >= 1)
623 ;; similarly for the beq variant using bcc.
624 ;; This is a common looping idiom (while (n--))
625 (define_peephole2
626   [(set (match_operand:SI 0 "arm_general_register_operand" "")
627         (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
628                  (const_int -1)))
629    (set (match_operand 2 "cc_register" "")
630         (compare (match_dup 0) (const_int -1)))
631    (set (pc)
632         (if_then_else (match_operator 3 "equality_operator"
633                        [(match_dup 2) (const_int 0)])
634                       (match_operand 4 "" "")
635                       (match_operand 5 "" "")))]
636   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
637   [(parallel[
638     (set (match_dup 2)
639          (compare:CC
640           (match_dup 1) (const_int 1)))
641     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
642    (set (pc)
643         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
644                       (match_dup 4)
645                       (match_dup 5)))]
646   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
647    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
648                                   ? GEU : LTU),
649                                  VOIDmode, 
650                                  operands[2], const0_rtx);"
651 )
652
653 ;; The next four insns work because they compare the result with one of
654 ;; the operands, and we know that the use of the condition code is
655 ;; either GEU or LTU, so we can use the carry flag from the addition
656 ;; instead of doing the compare a second time.
657 (define_insn "*addsi3_compare_op1"
658   [(set (reg:CC_C CC_REGNUM)
659         (compare:CC_C
660          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
661                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
662          (match_dup 1)))
663    (set (match_operand:SI 0 "s_register_operand" "=r,r")
664         (plus:SI (match_dup 1) (match_dup 2)))]
665   "TARGET_ARM"
666   "@
667    add%?s\\t%0, %1, %2
668    sub%?s\\t%0, %1, #%n2"
669   [(set_attr "conds" "set")]
670 )
671
672 (define_insn "*addsi3_compare_op2"
673   [(set (reg:CC_C CC_REGNUM)
674         (compare:CC_C
675          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
676                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
677          (match_dup 2)))
678    (set (match_operand:SI 0 "s_register_operand" "=r,r")
679         (plus:SI (match_dup 1) (match_dup 2)))]
680   "TARGET_ARM"
681   "@
682    add%?s\\t%0, %1, %2
683    sub%?s\\t%0, %1, #%n2"
684   [(set_attr "conds" "set")]
685 )
686
687 (define_insn "*compare_addsi2_op0"
688   [(set (reg:CC_C CC_REGNUM)
689         (compare:CC_C
690          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
691                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
692          (match_dup 0)))]
693   "TARGET_ARM"
694   "@
695    cmn%?\\t%0, %1
696    cmp%?\\t%0, #%n1"
697   [(set_attr "conds" "set")]
698 )
699
700 (define_insn "*compare_addsi2_op1"
701   [(set (reg:CC_C CC_REGNUM)
702         (compare:CC_C
703          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
704                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
705          (match_dup 1)))]
706   "TARGET_ARM"
707   "@
708    cmn%?\\t%0, %1
709    cmp%?\\t%0, #%n1"
710   [(set_attr "conds" "set")]
711 )
712
713 (define_insn "*addsi3_carryin"
714   [(set (match_operand:SI 0 "s_register_operand" "=r")
715         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
716                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
717                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
718   "TARGET_ARM"
719   "adc%?\\t%0, %1, %2"
720   [(set_attr "conds" "use")]
721 )
722
723 (define_insn "*addsi3_carryin_shift"
724   [(set (match_operand:SI 0 "s_register_operand" "=r")
725         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
726                  (plus:SI
727                    (match_operator:SI 2 "shift_operator"
728                       [(match_operand:SI 3 "s_register_operand" "r")
729                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
730                     (match_operand:SI 1 "s_register_operand" "r"))))]
731   "TARGET_ARM"
732   "adc%?\\t%0, %1, %3%S2"
733   [(set_attr "conds" "use")
734    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
735                       (const_string "alu_shift")
736                       (const_string "alu_shift_reg")))]
737 )
738
739 (define_insn "*addsi3_carryin_alt1"
740   [(set (match_operand:SI 0 "s_register_operand" "=r")
741         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
742                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
743                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
744   "TARGET_ARM"
745   "adc%?\\t%0, %1, %2"
746   [(set_attr "conds" "use")]
747 )
748
749 (define_insn "*addsi3_carryin_alt2"
750   [(set (match_operand:SI 0 "s_register_operand" "=r")
751         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
752                           (match_operand:SI 1 "s_register_operand" "r"))
753                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
754   "TARGET_ARM"
755   "adc%?\\t%0, %1, %2"
756   [(set_attr "conds" "use")]
757 )
758
759 (define_insn "*addsi3_carryin_alt3"
760   [(set (match_operand:SI 0 "s_register_operand" "=r")
761         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
762                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
763                  (match_operand:SI 1 "s_register_operand" "r")))]
764   "TARGET_ARM"
765   "adc%?\\t%0, %1, %2"
766   [(set_attr "conds" "use")]
767 )
768
769 (define_insn "incscc"
770   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
771         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
772                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
773                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
774   "TARGET_ARM"
775   "@
776   add%d2\\t%0, %1, #1
777   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
778   [(set_attr "conds" "use")
779    (set_attr "length" "4,8")]
780 )
781
782 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
783 (define_split
784   [(set (match_operand:SI 0 "s_register_operand" "")
785         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
786                             (match_operand:SI 2 "s_register_operand" ""))
787                  (const_int -1)))
788    (clobber (match_operand:SI 3 "s_register_operand" ""))]
789   "TARGET_ARM"
790   [(set (match_dup 3) (match_dup 1))
791    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
792   "
793   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
794 ")
795
796 (define_expand "addsf3"
797   [(set (match_operand:SF          0 "s_register_operand" "")
798         (plus:SF (match_operand:SF 1 "s_register_operand" "")
799                  (match_operand:SF 2 "arm_float_add_operand" "")))]
800   "TARGET_ARM && TARGET_HARD_FLOAT"
801   "
802   if (TARGET_MAVERICK
803       && !cirrus_fp_register (operands[2], SFmode))
804     operands[2] = force_reg (SFmode, operands[2]);
805 ")
806
807 (define_expand "adddf3"
808   [(set (match_operand:DF          0 "s_register_operand" "")
809         (plus:DF (match_operand:DF 1 "s_register_operand" "")
810                  (match_operand:DF 2 "arm_float_add_operand" "")))]
811   "TARGET_ARM && TARGET_HARD_FLOAT"
812   "
813   if (TARGET_MAVERICK
814       && !cirrus_fp_register (operands[2], DFmode))
815     operands[2] = force_reg (DFmode, operands[2]);
816 ")
817
818 (define_expand "subdi3"
819  [(parallel
820    [(set (match_operand:DI            0 "s_register_operand" "")
821           (minus:DI (match_operand:DI 1 "s_register_operand" "")
822                     (match_operand:DI 2 "s_register_operand" "")))
823     (clobber (reg:CC CC_REGNUM))])]
824   "TARGET_EITHER"
825   "
826   if (TARGET_HARD_FLOAT && TARGET_MAVERICK
827       && TARGET_ARM
828       && cirrus_fp_register (operands[0], DImode)
829       && cirrus_fp_register (operands[1], DImode))
830     {
831       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
832       DONE;
833     }
834
835   if (TARGET_THUMB)
836     {
837       if (GET_CODE (operands[1]) != REG)
838         operands[1] = force_reg (SImode, operands[1]);
839       if (GET_CODE (operands[2]) != REG)
840         operands[2] = force_reg (SImode, operands[2]);
841      }  
842   "
843 )
844
845 (define_insn "*arm_subdi3"
846   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
847         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
848                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
849    (clobber (reg:CC CC_REGNUM))]
850   "TARGET_ARM"
851   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
852   [(set_attr "conds" "clob")
853    (set_attr "length" "8")]
854 )
855
856 (define_insn "*thumb_subdi3"
857   [(set (match_operand:DI           0 "register_operand" "=l")
858         (minus:DI (match_operand:DI 1 "register_operand"  "0")
859                   (match_operand:DI 2 "register_operand"  "l")))
860    (clobber (reg:CC CC_REGNUM))]
861   "TARGET_THUMB"
862   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
863   [(set_attr "length" "4")]
864 )
865
866 (define_insn "*subdi_di_zesidi"
867   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
868         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
869                   (zero_extend:DI
870                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
871    (clobber (reg:CC CC_REGNUM))]
872   "TARGET_ARM"
873   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
874   [(set_attr "conds" "clob")
875    (set_attr "length" "8")]
876 )
877
878 (define_insn "*subdi_di_sesidi"
879   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
880         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
881                   (sign_extend:DI
882                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
883    (clobber (reg:CC CC_REGNUM))]
884   "TARGET_ARM"
885   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
886   [(set_attr "conds" "clob")
887    (set_attr "length" "8")]
888 )
889
890 (define_insn "*subdi_zesidi_di"
891   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
892         (minus:DI (zero_extend:DI
893                    (match_operand:SI 2 "s_register_operand"  "r,r"))
894                   (match_operand:DI  1 "s_register_operand" "?r,0")))
895    (clobber (reg:CC CC_REGNUM))]
896   "TARGET_ARM"
897   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
898   [(set_attr "conds" "clob")
899    (set_attr "length" "8")]
900 )
901
902 (define_insn "*subdi_sesidi_di"
903   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
904         (minus:DI (sign_extend:DI
905                    (match_operand:SI 2 "s_register_operand"   "r,r"))
906                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
907    (clobber (reg:CC CC_REGNUM))]
908   "TARGET_ARM"
909   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
910   [(set_attr "conds" "clob")
911    (set_attr "length" "8")]
912 )
913
914 (define_insn "*subdi_zesidi_zesidi"
915   [(set (match_operand:DI            0 "s_register_operand" "=r")
916         (minus:DI (zero_extend:DI
917                    (match_operand:SI 1 "s_register_operand"  "r"))
918                   (zero_extend:DI
919                    (match_operand:SI 2 "s_register_operand"  "r"))))
920    (clobber (reg:CC CC_REGNUM))]
921   "TARGET_ARM"
922   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
923   [(set_attr "conds" "clob")
924    (set_attr "length" "8")]
925 )
926
927 (define_expand "subsi3"
928   [(set (match_operand:SI           0 "s_register_operand" "")
929         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
930                   (match_operand:SI 2 "s_register_operand" "")))]
931   "TARGET_EITHER"
932   "
933   if (GET_CODE (operands[1]) == CONST_INT)
934     {
935       if (TARGET_ARM)
936         {
937           arm_split_constant (MINUS, SImode, NULL_RTX,
938                               INTVAL (operands[1]), operands[0],
939                               operands[2],
940                               (no_new_pseudos ? 0
941                                :  preserve_subexpressions_p ()));
942           DONE;
943         }
944       else /* TARGET_THUMB */
945         operands[1] = force_reg (SImode, operands[1]);
946     }
947   "
948 )
949
950 (define_insn "*thumb_subsi3_insn"
951   [(set (match_operand:SI           0 "register_operand" "=l")
952         (minus:SI (match_operand:SI 1 "register_operand" "l")
953                   (match_operand:SI 2 "register_operand" "l")))]
954   "TARGET_THUMB"
955   "sub\\t%0, %1, %2"
956   [(set_attr "length" "2")]
957 )
958
959 (define_insn_and_split "*arm_subsi3_insn"
960   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
961         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
962                   (match_operand:SI 2 "s_register_operand" "r,r")))]
963   "TARGET_ARM"
964   "@
965    rsb%?\\t%0, %2, %1
966    #"
967   "TARGET_ARM
968    && GET_CODE (operands[1]) == CONST_INT
969    && !const_ok_for_arm (INTVAL (operands[1]))"
970   [(clobber (const_int 0))]
971   "
972   arm_split_constant (MINUS, SImode, curr_insn,
973                       INTVAL (operands[1]), operands[0], operands[2], 0);
974   DONE;
975   "
976   [(set_attr "length" "4,16")
977    (set_attr "predicable" "yes")]
978 )
979
980 (define_peephole2
981   [(match_scratch:SI 3 "r")
982    (set (match_operand:SI 0 "arm_general_register_operand" "")
983         (minus:SI (match_operand:SI 1 "const_int_operand" "")
984                   (match_operand:SI 2 "arm_general_register_operand" "")))]
985   "TARGET_ARM
986    && !const_ok_for_arm (INTVAL (operands[1]))
987    && const_ok_for_arm (~INTVAL (operands[1]))"
988   [(set (match_dup 3) (match_dup 1))
989    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
990   ""
991 )
992
993 (define_insn "*subsi3_compare0"
994   [(set (reg:CC_NOOV CC_REGNUM)
995         (compare:CC_NOOV
996          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
997                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
998          (const_int 0)))
999    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1000         (minus:SI (match_dup 1) (match_dup 2)))]
1001   "TARGET_ARM"
1002   "@
1003    sub%?s\\t%0, %1, %2
1004    rsb%?s\\t%0, %2, %1"
1005   [(set_attr "conds" "set")]
1006 )
1007
1008 (define_insn "decscc"
1009   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1010         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1011                   (match_operator:SI 2 "arm_comparison_operator"
1012                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1013   "TARGET_ARM"
1014   "@
1015    sub%d2\\t%0, %1, #1
1016    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1017   [(set_attr "conds" "use")
1018    (set_attr "length" "*,8")]
1019 )
1020
1021 (define_expand "subsf3"
1022   [(set (match_operand:SF           0 "s_register_operand" "")
1023         (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1024                   (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1025   "TARGET_ARM && TARGET_HARD_FLOAT"
1026   "
1027   if (TARGET_MAVERICK)
1028     {
1029       if (!cirrus_fp_register (operands[1], SFmode))
1030         operands[1] = force_reg (SFmode, operands[1]);
1031       if (!cirrus_fp_register (operands[2], SFmode))
1032         operands[2] = force_reg (SFmode, operands[2]);
1033     }
1034 ")
1035
1036 (define_expand "subdf3"
1037   [(set (match_operand:DF           0 "s_register_operand" "")
1038         (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1039                   (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1040   "TARGET_ARM && TARGET_HARD_FLOAT"
1041   "
1042   if (TARGET_MAVERICK)
1043     {
1044        if (!cirrus_fp_register (operands[1], DFmode))
1045          operands[1] = force_reg (DFmode, operands[1]);
1046        if (!cirrus_fp_register (operands[2], DFmode))
1047          operands[2] = force_reg (DFmode, operands[2]);
1048     }
1049 ")
1050
1051 \f
1052 ;; Multiplication insns
1053
1054 (define_expand "mulsi3"
1055   [(set (match_operand:SI          0 "s_register_operand" "")
1056         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1057                  (match_operand:SI 1 "s_register_operand" "")))]
1058   "TARGET_EITHER"
1059   ""
1060 )
1061
1062 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1063 (define_insn "*arm_mulsi3"
1064   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1065         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1066                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1067   "TARGET_ARM"
1068   "mul%?\\t%0, %2, %1"
1069   [(set_attr "insn" "mul")
1070    (set_attr "predicable" "yes")]
1071 )
1072
1073 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1074 ; 1 and 2; are the same, because reload will make operand 0 match 
1075 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1076 ; this by adding another alternative to match this case, and then `reload' 
1077 ; it ourselves.  This alternative must come first.
1078 (define_insn "*thumb_mulsi3"
1079   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1080         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1081                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1082   "TARGET_THUMB"
1083   "*
1084   if (which_alternative < 2)
1085     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1086   else
1087     return \"mul\\t%0, %0, %2\";
1088   "
1089   [(set_attr "length" "4,4,2")
1090    (set_attr "insn" "mul")]
1091 )
1092
1093 (define_insn "*mulsi3_compare0"
1094   [(set (reg:CC_NOOV CC_REGNUM)
1095         (compare:CC_NOOV (mult:SI
1096                           (match_operand:SI 2 "s_register_operand" "r,r")
1097                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1098                          (const_int 0)))
1099    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1100         (mult:SI (match_dup 2) (match_dup 1)))]
1101   "TARGET_ARM && !arm_arch_xscale"
1102   "mul%?s\\t%0, %2, %1"
1103   [(set_attr "conds" "set")
1104    (set_attr "insn" "muls")]
1105 )
1106
1107 (define_insn "*mulsi_compare0_scratch"
1108   [(set (reg:CC_NOOV CC_REGNUM)
1109         (compare:CC_NOOV (mult:SI
1110                           (match_operand:SI 2 "s_register_operand" "r,r")
1111                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1112                          (const_int 0)))
1113    (clobber (match_scratch:SI 0 "=&r,&r"))]
1114   "TARGET_ARM && !arm_arch_xscale"
1115   "mul%?s\\t%0, %2, %1"
1116   [(set_attr "conds" "set")
1117    (set_attr "insn" "muls")]
1118 )
1119
1120 ;; Unnamed templates to match MLA instruction.
1121
1122 (define_insn "*mulsi3addsi"
1123   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1124         (plus:SI
1125           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1126                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1127           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1128   "TARGET_ARM"
1129   "mla%?\\t%0, %2, %1, %3"
1130   [(set_attr "insn" "mla")
1131    (set_attr "predicable" "yes")]
1132 )
1133
1134 (define_insn "*mulsi3addsi_compare0"
1135   [(set (reg:CC_NOOV CC_REGNUM)
1136         (compare:CC_NOOV
1137          (plus:SI (mult:SI
1138                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1139                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1140                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1141          (const_int 0)))
1142    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1143         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1144                  (match_dup 3)))]
1145   "TARGET_ARM && !arm_arch_xscale"
1146   "mla%?s\\t%0, %2, %1, %3"
1147   [(set_attr "conds" "set")
1148    (set_attr "insn" "mlas")]
1149 )
1150
1151 (define_insn "*mulsi3addsi_compare0_scratch"
1152   [(set (reg:CC_NOOV CC_REGNUM)
1153         (compare:CC_NOOV
1154          (plus:SI (mult:SI
1155                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1156                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1157                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1158          (const_int 0)))
1159    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1160   "TARGET_ARM && !arm_arch_xscale"
1161   "mla%?s\\t%0, %2, %1, %3"
1162   [(set_attr "conds" "set")
1163    (set_attr "insn" "mlas")]
1164 )
1165
1166 ;; Unnamed template to match long long multiply-accumulate (smlal)
1167
1168 (define_insn "*mulsidi3adddi"
1169   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1170         (plus:DI
1171          (mult:DI
1172           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1173           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1174          (match_operand:DI 1 "s_register_operand" "0")))]
1175   "TARGET_ARM && arm_arch3m"
1176   "smlal%?\\t%Q0, %R0, %3, %2"
1177   [(set_attr "insn" "smlal")
1178    (set_attr "predicable" "yes")]
1179 )
1180
1181 (define_insn "mulsidi3"
1182   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1183         (mult:DI
1184          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1185          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1186   "TARGET_ARM && arm_arch3m"
1187   "smull%?\\t%Q0, %R0, %1, %2"
1188   [(set_attr "insn" "smull")
1189    (set_attr "predicable" "yes")]
1190 )
1191
1192 (define_insn "umulsidi3"
1193   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1194         (mult:DI
1195          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1196          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1197   "TARGET_ARM && arm_arch3m"
1198   "umull%?\\t%Q0, %R0, %1, %2"
1199   [(set_attr "insn" "umull")
1200    (set_attr "predicable" "yes")]
1201 )
1202
1203 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1204
1205 (define_insn "*umulsidi3adddi"
1206   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1207         (plus:DI
1208          (mult:DI
1209           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1210           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1211          (match_operand:DI 1 "s_register_operand" "0")))]
1212   "TARGET_ARM && arm_arch3m"
1213   "umlal%?\\t%Q0, %R0, %3, %2"
1214   [(set_attr "insn" "umlal")
1215    (set_attr "predicable" "yes")]
1216 )
1217
1218 (define_insn "smulsi3_highpart"
1219   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1220         (truncate:SI
1221          (lshiftrt:DI
1222           (mult:DI
1223            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1224            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1225           (const_int 32))))
1226    (clobber (match_scratch:SI 3 "=&r,&r"))]
1227   "TARGET_ARM && arm_arch3m"
1228   "smull%?\\t%3, %0, %2, %1"
1229   [(set_attr "insn" "smull")
1230    (set_attr "predicable" "yes")]
1231 )
1232
1233 (define_insn "umulsi3_highpart"
1234   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1235         (truncate:SI
1236          (lshiftrt:DI
1237           (mult:DI
1238            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1239            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1240           (const_int 32))))
1241    (clobber (match_scratch:SI 3 "=&r,&r"))]
1242   "TARGET_ARM && arm_arch3m"
1243   "umull%?\\t%3, %0, %2, %1"
1244   [(set_attr "insn" "umull")
1245    (set_attr "predicable" "yes")]
1246 )
1247
1248 (define_insn "mulhisi3"
1249   [(set (match_operand:SI 0 "s_register_operand" "=r")
1250         (mult:SI (sign_extend:SI
1251                   (match_operand:HI 1 "s_register_operand" "%r"))
1252                  (sign_extend:SI
1253                   (match_operand:HI 2 "s_register_operand" "r"))))]
1254   "TARGET_ARM && arm_arch5e"
1255   "smulbb%?\\t%0, %1, %2"
1256   [(set_attr "insn" "smulxy")
1257    (set_attr "predicable" "yes")]
1258 )
1259
1260 (define_insn "*mulhisi3tb"
1261   [(set (match_operand:SI 0 "s_register_operand" "=r")
1262         (mult:SI (ashiftrt:SI
1263                   (match_operand:SI 1 "s_register_operand" "r")
1264                   (const_int 16))
1265                  (sign_extend:SI
1266                   (match_operand:HI 2 "s_register_operand" "r"))))]
1267   "TARGET_ARM && arm_arch5e"
1268   "smultb%?\\t%0, %1, %2"
1269   [(set_attr "insn" "smulxy")
1270    (set_attr "predicable" "yes")]
1271 )
1272
1273 (define_insn "*mulhisi3bt"
1274   [(set (match_operand:SI 0 "s_register_operand" "=r")
1275         (mult:SI (sign_extend:SI
1276                   (match_operand:HI 1 "s_register_operand" "r"))
1277                  (ashiftrt:SI
1278                   (match_operand:SI 2 "s_register_operand" "r")
1279                   (const_int 16))))]
1280   "TARGET_ARM && arm_arch5e"
1281   "smulbt%?\\t%0, %1, %2"
1282   [(set_attr "insn" "smulxy")
1283    (set_attr "predicable" "yes")]
1284 )
1285
1286 (define_insn "*mulhisi3tt"
1287   [(set (match_operand:SI 0 "s_register_operand" "=r")
1288         (mult:SI (ashiftrt:SI
1289                   (match_operand:SI 1 "s_register_operand" "r")
1290                   (const_int 16))
1291                  (ashiftrt:SI
1292                   (match_operand:SI 2 "s_register_operand" "r")
1293                   (const_int 16))))]
1294   "TARGET_ARM && arm_arch5e"
1295   "smultt%?\\t%0, %1, %2"
1296   [(set_attr "insn" "smulxy")
1297    (set_attr "predicable" "yes")]
1298 )
1299
1300 (define_insn "*mulhisi3addsi"
1301   [(set (match_operand:SI 0 "s_register_operand" "=r")
1302         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1303                  (mult:SI (sign_extend:SI
1304                            (match_operand:HI 2 "s_register_operand" "%r"))
1305                           (sign_extend:SI
1306                            (match_operand:HI 3 "s_register_operand" "r")))))]
1307   "TARGET_ARM && arm_arch5e"
1308   "smlabb%?\\t%0, %2, %3, %1"
1309   [(set_attr "insn" "smlaxy")
1310    (set_attr "predicable" "yes")]
1311 )
1312
1313 (define_insn "*mulhidi3adddi"
1314   [(set (match_operand:DI 0 "s_register_operand" "=r")
1315         (plus:DI
1316           (match_operand:DI 1 "s_register_operand" "0")
1317           (mult:DI (sign_extend:DI
1318                     (match_operand:HI 2 "s_register_operand" "%r"))
1319                    (sign_extend:DI
1320                     (match_operand:HI 3 "s_register_operand" "r")))))]
1321   "TARGET_ARM && arm_arch5e"
1322   "smlalbb%?\\t%Q0, %R0, %2, %3"
1323   [(set_attr "insn" "smlalxy")
1324    (set_attr "predicable" "yes")])
1325
1326 (define_expand "mulsf3"
1327   [(set (match_operand:SF          0 "s_register_operand" "")
1328         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1329                  (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1330   "TARGET_ARM && TARGET_HARD_FLOAT"
1331   "
1332   if (TARGET_MAVERICK
1333       && !cirrus_fp_register (operands[2], SFmode))
1334     operands[2] = force_reg (SFmode, operands[2]);
1335 ")
1336
1337 (define_expand "muldf3"
1338   [(set (match_operand:DF          0 "s_register_operand" "")
1339         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1340                  (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1341   "TARGET_ARM && TARGET_HARD_FLOAT"
1342   "
1343   if (TARGET_MAVERICK
1344       && !cirrus_fp_register (operands[2], DFmode))
1345     operands[2] = force_reg (DFmode, operands[2]);
1346 ")
1347 \f
1348 ;; Division insns
1349
1350 (define_expand "divsf3"
1351   [(set (match_operand:SF 0 "s_register_operand" "")
1352         (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
1353                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1354   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1355   "")
1356
1357 (define_expand "divdf3"
1358   [(set (match_operand:DF 0 "s_register_operand" "")
1359         (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
1360                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1361   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
1362   "")
1363 \f
1364 ;; Modulo insns
1365
1366 (define_expand "modsf3"
1367   [(set (match_operand:SF 0 "s_register_operand" "")
1368         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1369                 (match_operand:SF 2 "arm_float_rhs_operand" "")))]
1370   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1371   "")
1372
1373 (define_expand "moddf3"
1374   [(set (match_operand:DF 0 "s_register_operand" "")
1375         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1376                 (match_operand:DF 2 "arm_float_rhs_operand" "")))]
1377   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
1378   "")
1379 \f
1380 ;; Boolean and,ior,xor insns
1381
1382 ;; Split up double word logical operations
1383
1384 ;; Split up simple DImode logical operations.  Simply perform the logical
1385 ;; operation on the upper and lower halves of the registers.
1386 (define_split
1387   [(set (match_operand:DI 0 "s_register_operand" "")
1388         (match_operator:DI 6 "logical_binary_operator"
1389           [(match_operand:DI 1 "s_register_operand" "")
1390            (match_operand:DI 2 "s_register_operand" "")]))]
1391   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1392   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1393    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1394   "
1395   {
1396     operands[3] = gen_highpart (SImode, operands[0]);
1397     operands[0] = gen_lowpart (SImode, operands[0]);
1398     operands[4] = gen_highpart (SImode, operands[1]);
1399     operands[1] = gen_lowpart (SImode, operands[1]);
1400     operands[5] = gen_highpart (SImode, operands[2]);
1401     operands[2] = gen_lowpart (SImode, operands[2]);
1402   }"
1403 )
1404
1405 (define_split
1406   [(set (match_operand:DI 0 "s_register_operand" "")
1407         (match_operator:DI 6 "logical_binary_operator"
1408           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1409            (match_operand:DI 1 "s_register_operand" "")]))]
1410   "TARGET_ARM && reload_completed"
1411   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1412    (set (match_dup 3) (match_op_dup:SI 6
1413                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1414                          (match_dup 4)]))]
1415   "
1416   {
1417     operands[3] = gen_highpart (SImode, operands[0]);
1418     operands[0] = gen_lowpart (SImode, operands[0]);
1419     operands[4] = gen_highpart (SImode, operands[1]);
1420     operands[1] = gen_lowpart (SImode, operands[1]);
1421     operands[5] = gen_highpart (SImode, operands[2]);
1422     operands[2] = gen_lowpart (SImode, operands[2]);
1423   }"
1424 )
1425
1426 ;; The zero extend of operand 2 means we can just copy the high part of
1427 ;; operand1 into operand0.
1428 (define_split
1429   [(set (match_operand:DI 0 "s_register_operand" "")
1430         (ior:DI
1431           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1432           (match_operand:DI 1 "s_register_operand" "")))]
1433   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1434   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1435    (set (match_dup 3) (match_dup 4))]
1436   "
1437   {
1438     operands[4] = gen_highpart (SImode, operands[1]);
1439     operands[3] = gen_highpart (SImode, operands[0]);
1440     operands[0] = gen_lowpart (SImode, operands[0]);
1441     operands[1] = gen_lowpart (SImode, operands[1]);
1442   }"
1443 )
1444
1445 ;; The zero extend of operand 2 means we can just copy the high part of
1446 ;; operand1 into operand0.
1447 (define_split
1448   [(set (match_operand:DI 0 "s_register_operand" "")
1449         (xor:DI
1450           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1451           (match_operand:DI 1 "s_register_operand" "")))]
1452   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1453   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1454    (set (match_dup 3) (match_dup 4))]
1455   "
1456   {
1457     operands[4] = gen_highpart (SImode, operands[1]);
1458     operands[3] = gen_highpart (SImode, operands[0]);
1459     operands[0] = gen_lowpart (SImode, operands[0]);
1460     operands[1] = gen_lowpart (SImode, operands[1]);
1461   }"
1462 )
1463
1464 (define_insn "anddi3"
1465   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1466         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1467                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1468   "TARGET_ARM && ! TARGET_IWMMXT"
1469   "#"
1470   [(set_attr "length" "8")]
1471 )
1472
1473 (define_insn_and_split "*anddi_zesidi_di"
1474   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1475         (and:DI (zero_extend:DI
1476                  (match_operand:SI 2 "s_register_operand" "r,r"))
1477                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1478   "TARGET_ARM"
1479   "#"
1480   "TARGET_ARM && reload_completed"
1481   ; The zero extend of operand 2 clears the high word of the output
1482   ; operand.
1483   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1484    (set (match_dup 3) (const_int 0))]
1485   "
1486   {
1487     operands[3] = gen_highpart (SImode, operands[0]);
1488     operands[0] = gen_lowpart (SImode, operands[0]);
1489     operands[1] = gen_lowpart (SImode, operands[1]);
1490   }"
1491   [(set_attr "length" "8")]
1492 )
1493
1494 (define_insn "*anddi_sesdi_di"
1495   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1496         (and:DI (sign_extend:DI
1497                  (match_operand:SI 2 "s_register_operand" "r,r"))
1498                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1499   "TARGET_ARM"
1500   "#"
1501   [(set_attr "length" "8")]
1502 )
1503
1504 (define_expand "andsi3"
1505   [(set (match_operand:SI         0 "s_register_operand" "")
1506         (and:SI (match_operand:SI 1 "s_register_operand" "")
1507                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1508   "TARGET_EITHER"
1509   "
1510   if (TARGET_ARM)
1511     {
1512       if (GET_CODE (operands[2]) == CONST_INT)
1513         {
1514           arm_split_constant (AND, SImode, NULL_RTX,
1515                               INTVAL (operands[2]), operands[0],
1516                               operands[1],
1517                               (no_new_pseudos
1518                                ? 0 : preserve_subexpressions_p ()));
1519           DONE;
1520         }
1521     }
1522   else /* TARGET_THUMB */
1523     {
1524       if (GET_CODE (operands[2]) != CONST_INT)
1525         operands[2] = force_reg (SImode, operands[2]);
1526       else
1527         {
1528           int i;
1529           
1530           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1531             {
1532               operands[2] = force_reg (SImode,
1533                                        GEN_INT (~INTVAL (operands[2])));
1534               
1535               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1536               
1537               DONE;
1538             }
1539
1540           for (i = 9; i <= 31; i++)
1541             {
1542               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1543                 {
1544                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1545                                         const0_rtx));
1546                   DONE;
1547                 }
1548               else if ((((HOST_WIDE_INT) 1) << i) - 1
1549                        == ~INTVAL (operands[2]))
1550                 {
1551                   rtx shift = GEN_INT (i);
1552                   rtx reg = gen_reg_rtx (SImode);
1553                 
1554                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1555                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1556                   
1557                   DONE;
1558                 }
1559             }
1560
1561           operands[2] = force_reg (SImode, operands[2]);
1562         }
1563     }
1564   "
1565 )
1566
1567 (define_insn_and_split "*arm_andsi3_insn"
1568   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1569         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1570                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1571   "TARGET_ARM"
1572   "@
1573    and%?\\t%0, %1, %2
1574    bic%?\\t%0, %1, #%B2
1575    #"
1576   "TARGET_ARM
1577    && GET_CODE (operands[2]) == CONST_INT
1578    && !(const_ok_for_arm (INTVAL (operands[2]))
1579         || const_ok_for_arm (~INTVAL (operands[2])))"
1580   [(clobber (const_int 0))]
1581   "
1582   arm_split_constant  (AND, SImode, curr_insn, 
1583                        INTVAL (operands[2]), operands[0], operands[1], 0);
1584   DONE;
1585   "
1586   [(set_attr "length" "4,4,16")
1587    (set_attr "predicable" "yes")]
1588 )
1589
1590 (define_insn "*thumb_andsi3_insn"
1591   [(set (match_operand:SI         0 "register_operand" "=l")
1592         (and:SI (match_operand:SI 1 "register_operand" "%0")
1593                 (match_operand:SI 2 "register_operand" "l")))]
1594   "TARGET_THUMB"
1595   "and\\t%0, %0, %2"
1596   [(set_attr "length" "2")]
1597 )
1598
1599 (define_insn "*andsi3_compare0"
1600   [(set (reg:CC_NOOV CC_REGNUM)
1601         (compare:CC_NOOV
1602          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1603                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1604          (const_int 0)))
1605    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1606         (and:SI (match_dup 1) (match_dup 2)))]
1607   "TARGET_ARM"
1608   "@
1609    and%?s\\t%0, %1, %2
1610    bic%?s\\t%0, %1, #%B2"
1611   [(set_attr "conds" "set")]
1612 )
1613
1614 (define_insn "*andsi3_compare0_scratch"
1615   [(set (reg:CC_NOOV CC_REGNUM)
1616         (compare:CC_NOOV
1617          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1618                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1619          (const_int 0)))
1620    (clobber (match_scratch:SI 2 "=X,r"))]
1621   "TARGET_ARM"
1622   "@
1623    tst%?\\t%0, %1
1624    bic%?s\\t%2, %0, #%B1"
1625   [(set_attr "conds" "set")]
1626 )
1627
1628 (define_insn "*zeroextractsi_compare0_scratch"
1629   [(set (reg:CC_NOOV CC_REGNUM)
1630         (compare:CC_NOOV (zero_extract:SI
1631                           (match_operand:SI 0 "s_register_operand" "r")
1632                           (match_operand 1 "const_int_operand" "n")
1633                           (match_operand 2 "const_int_operand" "n"))
1634                          (const_int 0)))]
1635   "TARGET_ARM
1636   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1637       && INTVAL (operands[1]) > 0 
1638       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1639       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1640   "*
1641   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1642                          << INTVAL (operands[2]));
1643   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1644   return \"\";
1645   "
1646   [(set_attr "conds" "set")]
1647 )
1648
1649 (define_insn "*ne_zeroextractsi"
1650   [(set (match_operand:SI 0 "s_register_operand" "=r")
1651         (ne:SI (zero_extract:SI
1652                 (match_operand:SI 1 "s_register_operand" "r")
1653                 (match_operand:SI 2 "const_int_operand" "n")
1654                 (match_operand:SI 3 "const_int_operand" "n"))
1655                (const_int 0)))
1656    (clobber (reg:CC CC_REGNUM))]
1657   "TARGET_ARM
1658    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1659        && INTVAL (operands[2]) > 0 
1660        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1661        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1662   "*
1663   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1664                          << INTVAL (operands[3]));
1665   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1666   return \"movne\\t%0, #1\";
1667   "
1668   [(set_attr "conds" "clob")
1669    (set_attr "length" "8")]
1670 )
1671
1672 (define_split
1673   [(set (match_operand:SI 0 "s_register_operand" "")
1674         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1675                          (match_operand:SI 2 "const_int_operand" "")
1676                          (match_operand:SI 3 "const_int_operand" "")))
1677    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1678   "TARGET_THUMB"
1679   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1680    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1681   "{
1682      HOST_WIDE_INT temp = INTVAL (operands[2]);
1683
1684      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1685      operands[3] = GEN_INT (32 - temp);
1686    }"
1687 )
1688
1689 (define_split
1690   [(set (match_operand:SI 0 "s_register_operand" "")
1691         (match_operator:SI 1 "shiftable_operator"
1692          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1693                            (match_operand:SI 3 "const_int_operand" "")
1694                            (match_operand:SI 4 "const_int_operand" ""))
1695           (match_operand:SI 5 "s_register_operand" "")]))
1696    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1697   "TARGET_ARM"
1698   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1699    (set (match_dup 0)
1700         (match_op_dup 1
1701          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1702           (match_dup 5)]))]
1703   "{
1704      HOST_WIDE_INT temp = INTVAL (operands[3]);
1705
1706      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1707      operands[4] = GEN_INT (32 - temp);
1708    }"
1709 )
1710   
1711 (define_split
1712   [(set (match_operand:SI 0 "s_register_operand" "")
1713         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1714                          (match_operand:SI 2 "const_int_operand" "")
1715                          (match_operand:SI 3 "const_int_operand" "")))]
1716   "TARGET_THUMB"
1717   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1718    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1719   "{
1720      HOST_WIDE_INT temp = INTVAL (operands[2]);
1721
1722      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1723      operands[3] = GEN_INT (32 - temp);
1724    }"
1725 )
1726
1727 (define_split
1728   [(set (match_operand:SI 0 "s_register_operand" "")
1729         (match_operator:SI 1 "shiftable_operator"
1730          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1731                            (match_operand:SI 3 "const_int_operand" "")
1732                            (match_operand:SI 4 "const_int_operand" ""))
1733           (match_operand:SI 5 "s_register_operand" "")]))
1734    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1735   "TARGET_ARM"
1736   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1737    (set (match_dup 0)
1738         (match_op_dup 1
1739          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1740           (match_dup 5)]))]
1741   "{
1742      HOST_WIDE_INT temp = INTVAL (operands[3]);
1743
1744      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1745      operands[4] = GEN_INT (32 - temp);
1746    }"
1747 )
1748   
1749 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1750 ;;; represented by the bitfield, then this will produce incorrect results.
1751 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1752 ;;; which have a real bit-field insert instruction, the truncation happens
1753 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1754 ;;; bit-field insert instruction, we would have to emit code here to truncate
1755 ;;; the value before we insert.  This loses some of the advantage of having
1756 ;;; this insv pattern, so this pattern needs to be reevalutated.
1757
1758 (define_expand "insv"
1759   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1760                          (match_operand:SI 1 "general_operand" "")
1761                          (match_operand:SI 2 "general_operand" ""))
1762         (match_operand:SI 3 "reg_or_int_operand" ""))]
1763   "TARGET_ARM"
1764   "
1765   {
1766     int start_bit = INTVAL (operands[2]);
1767     int width = INTVAL (operands[1]);
1768     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1769     rtx target, subtarget;
1770
1771     target = operands[0];
1772     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1773        subreg as the final target.  */
1774     if (GET_CODE (target) == SUBREG)
1775       {
1776         subtarget = gen_reg_rtx (SImode);
1777         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1778             < GET_MODE_SIZE (SImode))
1779           target = SUBREG_REG (target);
1780       }
1781     else
1782       subtarget = target;    
1783
1784     if (GET_CODE (operands[3]) == CONST_INT)
1785       {
1786         /* Since we are inserting a known constant, we may be able to
1787            reduce the number of bits that we have to clear so that
1788            the mask becomes simple.  */
1789         /* ??? This code does not check to see if the new mask is actually
1790            simpler.  It may not be.  */
1791         rtx op1 = gen_reg_rtx (SImode);
1792         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1793            start of this pattern.  */
1794         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1795         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1796
1797         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1798         emit_insn (gen_iorsi3 (subtarget, op1,
1799                                GEN_INT (op3_value << start_bit)));
1800       }
1801     else if (start_bit == 0
1802              && !(const_ok_for_arm (mask)
1803                   || const_ok_for_arm (~mask)))
1804       {
1805         /* A Trick, since we are setting the bottom bits in the word,
1806            we can shift operand[3] up, operand[0] down, OR them together
1807            and rotate the result back again.  This takes 3 insns, and
1808            the third might be mergeable into another op.  */
1809         /* The shift up copes with the possibility that operand[3] is
1810            wider than the bitfield.  */
1811         rtx op0 = gen_reg_rtx (SImode);
1812         rtx op1 = gen_reg_rtx (SImode);
1813
1814         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1815         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1816         emit_insn (gen_iorsi3  (op1, op1, op0));
1817         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1818       }
1819     else if ((width + start_bit == 32)
1820              && !(const_ok_for_arm (mask)
1821                   || const_ok_for_arm (~mask)))
1822       {
1823         /* Similar trick, but slightly less efficient.  */
1824
1825         rtx op0 = gen_reg_rtx (SImode);
1826         rtx op1 = gen_reg_rtx (SImode);
1827
1828         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1829         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1830         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1831         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1832       }
1833     else
1834       {
1835         rtx op0 = GEN_INT (mask);
1836         rtx op1 = gen_reg_rtx (SImode);
1837         rtx op2 = gen_reg_rtx (SImode);
1838
1839         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1840           {
1841             rtx tmp = gen_reg_rtx (SImode);
1842
1843             emit_insn (gen_movsi (tmp, op0));
1844             op0 = tmp;
1845           }
1846
1847         /* Mask out any bits in operand[3] that are not needed.  */
1848            emit_insn (gen_andsi3 (op1, operands[3], op0));
1849
1850         if (GET_CODE (op0) == CONST_INT
1851             && (const_ok_for_arm (mask << start_bit)
1852                 || const_ok_for_arm (~(mask << start_bit))))
1853           {
1854             op0 = GEN_INT (~(mask << start_bit));
1855             emit_insn (gen_andsi3 (op2, operands[0], op0));
1856           }
1857         else
1858           {
1859             if (GET_CODE (op0) == CONST_INT)
1860               {
1861                 rtx tmp = gen_reg_rtx (SImode);
1862
1863                 emit_insn (gen_movsi (tmp, op0));
1864                 op0 = tmp;
1865               }
1866
1867             if (start_bit != 0)
1868               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1869             
1870             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1871           }
1872
1873         if (start_bit != 0)
1874           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1875
1876         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1877       }
1878
1879     if (subtarget != target)
1880       {
1881         /* If TARGET is still a SUBREG, then it must be wider than a word,
1882            so we must be careful only to set the subword we were asked to.  */
1883         if (GET_CODE (target) == SUBREG)
1884           emit_move_insn (target, subtarget);
1885         else
1886           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1887       }
1888
1889     DONE;
1890   }"
1891 )
1892
1893 ; constants for op 2 will never be given to these patterns.
1894 (define_insn_and_split "*anddi_notdi_di"
1895   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1896         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1897                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1898   "TARGET_ARM"
1899   "#"
1900   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1901   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1902    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1903   "
1904   {
1905     operands[3] = gen_highpart (SImode, operands[0]);
1906     operands[0] = gen_lowpart (SImode, operands[0]);
1907     operands[4] = gen_highpart (SImode, operands[1]);
1908     operands[1] = gen_lowpart (SImode, operands[1]);
1909     operands[5] = gen_highpart (SImode, operands[2]);
1910     operands[2] = gen_lowpart (SImode, operands[2]);
1911   }"
1912   [(set_attr "length" "8")
1913    (set_attr "predicable" "yes")]
1914 )
1915   
1916 (define_insn_and_split "*anddi_notzesidi_di"
1917   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1918         (and:DI (not:DI (zero_extend:DI
1919                          (match_operand:SI 2 "s_register_operand" "r,r")))
1920                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1921   "TARGET_ARM"
1922   "@
1923    bic%?\\t%Q0, %Q1, %2
1924    #"
1925   ; (not (zero_extend ...)) allows us to just copy the high word from
1926   ; operand1 to operand0.
1927   "TARGET_ARM
1928    && reload_completed
1929    && operands[0] != operands[1]"
1930   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1931    (set (match_dup 3) (match_dup 4))]
1932   "
1933   {
1934     operands[3] = gen_highpart (SImode, operands[0]);
1935     operands[0] = gen_lowpart (SImode, operands[0]);
1936     operands[4] = gen_highpart (SImode, operands[1]);
1937     operands[1] = gen_lowpart (SImode, operands[1]);
1938   }"
1939   [(set_attr "length" "4,8")
1940    (set_attr "predicable" "yes")]
1941 )
1942   
1943 (define_insn_and_split "*anddi_notsesidi_di"
1944   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1945         (and:DI (not:DI (sign_extend:DI
1946                          (match_operand:SI 2 "s_register_operand" "r,r")))
1947                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1948   "TARGET_ARM"
1949   "#"
1950   "TARGET_ARM && reload_completed"
1951   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1952    (set (match_dup 3) (and:SI (not:SI
1953                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
1954                                (match_dup 4)))]
1955   "
1956   {
1957     operands[3] = gen_highpart (SImode, operands[0]);
1958     operands[0] = gen_lowpart (SImode, operands[0]);
1959     operands[4] = gen_highpart (SImode, operands[1]);
1960     operands[1] = gen_lowpart (SImode, operands[1]);
1961   }"
1962   [(set_attr "length" "8")
1963    (set_attr "predicable" "yes")]
1964 )
1965   
1966 (define_insn "andsi_notsi_si"
1967   [(set (match_operand:SI 0 "s_register_operand" "=r")
1968         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1969                 (match_operand:SI 1 "s_register_operand" "r")))]
1970   "TARGET_ARM"
1971   "bic%?\\t%0, %1, %2"
1972   [(set_attr "predicable" "yes")]
1973 )
1974
1975 (define_insn "bicsi3"
1976   [(set (match_operand:SI                 0 "register_operand" "=l")
1977         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1978                 (match_operand:SI         2 "register_operand" "0")))]
1979   "TARGET_THUMB"
1980   "bic\\t%0, %0, %1"
1981   [(set_attr "length" "2")]
1982 )
1983
1984 (define_insn "andsi_not_shiftsi_si"
1985   [(set (match_operand:SI 0 "s_register_operand" "=r")
1986         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1987                          [(match_operand:SI 2 "s_register_operand" "r")
1988                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1989                 (match_operand:SI 1 "s_register_operand" "r")))]
1990   "TARGET_ARM"
1991   "bic%?\\t%0, %1, %2%S4"
1992   [(set_attr "predicable" "yes")
1993    (set_attr "shift" "2")
1994    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
1995                       (const_string "alu_shift")
1996                       (const_string "alu_shift_reg")))]
1997 )
1998
1999 (define_insn "*andsi_notsi_si_compare0"
2000   [(set (reg:CC_NOOV CC_REGNUM)
2001         (compare:CC_NOOV
2002          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2003                  (match_operand:SI 1 "s_register_operand" "r"))
2004          (const_int 0)))
2005    (set (match_operand:SI 0 "s_register_operand" "=r")
2006         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2007   "TARGET_ARM"
2008   "bic%?s\\t%0, %1, %2"
2009   [(set_attr "conds" "set")]
2010 )
2011
2012 (define_insn "*andsi_notsi_si_compare0_scratch"
2013   [(set (reg:CC_NOOV CC_REGNUM)
2014         (compare:CC_NOOV
2015          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2016                  (match_operand:SI 1 "s_register_operand" "r"))
2017          (const_int 0)))
2018    (clobber (match_scratch:SI 0 "=r"))]
2019   "TARGET_ARM"
2020   "bic%?s\\t%0, %1, %2"
2021   [(set_attr "conds" "set")]
2022 )
2023
2024 (define_insn "iordi3"
2025   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2026         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2027                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2028   "TARGET_ARM && ! TARGET_IWMMXT"
2029   "#"
2030   [(set_attr "length" "8")
2031    (set_attr "predicable" "yes")]
2032 )
2033
2034 (define_insn "*iordi_zesidi_di"
2035   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2036         (ior:DI (zero_extend:DI
2037                  (match_operand:SI 2 "s_register_operand" "r,r"))
2038                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2039   "TARGET_ARM"
2040   "@
2041    orr%?\\t%Q0, %Q1, %2
2042    #"
2043   [(set_attr "length" "4,8")
2044    (set_attr "predicable" "yes")]
2045 )
2046
2047 (define_insn "*iordi_sesidi_di"
2048   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2049         (ior:DI (sign_extend:DI
2050                  (match_operand:SI 2 "s_register_operand" "r,r"))
2051                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2052   "TARGET_ARM"
2053   "#"
2054   [(set_attr "length" "8")
2055    (set_attr "predicable" "yes")]
2056 )
2057
2058 (define_expand "iorsi3"
2059   [(set (match_operand:SI         0 "s_register_operand" "")
2060         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2061                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2062   "TARGET_EITHER"
2063   "
2064   if (GET_CODE (operands[2]) == CONST_INT)
2065     {
2066       if (TARGET_ARM)
2067         {
2068           arm_split_constant (IOR, SImode, NULL_RTX,
2069                               INTVAL (operands[2]), operands[0], operands[1],
2070                               (no_new_pseudos
2071                               ? 0 : preserve_subexpressions_p ()));
2072           DONE;
2073         }
2074       else /* TARGET_THUMB */
2075         operands [2] = force_reg (SImode, operands [2]);
2076     }
2077   "
2078 )
2079
2080 (define_insn_and_split "*arm_iorsi3"
2081   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2082         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2083                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2084   "TARGET_ARM"
2085   "@
2086    orr%?\\t%0, %1, %2
2087    #"
2088   "TARGET_ARM
2089    && GET_CODE (operands[2]) == CONST_INT
2090    && !const_ok_for_arm (INTVAL (operands[2]))"
2091   [(clobber (const_int 0))]
2092   "
2093   arm_split_constant (IOR, SImode, curr_insn, 
2094                       INTVAL (operands[2]), operands[0], operands[1], 0);
2095   DONE;
2096   "
2097   [(set_attr "length" "4,16")
2098    (set_attr "predicable" "yes")]
2099 )
2100
2101 (define_insn "*thumb_iorsi3"
2102   [(set (match_operand:SI         0 "register_operand" "=l")
2103         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2104                 (match_operand:SI 2 "register_operand" "l")))]
2105   "TARGET_THUMB"
2106   "orr\\t%0, %0, %2"
2107   [(set_attr "length" "2")]
2108 )
2109
2110 (define_peephole2
2111   [(match_scratch:SI 3 "r")
2112    (set (match_operand:SI 0 "arm_general_register_operand" "")
2113         (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
2114                 (match_operand:SI 2 "const_int_operand" "")))]
2115   "TARGET_ARM
2116    && !const_ok_for_arm (INTVAL (operands[2]))
2117    && const_ok_for_arm (~INTVAL (operands[2]))"
2118   [(set (match_dup 3) (match_dup 2))
2119    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2120   ""
2121 )
2122
2123 (define_insn "*iorsi3_compare0"
2124   [(set (reg:CC_NOOV CC_REGNUM)
2125         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2126                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2127                          (const_int 0)))
2128    (set (match_operand:SI 0 "s_register_operand" "=r")
2129         (ior:SI (match_dup 1) (match_dup 2)))]
2130   "TARGET_ARM"
2131   "orr%?s\\t%0, %1, %2"
2132   [(set_attr "conds" "set")]
2133 )
2134
2135 (define_insn "*iorsi3_compare0_scratch"
2136   [(set (reg:CC_NOOV CC_REGNUM)
2137         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2138                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2139                          (const_int 0)))
2140    (clobber (match_scratch:SI 0 "=r"))]
2141   "TARGET_ARM"
2142   "orr%?s\\t%0, %1, %2"
2143   [(set_attr "conds" "set")]
2144 )
2145
2146 (define_insn "xordi3"
2147   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2148         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2149                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2150   "TARGET_ARM && !TARGET_IWMMXT"
2151   "#"
2152   [(set_attr "length" "8")
2153    (set_attr "predicable" "yes")]
2154 )
2155
2156 (define_insn "*xordi_zesidi_di"
2157   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2158         (xor:DI (zero_extend:DI
2159                  (match_operand:SI 2 "s_register_operand" "r,r"))
2160                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2161   "TARGET_ARM"
2162   "@
2163    eor%?\\t%Q0, %Q1, %2
2164    #"
2165   [(set_attr "length" "4,8")
2166    (set_attr "predicable" "yes")]
2167 )
2168
2169 (define_insn "*xordi_sesidi_di"
2170   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2171         (xor:DI (sign_extend:DI
2172                  (match_operand:SI 2 "s_register_operand" "r,r"))
2173                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2174   "TARGET_ARM"
2175   "#"
2176   [(set_attr "length" "8")
2177    (set_attr "predicable" "yes")]
2178 )
2179
2180 (define_expand "xorsi3"
2181   [(set (match_operand:SI         0 "s_register_operand" "")
2182         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2183                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2184   "TARGET_EITHER"
2185   "if (TARGET_THUMB)
2186      if (GET_CODE (operands[2]) == CONST_INT)
2187        operands[2] = force_reg (SImode, operands[2]);
2188   "
2189 )
2190
2191 (define_insn "*arm_xorsi3"
2192   [(set (match_operand:SI         0 "s_register_operand" "=r")
2193         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2194                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2195   "TARGET_ARM"
2196   "eor%?\\t%0, %1, %2"
2197   [(set_attr "predicable" "yes")]
2198 )
2199
2200 (define_insn "*thumb_xorsi3"
2201   [(set (match_operand:SI         0 "register_operand" "=l")
2202         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2203                 (match_operand:SI 2 "register_operand" "l")))]
2204   "TARGET_THUMB"
2205   "eor\\t%0, %0, %2"
2206   [(set_attr "length" "2")]
2207 )
2208
2209 (define_insn "*xorsi3_compare0"
2210   [(set (reg:CC_NOOV CC_REGNUM)
2211         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2212                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2213                          (const_int 0)))
2214    (set (match_operand:SI 0 "s_register_operand" "=r")
2215         (xor:SI (match_dup 1) (match_dup 2)))]
2216   "TARGET_ARM"
2217   "eor%?s\\t%0, %1, %2"
2218   [(set_attr "conds" "set")]
2219 )
2220
2221 (define_insn "*xorsi3_compare0_scratch"
2222   [(set (reg:CC_NOOV CC_REGNUM)
2223         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2224                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2225                          (const_int 0)))]
2226   "TARGET_ARM"
2227   "teq%?\\t%0, %1"
2228   [(set_attr "conds" "set")]
2229 )
2230
2231 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2232 ; (NOT D) we can sometimes merge the final NOT into one of the following
2233 ; insns.
2234
2235 (define_split
2236   [(set (match_operand:SI 0 "s_register_operand" "")
2237         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2238                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2239                 (match_operand:SI 3 "arm_rhs_operand" "")))
2240    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2241   "TARGET_ARM"
2242   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2243                               (not:SI (match_dup 3))))
2244    (set (match_dup 0) (not:SI (match_dup 4)))]
2245   ""
2246 )
2247
2248 (define_insn "*andsi_iorsi3_notsi"
2249   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2250         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2251                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2252                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2253   "TARGET_ARM"
2254   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2255   [(set_attr "length" "8")
2256    (set_attr "predicable" "yes")]
2257 )
2258
2259 (define_split
2260   [(set (match_operand:SI 0 "s_register_operand" "")
2261         (match_operator:SI 1 "logical_binary_operator"
2262          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2263                            (match_operand:SI 3 "const_int_operand" "")
2264                            (match_operand:SI 4 "const_int_operand" ""))
2265           (match_operator:SI 9 "logical_binary_operator"
2266            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2267                          (match_operand:SI 6 "const_int_operand" ""))
2268             (match_operand:SI 7 "s_register_operand" "")])]))
2269    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2270   "TARGET_ARM
2271    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2272    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2273   [(set (match_dup 8)
2274         (match_op_dup 1
2275          [(ashift:SI (match_dup 2) (match_dup 4))
2276           (match_dup 5)]))
2277    (set (match_dup 0)
2278         (match_op_dup 1
2279          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2280           (match_dup 7)]))]
2281   "
2282   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2283 ")
2284
2285 (define_split
2286   [(set (match_operand:SI 0 "s_register_operand" "")
2287         (match_operator:SI 1 "logical_binary_operator"
2288          [(match_operator:SI 9 "logical_binary_operator"
2289            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2290                          (match_operand:SI 6 "const_int_operand" ""))
2291             (match_operand:SI 7 "s_register_operand" "")])
2292           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2293                            (match_operand:SI 3 "const_int_operand" "")
2294                            (match_operand:SI 4 "const_int_operand" ""))]))
2295    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2296   "TARGET_ARM
2297    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2298    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2299   [(set (match_dup 8)
2300         (match_op_dup 1
2301          [(ashift:SI (match_dup 2) (match_dup 4))
2302           (match_dup 5)]))
2303    (set (match_dup 0)
2304         (match_op_dup 1
2305          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2306           (match_dup 7)]))]
2307   "
2308   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2309 ")
2310
2311 (define_split
2312   [(set (match_operand:SI 0 "s_register_operand" "")
2313         (match_operator:SI 1 "logical_binary_operator"
2314          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2315                            (match_operand:SI 3 "const_int_operand" "")
2316                            (match_operand:SI 4 "const_int_operand" ""))
2317           (match_operator:SI 9 "logical_binary_operator"
2318            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2319                          (match_operand:SI 6 "const_int_operand" ""))
2320             (match_operand:SI 7 "s_register_operand" "")])]))
2321    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2322   "TARGET_ARM
2323    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2324    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2325   [(set (match_dup 8)
2326         (match_op_dup 1
2327          [(ashift:SI (match_dup 2) (match_dup 4))
2328           (match_dup 5)]))
2329    (set (match_dup 0)
2330         (match_op_dup 1
2331          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2332           (match_dup 7)]))]
2333   "
2334   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2335 ")
2336
2337 (define_split
2338   [(set (match_operand:SI 0 "s_register_operand" "")
2339         (match_operator:SI 1 "logical_binary_operator"
2340          [(match_operator:SI 9 "logical_binary_operator"
2341            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2342                          (match_operand:SI 6 "const_int_operand" ""))
2343             (match_operand:SI 7 "s_register_operand" "")])
2344           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2345                            (match_operand:SI 3 "const_int_operand" "")
2346                            (match_operand:SI 4 "const_int_operand" ""))]))
2347    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2348   "TARGET_ARM
2349    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2350    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2351   [(set (match_dup 8)
2352         (match_op_dup 1
2353          [(ashift:SI (match_dup 2) (match_dup 4))
2354           (match_dup 5)]))
2355    (set (match_dup 0)
2356         (match_op_dup 1
2357          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2358           (match_dup 7)]))]
2359   "
2360   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2361 ")
2362 \f
2363
2364 ;; Minimum and maximum insns
2365
2366 (define_insn "smaxsi3"
2367   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2368         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2369                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2370    (clobber (reg:CC CC_REGNUM))]
2371   "TARGET_ARM"
2372   "@
2373    cmp\\t%1, %2\;movlt\\t%0, %2
2374    cmp\\t%1, %2\;movge\\t%0, %1
2375    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2376   [(set_attr "conds" "clob")
2377    (set_attr "length" "8,8,12")]
2378 )
2379
2380 (define_insn "sminsi3"
2381   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2382         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2383                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2384    (clobber (reg:CC CC_REGNUM))]
2385   "TARGET_ARM"
2386   "@
2387    cmp\\t%1, %2\;movge\\t%0, %2
2388    cmp\\t%1, %2\;movlt\\t%0, %1
2389    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2390   [(set_attr "conds" "clob")
2391    (set_attr "length" "8,8,12")]
2392 )
2393
2394 (define_insn "umaxsi3"
2395   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2396         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2397                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2398    (clobber (reg:CC CC_REGNUM))]
2399   "TARGET_ARM"
2400   "@
2401    cmp\\t%1, %2\;movcc\\t%0, %2
2402    cmp\\t%1, %2\;movcs\\t%0, %1
2403    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2404   [(set_attr "conds" "clob")
2405    (set_attr "length" "8,8,12")]
2406 )
2407
2408 (define_insn "uminsi3"
2409   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2410         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2411                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2412    (clobber (reg:CC CC_REGNUM))]
2413   "TARGET_ARM"
2414   "@
2415    cmp\\t%1, %2\;movcs\\t%0, %2
2416    cmp\\t%1, %2\;movcc\\t%0, %1
2417    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2418   [(set_attr "conds" "clob")
2419    (set_attr "length" "8,8,12")]
2420 )
2421
2422 (define_insn "*store_minmaxsi"
2423   [(set (match_operand:SI 0 "memory_operand" "=m")
2424         (match_operator:SI 3 "minmax_operator"
2425          [(match_operand:SI 1 "s_register_operand" "r")
2426           (match_operand:SI 2 "s_register_operand" "r")]))
2427    (clobber (reg:CC CC_REGNUM))]
2428   "TARGET_ARM"
2429   "*
2430   operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
2431                                 operands[1], operands[2]);
2432   output_asm_insn (\"cmp\\t%1, %2\", operands);
2433   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2434   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2435   return \"\";
2436   "
2437   [(set_attr "conds" "clob")
2438    (set_attr "length" "12")
2439    (set_attr "type" "store1")]
2440 )
2441
2442 ; Reject the frame pointer in operand[1], since reloading this after
2443 ; it has been eliminated can cause carnage.
2444 (define_insn "*minmax_arithsi"
2445   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2446         (match_operator:SI 4 "shiftable_operator"
2447          [(match_operator:SI 5 "minmax_operator"
2448            [(match_operand:SI 2 "s_register_operand" "r,r")
2449             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2450           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2451    (clobber (reg:CC CC_REGNUM))]
2452   "TARGET_ARM
2453    && (GET_CODE (operands[1]) != REG
2454        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2455            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2456   "*
2457   {
2458     enum rtx_code code = GET_CODE (operands[4]);
2459
2460     operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
2461                                   operands[2], operands[3]);
2462     output_asm_insn (\"cmp\\t%2, %3\", operands);
2463     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2464     if (which_alternative != 0 || operands[3] != const0_rtx
2465         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2466       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2467     return \"\";
2468   }"
2469   [(set_attr "conds" "clob")
2470    (set_attr "length" "12")]
2471 )
2472
2473 \f
2474 ;; Shift and rotation insns
2475
2476 (define_expand "ashldi3"
2477   [(set (match_operand:DI            0 "s_register_operand" "")
2478         (ashift:DI (match_operand:DI 1 "s_register_operand" "")
2479                    (match_operand:SI 2 "reg_or_int_operand" "")))]
2480   "TARGET_ARM"
2481   "
2482   if (GET_CODE (operands[2]) == CONST_INT)
2483     {
2484       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2485         {
2486           emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
2487           DONE;
2488         }
2489         /* Ideally we shouldn't fail here if we could know that operands[1] 
2490            ends up already living in an iwmmxt register. Otherwise it's
2491            cheaper to have the alternate code being generated than moving
2492            values to iwmmxt regs and back.  */
2493         FAIL;
2494     }
2495   else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
2496     FAIL;
2497   "
2498 )
2499
2500 (define_insn "arm_ashldi3_1bit"
2501   [(set (match_operand:DI            0 "s_register_operand" "=&r,r")
2502         (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2503                    (const_int 1)))
2504    (clobber (reg:CC CC_REGNUM))]
2505   "TARGET_ARM"
2506   "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
2507   [(set_attr "conds" "clob")
2508    (set_attr "length" "8")]
2509 )
2510
2511 (define_expand "ashlsi3"
2512   [(set (match_operand:SI            0 "s_register_operand" "")
2513         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2514                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2515   "TARGET_EITHER"
2516   "
2517   if (GET_CODE (operands[2]) == CONST_INT
2518       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2519     {
2520       emit_insn (gen_movsi (operands[0], const0_rtx));
2521       DONE;
2522     }
2523   "
2524 )
2525
2526 (define_insn "*thumb_ashlsi3"
2527   [(set (match_operand:SI            0 "register_operand" "=l,l")
2528         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2529                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2530   "TARGET_THUMB"
2531   "lsl\\t%0, %1, %2"
2532   [(set_attr "length" "2")]
2533 )
2534
2535 (define_expand "ashrdi3"
2536   [(set (match_operand:DI              0 "s_register_operand" "")
2537         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2538                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2539   "TARGET_ARM"
2540   "
2541   if (GET_CODE (operands[2]) == CONST_INT)
2542     {
2543       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2544         {
2545           emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
2546           DONE;
2547         }
2548         /* Ideally we shouldn't fail here if we could know that operands[1] 
2549            ends up already living in an iwmmxt register. Otherwise it's
2550            cheaper to have the alternate code being generated than moving
2551            values to iwmmxt regs and back.  */
2552         FAIL;
2553     }
2554   else if (!TARGET_REALLY_IWMMXT)
2555     FAIL;
2556   "
2557 )
2558
2559 (define_insn "arm_ashrdi3_1bit"
2560   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2561         (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2562                      (const_int 1)))
2563    (clobber (reg:CC CC_REGNUM))]
2564   "TARGET_ARM"
2565   "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
2566   [(set_attr "conds" "clob")
2567    (set_attr "length" "8")]
2568 )
2569
2570 (define_expand "ashrsi3"
2571   [(set (match_operand:SI              0 "s_register_operand" "")
2572         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2573                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2574   "TARGET_EITHER"
2575   "
2576   if (GET_CODE (operands[2]) == CONST_INT
2577       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2578     operands[2] = GEN_INT (31);
2579   "
2580 )
2581
2582 (define_insn "*thumb_ashrsi3"
2583   [(set (match_operand:SI              0 "register_operand" "=l,l")
2584         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2585                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2586   "TARGET_THUMB"
2587   "asr\\t%0, %1, %2"
2588   [(set_attr "length" "2")]
2589 )
2590
2591 (define_expand "lshrdi3"
2592   [(set (match_operand:DI              0 "s_register_operand" "")
2593         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
2594                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2595   "TARGET_ARM"
2596   "
2597   if (GET_CODE (operands[2]) == CONST_INT)
2598     {
2599       if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
2600         {
2601           emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
2602           DONE;
2603         }
2604         /* Ideally we shouldn't fail here if we could know that operands[1] 
2605            ends up already living in an iwmmxt register. Otherwise it's
2606            cheaper to have the alternate code being generated than moving
2607            values to iwmmxt regs and back.  */
2608         FAIL;
2609     }
2610   else if (!TARGET_REALLY_IWMMXT)
2611     FAIL;
2612   "
2613 )
2614
2615 (define_insn "arm_lshrdi3_1bit"
2616   [(set (match_operand:DI              0 "s_register_operand" "=&r,r")
2617         (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
2618                      (const_int 1)))
2619    (clobber (reg:CC CC_REGNUM))]
2620   "TARGET_ARM"
2621   "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
2622   [(set_attr "conds" "clob")
2623    (set_attr "length" "8")]
2624 )
2625
2626 (define_expand "lshrsi3"
2627   [(set (match_operand:SI              0 "s_register_operand" "")
2628         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2629                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2630   "TARGET_EITHER"
2631   "
2632   if (GET_CODE (operands[2]) == CONST_INT
2633       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2634     {
2635       emit_insn (gen_movsi (operands[0], const0_rtx));
2636       DONE;
2637     }
2638   "
2639 )
2640
2641 (define_insn "*thumb_lshrsi3"
2642   [(set (match_operand:SI              0 "register_operand" "=l,l")
2643         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2644                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2645   "TARGET_THUMB"
2646   "lsr\\t%0, %1, %2"
2647   [(set_attr "length" "2")]
2648 )
2649
2650 (define_expand "rotlsi3"
2651   [(set (match_operand:SI              0 "s_register_operand" "")
2652         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2653                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2654   "TARGET_ARM"
2655   "
2656   if (GET_CODE (operands[2]) == CONST_INT)
2657     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2658   else
2659     {
2660       rtx reg = gen_reg_rtx (SImode);
2661       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2662       operands[2] = reg;
2663     }
2664   "
2665 )
2666
2667 (define_expand "rotrsi3"
2668   [(set (match_operand:SI              0 "s_register_operand" "")
2669         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2670                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2671   "TARGET_EITHER"
2672   "
2673   if (TARGET_ARM)
2674     {
2675       if (GET_CODE (operands[2]) == CONST_INT
2676           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2677         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2678     }
2679   else /* TARGET_THUMB */
2680     {
2681       if (GET_CODE (operands [2]) == CONST_INT)
2682         operands [2] = force_reg (SImode, operands[2]);
2683     }
2684   "
2685 )
2686
2687 (define_insn "*thumb_rotrsi3"
2688   [(set (match_operand:SI              0 "register_operand" "=l")
2689         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2690                      (match_operand:SI 2 "register_operand" "l")))]
2691   "TARGET_THUMB"
2692   "ror\\t%0, %0, %2"
2693   [(set_attr "length" "2")]
2694 )
2695
2696 (define_insn "*arm_shiftsi3"
2697   [(set (match_operand:SI   0 "s_register_operand" "=r")
2698         (match_operator:SI  3 "shift_operator"
2699          [(match_operand:SI 1 "s_register_operand"  "r")
2700           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2701   "TARGET_ARM"
2702   "mov%?\\t%0, %1%S3"
2703   [(set_attr "predicable" "yes")
2704    (set_attr "shift" "1")
2705    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2706                       (const_string "alu_shift")
2707                       (const_string "alu_shift_reg")))]
2708 )
2709
2710 (define_insn "*shiftsi3_compare0"
2711   [(set (reg:CC_NOOV CC_REGNUM)
2712         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2713                           [(match_operand:SI 1 "s_register_operand" "r")
2714                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2715                          (const_int 0)))
2716    (set (match_operand:SI 0 "s_register_operand" "=r")
2717         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2718   "TARGET_ARM"
2719   "mov%?s\\t%0, %1%S3"
2720   [(set_attr "conds" "set")
2721    (set_attr "shift" "1")
2722    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2723                       (const_string "alu_shift")
2724                       (const_string "alu_shift_reg")))]
2725 )
2726
2727 (define_insn "*shiftsi3_compare0_scratch"
2728   [(set (reg:CC_NOOV CC_REGNUM)
2729         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2730                           [(match_operand:SI 1 "s_register_operand" "r")
2731                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2732                          (const_int 0)))
2733    (clobber (match_scratch:SI 0 "=r"))]
2734   "TARGET_ARM"
2735   "mov%?s\\t%0, %1%S3"
2736   [(set_attr "conds" "set")
2737    (set_attr "shift" "1")]
2738 )
2739
2740 (define_insn "*notsi_shiftsi"
2741   [(set (match_operand:SI 0 "s_register_operand" "=r")
2742         (not:SI (match_operator:SI 3 "shift_operator"
2743                  [(match_operand:SI 1 "s_register_operand" "r")
2744                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2745   "TARGET_ARM"
2746   "mvn%?\\t%0, %1%S3"
2747   [(set_attr "predicable" "yes")
2748    (set_attr "shift" "1")
2749    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2750                       (const_string "alu_shift")
2751                       (const_string "alu_shift_reg")))]
2752 )
2753
2754 (define_insn "*notsi_shiftsi_compare0"
2755   [(set (reg:CC_NOOV CC_REGNUM)
2756         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2757                           [(match_operand:SI 1 "s_register_operand" "r")
2758                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2759                          (const_int 0)))
2760    (set (match_operand:SI 0 "s_register_operand" "=r")
2761         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2762   "TARGET_ARM"
2763   "mvn%?s\\t%0, %1%S3"
2764   [(set_attr "conds" "set")
2765    (set_attr "shift" "1")
2766    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2767                       (const_string "alu_shift")
2768                       (const_string "alu_shift_reg")))]
2769 )
2770
2771 (define_insn "*not_shiftsi_compare0_scratch"
2772   [(set (reg:CC_NOOV CC_REGNUM)
2773         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2774                           [(match_operand:SI 1 "s_register_operand" "r")
2775                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2776                          (const_int 0)))
2777    (clobber (match_scratch:SI 0 "=r"))]
2778   "TARGET_ARM"
2779   "mvn%?s\\t%0, %1%S3"
2780   [(set_attr "conds" "set")
2781    (set_attr "shift" "1")
2782    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
2783                       (const_string "alu_shift")
2784                       (const_string "alu_shift_reg")))]
2785 )
2786
2787 ;; We don't really have extzv, but defining this using shifts helps
2788 ;; to reduce register pressure later on.
2789
2790 (define_expand "extzv"
2791   [(set (match_dup 4)
2792         (ashift:SI (match_operand:SI   1 "register_operand" "")
2793                    (match_operand:SI   2 "const_int_operand" "")))
2794    (set (match_operand:SI              0 "register_operand" "")
2795         (lshiftrt:SI (match_dup 4)
2796                      (match_operand:SI 3 "const_int_operand" "")))]
2797   "TARGET_THUMB"
2798   "
2799   {
2800     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2801     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2802     
2803     operands[3] = GEN_INT (rshift);
2804     
2805     if (lshift == 0)
2806       {
2807         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2808         DONE;
2809       }
2810       
2811     operands[2] = GEN_INT (lshift);
2812     operands[4] = gen_reg_rtx (SImode);
2813   }"
2814 )
2815
2816 \f
2817 ;; Unary arithmetic insns
2818
2819 (define_expand "negdi2"
2820  [(parallel
2821    [(set (match_operand:DI          0 "s_register_operand" "")
2822           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2823     (clobber (reg:CC CC_REGNUM))])]
2824   "TARGET_EITHER"
2825   "
2826   if (TARGET_THUMB)
2827     {
2828       if (GET_CODE (operands[1]) != REG)
2829         operands[1] = force_reg (SImode, operands[1]);
2830      }
2831   "
2832 )
2833
2834 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2835 ;; The second alternative is to allow the common case of a *full* overlap.
2836 (define_insn "*arm_negdi2"
2837   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2838         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2839    (clobber (reg:CC CC_REGNUM))]
2840   "TARGET_ARM"
2841   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2842   [(set_attr "conds" "clob")
2843    (set_attr "length" "8")]
2844 )
2845
2846 (define_insn "*thumb_negdi2"
2847   [(set (match_operand:DI         0 "register_operand" "=&l")
2848         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2849    (clobber (reg:CC CC_REGNUM))]
2850   "TARGET_THUMB"
2851   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2852   [(set_attr "length" "6")]
2853 )
2854
2855 (define_expand "negsi2"
2856   [(set (match_operand:SI         0 "s_register_operand" "")
2857         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2858   "TARGET_EITHER"
2859   ""
2860 )
2861
2862 (define_insn "*arm_negsi2"
2863   [(set (match_operand:SI         0 "s_register_operand" "=r")
2864         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2865   "TARGET_ARM"
2866   "rsb%?\\t%0, %1, #0"
2867   [(set_attr "predicable" "yes")]
2868 )
2869
2870 (define_insn "*thumb_negsi2"
2871   [(set (match_operand:SI         0 "register_operand" "=l")
2872         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2873   "TARGET_THUMB"
2874   "neg\\t%0, %1"
2875   [(set_attr "length" "2")]
2876 )
2877
2878 (define_expand "negsf2"
2879   [(set (match_operand:SF         0 "s_register_operand" "")
2880         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2881   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2882   ""
2883 )
2884
2885 (define_expand "negdf2"
2886   [(set (match_operand:DF         0 "s_register_operand" "")
2887         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2888   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
2889   "")
2890
2891 ;; abssi2 doesn't really clobber the condition codes if a different register
2892 ;; is being set.  To keep things simple, assume during rtl manipulations that
2893 ;; it does, but tell the final scan operator the truth.  Similarly for
2894 ;; (neg (abs...))
2895
2896 (define_expand "abssi2"
2897   [(parallel
2898     [(set (match_operand:SI         0 "s_register_operand" "")
2899           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2900      (clobber (reg:CC CC_REGNUM))])]
2901   "TARGET_ARM"
2902   "")
2903
2904 (define_insn "*arm_abssi2"
2905   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2906         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2907    (clobber (reg:CC CC_REGNUM))]
2908   "TARGET_ARM"
2909   "@
2910    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2911    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2912   [(set_attr "conds" "clob,*")
2913    (set_attr "shift" "1")
2914    ;; predicable can't be set based on the variant, so left as no
2915    (set_attr "length" "8")]
2916 )
2917
2918 (define_insn "*neg_abssi2"
2919   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2920         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2921    (clobber (reg:CC CC_REGNUM))]
2922   "TARGET_ARM"
2923   "@
2924    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2925    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2926   [(set_attr "conds" "clob,*")
2927    (set_attr "shift" "1")
2928    ;; predicable can't be set based on the variant, so left as no
2929    (set_attr "length" "8")]
2930 )
2931
2932 (define_expand "abssf2"
2933   [(set (match_operand:SF         0 "s_register_operand" "")
2934         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2935   "TARGET_ARM && TARGET_HARD_FLOAT"
2936   "")
2937
2938 (define_expand "absdf2"
2939   [(set (match_operand:DF         0 "s_register_operand" "")
2940         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2941   "TARGET_ARM && TARGET_HARD_FLOAT"
2942   "")
2943
2944 (define_expand "sqrtsf2"
2945   [(set (match_operand:SF 0 "s_register_operand" "")
2946         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2947   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2948   "")
2949
2950 (define_expand "sqrtdf2"
2951   [(set (match_operand:DF 0 "s_register_operand" "")
2952         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2953   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
2954   "")
2955
2956 (define_insn_and_split "one_cmpldi2"
2957   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2958         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2959   "TARGET_ARM"
2960   "#"
2961   "TARGET_ARM && reload_completed"
2962   [(set (match_dup 0) (not:SI (match_dup 1)))
2963    (set (match_dup 2) (not:SI (match_dup 3)))]
2964   "
2965   {
2966     operands[2] = gen_highpart (SImode, operands[0]);
2967     operands[0] = gen_lowpart (SImode, operands[0]);
2968     operands[3] = gen_highpart (SImode, operands[1]);
2969     operands[1] = gen_lowpart (SImode, operands[1]);
2970   }"
2971   [(set_attr "length" "8")
2972    (set_attr "predicable" "yes")]
2973 )
2974
2975 (define_expand "one_cmplsi2"
2976   [(set (match_operand:SI         0 "s_register_operand" "")
2977         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2978   "TARGET_EITHER"
2979   ""
2980 )
2981
2982 (define_insn "*arm_one_cmplsi2"
2983   [(set (match_operand:SI         0 "s_register_operand" "=r")
2984         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2985   "TARGET_ARM"
2986   "mvn%?\\t%0, %1"
2987   [(set_attr "predicable" "yes")]
2988 )
2989
2990 (define_insn "*thumb_one_cmplsi2"
2991   [(set (match_operand:SI         0 "register_operand" "=l")
2992         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
2993   "TARGET_THUMB"
2994   "mvn\\t%0, %1"
2995   [(set_attr "length" "2")]
2996 )
2997
2998 (define_insn "*notsi_compare0"
2999   [(set (reg:CC_NOOV CC_REGNUM)
3000         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3001                          (const_int 0)))
3002    (set (match_operand:SI 0 "s_register_operand" "=r")
3003         (not:SI (match_dup 1)))]
3004   "TARGET_ARM"
3005   "mvn%?s\\t%0, %1"
3006   [(set_attr "conds" "set")]
3007 )
3008
3009 (define_insn "*notsi_compare0_scratch"
3010   [(set (reg:CC_NOOV CC_REGNUM)
3011         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3012                          (const_int 0)))
3013    (clobber (match_scratch:SI 0 "=r"))]
3014   "TARGET_ARM"
3015   "mvn%?s\\t%0, %1"
3016   [(set_attr "conds" "set")]
3017 )
3018 \f
3019 ;; Fixed <--> Floating conversion insns
3020
3021 (define_expand "floatsisf2"
3022   [(set (match_operand:SF           0 "s_register_operand" "")
3023         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
3024   "TARGET_ARM && TARGET_HARD_FLOAT"
3025   "
3026   if (TARGET_MAVERICK)
3027     {
3028       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
3029       DONE;
3030     }
3031 ")
3032
3033 (define_expand "floatsidf2"
3034   [(set (match_operand:DF           0 "s_register_operand" "")
3035         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
3036   "TARGET_ARM && TARGET_HARD_FLOAT"
3037   "
3038   if (TARGET_MAVERICK)
3039     {
3040       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3041       DONE;
3042     }
3043 ")
3044
3045 (define_expand "fix_truncsfsi2"
3046   [(set (match_operand:SI         0 "s_register_operand" "")
3047         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3048   "TARGET_ARM && TARGET_HARD_FLOAT"
3049   "
3050   if (TARGET_MAVERICK)
3051     {
3052       if (!cirrus_fp_register (operands[0], SImode))
3053         operands[0] = force_reg (SImode, operands[0]);
3054       if (!cirrus_fp_register (operands[1], SFmode))
3055         operands[1] = force_reg (SFmode, operands[0]);
3056       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3057       DONE;
3058     }
3059 ")
3060
3061 (define_expand "fix_truncdfsi2"
3062   [(set (match_operand:SI         0 "s_register_operand" "")
3063         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3064   "TARGET_ARM && TARGET_HARD_FLOAT"
3065   "
3066   if (TARGET_MAVERICK)
3067     {
3068       if (!cirrus_fp_register (operands[1], DFmode))
3069         operands[1] = force_reg (DFmode, operands[0]);
3070       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3071       DONE;
3072     }
3073 ")
3074
3075 ;; Truncation insns
3076
3077 (define_expand "truncdfsf2"
3078   [(set (match_operand:SF  0 "s_register_operand" "")
3079         (float_truncate:SF
3080          (match_operand:DF 1 "s_register_operand" "")))]
3081   "TARGET_ARM && TARGET_HARD_FLOAT"
3082   ""
3083 )
3084 \f
3085 ;; Zero and sign extension instructions.
3086
3087 (define_insn "zero_extendsidi2"
3088   [(set (match_operand:DI 0 "s_register_operand" "=r")
3089         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3090   "TARGET_ARM"
3091   "*
3092     if (REGNO (operands[1])
3093         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3094       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3095     return \"mov%?\\t%R0, #0\";
3096   "
3097   [(set_attr "length" "8")
3098    (set_attr "predicable" "yes")]
3099 )
3100
3101 (define_insn "zero_extendqidi2"
3102   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3103         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3104   "TARGET_ARM"
3105   "@
3106    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3107    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3108   [(set_attr "length" "8")
3109    (set_attr "predicable" "yes")
3110    (set_attr "type" "*,load_byte")
3111    (set_attr "pool_range" "*,4092")
3112    (set_attr "neg_pool_range" "*,4084")]
3113 )
3114
3115 (define_insn "extendsidi2"
3116   [(set (match_operand:DI 0 "s_register_operand" "=r")
3117         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3118   "TARGET_ARM"
3119   "*
3120     if (REGNO (operands[1])
3121         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3122       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3123     return \"mov%?\\t%R0, %Q0, asr #31\";
3124   "
3125   [(set_attr "length" "8")
3126    (set_attr "shift" "1")
3127    (set_attr "predicable" "yes")]
3128 )
3129
3130 (define_expand "zero_extendhisi2"
3131   [(set (match_dup 2)
3132         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3133                    (const_int 16)))
3134    (set (match_operand:SI 0 "s_register_operand" "")
3135         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3136   "TARGET_EITHER"
3137   "
3138   {
3139     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3140       {
3141         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3142                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3143         DONE;
3144       }
3145
3146     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3147       {
3148         emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3149         DONE;
3150       }
3151
3152     if (!s_register_operand (operands[1], HImode))
3153       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3154
3155     if (arm_arch6)
3156       {
3157         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3158                                 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
3159         DONE;
3160       }
3161
3162     operands[1] = gen_lowpart (SImode, operands[1]);
3163     operands[2] = gen_reg_rtx (SImode);
3164   }"
3165 )
3166
3167 (define_insn "*thumb_zero_extendhisi2"
3168   [(set (match_operand:SI 0 "register_operand" "=l")
3169         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3170   "TARGET_THUMB && !arm_arch6"
3171   "*
3172   rtx mem = XEXP (operands[1], 0);
3173
3174   if (GET_CODE (mem) == CONST)
3175     mem = XEXP (mem, 0);
3176     
3177   if (GET_CODE (mem) == LABEL_REF)
3178     return \"ldr\\t%0, %1\";
3179     
3180   if (GET_CODE (mem) == PLUS)
3181     {
3182       rtx a = XEXP (mem, 0);
3183       rtx b = XEXP (mem, 1);
3184
3185       /* This can happen due to bugs in reload.  */
3186       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3187         {
3188           rtx ops[2];
3189           ops[0] = operands[0];
3190           ops[1] = a;
3191       
3192           output_asm_insn (\"mov        %0, %1\", ops);
3193
3194           XEXP (mem, 0) = operands[0];
3195        }
3196
3197       else if (   GET_CODE (a) == LABEL_REF
3198                && GET_CODE (b) == CONST_INT)
3199         return \"ldr\\t%0, %1\";
3200     }
3201     
3202   return \"ldrh\\t%0, %1\";
3203   "
3204   [(set_attr "length" "4")
3205    (set_attr "type" "load_byte")
3206    (set_attr "pool_range" "60")]
3207 )
3208
3209 (define_insn "*thumb_zero_extendhisi2_v6"
3210   [(set (match_operand:SI 0 "register_operand" "=l,l")
3211         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
3212   "TARGET_THUMB && arm_arch6"
3213   "*
3214   rtx mem;
3215
3216   if (which_alternative == 0)
3217     return \"uxth\\t%0, %1\";
3218
3219   mem = XEXP (operands[1], 0);
3220
3221   if (GET_CODE (mem) == CONST)
3222     mem = XEXP (mem, 0);
3223     
3224   if (GET_CODE (mem) == LABEL_REF)
3225     return \"ldr\\t%0, %1\";
3226     
3227   if (GET_CODE (mem) == PLUS)
3228     {
3229       rtx a = XEXP (mem, 0);
3230       rtx b = XEXP (mem, 1);
3231
3232       /* This can happen due to bugs in reload.  */
3233       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3234         {
3235           rtx ops[2];
3236           ops[0] = operands[0];
3237           ops[1] = a;
3238       
3239           output_asm_insn (\"mov        %0, %1\", ops);
3240
3241           XEXP (mem, 0) = operands[0];
3242        }
3243
3244       else if (   GET_CODE (a) == LABEL_REF
3245                && GET_CODE (b) == CONST_INT)
3246         return \"ldr\\t%0, %1\";
3247     }
3248     
3249   return \"ldrh\\t%0, %1\";
3250   "
3251   [(set_attr "length" "2,4")
3252    (set_attr "type" "alu_shift,load_byte")
3253    (set_attr "pool_range" "*,60")]
3254 )
3255
3256 (define_insn "*arm_zero_extendhisi2"
3257   [(set (match_operand:SI 0 "s_register_operand" "=r")
3258         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3259   "TARGET_ARM && arm_arch4 && !arm_arch6"
3260   "ldr%?h\\t%0, %1"
3261   [(set_attr "type" "load_byte")
3262    (set_attr "predicable" "yes")
3263    (set_attr "pool_range" "256")
3264    (set_attr "neg_pool_range" "244")]
3265 )
3266
3267 (define_insn "*arm_zero_extendhisi2_v6"
3268   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3269         (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3270   "TARGET_ARM && arm_arch6"
3271   "@
3272    uxth%?\\t%0, %1
3273    ldr%?h\\t%0, %1"
3274   [(set_attr "type" "alu_shift,load_byte")
3275    (set_attr "predicable" "yes")
3276    (set_attr "pool_range" "*,256")
3277    (set_attr "neg_pool_range" "*,244")]
3278 )
3279
3280 (define_insn "*arm_zero_extendhisi2addsi"
3281   [(set (match_operand:SI 0 "s_register_operand" "=r")
3282         (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3283                  (match_operand:SI 2 "s_register_operand" "r")))]
3284   "TARGET_ARM && arm_arch6"
3285   "uxtah%?\\t%0, %2, %1"
3286   [(set_attr "type" "alu_shift")
3287    (set_attr "predicable" "yes")]
3288 )
3289
3290 (define_split
3291   [(set (match_operand:SI 0 "s_register_operand" "")
3292         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3293    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3294   "TARGET_ARM && (!arm_arch4)"
3295   [(set (match_dup 2) (match_dup 1))
3296    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3297   "
3298   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3299     FAIL;
3300   "
3301 )
3302
3303 (define_split
3304   [(set (match_operand:SI 0 "s_register_operand" "")
3305         (match_operator:SI 3 "shiftable_operator"
3306          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3307           (match_operand:SI 4 "s_register_operand" "")]))
3308    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3309   "TARGET_ARM && (!arm_arch4)"
3310   [(set (match_dup 2) (match_dup 1))
3311    (set (match_dup 0)
3312         (match_op_dup 3
3313          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3314   "
3315   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3316     FAIL;
3317   "
3318 )
3319
3320 (define_expand "zero_extendqisi2"
3321   [(set (match_operand:SI 0 "s_register_operand" "")
3322         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3323   "TARGET_EITHER"
3324   "
3325   if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
3326     {
3327       if (TARGET_ARM)
3328         {
3329           emit_insn (gen_andsi3 (operands[0],
3330                                  gen_lowpart (SImode, operands[1]),
3331                                  GEN_INT (255)));
3332         }
3333       else /* TARGET_THUMB */
3334         {
3335           rtx temp = gen_reg_rtx (SImode);
3336           rtx ops[3];
3337           
3338           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3339           operands[1] = gen_lowpart (SImode, operands[1]);
3340
3341           ops[0] = temp;
3342           ops[1] = operands[1];
3343           ops[2] = GEN_INT (24);
3344
3345           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3346                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3347           
3348           ops[0] = operands[0];
3349           ops[1] = temp;
3350           ops[2] = GEN_INT (24);
3351
3352           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3353                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3354         }
3355       DONE;
3356     }
3357   "
3358 )
3359
3360 (define_insn "*thumb_zero_extendqisi2"
3361   [(set (match_operand:SI 0 "register_operand" "=l")
3362         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3363   "TARGET_THUMB && !arm_arch6"
3364   "ldrb\\t%0, %1"
3365   [(set_attr "length" "2")
3366    (set_attr "type" "load_byte")
3367    (set_attr "pool_range" "32")]
3368 )
3369
3370 (define_insn "*thumb_zero_extendqisi2_v6"
3371   [(set (match_operand:SI 0 "register_operand" "=l,l")
3372         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
3373   "TARGET_THUMB && arm_arch6"
3374   "@
3375    uxtb\\t%0, %1
3376    ldrb\\t%0, %1"
3377   [(set_attr "length" "2,2")
3378    (set_attr "type" "alu_shift,load_byte")
3379    (set_attr "pool_range" "*,32")]
3380 )
3381
3382 (define_insn "*arm_zero_extendqisi2"
3383   [(set (match_operand:SI 0 "s_register_operand" "=r")
3384         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3385   "TARGET_ARM && !arm_arch6"
3386   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3387   [(set_attr "type" "load_byte")
3388    (set_attr "predicable" "yes")
3389    (set_attr "pool_range" "4096")
3390    (set_attr "neg_pool_range" "4084")]
3391 )
3392
3393 (define_insn "*arm_zero_extendqisi2_v6"
3394   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3395         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3396   "TARGET_ARM && arm_arch6"
3397   "@
3398    uxtb%?\\t%0, %1
3399    ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3400   [(set_attr "type" "alu_shift,load_byte")
3401    (set_attr "predicable" "yes")
3402    (set_attr "pool_range" "*,4096")
3403    (set_attr "neg_pool_range" "*,4084")]
3404 )
3405
3406 (define_insn "*arm_zero_extendqisi2addsi"
3407   [(set (match_operand:SI 0 "s_register_operand" "=r")
3408         (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3409                  (match_operand:SI 2 "s_register_operand" "r")))]
3410   "TARGET_ARM && arm_arch6"
3411   "uxtab%?\\t%0, %2, %1"
3412   [(set_attr "predicable" "yes")
3413    (set_attr "type" "alu_shift")]
3414 )
3415
3416 (define_split
3417   [(set (match_operand:SI 0 "s_register_operand" "")
3418         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3419    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3420   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3421   [(set (match_dup 2) (match_dup 1))
3422    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3423   ""
3424 )
3425
3426 (define_insn "*compareqi_eq0"
3427   [(set (reg:CC_Z CC_REGNUM)
3428         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3429                          (const_int 0)))]
3430   "TARGET_ARM"
3431   "tst\\t%0, #255"
3432   [(set_attr "conds" "set")]
3433 )
3434
3435 (define_expand "extendhisi2"
3436   [(set (match_dup 2)
3437         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3438                    (const_int 16)))
3439    (set (match_operand:SI 0 "s_register_operand" "")
3440         (ashiftrt:SI (match_dup 2)
3441                      (const_int 16)))]
3442   "TARGET_EITHER"
3443   "
3444   {
3445     if (GET_CODE (operands[1]) == MEM)
3446       {
3447         if (TARGET_THUMB)
3448           {
3449             emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3450             DONE;
3451           }
3452         else if (arm_arch4)
3453           {
3454             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3455                        gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3456             DONE;
3457           }
3458       }
3459
3460     if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
3461       {
3462         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3463         DONE;
3464       }
3465
3466     if (!s_register_operand (operands[1], HImode))
3467       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3468
3469     if (arm_arch6)
3470       {
3471         if (TARGET_THUMB)
3472           emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
3473         else
3474           emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3475                      gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3476
3477         DONE;
3478       }
3479
3480     operands[1] = gen_lowpart (SImode, operands[1]);
3481     operands[2] = gen_reg_rtx (SImode);
3482   }"
3483 )
3484
3485 (define_insn "thumb_extendhisi2"
3486   [(set (match_operand:SI 0 "register_operand" "=l")
3487         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3488    (clobber (match_scratch:SI 2 "=&l"))]
3489   "TARGET_THUMB && !arm_arch6"
3490   "*
3491   {
3492     rtx ops[4];
3493     rtx mem = XEXP (operands[1], 0);
3494
3495     /* This code used to try to use 'V', and fix the address only if it was
3496        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3497        range of QImode offsets, and offsettable_address_p does a QImode
3498        address check.  */
3499        
3500     if (GET_CODE (mem) == CONST)
3501       mem = XEXP (mem, 0);
3502     
3503     if (GET_CODE (mem) == LABEL_REF)
3504       return \"ldr\\t%0, %1\";
3505     
3506     if (GET_CODE (mem) == PLUS)
3507       {
3508         rtx a = XEXP (mem, 0);
3509         rtx b = XEXP (mem, 1);
3510
3511         if (GET_CODE (a) == LABEL_REF
3512             && GET_CODE (b) == CONST_INT)
3513           return \"ldr\\t%0, %1\";
3514
3515         if (GET_CODE (b) == REG)
3516           return \"ldrsh\\t%0, %1\";
3517           
3518         ops[1] = a;
3519         ops[2] = b;
3520       }
3521     else
3522       {
3523         ops[1] = mem;
3524         ops[2] = const0_rtx;
3525       }
3526       
3527     if (GET_CODE (ops[1]) != REG)
3528       {
3529         debug_rtx (ops[1]);
3530         abort ();
3531       }
3532
3533     ops[0] = operands[0];
3534     ops[3] = operands[2];
3535     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3536     return \"\";
3537   }"
3538   [(set_attr "length" "4")
3539    (set_attr "type" "load_byte")
3540    (set_attr "pool_range" "1020")]
3541 )
3542
3543 ;; We used to have an early-clobber on the scratch register here.
3544 ;; However, there's a bug somewhere in reload which means that this
3545 ;; can be partially ignored during spill allocation if the memory
3546 ;; address also needs reloading; this causes an abort later on when
3547 ;; we try to verify the operands.  Fortunately, we don't really need
3548 ;; the early-clobber: we can always use operand 0 if operand 2
3549 ;; overlaps the address.
3550 (define_insn "*thumb_extendhisi2_insn_v6"
3551   [(set (match_operand:SI 0 "register_operand" "=l,l")
3552         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
3553    (clobber (match_scratch:SI 2 "=X,l"))]
3554   "TARGET_THUMB && arm_arch6"
3555   "*
3556   {
3557     rtx ops[4];
3558     rtx mem;
3559
3560     if (which_alternative == 0)
3561       return \"sxth\\t%0, %1\";
3562
3563     mem = XEXP (operands[1], 0);
3564
3565     /* This code used to try to use 'V', and fix the address only if it was
3566        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3567        range of QImode offsets, and offsettable_address_p does a QImode
3568        address check.  */
3569        
3570     if (GET_CODE (mem) == CONST)
3571       mem = XEXP (mem, 0);
3572     
3573     if (GET_CODE (mem) == LABEL_REF)
3574       return \"ldr\\t%0, %1\";
3575     
3576     if (GET_CODE (mem) == PLUS)
3577       {
3578         rtx a = XEXP (mem, 0);
3579         rtx b = XEXP (mem, 1);
3580
3581         if (GET_CODE (a) == LABEL_REF
3582             && GET_CODE (b) == CONST_INT)
3583           return \"ldr\\t%0, %1\";
3584
3585         if (GET_CODE (b) == REG)
3586           return \"ldrsh\\t%0, %1\";
3587           
3588         ops[1] = a;
3589         ops[2] = b;
3590       }
3591     else
3592       {
3593         ops[1] = mem;
3594         ops[2] = const0_rtx;
3595       }
3596       
3597     if (GET_CODE (ops[1]) != REG)
3598       {
3599         debug_rtx (ops[1]);
3600         abort ();
3601       }
3602
3603     ops[0] = operands[0];
3604     if (reg_mentioned_p (operands[2], ops[1]))
3605       ops[3] = ops[0];
3606     else
3607       ops[3] = operands[2];
3608     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3609     return \"\";
3610   }"
3611   [(set_attr "length" "2,4")
3612    (set_attr "type" "alu_shift,load_byte")
3613    (set_attr "pool_range" "*,1020")]
3614 )
3615
3616 (define_expand "extendhisi2_mem"
3617   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3618    (set (match_dup 3)
3619         (zero_extend:SI (match_dup 7)))
3620    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3621    (set (match_operand:SI 0 "" "")
3622         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3623   "TARGET_ARM"
3624   "
3625   {
3626     rtx mem1, mem2;
3627     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3628
3629     mem1 = gen_rtx_MEM (QImode, addr);
3630     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3631     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3632     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3633     operands[0] = gen_lowpart (SImode, operands[0]);
3634     operands[1] = mem1;
3635     operands[2] = gen_reg_rtx (SImode);
3636     operands[3] = gen_reg_rtx (SImode);
3637     operands[6] = gen_reg_rtx (SImode);
3638     operands[7] = mem2;
3639
3640     if (BYTES_BIG_ENDIAN)
3641       {
3642         operands[4] = operands[2];
3643         operands[5] = operands[3];
3644       }
3645     else
3646       {
3647         operands[4] = operands[3];
3648         operands[5] = operands[2];
3649       }
3650   }"
3651 )
3652
3653 (define_insn "*arm_extendhisi2"
3654   [(set (match_operand:SI 0 "s_register_operand" "=r")
3655         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3656   "TARGET_ARM && arm_arch4 && !arm_arch6"
3657   "ldr%?sh\\t%0, %1"
3658   [(set_attr "type" "load_byte")
3659    (set_attr "predicable" "yes")
3660    (set_attr "pool_range" "256")
3661    (set_attr "neg_pool_range" "244")]
3662 )
3663
3664 (define_insn "*arm_extendhisi2_v6"
3665   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3666         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
3667   "TARGET_ARM && arm_arch6"
3668   "@
3669    sxth%?\\t%0, %1
3670    ldr%?sh\\t%0, %1"
3671   [(set_attr "type" "alu_shift,load_byte")
3672    (set_attr "predicable" "yes")
3673    (set_attr "pool_range" "*,256")
3674    (set_attr "neg_pool_range" "*,244")]
3675 )
3676
3677 (define_insn "*arm_extendhisi2addsi"
3678   [(set (match_operand:SI 0 "s_register_operand" "=r")
3679         (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
3680                  (match_operand:SI 2 "s_register_operand" "r")))]
3681   "TARGET_ARM && arm_arch6"
3682   "sxtah%?\\t%0, %2, %1"
3683 )
3684
3685 (define_split
3686   [(set (match_operand:SI                 0 "s_register_operand" "")
3687         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3688    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3689   "TARGET_ARM && (!arm_arch4)"
3690   [(set (match_dup 2) (match_dup 1))
3691    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3692   "
3693   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3694     FAIL;
3695   "
3696 )
3697
3698 (define_split
3699   [(set (match_operand:SI                   0 "s_register_operand" "")
3700         (match_operator:SI                  3 "shiftable_operator"
3701          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3702           (match_operand:SI                 4 "s_register_operand" "")]))
3703    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3704   "TARGET_ARM && (!arm_arch4)"
3705   [(set (match_dup 2) (match_dup 1))
3706    (set (match_dup 0)
3707         (match_op_dup 3
3708          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3709   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3710      FAIL;
3711   "
3712 )
3713
3714 (define_expand "extendqihi2"
3715   [(set (match_dup 2)
3716         (ashift:SI (match_operand:QI 1 "general_operand" "")
3717                    (const_int 24)))
3718    (set (match_operand:HI 0 "s_register_operand" "")
3719         (ashiftrt:SI (match_dup 2)
3720                      (const_int 24)))]
3721   "TARGET_ARM"
3722   "
3723   {
3724     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3725       {
3726         emit_insn (gen_rtx_SET (VOIDmode,
3727                                 operands[0],
3728                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3729         DONE;
3730       }
3731     if (!s_register_operand (operands[1], QImode))
3732       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3733     operands[0] = gen_lowpart (SImode, operands[0]);
3734     operands[1] = gen_lowpart (SImode, operands[1]);
3735     operands[2] = gen_reg_rtx (SImode);
3736   }"
3737 )
3738
3739 (define_insn "*extendqihi_insn"
3740   [(set (match_operand:HI 0 "s_register_operand" "=r")
3741         (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
3742   "TARGET_ARM && arm_arch4"
3743   "ldr%?sb\\t%0, %1"
3744   [(set_attr "type" "load_byte")
3745    (set_attr "predicable" "yes")
3746    (set_attr "pool_range" "256")
3747    (set_attr "neg_pool_range" "244")]
3748 )
3749
3750 (define_expand "extendqisi2"
3751   [(set (match_dup 2)
3752         (ashift:SI (match_operand:QI 1 "general_operand" "")
3753                    (const_int 24)))
3754    (set (match_operand:SI 0 "s_register_operand" "")
3755         (ashiftrt:SI (match_dup 2)
3756                      (const_int 24)))]
3757   "TARGET_EITHER"
3758   "
3759   {
3760     if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
3761       {
3762         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3763                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3764         DONE;
3765       }
3766
3767     if (!s_register_operand (operands[1], QImode))
3768       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3769
3770     if (arm_arch6)
3771       {
3772         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3773                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3774         DONE;
3775       }
3776
3777     operands[1] = gen_lowpart (SImode, operands[1]);
3778     operands[2] = gen_reg_rtx (SImode);
3779   }"
3780 )
3781
3782 (define_insn "*arm_extendqisi"
3783   [(set (match_operand:SI 0 "s_register_operand" "=r")
3784         (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
3785   "TARGET_ARM && arm_arch4 && !arm_arch6"
3786   "ldr%?sb\\t%0, %1"
3787   [(set_attr "type" "load_byte")
3788    (set_attr "predicable" "yes")
3789    (set_attr "pool_range" "256")
3790    (set_attr "neg_pool_range" "244")]
3791 )
3792
3793 (define_insn "*arm_extendqisi_v6"
3794   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3795         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
3796   "TARGET_ARM && arm_arch6"
3797   "@
3798    sxtb%?\\t%0, %1
3799    ldr%?sb\\t%0, %1"
3800   [(set_attr "type" "alu_shift,load_byte")
3801    (set_attr "predicable" "yes")
3802    (set_attr "pool_range" "*,256")
3803    (set_attr "neg_pool_range" "*,244")]
3804 )
3805
3806 (define_insn "*arm_extendqisi2addsi"
3807   [(set (match_operand:SI 0 "s_register_operand" "=r")
3808         (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
3809                  (match_operand:SI 2 "s_register_operand" "r")))]
3810   "TARGET_ARM && arm_arch6"
3811   "sxtab%?\\t%0, %2, %1"
3812   [(set_attr "type" "alu_shift")
3813    (set_attr "predicable" "yes")]
3814 )
3815
3816 (define_insn "*thumb_extendqisi2"
3817   [(set (match_operand:SI 0 "register_operand" "=l,l")
3818         (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3819   "TARGET_THUMB && !arm_arch6"
3820   "*
3821   {
3822     rtx ops[3];
3823     rtx mem = XEXP (operands[1], 0);
3824     
3825     if (GET_CODE (mem) == CONST)
3826       mem = XEXP (mem, 0);
3827     
3828     if (GET_CODE (mem) == LABEL_REF)
3829       return \"ldr\\t%0, %1\";
3830
3831     if (GET_CODE (mem) == PLUS
3832         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3833       return \"ldr\\t%0, %1\";
3834       
3835     if (which_alternative == 0)
3836       return \"ldrsb\\t%0, %1\";
3837       
3838     ops[0] = operands[0];
3839     
3840     if (GET_CODE (mem) == PLUS)
3841       {
3842         rtx a = XEXP (mem, 0);
3843         rtx b = XEXP (mem, 1);
3844         
3845         ops[1] = a;
3846         ops[2] = b;
3847
3848         if (GET_CODE (a) == REG)
3849           {
3850             if (GET_CODE (b) == REG)
3851               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3852             else if (REGNO (a) == REGNO (ops[0]))
3853               {
3854                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3855                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3856                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3857               }
3858             else
3859               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3860           }
3861         else if (GET_CODE (b) != REG)
3862           abort ();
3863         else
3864           {
3865             if (REGNO (b) == REGNO (ops[0]))
3866               {
3867                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3868                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3869                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3870               }
3871             else
3872               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3873           }
3874       }
3875     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3876       {
3877         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3878         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3879         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3880       }
3881     else
3882       {
3883         ops[1] = mem;
3884         ops[2] = const0_rtx;
3885         
3886         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3887       }
3888     return \"\";
3889   }"
3890   [(set_attr "length" "2,6")
3891    (set_attr "type" "load_byte,load_byte")
3892    (set_attr "pool_range" "32,32")]
3893 )
3894
3895 (define_insn "*thumb_extendqisi2_v6"
3896   [(set (match_operand:SI 0 "register_operand" "=l,l,l")
3897         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
3898   "TARGET_THUMB && arm_arch6"
3899   "*
3900   {
3901     rtx ops[3];
3902     rtx mem;
3903
3904     if (which_alternative == 0)
3905       return \"sxtb\\t%0, %1\";
3906
3907     mem = XEXP (operands[1], 0);
3908     
3909     if (GET_CODE (mem) == CONST)
3910       mem = XEXP (mem, 0);
3911     
3912     if (GET_CODE (mem) == LABEL_REF)
3913       return \"ldr\\t%0, %1\";
3914
3915     if (GET_CODE (mem) == PLUS
3916         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3917       return \"ldr\\t%0, %1\";
3918       
3919     if (which_alternative == 0)
3920       return \"ldrsb\\t%0, %1\";
3921       
3922     ops[0] = operands[0];
3923     
3924     if (GET_CODE (mem) == PLUS)
3925       {
3926         rtx a = XEXP (mem, 0);
3927         rtx b = XEXP (mem, 1);
3928         
3929         ops[1] = a;
3930         ops[2] = b;
3931
3932         if (GET_CODE (a) == REG)
3933           {
3934             if (GET_CODE (b) == REG)
3935               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3936             else if (REGNO (a) == REGNO (ops[0]))
3937               {
3938                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3939                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3940               }
3941             else
3942               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3943           }
3944         else if (GET_CODE (b) != REG)
3945           abort ();
3946         else
3947           {
3948             if (REGNO (b) == REGNO (ops[0]))
3949               {
3950                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3951                 output_asm_insn (\"sxtb\\t%0, %0\", ops);
3952               }
3953             else
3954               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3955           }
3956       }
3957     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3958       {
3959         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3960         output_asm_insn (\"sxtb\\t%0, %0\", ops);
3961       }
3962     else
3963       {
3964         ops[1] = mem;
3965         ops[2] = const0_rtx;
3966         
3967         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3968       }
3969     return \"\";
3970   }"
3971   [(set_attr "length" "2,2,4")
3972    (set_attr "type" "alu_shift,load_byte,load_byte")
3973    (set_attr "pool_range" "*,32,32")]
3974 )
3975
3976 (define_expand "extendsfdf2"
3977   [(set (match_operand:DF                  0 "s_register_operand" "")
3978         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
3979   "TARGET_ARM && TARGET_HARD_FLOAT"
3980   ""
3981 )
3982 \f
3983 ;; Move insns (including loads and stores)
3984
3985 ;; XXX Just some ideas about movti.
3986 ;; I don't think these are a good idea on the arm, there just aren't enough
3987 ;; registers
3988 ;;(define_expand "loadti"
3989 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3990 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3991 ;;  "" "")
3992
3993 ;;(define_expand "storeti"
3994 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3995 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3996 ;;  "" "")
3997
3998 ;;(define_expand "movti"
3999 ;;  [(set (match_operand:TI 0 "general_operand" "")
4000 ;;      (match_operand:TI 1 "general_operand" ""))]
4001 ;;  ""
4002 ;;  "
4003 ;;{
4004 ;;  rtx insn;
4005 ;;
4006 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
4007 ;;    operands[1] = copy_to_reg (operands[1]);
4008 ;;  if (GET_CODE (operands[0]) == MEM)
4009 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
4010 ;;  else if (GET_CODE (operands[1]) == MEM)
4011 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
4012 ;;  else
4013 ;;    FAIL;
4014 ;;
4015 ;;  emit_insn (insn);
4016 ;;  DONE;
4017 ;;}")
4018
4019 ;; Recognize garbage generated above.
4020
4021 ;;(define_insn ""
4022 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
4023 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
4024 ;;  ""
4025 ;;  "*
4026 ;;  {
4027 ;;    register mem = (which_alternative < 3);
4028 ;;    register const char *template;
4029 ;;
4030 ;;    operands[mem] = XEXP (operands[mem], 0);
4031 ;;    switch (which_alternative)
4032 ;;      {
4033 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
4034 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
4035 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
4036 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
4037 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
4038 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
4039 ;;      }
4040 ;;    output_asm_insn (template, operands);
4041 ;;    return \"\";
4042 ;;  }")
4043
4044 (define_expand "movdi"
4045   [(set (match_operand:DI 0 "general_operand" "")
4046         (match_operand:DI 1 "general_operand" ""))]
4047   "TARGET_EITHER"
4048   "
4049   if (TARGET_THUMB)
4050     {
4051       if (!no_new_pseudos)
4052         {
4053           if (GET_CODE (operands[0]) != REG)
4054             operands[1] = force_reg (DImode, operands[1]);
4055         }
4056     }
4057   "
4058 )
4059
4060 (define_insn "*arm_movdi"
4061   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r ,m")
4062         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
4063   "TARGET_ARM
4064   && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
4065   && !TARGET_IWMMXT"
4066   "*
4067   return (output_move_double (operands));
4068   "
4069   [(set_attr "length" "8")
4070    (set_attr "type" "*,load2,store2")
4071    (set_attr "pool_range" "*,1020,*")
4072    (set_attr "neg_pool_range" "*,1008,*")]
4073 )
4074
4075 ;; We can't actually do base+index doubleword loads if the index and
4076 ;; destination overlap.  Split here so that we at least have chance to
4077 ;; schedule.
4078 (define_split
4079   [(set (match_operand:DI 0 "s_register_operand" "")
4080         (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
4081                          (match_operand:SI 2 "s_register_operand" ""))))]
4082   "TARGET_LDRD
4083   && reg_overlap_mentioned_p (operands[0], operands[1])
4084   && reg_overlap_mentioned_p (operands[0], operands[2])"
4085   [(set (match_dup 4)
4086         (plus:SI (match_dup 1)
4087                  (match_dup 2)))
4088    (set (match_dup 0)
4089         (mem:DI (match_dup 4)))]
4090   "
4091   operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
4092   "
4093 )
4094
4095 ;;; ??? This should have alternatives for constants.
4096 ;;; ??? This was originally identical to the movdf_insn pattern.
4097 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
4098 ;;; thumb_reorg with a memory reference.
4099 (define_insn "*thumb_movdi_insn"
4100   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
4101         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
4102   "TARGET_THUMB
4103    && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
4104    && (   register_operand (operands[0], DImode)
4105        || register_operand (operands[1], DImode))"
4106   "*
4107   {
4108   switch (which_alternative)
4109     {
4110     default:
4111     case 0:
4112       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4113         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
4114       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
4115     case 1:
4116       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
4117     case 2:
4118       operands[1] = GEN_INT (- INTVAL (operands[1]));
4119       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
4120     case 3:
4121       return \"ldmia\\t%1, {%0, %H0}\";
4122     case 4:
4123       return \"stmia\\t%0, {%1, %H1}\";
4124     case 5:
4125       return thumb_load_double_from_address (operands);
4126     case 6:
4127       operands[2] = gen_rtx_MEM (SImode,
4128                              plus_constant (XEXP (operands[0], 0), 4));
4129       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4130       return \"\";
4131     case 7:
4132       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4133         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4134       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4135     }
4136   }"
4137   [(set_attr "length" "4,4,6,2,2,6,4,4")
4138    (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
4139    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4140 )
4141
4142 (define_expand "movsi"
4143   [(set (match_operand:SI 0 "general_operand" "")
4144         (match_operand:SI 1 "general_operand" ""))]
4145   "TARGET_EITHER"
4146   "
4147   if (TARGET_ARM)
4148     {
4149       /* Everything except mem = const or mem = mem can be done easily.  */
4150       if (GET_CODE (operands[0]) == MEM)
4151         operands[1] = force_reg (SImode, operands[1]);
4152       if (arm_general_register_operand (operands[0], SImode)
4153           && GET_CODE (operands[1]) == CONST_INT
4154           && !(const_ok_for_arm (INTVAL (operands[1]))
4155                || const_ok_for_arm (~INTVAL (operands[1]))))
4156         {
4157            arm_split_constant (SET, SImode, NULL_RTX,
4158                                INTVAL (operands[1]), operands[0], NULL_RTX,
4159                               (no_new_pseudos ? 0
4160                                : preserve_subexpressions_p ()));
4161           DONE;
4162         }
4163     }
4164   else /* TARGET_THUMB....  */
4165     {
4166       if (!no_new_pseudos)
4167         {
4168           if (GET_CODE (operands[0]) != REG)
4169             operands[1] = force_reg (SImode, operands[1]);
4170         }
4171     }
4172     
4173   if (flag_pic
4174       && (CONSTANT_P (operands[1])
4175          || symbol_mentioned_p (operands[1])
4176          || label_mentioned_p (operands[1])))
4177     operands[1] = legitimize_pic_address (operands[1], SImode,
4178                                           (no_new_pseudos ? operands[0] : 0));
4179   "
4180 )
4181
4182 (define_insn "*arm_movsi_insn"
4183   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4184         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4185   "TARGET_ARM && ! TARGET_IWMMXT
4186    && !(TARGET_HARD_FLOAT && TARGET_VFP)
4187    && (   register_operand (operands[0], SImode)
4188        || register_operand (operands[1], SImode))"
4189   "@
4190    mov%?\\t%0, %1
4191    mvn%?\\t%0, #%B1
4192    ldr%?\\t%0, %1
4193    str%?\\t%1, %0"
4194   [(set_attr "type" "*,*,load1,store1")
4195    (set_attr "predicable" "yes")
4196    (set_attr "pool_range" "*,*,4096,*")
4197    (set_attr "neg_pool_range" "*,*,4084,*")]
4198 )
4199
4200 (define_split
4201   [(set (match_operand:SI 0 "arm_general_register_operand" "")
4202         (match_operand:SI 1 "const_int_operand" ""))]
4203   "TARGET_ARM
4204   && (!(const_ok_for_arm (INTVAL (operands[1]))
4205         || const_ok_for_arm (~INTVAL (operands[1]))))"
4206   [(clobber (const_int 0))]
4207   "
4208   arm_split_constant (SET, SImode, NULL_RTX, 
4209                       INTVAL (operands[1]), operands[0], NULL_RTX, 0);
4210   DONE;
4211   "
4212 )
4213
4214 (define_insn "*thumb_movsi_insn"
4215   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4216         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4217   "TARGET_THUMB
4218    && (   register_operand (operands[0], SImode) 
4219        || register_operand (operands[1], SImode))"
4220   "@
4221    mov  %0, %1
4222    mov  %0, %1
4223    #
4224    #
4225    ldmia\\t%1, {%0}
4226    stmia\\t%0, {%1}
4227    ldr\\t%0, %1
4228    str\\t%1, %0
4229    mov\\t%0, %1"
4230   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4231    (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
4232    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4233 )
4234
4235 (define_split 
4236   [(set (match_operand:SI 0 "register_operand" "")
4237         (match_operand:SI 1 "const_int_operand" ""))]
4238   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4239   [(set (match_dup 0) (match_dup 1))
4240    (set (match_dup 0) (neg:SI (match_dup 0)))]
4241   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4242 )
4243
4244 (define_split 
4245   [(set (match_operand:SI 0 "register_operand" "")
4246         (match_operand:SI 1 "const_int_operand" ""))]
4247   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4248   [(set (match_dup 0) (match_dup 1))
4249    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4250   "
4251   {
4252     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4253     unsigned HOST_WIDE_INT mask = 0xff;
4254     int i;
4255     
4256     for (i = 0; i < 25; i++)
4257       if ((val & (mask << i)) == val)
4258         break;
4259
4260     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4261     if (i == 0)
4262       FAIL;
4263
4264     operands[1] = GEN_INT (val >> i);
4265     operands[2] = GEN_INT (i);
4266   }"
4267 )
4268
4269 ;; When generating pic, we need to load the symbol offset into a register.
4270 ;; So that the optimizer does not confuse this with a normal symbol load
4271 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4272 ;; since that is the only type of relocation we can use.
4273
4274 ;; The rather odd constraints on the following are to force reload to leave
4275 ;; the insn alone, and to force the minipool generation pass to then move
4276 ;; the GOT symbol to memory.
4277
4278 (define_insn "pic_load_addr_arm"
4279   [(set (match_operand:SI 0 "s_register_operand" "=r")
4280         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4281   "TARGET_ARM && flag_pic"
4282   "ldr%?\\t%0, %1"
4283   [(set_attr "type" "load1")
4284    (set (attr "pool_range")     (const_int 4096))
4285    (set (attr "neg_pool_range") (const_int 4084))]
4286 )
4287
4288 (define_insn "pic_load_addr_thumb"
4289   [(set (match_operand:SI 0 "s_register_operand" "=l")
4290         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4291   "TARGET_THUMB && flag_pic"
4292   "ldr\\t%0, %1"
4293   [(set_attr "type" "load1")
4294    (set (attr "pool_range") (const_int 1024))]
4295 )
4296
4297 ;; This variant is used for AOF assembly, since it needs to mention the
4298 ;; pic register in the rtl.
4299 (define_expand "pic_load_addr_based"
4300   [(set (match_operand:SI 0 "s_register_operand" "")
4301         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4302   "TARGET_ARM && flag_pic"
4303   "operands[2] = pic_offset_table_rtx;"
4304 )
4305
4306 (define_insn "*pic_load_addr_based_insn"
4307   [(set (match_operand:SI 0 "s_register_operand" "=r")
4308         (unspec:SI [(match_operand 1 "" "")
4309                     (match_operand 2 "s_register_operand" "r")]
4310                    UNSPEC_PIC_SYM))]
4311   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4312   "*
4313 #ifdef AOF_ASSEMBLER
4314   operands[1] = aof_pic_entry (operands[1]);
4315 #endif
4316   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4317   return \"\";
4318   "
4319   [(set_attr "type" "load1")
4320    (set (attr "pool_range")
4321         (if_then_else (eq_attr "is_thumb" "yes")
4322                       (const_int 1024)
4323                       (const_int 4096)))
4324    (set (attr "neg_pool_range")
4325         (if_then_else (eq_attr "is_thumb" "yes")
4326                       (const_int 0)
4327                       (const_int 4084)))]
4328 )
4329
4330 (define_insn "pic_add_dot_plus_four"
4331   [(set (match_operand:SI 0 "register_operand" "+r")
4332         (unspec:SI [(plus:SI (match_dup 0)
4333                              (const (plus:SI (pc) (const_int 4))))]
4334                    UNSPEC_PIC_BASE))
4335    (use (label_ref (match_operand 1 "" "")))]
4336   "TARGET_THUMB && flag_pic"
4337   "*
4338   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4339                              CODE_LABEL_NUMBER (operands[1]));
4340   return \"add\\t%0, %|pc\";
4341   "
4342   [(set_attr "length" "2")]
4343 )
4344
4345 (define_insn "pic_add_dot_plus_eight"
4346   [(set (match_operand:SI 0 "register_operand" "+r")
4347         (unspec:SI [(plus:SI (match_dup 0)
4348                              (const (plus:SI (pc) (const_int 8))))]
4349                    UNSPEC_PIC_BASE))
4350    (use (label_ref (match_operand 1 "" "")))]
4351   "TARGET_ARM && flag_pic"
4352   "*
4353     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4354                                CODE_LABEL_NUMBER (operands[1]));
4355     return \"add%?\\t%0, %|pc, %0\";
4356   "
4357   [(set_attr "predicable" "yes")]
4358 )
4359
4360 (define_expand "builtin_setjmp_receiver"
4361   [(label_ref (match_operand 0 "" ""))]
4362   "flag_pic"
4363   "
4364 {
4365   arm_finalize_pic (0);
4366   DONE;
4367 }")
4368
4369 ;; If copying one reg to another we can set the condition codes according to
4370 ;; its value.  Such a move is common after a return from subroutine and the
4371 ;; result is being tested against zero.
4372
4373 (define_insn "*movsi_compare0"
4374   [(set (reg:CC CC_REGNUM)
4375         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4376                     (const_int 0)))
4377    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4378         (match_dup 1))]
4379   "TARGET_ARM"
4380   "@
4381    cmp%?\\t%0, #0
4382    sub%?s\\t%0, %1, #0"
4383   [(set_attr "conds" "set")]
4384 )
4385
4386 ;; Subroutine to store a half word from a register into memory.
4387 ;; Operand 0 is the source register (HImode)
4388 ;; Operand 1 is the destination address in a register (SImode)
4389
4390 ;; In both this routine and the next, we must be careful not to spill
4391 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4392 ;; can generate unrecognizable rtl.
4393
4394 (define_expand "storehi"
4395   [;; store the low byte
4396    (set (match_operand 1 "" "") (match_dup 3))
4397    ;; extract the high byte
4398    (set (match_dup 2)
4399         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4400    ;; store the high byte
4401    (set (match_dup 4) (match_dup 5))]
4402   "TARGET_ARM"
4403   "
4404   {
4405     rtx op1 = operands[1];
4406     rtx addr = XEXP (op1, 0);
4407     enum rtx_code code = GET_CODE (addr);
4408
4409     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4410         || code == MINUS)
4411       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4412
4413     operands[4] = adjust_address (op1, QImode, 1);
4414     operands[1] = adjust_address (operands[1], QImode, 0);
4415     operands[3] = gen_lowpart (QImode, operands[0]);
4416     operands[0] = gen_lowpart (SImode, operands[0]);
4417     operands[2] = gen_reg_rtx (SImode);
4418     operands[5] = gen_lowpart (QImode, operands[2]);
4419   }"
4420 )
4421
4422 (define_expand "storehi_bigend"
4423   [(set (match_dup 4) (match_dup 3))
4424    (set (match_dup 2)
4425         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4426    (set (match_operand 1 "" "") (match_dup 5))]
4427   "TARGET_ARM"
4428   "
4429   {
4430     rtx op1 = operands[1];
4431     rtx addr = XEXP (op1, 0);
4432     enum rtx_code code = GET_CODE (addr);
4433
4434     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4435         || code == MINUS)
4436       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4437
4438     operands[4] = adjust_address (op1, QImode, 1);
4439     operands[1] = adjust_address (operands[1], QImode, 0);
4440     operands[3] = gen_lowpart (QImode, operands[0]);
4441     operands[0] = gen_lowpart (SImode, operands[0]);
4442     operands[2] = gen_reg_rtx (SImode);
4443     operands[5] = gen_lowpart (QImode, operands[2]);
4444   }"
4445 )
4446
4447 ;; Subroutine to store a half word integer constant into memory.
4448 (define_expand "storeinthi"
4449   [(set (match_operand 0 "" "")
4450         (match_operand 1 "" ""))
4451    (set (match_dup 3) (match_dup 2))]
4452   "TARGET_ARM"
4453   "
4454   {
4455     HOST_WIDE_INT value = INTVAL (operands[1]);
4456     rtx addr = XEXP (operands[0], 0);
4457     rtx op0 = operands[0];
4458     enum rtx_code code = GET_CODE (addr);
4459
4460     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4461         || code == MINUS)
4462       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4463
4464     operands[1] = gen_reg_rtx (SImode);
4465     if (BYTES_BIG_ENDIAN)
4466       {
4467         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4468         if ((value & 255) == ((value >> 8) & 255))
4469           operands[2] = operands[1];
4470         else
4471           {
4472             operands[2] = gen_reg_rtx (SImode);
4473             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4474           }
4475       }
4476     else
4477       {
4478         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4479         if ((value & 255) == ((value >> 8) & 255))
4480           operands[2] = operands[1];
4481         else
4482           {
4483             operands[2] = gen_reg_rtx (SImode);
4484             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4485           }
4486       }
4487
4488     operands[3] = adjust_address (op0, QImode, 1);
4489     operands[0] = adjust_address (operands[0], QImode, 0);
4490     operands[2] = gen_lowpart (QImode, operands[2]);
4491     operands[1] = gen_lowpart (QImode, operands[1]);
4492   }"
4493 )
4494
4495 (define_expand "storehi_single_op"
4496   [(set (match_operand:HI 0 "memory_operand" "")
4497         (match_operand:HI 1 "general_operand" ""))]
4498   "TARGET_ARM && arm_arch4"
4499   "
4500   if (!s_register_operand (operands[1], HImode))
4501     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4502   "
4503 )
4504
4505 (define_expand "movhi"
4506   [(set (match_operand:HI 0 "general_operand" "")
4507         (match_operand:HI 1 "general_operand" ""))]
4508   "TARGET_EITHER"
4509   "
4510   if (TARGET_ARM)
4511     {
4512       if (!no_new_pseudos)
4513         {
4514           if (GET_CODE (operands[0]) == MEM)
4515             {
4516               if (arm_arch4)
4517                 {
4518                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4519                   DONE;
4520                 }
4521               if (GET_CODE (operands[1]) == CONST_INT)
4522                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4523               else
4524                 {
4525                   if (GET_CODE (operands[1]) == MEM)
4526                     operands[1] = force_reg (HImode, operands[1]);
4527                   if (BYTES_BIG_ENDIAN)
4528                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4529                   else
4530                    emit_insn (gen_storehi (operands[1], operands[0]));
4531                 }
4532               DONE;
4533             }
4534           /* Sign extend a constant, and keep it in an SImode reg.  */
4535           else if (GET_CODE (operands[1]) == CONST_INT)
4536             {
4537               rtx reg = gen_reg_rtx (SImode);
4538               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4539
4540               /* If the constant is already valid, leave it alone.  */
4541               if (!const_ok_for_arm (val))
4542                 {
4543                   /* If setting all the top bits will make the constant 
4544                      loadable in a single instruction, then set them.  
4545                      Otherwise, sign extend the number.  */
4546
4547                   if (const_ok_for_arm (~(val | ~0xffff)))
4548                     val |= ~0xffff;
4549                   else if (val & 0x8000)
4550                     val |= ~0xffff;
4551                 }
4552
4553               emit_insn (gen_movsi (reg, GEN_INT (val)));
4554               operands[1] = gen_lowpart (HImode, reg);
4555             }
4556           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4557                    && GET_CODE (operands[1]) == MEM)
4558             {
4559               rtx reg = gen_reg_rtx (SImode);
4560
4561               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4562               operands[1] = gen_lowpart (HImode, reg);
4563             }
4564           else if (!arm_arch4)
4565             {
4566               if (GET_CODE (operands[1]) == MEM)
4567                 {
4568                   rtx base;
4569                   rtx offset = const0_rtx;
4570                   rtx reg = gen_reg_rtx (SImode);
4571
4572                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4573                        || (GET_CODE (base) == PLUS
4574                            && (GET_CODE (offset = XEXP (base, 1))
4575                                == CONST_INT)
4576                            && ((INTVAL(offset) & 1) != 1)
4577                            && GET_CODE (base = XEXP (base, 0)) == REG))
4578                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4579                     {
4580                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4581                       rtx new;
4582
4583                       new = gen_rtx_MEM (SImode,
4584                                          plus_constant (base, new_offset));
4585                       MEM_COPY_ATTRIBUTES (new, operands[1]);
4586                       emit_insn (gen_movsi (reg, new));
4587                       if (((INTVAL (offset) & 2) != 0)
4588                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4589                         {
4590                           rtx reg2 = gen_reg_rtx (SImode);
4591
4592                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4593                           reg = reg2;
4594                         }
4595                     }
4596                   else
4597                     emit_insn (gen_movhi_bytes (reg, operands[1]));
4598
4599                   operands[1] = gen_lowpart (HImode, reg);
4600                }
4601            }
4602         }
4603       /* Handle loading a large integer during reload.  */
4604       else if (GET_CODE (operands[1]) == CONST_INT
4605                && !const_ok_for_arm (INTVAL (operands[1]))
4606                && !const_ok_for_arm (~INTVAL (operands[1])))
4607         {
4608           /* Writing a constant to memory needs a scratch, which should
4609              be handled with SECONDARY_RELOADs.  */
4610           if (GET_CODE (operands[0]) != REG)
4611             abort ();
4612
4613           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4614           emit_insn (gen_movsi (operands[0], operands[1]));
4615           DONE;
4616        }
4617     }
4618   else /* TARGET_THUMB */
4619     {
4620       if (!no_new_pseudos)
4621         {
4622           if (GET_CODE (operands[0]) != REG)
4623             operands[1] = force_reg (HImode, operands[1]);
4624
4625           /* ??? We shouldn't really get invalid addresses here, but this can
4626              happen if we are passed a SP (never OK for HImode/QImode) or 
4627              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4628              HImode/QImode) relative address.  */
4629           /* ??? This should perhaps be fixed elsewhere, for instance, in
4630              fixup_stack_1, by checking for other kinds of invalid addresses,
4631              e.g. a bare reference to a virtual register.  This may confuse the
4632              alpha though, which must handle this case differently.  */
4633           if (GET_CODE (operands[0]) == MEM
4634               && !memory_address_p (GET_MODE (operands[0]),
4635                                     XEXP (operands[0], 0)))
4636             operands[0]
4637               = replace_equiv_address (operands[0],
4638                                        copy_to_reg (XEXP (operands[0], 0)));
4639    
4640           if (GET_CODE (operands[1]) == MEM
4641               && !memory_address_p (GET_MODE (operands[1]),
4642                                     XEXP (operands[1], 0)))
4643             operands[1]
4644               = replace_equiv_address (operands[1],
4645                                        copy_to_reg (XEXP (operands[1], 0)));
4646         }
4647       /* Handle loading a large integer during reload.  */
4648       else if (GET_CODE (operands[1]) == CONST_INT
4649                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4650         {
4651           /* Writing a constant to memory needs a scratch, which should
4652              be handled with SECONDARY_RELOADs.  */
4653           if (GET_CODE (operands[0]) != REG)
4654             abort ();
4655
4656           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4657           emit_insn (gen_movsi (operands[0], operands[1]));
4658           DONE;
4659         }
4660     }
4661   "
4662 )
4663
4664 (define_insn "*thumb_movhi_insn"
4665   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4666         (match_operand:HI 1 "general_operand"       "l,m,l,*h,*r,I"))]
4667   "TARGET_THUMB
4668    && (   register_operand (operands[0], HImode)
4669        || register_operand (operands[1], HImode))"
4670   "*
4671   switch (which_alternative)
4672     {
4673     case 0: return \"add        %0, %1, #0\";
4674     case 2: return \"strh       %1, %0\";
4675     case 3: return \"mov        %0, %1\";
4676     case 4: return \"mov        %0, %1\";
4677     case 5: return \"mov        %0, %1\";
4678     default: abort ();
4679     case 1:
4680       /* The stack pointer can end up being taken as an index register.
4681           Catch this case here and deal with it.  */
4682       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4683           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4684           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4685         {
4686           rtx ops[2];
4687           ops[0] = operands[0];
4688           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4689       
4690           output_asm_insn (\"mov        %0, %1\", ops);
4691
4692           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4693     
4694         }
4695       return \"ldrh     %0, %1\";
4696     }"
4697   [(set_attr "length" "2,4,2,2,2,2")
4698    (set_attr "type" "*,load1,store1,*,*,*")]
4699 )
4700
4701
4702 (define_expand "movhi_bytes"
4703   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4704    (set (match_dup 3)
4705         (zero_extend:SI (match_dup 6)))
4706    (set (match_operand:SI 0 "" "")
4707          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4708   "TARGET_ARM"
4709   "
4710   {
4711     rtx mem1, mem2;
4712     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4713
4714     mem1 = gen_rtx_MEM (QImode, addr);
4715     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4716     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4717     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4718     operands[0] = gen_lowpart (SImode, operands[0]);
4719     operands[1] = mem1;
4720     operands[2] = gen_reg_rtx (SImode);
4721     operands[3] = gen_reg_rtx (SImode);
4722     operands[6] = mem2;
4723
4724     if (BYTES_BIG_ENDIAN)
4725       {
4726         operands[4] = operands[2];
4727         operands[5] = operands[3];
4728       }
4729     else
4730       {
4731         operands[4] = operands[3];
4732         operands[5] = operands[2];
4733       }
4734   }"
4735 )
4736
4737 (define_expand "movhi_bigend"
4738   [(set (match_dup 2)
4739         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4740                    (const_int 16)))
4741    (set (match_dup 3)
4742         (ashiftrt:SI (match_dup 2) (const_int 16)))
4743    (set (match_operand:HI 0 "s_register_operand" "")
4744         (match_dup 4))]
4745   "TARGET_ARM"
4746   "
4747   operands[2] = gen_reg_rtx (SImode);
4748   operands[3] = gen_reg_rtx (SImode);
4749   operands[4] = gen_lowpart (HImode, operands[3]);
4750   "
4751 )
4752
4753 ;; Pattern to recognize insn generated default case above
4754 (define_insn "*movhi_insn_arch4"
4755   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4756         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4757   "TARGET_ARM
4758    && arm_arch4
4759    && (GET_CODE (operands[1]) != CONST_INT
4760        || const_ok_for_arm (INTVAL (operands[1]))
4761        || const_ok_for_arm (~INTVAL (operands[1])))"
4762   "@
4763    mov%?\\t%0, %1\\t%@ movhi
4764    mvn%?\\t%0, #%B1\\t%@ movhi
4765    str%?h\\t%1, %0\\t%@ movhi 
4766    ldr%?h\\t%0, %1\\t%@ movhi"
4767   [(set_attr "type" "*,*,store1,load1")
4768    (set_attr "predicable" "yes")
4769    (set_attr "pool_range" "*,*,*,256")
4770    (set_attr "neg_pool_range" "*,*,*,244")]
4771 )
4772
4773 (define_insn "*movhi_bytes"
4774   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4775         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4776   "TARGET_ARM"
4777   "@
4778    mov%?\\t%0, %1\\t%@ movhi
4779    mvn%?\\t%0, #%B1\\t%@ movhi"
4780   [(set_attr "predicable" "yes")]
4781 )
4782
4783 (define_insn "thumb_movhi_clobber"
4784   [(set (match_operand:HI     0 "memory_operand"   "=m")
4785         (match_operand:HI     1 "register_operand" "l"))
4786    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4787   "TARGET_THUMB"
4788   "*
4789   abort ();"
4790 )
4791         
4792 ;; We use a DImode scratch because we may occasionally need an additional
4793 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4794 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4795 (define_expand "reload_outhi"
4796   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4797               (match_operand:HI 1 "s_register_operand"        "r")
4798               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4799   "TARGET_EITHER"
4800   "if (TARGET_ARM)
4801      arm_reload_out_hi (operands);
4802    else
4803      thumb_reload_out_hi (operands);
4804   DONE;
4805   "
4806 )
4807
4808 (define_expand "reload_inhi"
4809   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4810               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4811               (match_operand:DI 2 "s_register_operand" "=&r")])]
4812   "TARGET_EITHER"
4813   "
4814   if (TARGET_ARM)
4815     arm_reload_in_hi (operands);
4816   else
4817     thumb_reload_out_hi (operands);
4818   DONE;
4819 ")
4820
4821 (define_expand "movqi"
4822   [(set (match_operand:QI 0 "general_operand" "")
4823         (match_operand:QI 1 "general_operand" ""))]
4824   "TARGET_EITHER"
4825   "
4826   if (TARGET_ARM)
4827     {
4828       /* Everything except mem = const or mem = mem can be done easily */
4829
4830       if (!no_new_pseudos)
4831         {
4832           if (GET_CODE (operands[1]) == CONST_INT)
4833             {
4834               rtx reg = gen_reg_rtx (SImode);
4835
4836               emit_insn (gen_movsi (reg, operands[1]));
4837               operands[1] = gen_lowpart (QImode, reg);
4838             }
4839           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4840             {
4841               rtx reg = gen_reg_rtx (SImode);
4842
4843               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4844               operands[1] = gen_lowpart (QImode, reg);
4845             }
4846           if (GET_CODE (operands[0]) == MEM)
4847             operands[1] = force_reg (QImode, operands[1]);
4848         }
4849     }
4850   else /* TARGET_THUMB */
4851     {
4852       if (!no_new_pseudos)
4853         {
4854           if (GET_CODE (operands[0]) != REG)
4855             operands[1] = force_reg (QImode, operands[1]);
4856
4857           /* ??? We shouldn't really get invalid addresses here, but this can
4858              happen if we are passed a SP (never OK for HImode/QImode) or
4859              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4860              HImode/QImode) relative address.  */
4861           /* ??? This should perhaps be fixed elsewhere, for instance, in
4862              fixup_stack_1, by checking for other kinds of invalid addresses,
4863              e.g. a bare reference to a virtual register.  This may confuse the
4864              alpha though, which must handle this case differently.  */
4865           if (GET_CODE (operands[0]) == MEM
4866               && !memory_address_p (GET_MODE (operands[0]),
4867                                      XEXP (operands[0], 0)))
4868             operands[0]
4869               = replace_equiv_address (operands[0],
4870                                        copy_to_reg (XEXP (operands[0], 0)));
4871           if (GET_CODE (operands[1]) == MEM
4872               && !memory_address_p (GET_MODE (operands[1]),
4873                                     XEXP (operands[1], 0)))
4874              operands[1]
4875                = replace_equiv_address (operands[1],
4876                                         copy_to_reg (XEXP (operands[1], 0)));
4877         }
4878       /* Handle loading a large integer during reload.  */
4879       else if (GET_CODE (operands[1]) == CONST_INT
4880                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4881         {
4882           /* Writing a constant to memory needs a scratch, which should
4883              be handled with SECONDARY_RELOADs.  */
4884           if (GET_CODE (operands[0]) != REG)
4885             abort ();
4886
4887           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4888           emit_insn (gen_movsi (operands[0], operands[1]));
4889           DONE;
4890        }
4891     }
4892   "
4893 )
4894
4895
4896 (define_insn "*arm_movqi_insn"
4897   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4898         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4899   "TARGET_ARM
4900    && (   register_operand (operands[0], QImode)
4901        || register_operand (operands[1], QImode))"
4902   "@
4903    mov%?\\t%0, %1
4904    mvn%?\\t%0, #%B1
4905    ldr%?b\\t%0, %1
4906    str%?b\\t%1, %0"
4907   [(set_attr "type" "*,*,load1,store1")
4908    (set_attr "predicable" "yes")]
4909 )
4910
4911 (define_insn "*thumb_movqi_insn"
4912   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4913         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4914   "TARGET_THUMB
4915    && (   register_operand (operands[0], QImode)
4916        || register_operand (operands[1], QImode))"
4917   "@
4918    add\\t%0, %1, #0
4919    ldrb\\t%0, %1
4920    strb\\t%1, %0
4921    mov\\t%0, %1
4922    mov\\t%0, %1
4923    mov\\t%0, %1"
4924   [(set_attr "length" "2")
4925    (set_attr "type" "*,load1,store1,*,*,*")
4926    (set_attr "pool_range" "*,32,*,*,*,*")]
4927 )
4928
4929 (define_expand "movsf"
4930   [(set (match_operand:SF 0 "general_operand" "")
4931         (match_operand:SF 1 "general_operand" ""))]
4932   "TARGET_EITHER"
4933   "
4934   if (TARGET_ARM)
4935     {
4936       if (GET_CODE (operands[0]) == MEM)
4937         operands[1] = force_reg (SFmode, operands[1]);
4938     }
4939   else /* TARGET_THUMB */
4940     {
4941       if (!no_new_pseudos)
4942         {
4943            if (GET_CODE (operands[0]) != REG)
4944              operands[1] = force_reg (SFmode, operands[1]);
4945         }
4946     }
4947   "
4948 )
4949
4950 (define_split
4951   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4952         (match_operand:SF 1 "immediate_operand" ""))]
4953   "TARGET_ARM
4954    && !(TARGET_HARD_FLOAT && TARGET_FPA)
4955    && reload_completed
4956    && GET_CODE (operands[1]) == CONST_DOUBLE"
4957   [(set (match_dup 2) (match_dup 3))]
4958   "
4959   operands[2] = gen_lowpart (SImode, operands[0]);
4960   operands[3] = gen_lowpart (SImode, operands[1]);
4961   if (operands[2] == 0 || operands[3] == 0)
4962     FAIL;
4963   "
4964 )
4965
4966 (define_insn "*arm_movsf_soft_insn"
4967   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4968         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4969   "TARGET_ARM
4970    && TARGET_SOFT_FLOAT
4971    && (GET_CODE (operands[0]) != MEM
4972        || register_operand (operands[1], SFmode))"
4973   "@
4974    mov%?\\t%0, %1
4975    ldr%?\\t%0, %1\\t%@ float
4976    str%?\\t%1, %0\\t%@ float"
4977   [(set_attr "length" "4,4,4")
4978    (set_attr "predicable" "yes")
4979    (set_attr "type" "*,load1,store1")
4980    (set_attr "pool_range" "*,4096,*")
4981    (set_attr "neg_pool_range" "*,4084,*")]
4982 )
4983
4984 ;;; ??? This should have alternatives for constants.
4985 (define_insn "*thumb_movsf_insn"
4986   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4987         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4988   "TARGET_THUMB
4989    && (   register_operand (operands[0], SFmode) 
4990        || register_operand (operands[1], SFmode))"
4991   "@
4992    add\\t%0, %1, #0
4993    ldmia\\t%1, {%0}
4994    stmia\\t%0, {%1}
4995    ldr\\t%0, %1
4996    str\\t%1, %0
4997    mov\\t%0, %1
4998    mov\\t%0, %1"
4999   [(set_attr "length" "2")
5000    (set_attr "type" "*,load1,store1,load1,store1,*,*")
5001    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5002 )
5003
5004 (define_expand "movdf"
5005   [(set (match_operand:DF 0 "general_operand" "")
5006         (match_operand:DF 1 "general_operand" ""))]
5007   "TARGET_EITHER"
5008   "
5009   if (TARGET_ARM)
5010     {
5011       if (GET_CODE (operands[0]) == MEM)
5012         operands[1] = force_reg (DFmode, operands[1]);
5013     }
5014   else /* TARGET_THUMB */
5015     {
5016       if (!no_new_pseudos)
5017         {
5018           if (GET_CODE (operands[0]) != REG)
5019             operands[1] = force_reg (DFmode, operands[1]);
5020         }
5021     }
5022   "
5023 )
5024
5025 ;; Reloading a df mode value stored in integer regs to memory can require a
5026 ;; scratch reg.
5027 (define_expand "reload_outdf"
5028   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5029    (match_operand:DF 1 "s_register_operand" "r")
5030    (match_operand:SI 2 "s_register_operand" "=&r")]
5031   "TARGET_ARM"
5032   "
5033   {
5034     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5035
5036     if (code == REG)
5037       operands[2] = XEXP (operands[0], 0);
5038     else if (code == POST_INC || code == PRE_DEC)
5039       {
5040         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5041         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5042         emit_insn (gen_movdi (operands[0], operands[1]));
5043         DONE;
5044       }
5045     else if (code == PRE_INC)
5046       {
5047         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5048
5049         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5050         operands[2] = reg;
5051       }
5052     else if (code == POST_DEC)
5053       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5054     else
5055       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5056                              XEXP (XEXP (operands[0], 0), 1)));
5057
5058     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5059                             operands[1]));
5060
5061     if (code == POST_DEC)
5062       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5063
5064     DONE;
5065   }"
5066 )
5067
5068 (define_insn "*movdf_soft_insn"
5069   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5070         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5071   "TARGET_ARM && TARGET_SOFT_FLOAT
5072   "
5073   "* return output_move_double (operands);"
5074   [(set_attr "length" "8,8,8")
5075    (set_attr "type" "*,load2,store2")
5076    (set_attr "pool_range" "1020")
5077    (set_attr "neg_pool_range" "1008")]
5078 )
5079
5080 ;;; ??? This should have alternatives for constants.
5081 ;;; ??? This was originally identical to the movdi_insn pattern.
5082 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5083 ;;; thumb_reorg with a memory reference.
5084 (define_insn "*thumb_movdf_insn"
5085   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5086         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5087   "TARGET_THUMB
5088    && (   register_operand (operands[0], DFmode)
5089        || register_operand (operands[1], DFmode))"
5090   "*
5091   switch (which_alternative)
5092     {
5093     default:
5094     case 0:
5095       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5096         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5097       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5098     case 1:
5099       return \"ldmia\\t%1, {%0, %H0}\";
5100     case 2:
5101       return \"stmia\\t%0, {%1, %H1}\";
5102     case 3:
5103       return thumb_load_double_from_address (operands);
5104     case 4:
5105       operands[2] = gen_rtx_MEM (SImode,
5106                                  plus_constant (XEXP (operands[0], 0), 4));
5107       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5108       return \"\";
5109     case 5:
5110       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5111         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5112       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5113     }
5114   "
5115   [(set_attr "length" "4,2,2,6,4,4")
5116    (set_attr "type" "*,load2,store2,load2,store2,*")
5117    (set_attr "pool_range" "*,*,*,1020,*,*")]
5118 )
5119
5120 ;; Vector Moves
5121 (define_expand "movv2si"
5122   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5123         (match_operand:V2SI 1 "general_operand" ""))]
5124   "TARGET_REALLY_IWMMXT"
5125 {
5126 })
5127
5128 (define_expand "movv4hi"
5129   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5130         (match_operand:V4HI 1 "general_operand" ""))]
5131   "TARGET_REALLY_IWMMXT"
5132 {
5133 })
5134
5135 (define_expand "movv8qi"
5136   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5137         (match_operand:V8QI 1 "general_operand" ""))]
5138   "TARGET_REALLY_IWMMXT"
5139 {
5140 })
5141 \f
5142
5143 ;; load- and store-multiple insns
5144 ;; The arm can load/store any set of registers, provided that they are in
5145 ;; ascending order; but that is beyond GCC so stick with what it knows.
5146
5147 (define_expand "load_multiple"
5148   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5149                           (match_operand:SI 1 "" ""))
5150                      (use (match_operand:SI 2 "" ""))])]
5151   "TARGET_ARM"
5152   "
5153   /* Support only fixed point registers.  */
5154   if (GET_CODE (operands[2]) != CONST_INT
5155       || INTVAL (operands[2]) > 14
5156       || INTVAL (operands[2]) < 2
5157       || GET_CODE (operands[1]) != MEM
5158       || GET_CODE (operands[0]) != REG
5159       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5160       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5161     FAIL;
5162
5163   operands[3]
5164     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5165                              force_reg (SImode, XEXP (operands[1], 0)),
5166                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5167                              MEM_IN_STRUCT_P(operands[1]),
5168                              MEM_SCALAR_P (operands[1]));
5169   "
5170 )
5171
5172 ;; Load multiple with write-back
5173
5174 (define_insn "*ldmsi_postinc4"
5175   [(match_parallel 0 "load_multiple_operation"
5176     [(set (match_operand:SI 1 "s_register_operand" "=r")
5177           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5178                    (const_int 16)))
5179      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5180           (mem:SI (match_dup 2)))
5181      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5182           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5183      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5184           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5185      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5186           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5187   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5188   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5189   [(set_attr "type" "load4")
5190    (set_attr "predicable" "yes")]
5191 )
5192
5193 (define_insn "*ldmsi_postinc3"
5194   [(match_parallel 0 "load_multiple_operation"
5195     [(set (match_operand:SI 1 "s_register_operand" "=r")
5196           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5197                    (const_int 12)))
5198      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5199           (mem:SI (match_dup 2)))
5200      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5201           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5202      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5203           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5204   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5205   "ldm%?ia\\t%1!, {%3, %4, %5}"
5206   [(set_attr "type" "load3")
5207    (set_attr "predicable" "yes")]
5208 )
5209
5210 (define_insn "*ldmsi_postinc2"
5211   [(match_parallel 0 "load_multiple_operation"
5212     [(set (match_operand:SI 1 "s_register_operand" "=r")
5213           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5214                    (const_int 8)))
5215      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5216           (mem:SI (match_dup 2)))
5217      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5218           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5219   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5220   "ldm%?ia\\t%1!, {%3, %4}"
5221   [(set_attr "type" "load2")
5222    (set_attr "predicable" "yes")]
5223 )
5224
5225 ;; Ordinary load multiple
5226
5227 (define_insn "*ldmsi4"
5228   [(match_parallel 0 "load_multiple_operation"
5229     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5230           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5231      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5232           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5233      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5234           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5235      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5236           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5237   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5238   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5239   [(set_attr "type" "load4")
5240    (set_attr "predicable" "yes")]
5241 )
5242
5243 (define_insn "*ldmsi3"
5244   [(match_parallel 0 "load_multiple_operation"
5245     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5246           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5247      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5248           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5249      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5250           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5251   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5252   "ldm%?ia\\t%1, {%2, %3, %4}"
5253   [(set_attr "type" "load3")
5254    (set_attr "predicable" "yes")]
5255 )
5256
5257 (define_insn "*ldmsi2"
5258   [(match_parallel 0 "load_multiple_operation"
5259     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5260           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5261      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5262           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5263   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5264   "ldm%?ia\\t%1, {%2, %3}"
5265   [(set_attr "type" "load2")
5266    (set_attr "predicable" "yes")]
5267 )
5268
5269 (define_expand "store_multiple"
5270   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5271                           (match_operand:SI 1 "" ""))
5272                      (use (match_operand:SI 2 "" ""))])]
5273   "TARGET_ARM"
5274   "
5275   /* Support only fixed point registers.  */
5276   if (GET_CODE (operands[2]) != CONST_INT
5277       || INTVAL (operands[2]) > 14
5278       || INTVAL (operands[2]) < 2
5279       || GET_CODE (operands[1]) != REG
5280       || GET_CODE (operands[0]) != MEM
5281       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5282       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5283     FAIL;
5284
5285   operands[3]
5286     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5287                               force_reg (SImode, XEXP (operands[0], 0)),
5288                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5289                               MEM_IN_STRUCT_P(operands[0]), 
5290                               MEM_SCALAR_P (operands[0]));
5291   "
5292 )
5293
5294 ;; Store multiple with write-back
5295
5296 (define_insn "*stmsi_postinc4"
5297   [(match_parallel 0 "store_multiple_operation"
5298     [(set (match_operand:SI 1 "s_register_operand" "=r")
5299           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5300                    (const_int 16)))
5301      (set (mem:SI (match_dup 2))
5302           (match_operand:SI 3 "arm_hard_register_operand" ""))
5303      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5304           (match_operand:SI 4 "arm_hard_register_operand" ""))
5305      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5306           (match_operand:SI 5 "arm_hard_register_operand" ""))
5307      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5308           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5309   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5310   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5311   [(set_attr "predicable" "yes")
5312    (set_attr "type" "store4")]
5313 )
5314
5315 (define_insn "*stmsi_postinc3"
5316   [(match_parallel 0 "store_multiple_operation"
5317     [(set (match_operand:SI 1 "s_register_operand" "=r")
5318           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5319                    (const_int 12)))
5320      (set (mem:SI (match_dup 2))
5321           (match_operand:SI 3 "arm_hard_register_operand" ""))
5322      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5323           (match_operand:SI 4 "arm_hard_register_operand" ""))
5324      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5325           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5326   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5327   "stm%?ia\\t%1!, {%3, %4, %5}"
5328   [(set_attr "predicable" "yes")
5329    (set_attr "type" "store3")]
5330 )
5331
5332 (define_insn "*stmsi_postinc2"
5333   [(match_parallel 0 "store_multiple_operation"
5334     [(set (match_operand:SI 1 "s_register_operand" "=r")
5335           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5336                    (const_int 8)))
5337      (set (mem:SI (match_dup 2))
5338           (match_operand:SI 3 "arm_hard_register_operand" ""))
5339      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5340           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5341   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5342   "stm%?ia\\t%1!, {%3, %4}"
5343   [(set_attr "predicable" "yes")
5344    (set_attr "type" "store2")]
5345 )
5346
5347 ;; Ordinary store multiple
5348
5349 (define_insn "*stmsi4"
5350   [(match_parallel 0 "store_multiple_operation"
5351     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5352           (match_operand:SI 2 "arm_hard_register_operand" ""))
5353      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5354           (match_operand:SI 3 "arm_hard_register_operand" ""))
5355      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5356           (match_operand:SI 4 "arm_hard_register_operand" ""))
5357      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5358           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5359   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5360   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5361   [(set_attr "predicable" "yes")
5362    (set_attr "type" "store4")]
5363 )
5364
5365 (define_insn "*stmsi3"
5366   [(match_parallel 0 "store_multiple_operation"
5367     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5368           (match_operand:SI 2 "arm_hard_register_operand" ""))
5369      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5370           (match_operand:SI 3 "arm_hard_register_operand" ""))
5371      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5372           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5373   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5374   "stm%?ia\\t%1, {%2, %3, %4}"
5375   [(set_attr "predicable" "yes")
5376    (set_attr "type" "store3")]
5377 )
5378
5379 (define_insn "*stmsi2"
5380   [(match_parallel 0 "store_multiple_operation"
5381     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5382           (match_operand:SI 2 "arm_hard_register_operand" ""))
5383      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5384           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5385   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5386   "stm%?ia\\t%1, {%2, %3}"
5387   [(set_attr "predicable" "yes")
5388    (set_attr "type" "store2")]
5389 )
5390
5391 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5392 ;; We could let this apply for blocks of less than this, but it clobbers so
5393 ;; many registers that there is then probably a better way.
5394
5395 (define_expand "movstrqi"
5396   [(match_operand:BLK 0 "general_operand" "")
5397    (match_operand:BLK 1 "general_operand" "")
5398    (match_operand:SI 2 "const_int_operand" "")
5399    (match_operand:SI 3 "const_int_operand" "")]
5400   "TARGET_EITHER"
5401   "
5402   if (TARGET_ARM)
5403     {
5404       if (arm_gen_movstrqi (operands))
5405         DONE;
5406       FAIL;
5407     }
5408   else /* TARGET_THUMB */
5409     {
5410       if (   INTVAL (operands[3]) != 4
5411           || INTVAL (operands[2]) > 48)
5412         FAIL;
5413
5414       thumb_expand_movstrqi (operands);
5415       DONE;
5416     }
5417   "
5418 )
5419
5420 ;; Thumb block-move insns
5421
5422 (define_insn "movmem12b"
5423   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5424         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5425    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5426         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5427    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5428         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5429    (set (match_operand:SI 0 "register_operand" "=l")
5430         (plus:SI (match_dup 2) (const_int 12)))
5431    (set (match_operand:SI 1 "register_operand" "=l")
5432         (plus:SI (match_dup 3) (const_int 12)))
5433    (clobber (match_scratch:SI 4 "=&l"))
5434    (clobber (match_scratch:SI 5 "=&l"))
5435    (clobber (match_scratch:SI 6 "=&l"))]
5436   "TARGET_THUMB"
5437   "* return thumb_output_move_mem_multiple (3, operands);"
5438   [(set_attr "length" "4")
5439    ; This isn't entirely accurate...  It loads as well, but in terms of
5440    ; scheduling the following insn it is better to consider it as a store
5441    (set_attr "type" "store3")]
5442 )
5443
5444 (define_insn "movmem8b"
5445   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5446         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5447    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5448         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5449    (set (match_operand:SI 0 "register_operand" "=l")
5450         (plus:SI (match_dup 2) (const_int 8)))
5451    (set (match_operand:SI 1 "register_operand" "=l")
5452         (plus:SI (match_dup 3) (const_int 8)))
5453    (clobber (match_scratch:SI 4 "=&l"))
5454    (clobber (match_scratch:SI 5 "=&l"))]
5455   "TARGET_THUMB"
5456   "* return thumb_output_move_mem_multiple (2, operands);"
5457   [(set_attr "length" "4")
5458    ; This isn't entirely accurate...  It loads as well, but in terms of
5459    ; scheduling the following insn it is better to consider it as a store
5460    (set_attr "type" "store2")]
5461 )
5462
5463 \f
5464
5465 ;; Compare & branch insns
5466 ;; The range calculations are based as follows:
5467 ;; For forward branches, the address calculation returns the address of
5468 ;; the next instruction.  This is 2 beyond the branch instruction.
5469 ;; For backward branches, the address calculation returns the address of
5470 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5471 ;; instruction for the shortest sequence, and 4 before the branch instruction
5472 ;; if we have to jump around an unconditional branch.
5473 ;; To the basic branch range the PC offset must be added (this is +4).
5474 ;; So for forward branches we have 
5475 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5476 ;; And for backward branches we have 
5477 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5478 ;;
5479 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5480 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5481
5482 (define_expand "cbranchsi4"
5483   [(set (pc) (if_then_else
5484               (match_operator 0 "arm_comparison_operator"
5485                [(match_operand:SI 1 "s_register_operand" "")
5486                 (match_operand:SI 2 "nonmemory_operand" "")])
5487               (label_ref (match_operand 3 "" ""))
5488               (pc)))]
5489   "TARGET_THUMB"
5490   "
5491   if (thumb_cmpneg_operand (operands[2], SImode))
5492     {
5493       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5494                                               operands[3], operands[0]));
5495       DONE;
5496     }
5497   if (!thumb_cmp_operand (operands[2], SImode))
5498     operands[2] = force_reg (SImode, operands[2]);
5499   ")
5500
5501 (define_insn "*cbranchsi4_insn"
5502   [(set (pc) (if_then_else
5503               (match_operator 0 "arm_comparison_operator"
5504                [(match_operand:SI 1 "s_register_operand" "l,*h")
5505                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5506               (label_ref (match_operand 3 "" ""))
5507               (pc)))]
5508   "TARGET_THUMB"
5509   "*
5510   output_asm_insn (\"cmp\\t%1, %2\", operands);
5511
5512   switch (get_attr_length (insn))
5513     {
5514     case 4:  return \"b%d0\\t%l3\";
5515     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5516     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5517     }
5518   "
5519   [(set (attr "far_jump")
5520         (if_then_else
5521             (eq_attr "length" "8")
5522             (const_string "yes")
5523             (const_string "no")))
5524    (set (attr "length") 
5525         (if_then_else
5526             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5527                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5528             (const_int 4)
5529             (if_then_else
5530                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5531                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5532                 (const_int 6)
5533                 (const_int 8))))]
5534 )
5535
5536 (define_insn "cbranchsi4_scratch"
5537   [(set (pc) (if_then_else
5538               (match_operator 4 "arm_comparison_operator"
5539                [(match_operand:SI 1 "s_register_operand" "l,0")
5540                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5541               (label_ref (match_operand 3 "" ""))
5542               (pc)))
5543    (clobber (match_scratch:SI 0 "=l,l"))]
5544   "TARGET_THUMB"
5545   "*
5546   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5547
5548   switch (get_attr_length (insn))
5549     {
5550     case 4:  return \"b%d4\\t%l3\";
5551     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5552     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5553     }
5554   "
5555   [(set (attr "far_jump")
5556         (if_then_else
5557             (eq_attr "length" "8")
5558             (const_string "yes")
5559             (const_string "no")))
5560    (set (attr "length") 
5561         (if_then_else
5562             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5563                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5564             (const_int 4)
5565             (if_then_else
5566                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5567                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5568                 (const_int 6)
5569                 (const_int 8))))]
5570 )
5571 (define_insn "*movsi_cbranchsi4"
5572   [(set (pc)
5573         (if_then_else
5574          (match_operator 3 "arm_comparison_operator"
5575           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5576            (const_int 0)])
5577          (label_ref (match_operand 2 "" ""))
5578          (pc)))
5579    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5580         (match_dup 1))]
5581   "TARGET_THUMB"
5582   "*{
5583   if (which_alternative == 0)
5584     output_asm_insn (\"cmp\t%0, #0\", operands);
5585   else if (which_alternative == 1)
5586     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5587   else
5588     {
5589       output_asm_insn (\"cmp\t%1, #0\", operands);
5590       if (which_alternative == 2)
5591         output_asm_insn (\"mov\t%0, %1\", operands);
5592       else
5593         output_asm_insn (\"str\t%1, %0\", operands);
5594     }
5595   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5596     {
5597     case 4:  return \"b%d3\\t%l2\";
5598     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5599     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5600     }
5601   }"
5602   [(set (attr "far_jump")
5603         (if_then_else
5604             (ior (and (gt (symbol_ref ("which_alternative"))
5605                           (const_int 1))
5606                       (eq_attr "length" "8"))
5607                  (eq_attr "length" "10"))
5608             (const_string "yes")
5609             (const_string "no")))
5610    (set (attr "length")
5611      (if_then_else
5612        (le (symbol_ref ("which_alternative"))
5613                        (const_int 1))
5614        (if_then_else
5615          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5616               (le (minus (match_dup 2) (pc)) (const_int 256)))
5617          (const_int 4)
5618          (if_then_else
5619            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5620                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5621            (const_int 6)
5622            (const_int 8)))
5623        (if_then_else
5624          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5625               (le (minus (match_dup 2) (pc)) (const_int 256)))
5626          (const_int 6)
5627          (if_then_else
5628            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5629                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5630            (const_int 8)
5631            (const_int 10)))))]
5632 )
5633
5634 (define_insn "*negated_cbranchsi4"
5635   [(set (pc)
5636         (if_then_else
5637          (match_operator 0 "arm_comparison_operator"
5638           [(match_operand:SI 1 "s_register_operand" "l")
5639            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5640          (label_ref (match_operand 3 "" ""))
5641          (pc)))]
5642   "TARGET_THUMB"
5643   "*
5644   output_asm_insn (\"cmn\\t%1, %2\", operands);
5645   switch (get_attr_length (insn))
5646     {
5647     case 4:  return \"b%d0\\t%l3\";
5648     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5649     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5650     }
5651   "
5652   [(set (attr "far_jump")
5653         (if_then_else
5654             (eq_attr "length" "8")
5655             (const_string "yes")
5656             (const_string "no")))
5657    (set (attr "length") 
5658         (if_then_else
5659             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5660                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5661             (const_int 4)
5662             (if_then_else
5663                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5664                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5665                 (const_int 6)
5666                 (const_int 8))))]
5667 )
5668
5669 (define_insn "*tbit_cbranch"
5670   [(set (pc)
5671         (if_then_else
5672          (match_operator 0 "equality_operator"
5673           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5674                             (const_int 1)
5675                             (match_operand:SI 2 "const_int_operand" "i"))
5676            (const_int 0)])
5677          (label_ref (match_operand 3 "" ""))
5678          (pc)))
5679    (clobber (match_scratch:SI 4 "=l"))]
5680   "TARGET_THUMB"
5681   "*
5682   {
5683   rtx op[3];
5684   op[0] = operands[4];
5685   op[1] = operands[1];
5686   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5687
5688   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5689   switch (get_attr_length (insn))
5690     {
5691     case 4:  return \"b%d0\\t%l3\";
5692     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5693     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5694     }
5695   }"
5696   [(set (attr "far_jump")
5697         (if_then_else
5698             (eq_attr "length" "8")
5699             (const_string "yes")
5700             (const_string "no")))
5701    (set (attr "length") 
5702         (if_then_else
5703             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5704                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5705             (const_int 4)
5706             (if_then_else
5707                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5708                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5709                 (const_int 6)
5710                 (const_int 8))))]
5711 )
5712   
5713 (define_insn "*tstsi3_cbranch"
5714   [(set (pc)
5715         (if_then_else
5716          (match_operator 3 "equality_operator"
5717           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5718                    (match_operand:SI 1 "s_register_operand" "l"))
5719            (const_int 0)])
5720          (label_ref (match_operand 2 "" ""))
5721          (pc)))]
5722   "TARGET_THUMB"
5723   "*
5724   {
5725   output_asm_insn (\"tst\\t%0, %1\", operands);
5726   switch (get_attr_length (insn))
5727     {
5728     case 4:  return \"b%d3\\t%l2\";
5729     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5730     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5731     }
5732   }"
5733   [(set (attr "far_jump")
5734         (if_then_else
5735             (eq_attr "length" "8")
5736             (const_string "yes")
5737             (const_string "no")))
5738    (set (attr "length") 
5739         (if_then_else
5740             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5741                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5742             (const_int 4)
5743             (if_then_else
5744                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5745                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5746                 (const_int 6)
5747                 (const_int 8))))]
5748 )
5749   
5750 (define_insn "*andsi3_cbranch"
5751   [(set (pc)
5752         (if_then_else
5753          (match_operator 5 "equality_operator"
5754           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5755                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5756            (const_int 0)])
5757          (label_ref (match_operand 4 "" ""))
5758          (pc)))
5759    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5760         (and:SI (match_dup 2) (match_dup 3)))
5761    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5762   "TARGET_THUMB"
5763   "*
5764   {
5765   if (which_alternative == 0)
5766     output_asm_insn (\"and\\t%0, %3\", operands);
5767   else if (which_alternative == 1)
5768     {
5769       output_asm_insn (\"and\\t%1, %3\", operands);
5770       output_asm_insn (\"mov\\t%0, %1\", operands);
5771     }
5772   else
5773     {
5774       output_asm_insn (\"and\\t%1, %3\", operands);
5775       output_asm_insn (\"str\\t%1, %0\", operands);
5776     }
5777
5778   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5779     {
5780     case 4:  return \"b%d5\\t%l4\";
5781     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5782     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5783     }
5784   }"
5785   [(set (attr "far_jump")
5786         (if_then_else
5787             (ior (and (eq (symbol_ref ("which_alternative"))
5788                           (const_int 0))
5789                       (eq_attr "length" "8"))
5790                  (eq_attr "length" "10"))
5791             (const_string "yes")
5792             (const_string "no")))
5793    (set (attr "length")
5794      (if_then_else
5795        (eq (symbol_ref ("which_alternative"))
5796                        (const_int 0))
5797        (if_then_else
5798          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5799               (le (minus (match_dup 4) (pc)) (const_int 256)))
5800          (const_int 4)
5801          (if_then_else
5802            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5803                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5804            (const_int 6)
5805            (const_int 8)))
5806        (if_then_else
5807          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5808               (le (minus (match_dup 4) (pc)) (const_int 256)))
5809          (const_int 6)
5810          (if_then_else
5811            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5812                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5813            (const_int 8)
5814            (const_int 10)))))]
5815 )
5816
5817 (define_insn "*orrsi3_cbranch_scratch"
5818   [(set (pc)
5819         (if_then_else
5820          (match_operator 4 "equality_operator"
5821           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5822                    (match_operand:SI 2 "s_register_operand" "l"))
5823            (const_int 0)])
5824          (label_ref (match_operand 3 "" ""))
5825          (pc)))
5826    (clobber (match_scratch:SI 0 "=l"))]
5827   "TARGET_THUMB"
5828   "*
5829   {
5830   output_asm_insn (\"orr\\t%0, %2\", operands);
5831   switch (get_attr_length (insn))
5832     {
5833     case 4:  return \"b%d4\\t%l3\";
5834     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5835     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5836     }
5837   }"
5838   [(set (attr "far_jump")
5839         (if_then_else
5840             (eq_attr "length" "8")
5841             (const_string "yes")
5842             (const_string "no")))
5843    (set (attr "length") 
5844         (if_then_else
5845             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5846                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5847             (const_int 4)
5848             (if_then_else
5849                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5850                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5851                 (const_int 6)
5852                 (const_int 8))))]
5853 )
5854   
5855 (define_insn "*orrsi3_cbranch"
5856   [(set (pc)
5857         (if_then_else
5858          (match_operator 5 "equality_operator"
5859           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5860                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5861            (const_int 0)])
5862          (label_ref (match_operand 4 "" ""))
5863          (pc)))
5864    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5865         (ior:SI (match_dup 2) (match_dup 3)))
5866    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5867   "TARGET_THUMB"
5868   "*
5869   {
5870   if (which_alternative == 0)
5871     output_asm_insn (\"orr\\t%0, %3\", operands);
5872   else if (which_alternative == 1)
5873     {
5874       output_asm_insn (\"orr\\t%1, %3\", operands);
5875       output_asm_insn (\"mov\\t%0, %1\", operands);
5876     }
5877   else
5878     {
5879       output_asm_insn (\"orr\\t%1, %3\", operands);
5880       output_asm_insn (\"str\\t%1, %0\", operands);
5881     }
5882
5883   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5884     {
5885     case 4:  return \"b%d5\\t%l4\";
5886     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5887     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5888     }
5889   }"
5890   [(set (attr "far_jump")
5891         (if_then_else
5892             (ior (and (eq (symbol_ref ("which_alternative"))
5893                           (const_int 0))
5894                       (eq_attr "length" "8"))
5895                  (eq_attr "length" "10"))
5896             (const_string "yes")
5897             (const_string "no")))
5898    (set (attr "length")
5899      (if_then_else
5900        (eq (symbol_ref ("which_alternative"))
5901                        (const_int 0))
5902        (if_then_else
5903          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5904               (le (minus (match_dup 4) (pc)) (const_int 256)))
5905          (const_int 4)
5906          (if_then_else
5907            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5908                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5909            (const_int 6)
5910            (const_int 8)))
5911        (if_then_else
5912          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5913               (le (minus (match_dup 4) (pc)) (const_int 256)))
5914          (const_int 6)
5915          (if_then_else
5916            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5917                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5918            (const_int 8)
5919            (const_int 10)))))]
5920 )
5921
5922 (define_insn "*xorsi3_cbranch_scratch"
5923   [(set (pc)
5924         (if_then_else
5925          (match_operator 4 "equality_operator"
5926           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
5927                    (match_operand:SI 2 "s_register_operand" "l"))
5928            (const_int 0)])
5929          (label_ref (match_operand 3 "" ""))
5930          (pc)))
5931    (clobber (match_scratch:SI 0 "=l"))]
5932   "TARGET_THUMB"
5933   "*
5934   {
5935   output_asm_insn (\"eor\\t%0, %2\", operands);
5936   switch (get_attr_length (insn))
5937     {
5938     case 4:  return \"b%d4\\t%l3\";
5939     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5940     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5941     }
5942   }"
5943   [(set (attr "far_jump")
5944         (if_then_else
5945             (eq_attr "length" "8")
5946             (const_string "yes")
5947             (const_string "no")))
5948    (set (attr "length") 
5949         (if_then_else
5950             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5951                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5952             (const_int 4)
5953             (if_then_else
5954                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5955                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5956                 (const_int 6)
5957                 (const_int 8))))]
5958 )
5959   
5960 (define_insn "*xorsi3_cbranch"
5961   [(set (pc)
5962         (if_then_else
5963          (match_operator 5 "equality_operator"
5964           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5965                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5966            (const_int 0)])
5967          (label_ref (match_operand 4 "" ""))
5968          (pc)))
5969    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5970         (xor:SI (match_dup 2) (match_dup 3)))
5971    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5972   "TARGET_THUMB"
5973   "*
5974   {
5975   if (which_alternative == 0)
5976     output_asm_insn (\"eor\\t%0, %3\", operands);
5977   else if (which_alternative == 1)
5978     {
5979       output_asm_insn (\"eor\\t%1, %3\", operands);
5980       output_asm_insn (\"mov\\t%0, %1\", operands);
5981     }
5982   else
5983     {
5984       output_asm_insn (\"eor\\t%1, %3\", operands);
5985       output_asm_insn (\"str\\t%1, %0\", operands);
5986     }
5987
5988   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5989     {
5990     case 4:  return \"b%d5\\t%l4\";
5991     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5992     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5993     }
5994   }"
5995   [(set (attr "far_jump")
5996         (if_then_else
5997             (ior (and (eq (symbol_ref ("which_alternative"))
5998                           (const_int 0))
5999                       (eq_attr "length" "8"))
6000                  (eq_attr "length" "10"))
6001             (const_string "yes")
6002             (const_string "no")))
6003    (set (attr "length")
6004      (if_then_else
6005        (eq (symbol_ref ("which_alternative"))
6006                        (const_int 0))
6007        (if_then_else
6008          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6009               (le (minus (match_dup 4) (pc)) (const_int 256)))
6010          (const_int 4)
6011          (if_then_else
6012            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6013                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6014            (const_int 6)
6015            (const_int 8)))
6016        (if_then_else
6017          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6018               (le (minus (match_dup 4) (pc)) (const_int 256)))
6019          (const_int 6)
6020          (if_then_else
6021            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6022                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6023            (const_int 8)
6024            (const_int 10)))))]
6025 )
6026
6027 (define_insn "*bicsi3_cbranch_scratch"
6028   [(set (pc)
6029         (if_then_else
6030          (match_operator 4 "equality_operator"
6031           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
6032                    (match_operand:SI 1 "s_register_operand" "0"))
6033            (const_int 0)])
6034          (label_ref (match_operand 3 "" ""))
6035          (pc)))
6036    (clobber (match_scratch:SI 0 "=l"))]
6037   "TARGET_THUMB"
6038   "*
6039   {
6040   output_asm_insn (\"bic\\t%0, %2\", operands);
6041   switch (get_attr_length (insn))
6042     {
6043     case 4:  return \"b%d4\\t%l3\";
6044     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6045     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6046     }
6047   }"
6048   [(set (attr "far_jump")
6049         (if_then_else
6050             (eq_attr "length" "8")
6051             (const_string "yes")
6052             (const_string "no")))
6053    (set (attr "length") 
6054         (if_then_else
6055             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6056                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6057             (const_int 4)
6058             (if_then_else
6059                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6060                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6061                 (const_int 6)
6062                 (const_int 8))))]
6063 )
6064   
6065 (define_insn "*bicsi3_cbranch"
6066   [(set (pc)
6067         (if_then_else
6068          (match_operator 5 "equality_operator"
6069           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6070                    (match_operand:SI 2 "s_register_operand" "0,1,1,1"))
6071            (const_int 0)])
6072          (label_ref (match_operand 4 "" ""))
6073          (pc)))
6074    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6075         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
6076    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6077   "TARGET_THUMB"
6078   "*
6079   {
6080   if (which_alternative == 0)
6081     output_asm_insn (\"bic\\t%0, %3\", operands);
6082   else if (which_alternative == 1)
6083     {
6084       output_asm_insn (\"bic\\t%1, %3\", operands);
6085       output_asm_insn (\"mov\\t%0, %1\", operands);
6086     }
6087   else
6088     {
6089       output_asm_insn (\"bic\\t%1, %3\", operands);
6090       output_asm_insn (\"str\\t%1, %0\", operands);
6091     }
6092
6093   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6094     {
6095     case 4:  return \"b%d5\\t%l4\";
6096     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6097     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6098     }
6099   }"
6100   [(set (attr "far_jump")
6101         (if_then_else
6102             (ior (and (eq (symbol_ref ("which_alternative"))
6103                           (const_int 0))
6104                       (eq_attr "length" "8"))
6105                  (eq_attr "length" "10"))
6106             (const_string "yes")
6107             (const_string "no")))
6108    (set (attr "length")
6109      (if_then_else
6110        (eq (symbol_ref ("which_alternative"))
6111                        (const_int 0))
6112        (if_then_else
6113          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6114               (le (minus (match_dup 4) (pc)) (const_int 256)))
6115          (const_int 4)
6116          (if_then_else
6117            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6118                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6119            (const_int 6)
6120            (const_int 8)))
6121        (if_then_else
6122          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6123               (le (minus (match_dup 4) (pc)) (const_int 256)))
6124          (const_int 6)
6125          (if_then_else
6126            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6127                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6128            (const_int 8)
6129            (const_int 10)))))]
6130 )
6131
6132 (define_insn "*cbranchne_decr1"
6133   [(set (pc)
6134         (if_then_else (match_operator 3 "equality_operator"
6135                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6136                         (const_int 0)])
6137                       (label_ref (match_operand 4 "" ""))
6138                       (pc)))
6139    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6140         (plus:SI (match_dup 2) (const_int -1)))
6141    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6142   "TARGET_THUMB"
6143   "*
6144    {
6145      rtx cond[2];
6146      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6147                                 ? GEU : LTU),
6148                                VOIDmode, operands[2], const1_rtx);
6149      cond[1] = operands[4];
6150
6151      if (which_alternative == 0)
6152        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6153      else if (which_alternative == 1)
6154        {
6155          /* We must provide an alternative for a hi reg because reload 
6156             cannot handle output reloads on a jump instruction, but we
6157             can't subtract into that.  Fortunately a mov from lo to hi
6158             does not clobber the condition codes.  */
6159          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6160          output_asm_insn (\"mov\\t%0, %1\", operands);
6161        }
6162      else
6163        {
6164          /* Similarly, but the target is memory.  */
6165          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6166          output_asm_insn (\"str\\t%1, %0\", operands);
6167        }
6168
6169      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6170        {
6171          case 4:
6172            output_asm_insn (\"b%d0\\t%l1\", cond);
6173            return \"\";
6174          case 6:
6175            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6176            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6177          default:
6178            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6179            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6180        }
6181    }
6182   "
6183   [(set (attr "far_jump")
6184         (if_then_else
6185             (ior (and (eq (symbol_ref ("which_alternative"))
6186                           (const_int 0))
6187                       (eq_attr "length" "8"))
6188                  (eq_attr "length" "10"))
6189             (const_string "yes")
6190             (const_string "no")))
6191    (set_attr_alternative "length"
6192       [
6193        ;; Alternative 0
6194        (if_then_else
6195          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6196               (le (minus (match_dup 4) (pc)) (const_int 256)))
6197          (const_int 4)
6198          (if_then_else
6199            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6200                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6201            (const_int 6)
6202            (const_int 8)))
6203        ;; Alternative 1
6204        (if_then_else
6205          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6206               (le (minus (match_dup 4) (pc)) (const_int 256)))
6207          (const_int 6)
6208          (if_then_else
6209            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6210                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6211            (const_int 8)
6212            (const_int 10)))
6213        ;; Alternative 2
6214        (if_then_else
6215          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6216               (le (minus (match_dup 4) (pc)) (const_int 256)))
6217          (const_int 6)
6218          (if_then_else
6219            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6220                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6221            (const_int 8)
6222            (const_int 10)))
6223        ;; Alternative 3
6224        (if_then_else
6225          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6226               (le (minus (match_dup 4) (pc)) (const_int 256)))
6227          (const_int 6)
6228          (if_then_else
6229            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6230                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6231            (const_int 8)
6232            (const_int 10)))])]
6233 )
6234
6235 (define_insn "*addsi3_cbranch"
6236   [(set (pc)
6237         (if_then_else
6238          (match_operator 4 "comparison_operator"
6239           [(plus:SI
6240             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6241             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6242            (const_int 0)])
6243          (label_ref (match_operand 5 "" ""))
6244          (pc)))
6245    (set
6246     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6247     (plus:SI (match_dup 2) (match_dup 3)))
6248    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6249   "TARGET_THUMB
6250    && (GET_CODE (operands[4]) == EQ
6251        || GET_CODE (operands[4]) == NE
6252        || GET_CODE (operands[4]) == GE
6253        || GET_CODE (operands[4]) == LT)"
6254   "*
6255    {
6256      rtx cond[3];
6257
6258      
6259      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6260      cond[1] = operands[2];
6261      cond[2] = operands[3];
6262
6263      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6264        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6265      else
6266        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6267
6268      if (which_alternative >= 3
6269          && which_alternative < 4)
6270        output_asm_insn (\"mov\\t%0, %1\", operands);
6271      else if (which_alternative >= 4)
6272        output_asm_insn (\"str\\t%1, %0\", operands);
6273
6274      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6275        {
6276          case 4:
6277            return \"b%d4\\t%l5\";
6278          case 6:
6279            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6280          default:
6281            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6282        }
6283    }
6284   "
6285   [(set (attr "far_jump")
6286         (if_then_else
6287             (ior (and (lt (symbol_ref ("which_alternative"))
6288                           (const_int 3))
6289                       (eq_attr "length" "8"))
6290                  (eq_attr "length" "10"))
6291             (const_string "yes")
6292             (const_string "no")))
6293    (set (attr "length")
6294      (if_then_else
6295        (lt (symbol_ref ("which_alternative"))
6296                        (const_int 3))
6297        (if_then_else
6298          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6299               (le (minus (match_dup 5) (pc)) (const_int 256)))
6300          (const_int 4)
6301          (if_then_else
6302            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6303                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6304            (const_int 6)
6305            (const_int 8)))
6306        (if_then_else
6307          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6308               (le (minus (match_dup 5) (pc)) (const_int 256)))
6309          (const_int 6)
6310          (if_then_else
6311            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6312                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6313            (const_int 8)
6314            (const_int 10)))))]
6315 )
6316
6317 (define_insn "*addsi3_cbranch_scratch"
6318   [(set (pc)
6319         (if_then_else
6320          (match_operator 3 "comparison_operator"
6321           [(plus:SI
6322             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6323             (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6324            (const_int 0)])
6325          (label_ref (match_operand 4 "" ""))
6326          (pc)))
6327    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6328   "TARGET_THUMB
6329    && (GET_CODE (operands[3]) == EQ
6330        || GET_CODE (operands[3]) == NE
6331        || GET_CODE (operands[3]) == GE
6332        || GET_CODE (operands[3]) == LT)"
6333   "*
6334    {
6335      switch (which_alternative)
6336        {
6337        case 0:
6338          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6339          break;
6340        case 1:
6341          output_asm_insn (\"cmn\t%1, %2\", operands);
6342          break;
6343        case 3:
6344          output_asm_insn (\"add\t%0, %1, %2\", operands);
6345          break;
6346        case 4:
6347          output_asm_insn (\"add\t%0, %0, %2\", operands);
6348          break;
6349        }
6350
6351      switch (get_attr_length (insn))
6352        {
6353          case 4:
6354            return \"b%d3\\t%l4\";
6355          case 6:
6356            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6357          default:
6358            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6359        }
6360    }
6361   "
6362   [(set (attr "far_jump")
6363         (if_then_else
6364             (eq_attr "length" "8")
6365             (const_string "yes")
6366             (const_string "no")))
6367    (set (attr "length")
6368        (if_then_else
6369          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6370               (le (minus (match_dup 4) (pc)) (const_int 256)))
6371          (const_int 4)
6372          (if_then_else
6373            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6374                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6375            (const_int 6)
6376            (const_int 8))))]
6377 )
6378
6379 (define_insn "*subsi3_cbranch"
6380   [(set (pc)
6381         (if_then_else
6382          (match_operator 4 "comparison_operator"
6383           [(minus:SI
6384             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6385             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6386            (const_int 0)])
6387          (label_ref (match_operand 5 "" ""))
6388          (pc)))
6389    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6390         (minus:SI (match_dup 2) (match_dup 3)))
6391    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6392   "TARGET_THUMB
6393    && (GET_CODE (operands[4]) == EQ
6394        || GET_CODE (operands[4]) == NE
6395        || GET_CODE (operands[4]) == GE
6396        || GET_CODE (operands[4]) == LT)"
6397   "*
6398    {
6399      if (which_alternative == 0)
6400        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6401      else if (which_alternative == 1)
6402        {
6403          /* We must provide an alternative for a hi reg because reload 
6404             cannot handle output reloads on a jump instruction, but we
6405             can't subtract into that.  Fortunately a mov from lo to hi
6406             does not clobber the condition codes.  */
6407          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6408          output_asm_insn (\"mov\\t%0, %1\", operands);
6409        }
6410      else
6411        {
6412          /* Similarly, but the target is memory.  */
6413          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6414          output_asm_insn (\"str\\t%1, %0\", operands);
6415        }
6416
6417      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6418        {
6419          case 4:
6420            return \"b%d4\\t%l5\";
6421          case 6:
6422            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6423          default:
6424            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6425        }
6426    }
6427   "
6428   [(set (attr "far_jump")
6429         (if_then_else
6430             (ior (and (eq (symbol_ref ("which_alternative"))
6431                           (const_int 0))
6432                       (eq_attr "length" "8"))
6433                  (eq_attr "length" "10"))
6434             (const_string "yes")
6435             (const_string "no")))
6436    (set (attr "length")
6437      (if_then_else
6438        (eq (symbol_ref ("which_alternative"))
6439                        (const_int 0))
6440        (if_then_else
6441          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6442               (le (minus (match_dup 5) (pc)) (const_int 256)))
6443          (const_int 4)
6444          (if_then_else
6445            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6446                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6447            (const_int 6)
6448            (const_int 8)))
6449        (if_then_else
6450          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6451               (le (minus (match_dup 5) (pc)) (const_int 256)))
6452          (const_int 6)
6453          (if_then_else
6454            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6455                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6456            (const_int 8)
6457            (const_int 10)))))]
6458 )
6459
6460 (define_insn "*subsi3_cbranch_scratch"
6461   [(set (pc)
6462         (if_then_else
6463          (match_operator 0 "arm_comparison_operator"
6464           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6465                      (match_operand:SI 2 "nonmemory_operand" "l"))
6466            (const_int 0)])
6467          (label_ref (match_operand 3 "" ""))
6468          (pc)))]
6469   "TARGET_THUMB
6470    && (GET_CODE (operands[0]) == EQ
6471        || GET_CODE (operands[0]) == NE
6472        || GET_CODE (operands[0]) == GE
6473        || GET_CODE (operands[0]) == LT)"
6474   "*
6475   output_asm_insn (\"cmp\\t%1, %2\", operands);
6476   switch (get_attr_length (insn))
6477     {
6478     case 4:  return \"b%d0\\t%l3\";
6479     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6480     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6481     }
6482   "
6483   [(set (attr "far_jump")
6484         (if_then_else
6485             (eq_attr "length" "8")
6486             (const_string "yes")
6487             (const_string "no")))
6488    (set (attr "length") 
6489         (if_then_else
6490             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6491                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6492             (const_int 4)
6493             (if_then_else
6494                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6495                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6496                 (const_int 6)
6497                 (const_int 8))))]
6498 )
6499
6500 ;; Comparison and test insns
6501
6502 (define_expand "cmpsi"
6503   [(match_operand:SI 0 "s_register_operand" "")
6504    (match_operand:SI 1 "arm_add_operand" "")]
6505   "TARGET_ARM"
6506   "{
6507     arm_compare_op0 = operands[0];
6508     arm_compare_op1 = operands[1];
6509     DONE;
6510   }"
6511 )
6512
6513 (define_expand "cmpsf"
6514   [(match_operand:SF 0 "s_register_operand" "")
6515    (match_operand:SF 1 "arm_float_compare_operand" "")]
6516   "TARGET_ARM && TARGET_HARD_FLOAT"
6517   "
6518   arm_compare_op0 = operands[0];
6519   arm_compare_op1 = operands[1];
6520   DONE;
6521   "
6522 )
6523
6524 (define_expand "cmpdf"
6525   [(match_operand:DF 0 "s_register_operand" "")
6526    (match_operand:DF 1 "arm_float_compare_operand" "")]
6527   "TARGET_ARM && TARGET_HARD_FLOAT"
6528   "
6529   arm_compare_op0 = operands[0];
6530   arm_compare_op1 = operands[1];
6531   DONE;
6532   "
6533 )
6534
6535 (define_insn "*arm_cmpsi_insn"
6536   [(set (reg:CC CC_REGNUM)
6537         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6538                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6539   "TARGET_ARM"
6540   "@
6541    cmp%?\\t%0, %1
6542    cmn%?\\t%0, #%n1"
6543   [(set_attr "conds" "set")]
6544 )
6545
6546 (define_insn "*cmpsi_shiftsi"
6547   [(set (reg:CC CC_REGNUM)
6548         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6549                     (match_operator:SI  3 "shift_operator"
6550                      [(match_operand:SI 1 "s_register_operand" "r")
6551                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6552   "TARGET_ARM"
6553   "cmp%?\\t%0, %1%S3"
6554   [(set_attr "conds" "set")
6555    (set_attr "shift" "1")
6556    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6557                       (const_string "alu_shift")
6558                       (const_string "alu_shift_reg")))]
6559 )
6560
6561 (define_insn "*cmpsi_shiftsi_swp"
6562   [(set (reg:CC_SWP CC_REGNUM)
6563         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6564                          [(match_operand:SI 1 "s_register_operand" "r")
6565                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6566                         (match_operand:SI 0 "s_register_operand" "r")))]
6567   "TARGET_ARM"
6568   "cmp%?\\t%0, %1%S3"
6569   [(set_attr "conds" "set")
6570    (set_attr "shift" "1")
6571    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6572                       (const_string "alu_shift")
6573                       (const_string "alu_shift_reg")))]
6574 )
6575
6576 (define_insn "*cmpsi_neg_shiftsi"
6577   [(set (reg:CC CC_REGNUM)
6578         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6579                     (neg:SI (match_operator:SI 3 "shift_operator"
6580                              [(match_operand:SI 1 "s_register_operand" "r")
6581                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6582   "TARGET_ARM"
6583   "cmn%?\\t%0, %1%S3"
6584   [(set_attr "conds" "set")
6585    (set_attr "shift" "1")
6586    (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
6587                       (const_string "alu_shift")
6588                       (const_string "alu_shift_reg")))]
6589 )
6590
6591 ;; Cirrus SF compare instruction
6592 (define_insn "*cirrus_cmpsf"
6593   [(set (reg:CCFP CC_REGNUM)
6594         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6595                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6596   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6597   "cfcmps%?\\tr15, %V0, %V1"
6598   [(set_attr "type"   "mav_farith")
6599    (set_attr "cirrus" "compare")]
6600 )
6601
6602 ;; Cirrus DF compare instruction
6603 (define_insn "*cirrus_cmpdf"
6604   [(set (reg:CCFP CC_REGNUM)
6605         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6606                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6607   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6608   "cfcmpd%?\\tr15, %V0, %V1"
6609   [(set_attr "type"   "mav_farith")
6610    (set_attr "cirrus" "compare")]
6611 )
6612
6613 ;; Cirrus DI compare instruction
6614 (define_expand "cmpdi"
6615   [(match_operand:DI 0 "cirrus_fp_register" "")
6616    (match_operand:DI 1 "cirrus_fp_register" "")]
6617   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6618   "{
6619      arm_compare_op0 = operands[0];
6620      arm_compare_op1 = operands[1];
6621      DONE;
6622    }")
6623
6624 (define_insn "*cirrus_cmpdi"
6625   [(set (reg:CC CC_REGNUM)
6626         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6627                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6628   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
6629   "cfcmp64%?\\tr15, %V0, %V1"
6630   [(set_attr "type"   "mav_farith")
6631    (set_attr "cirrus" "compare")]
6632 )
6633
6634 ; This insn allows redundant compares to be removed by cse, nothing should
6635 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6636 ; is deleted later on. The match_dup will match the mode here, so that
6637 ; mode changes of the condition codes aren't lost by this even though we don't
6638 ; specify what they are.
6639
6640 (define_insn "*deleted_compare"
6641   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6642   "TARGET_ARM"
6643   "\\t%@ deleted compare"
6644   [(set_attr "conds" "set")
6645    (set_attr "length" "0")]
6646 )
6647
6648 \f
6649 ;; Conditional branch insns
6650
6651 (define_expand "beq"
6652   [(set (pc)
6653         (if_then_else (eq (match_dup 1) (const_int 0))
6654                       (label_ref (match_operand 0 "" ""))
6655                       (pc)))]
6656   "TARGET_ARM"
6657   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6658 )
6659
6660 (define_expand "bne"
6661   [(set (pc)
6662         (if_then_else (ne (match_dup 1) (const_int 0))
6663                       (label_ref (match_operand 0 "" ""))
6664                       (pc)))]
6665   "TARGET_ARM"
6666   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6667 )
6668
6669 (define_expand "bgt"
6670   [(set (pc)
6671         (if_then_else (gt (match_dup 1) (const_int 0))
6672                       (label_ref (match_operand 0 "" ""))
6673                       (pc)))]
6674   "TARGET_ARM"
6675   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6676 )
6677
6678 (define_expand "ble"
6679   [(set (pc)
6680         (if_then_else (le (match_dup 1) (const_int 0))
6681                       (label_ref (match_operand 0 "" ""))
6682                       (pc)))]
6683   "TARGET_ARM"
6684   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6685 )
6686
6687 (define_expand "bge"
6688   [(set (pc)
6689         (if_then_else (ge (match_dup 1) (const_int 0))
6690                       (label_ref (match_operand 0 "" ""))
6691                       (pc)))]
6692   "TARGET_ARM"
6693   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6694 )
6695
6696 (define_expand "blt"
6697   [(set (pc)
6698         (if_then_else (lt (match_dup 1) (const_int 0))
6699                       (label_ref (match_operand 0 "" ""))
6700                       (pc)))]
6701   "TARGET_ARM"
6702   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6703 )
6704
6705 (define_expand "bgtu"
6706   [(set (pc)
6707         (if_then_else (gtu (match_dup 1) (const_int 0))
6708                       (label_ref (match_operand 0 "" ""))
6709                       (pc)))]
6710   "TARGET_ARM"
6711   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6712 )
6713
6714 (define_expand "bleu"
6715   [(set (pc)
6716         (if_then_else (leu (match_dup 1) (const_int 0))
6717                       (label_ref (match_operand 0 "" ""))
6718                       (pc)))]
6719   "TARGET_ARM"
6720   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6721 )
6722
6723 (define_expand "bgeu"
6724   [(set (pc)
6725         (if_then_else (geu (match_dup 1) (const_int 0))
6726                       (label_ref (match_operand 0 "" ""))
6727                       (pc)))]
6728   "TARGET_ARM"
6729   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6730 )
6731
6732 (define_expand "bltu"
6733   [(set (pc)
6734         (if_then_else (ltu (match_dup 1) (const_int 0))
6735                       (label_ref (match_operand 0 "" ""))
6736                       (pc)))]
6737   "TARGET_ARM"
6738   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6739 )
6740
6741 (define_expand "bunordered"
6742   [(set (pc)
6743         (if_then_else (unordered (match_dup 1) (const_int 0))
6744                       (label_ref (match_operand 0 "" ""))
6745                       (pc)))]
6746   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6747   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6748                                       arm_compare_op1);"
6749 )
6750
6751 (define_expand "bordered"
6752   [(set (pc)
6753         (if_then_else (ordered (match_dup 1) (const_int 0))
6754                       (label_ref (match_operand 0 "" ""))
6755                       (pc)))]
6756   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6757   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6758                                       arm_compare_op1);"
6759 )
6760
6761 (define_expand "bungt"
6762   [(set (pc)
6763         (if_then_else (ungt (match_dup 1) (const_int 0))
6764                       (label_ref (match_operand 0 "" ""))
6765                       (pc)))]
6766   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6767   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6768 )
6769
6770 (define_expand "bunlt"
6771   [(set (pc)
6772         (if_then_else (unlt (match_dup 1) (const_int 0))
6773                       (label_ref (match_operand 0 "" ""))
6774                       (pc)))]
6775   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6776   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6777 )
6778
6779 (define_expand "bunge"
6780   [(set (pc)
6781         (if_then_else (unge (match_dup 1) (const_int 0))
6782                       (label_ref (match_operand 0 "" ""))
6783                       (pc)))]
6784   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6785   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6786 )
6787
6788 (define_expand "bunle"
6789   [(set (pc)
6790         (if_then_else (unle (match_dup 1) (const_int 0))
6791                       (label_ref (match_operand 0 "" ""))
6792                       (pc)))]
6793   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6794   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6795 )
6796
6797 ;; The following two patterns need two branch instructions, since there is
6798 ;; no single instruction that will handle all cases.
6799 (define_expand "buneq"
6800   [(set (pc)
6801         (if_then_else (uneq (match_dup 1) (const_int 0))
6802                       (label_ref (match_operand 0 "" ""))
6803                       (pc)))]
6804   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6805   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6806 )
6807
6808 (define_expand "bltgt"
6809   [(set (pc)
6810         (if_then_else (ltgt (match_dup 1) (const_int 0))
6811                       (label_ref (match_operand 0 "" ""))
6812                       (pc)))]
6813   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6814   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6815 )
6816
6817 ;;
6818 ;; Patterns to match conditional branch insns.
6819 ;;
6820
6821 ; Special pattern to match UNEQ.
6822 (define_insn "*arm_buneq"
6823   [(set (pc)
6824         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6825                       (label_ref (match_operand 0 "" ""))
6826                       (pc)))]
6827   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6828   "*
6829   if (arm_ccfsm_state != 0)
6830     abort ();
6831
6832   return \"bvs\\t%l0\;beq\\t%l0\";
6833   "
6834   [(set_attr "conds" "jump_clob")
6835    (set_attr "length" "8")]
6836 )
6837
6838 ; Special pattern to match LTGT.
6839 (define_insn "*arm_bltgt"
6840   [(set (pc)
6841         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6842                       (label_ref (match_operand 0 "" ""))
6843                       (pc)))]
6844   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6845   "*
6846   if (arm_ccfsm_state != 0)
6847     abort ();
6848
6849   return \"bmi\\t%l0\;bgt\\t%l0\";
6850   "
6851   [(set_attr "conds" "jump_clob")
6852    (set_attr "length" "8")]
6853 )
6854
6855 (define_insn "*arm_cond_branch"
6856   [(set (pc)
6857         (if_then_else (match_operator 1 "arm_comparison_operator"
6858                        [(match_operand 2 "cc_register" "") (const_int 0)])
6859                       (label_ref (match_operand 0 "" ""))
6860                       (pc)))]
6861   "TARGET_ARM"
6862   "*
6863   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6864     {
6865       arm_ccfsm_state += 2;
6866       return \"\";
6867     }
6868   return \"b%d1\\t%l0\";
6869   "
6870   [(set_attr "conds" "use")
6871    (set_attr "type" "branch")]
6872 )
6873
6874 ; Special pattern to match reversed UNEQ.
6875 (define_insn "*arm_buneq_reversed"
6876   [(set (pc)
6877         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6878                       (pc)
6879                       (label_ref (match_operand 0 "" ""))))]
6880   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6881   "*
6882   if (arm_ccfsm_state != 0)
6883     abort ();
6884
6885   return \"bmi\\t%l0\;bgt\\t%l0\";
6886   "
6887   [(set_attr "conds" "jump_clob")
6888    (set_attr "length" "8")]
6889 )
6890
6891 ; Special pattern to match reversed LTGT.
6892 (define_insn "*arm_bltgt_reversed"
6893   [(set (pc)
6894         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6895                       (pc)
6896                       (label_ref (match_operand 0 "" ""))))]
6897   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
6898   "*
6899   if (arm_ccfsm_state != 0)
6900     abort ();
6901
6902   return \"bvs\\t%l0\;beq\\t%l0\";
6903   "
6904   [(set_attr "conds" "jump_clob")
6905    (set_attr "length" "8")]
6906 )
6907
6908 (define_insn "*arm_cond_branch_reversed"
6909   [(set (pc)
6910         (if_then_else (match_operator 1 "arm_comparison_operator"
6911                        [(match_operand 2 "cc_register" "") (const_int 0)])
6912                       (pc)
6913                       (label_ref (match_operand 0 "" ""))))]
6914   "TARGET_ARM"
6915   "*
6916   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6917     {
6918       arm_ccfsm_state += 2;
6919       return \"\";
6920     }
6921   return \"b%D1\\t%l0\";
6922   "
6923   [(set_attr "conds" "use")
6924    (set_attr "type" "branch")]
6925 )
6926
6927 \f
6928
6929 ; scc insns
6930
6931 (define_expand "seq"
6932   [(set (match_operand:SI 0 "s_register_operand" "")
6933         (eq:SI (match_dup 1) (const_int 0)))]
6934   "TARGET_ARM"
6935   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6936 )
6937
6938 (define_expand "sne"
6939   [(set (match_operand:SI 0 "s_register_operand" "")
6940         (ne:SI (match_dup 1) (const_int 0)))]
6941   "TARGET_ARM"
6942   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6943 )
6944
6945 (define_expand "sgt"
6946   [(set (match_operand:SI 0 "s_register_operand" "")
6947         (gt:SI (match_dup 1) (const_int 0)))]
6948   "TARGET_ARM"
6949   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6950 )
6951
6952 (define_expand "sle"
6953   [(set (match_operand:SI 0 "s_register_operand" "")
6954         (le:SI (match_dup 1) (const_int 0)))]
6955   "TARGET_ARM"
6956   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6957 )
6958
6959 (define_expand "sge"
6960   [(set (match_operand:SI 0 "s_register_operand" "")
6961         (ge:SI (match_dup 1) (const_int 0)))]
6962   "TARGET_ARM"
6963   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6964 )
6965
6966 (define_expand "slt"
6967   [(set (match_operand:SI 0 "s_register_operand" "")
6968         (lt:SI (match_dup 1) (const_int 0)))]
6969   "TARGET_ARM"
6970   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6971 )
6972
6973 (define_expand "sgtu"
6974   [(set (match_operand:SI 0 "s_register_operand" "")
6975         (gtu:SI (match_dup 1) (const_int 0)))]
6976   "TARGET_ARM"
6977   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6978 )
6979
6980 (define_expand "sleu"
6981   [(set (match_operand:SI 0 "s_register_operand" "")
6982         (leu:SI (match_dup 1) (const_int 0)))]
6983   "TARGET_ARM"
6984   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6985 )
6986
6987 (define_expand "sgeu"
6988   [(set (match_operand:SI 0 "s_register_operand" "")
6989         (geu:SI (match_dup 1) (const_int 0)))]
6990   "TARGET_ARM"
6991   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6992 )
6993
6994 (define_expand "sltu"
6995   [(set (match_operand:SI 0 "s_register_operand" "")
6996         (ltu:SI (match_dup 1) (const_int 0)))]
6997   "TARGET_ARM"
6998   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6999 )
7000
7001 (define_expand "sunordered"
7002   [(set (match_operand:SI 0 "s_register_operand" "")
7003         (unordered:SI (match_dup 1) (const_int 0)))]
7004   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7005   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
7006                                       arm_compare_op1);"
7007 )
7008
7009 (define_expand "sordered"
7010   [(set (match_operand:SI 0 "s_register_operand" "")
7011         (ordered:SI (match_dup 1) (const_int 0)))]
7012   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7013   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
7014                                       arm_compare_op1);"
7015 )
7016
7017 (define_expand "sungt"
7018   [(set (match_operand:SI 0 "s_register_operand" "")
7019         (ungt:SI (match_dup 1) (const_int 0)))]
7020   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7021   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
7022                                       arm_compare_op1);"
7023 )
7024
7025 (define_expand "sunge"
7026   [(set (match_operand:SI 0 "s_register_operand" "")
7027         (unge:SI (match_dup 1) (const_int 0)))]
7028   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7029   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
7030                                       arm_compare_op1);"
7031 )
7032
7033 (define_expand "sunlt"
7034   [(set (match_operand:SI 0 "s_register_operand" "")
7035         (unlt:SI (match_dup 1) (const_int 0)))]
7036   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7037   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
7038                                       arm_compare_op1);"
7039 )
7040
7041 (define_expand "sunle"
7042   [(set (match_operand:SI 0 "s_register_operand" "")
7043         (unle:SI (match_dup 1) (const_int 0)))]
7044   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7045   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
7046                                       arm_compare_op1);"
7047 )
7048
7049 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
7050 ;;; simple ARM instructions. 
7051 ;
7052 ; (define_expand "suneq"
7053 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7054 ;       (uneq:SI (match_dup 1) (const_int 0)))]
7055 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7056 ;   "abort ();"
7057 ; )
7058 ;
7059 ; (define_expand "sltgt"
7060 ;   [(set (match_operand:SI 0 "s_register_operand" "")
7061 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
7062 ;   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
7063 ;   "abort ();"
7064 ; )
7065
7066 (define_insn "*mov_scc"
7067   [(set (match_operand:SI 0 "s_register_operand" "=r")
7068         (match_operator:SI 1 "arm_comparison_operator"
7069          [(match_operand 2 "cc_register" "") (const_int 0)]))]
7070   "TARGET_ARM"
7071   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
7072   [(set_attr "conds" "use")
7073    (set_attr "length" "8")]
7074 )
7075
7076 (define_insn "*mov_negscc"
7077   [(set (match_operand:SI 0 "s_register_operand" "=r")
7078         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
7079                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7080   "TARGET_ARM"
7081   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
7082   [(set_attr "conds" "use")
7083    (set_attr "length" "8")]
7084 )
7085
7086 (define_insn "*mov_notscc"
7087   [(set (match_operand:SI 0 "s_register_operand" "=r")
7088         (not:SI (match_operator:SI 1 "arm_comparison_operator"
7089                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
7090   "TARGET_ARM"
7091   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
7092   [(set_attr "conds" "use")
7093    (set_attr "length" "8")]
7094 )
7095
7096 \f
7097 ;; Conditional move insns
7098
7099 (define_expand "movsicc"
7100   [(set (match_operand:SI 0 "s_register_operand" "")
7101         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
7102                          (match_operand:SI 2 "arm_not_operand" "")
7103                          (match_operand:SI 3 "arm_not_operand" "")))]
7104   "TARGET_ARM"
7105   "
7106   {
7107     enum rtx_code code = GET_CODE (operands[1]);
7108     rtx ccreg;
7109
7110     if (code == UNEQ || code == LTGT)
7111       FAIL;
7112
7113     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7114     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7115   }"
7116 )
7117
7118 (define_expand "movsfcc"
7119   [(set (match_operand:SF 0 "s_register_operand" "")
7120         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7121                          (match_operand:SF 2 "s_register_operand" "")
7122                          (match_operand:SF 3 "nonmemory_operand" "")))]
7123   "TARGET_ARM"
7124   "
7125   {
7126     enum rtx_code code = GET_CODE (operands[1]);
7127     rtx ccreg;
7128
7129     if (code == UNEQ || code == LTGT)
7130       FAIL;
7131
7132     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7133        Otherwise, ensure it is a valid FP add operand */
7134     if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
7135         || (!arm_float_add_operand (operands[3], SFmode)))
7136       operands[3] = force_reg (SFmode, operands[3]);
7137
7138     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7139     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7140   }"
7141 )
7142
7143 (define_expand "movdfcc"
7144   [(set (match_operand:DF 0 "s_register_operand" "")
7145         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7146                          (match_operand:DF 2 "s_register_operand" "")
7147                          (match_operand:DF 3 "arm_float_add_operand" "")))]
7148   "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
7149   "
7150   {
7151     enum rtx_code code = GET_CODE (operands[1]);
7152     rtx ccreg;
7153
7154     if (code == UNEQ || code == LTGT)
7155       FAIL;
7156
7157     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7158     operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
7159   }"
7160 )
7161
7162 (define_insn "*movsicc_insn"
7163   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7164         (if_then_else:SI
7165          (match_operator 3 "arm_comparison_operator"
7166           [(match_operand 4 "cc_register" "") (const_int 0)])
7167          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7168          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7169   "TARGET_ARM"
7170   "@
7171    mov%D3\\t%0, %2
7172    mvn%D3\\t%0, #%B2
7173    mov%d3\\t%0, %1
7174    mvn%d3\\t%0, #%B1
7175    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7176    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7177    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7178    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7179   [(set_attr "length" "4,4,4,4,8,8,8,8")
7180    (set_attr "conds" "use")]
7181 )
7182
7183 (define_insn "*movsfcc_soft_insn"
7184   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7185         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7186                           [(match_operand 4 "cc_register" "") (const_int 0)])
7187                          (match_operand:SF 1 "s_register_operand" "0,r")
7188                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7189   "TARGET_ARM && TARGET_SOFT_FLOAT"
7190   "@
7191    mov%D3\\t%0, %2
7192    mov%d3\\t%0, %1"
7193   [(set_attr "conds" "use")]
7194 )
7195
7196 \f
7197 ;; Jump and linkage insns
7198
7199 (define_expand "jump"
7200   [(set (pc)
7201         (label_ref (match_operand 0 "" "")))]
7202   "TARGET_EITHER"
7203   ""
7204 )
7205
7206 (define_insn "*arm_jump"
7207   [(set (pc)
7208         (label_ref (match_operand 0 "" "")))]
7209   "TARGET_ARM"
7210   "*
7211   {
7212     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7213       {
7214         arm_ccfsm_state += 2;
7215         return \"\";
7216       }
7217     return \"b%?\\t%l0\";
7218   }
7219   "
7220   [(set_attr "predicable" "yes")]
7221 )
7222
7223 (define_insn "*thumb_jump"
7224   [(set (pc)
7225         (label_ref (match_operand 0 "" "")))]
7226   "TARGET_THUMB"
7227   "*
7228   if (get_attr_length (insn) == 2)
7229     return \"b\\t%l0\";
7230   return \"bl\\t%l0\\t%@ far jump\";
7231   "
7232   [(set (attr "far_jump")
7233         (if_then_else
7234             (eq_attr "length" "4")
7235             (const_string "yes")
7236             (const_string "no")))
7237    (set (attr "length") 
7238         (if_then_else
7239             (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
7240                  (le (minus (match_dup 0) (pc)) (const_int 2048)))
7241             (const_int 2)
7242             (const_int 4)))]
7243 )
7244
7245 (define_expand "call"
7246   [(parallel [(call (match_operand 0 "memory_operand" "")
7247                     (match_operand 1 "general_operand" ""))
7248               (use (match_operand 2 "" ""))
7249               (clobber (reg:SI LR_REGNUM))])]
7250   "TARGET_EITHER"
7251   "
7252   {
7253     rtx callee;
7254     
7255     /* In an untyped call, we can get NULL for operand 2.  */
7256     if (operands[2] == NULL_RTX)
7257       operands[2] = const0_rtx;
7258       
7259     /* This is to decide if we should generate indirect calls by loading the
7260        32 bit address of the callee into a register before performing the
7261        branch and link.  operand[2] encodes the long_call/short_call
7262        attribute of the function being called.  This attribute is set whenever
7263        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7264        is used, and the short_call attribute can also be set if function is
7265        declared as static or if it has already been defined in the current
7266        compilation unit.  See arm.c and arm.h for info about this.  The third
7267        parameter to arm_is_longcall_p is used to tell it which pattern
7268        invoked it.  */
7269     callee  = XEXP (operands[0], 0);
7270     
7271     if (GET_CODE (callee) != REG
7272        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7273       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7274   }"
7275 )
7276
7277 (define_insn "*call_reg"
7278   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7279          (match_operand 1 "" ""))
7280    (use (match_operand 2 "" ""))
7281    (clobber (reg:SI LR_REGNUM))]
7282   "TARGET_ARM"
7283   "*
7284   return output_call (operands);
7285   "
7286   ;; length is worst case, normally it is only two
7287   [(set_attr "length" "12")
7288    (set_attr "type" "call")]
7289 )
7290
7291 (define_insn "*call_mem"
7292   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7293          (match_operand 1 "" ""))
7294    (use (match_operand 2 "" ""))
7295    (clobber (reg:SI LR_REGNUM))]
7296   "TARGET_ARM"
7297   "*
7298   return output_call_mem (operands);
7299   "
7300   [(set_attr "length" "12")
7301    (set_attr "type" "call")]
7302 )
7303
7304 (define_insn "*call_indirect"
7305   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7306          (match_operand 1 "" ""))
7307    (use (match_operand 2 "" ""))
7308    (clobber (reg:SI LR_REGNUM))]
7309   "TARGET_THUMB"
7310   "*
7311   {
7312     if (TARGET_CALLER_INTERWORKING)
7313       return \"bl\\t%__interwork_call_via_%0\";
7314     else
7315       return \"bl\\t%__call_via_%0\";
7316   }"
7317   [(set_attr "type" "call")]
7318 )
7319
7320 (define_insn "*call_value_indirect"
7321   [(set (match_operand 0 "" "")
7322         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7323               (match_operand 2 "" "")))
7324    (use (match_operand 3 "" ""))
7325    (clobber (reg:SI LR_REGNUM))]
7326   "TARGET_THUMB"
7327   "*
7328   {
7329     if (TARGET_CALLER_INTERWORKING)
7330       return \"bl\\t%__interwork_call_via_%1\";
7331     else
7332       return \"bl\\t%__call_via_%1\";
7333   }"
7334   [(set_attr "type" "call")]
7335 )
7336
7337 (define_expand "call_value"
7338   [(parallel [(set (match_operand       0 "" "")
7339                    (call (match_operand 1 "memory_operand" "")
7340                          (match_operand 2 "general_operand" "")))
7341               (use (match_operand 3 "" ""))
7342               (clobber (reg:SI LR_REGNUM))])]
7343   "TARGET_EITHER"
7344   "
7345   {
7346     rtx callee = XEXP (operands[1], 0);
7347     
7348     /* In an untyped call, we can get NULL for operand 2.  */
7349     if (operands[3] == 0)
7350       operands[3] = const0_rtx;
7351       
7352     /* See the comment in define_expand \"call\".  */
7353     if (GET_CODE (callee) != REG
7354         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7355       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7356   }"
7357 )
7358
7359 (define_insn "*call_value_reg"
7360   [(set (match_operand 0 "" "")
7361         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7362               (match_operand 2 "" "")))
7363    (use (match_operand 3 "" ""))
7364    (clobber (reg:SI LR_REGNUM))]
7365   "TARGET_ARM"
7366   "*
7367   return output_call (&operands[1]);
7368   "
7369   [(set_attr "length" "12")
7370    (set_attr "type" "call")]
7371 )
7372
7373 (define_insn "*call_value_mem"
7374   [(set (match_operand 0 "" "")
7375         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7376               (match_operand 2 "" "")))
7377    (use (match_operand 3 "" ""))
7378    (clobber (reg:SI LR_REGNUM))]
7379   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7380   "*
7381   return output_call_mem (&operands[1]);
7382   "
7383   [(set_attr "length" "12")
7384    (set_attr "type" "call")]
7385 )
7386
7387 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7388 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7389
7390 (define_insn "*call_symbol"
7391   [(call (mem:SI (match_operand:SI 0 "" ""))
7392          (match_operand 1 "" ""))
7393    (use (match_operand 2 "" ""))
7394    (clobber (reg:SI LR_REGNUM))]
7395   "TARGET_ARM
7396    && (GET_CODE (operands[0]) == SYMBOL_REF)
7397    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7398   "*
7399   {
7400     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7401   }"
7402   [(set_attr "type" "call")]
7403 )
7404
7405 (define_insn "*call_value_symbol"
7406   [(set (match_operand 0 "s_register_operand" "")
7407         (call (mem:SI (match_operand:SI 1 "" ""))
7408         (match_operand:SI 2 "" "")))
7409    (use (match_operand 3 "" ""))
7410    (clobber (reg:SI LR_REGNUM))]
7411   "TARGET_ARM
7412    && (GET_CODE (operands[1]) == SYMBOL_REF)
7413    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7414   "*
7415   {
7416     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7417   }"
7418   [(set_attr "type" "call")]
7419 )
7420
7421 (define_insn "*call_insn"
7422   [(call (mem:SI (match_operand:SI 0 "" ""))
7423          (match_operand:SI 1 "" ""))
7424    (use (match_operand 2 "" ""))
7425    (clobber (reg:SI LR_REGNUM))]
7426   "TARGET_THUMB
7427    && GET_CODE (operands[0]) == SYMBOL_REF
7428    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7429   "bl\\t%a0"
7430   [(set_attr "length" "4")
7431    (set_attr "type" "call")]
7432 )
7433
7434 (define_insn "*call_value_insn"
7435   [(set (match_operand 0 "register_operand" "")
7436         (call (mem:SI (match_operand 1 "" ""))
7437               (match_operand 2 "" "")))
7438    (use (match_operand 3 "" ""))
7439    (clobber (reg:SI LR_REGNUM))]
7440   "TARGET_THUMB
7441    && GET_CODE (operands[1]) == SYMBOL_REF
7442    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7443   "bl\\t%a1"
7444   [(set_attr "length" "4")
7445    (set_attr "type" "call")]
7446 )
7447
7448 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7449 (define_expand "sibcall"
7450   [(parallel [(call (match_operand 0 "memory_operand" "")
7451                     (match_operand 1 "general_operand" ""))
7452               (return)
7453               (use (match_operand 2 "" ""))])]
7454   "TARGET_ARM"
7455   "
7456   {
7457     if (operands[2] == NULL_RTX)
7458       operands[2] = const0_rtx;
7459   }"
7460 )
7461
7462 (define_expand "sibcall_value"
7463   [(parallel [(set (match_operand 0 "register_operand" "")
7464                    (call (match_operand 1 "memory_operand" "")
7465                          (match_operand 2 "general_operand" "")))
7466               (return)
7467               (use (match_operand 3 "" ""))])]
7468   "TARGET_ARM"
7469   "
7470   {
7471     if (operands[3] == NULL_RTX)
7472       operands[3] = const0_rtx;
7473   }"
7474 )
7475
7476 (define_insn "*sibcall_insn"
7477  [(call (mem:SI (match_operand:SI 0 "" "X"))
7478         (match_operand 1 "" ""))
7479   (return)
7480   (use (match_operand 2 "" ""))]
7481   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7482   "*
7483   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7484   "
7485   [(set_attr "type" "call")]
7486 )
7487
7488 (define_insn "*sibcall_value_insn"
7489  [(set (match_operand 0 "s_register_operand" "")
7490        (call (mem:SI (match_operand:SI 1 "" "X"))
7491              (match_operand 2 "" "")))
7492   (return)
7493   (use (match_operand 3 "" ""))]
7494   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7495   "*
7496   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7497   "
7498   [(set_attr "type" "call")]
7499 )
7500
7501 ;; Often the return insn will be the same as loading from memory, so set attr
7502 (define_insn "return"
7503   [(return)]
7504   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7505   "*
7506   {
7507     if (arm_ccfsm_state == 2)
7508       {
7509         arm_ccfsm_state += 2;
7510         return \"\";
7511       }
7512     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7513   }"
7514   [(set_attr "type" "load1")
7515    (set_attr "length" "12")
7516    (set_attr "predicable" "yes")]
7517 )
7518
7519 (define_insn "*cond_return"
7520   [(set (pc)
7521         (if_then_else (match_operator 0 "arm_comparison_operator"
7522                        [(match_operand 1 "cc_register" "") (const_int 0)])
7523                       (return)
7524                       (pc)))]
7525   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7526   "*
7527   {
7528     if (arm_ccfsm_state == 2)
7529       {
7530         arm_ccfsm_state += 2;
7531         return \"\";
7532       }
7533     return output_return_instruction (operands[0], TRUE, FALSE);
7534   }"
7535   [(set_attr "conds" "use")
7536    (set_attr "length" "12")
7537    (set_attr "type" "load1")]
7538 )
7539
7540 (define_insn "*cond_return_inverted"
7541   [(set (pc)
7542         (if_then_else (match_operator 0 "arm_comparison_operator"
7543                        [(match_operand 1 "cc_register" "") (const_int 0)])
7544                       (pc)
7545                       (return)))]
7546   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7547   "*
7548   {
7549     if (arm_ccfsm_state == 2)
7550       {
7551         arm_ccfsm_state += 2;
7552         return \"\";
7553       }
7554     return output_return_instruction (operands[0], TRUE, TRUE);
7555   }"
7556   [(set_attr "conds" "use")
7557    (set_attr "type" "load1")]
7558 )
7559
7560 ;; Generate a sequence of instructions to determine if the processor is
7561 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7562 ;; mask.
7563
7564 (define_expand "return_addr_mask"
7565   [(set (match_dup 1)
7566       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7567                        (const_int 0)))
7568    (set (match_operand:SI 0 "s_register_operand" "")
7569       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7570                        (const_int -1)
7571                        (const_int 67108860)))] ; 0x03fffffc
7572   "TARGET_ARM"
7573   "
7574   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7575   ")
7576
7577 (define_insn "*check_arch2"
7578   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7579       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7580                        (const_int 0)))]
7581   "TARGET_ARM"
7582   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7583   [(set_attr "length" "8")
7584    (set_attr "conds" "set")]
7585 )
7586
7587 ;; Call subroutine returning any type.
7588
7589 (define_expand "untyped_call"
7590   [(parallel [(call (match_operand 0 "" "")
7591                     (const_int 0))
7592               (match_operand 1 "" "")
7593               (match_operand 2 "" "")])]
7594   "TARGET_ARM"
7595   "
7596   {
7597     int i;
7598
7599     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7600
7601     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7602       {
7603         rtx set = XVECEXP (operands[2], 0, i);
7604
7605         emit_move_insn (SET_DEST (set), SET_SRC (set));
7606       }
7607
7608     /* The optimizer does not know that the call sets the function value
7609        registers we stored in the result block.  We avoid problems by
7610        claiming that all hard registers are used and clobbered at this
7611        point.  */
7612     emit_insn (gen_blockage ());
7613
7614     DONE;
7615   }"
7616 )
7617
7618 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7619 ;; all of memory.  This blocks insns from being moved across this point.
7620
7621 (define_insn "blockage"
7622   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7623   "TARGET_EITHER"
7624   ""
7625   [(set_attr "length" "0")
7626    (set_attr "type" "block")]
7627 )
7628
7629 (define_expand "casesi"
7630   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7631    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7632    (match_operand:SI 2 "const_int_operand" "")  ; total range
7633    (match_operand:SI 3 "" "")                   ; table label
7634    (match_operand:SI 4 "" "")]                  ; Out of range label
7635   "TARGET_ARM"
7636   "
7637   {
7638     rtx reg;
7639     if (operands[1] != const0_rtx)
7640       {
7641         reg = gen_reg_rtx (SImode);
7642
7643         emit_insn (gen_addsi3 (reg, operands[0],
7644                                GEN_INT (-INTVAL (operands[1]))));
7645         operands[0] = reg;
7646       }
7647
7648     if (!const_ok_for_arm (INTVAL (operands[2])))
7649       operands[2] = force_reg (SImode, operands[2]);
7650
7651     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7652                                          operands[4]));
7653     DONE;
7654   }"
7655 )
7656
7657 ;; The USE in this pattern is needed to tell flow analysis that this is
7658 ;; a CASESI insn.  It has no other purpose.
7659 (define_insn "casesi_internal"
7660   [(parallel [(set (pc)
7661                (if_then_else
7662                 (leu (match_operand:SI 0 "s_register_operand" "r")
7663                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7664                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7665                                  (label_ref (match_operand 2 "" ""))))
7666                 (label_ref (match_operand 3 "" ""))))
7667               (clobber (reg:CC CC_REGNUM))
7668               (use (label_ref (match_dup 2)))])]
7669   "TARGET_ARM"
7670   "*
7671     if (flag_pic)
7672       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7673     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7674   "
7675   [(set_attr "conds" "clob")
7676    (set_attr "length" "12")]
7677 )
7678
7679 (define_expand "indirect_jump"
7680   [(set (pc)
7681         (match_operand:SI 0 "s_register_operand" ""))]
7682   "TARGET_EITHER"
7683   ""
7684 )
7685
7686 (define_insn "*arm_indirect_jump"
7687   [(set (pc)
7688         (match_operand:SI 0 "s_register_operand" "r"))]
7689   "TARGET_ARM"
7690   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7691   [(set_attr "predicable" "yes")]
7692 )
7693
7694 ;; Although not supported by the define_expand above,
7695 ;; cse/combine may generate this form.
7696 (define_insn "*load_indirect_jump"
7697   [(set (pc)
7698         (match_operand:SI 0 "memory_operand" "m"))]
7699   "TARGET_ARM"
7700   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7701   [(set_attr "type" "load1")
7702    (set_attr "pool_range" "4096")
7703    (set_attr "neg_pool_range" "4084")
7704    (set_attr "predicable" "yes")]
7705 )
7706
7707 (define_insn "*thumb_indirect_jump"
7708   [(set (pc)
7709         (match_operand:SI 0 "register_operand" "l*r"))]
7710   "TARGET_THUMB"
7711   "mov\\tpc, %0"
7712   [(set_attr "conds" "clob")
7713    (set_attr "length" "2")]
7714 )
7715
7716 \f
7717 ;; Misc insns
7718
7719 (define_insn "nop"
7720   [(const_int 0)]
7721   "TARGET_EITHER"
7722   "*
7723   if (TARGET_ARM)
7724     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7725   return  \"mov\\tr8, r8\";
7726   "
7727   [(set (attr "length")
7728         (if_then_else (eq_attr "is_thumb" "yes")
7729                       (const_int 2)
7730                       (const_int 4)))]
7731 )
7732
7733 \f
7734 ;; Patterns to allow combination of arithmetic, cond code and shifts
7735
7736 (define_insn "*arith_shiftsi"
7737   [(set (match_operand:SI 0 "s_register_operand" "=r")
7738         (match_operator:SI 1 "shiftable_operator"
7739           [(match_operator:SI 3 "shift_operator"
7740              [(match_operand:SI 4 "s_register_operand" "r")
7741               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7742            (match_operand:SI 2 "s_register_operand" "r")]))]
7743   "TARGET_ARM"
7744   "%i1%?\\t%0, %2, %4%S3"
7745   [(set_attr "predicable" "yes")
7746    (set_attr "shift" "4")
7747    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7748                       (const_string "alu_shift")
7749                       (const_string "alu_shift_reg")))]
7750 )
7751
7752 (define_split
7753   [(set (match_operand:SI 0 "s_register_operand" "")
7754         (match_operator:SI 1 "shiftable_operator"
7755          [(match_operator:SI 2 "shiftable_operator"
7756            [(match_operator:SI 3 "shift_operator"
7757              [(match_operand:SI 4 "s_register_operand" "")
7758               (match_operand:SI 5 "reg_or_int_operand" "")])
7759             (match_operand:SI 6 "s_register_operand" "")])
7760           (match_operand:SI 7 "arm_rhs_operand" "")]))
7761    (clobber (match_operand:SI 8 "s_register_operand" ""))]
7762   "TARGET_ARM"
7763   [(set (match_dup 8)
7764         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7765                          (match_dup 6)]))
7766    (set (match_dup 0)
7767         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7768   "")
7769
7770 (define_insn "*arith_shiftsi_compare0"
7771   [(set (reg:CC_NOOV CC_REGNUM)
7772         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7773                           [(match_operator:SI 3 "shift_operator"
7774                             [(match_operand:SI 4 "s_register_operand" "r")
7775                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7776                            (match_operand:SI 2 "s_register_operand" "r")])
7777                          (const_int 0)))
7778    (set (match_operand:SI 0 "s_register_operand" "=r")
7779         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7780                          (match_dup 2)]))]
7781   "TARGET_ARM"
7782   "%i1%?s\\t%0, %2, %4%S3"
7783   [(set_attr "conds" "set")
7784    (set_attr "shift" "4")
7785    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7786                       (const_string "alu_shift")
7787                       (const_string "alu_shift_reg")))]
7788 )
7789
7790 (define_insn "*arith_shiftsi_compare0_scratch"
7791   [(set (reg:CC_NOOV CC_REGNUM)
7792         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7793                           [(match_operator:SI 3 "shift_operator"
7794                             [(match_operand:SI 4 "s_register_operand" "r")
7795                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7796                            (match_operand:SI 2 "s_register_operand" "r")])
7797                          (const_int 0)))
7798    (clobber (match_scratch:SI 0 "=r"))]
7799   "TARGET_ARM"
7800   "%i1%?s\\t%0, %2, %4%S3"
7801   [(set_attr "conds" "set")
7802    (set_attr "shift" "4")
7803    (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
7804                       (const_string "alu_shift")
7805                       (const_string "alu_shift_reg")))]
7806 )
7807
7808 (define_insn "*sub_shiftsi"
7809   [(set (match_operand:SI 0 "s_register_operand" "=r")
7810         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7811                   (match_operator:SI 2 "shift_operator"
7812                    [(match_operand:SI 3 "s_register_operand" "r")
7813                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7814   "TARGET_ARM"
7815   "sub%?\\t%0, %1, %3%S2"
7816   [(set_attr "predicable" "yes")
7817    (set_attr "shift" "3")
7818    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7819                       (const_string "alu_shift")
7820                       (const_string "alu_shift_reg")))]
7821 )
7822
7823 (define_insn "*sub_shiftsi_compare0"
7824   [(set (reg:CC_NOOV CC_REGNUM)
7825         (compare:CC_NOOV
7826          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7827                    (match_operator:SI 2 "shift_operator"
7828                     [(match_operand:SI 3 "s_register_operand" "r")
7829                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7830          (const_int 0)))
7831    (set (match_operand:SI 0 "s_register_operand" "=r")
7832         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7833                                                  (match_dup 4)])))]
7834   "TARGET_ARM"
7835   "sub%?s\\t%0, %1, %3%S2"
7836   [(set_attr "conds" "set")
7837    (set_attr "shift" "3")
7838    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7839                       (const_string "alu_shift")
7840                       (const_string "alu_shift_reg")))]
7841 )
7842
7843 (define_insn "*sub_shiftsi_compare0_scratch"
7844   [(set (reg:CC_NOOV CC_REGNUM)
7845         (compare:CC_NOOV
7846          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7847                    (match_operator:SI 2 "shift_operator"
7848                     [(match_operand:SI 3 "s_register_operand" "r")
7849                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7850          (const_int 0)))
7851    (clobber (match_scratch:SI 0 "=r"))]
7852   "TARGET_ARM"
7853   "sub%?s\\t%0, %1, %3%S2"
7854   [(set_attr "conds" "set")
7855    (set_attr "shift" "3")
7856    (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
7857                       (const_string "alu_shift")
7858                       (const_string "alu_shift_reg")))]
7859 )
7860
7861 \f
7862
7863 (define_insn "*and_scc"
7864   [(set (match_operand:SI 0 "s_register_operand" "=r")
7865         (and:SI (match_operator:SI 1 "arm_comparison_operator"
7866                  [(match_operand 3 "cc_register" "") (const_int 0)])
7867                 (match_operand:SI 2 "s_register_operand" "r")))]
7868   "TARGET_ARM"
7869   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7870   [(set_attr "conds" "use")
7871    (set_attr "length" "8")]
7872 )
7873
7874 (define_insn "*ior_scc"
7875   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7876         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7877                  [(match_operand 3 "cc_register" "") (const_int 0)])
7878                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7879   "TARGET_ARM"
7880   "@
7881    orr%d2\\t%0, %1, #1
7882    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7883   [(set_attr "conds" "use")
7884    (set_attr "length" "4,8")]
7885 )
7886
7887 (define_insn "*compare_scc"
7888   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7889         (match_operator:SI 1 "arm_comparison_operator"
7890          [(match_operand:SI 2 "s_register_operand" "r,r")
7891           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7892    (clobber (reg:CC CC_REGNUM))]
7893   "TARGET_ARM"
7894   "*
7895     if (operands[3] == const0_rtx)
7896       {
7897         if (GET_CODE (operands[1]) == LT)
7898           return \"mov\\t%0, %2, lsr #31\";
7899
7900         if (GET_CODE (operands[1]) == GE)
7901           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7902
7903         if (GET_CODE (operands[1]) == EQ)
7904           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
7905       }
7906
7907     if (GET_CODE (operands[1]) == NE)
7908       {
7909         if (which_alternative == 1)
7910           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7911         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7912       }
7913     if (which_alternative == 1)
7914       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7915     else
7916       output_asm_insn (\"cmp\\t%2, %3\", operands);
7917     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7918   "
7919   [(set_attr "conds" "clob")
7920    (set_attr "length" "12")]
7921 )
7922
7923 (define_insn "*cond_move"
7924   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7925         (if_then_else:SI (match_operator 3 "equality_operator"
7926                           [(match_operator 4 "arm_comparison_operator"
7927                             [(match_operand 5 "cc_register" "") (const_int 0)])
7928                            (const_int 0)])
7929                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7930                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7931   "TARGET_ARM"
7932   "*
7933     if (GET_CODE (operands[3]) == NE)
7934       {
7935         if (which_alternative != 1)
7936           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7937         if (which_alternative != 0)
7938           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7939         return \"\";
7940       }
7941     if (which_alternative != 0)
7942       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7943     if (which_alternative != 1)
7944       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7945     return \"\";
7946   "
7947   [(set_attr "conds" "use")
7948    (set_attr "length" "4,4,8")]
7949 )
7950
7951 (define_insn "*cond_arith"
7952   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7953         (match_operator:SI 5 "shiftable_operator" 
7954          [(match_operator:SI 4 "arm_comparison_operator"
7955            [(match_operand:SI 2 "s_register_operand" "r,r")
7956             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7957           (match_operand:SI 1 "s_register_operand" "0,?r")]))
7958    (clobber (reg:CC CC_REGNUM))]
7959   "TARGET_ARM"
7960   "*
7961     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7962       return \"%i5\\t%0, %1, %2, lsr #31\";
7963
7964     output_asm_insn (\"cmp\\t%2, %3\", operands);
7965     if (GET_CODE (operands[5]) == AND)
7966       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7967     else if (GET_CODE (operands[5]) == MINUS)
7968       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7969     else if (which_alternative != 0)
7970       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7971     return \"%i5%d4\\t%0, %1, #1\";
7972   "
7973   [(set_attr "conds" "clob")
7974    (set_attr "length" "12")]
7975 )
7976
7977 (define_insn "*cond_sub"
7978   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7979         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7980                   (match_operator:SI 4 "arm_comparison_operator"
7981                    [(match_operand:SI 2 "s_register_operand" "r,r")
7982                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7983    (clobber (reg:CC CC_REGNUM))]
7984   "TARGET_ARM"
7985   "*
7986     output_asm_insn (\"cmp\\t%2, %3\", operands);
7987     if (which_alternative != 0)
7988       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7989     return \"sub%d4\\t%0, %1, #1\";
7990   "
7991   [(set_attr "conds" "clob")
7992    (set_attr "length" "8,12")]
7993 )
7994
7995 (define_insn "*cmp_ite0"
7996   [(set (match_operand 6 "dominant_cc_register" "")
7997         (compare
7998          (if_then_else:SI
7999           (match_operator 4 "arm_comparison_operator"
8000            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8001             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8002           (match_operator:SI 5 "arm_comparison_operator"
8003            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8004             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8005           (const_int 0))
8006          (const_int 0)))]
8007   "TARGET_ARM"
8008   "*
8009   {
8010     static const char * const opcodes[4][2] =
8011     {
8012       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8013        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8014       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8015        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8016       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8017        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8018       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8019        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8020     };
8021     int swap =
8022       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8023
8024     return opcodes[which_alternative][swap];
8025   }"
8026   [(set_attr "conds" "set")
8027    (set_attr "length" "8")]
8028 )
8029
8030 (define_insn "*cmp_ite1"
8031   [(set (match_operand 6 "dominant_cc_register" "")
8032         (compare
8033          (if_then_else:SI
8034           (match_operator 4 "arm_comparison_operator"
8035            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8036             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8037           (match_operator:SI 5 "arm_comparison_operator"
8038            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8039             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
8040           (const_int 1))
8041          (const_int 0)))]
8042   "TARGET_ARM"
8043   "*
8044   {
8045     static const char * const opcodes[4][2] =
8046     {
8047       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
8048        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8049       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
8050        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8051       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
8052        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8053       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
8054        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8055     };
8056     int swap =
8057       comparison_dominates_p (GET_CODE (operands[5]),
8058                               reverse_condition (GET_CODE (operands[4])));
8059
8060     return opcodes[which_alternative][swap];
8061   }"
8062   [(set_attr "conds" "set")
8063    (set_attr "length" "8")]
8064 )
8065
8066 (define_insn "*cmp_and"
8067   [(set (match_operand 6 "dominant_cc_register" "")
8068         (compare
8069          (and:SI
8070           (match_operator 4 "arm_comparison_operator"
8071            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8072             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8073           (match_operator:SI 5 "arm_comparison_operator"
8074            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8075             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8076          (const_int 0)))]
8077   "TARGET_ARM"
8078   "*
8079   {
8080     static const char *const opcodes[4][2] =
8081     {
8082       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
8083        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
8084       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
8085        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
8086       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
8087        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
8088       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
8089        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
8090     };
8091     int swap =
8092       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8093
8094     return opcodes[which_alternative][swap];
8095   }"
8096   [(set_attr "conds" "set")
8097    (set_attr "predicable" "no")
8098    (set_attr "length" "8")]
8099 )
8100
8101 (define_insn "*cmp_ior"
8102   [(set (match_operand 6 "dominant_cc_register" "")
8103         (compare
8104          (ior:SI
8105           (match_operator 4 "arm_comparison_operator"
8106            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
8107             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
8108           (match_operator:SI 5 "arm_comparison_operator"
8109            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
8110             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
8111          (const_int 0)))]
8112   "TARGET_ARM"
8113   "*
8114 {
8115   static const char *const opcodes[4][2] =
8116   {
8117     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
8118      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8119     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8120      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8121     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8122      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8123     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8124      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8125   };
8126   int swap =
8127     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8128
8129   return opcodes[which_alternative][swap];
8130 }
8131 "
8132   [(set_attr "conds" "set")
8133    (set_attr "length" "8")]
8134 )
8135
8136 (define_insn_and_split "*ior_scc_scc"
8137   [(set (match_operand:SI 0 "s_register_operand" "=r")
8138         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8139                  [(match_operand:SI 1 "s_register_operand" "r")
8140                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8141                 (match_operator:SI 6 "arm_comparison_operator"
8142                  [(match_operand:SI 4 "s_register_operand" "r")
8143                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8144    (clobber (reg:CC CC_REGNUM))]
8145   "TARGET_ARM
8146    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8147        != CCmode)"
8148   "#"
8149   "TARGET_ARM && reload_completed"
8150   [(set (match_dup 7)
8151         (compare
8152          (ior:SI
8153           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8154           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8155          (const_int 0)))
8156    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8157   "operands[7]
8158      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8159                                                   DOM_CC_X_OR_Y),
8160                     CC_REGNUM);"
8161   [(set_attr "conds" "clob")
8162    (set_attr "length" "16")])
8163
8164 ; If the above pattern is followed by a CMP insn, then the compare is 
8165 ; redundant, since we can rework the conditional instruction that follows.
8166 (define_insn_and_split "*ior_scc_scc_cmp"
8167   [(set (match_operand 0 "dominant_cc_register" "")
8168         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8169                           [(match_operand:SI 1 "s_register_operand" "r")
8170                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8171                          (match_operator:SI 6 "arm_comparison_operator"
8172                           [(match_operand:SI 4 "s_register_operand" "r")
8173                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8174                  (const_int 0)))
8175    (set (match_operand:SI 7 "s_register_operand" "=r")
8176         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8177                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8178   "TARGET_ARM"
8179   "#"
8180   "TARGET_ARM && reload_completed"
8181   [(set (match_dup 0)
8182         (compare
8183          (ior:SI
8184           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8185           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8186          (const_int 0)))
8187    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8188   ""
8189   [(set_attr "conds" "set")
8190    (set_attr "length" "16")])
8191
8192 (define_insn_and_split "*and_scc_scc"
8193   [(set (match_operand:SI 0 "s_register_operand" "=r")
8194         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8195                  [(match_operand:SI 1 "s_register_operand" "r")
8196                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8197                 (match_operator:SI 6 "arm_comparison_operator"
8198                  [(match_operand:SI 4 "s_register_operand" "r")
8199                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8200    (clobber (reg:CC CC_REGNUM))]
8201   "TARGET_ARM
8202    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8203        != CCmode)"
8204   "#"
8205   "TARGET_ARM && reload_completed
8206    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8207        != CCmode)"
8208   [(set (match_dup 7)
8209         (compare
8210          (and:SI
8211           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8212           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8213          (const_int 0)))
8214    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8215   "operands[7]
8216      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8217                                                   DOM_CC_X_AND_Y),
8218                     CC_REGNUM);"
8219   [(set_attr "conds" "clob")
8220    (set_attr "length" "16")])
8221
8222 ; If the above pattern is followed by a CMP insn, then the compare is 
8223 ; redundant, since we can rework the conditional instruction that follows.
8224 (define_insn_and_split "*and_scc_scc_cmp"
8225   [(set (match_operand 0 "dominant_cc_register" "")
8226         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8227                           [(match_operand:SI 1 "s_register_operand" "r")
8228                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8229                          (match_operator:SI 6 "arm_comparison_operator"
8230                           [(match_operand:SI 4 "s_register_operand" "r")
8231                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8232                  (const_int 0)))
8233    (set (match_operand:SI 7 "s_register_operand" "=r")
8234         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8235                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8236   "TARGET_ARM"
8237   "#"
8238   "TARGET_ARM && reload_completed"
8239   [(set (match_dup 0)
8240         (compare
8241          (and:SI
8242           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8243           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8244          (const_int 0)))
8245    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8246   ""
8247   [(set_attr "conds" "set")
8248    (set_attr "length" "16")])
8249
8250 ;; If there is no dominance in the comparison, then we can still save an
8251 ;; instruction in the AND case, since we can know that the second compare
8252 ;; need only zero the value if false (if true, then the value is already
8253 ;; correct).
8254 (define_insn_and_split "*and_scc_scc_nodom"
8255   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8256         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8257                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8258                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8259                 (match_operator:SI 6 "arm_comparison_operator"
8260                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8261                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8262    (clobber (reg:CC CC_REGNUM))]
8263   "TARGET_ARM
8264    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8265        == CCmode)"
8266   "#"
8267   "TARGET_ARM && reload_completed"
8268   [(parallel [(set (match_dup 0)
8269                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8270               (clobber (reg:CC CC_REGNUM))])
8271    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8272    (set (match_dup 0)
8273         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8274                          (match_dup 0)
8275                          (const_int 0)))]
8276   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8277                                               operands[4], operands[5]),
8278                               CC_REGNUM);
8279    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8280                                   operands[5]);"
8281   [(set_attr "conds" "clob")
8282    (set_attr "length" "20")])
8283
8284 (define_split
8285   [(set (reg:CC_NOOV CC_REGNUM)
8286         (compare:CC_NOOV (ior:SI
8287                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8288                                   (const_int 1))
8289                           (match_operator:SI 1 "comparison_operator"
8290                            [(match_operand:SI 2 "s_register_operand" "")
8291                             (match_operand:SI 3 "arm_add_operand" "")]))
8292                          (const_int 0)))
8293    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8294   "TARGET_ARM"
8295   [(set (match_dup 4)
8296         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8297                 (match_dup 0)))
8298    (set (reg:CC_NOOV CC_REGNUM)
8299         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8300                          (const_int 0)))]
8301   "")
8302
8303 (define_split
8304   [(set (reg:CC_NOOV CC_REGNUM)
8305         (compare:CC_NOOV (ior:SI
8306                           (match_operator:SI 1 "comparison_operator"
8307                            [(match_operand:SI 2 "s_register_operand" "")
8308                             (match_operand:SI 3 "arm_add_operand" "")])
8309                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8310                                   (const_int 1)))
8311                          (const_int 0)))
8312    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8313   "TARGET_ARM"
8314   [(set (match_dup 4)
8315         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8316                 (match_dup 0)))
8317    (set (reg:CC_NOOV CC_REGNUM)
8318         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8319                          (const_int 0)))]
8320   "")
8321
8322 (define_insn "*negscc"
8323   [(set (match_operand:SI 0 "s_register_operand" "=r")
8324         (neg:SI (match_operator 3 "arm_comparison_operator"
8325                  [(match_operand:SI 1 "s_register_operand" "r")
8326                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8327    (clobber (reg:CC CC_REGNUM))]
8328   "TARGET_ARM"
8329   "*
8330   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8331     return \"mov\\t%0, %1, asr #31\";
8332
8333   if (GET_CODE (operands[3]) == NE)
8334     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8335
8336   if (GET_CODE (operands[3]) == GT)
8337     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8338
8339   output_asm_insn (\"cmp\\t%1, %2\", operands);
8340   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8341   return \"mvn%d3\\t%0, #0\";
8342   "
8343   [(set_attr "conds" "clob")
8344    (set_attr "length" "12")]
8345 )
8346
8347 (define_insn "movcond"
8348   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8349         (if_then_else:SI
8350          (match_operator 5 "arm_comparison_operator"
8351           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8352            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8353          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8354          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8355    (clobber (reg:CC CC_REGNUM))]
8356   "TARGET_ARM"
8357   "*
8358   if (GET_CODE (operands[5]) == LT
8359       && (operands[4] == const0_rtx))
8360     {
8361       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8362         {
8363           if (operands[2] == const0_rtx)
8364             return \"and\\t%0, %1, %3, asr #31\";
8365           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8366         }
8367       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8368         {
8369           if (operands[1] == const0_rtx)
8370             return \"bic\\t%0, %2, %3, asr #31\";
8371           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8372         }
8373       /* The only case that falls through to here is when both ops 1 & 2
8374          are constants.  */
8375     }
8376
8377   if (GET_CODE (operands[5]) == GE
8378       && (operands[4] == const0_rtx))
8379     {
8380       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8381         {
8382           if (operands[2] == const0_rtx)
8383             return \"bic\\t%0, %1, %3, asr #31\";
8384           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8385         }
8386       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8387         {
8388           if (operands[1] == const0_rtx)
8389             return \"and\\t%0, %2, %3, asr #31\";
8390           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8391         }
8392       /* The only case that falls through to here is when both ops 1 & 2
8393          are constants.  */
8394     }
8395   if (GET_CODE (operands[4]) == CONST_INT
8396       && !const_ok_for_arm (INTVAL (operands[4])))
8397     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8398   else
8399     output_asm_insn (\"cmp\\t%3, %4\", operands);
8400   if (which_alternative != 0)
8401     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8402   if (which_alternative != 1)
8403     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8404   return \"\";
8405   "
8406   [(set_attr "conds" "clob")
8407    (set_attr "length" "8,8,12")]
8408 )
8409
8410 (define_insn "*ifcompare_plus_move"
8411   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8412         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8413                           [(match_operand:SI 4 "s_register_operand" "r,r")
8414                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8415                          (plus:SI
8416                           (match_operand:SI 2 "s_register_operand" "r,r")
8417                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8418                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8419    (clobber (reg:CC CC_REGNUM))]
8420   "TARGET_ARM"
8421   "#"
8422   [(set_attr "conds" "clob")
8423    (set_attr "length" "8,12")]
8424 )
8425
8426 (define_insn "*if_plus_move"
8427   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8428         (if_then_else:SI
8429          (match_operator 4 "arm_comparison_operator"
8430           [(match_operand 5 "cc_register" "") (const_int 0)])
8431          (plus:SI
8432           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8433           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8434          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8435   "TARGET_ARM"
8436   "@
8437    add%d4\\t%0, %2, %3
8438    sub%d4\\t%0, %2, #%n3
8439    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8440    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8441   [(set_attr "conds" "use")
8442    (set_attr "length" "4,4,8,8")
8443    (set_attr "type" "*,*,*,*")]
8444 )
8445
8446 (define_insn "*ifcompare_move_plus"
8447   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8448         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8449                           [(match_operand:SI 4 "s_register_operand" "r,r")
8450                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8451                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8452                          (plus:SI
8453                           (match_operand:SI 2 "s_register_operand" "r,r")
8454                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8455    (clobber (reg:CC CC_REGNUM))]
8456   "TARGET_ARM"
8457   "#"
8458   [(set_attr "conds" "clob")
8459    (set_attr "length" "8,12")]
8460 )
8461
8462 (define_insn "*if_move_plus"
8463   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8464         (if_then_else:SI
8465          (match_operator 4 "arm_comparison_operator"
8466           [(match_operand 5 "cc_register" "") (const_int 0)])
8467          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8468          (plus:SI
8469           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8470           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8471   "TARGET_ARM"
8472   "@
8473    add%D4\\t%0, %2, %3
8474    sub%D4\\t%0, %2, #%n3
8475    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8476    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8477   [(set_attr "conds" "use")
8478    (set_attr "length" "4,4,8,8")
8479    (set_attr "type" "*,*,*,*")]
8480 )
8481
8482 (define_insn "*ifcompare_arith_arith"
8483   [(set (match_operand:SI 0 "s_register_operand" "=r")
8484         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8485                           [(match_operand:SI 5 "s_register_operand" "r")
8486                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8487                          (match_operator:SI 8 "shiftable_operator"
8488                           [(match_operand:SI 1 "s_register_operand" "r")
8489                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8490                          (match_operator:SI 7 "shiftable_operator"
8491                           [(match_operand:SI 3 "s_register_operand" "r")
8492                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8493    (clobber (reg:CC CC_REGNUM))]
8494   "TARGET_ARM"
8495   "#"
8496   [(set_attr "conds" "clob")
8497    (set_attr "length" "12")]
8498 )
8499
8500 (define_insn "*if_arith_arith"
8501   [(set (match_operand:SI 0 "s_register_operand" "=r")
8502         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8503                           [(match_operand 8 "cc_register" "") (const_int 0)])
8504                          (match_operator:SI 6 "shiftable_operator"
8505                           [(match_operand:SI 1 "s_register_operand" "r")
8506                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8507                          (match_operator:SI 7 "shiftable_operator"
8508                           [(match_operand:SI 3 "s_register_operand" "r")
8509                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8510   "TARGET_ARM"
8511   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8512   [(set_attr "conds" "use")
8513    (set_attr "length" "8")]
8514 )
8515
8516 (define_insn "*ifcompare_arith_move"
8517   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8518         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8519                           [(match_operand:SI 2 "s_register_operand" "r,r")
8520                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8521                          (match_operator:SI 7 "shiftable_operator"
8522                           [(match_operand:SI 4 "s_register_operand" "r,r")
8523                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8524                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8525    (clobber (reg:CC CC_REGNUM))]
8526   "TARGET_ARM"
8527   "*
8528   /* If we have an operation where (op x 0) is the identity operation and
8529      the conditional operator is LT or GE and we are comparing against zero and
8530      everything is in registers then we can do this in two instructions.  */
8531   if (operands[3] == const0_rtx
8532       && GET_CODE (operands[7]) != AND
8533       && GET_CODE (operands[5]) == REG
8534       && GET_CODE (operands[1]) == REG 
8535       && REGNO (operands[1]) == REGNO (operands[4])
8536       && REGNO (operands[4]) != REGNO (operands[0]))
8537     {
8538       if (GET_CODE (operands[6]) == LT)
8539         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8540       else if (GET_CODE (operands[6]) == GE)
8541         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8542     }
8543   if (GET_CODE (operands[3]) == CONST_INT
8544       && !const_ok_for_arm (INTVAL (operands[3])))
8545     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8546   else
8547     output_asm_insn (\"cmp\\t%2, %3\", operands);
8548   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8549   if (which_alternative != 0)
8550     return \"mov%D6\\t%0, %1\";
8551   return \"\";
8552   "
8553   [(set_attr "conds" "clob")
8554    (set_attr "length" "8,12")]
8555 )
8556
8557 (define_insn "*if_arith_move"
8558   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8559         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8560                           [(match_operand 6 "cc_register" "") (const_int 0)])
8561                          (match_operator:SI 5 "shiftable_operator"
8562                           [(match_operand:SI 2 "s_register_operand" "r,r")
8563                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8564                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8565   "TARGET_ARM"
8566   "@
8567    %I5%d4\\t%0, %2, %3
8568    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8569   [(set_attr "conds" "use")
8570    (set_attr "length" "4,8")
8571    (set_attr "type" "*,*")]
8572 )
8573
8574 (define_insn "*ifcompare_move_arith"
8575   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8576         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8577                           [(match_operand:SI 4 "s_register_operand" "r,r")
8578                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8579                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8580                          (match_operator:SI 7 "shiftable_operator"
8581                           [(match_operand:SI 2 "s_register_operand" "r,r")
8582                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8583    (clobber (reg:CC CC_REGNUM))]
8584   "TARGET_ARM"
8585   "*
8586   /* If we have an operation where (op x 0) is the identity operation and
8587      the conditional operator is LT or GE and we are comparing against zero and
8588      everything is in registers then we can do this in two instructions */
8589   if (operands[5] == const0_rtx
8590       && GET_CODE (operands[7]) != AND
8591       && GET_CODE (operands[3]) == REG
8592       && GET_CODE (operands[1]) == REG 
8593       && REGNO (operands[1]) == REGNO (operands[2])
8594       && REGNO (operands[2]) != REGNO (operands[0]))
8595     {
8596       if (GET_CODE (operands[6]) == GE)
8597         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8598       else if (GET_CODE (operands[6]) == LT)
8599         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8600     }
8601
8602   if (GET_CODE (operands[5]) == CONST_INT
8603       && !const_ok_for_arm (INTVAL (operands[5])))
8604     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8605   else
8606     output_asm_insn (\"cmp\\t%4, %5\", operands);
8607
8608   if (which_alternative != 0)
8609     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8610   return \"%I7%D6\\t%0, %2, %3\";
8611   "
8612   [(set_attr "conds" "clob")
8613    (set_attr "length" "8,12")]
8614 )
8615
8616 (define_insn "*if_move_arith"
8617   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8618         (if_then_else:SI
8619          (match_operator 4 "arm_comparison_operator"
8620           [(match_operand 6 "cc_register" "") (const_int 0)])
8621          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8622          (match_operator:SI 5 "shiftable_operator"
8623           [(match_operand:SI 2 "s_register_operand" "r,r")
8624            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8625   "TARGET_ARM"
8626   "@
8627    %I5%D4\\t%0, %2, %3
8628    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8629   [(set_attr "conds" "use")
8630    (set_attr "length" "4,8")
8631    (set_attr "type" "*,*")]
8632 )
8633
8634 (define_insn "*ifcompare_move_not"
8635   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8636         (if_then_else:SI
8637          (match_operator 5 "arm_comparison_operator"
8638           [(match_operand:SI 3 "s_register_operand" "r,r")
8639            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8640          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8641          (not:SI
8642           (match_operand:SI 2 "s_register_operand" "r,r"))))
8643    (clobber (reg:CC CC_REGNUM))]
8644   "TARGET_ARM"
8645   "#"
8646   [(set_attr "conds" "clob")
8647    (set_attr "length" "8,12")]
8648 )
8649
8650 (define_insn "*if_move_not"
8651   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8652         (if_then_else:SI
8653          (match_operator 4 "arm_comparison_operator"
8654           [(match_operand 3 "cc_register" "") (const_int 0)])
8655          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8656          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8657   "TARGET_ARM"
8658   "@
8659    mvn%D4\\t%0, %2
8660    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8661    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8662   [(set_attr "conds" "use")
8663    (set_attr "length" "4,8,8")]
8664 )
8665
8666 (define_insn "*ifcompare_not_move"
8667   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8668         (if_then_else:SI 
8669          (match_operator 5 "arm_comparison_operator"
8670           [(match_operand:SI 3 "s_register_operand" "r,r")
8671            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8672          (not:SI
8673           (match_operand:SI 2 "s_register_operand" "r,r"))
8674          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8675    (clobber (reg:CC CC_REGNUM))]
8676   "TARGET_ARM"
8677   "#"
8678   [(set_attr "conds" "clob")
8679    (set_attr "length" "8,12")]
8680 )
8681
8682 (define_insn "*if_not_move"
8683   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8684         (if_then_else:SI
8685          (match_operator 4 "arm_comparison_operator"
8686           [(match_operand 3 "cc_register" "") (const_int 0)])
8687          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8688          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8689   "TARGET_ARM"
8690   "@
8691    mvn%d4\\t%0, %2
8692    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8693    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8694   [(set_attr "conds" "use")
8695    (set_attr "length" "4,8,8")]
8696 )
8697
8698 (define_insn "*ifcompare_shift_move"
8699   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8700         (if_then_else:SI
8701          (match_operator 6 "arm_comparison_operator"
8702           [(match_operand:SI 4 "s_register_operand" "r,r")
8703            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8704          (match_operator:SI 7 "shift_operator"
8705           [(match_operand:SI 2 "s_register_operand" "r,r")
8706            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8707          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8708    (clobber (reg:CC CC_REGNUM))]
8709   "TARGET_ARM"
8710   "#"
8711   [(set_attr "conds" "clob")
8712    (set_attr "length" "8,12")]
8713 )
8714
8715 (define_insn "*if_shift_move"
8716   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8717         (if_then_else:SI
8718          (match_operator 5 "arm_comparison_operator"
8719           [(match_operand 6 "cc_register" "") (const_int 0)])
8720          (match_operator:SI 4 "shift_operator"
8721           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8722            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8723          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8724   "TARGET_ARM"
8725   "@
8726    mov%d5\\t%0, %2%S4
8727    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8728    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8729   [(set_attr "conds" "use")
8730    (set_attr "shift" "2")
8731    (set_attr "length" "4,8,8")
8732    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8733                       (const_string "alu_shift")
8734                       (const_string "alu_shift_reg")))]
8735 )
8736
8737 (define_insn "*ifcompare_move_shift"
8738   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8739         (if_then_else:SI
8740          (match_operator 6 "arm_comparison_operator"
8741           [(match_operand:SI 4 "s_register_operand" "r,r")
8742            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8743          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8744          (match_operator:SI 7 "shift_operator"
8745           [(match_operand:SI 2 "s_register_operand" "r,r")
8746            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8747    (clobber (reg:CC CC_REGNUM))]
8748   "TARGET_ARM"
8749   "#"
8750   [(set_attr "conds" "clob")
8751    (set_attr "length" "8,12")]
8752 )
8753
8754 (define_insn "*if_move_shift"
8755   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8756         (if_then_else:SI
8757          (match_operator 5 "arm_comparison_operator"
8758           [(match_operand 6 "cc_register" "") (const_int 0)])
8759          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8760          (match_operator:SI 4 "shift_operator"
8761           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8762            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8763   "TARGET_ARM"
8764   "@
8765    mov%D5\\t%0, %2%S4
8766    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8767    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8768   [(set_attr "conds" "use")
8769    (set_attr "shift" "2")
8770    (set_attr "length" "4,8,8")
8771    (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
8772                       (const_string "alu_shift")
8773                       (const_string "alu_shift_reg")))]
8774 )
8775
8776 (define_insn "*ifcompare_shift_shift"
8777   [(set (match_operand:SI 0 "s_register_operand" "=r")
8778         (if_then_else:SI
8779          (match_operator 7 "arm_comparison_operator"
8780           [(match_operand:SI 5 "s_register_operand" "r")
8781            (match_operand:SI 6 "arm_add_operand" "rIL")])
8782          (match_operator:SI 8 "shift_operator"
8783           [(match_operand:SI 1 "s_register_operand" "r")
8784            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8785          (match_operator:SI 9 "shift_operator"
8786           [(match_operand:SI 3 "s_register_operand" "r")
8787            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8788    (clobber (reg:CC CC_REGNUM))]
8789   "TARGET_ARM"
8790   "#"
8791   [(set_attr "conds" "clob")
8792    (set_attr "length" "12")]
8793 )
8794
8795 (define_insn "*if_shift_shift"
8796   [(set (match_operand:SI 0 "s_register_operand" "=r")
8797         (if_then_else:SI
8798          (match_operator 5 "arm_comparison_operator"
8799           [(match_operand 8 "cc_register" "") (const_int 0)])
8800          (match_operator:SI 6 "shift_operator"
8801           [(match_operand:SI 1 "s_register_operand" "r")
8802            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8803          (match_operator:SI 7 "shift_operator"
8804           [(match_operand:SI 3 "s_register_operand" "r")
8805            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8806   "TARGET_ARM"
8807   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8808   [(set_attr "conds" "use")
8809    (set_attr "shift" "1")
8810    (set_attr "length" "8")
8811    (set (attr "type") (if_then_else
8812                         (and (match_operand 2 "const_int_operand" "")
8813                              (match_operand 4 "const_int_operand" ""))
8814                       (const_string "alu_shift")
8815                       (const_string "alu_shift_reg")))]
8816 )
8817
8818 (define_insn "*ifcompare_not_arith"
8819   [(set (match_operand:SI 0 "s_register_operand" "=r")
8820         (if_then_else:SI
8821          (match_operator 6 "arm_comparison_operator"
8822           [(match_operand:SI 4 "s_register_operand" "r")
8823            (match_operand:SI 5 "arm_add_operand" "rIL")])
8824          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8825          (match_operator:SI 7 "shiftable_operator"
8826           [(match_operand:SI 2 "s_register_operand" "r")
8827            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8828    (clobber (reg:CC CC_REGNUM))]
8829   "TARGET_ARM"
8830   "#"
8831   [(set_attr "conds" "clob")
8832    (set_attr "length" "12")]
8833 )
8834
8835 (define_insn "*if_not_arith"
8836   [(set (match_operand:SI 0 "s_register_operand" "=r")
8837         (if_then_else:SI
8838          (match_operator 5 "arm_comparison_operator"
8839           [(match_operand 4 "cc_register" "") (const_int 0)])
8840          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8841          (match_operator:SI 6 "shiftable_operator"
8842           [(match_operand:SI 2 "s_register_operand" "r")
8843            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8844   "TARGET_ARM"
8845   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8846   [(set_attr "conds" "use")
8847    (set_attr "length" "8")]
8848 )
8849
8850 (define_insn "*ifcompare_arith_not"
8851   [(set (match_operand:SI 0 "s_register_operand" "=r")
8852         (if_then_else:SI
8853          (match_operator 6 "arm_comparison_operator"
8854           [(match_operand:SI 4 "s_register_operand" "r")
8855            (match_operand:SI 5 "arm_add_operand" "rIL")])
8856          (match_operator:SI 7 "shiftable_operator"
8857           [(match_operand:SI 2 "s_register_operand" "r")
8858            (match_operand:SI 3 "arm_rhs_operand" "rI")])
8859          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8860    (clobber (reg:CC CC_REGNUM))]
8861   "TARGET_ARM"
8862   "#"
8863   [(set_attr "conds" "clob")
8864    (set_attr "length" "12")]
8865 )
8866
8867 (define_insn "*if_arith_not"
8868   [(set (match_operand:SI 0 "s_register_operand" "=r")
8869         (if_then_else:SI
8870          (match_operator 5 "arm_comparison_operator"
8871           [(match_operand 4 "cc_register" "") (const_int 0)])
8872          (match_operator:SI 6 "shiftable_operator"
8873           [(match_operand:SI 2 "s_register_operand" "r")
8874            (match_operand:SI 3 "arm_rhs_operand" "rI")])
8875          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
8876   "TARGET_ARM"
8877   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8878   [(set_attr "conds" "use")
8879    (set_attr "length" "8")]
8880 )
8881
8882 (define_insn "*ifcompare_neg_move"
8883   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8884         (if_then_else:SI
8885          (match_operator 5 "arm_comparison_operator"
8886           [(match_operand:SI 3 "s_register_operand" "r,r")
8887            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8888          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
8889          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8890    (clobber (reg:CC CC_REGNUM))]
8891   "TARGET_ARM"
8892   "#"
8893   [(set_attr "conds" "clob")
8894    (set_attr "length" "8,12")]
8895 )
8896
8897 (define_insn "*if_neg_move"
8898   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8899         (if_then_else:SI
8900          (match_operator 4 "arm_comparison_operator"
8901           [(match_operand 3 "cc_register" "") (const_int 0)])
8902          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8903          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8904   "TARGET_ARM"
8905   "@
8906    rsb%d4\\t%0, %2, #0
8907    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8908    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8909   [(set_attr "conds" "use")
8910    (set_attr "length" "4,8,8")]
8911 )
8912
8913 (define_insn "*ifcompare_move_neg"
8914   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8915         (if_then_else:SI
8916          (match_operator 5 "arm_comparison_operator"
8917           [(match_operand:SI 3 "s_register_operand" "r,r")
8918            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8919          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8920          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8921    (clobber (reg:CC CC_REGNUM))]
8922   "TARGET_ARM"
8923   "#"
8924   [(set_attr "conds" "clob")
8925    (set_attr "length" "8,12")]
8926 )
8927
8928 (define_insn "*if_move_neg"
8929   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8930         (if_then_else:SI
8931          (match_operator 4 "arm_comparison_operator"
8932           [(match_operand 3 "cc_register" "") (const_int 0)])
8933          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8934          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8935   "TARGET_ARM"
8936   "@
8937    rsb%D4\\t%0, %2, #0
8938    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8939    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8940   [(set_attr "conds" "use")
8941    (set_attr "length" "4,8,8")]
8942 )
8943
8944 (define_insn "*arith_adjacentmem"
8945   [(set (match_operand:SI 0 "s_register_operand" "=r")
8946         (match_operator:SI 1 "shiftable_operator"
8947          [(match_operand:SI 2 "memory_operand" "m")
8948           (match_operand:SI 3 "memory_operand" "m")]))
8949    (clobber (match_scratch:SI 4 "=r"))]
8950   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8951   "*
8952   {
8953     rtx ldm[3];
8954     rtx arith[4];
8955     int val1 = 0, val2 = 0;
8956
8957     if (REGNO (operands[0]) > REGNO (operands[4]))
8958       {
8959         ldm[1] = operands[4];
8960         ldm[2] = operands[0];
8961       }
8962     else
8963       {
8964         ldm[1] = operands[0];
8965         ldm[2] = operands[4];
8966       }
8967     if (GET_CODE (XEXP (operands[2], 0)) != REG)
8968       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8969     if (GET_CODE (XEXP (operands[3], 0)) != REG)
8970       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8971     arith[0] = operands[0];
8972     arith[3] = operands[1];
8973     if (val1 < val2)
8974       {
8975         arith[1] = ldm[1];
8976         arith[2] = ldm[2];
8977       }
8978     else
8979       {
8980         arith[1] = ldm[2];
8981         arith[2] = ldm[1];
8982       }
8983    if (val1 && val2)
8984       {
8985         rtx ops[3];
8986         ldm[0] = ops[0] = operands[4];
8987         ops[1] = XEXP (XEXP (operands[2], 0), 0);
8988         ops[2] = XEXP (XEXP (operands[2], 0), 1);
8989         output_add_immediate (ops);
8990         if (val1 < val2)
8991           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8992         else
8993           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8994       }
8995     else if (val1)
8996       {
8997         ldm[0] = XEXP (operands[3], 0);
8998         if (val1 < val2)
8999           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9000         else
9001           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9002       }
9003     else
9004       {
9005         ldm[0] = XEXP (operands[2], 0);
9006         if (val1 < val2)
9007           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
9008         else
9009           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
9010       }
9011     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
9012     return \"\";
9013   }"
9014   [(set_attr "length" "12")
9015    (set_attr "predicable" "yes")
9016    (set_attr "type" "load1")]
9017 )
9018
9019 ;; the arm can support extended pre-inc instructions
9020
9021 ;; In all these cases, we use operands 0 and 1 for the register being
9022 ;; incremented because those are the operands that local-alloc will
9023 ;; tie and these are the pair most likely to be tieable (and the ones
9024 ;; that will benefit the most).
9025
9026 ;; We reject the frame pointer if it occurs anywhere in these patterns since
9027 ;; elimination will cause too many headaches.
9028
9029 (define_insn "*strqi_preinc"
9030   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9031                          (match_operand:SI 2 "index_operand" "rJ")))
9032         (match_operand:QI 3 "s_register_operand" "r"))
9033    (set (match_operand:SI 0 "s_register_operand" "=r")
9034         (plus:SI (match_dup 1) (match_dup 2)))]
9035   "TARGET_ARM
9036    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9037    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9038    && (GET_CODE (operands[2]) != REG
9039        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9040   "str%?b\\t%3, [%0, %2]!"
9041   [(set_attr "type" "store1")
9042    (set_attr "predicable" "yes")]
9043 )
9044
9045 (define_insn "*strqi_predec"
9046   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9047                           (match_operand:SI 2 "s_register_operand" "r")))
9048         (match_operand:QI 3 "s_register_operand" "r"))
9049    (set (match_operand:SI 0 "s_register_operand" "=r")
9050         (minus:SI (match_dup 1) (match_dup 2)))]
9051   "TARGET_ARM
9052    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9053    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9054    && (GET_CODE (operands[2]) != REG
9055        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9056   "str%?b\\t%3, [%0, -%2]!"
9057   [(set_attr "type" "store1")
9058    (set_attr "predicable" "yes")]
9059 )
9060
9061 (define_insn "*loadqi_preinc"
9062   [(set (match_operand:QI 3 "s_register_operand" "=r")
9063         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9064                          (match_operand:SI 2 "index_operand" "rJ"))))
9065    (set (match_operand:SI 0 "s_register_operand" "=r")
9066         (plus:SI (match_dup 1) (match_dup 2)))]
9067   "TARGET_ARM
9068    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9069    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9070    && (GET_CODE (operands[2]) != REG
9071        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9072   "ldr%?b\\t%3, [%0, %2]!"
9073   [(set_attr "type" "load_byte")
9074    (set_attr "predicable" "yes")]
9075 )
9076
9077 (define_insn "*loadqi_predec"
9078   [(set (match_operand:QI 3 "s_register_operand" "=r")
9079         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9080                           (match_operand:SI 2 "s_register_operand" "r"))))
9081    (set (match_operand:SI 0 "s_register_operand" "=r")
9082         (minus:SI (match_dup 1) (match_dup 2)))]
9083   "TARGET_ARM
9084    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9085    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9086    && (GET_CODE (operands[2]) != REG
9087        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9088   "ldr%?b\\t%3, [%0, -%2]!"
9089   [(set_attr "type" "load_byte")
9090    (set_attr "predicable" "yes")]
9091 )
9092
9093 (define_insn "*loadqisi_preinc"
9094   [(set (match_operand:SI 3 "s_register_operand" "=r")
9095         (zero_extend:SI
9096          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9097                           (match_operand:SI 2 "index_operand" "rJ")))))
9098    (set (match_operand:SI 0 "s_register_operand" "=r")
9099         (plus:SI (match_dup 1) (match_dup 2)))]
9100   "TARGET_ARM
9101    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9102    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9103    && (GET_CODE (operands[2]) != REG
9104        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9105   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
9106   [(set_attr "type" "load_byte")
9107    (set_attr "predicable" "yes")]
9108 )
9109
9110 (define_insn "*loadqisi_predec"
9111   [(set (match_operand:SI 3 "s_register_operand" "=r")
9112         (zero_extend:SI
9113          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9114                            (match_operand:SI 2 "s_register_operand" "r")))))
9115    (set (match_operand:SI 0 "s_register_operand" "=r")
9116         (minus:SI (match_dup 1) (match_dup 2)))]
9117   "TARGET_ARM
9118    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9119    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9120    && (GET_CODE (operands[2]) != REG
9121        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9122   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
9123   [(set_attr "type" "load_byte")
9124    (set_attr "predicable" "yes")]
9125 )
9126
9127 (define_insn "*strsi_preinc"
9128   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9129                          (match_operand:SI 2 "index_operand" "rJ")))
9130         (match_operand:SI 3 "s_register_operand" "r"))
9131    (set (match_operand:SI 0 "s_register_operand" "=r")
9132         (plus:SI (match_dup 1) (match_dup 2)))]
9133   "TARGET_ARM
9134    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9135    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9136    && (GET_CODE (operands[2]) != REG
9137        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9138   "str%?\\t%3, [%0, %2]!"
9139   [(set_attr "type" "store1")
9140    (set_attr "predicable" "yes")]
9141 )
9142
9143 (define_insn "*strsi_predec"
9144   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9145                           (match_operand:SI 2 "s_register_operand" "r")))
9146         (match_operand:SI 3 "s_register_operand" "r"))
9147    (set (match_operand:SI 0 "s_register_operand" "=r")
9148         (minus:SI (match_dup 1) (match_dup 2)))]
9149   "TARGET_ARM
9150    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9151    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9152    && (GET_CODE (operands[2]) != REG
9153        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9154   "str%?\\t%3, [%0, -%2]!"
9155   [(set_attr "type" "store1")
9156    (set_attr "predicable" "yes")]
9157 )
9158
9159 (define_insn "*loadsi_preinc"
9160   [(set (match_operand:SI 3 "s_register_operand" "=r")
9161         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9162                          (match_operand:SI 2 "index_operand" "rJ"))))
9163    (set (match_operand:SI 0 "s_register_operand" "=r")
9164         (plus:SI (match_dup 1) (match_dup 2)))]
9165   "TARGET_ARM
9166    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9167    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9168    && (GET_CODE (operands[2]) != REG
9169        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9170   "ldr%?\\t%3, [%0, %2]!"
9171   [(set_attr "type" "load1")
9172    (set_attr "predicable" "yes")]
9173 )
9174
9175 (define_insn "*loadsi_predec"
9176   [(set (match_operand:SI 3 "s_register_operand" "=r")
9177         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9178                           (match_operand:SI 2 "s_register_operand" "r"))))
9179    (set (match_operand:SI 0 "s_register_operand" "=r")
9180         (minus:SI (match_dup 1) (match_dup 2)))]
9181   "TARGET_ARM
9182    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9183    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9184    && (GET_CODE (operands[2]) != REG
9185        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9186   "ldr%?\\t%3, [%0, -%2]!"
9187   [(set_attr "type" "load1")
9188    (set_attr "predicable" "yes")]
9189 )
9190
9191 (define_insn "*strqi_shiftpreinc"
9192   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9193                           [(match_operand:SI 3 "s_register_operand" "r")
9194                            (match_operand:SI 4 "const_shift_operand" "n")])
9195                          (match_operand:SI 1 "s_register_operand" "0")))
9196         (match_operand:QI 5 "s_register_operand" "r"))
9197    (set (match_operand:SI 0 "s_register_operand" "=r")
9198         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9199                  (match_dup 1)))]
9200   "TARGET_ARM
9201    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9202    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9203    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9204   "str%?b\\t%5, [%0, %3%S2]!"
9205   [(set_attr "type" "store1")
9206    (set_attr "predicable" "yes")]
9207 )
9208
9209 (define_insn "*strqi_shiftpredec"
9210   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9211                           (match_operator:SI 2 "shift_operator"
9212                            [(match_operand:SI 3 "s_register_operand" "r")
9213                             (match_operand:SI 4 "const_shift_operand" "n")])))
9214         (match_operand:QI 5 "s_register_operand" "r"))
9215    (set (match_operand:SI 0 "s_register_operand" "=r")
9216         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9217                                                  (match_dup 4)])))]
9218   "TARGET_ARM
9219    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9220    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9221    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9222   "str%?b\\t%5, [%0, -%3%S2]!"
9223   [(set_attr "type" "store1")
9224    (set_attr "predicable" "yes")]
9225 )
9226
9227 (define_insn "*loadqi_shiftpreinc"
9228   [(set (match_operand:QI 5 "s_register_operand" "=r")
9229         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9230                           [(match_operand:SI 3 "s_register_operand" "r")
9231                            (match_operand:SI 4 "const_shift_operand" "n")])
9232                          (match_operand:SI 1 "s_register_operand" "0"))))
9233    (set (match_operand:SI 0 "s_register_operand" "=r")
9234         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9235                  (match_dup 1)))]
9236   "TARGET_ARM
9237    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9238    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9239    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9240   "ldr%?b\\t%5, [%0, %3%S2]!"
9241   [(set_attr "type" "load_byte")
9242    (set_attr "predicable" "yes")]
9243 )
9244
9245 (define_insn "*loadqi_shiftpredec"
9246   [(set (match_operand:QI 5 "s_register_operand" "=r")
9247         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9248                           (match_operator:SI 2 "shift_operator"
9249                            [(match_operand:SI 3 "s_register_operand" "r")
9250                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9251    (set (match_operand:SI 0 "s_register_operand" "=r")
9252         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9253                                                  (match_dup 4)])))]
9254   "TARGET_ARM
9255    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9256    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9257    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9258   "ldr%?b\\t%5, [%0, -%3%S2]!"
9259   [(set_attr "type" "load_byte")
9260    (set_attr "predicable" "yes")]
9261 )
9262
9263 (define_insn "*strsi_shiftpreinc"
9264   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9265                           [(match_operand:SI 3 "s_register_operand" "r")
9266                            (match_operand:SI 4 "const_shift_operand" "n")])
9267                          (match_operand:SI 1 "s_register_operand" "0")))
9268         (match_operand:SI 5 "s_register_operand" "r"))
9269    (set (match_operand:SI 0 "s_register_operand" "=r")
9270         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9271                  (match_dup 1)))]
9272   "TARGET_ARM
9273    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9274    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9275    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9276   "str%?\\t%5, [%0, %3%S2]!"
9277   [(set_attr "type" "store1")
9278    (set_attr "predicable" "yes")]
9279 )
9280
9281 (define_insn "*strsi_shiftpredec"
9282   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9283                           (match_operator:SI 2 "shift_operator"
9284                            [(match_operand:SI 3 "s_register_operand" "r")
9285                             (match_operand:SI 4 "const_shift_operand" "n")])))
9286         (match_operand:SI 5 "s_register_operand" "r"))
9287    (set (match_operand:SI 0 "s_register_operand" "=r")
9288         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9289                                                  (match_dup 4)])))]
9290   "TARGET_ARM
9291    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9292    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9293    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9294   "str%?\\t%5, [%0, -%3%S2]!"
9295   [(set_attr "type" "store1")
9296    (set_attr "predicable" "yes")]
9297 )
9298
9299 (define_insn "*loadsi_shiftpreinc"
9300   [(set (match_operand:SI 5 "s_register_operand" "=r")
9301         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9302                           [(match_operand:SI 3 "s_register_operand" "r")
9303                            (match_operand:SI 4 "const_shift_operand" "n")])
9304                          (match_operand:SI 1 "s_register_operand" "0"))))
9305    (set (match_operand:SI 0 "s_register_operand" "=r")
9306         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9307                  (match_dup 1)))]
9308   "TARGET_ARM
9309    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9310    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9311    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9312   "ldr%?\\t%5, [%0, %3%S2]!"
9313   [(set_attr "type" "load1")
9314    (set_attr "predicable" "yes")]
9315 )
9316
9317 (define_insn "*loadsi_shiftpredec"
9318   [(set (match_operand:SI 5 "s_register_operand" "=r")
9319         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9320                           (match_operator:SI 2 "shift_operator"
9321                            [(match_operand:SI 3 "s_register_operand" "r")
9322                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9323    (set (match_operand:SI 0 "s_register_operand" "=r")
9324         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9325                                                  (match_dup 4)])))]
9326   "TARGET_ARM
9327    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9328    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9329    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9330   "ldr%?\\t%5, [%0, -%3%S2]!"
9331   [(set_attr "type" "load1")
9332    (set_attr "predicable" "yes")])
9333
9334 ; It can also support extended post-inc expressions, but combine doesn't
9335 ; try these....
9336 ; It doesn't seem worth adding peepholes for anything but the most common
9337 ; cases since, unlike combine, the increment must immediately follow the load
9338 ; for this pattern to match.
9339 ; We must watch to see that the source/destination register isn't also the
9340 ; same as the base address register, and that if the index is a register,
9341 ; that it is not the same as the base address register.  In such cases the
9342 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9343 ; we cannot use it.
9344
9345 (define_peephole
9346   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9347         (match_operand:QI 2 "s_register_operand" "r"))
9348    (set (match_dup 0)
9349         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9350   "TARGET_ARM
9351    && (REGNO (operands[2]) != REGNO (operands[0]))
9352    && (GET_CODE (operands[1]) != REG
9353        || (REGNO (operands[1]) != REGNO (operands[0])))"
9354   "str%?b\\t%2, [%0], %1"
9355 )
9356
9357 (define_peephole
9358   [(set (match_operand:QI 0 "s_register_operand" "=r")
9359         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9360    (set (match_dup 1)
9361         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9362   "TARGET_ARM
9363    && REGNO (operands[0]) != REGNO(operands[1])
9364    && (GET_CODE (operands[2]) != REG
9365        || REGNO(operands[0]) != REGNO (operands[2]))"
9366   "ldr%?b\\t%0, [%1], %2"
9367 )
9368
9369 (define_peephole
9370   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9371         (match_operand:SI 2 "s_register_operand" "r"))
9372    (set (match_dup 0)
9373         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9374   "TARGET_ARM
9375    && (REGNO (operands[2]) != REGNO (operands[0]))
9376    && (GET_CODE (operands[1]) != REG
9377        || (REGNO (operands[1]) != REGNO (operands[0])))"
9378   "str%?\\t%2, [%0], %1"
9379 )
9380
9381 (define_peephole
9382   [(set (match_operand:SI 0 "s_register_operand" "=r")
9383         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9384    (set (match_dup 1)
9385         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9386   "TARGET_ARM
9387    && REGNO (operands[0]) != REGNO(operands[1])
9388    && (GET_CODE (operands[2]) != REG
9389        || REGNO(operands[0]) != REGNO (operands[2]))"
9390   "ldr%?\\t%0, [%1], %2"
9391 )
9392
9393 (define_peephole
9394   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9395                          (match_operand:SI 1 "index_operand" "rJ")))
9396         (match_operand:QI 2 "s_register_operand" "r"))
9397    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9398   "TARGET_ARM
9399    && (REGNO (operands[2]) != REGNO (operands[0]))
9400    && (GET_CODE (operands[1]) != REG
9401        || (REGNO (operands[1]) != REGNO (operands[0])))"
9402   "str%?b\\t%2, [%0, %1]!"
9403 )
9404
9405 (define_peephole
9406   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9407                           [(match_operand:SI 0 "s_register_operand" "r")
9408                            (match_operand:SI 1 "const_int_operand" "n")])
9409                          (match_operand:SI 2 "s_register_operand" "+r")))
9410         (match_operand:QI 3 "s_register_operand" "r"))
9411    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9412                                (match_dup 2)))]
9413   "TARGET_ARM
9414    && (REGNO (operands[3]) != REGNO (operands[2]))
9415    && (REGNO (operands[0]) != REGNO (operands[2]))"
9416   "str%?b\\t%3, [%2, %0%S4]!"
9417 )
9418
9419 ; This pattern is never tried by combine, so do it as a peephole
9420
9421 (define_peephole2
9422   [(set (match_operand:SI 0 "arm_general_register_operand" "")
9423         (match_operand:SI 1 "arm_general_register_operand" ""))
9424    (set (reg:CC CC_REGNUM)
9425         (compare:CC (match_dup 1) (const_int 0)))]
9426   "TARGET_ARM"
9427   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9428               (set (match_dup 0) (match_dup 1))])]
9429   ""
9430 )
9431
9432 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9433 ; reversed, check that the memory references aren't volatile.
9434
9435 (define_peephole
9436   [(set (match_operand:SI 0 "s_register_operand" "=r")
9437         (match_operand:SI 4 "memory_operand" "m"))
9438    (set (match_operand:SI 1 "s_register_operand" "=r")
9439         (match_operand:SI 5 "memory_operand" "m"))
9440    (set (match_operand:SI 2 "s_register_operand" "=r")
9441         (match_operand:SI 6 "memory_operand" "m"))
9442    (set (match_operand:SI 3 "s_register_operand" "=r")
9443         (match_operand:SI 7 "memory_operand" "m"))]
9444   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9445   "*
9446   return emit_ldm_seq (operands, 4);
9447   "
9448 )
9449
9450 (define_peephole
9451   [(set (match_operand:SI 0 "s_register_operand" "=r")
9452         (match_operand:SI 3 "memory_operand" "m"))
9453    (set (match_operand:SI 1 "s_register_operand" "=r")
9454         (match_operand:SI 4 "memory_operand" "m"))
9455    (set (match_operand:SI 2 "s_register_operand" "=r")
9456         (match_operand:SI 5 "memory_operand" "m"))]
9457   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9458   "*
9459   return emit_ldm_seq (operands, 3);
9460   "
9461 )
9462
9463 (define_peephole
9464   [(set (match_operand:SI 0 "s_register_operand" "=r")
9465         (match_operand:SI 2 "memory_operand" "m"))
9466    (set (match_operand:SI 1 "s_register_operand" "=r")
9467         (match_operand:SI 3 "memory_operand" "m"))]
9468   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9469   "*
9470   return emit_ldm_seq (operands, 2);
9471   "
9472 )
9473
9474 (define_peephole
9475   [(set (match_operand:SI 4 "memory_operand" "=m")
9476         (match_operand:SI 0 "s_register_operand" "r"))
9477    (set (match_operand:SI 5 "memory_operand" "=m")
9478         (match_operand:SI 1 "s_register_operand" "r"))
9479    (set (match_operand:SI 6 "memory_operand" "=m")
9480         (match_operand:SI 2 "s_register_operand" "r"))
9481    (set (match_operand:SI 7 "memory_operand" "=m")
9482         (match_operand:SI 3 "s_register_operand" "r"))]
9483   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9484   "*
9485   return emit_stm_seq (operands, 4);
9486   "
9487 )
9488
9489 (define_peephole
9490   [(set (match_operand:SI 3 "memory_operand" "=m")
9491         (match_operand:SI 0 "s_register_operand" "r"))
9492    (set (match_operand:SI 4 "memory_operand" "=m")
9493         (match_operand:SI 1 "s_register_operand" "r"))
9494    (set (match_operand:SI 5 "memory_operand" "=m")
9495         (match_operand:SI 2 "s_register_operand" "r"))]
9496   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9497   "*
9498   return emit_stm_seq (operands, 3);
9499   "
9500 )
9501
9502 (define_peephole
9503   [(set (match_operand:SI 2 "memory_operand" "=m")
9504         (match_operand:SI 0 "s_register_operand" "r"))
9505    (set (match_operand:SI 3 "memory_operand" "=m")
9506         (match_operand:SI 1 "s_register_operand" "r"))]
9507   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9508   "*
9509   return emit_stm_seq (operands, 2);
9510   "
9511 )
9512
9513 (define_split
9514   [(set (match_operand:SI 0 "s_register_operand" "")
9515         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9516                        (const_int 0))
9517                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9518                          [(match_operand:SI 3 "s_register_operand" "")
9519                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9520    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9521   "TARGET_ARM"
9522   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9523    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9524                               (match_dup 5)))]
9525   ""
9526 )
9527
9528 ;; This split can be used because CC_Z mode implies that the following
9529 ;; branch will be an equality, or an unsigned inequality, so the sign
9530 ;; extension is not needed.
9531
9532 (define_split
9533   [(set (reg:CC_Z CC_REGNUM)
9534         (compare:CC_Z
9535          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9536                     (const_int 24))
9537          (match_operand 1 "const_int_operand" "")))
9538    (clobber (match_scratch:SI 2 ""))]
9539   "TARGET_ARM
9540    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9541        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9542   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9543    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9544   "
9545   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9546   "
9547 )
9548
9549 (define_expand "prologue"
9550   [(clobber (const_int 0))]
9551   "TARGET_EITHER"
9552   "if (TARGET_ARM)
9553      arm_expand_prologue ();
9554    else
9555      thumb_expand_prologue ();
9556   DONE;
9557   "
9558 )
9559
9560 (define_expand "epilogue"
9561   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9562   "TARGET_EITHER"
9563   "
9564   if (TARGET_THUMB)
9565     thumb_expand_epilogue ();
9566   else if (USE_RETURN_INSN (FALSE))
9567     {
9568       emit_jump_insn (gen_return ());
9569       DONE;
9570     }
9571   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9572         gen_rtvec (1,
9573                 gen_rtx_RETURN (VOIDmode)),
9574         VUNSPEC_EPILOGUE));
9575   DONE;
9576   "
9577 )
9578
9579 ;; Note - although unspec_volatile's USE all hard registers,
9580 ;; USEs are ignored after relaod has completed.  Thus we need
9581 ;; to add an unspec of the link register to ensure that flow
9582 ;; does not think that it is unused by the sibcall branch that
9583 ;; will replace the standard function epilogue.
9584 (define_insn "sibcall_epilogue"
9585   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9586               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9587   "TARGET_ARM"
9588   "*
9589   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9590     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9591   return arm_output_epilogue (next_nonnote_insn (insn));
9592   "
9593 ;; Length is absolute worst case
9594   [(set_attr "length" "44")
9595    (set_attr "type" "block")
9596    ;; We don't clobber the conditions, but the potential length of this
9597    ;; operation is sufficient to make conditionalizing the sequence 
9598    ;; unlikely to be profitable.
9599    (set_attr "conds" "clob")]
9600 )
9601
9602 (define_insn "*epilogue_insns"
9603   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9604   "TARGET_EITHER"
9605   "*
9606   if (TARGET_ARM)
9607     return arm_output_epilogue (NULL);
9608   else /* TARGET_THUMB */
9609     return thumb_unexpanded_epilogue ();
9610   "
9611   ; Length is absolute worst case
9612   [(set_attr "length" "44")
9613    (set_attr "type" "block")
9614    ;; We don't clobber the conditions, but the potential length of this
9615    ;; operation is sufficient to make conditionalizing the sequence 
9616    ;; unlikely to be profitable.
9617    (set_attr "conds" "clob")]
9618 )
9619
9620 (define_expand "eh_epilogue"
9621   [(use (match_operand:SI 0 "register_operand" ""))
9622    (use (match_operand:SI 1 "register_operand" ""))
9623    (use (match_operand:SI 2 "register_operand" ""))]
9624   "TARGET_EITHER"
9625   "
9626   {
9627     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9628     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9629       {
9630         rtx ra = gen_rtx_REG (Pmode, 2);
9631
9632         emit_move_insn (ra, operands[2]);
9633         operands[2] = ra;
9634       }
9635     /* This is a hack -- we may have crystalized the function type too
9636        early.  */
9637     cfun->machine->func_type = 0;
9638   }"
9639 )
9640
9641 ;; This split is only used during output to reduce the number of patterns
9642 ;; that need assembler instructions adding to them.  We allowed the setting
9643 ;; of the conditions to be implicit during rtl generation so that
9644 ;; the conditional compare patterns would work.  However this conflicts to
9645 ;; some extent with the conditional data operations, so we have to split them
9646 ;; up again here.
9647
9648 (define_split
9649   [(set (match_operand:SI 0 "s_register_operand" "")
9650         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9651                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9652                          (match_dup 0)
9653                          (match_operand 4 "" "")))
9654    (clobber (reg:CC CC_REGNUM))]
9655   "TARGET_ARM && reload_completed"
9656   [(set (match_dup 5) (match_dup 6))
9657    (cond_exec (match_dup 7)
9658               (set (match_dup 0) (match_dup 4)))]
9659   "
9660   {
9661     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9662                                              operands[2], operands[3]);
9663     enum rtx_code rc = GET_CODE (operands[1]);
9664
9665     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9666     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9667     if (mode == CCFPmode || mode == CCFPEmode)
9668       rc = reverse_condition_maybe_unordered (rc);
9669     else
9670       rc = reverse_condition (rc);
9671
9672     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9673   }"
9674 )
9675
9676 (define_split
9677   [(set (match_operand:SI 0 "s_register_operand" "")
9678         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9679                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9680                          (match_operand 4 "" "")
9681                          (match_dup 0)))
9682    (clobber (reg:CC CC_REGNUM))]
9683   "TARGET_ARM && reload_completed"
9684   [(set (match_dup 5) (match_dup 6))
9685    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9686               (set (match_dup 0) (match_dup 4)))]
9687   "
9688   {
9689     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9690                                              operands[2], operands[3]);
9691
9692     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9693     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9694   }"
9695 )
9696
9697 (define_split
9698   [(set (match_operand:SI 0 "s_register_operand" "")
9699         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9700                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9701                          (match_operand 4 "" "")
9702                          (match_operand 5 "" "")))
9703    (clobber (reg:CC CC_REGNUM))]
9704   "TARGET_ARM && reload_completed"
9705   [(set (match_dup 6) (match_dup 7))
9706    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9707               (set (match_dup 0) (match_dup 4)))
9708    (cond_exec (match_dup 8)
9709               (set (match_dup 0) (match_dup 5)))]
9710   "
9711   {
9712     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9713                                              operands[2], operands[3]);
9714     enum rtx_code rc = GET_CODE (operands[1]);
9715
9716     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9717     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9718     if (mode == CCFPmode || mode == CCFPEmode)
9719       rc = reverse_condition_maybe_unordered (rc);
9720     else
9721       rc = reverse_condition (rc);
9722
9723     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9724   }"
9725 )
9726
9727 (define_split
9728   [(set (match_operand:SI 0 "s_register_operand" "")
9729         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9730                           [(match_operand:SI 2 "s_register_operand" "")
9731                            (match_operand:SI 3 "arm_add_operand" "")])
9732                          (match_operand:SI 4 "arm_rhs_operand" "")
9733                          (not:SI
9734                           (match_operand:SI 5 "s_register_operand" ""))))
9735    (clobber (reg:CC CC_REGNUM))]
9736   "TARGET_ARM && reload_completed"
9737   [(set (match_dup 6) (match_dup 7))
9738    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9739               (set (match_dup 0) (match_dup 4)))
9740    (cond_exec (match_dup 8)
9741               (set (match_dup 0) (not:SI (match_dup 5))))]
9742   "
9743   {
9744     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9745                                              operands[2], operands[3]);
9746     enum rtx_code rc = GET_CODE (operands[1]);
9747
9748     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9749     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9750     if (mode == CCFPmode || mode == CCFPEmode)
9751       rc = reverse_condition_maybe_unordered (rc);
9752     else
9753       rc = reverse_condition (rc);
9754
9755     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9756   }"
9757 )
9758
9759 (define_insn "*cond_move_not"
9760   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9761         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9762                           [(match_operand 3 "cc_register" "") (const_int 0)])
9763                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9764                          (not:SI
9765                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9766   "TARGET_ARM"
9767   "@
9768    mvn%D4\\t%0, %2
9769    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9770   [(set_attr "conds" "use")
9771    (set_attr "length" "4,8")]
9772 )
9773
9774 ;; The next two patterns occur when an AND operation is followed by a
9775 ;; scc insn sequence 
9776
9777 (define_insn "*sign_extract_onebit"
9778   [(set (match_operand:SI 0 "s_register_operand" "=r")
9779         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9780                          (const_int 1)
9781                          (match_operand:SI 2 "const_int_operand" "n")))
9782     (clobber (reg:CC CC_REGNUM))]
9783   "TARGET_ARM"
9784   "*
9785     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9786     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9787     return \"mvnne\\t%0, #0\";
9788   "
9789   [(set_attr "conds" "clob")
9790    (set_attr "length" "8")]
9791 )
9792
9793 (define_insn "*not_signextract_onebit"
9794   [(set (match_operand:SI 0 "s_register_operand" "=r")
9795         (not:SI
9796          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9797                           (const_int 1)
9798                           (match_operand:SI 2 "const_int_operand" "n"))))
9799    (clobber (reg:CC CC_REGNUM))]
9800   "TARGET_ARM"
9801   "*
9802     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9803     output_asm_insn (\"tst\\t%1, %2\", operands);
9804     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9805     return \"movne\\t%0, #0\";
9806   "
9807   [(set_attr "conds" "clob")
9808    (set_attr "length" "12")]
9809 )
9810
9811 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9812 ;; expressions.  For simplicity, the first register is also in the unspec
9813 ;; part.
9814 (define_insn "*push_multi"
9815   [(match_parallel 2 "multi_register_push"
9816     [(set (match_operand:BLK 0 "memory_operand" "=m")
9817           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9818                       UNSPEC_PUSH_MULT))])]
9819   "TARGET_ARM"
9820   "*
9821   {
9822     int num_saves = XVECLEN (operands[2], 0);
9823      
9824     /* For the StrongARM at least it is faster to
9825        use STR to store only a single register.  */
9826     if (num_saves == 1)
9827       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9828     else
9829       {
9830         int i;
9831         char pattern[100];
9832
9833         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9834
9835         for (i = 1; i < num_saves; i++)
9836           {
9837             strcat (pattern, \", %|\");
9838             strcat (pattern,
9839                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9840           }
9841
9842         strcat (pattern, \"}\");
9843         output_asm_insn (pattern, operands);
9844       }
9845
9846     return \"\";
9847   }"
9848   [(set_attr "type" "store4")]
9849 )
9850
9851 (define_insn "stack_tie"
9852   [(set (mem:BLK (scratch))
9853         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9854                      (match_operand:SI 1 "s_register_operand" "r")]
9855                     UNSPEC_PRLG_STK))]
9856   ""
9857   ""
9858   [(set_attr "length" "0")]
9859 )
9860
9861 ;; Similarly for the floating point registers
9862 (define_insn "*push_fp_multi"
9863   [(match_parallel 2 "multi_register_push"
9864     [(set (match_operand:BLK 0 "memory_operand" "=m")
9865           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9866                       UNSPEC_PUSH_MULT))])]
9867   "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
9868   "*
9869   {
9870     char pattern[100];
9871
9872     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9873     output_asm_insn (pattern, operands);
9874     return \"\";
9875   }"
9876   [(set_attr "type" "f_store")]
9877 )
9878
9879 ;; Special patterns for dealing with the constant pool
9880
9881 (define_insn "align_4"
9882   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9883   "TARGET_EITHER"
9884   "*
9885   assemble_align (32);
9886   return \"\";
9887   "
9888 )
9889
9890 (define_insn "align_8"
9891   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9892   "TARGET_EITHER"
9893   "*
9894   assemble_align (64);
9895   return \"\";
9896   "
9897 )
9898
9899 (define_insn "consttable_end"
9900   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9901   "TARGET_EITHER"
9902   "*
9903   making_const_table = FALSE;
9904   return \"\";
9905   "
9906 )
9907
9908 (define_insn "consttable_1"
9909   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9910   "TARGET_THUMB"
9911   "*
9912   making_const_table = TRUE;
9913   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9914   assemble_zeros (3);
9915   return \"\";
9916   "
9917   [(set_attr "length" "4")]
9918 )
9919
9920 (define_insn "consttable_2"
9921   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9922   "TARGET_THUMB"
9923   "*
9924   making_const_table = TRUE;
9925   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9926   assemble_zeros (2);
9927   return \"\";
9928   "
9929   [(set_attr "length" "4")]
9930 )
9931
9932 (define_insn "consttable_4"
9933   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9934   "TARGET_EITHER"
9935   "*
9936   {
9937     making_const_table = TRUE;
9938     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9939       {
9940       case MODE_FLOAT:
9941       {
9942         REAL_VALUE_TYPE r;
9943         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9944         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9945         break;
9946       }
9947       default:
9948         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9949         break;
9950       }
9951     return \"\";
9952   }"
9953   [(set_attr "length" "4")]
9954 )
9955
9956 (define_insn "consttable_8"
9957   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9958   "TARGET_EITHER"
9959   "*
9960   {
9961     making_const_table = TRUE;
9962     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9963       {
9964        case MODE_FLOAT:
9965         {
9966           REAL_VALUE_TYPE r;
9967           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9968           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9969           break;
9970         }
9971       default:
9972         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9973         break;
9974       }
9975     return \"\";
9976   }"
9977   [(set_attr "length" "8")]
9978 )
9979
9980 ;; Miscellaneous Thumb patterns
9981
9982 (define_expand "tablejump"
9983   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9984               (use (label_ref (match_operand 1 "" "")))])]
9985   "TARGET_THUMB"
9986   "
9987   if (flag_pic)
9988     {
9989       /* Hopefully, CSE will eliminate this copy.  */
9990       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9991       rtx reg2 = gen_reg_rtx (SImode);
9992
9993       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9994       operands[0] = reg2;
9995     }
9996   "
9997 )
9998
9999 (define_insn "*thumb_tablejump"
10000   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
10001    (use (label_ref (match_operand 1 "" "")))]
10002   "TARGET_THUMB"
10003   "mov\\t%|pc, %0"
10004   [(set_attr "length" "2")]
10005 )
10006
10007 ;; V5 Instructions,
10008
10009 (define_insn "clzsi2"
10010   [(set (match_operand:SI 0 "s_register_operand" "=r")
10011         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
10012   "TARGET_ARM && arm_arch5"
10013   "clz%?\\t%0, %1"
10014   [(set_attr "predicable" "yes")])
10015
10016 (define_expand "ffssi2"
10017   [(set (match_operand:SI 0 "s_register_operand" "")
10018         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
10019   "TARGET_ARM && arm_arch5"
10020   "
10021   {
10022     rtx t1, t2, t3;
10023
10024     t1 = gen_reg_rtx (SImode);
10025     t2 = gen_reg_rtx (SImode);
10026     t3 = gen_reg_rtx (SImode);
10027
10028     emit_insn (gen_negsi2 (t1, operands[1]));
10029     emit_insn (gen_andsi3 (t2, operands[1], t1));
10030     emit_insn (gen_clzsi2 (t3, t2));
10031     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10032     DONE;
10033   }"
10034 )
10035
10036 (define_expand "ctzsi2"
10037   [(set (match_operand:SI 0 "s_register_operand" "")
10038         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10039   "TARGET_ARM && arm_arch5"
10040   "
10041   {
10042     rtx t1, t2, t3;
10043
10044     t1 = gen_reg_rtx (SImode);
10045     t2 = gen_reg_rtx (SImode);
10046     t3 = gen_reg_rtx (SImode);
10047
10048     emit_insn (gen_negsi2 (t1, operands[1]));
10049     emit_insn (gen_andsi3 (t2, operands[1], t1));
10050     emit_insn (gen_clzsi2 (t3, t2));
10051     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10052     DONE;
10053   }"
10054 )
10055
10056 ;; V5E instructions.
10057
10058 (define_insn "prefetch"
10059   [(prefetch (match_operand:SI 0 "address_operand" "p")
10060              (match_operand:SI 1 "" "")
10061              (match_operand:SI 2 "" ""))]
10062   "TARGET_ARM && arm_arch5e"
10063   "pld\\t%a0")
10064
10065 ;; General predication pattern
10066
10067 (define_cond_exec
10068   [(match_operator 0 "arm_comparison_operator"
10069     [(match_operand 1 "cc_register" "")
10070      (const_int 0)])]
10071   "TARGET_ARM"
10072   ""
10073 )
10074
10075 (define_insn "prologue_use"
10076   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10077   ""
10078   "%@ %0 needed for prologue"
10079 )
10080
10081 ;; Load the FPA co-processor patterns
10082 (include "fpa.md")
10083 ;; Load the Maverick co-processor patterns
10084 (include "cirrus.md")
10085 ;; Load the Intel Wireless Multimedia Extension patterns
10086 (include "iwmmxt.md")
10087 ;; Load the VFP co-processor patterns
10088 (include "vfp.md")
10089