OSDN Git Service

* arm.md (storehi): Avoid use of explicit subreg.
[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  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 ; PROG_MODE attribute is used to determine whether condition codes are
132 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
133 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
134 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
135
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
139
140 ;; Operand number of an input operand that is shifted.  Zero if the
141 ;; given instruction does not shift one of its input operands.
142 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 (define_attr "shift" "" (const_int 0))
144
145 ; Floating Point Unit.  If we only have floating point emulation, then there
146 ; is no point in scheduling the floating point insns.  (Well, for best
147 ; performance we should try and group them together).
148 (define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
149   (const (symbol_ref "arm_fpu_attr")))
150
151 ; LENGTH of an instruction (in bytes)
152 (define_attr "length" "" (const_int 4))
153
154 ; POOL_RANGE is how far away from a constant pool entry that this insn
155 ; can be placed.  If the distance is zero, then this insn will never
156 ; reference the pool.
157 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
158 ; before its address.
159 (define_attr "pool_range" "" (const_int 0))
160 (define_attr "neg_pool_range" "" (const_int 0))
161
162 ; An assembler sequence may clobber the condition codes without us knowing.
163 ; If such an insn references the pool, then we have no way of knowing how,
164 ; so use the most conservative value for pool_range.
165 (define_asm_attributes
166  [(set_attr "conds" "clob")
167   (set_attr "length" "4")
168   (set_attr "pool_range" "250")])
169
170 ; TYPE attribute is used to detect floating point instructions which, if
171 ; running on a co-processor can run in parallel with other, basic instructions
172 ; If write-buffer scheduling is enabled then it can also be used in the
173 ; scheduling of writes.
174
175 ; Classification of each insn
176 ; normal        any data instruction that doesn't hit memory or fp regs
177 ; mult          a multiply instruction
178 ; block         blockage insn, this blocks all functional units
179 ; float         a floating point arithmetic operation (subject to expansion)
180 ; fdivd         DFmode floating point division
181 ; fdivs         SFmode floating point division
182 ; fmul          Floating point multiply
183 ; ffmul         Fast floating point multiply
184 ; farith        Floating point arithmetic (4 cycle)
185 ; ffarith       Fast floating point arithmetic (2 cycle)
186 ; float_em      a floating point arithmetic operation that is normally emulated
187 ;               even on a machine with an fpa.
188 ; f_load        a floating point load from memory
189 ; f_store       a floating point store to memory
190 ; f_mem_r       a transfer of a floating point register to a real reg via mem
191 ; r_mem_f       the reverse of f_mem_r
192 ; f_2_r         fast transfer float to arm (no memory needed)
193 ; r_2_f         fast transfer arm to float
194 ; call          a subroutine call
195 ; load          any load from memory
196 ; store1        store 1 word to memory from arm registers
197 ; store2        store 2 words
198 ; store3        store 3 words
199 ; store4        store 4 words
200 ;  Additions for Cirrus Maverick co-processor:
201 ; mav_farith    Floating point arithmetic (4 cycle)
202 ; mav_dmult     Double multiplies (7 cycle)
203 ;
204 (define_attr "type"
205         "normal,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,call,load,store1,store2,store3,store4,mav_farith,mav_dmult" 
206         (const_string "normal"))
207
208 ; Load scheduling, set from the arm_ld_sched variable
209 ; initialized by arm_override_options() 
210 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
211
212 ; condition codes: this one is used by final_prescan_insn to speed up
213 ; conditionalizing instructions.  It saves having to scan the rtl to see if
214 ; it uses or alters the condition codes.
215
216 ; USE means that the condition codes are used by the insn in the process of
217 ;   outputting code, this means (at present) that we can't use the insn in
218 ;   inlined branches
219 ;
220 ; SET means that the purpose of the insn is to set the condition codes in a
221 ;   well defined manner.
222 ;
223 ; CLOB means that the condition codes are altered in an undefined manner, if
224 ;   they are altered at all
225 ;
226 ; JUMP_CLOB is used when the condition cannot be represented by a single
227 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
228 ;
229 ; NOCOND means that the condition codes are neither altered nor affect the
230 ;   output of this insn
231
232 (define_attr "conds" "use,set,clob,jump_clob,nocond"
233         (if_then_else (eq_attr "type" "call")
234          (if_then_else (eq_attr "prog_mode" "prog32")
235           (const_string "clob") (const_string "nocond"))
236          (const_string "nocond")))
237
238 ; Predicable means that the insn can be conditionally executed based on
239 ; an automatically added predicate (additional patterns are generated by 
240 ; gen...).  We default to 'no' because no Thumb patterns match this rule
241 ; and not all ARM patterns do.
242 (define_attr "predicable" "no,yes" (const_string "no"))
243
244 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
245 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
246 ; suffer blockages enough to warrant modelling this (and it can adversely
247 ; affect the schedule).
248 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
249
250 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
251 ; to stall the processor.  Used with model_wbuf above.
252 (define_attr "write_conflict" "no,yes"
253   (if_then_else (eq_attr "type"
254                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
255                 (const_string "yes")
256                 (const_string "no")))
257
258 ; Classify the insns into those that take one cycle and those that take more
259 ; than one on the main cpu execution unit.
260 (define_attr "core_cycles" "single,multi"
261   (if_then_else (eq_attr "type"
262                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
263                 (const_string "single")
264                 (const_string "multi")))
265
266 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
267 ;; distant label.  Only applicable to Thumb code.
268 (define_attr "far_jump" "yes,no" (const_string "no"))
269
270 (define_automaton "arm")
271
272 ;; Write buffer
273 ;
274 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
275 ;
276 ; The write buffer on some of the arm6 processors is hard to model exactly.
277 ; There is room in the buffer for up to two addresses and up to eight words
278 ; of memory, but the two needn't be split evenly.  When writing the two
279 ; addresses are fully pipelined.  However, a read from memory that is not
280 ; currently in the cache will block until the writes have completed.
281 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
282 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
283 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
284 ; cycle to add as well.
285 (define_cpu_unit "write_buf" "arm")
286
287 ;; Write blockage unit
288 ;
289 ; The write_blockage unit models (partially), the fact that reads will stall
290 ; until the write buffer empties.
291 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
292 ; so we don't model them here
293 (define_cpu_unit "write_blockage" "arm")
294
295 ;; Core
296 ;
297 (define_cpu_unit "core" "arm")
298
299 (define_insn_reservation "r_mem_f_wbuf" 5
300   (and (eq_attr "model_wbuf" "yes")
301        (eq_attr "type" "r_mem_f"))
302   "core+write_buf*3")
303
304 (define_insn_reservation "store1_wbuf" 5
305   (and (eq_attr "model_wbuf" "yes")
306        (eq_attr "type" "store1"))
307   "core+write_buf*3+write_blockage*5")
308
309 (define_insn_reservation "store2_wbuf" 7
310   (and (eq_attr "model_wbuf" "yes")
311        (eq_attr "type" "store2"))
312   "core+write_buf*4+write_blockage*7")
313
314 (define_insn_reservation "store3_wbuf" 9
315   (and (eq_attr "model_wbuf" "yes")
316        (eq_attr "type" "store3"))
317   "core+write_buf*5+write_blockage*9")
318
319 (define_insn_reservation "store4_wbuf" 11
320   (and (eq_attr "model_wbuf" "yes")
321        (eq_attr "type" "store4"))
322   "core+write_buf*6+write_blockage*11")
323
324 (define_insn_reservation "store2" 3
325   (and (eq_attr "model_wbuf" "no")
326        (eq_attr "type" "store2"))
327   "core*3")
328
329 (define_insn_reservation "store3" 4
330   (and (eq_attr "model_wbuf" "no")
331        (eq_attr "type" "store3"))
332   "core*4")
333
334 (define_insn_reservation "store4" 5
335   (and (eq_attr "model_wbuf" "no")
336        (eq_attr "type" "store4"))
337   "core*5")
338
339 (define_insn_reservation "store1_ldsched" 1
340   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1"))
341   "core")
342
343 (define_insn_reservation "load_ldsched_xscale" 3
344   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
345        (eq_attr "is_xscale" "yes"))
346   "core")
347
348 (define_insn_reservation "load_ldsched" 2
349   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
350        (eq_attr "is_xscale" "no"))
351   "core")
352
353 (define_insn_reservation "load_or_store" 2
354   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1"))
355   "core*2")
356
357 (define_insn_reservation "mult" 16
358   (and (eq_attr "ldsched" "no") (eq_attr "type" "mult"))
359   "core*16")
360
361 (define_insn_reservation "mult_ldsched_strongarm" 3
362   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
363        (eq_attr "type" "mult"))
364   "core*2")
365
366 (define_insn_reservation "mult_ldsched" 4
367   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
368        (eq_attr "type" "mult"))
369   "core*4")
370
371 (define_insn_reservation "multi_cycle" 32
372   (and (eq_attr "core_cycles" "multi")
373        (eq_attr "type" "!mult,load,store1,store2,store3,store4"))
374   "core*32")
375
376 (define_insn_reservation "single_cycle" 1
377   (eq_attr "core_cycles" "single")
378   "core")
379
380 \f
381 ;;---------------------------------------------------------------------------
382 ;; Insn patterns
383 ;;
384 ;; Addition insns.
385
386 ;; Note: For DImode insns, there is normally no reason why operands should
387 ;; not be in the same register, what we don't want is for something being
388 ;; written to partially overlap something that is an input.
389 ;; Cirrus 64bit additions should not be split because we have a native
390 ;; 64bit addition instructions.
391
392 (define_expand "adddi3"
393  [(parallel
394    [(set (match_operand:DI           0 "s_register_operand" "")
395           (plus:DI (match_operand:DI 1 "s_register_operand" "")
396                    (match_operand:DI 2 "s_register_operand" "")))
397     (clobber (reg:CC CC_REGNUM))])]
398   "TARGET_EITHER"
399   "
400   if (TARGET_CIRRUS)
401     {
402       if (!cirrus_fp_register (operands[0], DImode))
403         operands[0] = force_reg (DImode, operands[0]);
404       if (!cirrus_fp_register (operands[1], DImode))
405         operands[1] = force_reg (DImode, operands[1]);
406       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
407       DONE;
408     }
409
410   if (TARGET_THUMB)
411     {
412       if (GET_CODE (operands[1]) != REG)
413         operands[1] = force_reg (SImode, operands[1]);
414       if (GET_CODE (operands[2]) != REG)
415         operands[2] = force_reg (SImode, operands[2]);
416      }
417   "
418 )
419
420 (define_insn "*thumb_adddi3"
421   [(set (match_operand:DI          0 "register_operand" "=l")
422         (plus:DI (match_operand:DI 1 "register_operand" "%0")
423                  (match_operand:DI 2 "register_operand" "l")))
424    (clobber (reg:CC CC_REGNUM))
425   ]
426   "TARGET_THUMB"
427   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
428   [(set_attr "length" "4")]
429 )
430
431 (define_insn_and_split "*arm_adddi3"
432   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
433         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
434                  (match_operand:DI 2 "s_register_operand" "r,  0")))
435    (clobber (reg:CC CC_REGNUM))]
436   "TARGET_ARM && !TARGET_CIRRUS"
437   "#"
438   "TARGET_ARM && reload_completed"
439   [(parallel [(set (reg:CC_C CC_REGNUM)
440                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
441                                  (match_dup 1)))
442               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
443    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
444                                (plus:SI (match_dup 4) (match_dup 5))))]
445   "
446   {
447     operands[3] = gen_highpart (SImode, operands[0]);
448     operands[0] = gen_lowpart (SImode, operands[0]);
449     operands[4] = gen_highpart (SImode, operands[1]);
450     operands[1] = gen_lowpart (SImode, operands[1]);
451     operands[5] = gen_highpart (SImode, operands[2]);
452     operands[2] = gen_lowpart (SImode, operands[2]);
453   }"
454   [(set_attr "conds" "clob")
455    (set_attr "length" "8")]
456 )
457
458 (define_insn_and_split "*adddi_sesidi_di"
459   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
460         (plus:DI (sign_extend:DI
461                   (match_operand:SI 2 "s_register_operand" "r,r"))
462                  (match_operand:DI 1 "s_register_operand" "r,0")))
463    (clobber (reg:CC CC_REGNUM))]
464   "TARGET_ARM && !TARGET_CIRRUS"
465   "#"
466   "TARGET_ARM && reload_completed"
467   [(parallel [(set (reg:CC_C CC_REGNUM)
468                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
469                                  (match_dup 1)))
470               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
471    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
472                                (plus:SI (ashiftrt:SI (match_dup 2)
473                                                      (const_int 31))
474                                         (match_dup 4))))]
475   "
476   {
477     operands[3] = gen_highpart (SImode, operands[0]);
478     operands[0] = gen_lowpart (SImode, operands[0]);
479     operands[4] = gen_highpart (SImode, operands[1]);
480     operands[1] = gen_lowpart (SImode, operands[1]);
481     operands[2] = gen_lowpart (SImode, operands[2]);
482   }"
483   [(set_attr "conds" "clob")
484    (set_attr "length" "8")]
485 )
486
487 (define_insn_and_split "*adddi_zesidi_di"
488   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
489         (plus:DI (zero_extend:DI
490                   (match_operand:SI 2 "s_register_operand" "r,r"))
491                  (match_operand:DI 1 "s_register_operand" "r,0")))
492    (clobber (reg:CC CC_REGNUM))]
493   "TARGET_ARM && !TARGET_CIRRUS"
494   "#"
495   "TARGET_ARM && reload_completed"
496   [(parallel [(set (reg:CC_C CC_REGNUM)
497                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
498                                  (match_dup 1)))
499               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
500    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
501                                (plus:SI (match_dup 4) (const_int 0))))]
502   "
503   {
504     operands[3] = gen_highpart (SImode, operands[0]);
505     operands[0] = gen_lowpart (SImode, operands[0]);
506     operands[4] = gen_highpart (SImode, operands[1]);
507     operands[1] = gen_lowpart (SImode, operands[1]);
508     operands[2] = gen_lowpart (SImode, operands[2]);
509   }"
510   [(set_attr "conds" "clob")
511    (set_attr "length" "8")]
512 )
513
514 (define_expand "addsi3"
515   [(set (match_operand:SI          0 "s_register_operand" "")
516         (plus:SI (match_operand:SI 1 "s_register_operand" "")
517                  (match_operand:SI 2 "reg_or_int_operand" "")))]
518   "TARGET_EITHER"
519   "
520   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
521     {
522       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
523                           operands[1],
524                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
525       DONE;
526     }
527   "
528 )
529
530 ; If there is a scratch available, this will be faster than synthesizing the
531 ; addition.
532 (define_peephole2
533   [(match_scratch:SI 3 "r")
534    (set (match_operand:SI          0 "s_register_operand" "")
535         (plus:SI (match_operand:SI 1 "s_register_operand" "")
536                  (match_operand:SI 2 "const_int_operand"  "")))]
537   "TARGET_ARM &&
538    !(const_ok_for_arm (INTVAL (operands[2]))
539      || const_ok_for_arm (-INTVAL (operands[2])))
540     && const_ok_for_arm (~INTVAL (operands[2]))"
541   [(set (match_dup 3) (match_dup 2))
542    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
543   ""
544 )
545
546 (define_insn_and_split "*arm_addsi3"
547   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
548         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
549                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
550   "TARGET_ARM"
551   "@
552    add%?\\t%0, %1, %2
553    sub%?\\t%0, %1, #%n2
554    #"
555   "TARGET_ARM &&
556    GET_CODE (operands[2]) == CONST_INT
557    && !(const_ok_for_arm (INTVAL (operands[2]))
558         || const_ok_for_arm (-INTVAL (operands[2])))"
559   [(clobber (const_int 0))]
560   "
561   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
562                       operands[1], 0);
563   DONE;
564   "
565   [(set_attr "length" "4,4,16")
566    (set_attr "predicable" "yes")]
567 )
568
569 ;; Register group 'k' is a single register group containing only the stack
570 ;; register.  Trying to reload it will always fail catastrophically,
571 ;; so never allow those alternatives to match if reloading is needed.
572
573 (define_insn "*thumb_addsi3"
574   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
575         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
576                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
577   "TARGET_THUMB"
578   "*
579    static const char * const asms[] = 
580    {
581      \"add\\t%0, %0, %2\",
582      \"sub\\t%0, %0, #%n2\",
583      \"add\\t%0, %1, %2\",
584      \"add\\t%0, %0, %2\",
585      \"add\\t%0, %0, %2\",
586      \"add\\t%0, %1, %2\",
587      \"add\\t%0, %1, %2\"
588    };
589    if ((which_alternative == 2 || which_alternative == 6)
590        && GET_CODE (operands[2]) == CONST_INT
591        && INTVAL (operands[2]) < 0)
592      return \"sub\\t%0, %1, #%n2\";
593    return asms[which_alternative];
594   "
595   [(set_attr "length" "2")]
596 )
597
598 ;; Reloading and elimination of the frame pointer can
599 ;; sometimes cause this optimization to be missed.
600 (define_peephole2
601   [(set (match_operand:SI 0 "register_operand" "")
602         (match_operand:SI 1 "const_int_operand" ""))
603    (set (match_dup 0)
604         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
605   "TARGET_THUMB
606    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
607    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
608    && (INTVAL (operands[1]) & 3) == 0"
609   [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
610   ""
611 )
612
613 (define_insn "*addsi3_compare0"
614   [(set (reg:CC_NOOV CC_REGNUM)
615         (compare:CC_NOOV
616          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
617                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
618          (const_int 0)))
619    (set (match_operand:SI 0 "s_register_operand" "=r,r")
620         (plus:SI (match_dup 1) (match_dup 2)))]
621   "TARGET_ARM"
622   "@
623    add%?s\\t%0, %1, %2
624    sub%?s\\t%0, %1, #%n2"
625   [(set_attr "conds" "set")]
626 )
627
628 (define_insn "*addsi3_compare0_scratch"
629   [(set (reg:CC_NOOV CC_REGNUM)
630         (compare:CC_NOOV
631          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
632                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
633          (const_int 0)))]
634   "TARGET_ARM"
635   "@
636    cmn%?\\t%0, %1
637    cmp%?\\t%0, #%n1"
638   [(set_attr "conds" "set")]
639 )
640
641 ;; These patterns are the same ones as the two regular addsi3_compare0
642 ;; patterns, except we write them slightly different - the combiner
643 ;; tends to generate them this way.
644 (define_insn "*addsi3_compare0_for_combiner"
645   [(set (reg:CC CC_REGNUM)
646         (compare:CC
647          (match_operand:SI 1 "s_register_operand" "r,r")
648          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
649    (set (match_operand:SI 0 "s_register_operand" "=r,r")
650         (plus:SI (match_dup 1) (match_dup 2)))]
651   "TARGET_ARM"
652   "@
653    add%?s\\t%0, %1, %2
654    sub%?s\\t%0, %1, #%n2"
655   [(set_attr "conds" "set")]
656 )
657
658 (define_insn "*addsi3_compare0_scratch_for_combiner"
659   [(set (reg:CC CC_REGNUM)
660         (compare:CC
661          (match_operand:SI 0 "s_register_operand" "r,r")
662          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
663   "TARGET_ARM"
664   "@
665    cmn%?\\t%0, %1
666    cmp%?\\t%0, #%n1"
667   [(set_attr "conds" "set")]
668 )
669
670 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
671 ;; addend is a constant.
672 (define_insn "*cmpsi2_addneg"
673   [(set (reg:CC CC_REGNUM)
674         (compare:CC
675          (match_operand:SI 1 "s_register_operand" "r,r")
676          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
677    (set (match_operand:SI 0 "s_register_operand" "=r,r")
678         (plus:SI (match_dup 1)
679                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
680   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
681   "@
682    sub%?s\\t%0, %1, %2
683    add%?s\\t%0, %1, #%n2"
684   [(set_attr "conds" "set")]
685 )
686
687 ;; Convert the sequence
688 ;;  sub  rd, rn, #1
689 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
690 ;;  bne  dest
691 ;; into
692 ;;  subs rd, rn, #1
693 ;;  bcs  dest   ((unsigned)rn >= 1)
694 ;; similarly for the beq variant using bcc.
695 ;; This is a common looping idiom (while (n--))
696 (define_peephole2
697   [(set (match_operand:SI 0 "s_register_operand" "")
698         (plus:SI (match_operand:SI 1 "s_register_operand" "")
699                  (const_int -1)))
700    (set (match_operand 2 "cc_register" "")
701         (compare (match_dup 0) (const_int -1)))
702    (set (pc)
703         (if_then_else (match_operator 3 "equality_operator"
704                        [(match_dup 2) (const_int 0)])
705                       (match_operand 4 "" "")
706                       (match_operand 5 "" "")))]
707   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
708   [(parallel[
709     (set (match_dup 2)
710          (compare:CC
711           (match_dup 1) (const_int 1)))
712     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
713    (set (pc)
714         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
715                       (match_dup 4)
716                       (match_dup 5)))]
717   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
718    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
719                                   ? GEU : LTU),
720                                  VOIDmode, 
721                                  operands[2], const0_rtx);"
722 )
723
724 ;; The next four insns work because they compare the result with one of
725 ;; the operands, and we know that the use of the condition code is
726 ;; either GEU or LTU, so we can use the carry flag from the addition
727 ;; instead of doing the compare a second time.
728 (define_insn "*addsi3_compare_op1"
729   [(set (reg:CC_C CC_REGNUM)
730         (compare:CC_C
731          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
732                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
733          (match_dup 1)))
734    (set (match_operand:SI 0 "s_register_operand" "=r,r")
735         (plus:SI (match_dup 1) (match_dup 2)))]
736   "TARGET_ARM"
737   "@
738    add%?s\\t%0, %1, %2
739    sub%?s\\t%0, %1, #%n2"
740   [(set_attr "conds" "set")]
741 )
742
743 (define_insn "*addsi3_compare_op2"
744   [(set (reg:CC_C CC_REGNUM)
745         (compare:CC_C
746          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
747                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
748          (match_dup 2)))
749    (set (match_operand:SI 0 "s_register_operand" "=r,r")
750         (plus:SI (match_dup 1) (match_dup 2)))]
751   "TARGET_ARM"
752   "@
753    add%?s\\t%0, %1, %2
754    sub%?s\\t%0, %1, #%n2"
755   [(set_attr "conds" "set")]
756 )
757
758 (define_insn "*compare_addsi2_op0"
759   [(set (reg:CC_C CC_REGNUM)
760         (compare:CC_C
761          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
762                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
763          (match_dup 0)))]
764   "TARGET_ARM"
765   "@
766    cmn%?\\t%0, %1
767    cmp%?\\t%0, #%n1"
768   [(set_attr "conds" "set")]
769 )
770
771 (define_insn "*compare_addsi2_op1"
772   [(set (reg:CC_C CC_REGNUM)
773         (compare:CC_C
774          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
775                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
776          (match_dup 1)))]
777   "TARGET_ARM"
778   "@
779    cmn%?\\t%0, %1
780    cmp%?\\t%0, #%n1"
781   [(set_attr "conds" "set")]
782 )
783
784 (define_insn "*addsi3_carryin"
785   [(set (match_operand:SI 0 "s_register_operand" "=r")
786         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
787                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
788                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
789   "TARGET_ARM"
790   "adc%?\\t%0, %1, %2"
791   [(set_attr "conds" "use")]
792 )
793
794 (define_insn "*addsi3_carryin_shift"
795   [(set (match_operand:SI 0 "s_register_operand" "")
796         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
797                  (plus:SI
798                    (match_operator:SI 2 "shift_operator"
799                       [(match_operand:SI 3 "s_register_operand" "")
800                        (match_operand:SI 4 "reg_or_int_operand" "")])
801                     (match_operand:SI 1 "s_register_operand" ""))))]
802   "TARGET_ARM"
803   "adc%?\\t%0, %1, %3%S2"
804   [(set_attr "conds" "use")]
805 )
806
807 (define_insn "*addsi3_carryin_alt1"
808   [(set (match_operand:SI 0 "s_register_operand" "=r")
809         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
810                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
811                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
812   "TARGET_ARM"
813   "adc%?\\t%0, %1, %2"
814   [(set_attr "conds" "use")]
815 )
816
817 (define_insn "*addsi3_carryin_alt2"
818   [(set (match_operand:SI 0 "s_register_operand" "=r")
819         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
820                           (match_operand:SI 1 "s_register_operand" "r"))
821                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
822   "TARGET_ARM"
823   "adc%?\\t%0, %1, %2"
824   [(set_attr "conds" "use")]
825 )
826
827 (define_insn "*addsi3_carryin_alt3"
828   [(set (match_operand:SI 0 "s_register_operand" "=r")
829         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
830                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
831                  (match_operand:SI 1 "s_register_operand" "r")))]
832   "TARGET_ARM"
833   "adc%?\\t%0, %1, %2"
834   [(set_attr "conds" "use")]
835 )
836
837 (define_insn "incscc"
838   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
839         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
840                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
841                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
842   "TARGET_ARM"
843   "@
844   add%d2\\t%0, %1, #1
845   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
846   [(set_attr "conds" "use")
847    (set_attr "length" "4,8")]
848 )
849
850 (define_expand "addsf3"
851   [(set (match_operand:SF          0 "s_register_operand" "")
852         (plus:SF (match_operand:SF 1 "s_register_operand" "")
853                  (match_operand:SF 2 "fpa_add_operand" "")))]
854   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
855   "
856   if (TARGET_CIRRUS
857       && !cirrus_fp_register (operands[2], SFmode))
858     operands[2] = force_reg (SFmode, operands[2]);
859 ")
860
861 (define_expand "adddf3"
862   [(set (match_operand:DF          0 "s_register_operand" "")
863         (plus:DF (match_operand:DF 1 "s_register_operand" "")
864                  (match_operand:DF 2 "fpa_add_operand" "")))]
865   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
866   "
867   if (TARGET_CIRRUS
868       && !cirrus_fp_register (operands[2], DFmode))
869     operands[2] = force_reg (DFmode, operands[2]);
870 ")
871
872 (define_expand "subdi3"
873  [(parallel
874    [(set (match_operand:DI            0 "s_register_operand" "")
875           (minus:DI (match_operand:DI 1 "s_register_operand" "")
876                     (match_operand:DI 2 "s_register_operand" "")))
877     (clobber (reg:CC CC_REGNUM))])]
878   "TARGET_EITHER"
879   "
880   if (TARGET_CIRRUS
881       && TARGET_ARM
882       && cirrus_fp_register (operands[0], DImode)
883       && cirrus_fp_register (operands[1], DImode))
884     {
885       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
886       DONE;
887     }
888
889   if (TARGET_THUMB)
890     {
891       if (GET_CODE (operands[1]) != REG)
892         operands[1] = force_reg (SImode, operands[1]);
893       if (GET_CODE (operands[2]) != REG)
894         operands[2] = force_reg (SImode, operands[2]);
895      }  
896   "
897 )
898
899 (define_insn "*arm_subdi3"
900   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
901         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
902                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
903    (clobber (reg:CC CC_REGNUM))]
904   "TARGET_ARM"
905   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
906   [(set_attr "conds" "clob")
907    (set_attr "length" "8")]
908 )
909
910 (define_insn "*thumb_subdi3"
911   [(set (match_operand:DI           0 "register_operand" "=l")
912         (minus:DI (match_operand:DI 1 "register_operand"  "0")
913                   (match_operand:DI 2 "register_operand"  "l")))
914    (clobber (reg:CC CC_REGNUM))]
915   "TARGET_THUMB"
916   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
917   [(set_attr "length" "4")]
918 )
919
920 (define_insn "*subdi_di_zesidi"
921   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
922         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
923                   (zero_extend:DI
924                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
925    (clobber (reg:CC CC_REGNUM))]
926   "TARGET_ARM"
927   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
928   [(set_attr "conds" "clob")
929    (set_attr "length" "8")]
930 )
931
932 (define_insn "*subdi_di_sesidi"
933   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
934         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
935                   (sign_extend:DI
936                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
937    (clobber (reg:CC CC_REGNUM))]
938   "TARGET_ARM"
939   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
940   [(set_attr "conds" "clob")
941    (set_attr "length" "8")]
942 )
943
944 (define_insn "*subdi_zesidi_di"
945   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
946         (minus:DI (zero_extend:DI
947                    (match_operand:SI 2 "s_register_operand"  "r,r"))
948                   (match_operand:DI  1 "s_register_operand" "?r,0")))
949    (clobber (reg:CC CC_REGNUM))]
950   "TARGET_ARM"
951   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
952   [(set_attr "conds" "clob")
953    (set_attr "length" "8")]
954 )
955
956 (define_insn "*subdi_sesidi_di"
957   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
958         (minus:DI (sign_extend:DI
959                    (match_operand:SI 2 "s_register_operand"   "r,r"))
960                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
961    (clobber (reg:CC CC_REGNUM))]
962   "TARGET_ARM"
963   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
964   [(set_attr "conds" "clob")
965    (set_attr "length" "8")]
966 )
967
968 (define_insn "*subdi_zesidi_zesidi"
969   [(set (match_operand:DI            0 "s_register_operand" "=r")
970         (minus:DI (zero_extend:DI
971                    (match_operand:SI 1 "s_register_operand"  "r"))
972                   (zero_extend:DI
973                    (match_operand:SI 2 "s_register_operand"  "r"))))
974    (clobber (reg:CC CC_REGNUM))]
975   "TARGET_ARM"
976   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
977   [(set_attr "conds" "clob")
978    (set_attr "length" "8")]
979 )
980
981 (define_expand "subsi3"
982   [(set (match_operand:SI           0 "s_register_operand" "")
983         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
984                   (match_operand:SI 2 "s_register_operand" "")))]
985   "TARGET_EITHER"
986   "
987   if (GET_CODE (operands[1]) == CONST_INT)
988     {
989       if (TARGET_ARM)
990         {
991           arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
992                               operands[2],
993                               (no_new_pseudos ? 0
994                                :  preserve_subexpressions_p ()));
995           DONE;
996         }
997       else /* TARGET_THUMB */
998         operands[1] = force_reg (SImode, operands[1]);
999     }
1000   "
1001 )
1002
1003 (define_insn "*thumb_subsi3_insn"
1004   [(set (match_operand:SI           0 "register_operand" "=l")
1005         (minus:SI (match_operand:SI 1 "register_operand" "l")
1006                   (match_operand:SI 2 "register_operand" "l")))]
1007   "TARGET_THUMB"
1008   "sub\\t%0, %1, %2"
1009   [(set_attr "length" "2")]
1010 )
1011
1012 (define_insn_and_split "*arm_subsi3_insn"
1013   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
1014         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1015                   (match_operand:SI 2 "s_register_operand" "r,r")))]
1016   "TARGET_ARM"
1017   "@
1018    rsb%?\\t%0, %2, %1
1019    #"
1020   "TARGET_ARM
1021    && GET_CODE (operands[1]) == CONST_INT
1022    && !const_ok_for_arm (INTVAL (operands[1]))"
1023   [(clobber (const_int 0))]
1024   "
1025   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1026                       operands[2], 0);
1027   DONE;
1028   "
1029   [(set_attr "length" "4,16")
1030    (set_attr "predicable" "yes")]
1031 )
1032
1033 (define_peephole2
1034   [(match_scratch:SI 3 "r")
1035    (set (match_operand:SI           0 "s_register_operand" "")
1036         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1037                   (match_operand:SI 2 "s_register_operand" "")))]
1038   "TARGET_ARM
1039    && !const_ok_for_arm (INTVAL (operands[1]))
1040    && const_ok_for_arm (~INTVAL (operands[1]))"
1041   [(set (match_dup 3) (match_dup 1))
1042    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1043   ""
1044 )
1045
1046 (define_insn "*subsi3_compare0"
1047   [(set (reg:CC_NOOV CC_REGNUM)
1048         (compare:CC_NOOV
1049          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1050                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1051          (const_int 0)))
1052    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1053         (minus:SI (match_dup 1) (match_dup 2)))]
1054   "TARGET_ARM"
1055   "@
1056    sub%?s\\t%0, %1, %2
1057    rsb%?s\\t%0, %2, %1"
1058   [(set_attr "conds" "set")]
1059 )
1060
1061 (define_insn "decscc"
1062   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1063         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1064                   (match_operator:SI 2 "arm_comparison_operator"
1065                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1066   "TARGET_ARM"
1067   "@
1068    sub%d2\\t%0, %1, #1
1069    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1070   [(set_attr "conds" "use")
1071    (set_attr "length" "*,8")]
1072 )
1073
1074 (define_expand "subsf3"
1075   [(set (match_operand:SF           0 "s_register_operand" "")
1076         (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1077                   (match_operand:SF 2 "fpa_rhs_operand" "")))]
1078   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1079   "
1080   if (TARGET_CIRRUS)
1081     {
1082       if (!cirrus_fp_register (operands[1], SFmode))
1083         operands[1] = force_reg (SFmode, operands[1]);
1084       if (!cirrus_fp_register (operands[2], SFmode))
1085         operands[2] = force_reg (SFmode, operands[2]);
1086     }
1087 ")
1088
1089 (define_expand "subdf3"
1090   [(set (match_operand:DF           0 "s_register_operand" "")
1091         (minus:DF (match_operand:DF 1 "fpa_rhs_operand"     "")
1092                   (match_operand:DF 2 "fpa_rhs_operand"    "")))]
1093   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1094   "
1095   if (TARGET_CIRRUS)
1096     {
1097        if (!cirrus_fp_register (operands[1], DFmode))
1098          operands[1] = force_reg (DFmode, operands[1]);
1099        if (!cirrus_fp_register (operands[2], DFmode))
1100          operands[2] = force_reg (DFmode, operands[2]);
1101     }
1102 ")
1103
1104 \f
1105 ;; Multiplication insns
1106
1107 (define_expand "mulsi3"
1108   [(set (match_operand:SI          0 "s_register_operand" "")
1109         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1110                  (match_operand:SI 1 "s_register_operand" "")))]
1111   "TARGET_EITHER"
1112   ""
1113 )
1114
1115 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1116 (define_insn "*arm_mulsi3"
1117   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1118         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1119                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1120   "TARGET_ARM"
1121   "mul%?\\t%0, %2, %1"
1122   [(set_attr "type" "mult")
1123    (set_attr "predicable" "yes")]
1124 )
1125
1126 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1127 ; 1 and 2; are the same, because reload will make operand 0 match 
1128 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1129 ; this by adding another alternative to match this case, and then `reload' 
1130 ; it ourselves.  This alternative must come first.
1131 (define_insn "*thumb_mulsi3"
1132   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1133         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1134                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1135   "TARGET_THUMB"
1136   "*
1137   if (which_alternative < 2)
1138     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1139   else
1140     return \"mul\\t%0, %0, %2\";
1141   "
1142   [(set_attr "length" "4,4,2")
1143    (set_attr "type" "mult")]
1144 )
1145
1146 (define_insn "*mulsi3_compare0"
1147   [(set (reg:CC_NOOV CC_REGNUM)
1148         (compare:CC_NOOV (mult:SI
1149                           (match_operand:SI 2 "s_register_operand" "r,r")
1150                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1151                          (const_int 0)))
1152    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1153         (mult:SI (match_dup 2) (match_dup 1)))]
1154   "TARGET_ARM && !arm_arch_xscale"
1155   "mul%?s\\t%0, %2, %1"
1156   [(set_attr "conds" "set")
1157    (set_attr "type" "mult")]
1158 )
1159
1160 (define_insn "*mulsi_compare0_scratch"
1161   [(set (reg:CC_NOOV CC_REGNUM)
1162         (compare:CC_NOOV (mult:SI
1163                           (match_operand:SI 2 "s_register_operand" "r,r")
1164                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1165                          (const_int 0)))
1166    (clobber (match_scratch:SI 0 "=&r,&r"))]
1167   "TARGET_ARM && !arm_arch_xscale"
1168   "mul%?s\\t%0, %2, %1"
1169   [(set_attr "conds" "set")
1170    (set_attr "type" "mult")]
1171 )
1172
1173 ;; Unnamed templates to match MLA instruction.
1174
1175 (define_insn "*mulsi3addsi"
1176   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1177         (plus:SI
1178           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1179                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1180           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1181   "TARGET_ARM"
1182   "mla%?\\t%0, %2, %1, %3"
1183   [(set_attr "type" "mult")
1184    (set_attr "predicable" "yes")]
1185 )
1186
1187 (define_insn "*mulsi3addsi_compare0"
1188   [(set (reg:CC_NOOV CC_REGNUM)
1189         (compare:CC_NOOV
1190          (plus:SI (mult:SI
1191                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1192                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1193                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1194          (const_int 0)))
1195    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1196         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1197                  (match_dup 3)))]
1198   "TARGET_ARM && !arm_arch_xscale"
1199   "mla%?s\\t%0, %2, %1, %3"
1200   [(set_attr "conds" "set")
1201    (set_attr "type" "mult")]
1202 )
1203
1204 (define_insn "*mulsi3addsi_compare0_scratch"
1205   [(set (reg:CC_NOOV CC_REGNUM)
1206         (compare:CC_NOOV
1207          (plus:SI (mult:SI
1208                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1209                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1210                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1211          (const_int 0)))
1212    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1213   "TARGET_ARM && !arm_arch_xscale"
1214   "mla%?s\\t%0, %2, %1, %3"
1215   [(set_attr "conds" "set")
1216    (set_attr "type" "mult")]
1217 )
1218
1219 ;; Unnamed template to match long long multiply-accumlate (smlal)
1220
1221 (define_insn "*mulsidi3adddi"
1222   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1223         (plus:DI
1224          (mult:DI
1225           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1226           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1227          (match_operand:DI 1 "s_register_operand" "0")))]
1228   "TARGET_ARM && arm_fast_multiply"
1229   "smlal%?\\t%Q0, %R0, %3, %2"
1230   [(set_attr "type" "mult")
1231    (set_attr "predicable" "yes")]
1232 )
1233
1234 (define_insn "mulsidi3"
1235   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1236         (mult:DI
1237          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1238          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1239   "TARGET_ARM && arm_fast_multiply"
1240   "smull%?\\t%Q0, %R0, %1, %2"
1241   [(set_attr "type" "mult")
1242    (set_attr "predicable" "yes")]
1243 )
1244
1245 (define_insn "umulsidi3"
1246   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1247         (mult:DI
1248          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1249          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1250   "TARGET_ARM && arm_fast_multiply"
1251   "umull%?\\t%Q0, %R0, %1, %2"
1252   [(set_attr "type" "mult")
1253    (set_attr "predicable" "yes")]
1254 )
1255
1256 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1257
1258 (define_insn "*umulsidi3adddi"
1259   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1260         (plus:DI
1261          (mult:DI
1262           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1263           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1264          (match_operand:DI 1 "s_register_operand" "0")))]
1265   "TARGET_ARM && arm_fast_multiply"
1266   "umlal%?\\t%Q0, %R0, %3, %2"
1267   [(set_attr "type" "mult")
1268    (set_attr "predicable" "yes")]
1269 )
1270
1271 (define_insn "smulsi3_highpart"
1272   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1273         (truncate:SI
1274          (lshiftrt:DI
1275           (mult:DI
1276            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1277            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1278           (const_int 32))))
1279    (clobber (match_scratch:SI 3 "=&r,&r"))]
1280   "TARGET_ARM && arm_fast_multiply"
1281   "smull%?\\t%3, %0, %2, %1"
1282   [(set_attr "type" "mult")
1283    (set_attr "predicable" "yes")]
1284 )
1285
1286 (define_insn "umulsi3_highpart"
1287   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1288         (truncate:SI
1289          (lshiftrt:DI
1290           (mult:DI
1291            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1292            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1293           (const_int 32))))
1294    (clobber (match_scratch:SI 3 "=&r,&r"))]
1295   "TARGET_ARM && arm_fast_multiply"
1296   "umull%?\\t%3, %0, %2, %1"
1297   [(set_attr "type" "mult")
1298    (set_attr "predicable" "yes")]
1299 )
1300
1301 (define_insn "mulhisi3"
1302   [(set (match_operand:SI 0 "s_register_operand" "=r")
1303         (mult:SI (sign_extend:SI
1304                   (match_operand:HI 1 "s_register_operand" "%r"))
1305                  (sign_extend:SI
1306                   (match_operand:HI 2 "s_register_operand" "r"))))]
1307   "TARGET_ARM && arm_arch5e"
1308   "smulbb%?\\t%0, %1, %2"
1309   [(set_attr "type" "mult")
1310    (set_attr "predicable" "yes")]
1311 )
1312
1313 (define_insn "*mulhisi3tb"
1314   [(set (match_operand:SI 0 "s_register_operand" "=r")
1315         (mult:SI (ashiftrt:SI
1316                   (match_operand:SI 1 "s_register_operand" "r")
1317                   (const_int 16))
1318                  (sign_extend:SI
1319                   (match_operand:HI 2 "s_register_operand" "r"))))]
1320   "TARGET_ARM && arm_arch5e"
1321   "smultb%?\\t%0, %1, %2"
1322   [(set_attr "type" "mult")
1323    (set_attr "predicable" "yes")]
1324 )
1325
1326 (define_insn "*mulhisi3bt"
1327   [(set (match_operand:SI 0 "s_register_operand" "=r")
1328         (mult:SI (sign_extend:SI
1329                   (match_operand:HI 1 "s_register_operand" "r"))
1330                  (ashiftrt:SI
1331                   (match_operand:SI 2 "s_register_operand" "r")
1332                   (const_int 16))))]
1333   "TARGET_ARM && arm_arch5e"
1334   "smulbt%?\\t%0, %1, %2"
1335   [(set_attr "type" "mult")
1336    (set_attr "predicable" "yes")]
1337 )
1338
1339 (define_insn "*mulhisi3tt"
1340   [(set (match_operand:SI 0 "s_register_operand" "=r")
1341         (mult:SI (ashiftrt:SI
1342                   (match_operand:SI 1 "s_register_operand" "r")
1343                   (const_int 16))
1344                  (ashiftrt:SI
1345                   (match_operand:SI 2 "s_register_operand" "r")
1346                   (const_int 16))))]
1347   "TARGET_ARM && arm_arch5e"
1348   "smultt%?\\t%0, %1, %2"
1349   [(set_attr "type" "mult")
1350    (set_attr "predicable" "yes")]
1351 )
1352
1353 (define_insn "*mulhisi3addsi"
1354   [(set (match_operand:SI 0 "s_register_operand" "=r")
1355         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1356                  (mult:SI (sign_extend:SI
1357                            (match_operand:HI 2 "s_register_operand" "%r"))
1358                           (sign_extend:SI
1359                            (match_operand:HI 3 "s_register_operand" "r")))))]
1360   "TARGET_ARM && arm_arch5e"
1361   "smlabb%?\\t%0, %2, %3, %1"
1362   [(set_attr "type" "mult")
1363    (set_attr "predicable" "yes")]
1364 )
1365
1366 (define_insn "*mulhidi3adddi"
1367   [(set (match_operand:DI 0 "s_register_operand" "=r")
1368         (plus:DI
1369           (match_operand:DI 1 "s_register_operand" "0")
1370           (mult:DI (sign_extend:DI
1371                     (match_operand:HI 2 "s_register_operand" "%r"))
1372                    (sign_extend:DI
1373                     (match_operand:HI 3 "s_register_operand" "r")))))]
1374   "TARGET_ARM && arm_arch5e"
1375   "smlalbb%?\\t%Q0, %R0, %2, %3"
1376   [(set_attr "type" "mult")
1377    (set_attr "predicable" "yes")])
1378
1379 (define_expand "mulsf3"
1380   [(set (match_operand:SF          0 "s_register_operand" "")
1381         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1382                  (match_operand:SF 2 "fpa_rhs_operand" "")))]
1383   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1384   "
1385   if (TARGET_CIRRUS
1386       && !cirrus_fp_register (operands[2], SFmode))
1387     operands[2] = force_reg (SFmode, operands[2]);
1388 ")
1389
1390 (define_expand "muldf3"
1391   [(set (match_operand:DF          0 "s_register_operand" "")
1392         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1393                  (match_operand:DF 2 "fpa_rhs_operand" "")))]
1394   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1395   "
1396   if (TARGET_CIRRUS
1397       && !cirrus_fp_register (operands[2], DFmode))
1398     operands[2] = force_reg (DFmode, operands[2]);
1399 ")
1400 \f
1401 ;; Division insns
1402
1403 (define_expand "divsf3"
1404   [(set (match_operand:SF 0 "s_register_operand" "")
1405         (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1406                 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1407   "TARGET_ARM && TARGET_HARD_FLOAT"
1408   "")
1409
1410 (define_expand "divdf3"
1411   [(set (match_operand:DF 0 "s_register_operand" "")
1412         (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1413                 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1414   "TARGET_ARM && TARGET_HARD_FLOAT"
1415   "")
1416 \f
1417 ;; Modulo insns
1418
1419 (define_expand "modsf3"
1420   [(set (match_operand:SF 0 "s_register_operand" "")
1421         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1422                 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1423   "TARGET_ARM && TARGET_HARD_FLOAT"
1424   "")
1425
1426 (define_expand "moddf3"
1427   [(set (match_operand:DF 0 "s_register_operand" "")
1428         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1429                 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1430   "TARGET_ARM && TARGET_HARD_FLOAT"
1431   "")
1432 \f
1433 ;; Boolean and,ior,xor insns
1434
1435 ;; Split up double word logical operations
1436
1437 ;; Split up simple DImode logical operations.  Simply perform the logical
1438 ;; operation on the upper and lower halves of the registers.
1439 (define_split
1440   [(set (match_operand:DI 0 "s_register_operand" "")
1441         (match_operator:DI 6 "logical_binary_operator"
1442           [(match_operand:DI 1 "s_register_operand" "")
1443            (match_operand:DI 2 "s_register_operand" "")]))]
1444   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1445   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1446    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1447   "
1448   {
1449     operands[3] = gen_highpart (SImode, operands[0]);
1450     operands[0] = gen_lowpart (SImode, operands[0]);
1451     operands[4] = gen_highpart (SImode, operands[1]);
1452     operands[1] = gen_lowpart (SImode, operands[1]);
1453     operands[5] = gen_highpart (SImode, operands[2]);
1454     operands[2] = gen_lowpart (SImode, operands[2]);
1455   }"
1456 )
1457
1458 (define_split
1459   [(set (match_operand:DI 0 "s_register_operand" "")
1460         (match_operator:DI 6 "logical_binary_operator"
1461           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1462            (match_operand:DI 1 "s_register_operand" "")]))]
1463   "TARGET_ARM && reload_completed"
1464   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1465    (set (match_dup 3) (match_op_dup:SI 6
1466                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1467                          (match_dup 4)]))]
1468   "
1469   {
1470     operands[3] = gen_highpart (SImode, operands[0]);
1471     operands[0] = gen_lowpart (SImode, operands[0]);
1472     operands[4] = gen_highpart (SImode, operands[1]);
1473     operands[1] = gen_lowpart (SImode, operands[1]);
1474     operands[5] = gen_highpart (SImode, operands[2]);
1475     operands[2] = gen_lowpart (SImode, operands[2]);
1476   }"
1477 )
1478
1479 ;; The zero extend of operand 2 means we can just copy the high part of
1480 ;; operand1 into operand0.
1481 (define_split
1482   [(set (match_operand:DI 0 "s_register_operand" "")
1483         (ior:DI
1484           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1485           (match_operand:DI 1 "s_register_operand" "")))]
1486   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1487   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1488    (set (match_dup 3) (match_dup 4))]
1489   "
1490   {
1491     operands[4] = gen_highpart (SImode, operands[1]);
1492     operands[3] = gen_highpart (SImode, operands[0]);
1493     operands[0] = gen_lowpart (SImode, operands[0]);
1494     operands[1] = gen_lowpart (SImode, operands[1]);
1495   }"
1496 )
1497
1498 ;; The zero extend of operand 2 means we can just copy the high part of
1499 ;; operand1 into operand0.
1500 (define_split
1501   [(set (match_operand:DI 0 "s_register_operand" "")
1502         (xor:DI
1503           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1504           (match_operand:DI 1 "s_register_operand" "")))]
1505   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1506   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1507    (set (match_dup 3) (match_dup 4))]
1508   "
1509   {
1510     operands[4] = gen_highpart (SImode, operands[1]);
1511     operands[3] = gen_highpart (SImode, operands[0]);
1512     operands[0] = gen_lowpart (SImode, operands[0]);
1513     operands[1] = gen_lowpart (SImode, operands[1]);
1514   }"
1515 )
1516
1517 (define_insn "anddi3"
1518   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1519         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1520                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1521   "TARGET_ARM && ! TARGET_IWMMXT"
1522   "#"
1523   [(set_attr "length" "8")]
1524 )
1525
1526 (define_insn_and_split "*anddi_zesidi_di"
1527   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1528         (and:DI (zero_extend:DI
1529                  (match_operand:SI 2 "s_register_operand" "r,r"))
1530                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1531   "TARGET_ARM"
1532   "#"
1533   "TARGET_ARM && reload_completed"
1534   ; The zero extend of operand 2 clears the high word of the output
1535   ; operand.
1536   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1537    (set (match_dup 3) (const_int 0))]
1538   "
1539   {
1540     operands[3] = gen_highpart (SImode, operands[0]);
1541     operands[0] = gen_lowpart (SImode, operands[0]);
1542     operands[1] = gen_lowpart (SImode, operands[1]);
1543   }"
1544   [(set_attr "length" "8")]
1545 )
1546
1547 (define_insn "*anddi_sesdi_di"
1548   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1549         (and:DI (sign_extend:DI
1550                  (match_operand:SI 2 "s_register_operand" "r,r"))
1551                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1552   "TARGET_ARM"
1553   "#"
1554   [(set_attr "length" "8")]
1555 )
1556
1557 (define_expand "andsi3"
1558   [(set (match_operand:SI         0 "s_register_operand" "")
1559         (and:SI (match_operand:SI 1 "s_register_operand" "")
1560                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1561   "TARGET_EITHER"
1562   "
1563   if (TARGET_ARM)
1564     {
1565       if (GET_CODE (operands[2]) == CONST_INT)
1566         {
1567           arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1568                               operands[1],
1569                               (no_new_pseudos
1570                                ? 0 : preserve_subexpressions_p ()));
1571           DONE;
1572         }
1573     }
1574   else /* TARGET_THUMB */
1575     {
1576       if (GET_CODE (operands[2]) != CONST_INT)
1577         operands[2] = force_reg (SImode, operands[2]);
1578       else
1579         {
1580           int i;
1581           
1582           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1583             {
1584               operands[2] = force_reg (SImode,
1585                                        GEN_INT (~INTVAL (operands[2])));
1586               
1587               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1588               
1589               DONE;
1590             }
1591
1592           for (i = 9; i <= 31; i++)
1593             {
1594               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1595                 {
1596                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1597                                         const0_rtx));
1598                   DONE;
1599                 }
1600               else if ((((HOST_WIDE_INT) 1) << i) - 1
1601                        == ~INTVAL (operands[2]))
1602                 {
1603                   rtx shift = GEN_INT (i);
1604                   rtx reg = gen_reg_rtx (SImode);
1605                 
1606                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1607                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1608                   
1609                   DONE;
1610                 }
1611             }
1612
1613           operands[2] = force_reg (SImode, operands[2]);
1614         }
1615     }
1616   "
1617 )
1618
1619 (define_insn_and_split "*arm_andsi3_insn"
1620   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1621         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1622                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1623   "TARGET_ARM"
1624   "@
1625    and%?\\t%0, %1, %2
1626    bic%?\\t%0, %1, #%B2
1627    #"
1628   "TARGET_ARM
1629    && GET_CODE (operands[2]) == CONST_INT
1630    && !(const_ok_for_arm (INTVAL (operands[2]))
1631         || const_ok_for_arm (~INTVAL (operands[2])))"
1632   [(clobber (const_int 0))]
1633   "
1634   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1635                        operands[1], 0);
1636   DONE;
1637   "
1638   [(set_attr "length" "4,4,16")
1639    (set_attr "predicable" "yes")]
1640 )
1641
1642 (define_insn "*thumb_andsi3_insn"
1643   [(set (match_operand:SI         0 "register_operand" "=l")
1644         (and:SI (match_operand:SI 1 "register_operand" "%0")
1645                 (match_operand:SI 2 "register_operand" "l")))]
1646   "TARGET_THUMB"
1647   "and\\t%0, %0, %2"
1648   [(set_attr "length" "2")]
1649 )
1650
1651 (define_insn "*andsi3_compare0"
1652   [(set (reg:CC_NOOV CC_REGNUM)
1653         (compare:CC_NOOV
1654          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1655                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1656          (const_int 0)))
1657    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1658         (and:SI (match_dup 1) (match_dup 2)))]
1659   "TARGET_ARM"
1660   "@
1661    and%?s\\t%0, %1, %2
1662    bic%?s\\t%0, %1, #%B2"
1663   [(set_attr "conds" "set")]
1664 )
1665
1666 (define_insn "*andsi3_compare0_scratch"
1667   [(set (reg:CC_NOOV CC_REGNUM)
1668         (compare:CC_NOOV
1669          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1670                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1671          (const_int 0)))
1672    (clobber (match_scratch:SI 2 "=X,r"))]
1673   "TARGET_ARM"
1674   "@
1675    tst%?\\t%0, %1
1676    bic%?s\\t%2, %0, #%B1"
1677   [(set_attr "conds" "set")]
1678 )
1679
1680 (define_insn "*zeroextractsi_compare0_scratch"
1681   [(set (reg:CC_NOOV CC_REGNUM)
1682         (compare:CC_NOOV (zero_extract:SI
1683                           (match_operand:SI 0 "s_register_operand" "r")
1684                           (match_operand 1 "const_int_operand" "n")
1685                           (match_operand 2 "const_int_operand" "n"))
1686                          (const_int 0)))]
1687   "TARGET_ARM
1688   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1689       && INTVAL (operands[1]) > 0 
1690       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1691       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1692   "*
1693   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1694                          << INTVAL (operands[2]));
1695   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1696   return \"\";
1697   "
1698   [(set_attr "conds" "set")]
1699 )
1700
1701 (define_insn "*ne_zeroextractsi"
1702   [(set (match_operand:SI 0 "s_register_operand" "=r")
1703         (ne:SI (zero_extract:SI
1704                 (match_operand:SI 1 "s_register_operand" "r")
1705                 (match_operand:SI 2 "const_int_operand" "n")
1706                 (match_operand:SI 3 "const_int_operand" "n"))
1707                (const_int 0)))
1708    (clobber (reg:CC CC_REGNUM))]
1709   "TARGET_ARM
1710    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1711        && INTVAL (operands[2]) > 0 
1712        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1713        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1714   "*
1715   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1716                          << INTVAL (operands[3]));
1717   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1718   return \"movne\\t%0, #1\";
1719   "
1720   [(set_attr "conds" "clob")
1721    (set_attr "length" "8")]
1722 )
1723
1724 (define_split
1725   [(set (match_operand:SI 0 "s_register_operand" "")
1726         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1727                          (match_operand:SI 2 "const_int_operand" "")
1728                          (match_operand:SI 3 "const_int_operand" "")))
1729    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1730   "TARGET_THUMB"
1731   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1732    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1733   "{
1734      HOST_WIDE_INT temp = INTVAL (operands[2]);
1735
1736      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1737      operands[3] = GEN_INT (32 - temp);
1738    }"
1739 )
1740
1741 (define_split
1742   [(set (match_operand:SI 0 "s_register_operand" "")
1743         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1744                          (match_operand:SI 2 "const_int_operand" "")
1745                          (match_operand:SI 3 "const_int_operand" "")))]
1746   "TARGET_THUMB"
1747   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1748    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1749   "{
1750      HOST_WIDE_INT temp = INTVAL (operands[2]);
1751
1752      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1753      operands[3] = GEN_INT (32 - temp);
1754    }"
1755 )
1756
1757 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1758 ;;; represented by the bitfield, then this will produce incorrect results.
1759 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1760 ;;; which have a real bit-field insert instruction, the truncation happens
1761 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1762 ;;; bit-field insert instruction, we would have to emit code here to truncate
1763 ;;; the value before we insert.  This loses some of the advantage of having
1764 ;;; this insv pattern, so this pattern needs to be reevalutated.
1765
1766 (define_expand "insv"
1767   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1768                          (match_operand:SI 1 "general_operand" "")
1769                          (match_operand:SI 2 "general_operand" ""))
1770         (match_operand:SI 3 "reg_or_int_operand" ""))]
1771   "TARGET_ARM"
1772   "
1773   {
1774     int start_bit = INTVAL (operands[2]);
1775     int width = INTVAL (operands[1]);
1776     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1777     rtx target, subtarget;
1778
1779     target = operands[0];
1780     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1781        subreg as the final target.  */
1782     if (GET_CODE (target) == SUBREG)
1783       {
1784         subtarget = gen_reg_rtx (SImode);
1785         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1786             < GET_MODE_SIZE (SImode))
1787           target = SUBREG_REG (target);
1788       }
1789     else
1790       subtarget = target;    
1791
1792     if (GET_CODE (operands[3]) == CONST_INT)
1793       {
1794         /* Since we are inserting a known constant, we may be able to
1795            reduce the number of bits that we have to clear so that
1796            the mask becomes simple.  */
1797         /* ??? This code does not check to see if the new mask is actually
1798            simpler.  It may not be.  */
1799         rtx op1 = gen_reg_rtx (SImode);
1800         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1801            start of this pattern.  */
1802         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1803         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1804
1805         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1806         emit_insn (gen_iorsi3 (subtarget, op1,
1807                                GEN_INT (op3_value << start_bit)));
1808       }
1809     else if (start_bit == 0
1810              && !(const_ok_for_arm (mask)
1811                   || const_ok_for_arm (~mask)))
1812       {
1813         /* A Trick, since we are setting the bottom bits in the word,
1814            we can shift operand[3] up, operand[0] down, OR them together
1815            and rotate the result back again.  This takes 3 insns, and
1816            the third might be mergeable into another op.  */
1817         /* The shift up copes with the possibility that operand[3] is
1818            wider than the bitfield.  */
1819         rtx op0 = gen_reg_rtx (SImode);
1820         rtx op1 = gen_reg_rtx (SImode);
1821
1822         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1823         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1824         emit_insn (gen_iorsi3  (op1, op1, op0));
1825         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1826       }
1827     else if ((width + start_bit == 32)
1828              && !(const_ok_for_arm (mask)
1829                   || const_ok_for_arm (~mask)))
1830       {
1831         /* Similar trick, but slightly less efficient.  */
1832
1833         rtx op0 = gen_reg_rtx (SImode);
1834         rtx op1 = gen_reg_rtx (SImode);
1835
1836         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1837         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1838         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1839         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1840       }
1841     else
1842       {
1843         rtx op0 = GEN_INT (mask);
1844         rtx op1 = gen_reg_rtx (SImode);
1845         rtx op2 = gen_reg_rtx (SImode);
1846
1847         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1848           {
1849             rtx tmp = gen_reg_rtx (SImode);
1850
1851             emit_insn (gen_movsi (tmp, op0));
1852             op0 = tmp;
1853           }
1854
1855         /* Mask out any bits in operand[3] that are not needed.  */
1856            emit_insn (gen_andsi3 (op1, operands[3], op0));
1857
1858         if (GET_CODE (op0) == CONST_INT
1859             && (const_ok_for_arm (mask << start_bit)
1860                 || const_ok_for_arm (~(mask << start_bit))))
1861           {
1862             op0 = GEN_INT (~(mask << start_bit));
1863             emit_insn (gen_andsi3 (op2, operands[0], op0));
1864           }
1865         else
1866           {
1867             if (GET_CODE (op0) == CONST_INT)
1868               {
1869                 rtx tmp = gen_reg_rtx (SImode);
1870
1871                 emit_insn (gen_movsi (tmp, op0));
1872                 op0 = tmp;
1873               }
1874
1875             if (start_bit != 0)
1876               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1877             
1878             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1879           }
1880
1881         if (start_bit != 0)
1882           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1883
1884         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1885       }
1886
1887     if (subtarget != target)
1888       {
1889         /* If TARGET is still a SUBREG, then it must be wider than a word,
1890            so we must be careful only to set the subword we were asked to.  */
1891         if (GET_CODE (target) == SUBREG)
1892           emit_move_insn (target, subtarget);
1893         else
1894           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1895       }
1896
1897     DONE;
1898   }"
1899 )
1900
1901 ; constants for op 2 will never be given to these patterns.
1902 (define_insn_and_split "*anddi_notdi_di"
1903   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1904         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1905                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1906   "TARGET_ARM"
1907   "#"
1908   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1909   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1910    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1911   "
1912   {
1913     operands[3] = gen_highpart (SImode, operands[0]);
1914     operands[0] = gen_lowpart (SImode, operands[0]);
1915     operands[4] = gen_highpart (SImode, operands[1]);
1916     operands[1] = gen_lowpart (SImode, operands[1]);
1917     operands[5] = gen_highpart (SImode, operands[2]);
1918     operands[2] = gen_lowpart (SImode, operands[2]);
1919   }"
1920   [(set_attr "length" "8")
1921    (set_attr "predicable" "yes")]
1922 )
1923   
1924 (define_insn_and_split "*anddi_notzesidi_di"
1925   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1926         (and:DI (not:DI (zero_extend:DI
1927                          (match_operand:SI 2 "s_register_operand" "r,r")))
1928                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1929   "TARGET_ARM"
1930   "@
1931    bic%?\\t%Q0, %Q1, %2
1932    #"
1933   ; (not (zero_extend ...)) allows us to just copy the high word from
1934   ; operand1 to operand0.
1935   "TARGET_ARM
1936    && reload_completed
1937    && operands[0] != operands[1]"
1938   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1939    (set (match_dup 3) (match_dup 4))]
1940   "
1941   {
1942     operands[3] = gen_highpart (SImode, operands[0]);
1943     operands[0] = gen_lowpart (SImode, operands[0]);
1944     operands[4] = gen_highpart (SImode, operands[1]);
1945     operands[1] = gen_lowpart (SImode, operands[1]);
1946   }"
1947   [(set_attr "length" "4,8")
1948    (set_attr "predicable" "yes")]
1949 )
1950   
1951 (define_insn_and_split "*anddi_notsesidi_di"
1952   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1953         (and:DI (not:DI (sign_extend:DI
1954                          (match_operand:SI 2 "s_register_operand" "r,r")))
1955                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1956   "TARGET_ARM"
1957   "#"
1958   "TARGET_ARM && reload_completed"
1959   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1960    (set (match_dup 3) (and:SI (not:SI
1961                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
1962                                (match_dup 4)))]
1963   "
1964   {
1965     operands[3] = gen_highpart (SImode, operands[0]);
1966     operands[0] = gen_lowpart (SImode, operands[0]);
1967     operands[4] = gen_highpart (SImode, operands[1]);
1968     operands[1] = gen_lowpart (SImode, operands[1]);
1969   }"
1970   [(set_attr "length" "8")
1971    (set_attr "predicable" "yes")]
1972 )
1973   
1974 (define_insn "andsi_notsi_si"
1975   [(set (match_operand:SI 0 "s_register_operand" "=r")
1976         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1977                 (match_operand:SI 1 "s_register_operand" "r")))]
1978   "TARGET_ARM"
1979   "bic%?\\t%0, %1, %2"
1980   [(set_attr "predicable" "yes")]
1981 )
1982
1983 (define_insn "bicsi3"
1984   [(set (match_operand:SI                 0 "register_operand" "=l")
1985         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1986                 (match_operand:SI         2 "register_operand" "0")))]
1987   "TARGET_THUMB"
1988   "bic\\t%0, %0, %1"
1989   [(set_attr "length" "2")]
1990 )
1991
1992 (define_insn "andsi_not_shiftsi_si"
1993   [(set (match_operand:SI                   0 "s_register_operand" "=r")
1994         (and:SI (not:SI (match_operator:SI  4 "shift_operator"
1995                          [(match_operand:SI 2 "s_register_operand"  "r")
1996                           (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
1997                 (match_operand:SI           1 "s_register_operand"  "r")))]
1998   "TARGET_ARM"
1999   "bic%?\\t%0, %1, %2%S4"
2000   [(set_attr "predicable" "yes")
2001    (set_attr "shift" "2")
2002    ]
2003 )
2004
2005 (define_insn "*andsi_notsi_si_compare0"
2006   [(set (reg:CC_NOOV CC_REGNUM)
2007         (compare:CC_NOOV
2008          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2009                  (match_operand:SI 1 "s_register_operand" "r"))
2010          (const_int 0)))
2011    (set (match_operand:SI 0 "s_register_operand" "=r")
2012         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2013   "TARGET_ARM"
2014   "bic%?s\\t%0, %1, %2"
2015   [(set_attr "conds" "set")]
2016 )
2017
2018 (define_insn "*andsi_notsi_si_compare0_scratch"
2019   [(set (reg:CC_NOOV CC_REGNUM)
2020         (compare:CC_NOOV
2021          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2022                  (match_operand:SI 1 "s_register_operand" "r"))
2023          (const_int 0)))
2024    (clobber (match_scratch:SI 0 "=r"))]
2025   "TARGET_ARM"
2026   "bic%?s\\t%0, %1, %2"
2027   [(set_attr "conds" "set")]
2028 )
2029
2030 (define_insn "iordi3"
2031   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2032         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2033                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2034   "TARGET_ARM && ! TARGET_IWMMXT"
2035   "#"
2036   [(set_attr "length" "8")
2037    (set_attr "predicable" "yes")]
2038 )
2039
2040 (define_insn "*iordi_zesidi_di"
2041   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2042         (ior:DI (zero_extend:DI
2043                  (match_operand:SI 2 "s_register_operand" "r,r"))
2044                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2045   "TARGET_ARM"
2046   "@
2047    orr%?\\t%Q0, %Q1, %2
2048    #"
2049   [(set_attr "length" "4,8")
2050    (set_attr "predicable" "yes")]
2051 )
2052
2053 (define_insn "*iordi_sesidi_di"
2054   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2055         (ior:DI (sign_extend:DI
2056                  (match_operand:SI 2 "s_register_operand" "r,r"))
2057                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2058   "TARGET_ARM"
2059   "#"
2060   [(set_attr "length" "8")
2061    (set_attr "predicable" "yes")]
2062 )
2063
2064 (define_expand "iorsi3"
2065   [(set (match_operand:SI         0 "s_register_operand" "")
2066         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2067                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2068   "TARGET_EITHER"
2069   "
2070   if (GET_CODE (operands[2]) == CONST_INT)
2071     {
2072       if (TARGET_ARM)
2073         {
2074           arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2075                               operands[1],
2076                               (no_new_pseudos
2077                               ? 0 : preserve_subexpressions_p ()));
2078           DONE;
2079         }
2080       else /* TARGET_THUMB */
2081         operands [2] = force_reg (SImode, operands [2]);
2082     }
2083   "
2084 )
2085
2086 (define_insn_and_split "*arm_iorsi3"
2087   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2088         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2089                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2090   "TARGET_ARM"
2091   "@
2092    orr%?\\t%0, %1, %2
2093    #"
2094   "TARGET_ARM
2095    && GET_CODE (operands[2]) == CONST_INT
2096    && !const_ok_for_arm (INTVAL (operands[2]))"
2097   [(clobber (const_int 0))]
2098   "
2099   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2100                       operands[1], 0);
2101   DONE;
2102   "
2103   [(set_attr "length" "4,16")
2104    (set_attr "predicable" "yes")]
2105 )
2106
2107 (define_insn "*thumb_iorsi3"
2108   [(set (match_operand:SI         0 "register_operand" "=l")
2109         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2110                 (match_operand:SI 2 "register_operand" "l")))]
2111   "TARGET_THUMB"
2112   "orr\\t%0, %0, %2"
2113   [(set_attr "length" "2")]
2114 )
2115
2116 (define_peephole2
2117   [(match_scratch:SI 3 "r")
2118    (set (match_operand:SI         0 "s_register_operand" "")
2119         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2120                 (match_operand:SI 2 "const_int_operand" "")))]
2121   "TARGET_ARM
2122    && !const_ok_for_arm (INTVAL (operands[2]))
2123    && const_ok_for_arm (~INTVAL (operands[2]))"
2124   [(set (match_dup 3) (match_dup 2))
2125    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2126   ""
2127 )
2128
2129 (define_insn "*iorsi3_compare0"
2130   [(set (reg:CC_NOOV CC_REGNUM)
2131         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2132                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2133                          (const_int 0)))
2134    (set (match_operand:SI 0 "s_register_operand" "=r")
2135         (ior:SI (match_dup 1) (match_dup 2)))]
2136   "TARGET_ARM"
2137   "orr%?s\\t%0, %1, %2"
2138   [(set_attr "conds" "set")]
2139 )
2140
2141 (define_insn "*iorsi3_compare0_scratch"
2142   [(set (reg:CC_NOOV CC_REGNUM)
2143         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2144                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2145                          (const_int 0)))
2146    (clobber (match_scratch:SI 0 "=r"))]
2147   "TARGET_ARM"
2148   "orr%?s\\t%0, %1, %2"
2149   [(set_attr "conds" "set")]
2150 )
2151
2152 (define_insn "xordi3"
2153   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2154         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2155                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2156   "TARGET_ARM && !TARGET_IWMMXT"
2157   "#"
2158   [(set_attr "length" "8")
2159    (set_attr "predicable" "yes")]
2160 )
2161
2162 (define_insn "*xordi_zesidi_di"
2163   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2164         (xor:DI (zero_extend:DI
2165                  (match_operand:SI 2 "s_register_operand" "r,r"))
2166                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2167   "TARGET_ARM"
2168   "@
2169    eor%?\\t%Q0, %Q1, %2
2170    #"
2171   [(set_attr "length" "4,8")
2172    (set_attr "predicable" "yes")]
2173 )
2174
2175 (define_insn "*xordi_sesidi_di"
2176   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2177         (xor:DI (sign_extend:DI
2178                  (match_operand:SI 2 "s_register_operand" "r,r"))
2179                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2180   "TARGET_ARM"
2181   "#"
2182   [(set_attr "length" "8")
2183    (set_attr "predicable" "yes")]
2184 )
2185
2186 (define_expand "xorsi3"
2187   [(set (match_operand:SI         0 "s_register_operand" "")
2188         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2189                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2190   "TARGET_EITHER"
2191   "if (TARGET_THUMB)
2192      if (GET_CODE (operands[2]) == CONST_INT)
2193        operands[2] = force_reg (SImode, operands[2]);
2194   "
2195 )
2196
2197 (define_insn "*arm_xorsi3"
2198   [(set (match_operand:SI         0 "s_register_operand" "=r")
2199         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2200                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2201   "TARGET_ARM"
2202   "eor%?\\t%0, %1, %2"
2203   [(set_attr "predicable" "yes")]
2204 )
2205
2206 (define_insn "*thumb_xorsi3"
2207   [(set (match_operand:SI         0 "register_operand" "=l")
2208         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2209                 (match_operand:SI 2 "register_operand" "l")))]
2210   "TARGET_THUMB"
2211   "eor\\t%0, %0, %2"
2212   [(set_attr "length" "2")]
2213 )
2214
2215 (define_insn "*xorsi3_compare0"
2216   [(set (reg:CC_NOOV CC_REGNUM)
2217         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2218                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2219                          (const_int 0)))
2220    (set (match_operand:SI 0 "s_register_operand" "=r")
2221         (xor:SI (match_dup 1) (match_dup 2)))]
2222   "TARGET_ARM"
2223   "eor%?s\\t%0, %1, %2"
2224   [(set_attr "conds" "set")]
2225 )
2226
2227 (define_insn "*xorsi3_compare0_scratch"
2228   [(set (reg:CC_NOOV CC_REGNUM)
2229         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2230                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2231                          (const_int 0)))]
2232   "TARGET_ARM"
2233   "teq%?\\t%0, %1"
2234   [(set_attr "conds" "set")]
2235 )
2236
2237 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2238 ; (NOT D) we can sometimes merge the final NOT into one of the following
2239 ; insns.
2240
2241 (define_split
2242   [(set (match_operand:SI 0 "s_register_operand" "")
2243         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2244                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2245                 (match_operand:SI 3 "arm_rhs_operand" "")))
2246    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2247   "TARGET_ARM"
2248   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2249                               (not:SI (match_dup 3))))
2250    (set (match_dup 0) (not:SI (match_dup 4)))]
2251   ""
2252 )
2253
2254 (define_insn "*andsi_iorsi3_notsi"
2255   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2256         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2257                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2258                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2259   "TARGET_ARM"
2260   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2261   [(set_attr "length" "8")
2262    (set_attr "predicable" "yes")]
2263 )
2264
2265 \f
2266
2267 ;; Minimum and maximum insns
2268
2269 (define_insn "smaxsi3"
2270   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2271         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2272                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2273    (clobber (reg:CC CC_REGNUM))]
2274   "TARGET_ARM"
2275   "@
2276    cmp\\t%1, %2\;movlt\\t%0, %2
2277    cmp\\t%1, %2\;movge\\t%0, %1
2278    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2279   [(set_attr "conds" "clob")
2280    (set_attr "length" "8,8,12")]
2281 )
2282
2283 (define_insn "sminsi3"
2284   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2285         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2286                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2287    (clobber (reg:CC CC_REGNUM))]
2288   "TARGET_ARM"
2289   "@
2290    cmp\\t%1, %2\;movge\\t%0, %2
2291    cmp\\t%1, %2\;movlt\\t%0, %1
2292    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2293   [(set_attr "conds" "clob")
2294    (set_attr "length" "8,8,12")]
2295 )
2296
2297 (define_insn "umaxsi3"
2298   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2299         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2300                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2301    (clobber (reg:CC CC_REGNUM))]
2302   "TARGET_ARM"
2303   "@
2304    cmp\\t%1, %2\;movcc\\t%0, %2
2305    cmp\\t%1, %2\;movcs\\t%0, %1
2306    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2307   [(set_attr "conds" "clob")
2308    (set_attr "length" "8,8,12")]
2309 )
2310
2311 (define_insn "uminsi3"
2312   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2313         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2314                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2315    (clobber (reg:CC CC_REGNUM))]
2316   "TARGET_ARM"
2317   "@
2318    cmp\\t%1, %2\;movcs\\t%0, %2
2319    cmp\\t%1, %2\;movcc\\t%0, %1
2320    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2321   [(set_attr "conds" "clob")
2322    (set_attr "length" "8,8,12")]
2323 )
2324
2325 (define_insn "*store_minmaxsi"
2326   [(set (match_operand:SI 0 "memory_operand" "=m")
2327         (match_operator:SI 3 "minmax_operator"
2328          [(match_operand:SI 1 "s_register_operand" "r")
2329           (match_operand:SI 2 "s_register_operand" "r")]))
2330    (clobber (reg:CC CC_REGNUM))]
2331   "TARGET_ARM"
2332   "*
2333   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2334                          operands[2]);
2335   output_asm_insn (\"cmp\\t%1, %2\", operands);
2336   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2337   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2338   return \"\";
2339   "
2340   [(set_attr "conds" "clob")
2341    (set_attr "length" "12")
2342    (set_attr "type" "store1")]
2343 )
2344
2345 ; Reject the frame pointer in operand[1], since reloading this after
2346 ; it has been eliminated can cause carnage.
2347 (define_insn "*minmax_arithsi"
2348   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2349         (match_operator:SI 4 "shiftable_operator"
2350          [(match_operator:SI 5 "minmax_operator"
2351            [(match_operand:SI 2 "s_register_operand" "r,r")
2352             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2353           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2354    (clobber (reg:CC CC_REGNUM))]
2355   "TARGET_ARM
2356    && (GET_CODE (operands[1]) != REG
2357        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2358            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2359   "*
2360   {
2361     enum rtx_code code = GET_CODE (operands[4]);
2362
2363     operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2364                            operands[3]);
2365     output_asm_insn (\"cmp\\t%2, %3\", operands);
2366     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2367     if (which_alternative != 0 || operands[3] != const0_rtx
2368         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2369       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2370     return \"\";
2371   }"
2372   [(set_attr "conds" "clob")
2373    (set_attr "length" "12")]
2374 )
2375
2376 \f
2377 ;; Shift and rotation insns
2378
2379 (define_expand "ashlsi3"
2380   [(set (match_operand:SI            0 "s_register_operand" "")
2381         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2382                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2383   "TARGET_EITHER"
2384   "
2385   if (GET_CODE (operands[2]) == CONST_INT
2386       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2387     {
2388       emit_insn (gen_movsi (operands[0], const0_rtx));
2389       DONE;
2390     }
2391   "
2392 )
2393
2394 (define_insn "*thumb_ashlsi3"
2395   [(set (match_operand:SI            0 "register_operand" "=l,l")
2396         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2397                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2398   "TARGET_THUMB"
2399   "lsl\\t%0, %1, %2"
2400   [(set_attr "length" "2")]
2401 )
2402
2403 (define_expand "ashrsi3"
2404   [(set (match_operand:SI              0 "s_register_operand" "")
2405         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2406                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2407   "TARGET_EITHER"
2408   "
2409   if (GET_CODE (operands[2]) == CONST_INT
2410       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2411     operands[2] = GEN_INT (31);
2412   "
2413 )
2414
2415 (define_insn "*thumb_ashrsi3"
2416   [(set (match_operand:SI              0 "register_operand" "=l,l")
2417         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2418                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2419   "TARGET_THUMB"
2420   "asr\\t%0, %1, %2"
2421   [(set_attr "length" "2")]
2422 )
2423
2424 (define_expand "lshrsi3"
2425   [(set (match_operand:SI              0 "s_register_operand" "")
2426         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2427                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2428   "TARGET_EITHER"
2429   "
2430   if (GET_CODE (operands[2]) == CONST_INT
2431       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2432     {
2433       emit_insn (gen_movsi (operands[0], const0_rtx));
2434       DONE;
2435     }
2436   "
2437 )
2438
2439 (define_insn "*thumb_lshrsi3"
2440   [(set (match_operand:SI              0 "register_operand" "=l,l")
2441         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2442                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2443   "TARGET_THUMB"
2444   "lsr\\t%0, %1, %2"
2445   [(set_attr "length" "2")]
2446 )
2447
2448 (define_expand "rotlsi3"
2449   [(set (match_operand:SI              0 "s_register_operand" "")
2450         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2451                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2452   "TARGET_ARM"
2453   "
2454   if (GET_CODE (operands[2]) == CONST_INT)
2455     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2456   else
2457     {
2458       rtx reg = gen_reg_rtx (SImode);
2459       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2460       operands[2] = reg;
2461     }
2462   "
2463 )
2464
2465 (define_expand "rotrsi3"
2466   [(set (match_operand:SI              0 "s_register_operand" "")
2467         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2468                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2469   "TARGET_EITHER"
2470   "
2471   if (TARGET_ARM)
2472     {
2473       if (GET_CODE (operands[2]) == CONST_INT
2474           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2475         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2476     }
2477   else /* TARGET_THUMB */
2478     {
2479       if (GET_CODE (operands [2]) == CONST_INT)
2480         operands [2] = force_reg (SImode, operands[2]);
2481     }
2482   "
2483 )
2484
2485 (define_insn "*thumb_rotrsi3"
2486   [(set (match_operand:SI              0 "register_operand" "=l")
2487         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2488                      (match_operand:SI 2 "register_operand" "l")))]
2489   "TARGET_THUMB"
2490   "ror\\t%0, %0, %2"
2491   [(set_attr "length" "2")]
2492 )
2493
2494 (define_expand "ashldi3"
2495   [(set (match_operand:DI            0 "s_register_operand" "")
2496         (ashift:DI (match_operand:DI 1 "general_operand"    "")
2497                    (match_operand:SI 2 "general_operand"    "")))]
2498   "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)"
2499   "
2500   if (! s_register_operand (operands[1], DImode))
2501     operands[1] = copy_to_mode_reg (DImode, operands[1]);
2502   if (! s_register_operand (operands[2], SImode))
2503     operands[2] = copy_to_mode_reg (SImode, operands[2]);
2504   "
2505 )
2506
2507 (define_insn "*arm_shiftsi3"
2508   [(set (match_operand:SI   0 "s_register_operand" "=r")
2509         (match_operator:SI  3 "shift_operator"
2510          [(match_operand:SI 1 "s_register_operand"  "r")
2511           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2512   "TARGET_ARM"
2513   "mov%?\\t%0, %1%S3"
2514   [(set_attr "predicable" "yes")
2515    (set_attr "shift" "1")
2516    ]
2517 )
2518
2519 (define_insn "*shiftsi3_compare0"
2520   [(set (reg:CC_NOOV CC_REGNUM)
2521         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2522                           [(match_operand:SI 1 "s_register_operand" "r")
2523                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2524                          (const_int 0)))
2525    (set (match_operand:SI 0 "s_register_operand" "=r")
2526         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2527   "TARGET_ARM"
2528   "mov%?s\\t%0, %1%S3"
2529   [(set_attr "conds" "set")
2530    (set_attr "shift" "1")
2531    ]
2532 )
2533
2534 (define_insn "*shiftsi3_compare0_scratch"
2535   [(set (reg:CC_NOOV CC_REGNUM)
2536         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2537                           [(match_operand:SI 1 "s_register_operand" "r")
2538                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2539                          (const_int 0)))
2540    (clobber (match_scratch:SI 0 "=r"))]
2541   "TARGET_ARM"
2542   "mov%?s\\t%0, %1%S3"
2543   [(set_attr "conds" "set")
2544    (set_attr "shift" "1")
2545    ]
2546 )
2547
2548 (define_insn "*notsi_shiftsi"
2549   [(set (match_operand:SI 0 "s_register_operand" "=r")
2550         (not:SI (match_operator:SI 3 "shift_operator"
2551                  [(match_operand:SI 1 "s_register_operand" "r")
2552                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2553   "TARGET_ARM"
2554   "mvn%?\\t%0, %1%S3"
2555   [(set_attr "predicable" "yes")
2556    (set_attr "shift" "1")
2557    ]
2558 )
2559
2560 (define_insn "*notsi_shiftsi_compare0"
2561   [(set (reg:CC_NOOV CC_REGNUM)
2562         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2563                           [(match_operand:SI 1 "s_register_operand" "r")
2564                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2565                          (const_int 0)))
2566    (set (match_operand:SI 0 "s_register_operand" "=r")
2567         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2568   "TARGET_ARM"
2569   "mvn%?s\\t%0, %1%S3"
2570   [(set_attr "conds" "set")
2571    (set_attr "shift" "1")
2572    ]
2573 )
2574
2575 (define_insn "*not_shiftsi_compare0_scratch"
2576   [(set (reg:CC_NOOV CC_REGNUM)
2577         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2578                           [(match_operand:SI 1 "s_register_operand" "r")
2579                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2580                          (const_int 0)))
2581    (clobber (match_scratch:SI 0 "=r"))]
2582   "TARGET_ARM"
2583   "mvn%?s\\t%0, %1%S3"
2584   [(set_attr "conds" "set")
2585    (set_attr "shift" "1")
2586   ]
2587 )
2588
2589 ;; We don't really have extzv, but defining this using shifts helps
2590 ;; to reduce register pressure later on.
2591
2592 (define_expand "extzv"
2593   [(set (match_dup 4)
2594         (ashift:SI (match_operand:SI   1 "register_operand" "")
2595                    (match_operand:SI   2 "const_int_operand" "")))
2596    (set (match_operand:SI              0 "register_operand" "")
2597         (lshiftrt:SI (match_dup 4)
2598                      (match_operand:SI 3 "const_int_operand" "")))]
2599   "TARGET_THUMB"
2600   "
2601   {
2602     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2603     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2604     
2605     operands[3] = GEN_INT (rshift);
2606     
2607     if (lshift == 0)
2608       {
2609         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2610         DONE;
2611       }
2612       
2613     operands[2] = GEN_INT (lshift);
2614     operands[4] = gen_reg_rtx (SImode);
2615   }"
2616 )
2617
2618 \f
2619 ;; Unary arithmetic insns
2620
2621 (define_expand "negdi2"
2622  [(parallel
2623    [(set (match_operand:DI          0 "s_register_operand" "")
2624           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2625     (clobber (reg:CC CC_REGNUM))])]
2626   "TARGET_EITHER"
2627   "
2628   if (TARGET_THUMB)
2629     {
2630       if (GET_CODE (operands[1]) != REG)
2631         operands[1] = force_reg (SImode, operands[1]);
2632      }
2633   "
2634 )
2635
2636 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2637 ;; The second alternative is to allow the common case of a *full* overlap.
2638 (define_insn "*arm_negdi2"
2639   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2640         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2641    (clobber (reg:CC CC_REGNUM))]
2642   "TARGET_ARM"
2643   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2644   [(set_attr "conds" "clob")
2645    (set_attr "length" "8")]
2646 )
2647
2648 (define_insn "*thumb_negdi2"
2649   [(set (match_operand:DI         0 "register_operand" "=&l")
2650         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2651    (clobber (reg:CC CC_REGNUM))]
2652   "TARGET_THUMB"
2653   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2654   [(set_attr "length" "6")]
2655 )
2656
2657 (define_expand "negsi2"
2658   [(set (match_operand:SI         0 "s_register_operand" "")
2659         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2660   "TARGET_EITHER"
2661   ""
2662 )
2663
2664 (define_insn "*arm_negsi2"
2665   [(set (match_operand:SI         0 "s_register_operand" "=r")
2666         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2667   "TARGET_ARM"
2668   "rsb%?\\t%0, %1, #0"
2669   [(set_attr "predicable" "yes")]
2670 )
2671
2672 (define_insn "*thumb_negsi2"
2673   [(set (match_operand:SI         0 "register_operand" "=l")
2674         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2675   "TARGET_THUMB"
2676   "neg\\t%0, %1"
2677   [(set_attr "length" "2")]
2678 )
2679
2680 (define_expand "negsf2"
2681   [(set (match_operand:SF         0 "s_register_operand" "")
2682         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2683   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2684   ""
2685 )
2686
2687 (define_expand "negdf2"
2688   [(set (match_operand:DF         0 "s_register_operand" "")
2689         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2690   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2691   "")
2692
2693 ;; abssi2 doesn't really clobber the condition codes if a different register
2694 ;; is being set.  To keep things simple, assume during rtl manipulations that
2695 ;; it does, but tell the final scan operator the truth.  Similarly for
2696 ;; (neg (abs...))
2697
2698 (define_expand "abssi2"
2699   [(parallel
2700     [(set (match_operand:SI         0 "s_register_operand" "")
2701           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2702      (clobber (reg:CC CC_REGNUM))])]
2703   "TARGET_ARM"
2704   "")
2705
2706 (define_insn "*arm_abssi2"
2707   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2708         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2709    (clobber (reg:CC CC_REGNUM))]
2710   "TARGET_ARM"
2711   "@
2712    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2713    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2714   [(set_attr "conds" "clob,*")
2715    (set_attr "shift" "1")
2716    ;; predicable can't be set based on the variant, so left as no
2717    (set_attr "length" "8")]
2718 )
2719
2720 (define_insn "*neg_abssi2"
2721   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2722         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2723    (clobber (reg:CC CC_REGNUM))]
2724   "TARGET_ARM"
2725   "@
2726    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2727    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2728   [(set_attr "conds" "clob,*")
2729    (set_attr "shift" "1")
2730    ;; predicable can't be set based on the variant, so left as no
2731    (set_attr "length" "8")]
2732 )
2733
2734 (define_expand "abssf2"
2735   [(set (match_operand:SF         0 "s_register_operand" "")
2736         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2737   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2738   "")
2739
2740 (define_expand "absdf2"
2741   [(set (match_operand:DF         0 "s_register_operand" "")
2742         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2743   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2744   "")
2745
2746 (define_expand "sqrtsf2"
2747   [(set (match_operand:SF 0 "s_register_operand" "")
2748         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2749   "TARGET_ARM && TARGET_HARD_FLOAT"
2750   "")
2751
2752 (define_expand "sqrtdf2"
2753   [(set (match_operand:DF 0 "s_register_operand" "")
2754         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2755   "TARGET_ARM && TARGET_HARD_FLOAT"
2756   "")
2757
2758 (define_insn_and_split "one_cmpldi2"
2759   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2760         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2761   "TARGET_ARM"
2762   "#"
2763   "TARGET_ARM && reload_completed"
2764   [(set (match_dup 0) (not:SI (match_dup 1)))
2765    (set (match_dup 2) (not:SI (match_dup 3)))]
2766   "
2767   {
2768     operands[2] = gen_highpart (SImode, operands[0]);
2769     operands[0] = gen_lowpart (SImode, operands[0]);
2770     operands[3] = gen_highpart (SImode, operands[1]);
2771     operands[1] = gen_lowpart (SImode, operands[1]);
2772   }"
2773   [(set_attr "length" "8")
2774    (set_attr "predicable" "yes")]
2775 )
2776
2777 (define_expand "one_cmplsi2"
2778   [(set (match_operand:SI         0 "s_register_operand" "")
2779         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2780   "TARGET_EITHER"
2781   ""
2782 )
2783
2784 (define_insn "*arm_one_cmplsi2"
2785   [(set (match_operand:SI         0 "s_register_operand" "=r")
2786         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2787   "TARGET_ARM"
2788   "mvn%?\\t%0, %1"
2789   [(set_attr "predicable" "yes")]
2790 )
2791
2792 (define_insn "*thumb_one_cmplsi2"
2793   [(set (match_operand:SI         0 "register_operand" "=l")
2794         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
2795   "TARGET_THUMB"
2796   "mvn\\t%0, %1"
2797   [(set_attr "length" "2")]
2798 )
2799
2800 (define_insn "*notsi_compare0"
2801   [(set (reg:CC_NOOV CC_REGNUM)
2802         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2803                          (const_int 0)))
2804    (set (match_operand:SI 0 "s_register_operand" "=r")
2805         (not:SI (match_dup 1)))]
2806   "TARGET_ARM"
2807   "mvn%?s\\t%0, %1"
2808   [(set_attr "conds" "set")]
2809 )
2810
2811 (define_insn "*notsi_compare0_scratch"
2812   [(set (reg:CC_NOOV CC_REGNUM)
2813         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2814                          (const_int 0)))
2815    (clobber (match_scratch:SI 0 "=r"))]
2816   "TARGET_ARM"
2817   "mvn%?s\\t%0, %1"
2818   [(set_attr "conds" "set")]
2819 )
2820 \f
2821 ;; Fixed <--> Floating conversion insns
2822
2823 (define_expand "floatsisf2"
2824   [(set (match_operand:SF           0 "s_register_operand" "")
2825         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2826   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2827   "
2828   if (TARGET_CIRRUS)
2829     {
2830       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2831       DONE;
2832     }
2833 ")
2834
2835 (define_expand "floatsidf2"
2836   [(set (match_operand:DF           0 "s_register_operand" "")
2837         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2838   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2839   "
2840   if (TARGET_CIRRUS)
2841     {
2842       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
2843       DONE;
2844     }
2845 ")
2846
2847 (define_expand "fix_truncsfsi2"
2848   [(set (match_operand:SI         0 "s_register_operand" "")
2849         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
2850   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2851   "
2852   if (TARGET_CIRRUS)
2853     {
2854       if (!cirrus_fp_register (operands[0], SImode))
2855         operands[0] = force_reg (SImode, operands[0]);
2856       if (!cirrus_fp_register (operands[1], SFmode))
2857         operands[1] = force_reg (SFmode, operands[0]);
2858       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
2859       DONE;
2860     }
2861 ")
2862
2863 (define_expand "fix_truncdfsi2"
2864   [(set (match_operand:SI         0 "s_register_operand" "")
2865         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
2866   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2867   "
2868   if (TARGET_CIRRUS)
2869     {
2870       if (!cirrus_fp_register (operands[1], DFmode))
2871         operands[1] = force_reg (DFmode, operands[0]);
2872       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
2873       DONE;
2874     }
2875 ")
2876
2877 ;; Truncation insns
2878
2879 (define_expand "truncdfsf2"
2880   [(set (match_operand:SF  0 "s_register_operand" "")
2881         (float_truncate:SF
2882          (match_operand:DF 1 "s_register_operand" "")))]
2883   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2884   ""
2885 )
2886 \f
2887 ;; Zero and sign extension instructions.
2888
2889 (define_insn "zero_extendsidi2"
2890   [(set (match_operand:DI 0 "s_register_operand" "=r")
2891         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2892   "TARGET_ARM"
2893   "*
2894     if (REGNO (operands[1])
2895         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2896       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2897     return \"mov%?\\t%R0, #0\";
2898   "
2899   [(set_attr "length" "8")
2900    (set_attr "predicable" "yes")]
2901 )
2902
2903 (define_insn "zero_extendqidi2"
2904   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
2905         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2906   "TARGET_ARM"
2907   "@
2908    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2909    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2910   [(set_attr "length" "8")
2911    (set_attr "predicable" "yes")
2912    (set_attr "type" "*,load")
2913    (set_attr "pool_range" "*,4092")
2914    (set_attr "neg_pool_range" "*,4084")]
2915 )
2916
2917 (define_insn "extendsidi2"
2918   [(set (match_operand:DI 0 "s_register_operand" "=r")
2919         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2920   "TARGET_ARM"
2921   "*
2922     if (REGNO (operands[1])
2923         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2924       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2925     return \"mov%?\\t%R0, %Q0, asr #31\";
2926   "
2927   [(set_attr "length" "8")
2928    (set_attr "shift" "1")
2929    (set_attr "predicable" "yes")]
2930 )
2931
2932 (define_expand "zero_extendhisi2"
2933   [(set (match_dup 2)
2934         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2935                    (const_int 16)))
2936    (set (match_operand:SI 0 "s_register_operand" "")
2937         (lshiftrt:SI (match_dup 2) (const_int 16)))]
2938   "TARGET_EITHER"
2939   "
2940   {
2941     if (TARGET_ARM)
2942       {
2943         if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2944           {
2945            /* Note: We do not have to worry about TARGET_MMU_TRAPS
2946               here because the insn below will generate an LDRH instruction
2947               rather than an LDR instruction, so we cannot get an unaligned
2948               word access.  */
2949             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2950                                     gen_rtx_ZERO_EXTEND (SImode,
2951                                                          operands[1])));
2952             DONE;
2953           }
2954         if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2955           {
2956             emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2957             DONE;
2958           }
2959         if (!s_register_operand (operands[1], HImode))
2960           operands[1] = copy_to_mode_reg (HImode, operands[1]);
2961         operands[1] = gen_lowpart (SImode, operands[1]);
2962         operands[2] = gen_reg_rtx (SImode);
2963       }
2964     else /* TARGET_THUMB */
2965       {
2966         if (GET_CODE (operands[1]) == MEM)
2967           {
2968             rtx tmp;
2969
2970             tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
2971             tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
2972             emit_insn (tmp);
2973           }
2974         else
2975           {
2976             rtx ops[3];
2977             
2978             if (!s_register_operand (operands[1], HImode))
2979               operands[1] = copy_to_mode_reg (HImode, operands[1]);
2980             operands[1] = gen_lowpart (SImode, operands[1]);
2981             operands[2] = gen_reg_rtx (SImode);
2982             
2983             ops[0] = operands[2];
2984             ops[1] = operands[1];
2985             ops[2] = GEN_INT (16);
2986             
2987             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2988                                     gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
2989
2990             ops[0] = operands[0];
2991             ops[1] = operands[2];
2992             ops[2] = GEN_INT (16);
2993
2994             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2995                                     gen_rtx_LSHIFTRT (SImode, ops[1],
2996                                                       ops[2])));
2997           }
2998         DONE; 
2999       }
3000   }"
3001 )
3002
3003 (define_insn "*thumb_zero_extendhisi2"
3004   [(set (match_operand:SI                 0 "register_operand" "=l")
3005         (zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3006   "TARGET_THUMB"
3007   "*
3008   rtx mem = XEXP (operands[1], 0);
3009
3010   if (GET_CODE (mem) == CONST)
3011     mem = XEXP (mem, 0);
3012     
3013   if (GET_CODE (mem) == LABEL_REF)
3014     return \"ldr\\t%0, %1\";
3015     
3016   if (GET_CODE (mem) == PLUS)
3017     {
3018       rtx a = XEXP (mem, 0);
3019       rtx b = XEXP (mem, 1);
3020
3021       /* This can happen due to bugs in reload.  */
3022       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3023         {
3024           rtx ops[2];
3025           ops[0] = operands[0];
3026           ops[1] = a;
3027       
3028           output_asm_insn (\"mov        %0, %1\", ops);
3029
3030           XEXP (mem, 0) = operands[0];
3031        }
3032
3033       else if (   GET_CODE (a) == LABEL_REF
3034                && GET_CODE (b) == CONST_INT)
3035         return \"ldr\\t%0, %1\";
3036     }
3037     
3038   return \"ldrh\\t%0, %1\";
3039   "
3040   [(set_attr "length" "4")
3041    (set_attr "type" "load")
3042    (set_attr "pool_range" "60")]
3043 )
3044
3045 (define_insn "*arm_zero_extendhisi2"
3046   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3047         (zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3048   "TARGET_ARM && arm_arch4"
3049   "ldr%?h\\t%0, %1"
3050   [(set_attr "type" "load")
3051    (set_attr "predicable" "yes")
3052    (set_attr "pool_range" "256")
3053    (set_attr "neg_pool_range" "244")]
3054 )
3055
3056 (define_split
3057   [(set (match_operand:SI 0 "s_register_operand" "")
3058         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3059    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3060   "TARGET_ARM && (!arm_arch4)"
3061   [(set (match_dup 2) (match_dup 1))
3062    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3063   "
3064   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3065     FAIL;
3066   "
3067 )
3068
3069 (define_split
3070   [(set (match_operand:SI 0 "s_register_operand" "")
3071         (match_operator:SI 3 "shiftable_operator"
3072          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3073           (match_operand:SI 4 "s_register_operand" "")]))
3074    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3075   "TARGET_ARM && (!arm_arch4)"
3076   [(set (match_dup 2) (match_dup 1))
3077    (set (match_dup 0)
3078         (match_op_dup 3
3079          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3080   "
3081   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3082     FAIL;
3083   "
3084 )
3085
3086 (define_expand "zero_extendqisi2"
3087   [(set (match_operand:SI 0 "s_register_operand" "")
3088         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3089   "TARGET_EITHER"
3090   "
3091   if (GET_CODE (operands[1]) != MEM)
3092     {
3093       if (TARGET_ARM)
3094         {
3095           emit_insn (gen_andsi3 (operands[0],
3096                                  gen_lowpart (SImode, operands[1]),
3097                                  GEN_INT (255)));
3098         }
3099       else /* TARGET_THUMB */
3100         {
3101           rtx temp = gen_reg_rtx (SImode);
3102           rtx ops[3];
3103           
3104           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3105           operands[1] = gen_lowpart (SImode, operands[1]);
3106
3107           ops[0] = temp;
3108           ops[1] = operands[1];
3109           ops[2] = GEN_INT (24);
3110
3111           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3112                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3113           
3114           ops[0] = operands[0];
3115           ops[1] = temp;
3116           ops[2] = GEN_INT (24);
3117
3118           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3119                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3120         }
3121       DONE;
3122     }
3123   "
3124 )
3125
3126 (define_insn "*thumb_zero_extendqisi2"
3127   [(set (match_operand:SI                 0 "register_operand" "=l")
3128         (zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3129   "TARGET_THUMB"
3130   "ldrb\\t%0, %1"
3131   [(set_attr "length" "2")
3132    (set_attr "type" "load")
3133    (set_attr "pool_range" "32")]
3134 )
3135
3136 (define_insn "*arm_zero_extendqisi2"
3137   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3138         (zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3139   "TARGET_ARM"
3140   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3141   [(set_attr "type" "load")
3142    (set_attr "predicable" "yes")
3143    (set_attr "pool_range" "4096")
3144    (set_attr "neg_pool_range" "4084")]
3145 )
3146
3147 (define_split
3148   [(set (match_operand:SI 0 "s_register_operand" "")
3149         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3150    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3151   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3152   [(set (match_dup 2) (match_dup 1))
3153    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3154   ""
3155 )
3156
3157 (define_insn "*compareqi_eq0"
3158   [(set (reg:CC_Z CC_REGNUM)
3159         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3160                          (const_int 0)))]
3161   "TARGET_ARM"
3162   "tst\\t%0, #255"
3163   [(set_attr "conds" "set")]
3164 )
3165
3166 (define_expand "extendhisi2"
3167   [(set (match_dup 2)
3168         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3169                    (const_int 16)))
3170    (set (match_operand:SI 0 "s_register_operand" "")
3171         (ashiftrt:SI (match_dup 2)
3172                      (const_int 16)))]
3173   "TARGET_EITHER"
3174   "
3175   {
3176     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3177       {
3178        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3179           here because the insn below will generate an LDRH instruction
3180           rather than an LDR instruction, so we cannot get an unaligned
3181           word access.  */
3182         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3183                    gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3184         DONE;
3185       }
3186
3187     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3188       {
3189         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3190         DONE;
3191       }
3192     if (!s_register_operand (operands[1], HImode))
3193       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3194     operands[1] = gen_lowpart (SImode, operands[1]);
3195     operands[2] = gen_reg_rtx (SImode);
3196
3197     if (TARGET_THUMB)
3198       {
3199         rtx ops[3];
3200         
3201         ops[0] = operands[2];
3202         ops[1] = operands[1];
3203         ops[2] = GEN_INT (16);
3204         
3205         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3206                                 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3207             
3208         ops[0] = operands[0];
3209         ops[1] = operands[2];
3210         ops[2] = GEN_INT (16);
3211         
3212         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3213                                 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3214         
3215         DONE;
3216       }
3217   }"
3218 )
3219
3220 (define_insn "*thumb_extendhisi2_insn"
3221   [(set (match_operand:SI                 0 "register_operand" "=l")
3222         (sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3223    (clobber (match_scratch:SI             2                   "=&l"))]
3224   "TARGET_THUMB"
3225   "*
3226   {
3227     rtx ops[4];
3228     rtx mem = XEXP (operands[1], 0);
3229
3230     /* This code used to try to use 'V', and fix the address only if it was
3231        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3232        range of QImode offsets, and offsettable_address_p does a QImode
3233        address check.  */
3234        
3235     if (GET_CODE (mem) == CONST)
3236       mem = XEXP (mem, 0);
3237     
3238     if (GET_CODE (mem) == LABEL_REF)
3239       return \"ldr\\t%0, %1\";
3240     
3241     if (GET_CODE (mem) == PLUS)
3242       {
3243         rtx a = XEXP (mem, 0);
3244         rtx b = XEXP (mem, 1);
3245
3246         if (GET_CODE (a) == LABEL_REF
3247             && GET_CODE (b) == CONST_INT)
3248           return \"ldr\\t%0, %1\";
3249
3250         if (GET_CODE (b) == REG)
3251           return \"ldrsh\\t%0, %1\";
3252           
3253         ops[1] = a;
3254         ops[2] = b;
3255       }
3256     else
3257       {
3258         ops[1] = mem;
3259         ops[2] = const0_rtx;
3260       }
3261       
3262     if (GET_CODE (ops[1]) != REG)
3263       {
3264         debug_rtx (ops[1]);
3265         abort ();
3266       }
3267
3268     ops[0] = operands[0];
3269     ops[3] = operands[2];
3270     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3271     return \"\";
3272   }"
3273   [(set_attr "length" "4")
3274    (set_attr "type" "load")
3275    (set_attr "pool_range" "1020")]
3276 )
3277
3278 (define_expand "extendhisi2_mem"
3279   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3280    (set (match_dup 3)
3281         (zero_extend:SI (match_dup 7)))
3282    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3283    (set (match_operand:SI 0 "" "")
3284         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3285   "TARGET_ARM"
3286   "
3287   {
3288     rtx mem1, mem2;
3289     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3290
3291     mem1 = gen_rtx_MEM (QImode, addr);
3292     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3293     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3294     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3295     operands[0] = gen_lowpart (SImode, operands[0]);
3296     operands[1] = mem1;
3297     operands[2] = gen_reg_rtx (SImode);
3298     operands[3] = gen_reg_rtx (SImode);
3299     operands[6] = gen_reg_rtx (SImode);
3300     operands[7] = mem2;
3301
3302     if (BYTES_BIG_ENDIAN)
3303       {
3304         operands[4] = operands[2];
3305         operands[5] = operands[3];
3306       }
3307     else
3308       {
3309         operands[4] = operands[3];
3310         operands[5] = operands[2];
3311       }
3312   }"
3313 )
3314
3315 (define_insn "*arm_extendhisi_insn"
3316   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3317         (sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3318   "TARGET_ARM && arm_arch4"
3319   "ldr%?sh\\t%0, %1"
3320   [(set_attr "type" "load")
3321    (set_attr "predicable" "yes")
3322    (set_attr "pool_range" "256")
3323    (set_attr "neg_pool_range" "244")]
3324 )
3325
3326 (define_split
3327   [(set (match_operand:SI                 0 "s_register_operand" "")
3328         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3329    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3330   "TARGET_ARM && (!arm_arch4)"
3331   [(set (match_dup 2) (match_dup 1))
3332    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3333   "
3334   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3335     FAIL;
3336   "
3337 )
3338
3339 (define_split
3340   [(set (match_operand:SI                   0 "s_register_operand" "")
3341         (match_operator:SI                  3 "shiftable_operator"
3342          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3343           (match_operand:SI                 4 "s_register_operand" "")]))
3344    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3345   "TARGET_ARM && (!arm_arch4)"
3346   [(set (match_dup 2) (match_dup 1))
3347    (set (match_dup 0)
3348         (match_op_dup 3
3349          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3350   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3351      FAIL;
3352   "
3353 )
3354
3355 (define_expand "extendqihi2"
3356   [(set (match_dup 2)
3357         (ashift:SI (match_operand:QI 1 "general_operand" "")
3358                    (const_int 24)))
3359    (set (match_operand:HI 0 "s_register_operand" "")
3360         (ashiftrt:SI (match_dup 2)
3361                      (const_int 24)))]
3362   "TARGET_ARM"
3363   "
3364   {
3365     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3366       {
3367         emit_insn (gen_rtx_SET (VOIDmode,
3368                                 operands[0],
3369                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3370         DONE;
3371       }
3372     if (!s_register_operand (operands[1], QImode))
3373       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3374     operands[0] = gen_lowpart (SImode, operands[0]);
3375     operands[1] = gen_lowpart (SImode, operands[1]);
3376     operands[2] = gen_reg_rtx (SImode);
3377   }"
3378 )
3379
3380 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3381 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3382 (define_insn "*extendqihi_insn"
3383   [(set (match_operand:HI                 0 "s_register_operand" "=r")
3384         (sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3385   "TARGET_ARM && arm_arch4"
3386   "*
3387   /* If the address is invalid, this will split the instruction into two. */
3388   if (bad_signed_byte_operand (operands[1], VOIDmode))
3389     return \"#\";
3390   return \"ldr%?sb\\t%0, %1\";
3391   "
3392   [(set_attr "type" "load")
3393    (set_attr "predicable" "yes")
3394    (set_attr "length" "8")
3395    (set_attr "pool_range" "256")
3396    (set_attr "neg_pool_range" "244")]
3397 )
3398
3399 (define_split
3400   [(set (match_operand:HI 0 "s_register_operand" "")
3401         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3402   "TARGET_ARM && arm_arch4 && reload_completed"
3403   [(set (match_dup 3) (match_dup 1))
3404    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3405   "
3406   {
3407     HOST_WIDE_INT offset;
3408
3409     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3410     operands[2] = gen_rtx_MEM (QImode, operands[3]);
3411     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3412     operands[1] = XEXP (operands[1], 0);
3413     if (GET_CODE (operands[1]) == PLUS
3414         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3415         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3416              || const_ok_for_arm (-offset)))
3417       {
3418         HOST_WIDE_INT low = (offset > 0
3419                              ? (offset & 0xff) : -((-offset) & 0xff));
3420         XEXP (operands[2], 0) = plus_constant (operands[3], low);
3421         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3422       }
3423     /* Ensure the sum is in correct canonical form */
3424     else if (GET_CODE (operands[1]) == PLUS
3425              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3426              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3427       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3428                                            XEXP (operands[1], 1),
3429                                            XEXP (operands[1], 0));
3430   }"
3431 )
3432
3433 (define_expand "extendqisi2"
3434   [(set (match_dup 2)
3435         (ashift:SI (match_operand:QI 1 "general_operand" "")
3436                    (const_int 24)))
3437    (set (match_operand:SI 0 "s_register_operand" "")
3438         (ashiftrt:SI (match_dup 2)
3439                      (const_int 24)))]
3440   "TARGET_EITHER"
3441   "
3442   {
3443     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3444       {
3445         emit_insn (gen_rtx_SET (VOIDmode,
3446                                 operands[0],
3447                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3448         DONE;
3449       }
3450     if (!s_register_operand (operands[1], QImode))
3451       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3452     operands[1] = gen_lowpart (SImode, operands[1]);
3453     operands[2] = gen_reg_rtx (SImode);
3454     
3455     if (TARGET_THUMB)
3456       {
3457         rtx ops[3];
3458         
3459         ops[0] = operands[2];
3460         ops[1] = operands[1];
3461         ops[2] = GEN_INT (24);
3462         
3463         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3464                    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3465
3466         ops[0] = operands[0];
3467         ops[1] = operands[2];
3468         ops[2] = GEN_INT (24);
3469         
3470         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3471                    gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3472         
3473         DONE;
3474       }
3475   }"
3476 )
3477
3478 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3479 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3480 (define_insn "*arm_extendqisi_insn"
3481   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3482         (sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3483   "TARGET_ARM && arm_arch4"
3484   "*
3485   /* If the address is invalid, this will split the instruction into two. */
3486   if (bad_signed_byte_operand (operands[1], VOIDmode))
3487     return \"#\";
3488   return \"ldr%?sb\\t%0, %1\";
3489   "
3490   [(set_attr "type" "load")
3491    (set_attr "predicable" "yes")
3492    (set_attr "length" "8")
3493    (set_attr "pool_range" "256")
3494    (set_attr "neg_pool_range" "244")]
3495 )
3496
3497 (define_split
3498   [(set (match_operand:SI 0 "s_register_operand" "")
3499         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3500   "TARGET_ARM && arm_arch4 && reload_completed"
3501   [(set (match_dup 0) (match_dup 1))
3502    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3503   "
3504   {
3505     HOST_WIDE_INT offset;
3506
3507     operands[2] = gen_rtx_MEM (QImode, operands[0]);
3508     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3509     operands[1] = XEXP (operands[1], 0);
3510     if (GET_CODE (operands[1]) == PLUS
3511         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3512         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3513              || const_ok_for_arm (-offset)))
3514       {
3515         HOST_WIDE_INT low = (offset > 0
3516                              ? (offset & 0xff) : -((-offset) & 0xff));
3517         XEXP (operands[2], 0) = plus_constant (operands[0], low);
3518         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3519       }
3520     /* Ensure the sum is in correct canonical form */
3521     else if (GET_CODE (operands[1]) == PLUS
3522              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3523              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3524       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3525                                            XEXP (operands[1], 1),
3526                                            XEXP (operands[1], 0));
3527   }"
3528 )
3529
3530 (define_insn "*thumb_extendqisi2_insn"
3531   [(set (match_operand:SI                 0 "register_operand" "=l,l")
3532         (sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3533   "TARGET_THUMB"
3534   "*
3535   {
3536     rtx ops[3];
3537     rtx mem = XEXP (operands[1], 0);
3538     
3539     if (GET_CODE (mem) == CONST)
3540       mem = XEXP (mem, 0);
3541     
3542     if (GET_CODE (mem) == LABEL_REF)
3543       return \"ldr\\t%0, %1\";
3544
3545     if (GET_CODE (mem) == PLUS
3546         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3547       return \"ldr\\t%0, %1\";
3548       
3549     if (which_alternative == 0)
3550       return \"ldrsb\\t%0, %1\";
3551       
3552     ops[0] = operands[0];
3553     
3554     if (GET_CODE (mem) == PLUS)
3555       {
3556         rtx a = XEXP (mem, 0);
3557         rtx b = XEXP (mem, 1);
3558         
3559         ops[1] = a;
3560         ops[2] = b;
3561
3562         if (GET_CODE (a) == REG)
3563           {
3564             if (GET_CODE (b) == REG)
3565               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3566             else if (REGNO (a) == REGNO (ops[0]))
3567               {
3568                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3569                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3570                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3571               }
3572             else
3573               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3574           }
3575         else if (GET_CODE (b) != REG)
3576           abort ();
3577         else
3578           {
3579             if (REGNO (b) == REGNO (ops[0]))
3580               {
3581                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3582                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3583                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3584               }
3585             else
3586               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3587           }
3588       }
3589     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3590       {
3591         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3592         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3593         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3594       }
3595     else
3596       {
3597         ops[1] = mem;
3598         ops[2] = const0_rtx;
3599         
3600         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3601       }
3602     return \"\";
3603   }"
3604   [(set_attr "length" "2,6")
3605    (set_attr "type" "load,load")
3606    (set_attr "pool_range" "32,32")]
3607 )
3608
3609 (define_expand "extendsfdf2"
3610   [(set (match_operand:DF                  0 "s_register_operand" "")
3611         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
3612   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3613   ""
3614 )
3615 \f
3616 ;; Move insns (including loads and stores)
3617
3618 ;; XXX Just some ideas about movti.
3619 ;; I don't think these are a good idea on the arm, there just aren't enough
3620 ;; registers
3621 ;;(define_expand "loadti"
3622 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3623 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3624 ;;  "" "")
3625
3626 ;;(define_expand "storeti"
3627 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3628 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3629 ;;  "" "")
3630
3631 ;;(define_expand "movti"
3632 ;;  [(set (match_operand:TI 0 "general_operand" "")
3633 ;;      (match_operand:TI 1 "general_operand" ""))]
3634 ;;  ""
3635 ;;  "
3636 ;;{
3637 ;;  rtx insn;
3638 ;;
3639 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3640 ;;    operands[1] = copy_to_reg (operands[1]);
3641 ;;  if (GET_CODE (operands[0]) == MEM)
3642 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3643 ;;  else if (GET_CODE (operands[1]) == MEM)
3644 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3645 ;;  else
3646 ;;    FAIL;
3647 ;;
3648 ;;  emit_insn (insn);
3649 ;;  DONE;
3650 ;;}")
3651
3652 ;; Recognize garbage generated above.
3653
3654 ;;(define_insn ""
3655 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3656 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3657 ;;  ""
3658 ;;  "*
3659 ;;  {
3660 ;;    register mem = (which_alternative < 3);
3661 ;;    register const char *template;
3662 ;;
3663 ;;    operands[mem] = XEXP (operands[mem], 0);
3664 ;;    switch (which_alternative)
3665 ;;      {
3666 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3667 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3668 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3669 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3670 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3671 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3672 ;;      }
3673 ;;    output_asm_insn (template, operands);
3674 ;;    return \"\";
3675 ;;  }")
3676
3677 (define_expand "movdi"
3678   [(set (match_operand:DI 0 "general_operand" "")
3679         (match_operand:DI 1 "general_operand" ""))]
3680   "TARGET_EITHER"
3681   "
3682   if (TARGET_THUMB)
3683     {
3684       if (!no_new_pseudos)
3685         {
3686           if (GET_CODE (operands[0]) != REG)
3687             operands[1] = force_reg (DImode, operands[1]);
3688         }
3689     }
3690   "
3691 )
3692
3693 (define_insn "*arm_movdi"
3694   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3695         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3696   "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT"
3697   "*
3698   return (output_move_double (operands));
3699   "
3700   [(set_attr "length" "8")
3701    (set_attr "type" "*,load,store2")
3702    (set_attr "pool_range" "*,1020,*")
3703    (set_attr "neg_pool_range" "*,1008,*")]
3704 )
3705
3706 ;;; ??? This should have alternatives for constants.
3707 ;;; ??? This was originally identical to the movdf_insn pattern.
3708 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3709 ;;; thumb_reorg with a memory reference.
3710 (define_insn "*thumb_movdi_insn"
3711   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3712         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3713   "TARGET_THUMB
3714    && !TARGET_CIRRUS
3715    && (   register_operand (operands[0], DImode)
3716        || register_operand (operands[1], DImode))"
3717   "*
3718   {
3719   switch (which_alternative)
3720     {
3721     default:
3722     case 0:
3723       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3724         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3725       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3726     case 1:
3727       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3728     case 2:
3729       operands[1] = GEN_INT (- INTVAL (operands[1]));
3730       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3731     case 3:
3732       return \"ldmia\\t%1, {%0, %H0}\";
3733     case 4:
3734       return \"stmia\\t%0, {%1, %H1}\";
3735     case 5:
3736       return thumb_load_double_from_address (operands);
3737     case 6:
3738       operands[2] = gen_rtx (MEM, SImode,
3739                              plus_constant (XEXP (operands[0], 0), 4));
3740       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3741       return \"\";
3742     case 7:
3743       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3744         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3745       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3746     }
3747   }"
3748   [(set_attr "length" "4,4,6,2,2,6,4,4")
3749    (set_attr "type" "*,*,*,load,store2,load,store2,*")
3750    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3751 )
3752
3753 (define_expand "movsi"
3754   [(set (match_operand:SI 0 "general_operand" "")
3755         (match_operand:SI 1 "general_operand" ""))]
3756   "TARGET_EITHER"
3757   "
3758   if (TARGET_ARM)
3759     {
3760       /* Everything except mem = const or mem = mem can be done easily */
3761       if (GET_CODE (operands[0]) == MEM)
3762         operands[1] = force_reg (SImode, operands[1]);
3763       if (GET_CODE (operands[1]) == CONST_INT
3764           && !(const_ok_for_arm (INTVAL (operands[1]))
3765                || const_ok_for_arm (~INTVAL (operands[1]))))
3766         {
3767            arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3768                               NULL_RTX,
3769                               (no_new_pseudos ? 0
3770                                : preserve_subexpressions_p ()));
3771           DONE;
3772         }
3773     }
3774   else /* TARGET_THUMB.... */
3775     {
3776       if (!no_new_pseudos)
3777         {
3778           if (GET_CODE (operands[0]) != REG)
3779             operands[1] = force_reg (SImode, operands[1]);
3780         }
3781     }
3782     
3783   if (flag_pic
3784       && (CONSTANT_P (operands[1])
3785          || symbol_mentioned_p (operands[1])
3786          || label_mentioned_p (operands[1])))
3787     operands[1] = legitimize_pic_address (operands[1], SImode,
3788                                           (no_new_pseudos ? operands[0] : 0));
3789   "
3790 )
3791
3792 (define_insn "*arm_movsi_insn"
3793   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3794         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
3795   "TARGET_ARM && ! TARGET_IWMMXT
3796    && (   register_operand (operands[0], SImode)
3797        || register_operand (operands[1], SImode))"
3798   "@
3799    mov%?\\t%0, %1
3800    mvn%?\\t%0, #%B1
3801    ldr%?\\t%0, %1
3802    str%?\\t%1, %0"
3803   [(set_attr "type" "*,*,load,store1")
3804    (set_attr "predicable" "yes")
3805    (set_attr "pool_range" "*,*,4096,*")
3806    (set_attr "neg_pool_range" "*,*,4084,*")]
3807 )
3808
3809 (define_split
3810   [(set (match_operand:SI 0 "s_register_operand" "")
3811         (match_operand:SI 1 "const_int_operand" ""))]
3812   "TARGET_ARM
3813   && (!(const_ok_for_arm (INTVAL (operands[1]))
3814         || const_ok_for_arm (~INTVAL (operands[1]))))"
3815   [(clobber (const_int 0))]
3816   "
3817   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3818                       NULL_RTX, 0);
3819   DONE;
3820   "
3821 )
3822
3823 (define_insn "*thumb_movsi_insn"
3824   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3825         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
3826   "TARGET_THUMB
3827    && (   register_operand (operands[0], SImode) 
3828        || register_operand (operands[1], SImode))"
3829   "@
3830    mov  %0, %1
3831    mov  %0, %1
3832    #
3833    #
3834    ldmia\\t%1, {%0}
3835    stmia\\t%0, {%1}
3836    ldr\\t%0, %1
3837    str\\t%1, %0
3838    mov\\t%0, %1"
3839   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3840    (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3841    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3842 )
3843
3844 (define_split 
3845   [(set (match_operand:SI 0 "register_operand" "")
3846         (match_operand:SI 1 "const_int_operand" ""))]
3847   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3848   [(set (match_dup 0) (match_dup 1))
3849    (set (match_dup 0) (neg:SI (match_dup 0)))]
3850   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3851 )
3852
3853 (define_split 
3854   [(set (match_operand:SI 0 "register_operand" "")
3855         (match_operand:SI 1 "const_int_operand" ""))]
3856   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3857   [(set (match_dup 0) (match_dup 1))
3858    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3859   "
3860   {
3861     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3862     unsigned HOST_WIDE_INT mask = 0xff;
3863     int i;
3864     
3865     for (i = 0; i < 25; i++)
3866       if ((val & (mask << i)) == val)
3867         break;
3868
3869     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
3870     if (i == 0)
3871       FAIL;
3872
3873     operands[1] = GEN_INT (val >> i);
3874     operands[2] = GEN_INT (i);
3875   }"
3876 )
3877
3878 ;; When generating pic, we need to load the symbol offset into a register.
3879 ;; So that the optimizer does not confuse this with a normal symbol load
3880 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
3881 ;; since that is the only type of relocation we can use.
3882
3883 ;; The rather odd constraints on the following are to force reload to leave
3884 ;; the insn alone, and to force the minipool generation pass to then move
3885 ;; the GOT symbol to memory.
3886
3887 (define_insn "pic_load_addr_arm"
3888   [(set (match_operand:SI 0 "s_register_operand" "=r")
3889         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3890   "TARGET_ARM && flag_pic"
3891   "ldr%?\\t%0, %1"
3892   [(set_attr "type" "load")
3893    (set (attr "pool_range")     (const_int 4096))
3894    (set (attr "neg_pool_range") (const_int 4084))]
3895 )
3896
3897 (define_insn "pic_load_addr_thumb"
3898   [(set (match_operand:SI 0 "s_register_operand" "=l")
3899         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3900   "TARGET_THUMB && flag_pic"
3901   "ldr\\t%0, %1"
3902   [(set_attr "type" "load")
3903    (set (attr "pool_range") (const_int 1024))]
3904 )
3905
3906 ;; This variant is used for AOF assembly, since it needs to mention the
3907 ;; pic register in the rtl.
3908 (define_expand "pic_load_addr_based"
3909   [(set (match_operand:SI 0 "s_register_operand" "")
3910         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
3911   "TARGET_ARM && flag_pic"
3912   "operands[2] = pic_offset_table_rtx;"
3913 )
3914
3915 (define_insn "*pic_load_addr_based_insn"
3916   [(set (match_operand:SI 0 "s_register_operand" "=r")
3917         (unspec:SI [(match_operand 1 "" "")
3918                     (match_operand 2 "s_register_operand" "r")]
3919                    UNSPEC_PIC_SYM))]
3920   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
3921   "*
3922 #ifdef AOF_ASSEMBLER
3923   operands[1] = aof_pic_entry (operands[1]);
3924 #endif
3925   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3926   return \"\";
3927   "
3928   [(set_attr "type" "load")
3929    (set (attr "pool_range")
3930         (if_then_else (eq_attr "is_thumb" "yes")
3931                       (const_int 1024)
3932                       (const_int 4096)))
3933    (set (attr "neg_pool_range")
3934         (if_then_else (eq_attr "is_thumb" "yes")
3935                       (const_int 0)
3936                       (const_int 4084)))]
3937 )
3938
3939 (define_insn "pic_add_dot_plus_four"
3940   [(set (match_operand:SI 0 "register_operand" "+r")
3941         (unspec:SI [(plus:SI (match_dup 0)
3942                              (const (plus:SI (pc) (const_int 4))))]
3943                    UNSPEC_PIC_BASE))
3944    (use (label_ref (match_operand 1 "" "")))]
3945   "TARGET_THUMB && flag_pic"
3946   "*
3947   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3948                              CODE_LABEL_NUMBER (operands[1]));
3949   return \"add\\t%0, %|pc\";
3950   "
3951   [(set_attr "length" "2")]
3952 )
3953
3954 (define_insn "pic_add_dot_plus_eight"
3955   [(set (match_operand:SI 0 "register_operand" "+r")
3956         (unspec:SI [(plus:SI (match_dup 0)
3957                              (const (plus:SI (pc) (const_int 8))))]
3958                    UNSPEC_PIC_BASE))
3959    (use (label_ref (match_operand 1 "" "")))]
3960   "TARGET_ARM && flag_pic"
3961   "*
3962     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3963                                CODE_LABEL_NUMBER (operands[1]));
3964     return \"add%?\\t%0, %|pc, %0\";
3965   "
3966   [(set_attr "predicable" "yes")]
3967 )
3968
3969 (define_expand "builtin_setjmp_receiver"
3970   [(label_ref (match_operand 0 "" ""))]
3971   "flag_pic"
3972   "
3973 {
3974   arm_finalize_pic (0);
3975   DONE;
3976 }")
3977
3978 ;; If copying one reg to another we can set the condition codes according to
3979 ;; its value.  Such a move is common after a return from subroutine and the
3980 ;; result is being tested against zero.
3981
3982 (define_insn "*movsi_compare0"
3983   [(set (reg:CC CC_REGNUM)
3984         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
3985                     (const_int 0)))
3986    (set (match_operand:SI 0 "s_register_operand" "=r,r")
3987         (match_dup 1))]
3988   "TARGET_ARM"
3989   "@
3990    cmp%?\\t%0, #0
3991    sub%?s\\t%0, %1, #0"
3992   [(set_attr "conds" "set")]
3993 )
3994
3995 ;; Subroutine to store a half word from a register into memory.
3996 ;; Operand 0 is the source register (HImode)
3997 ;; Operand 1 is the destination address in a register (SImode)
3998
3999 ;; In both this routine and the next, we must be careful not to spill
4000 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4001 ;; can generate unrecognizable rtl.
4002
4003 (define_expand "storehi"
4004   [;; store the low byte
4005    (set (match_operand 1 "" "") (match_dup 3))
4006    ;; extract the high byte
4007    (set (match_dup 2)
4008         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4009    ;; store the high byte
4010    (set (match_dup 4) (match_dup 5))]
4011   "TARGET_ARM"
4012   "
4013   {
4014     rtx op1 = operands[1];
4015     rtx addr = XEXP (op1, 0);
4016     enum rtx_code code = GET_CODE (addr);
4017
4018     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4019         || code == MINUS)
4020       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4021
4022     operands[4] = adjust_address (op1, QImode, 1);
4023     operands[1] = adjust_address (operands[1], QImode, 0);
4024     operands[3] = gen_lowpart (QImode, operands[0]);
4025     operands[0] = gen_lowpart (SImode, operands[0]);
4026     operands[2] = gen_reg_rtx (SImode);
4027     operands[5] = gen_lowpart (QImode, operands[2]);
4028   }"
4029 )
4030
4031 (define_expand "storehi_bigend"
4032   [(set (match_dup 4) (match_dup 3))
4033    (set (match_dup 2)
4034         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4035    (set (match_operand 1 "" "") (match_dup 5))]
4036   "TARGET_ARM"
4037   "
4038   {
4039     rtx op1 = operands[1];
4040     rtx addr = XEXP (op1, 0);
4041     enum rtx_code code = GET_CODE (addr);
4042
4043     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4044         || code == MINUS)
4045       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4046
4047     operands[4] = adjust_address (op1, QImode, 1);
4048     operands[1] = adjust_address (operands[1], QImode, 0);
4049     operands[3] = gen_lowpart (QImode, operands[0]);
4050     operands[0] = gen_lowpart (SImode, operands[0]);
4051     operands[2] = gen_reg_rtx (SImode);
4052     operands[5] = gen_lowpart (QImode, operands[2]);
4053   }"
4054 )
4055
4056 ;; Subroutine to store a half word integer constant into memory.
4057 (define_expand "storeinthi"
4058   [(set (match_operand 0 "" "")
4059         (match_operand 1 "" ""))
4060    (set (match_dup 3) (match_dup 2))]
4061   "TARGET_ARM"
4062   "
4063   {
4064     HOST_WIDE_INT value = INTVAL (operands[1]);
4065     rtx addr = XEXP (operands[0], 0);
4066     rtx op0 = operands[0];
4067     enum rtx_code code = GET_CODE (addr);
4068
4069     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4070         || code == MINUS)
4071       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4072
4073     operands[1] = gen_reg_rtx (SImode);
4074     if (BYTES_BIG_ENDIAN)
4075       {
4076         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4077         if ((value & 255) == ((value >> 8) & 255))
4078           operands[2] = operands[1];
4079         else
4080           {
4081             operands[2] = gen_reg_rtx (SImode);
4082             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4083           }
4084       }
4085     else
4086       {
4087         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4088         if ((value & 255) == ((value >> 8) & 255))
4089           operands[2] = operands[1];
4090         else
4091           {
4092             operands[2] = gen_reg_rtx (SImode);
4093             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4094           }
4095       }
4096
4097     operands[3] = adjust_address (op0, QImode, 1);
4098     operands[0] = adjust_address (operands[0], QImode, 0);
4099     operands[2] = gen_lowpart (QImode, operands[2]);
4100     operands[1] = gen_lowpart (QImode, operands[1]);
4101   }"
4102 )
4103
4104 (define_expand "storehi_single_op"
4105   [(set (match_operand:HI 0 "memory_operand" "")
4106         (match_operand:HI 1 "general_operand" ""))]
4107   "TARGET_ARM && arm_arch4"
4108   "
4109   if (!s_register_operand (operands[1], HImode))
4110     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4111   "
4112 )
4113
4114 (define_expand "movhi"
4115   [(set (match_operand:HI 0 "general_operand" "")
4116         (match_operand:HI 1 "general_operand" ""))]
4117   "TARGET_EITHER"
4118   "
4119   if (TARGET_ARM)
4120     {
4121       if (!no_new_pseudos)
4122         {
4123           if (GET_CODE (operands[0]) == MEM)
4124             {
4125               if (arm_arch4)
4126                 {
4127                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4128                   DONE;
4129                 }
4130               if (GET_CODE (operands[1]) == CONST_INT)
4131                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4132               else
4133                 {
4134                   if (GET_CODE (operands[1]) == MEM)
4135                     operands[1] = force_reg (HImode, operands[1]);
4136                   if (BYTES_BIG_ENDIAN)
4137                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4138                   else
4139                    emit_insn (gen_storehi (operands[1], operands[0]));
4140                 }
4141               DONE;
4142             }
4143           /* Sign extend a constant, and keep it in an SImode reg.  */
4144           else if (GET_CODE (operands[1]) == CONST_INT)
4145             {
4146               rtx reg = gen_reg_rtx (SImode);
4147               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4148
4149               /* If the constant is already valid, leave it alone.  */
4150               if (!const_ok_for_arm (val))
4151                 {
4152                   /* If setting all the top bits will make the constant 
4153                      loadable in a single instruction, then set them.  
4154                      Otherwise, sign extend the number.  */
4155
4156                   if (const_ok_for_arm (~(val | ~0xffff)))
4157                     val |= ~0xffff;
4158                   else if (val & 0x8000)
4159                     val |= ~0xffff;
4160                 }
4161
4162               emit_insn (gen_movsi (reg, GEN_INT (val)));
4163               operands[1] = gen_lowpart (HImode, reg);
4164             }
4165           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4166                    && GET_CODE (operands[1]) == MEM)
4167             {
4168               rtx reg = gen_reg_rtx (SImode);
4169
4170               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4171               operands[1] = gen_lowpart (HImode, reg);
4172             }
4173           else if (!arm_arch4)
4174             {
4175              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4176                 for v4 and up architectures because LDRH instructions will
4177                 be used to access the HI values, and these cannot generate
4178                 unaligned word access faults in the MMU.  */
4179               if (GET_CODE (operands[1]) == MEM)
4180                 {
4181                   if (TARGET_MMU_TRAPS)
4182                     {
4183                       rtx base;
4184                       rtx offset = const0_rtx;
4185                       rtx reg = gen_reg_rtx (SImode);
4186
4187                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4188                            || (GET_CODE (base) == PLUS
4189                                && (GET_CODE (offset = XEXP (base, 1))
4190                                    == CONST_INT)
4191                                && ((INTVAL(offset) & 1) != 1)
4192                                && GET_CODE (base = XEXP (base, 0)) == REG))
4193                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4194                         {
4195                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4196                           rtx new;
4197
4198                           new = gen_rtx_MEM (SImode,
4199                                              plus_constant (base, new_offset));
4200                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4201                           emit_insn (gen_movsi (reg, new));
4202                           if (((INTVAL (offset) & 2) != 0)
4203                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4204                             {
4205                               rtx reg2 = gen_reg_rtx (SImode);
4206
4207                               emit_insn (gen_lshrsi3 (reg2, reg,
4208                                          GEN_INT (16)));
4209                               reg = reg2;
4210                             }
4211                         }
4212                       else
4213                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4214
4215                       operands[1] = gen_lowpart (HImode, reg);
4216                     }
4217                   else if (BYTES_BIG_ENDIAN)
4218                     {
4219                       rtx base;
4220                       rtx offset = const0_rtx;
4221
4222                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4223                            || (GET_CODE (base) == PLUS
4224                               && (GET_CODE (offset = XEXP (base, 1))
4225                                   == CONST_INT)
4226                               && GET_CODE (base = XEXP (base, 0)) == REG))
4227                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4228                         {
4229                           rtx reg = gen_reg_rtx (SImode);
4230                           rtx new;
4231
4232                           if ((INTVAL (offset) & 2) == 2)
4233                             {
4234                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4235                               new = gen_rtx_MEM (SImode,
4236                                                  plus_constant (base,
4237                                                                 new_offset));
4238                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4239                               emit_insn (gen_movsi (reg, new));
4240                             }
4241                           else
4242                             {
4243                               new = gen_rtx_MEM (SImode,
4244                                                  XEXP (operands[1], 0));
4245                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4246                               emit_insn (gen_rotated_loadsi (reg, new));
4247                             }
4248
4249                           operands[1] = gen_lowpart (HImode, reg);
4250                         }
4251                       else
4252                         {
4253                           emit_insn (gen_movhi_bigend (operands[0],
4254                                                        operands[1]));
4255                           DONE;
4256                         }
4257                     }
4258                }
4259            }
4260         }
4261       /* Handle loading a large integer during reload */
4262       else if (GET_CODE (operands[1]) == CONST_INT
4263                && !const_ok_for_arm (INTVAL (operands[1]))
4264                && !const_ok_for_arm (~INTVAL (operands[1])))
4265         {
4266           /* Writing a constant to memory needs a scratch, which should
4267              be handled with SECONDARY_RELOADs.  */
4268           if (GET_CODE (operands[0]) != REG)
4269             abort ();
4270
4271           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4272           emit_insn (gen_movsi (operands[0], operands[1]));
4273           DONE;
4274        }
4275     }
4276   else /* TARGET_THUMB */
4277     {
4278       if (!no_new_pseudos)
4279         {
4280           if (GET_CODE (operands[0]) != REG)
4281             operands[1] = force_reg (HImode, operands[1]);
4282
4283           /* ??? We shouldn't really get invalid addresses here, but this can
4284              happen if we are passed a SP (never OK for HImode/QImode) or 
4285              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4286              HImode/QImode) relative address.  */
4287           /* ??? This should perhaps be fixed elsewhere, for instance, in
4288              fixup_stack_1, by checking for other kinds of invalid addresses,
4289              e.g. a bare reference to a virtual register.  This may confuse the
4290              alpha though, which must handle this case differently.  */
4291           if (GET_CODE (operands[0]) == MEM
4292               && !memory_address_p (GET_MODE (operands[0]),
4293                                     XEXP (operands[0], 0)))
4294             operands[0]
4295               = replace_equiv_address (operands[0],
4296                                        copy_to_reg (XEXP (operands[0], 0)));
4297    
4298           if (GET_CODE (operands[1]) == MEM
4299               && !memory_address_p (GET_MODE (operands[1]),
4300                                     XEXP (operands[1], 0)))
4301             operands[1]
4302               = replace_equiv_address (operands[1],
4303                                        copy_to_reg (XEXP (operands[1], 0)));
4304         }
4305       /* Handle loading a large integer during reload */
4306       else if (GET_CODE (operands[1]) == CONST_INT
4307                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4308         {
4309           /* Writing a constant to memory needs a scratch, which should
4310              be handled with SECONDARY_RELOADs.  */
4311           if (GET_CODE (operands[0]) != REG)
4312             abort ();
4313
4314           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4315           emit_insn (gen_movsi (operands[0], operands[1]));
4316           DONE;
4317         }
4318     }
4319   "
4320 )
4321
4322 (define_insn "*thumb_movhi_insn"
4323   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4324         (match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4325   "TARGET_THUMB
4326    && (   register_operand (operands[0], HImode)
4327        || register_operand (operands[1], HImode))"
4328   "*
4329   switch (which_alternative)
4330     {
4331     case 0: return \"add        %0, %1, #0\";
4332     case 2: return \"strh       %1, %0\";
4333     case 3: return \"mov        %0, %1\";
4334     case 4: return \"mov        %0, %1\";
4335     case 5: return \"mov        %0, %1\";
4336     default: abort ();
4337     case 1:
4338       /* The stack pointer can end up being taken as an index register.
4339           Catch this case here and deal with it.  */
4340       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4341           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4342           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4343         {
4344           rtx ops[2];
4345           ops[0] = operands[0];
4346           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4347       
4348           output_asm_insn (\"mov        %0, %1\", ops);
4349
4350           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4351     
4352         }
4353       return \"ldrh     %0, %1\";
4354     }"
4355   [(set_attr "length" "2,4,2,2,2,2")
4356    (set_attr "type" "*,load,store1,*,*,*")
4357    (set_attr "pool_range" "*,64,*,*,*,*")]
4358 )
4359
4360
4361 (define_insn "rotated_loadsi"
4362   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4363         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4364                    (const_int 16)))]
4365   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4366   "*
4367   {
4368     rtx ops[2];
4369
4370     ops[0] = operands[0];
4371     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4372     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4373     return \"\";
4374   }"
4375   [(set_attr "type" "load")
4376    (set_attr "predicable" "yes")]
4377 )
4378
4379 (define_expand "movhi_bytes"
4380   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4381    (set (match_dup 3)
4382         (zero_extend:SI (match_dup 6)))
4383    (set (match_operand:SI 0 "" "")
4384          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4385   "TARGET_ARM"
4386   "
4387   {
4388     rtx mem1, mem2;
4389     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4390
4391     mem1 = gen_rtx_MEM (QImode, addr);
4392     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4393     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4394     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4395     operands[0] = gen_lowpart (SImode, operands[0]);
4396     operands[1] = mem1;
4397     operands[2] = gen_reg_rtx (SImode);
4398     operands[3] = gen_reg_rtx (SImode);
4399     operands[6] = mem2;
4400
4401     if (BYTES_BIG_ENDIAN)
4402       {
4403         operands[4] = operands[2];
4404         operands[5] = operands[3];
4405       }
4406     else
4407       {
4408         operands[4] = operands[3];
4409         operands[5] = operands[2];
4410       }
4411   }"
4412 )
4413
4414 (define_expand "movhi_bigend"
4415   [(set (match_dup 2)
4416         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4417                    (const_int 16)))
4418    (set (match_dup 3)
4419         (ashiftrt:SI (match_dup 2) (const_int 16)))
4420    (set (match_operand:HI 0 "s_register_operand" "")
4421         (match_dup 4))]
4422   "TARGET_ARM"
4423   "
4424   operands[2] = gen_reg_rtx (SImode);
4425   operands[3] = gen_reg_rtx (SImode);
4426   operands[4] = gen_lowpart (HImode, operands[3]);
4427   "
4428 )
4429
4430 ;; Pattern to recognize insn generated default case above
4431 (define_insn "*movhi_insn_arch4"
4432   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4433         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4434   "TARGET_ARM
4435    && arm_arch4
4436    && (GET_CODE (operands[1]) != CONST_INT
4437        || const_ok_for_arm (INTVAL (operands[1]))
4438        || const_ok_for_arm (~INTVAL (operands[1])))"
4439   "@
4440    mov%?\\t%0, %1\\t%@ movhi
4441    mvn%?\\t%0, #%B1\\t%@ movhi
4442    str%?h\\t%1, %0\\t%@ movhi 
4443    ldr%?h\\t%0, %1\\t%@ movhi"
4444   [(set_attr "type" "*,*,store1,load")
4445    (set_attr "predicable" "yes")
4446    (set_attr "pool_range" "*,*,*,256")
4447    (set_attr "neg_pool_range" "*,*,*,244")]
4448 )
4449
4450 (define_insn "*movhi_insn_littleend"
4451   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4452         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4453   "TARGET_ARM
4454    && !arm_arch4
4455    && !BYTES_BIG_ENDIAN
4456    && !TARGET_MMU_TRAPS
4457    && (GET_CODE (operands[1]) != CONST_INT
4458        || const_ok_for_arm (INTVAL (operands[1]))
4459        || const_ok_for_arm (~INTVAL (operands[1])))"
4460   "@
4461    mov%?\\t%0, %1\\t%@ movhi
4462    mvn%?\\t%0, #%B1\\t%@ movhi
4463    ldr%?\\t%0, %1\\t%@ movhi"
4464   [(set_attr "type" "*,*,load")
4465    (set_attr "predicable" "yes")
4466    (set_attr "pool_range" "4096")
4467    (set_attr "neg_pool_range" "4084")]
4468 )
4469
4470 (define_insn "*movhi_insn_bigend"
4471   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4472         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4473   "TARGET_ARM
4474    && !arm_arch4
4475    && BYTES_BIG_ENDIAN
4476    && !TARGET_MMU_TRAPS
4477    && (GET_CODE (operands[1]) != CONST_INT
4478        || const_ok_for_arm (INTVAL (operands[1]))
4479        || const_ok_for_arm (~INTVAL (operands[1])))"
4480   "@
4481    mov%?\\t%0, %1\\t%@ movhi
4482    mvn%?\\t%0, #%B1\\t%@ movhi
4483    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4484   [(set_attr "type" "*,*,load")
4485    (set_attr "predicable" "yes")
4486    (set_attr "length" "4,4,8")
4487    (set_attr "pool_range" "*,*,4092")
4488    (set_attr "neg_pool_range" "*,*,4084")]
4489 )
4490
4491 (define_insn "*loadhi_si_bigend"
4492   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4493         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4494                    (const_int 16)))]
4495   "TARGET_ARM
4496    && BYTES_BIG_ENDIAN
4497    && !TARGET_MMU_TRAPS"
4498   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4499   [(set_attr "type" "load")
4500    (set_attr "predicable" "yes")
4501    (set_attr "pool_range" "4096")
4502    (set_attr "neg_pool_range" "4084")]
4503 )
4504
4505 (define_insn "*movhi_bytes"
4506   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4507         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4508   "TARGET_ARM && TARGET_MMU_TRAPS"
4509   "@
4510    mov%?\\t%0, %1\\t%@ movhi
4511    mvn%?\\t%0, #%B1\\t%@ movhi"
4512   [(set_attr "predicable" "yes")]
4513 )
4514
4515 (define_insn "thumb_movhi_clobber"
4516   [(set (match_operand:HI     0 "memory_operand"   "=m")
4517         (match_operand:HI     1 "register_operand" "l"))
4518    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4519   "TARGET_THUMB"
4520   "*
4521   abort ();"
4522 )
4523         
4524 ;; We use a DImode scratch because we may occasionally need an additional
4525 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4526 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4527 (define_expand "reload_outhi"
4528   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4529               (match_operand:HI 1 "s_register_operand"        "r")
4530               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4531   "TARGET_EITHER"
4532   "if (TARGET_ARM)
4533      arm_reload_out_hi (operands);
4534    else
4535      thumb_reload_out_hi (operands);
4536   DONE;
4537   "
4538 )
4539
4540 (define_expand "reload_inhi"
4541   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4542               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4543               (match_operand:DI 2 "s_register_operand" "=&r")])]
4544   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4545   "
4546   if (TARGET_ARM)
4547     arm_reload_in_hi (operands);
4548   else
4549     thumb_reload_out_hi (operands);
4550   DONE;
4551 ")
4552
4553 (define_expand "movqi"
4554   [(set (match_operand:QI 0 "general_operand" "")
4555         (match_operand:QI 1 "general_operand" ""))]
4556   "TARGET_EITHER"
4557   "
4558   if (TARGET_ARM)
4559     {
4560       /* Everything except mem = const or mem = mem can be done easily */
4561
4562       if (!no_new_pseudos)
4563         {
4564           if (GET_CODE (operands[1]) == CONST_INT)
4565             {
4566               rtx reg = gen_reg_rtx (SImode);
4567
4568               emit_insn (gen_movsi (reg, operands[1]));
4569               operands[1] = gen_lowpart (QImode, reg);
4570             }
4571           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4572             {
4573               rtx reg = gen_reg_rtx (SImode);
4574
4575               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4576               operands[1] = gen_lowpart (QImode, reg);
4577             }
4578           if (GET_CODE (operands[0]) == MEM)
4579             operands[1] = force_reg (QImode, operands[1]);
4580         }
4581     }
4582   else /* TARGET_THUMB */
4583     {
4584       if (!no_new_pseudos)
4585         {
4586           if (GET_CODE (operands[0]) != REG)
4587             operands[1] = force_reg (QImode, operands[1]);
4588
4589           /* ??? We shouldn't really get invalid addresses here, but this can
4590              happen if we are passed a SP (never OK for HImode/QImode) or
4591              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4592              HImode/QImode) relative address.  */
4593           /* ??? This should perhaps be fixed elsewhere, for instance, in
4594              fixup_stack_1, by checking for other kinds of invalid addresses,
4595              e.g. a bare reference to a virtual register.  This may confuse the
4596              alpha though, which must handle this case differently.  */
4597           if (GET_CODE (operands[0]) == MEM
4598               && !memory_address_p (GET_MODE (operands[0]),
4599                                      XEXP (operands[0], 0)))
4600             operands[0]
4601               = replace_equiv_address (operands[0],
4602                                        copy_to_reg (XEXP (operands[0], 0)));
4603           if (GET_CODE (operands[1]) == MEM
4604               && !memory_address_p (GET_MODE (operands[1]),
4605                                     XEXP (operands[1], 0)))
4606              operands[1]
4607                = replace_equiv_address (operands[1],
4608                                         copy_to_reg (XEXP (operands[1], 0)));
4609         }
4610       /* Handle loading a large integer during reload */
4611       else if (GET_CODE (operands[1]) == CONST_INT
4612                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4613         {
4614           /* Writing a constant to memory needs a scratch, which should
4615              be handled with SECONDARY_RELOADs.  */
4616           if (GET_CODE (operands[0]) != REG)
4617             abort ();
4618
4619           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4620           emit_insn (gen_movsi (operands[0], operands[1]));
4621           DONE;
4622        }
4623     }
4624   "
4625 )
4626
4627
4628 (define_insn "*arm_movqi_insn"
4629   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4630         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4631   "TARGET_ARM
4632    && (   register_operand (operands[0], QImode)
4633        || register_operand (operands[1], QImode))"
4634   "@
4635    mov%?\\t%0, %1
4636    mvn%?\\t%0, #%B1
4637    ldr%?b\\t%0, %1
4638    str%?b\\t%1, %0"
4639   [(set_attr "type" "*,*,load,store1")
4640    (set_attr "predicable" "yes")]
4641 )
4642
4643 (define_insn "*thumb_movqi_insn"
4644   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4645         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4646   "TARGET_THUMB
4647    && (   register_operand (operands[0], QImode)
4648        || register_operand (operands[1], QImode))"
4649   "@
4650    add\\t%0, %1, #0
4651    ldrb\\t%0, %1
4652    strb\\t%1, %0
4653    mov\\t%0, %1
4654    mov\\t%0, %1
4655    mov\\t%0, %1"
4656   [(set_attr "length" "2")
4657    (set_attr "type" "*,load,store1,*,*,*")
4658    (set_attr "pool_range" "*,32,*,*,*,*")]
4659 )
4660
4661 (define_expand "movsf"
4662   [(set (match_operand:SF 0 "general_operand" "")
4663         (match_operand:SF 1 "general_operand" ""))]
4664   "TARGET_EITHER"
4665   "
4666   if (TARGET_ARM)
4667     {
4668       if (GET_CODE (operands[0]) == MEM)
4669         operands[1] = force_reg (SFmode, operands[1]);
4670     }
4671   else /* TARGET_THUMB */
4672     {
4673       if (!no_new_pseudos)
4674         {
4675            if (GET_CODE (operands[0]) != REG)
4676              operands[1] = force_reg (SFmode, operands[1]);
4677         }
4678     }
4679   "
4680 )
4681
4682 (define_split
4683   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4684         (match_operand:SF 1 "immediate_operand" ""))]
4685   "TARGET_ARM
4686    && !TARGET_HARD_FLOAT
4687    && reload_completed
4688    && GET_CODE (operands[1]) == CONST_DOUBLE"
4689   [(set (match_dup 2) (match_dup 3))]
4690   "
4691   operands[2] = gen_lowpart (SImode, operands[0]);
4692   operands[3] = gen_lowpart (SImode, operands[1]);
4693   if (operands[2] == 0 || operands[3] == 0)
4694     FAIL;
4695   "
4696 )
4697
4698 (define_insn "*arm_movsf_soft_insn"
4699   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4700         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4701   "TARGET_ARM
4702    && !TARGET_CIRRUS
4703    && TARGET_SOFT_FLOAT
4704    && (GET_CODE (operands[0]) != MEM
4705        || register_operand (operands[1], SFmode))"
4706   "@
4707    mov%?\\t%0, %1
4708    ldr%?\\t%0, %1\\t%@ float
4709    str%?\\t%1, %0\\t%@ float"
4710   [(set_attr "length" "4,4,4")
4711    (set_attr "predicable" "yes")
4712    (set_attr "type" "*,load,store1")
4713    (set_attr "pool_range" "*,4096,*")
4714    (set_attr "neg_pool_range" "*,4084,*")]
4715 )
4716
4717 ;;; ??? This should have alternatives for constants.
4718 (define_insn "*thumb_movsf_insn"
4719   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4720         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4721   "TARGET_THUMB
4722    && (   register_operand (operands[0], SFmode) 
4723        || register_operand (operands[1], SFmode))"
4724   "@
4725    add\\t%0, %1, #0
4726    ldmia\\t%1, {%0}
4727    stmia\\t%0, {%1}
4728    ldr\\t%0, %1
4729    str\\t%1, %0
4730    mov\\t%0, %1
4731    mov\\t%0, %1"
4732   [(set_attr "length" "2")
4733    (set_attr "type" "*,load,store1,load,store1,*,*")
4734    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4735 )
4736
4737 (define_expand "movdf"
4738   [(set (match_operand:DF 0 "general_operand" "")
4739         (match_operand:DF 1 "general_operand" ""))]
4740   "TARGET_EITHER"
4741   "
4742   if (TARGET_ARM)
4743     {
4744       if (GET_CODE (operands[0]) == MEM)
4745         operands[1] = force_reg (DFmode, operands[1]);
4746     }
4747   else /* TARGET_THUMB */
4748     {
4749       if (!no_new_pseudos)
4750         {
4751           if (GET_CODE (operands[0]) != REG)
4752             operands[1] = force_reg (DFmode, operands[1]);
4753         }
4754     }
4755   "
4756 )
4757
4758 ;; Reloading a df mode value stored in integer regs to memory can require a
4759 ;; scratch reg.
4760 (define_expand "reload_outdf"
4761   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4762    (match_operand:DF 1 "s_register_operand" "r")
4763    (match_operand:SI 2 "s_register_operand" "=&r")]
4764   "TARGET_ARM"
4765   "
4766   {
4767     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4768
4769     if (code == REG)
4770       operands[2] = XEXP (operands[0], 0);
4771     else if (code == POST_INC || code == PRE_DEC)
4772       {
4773         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4774         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4775         emit_insn (gen_movdi (operands[0], operands[1]));
4776         DONE;
4777       }
4778     else if (code == PRE_INC)
4779       {
4780         rtx reg = XEXP (XEXP (operands[0], 0), 0);
4781
4782         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4783         operands[2] = reg;
4784       }
4785     else if (code == POST_DEC)
4786       operands[2] = XEXP (XEXP (operands[0], 0), 0);
4787     else
4788       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4789                              XEXP (XEXP (operands[0], 0), 1)));
4790
4791     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4792                             operands[1]));
4793
4794     if (code == POST_DEC)
4795       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4796
4797     DONE;
4798   }"
4799 )
4800
4801 (define_insn "*movdf_soft_insn"
4802   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4803         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4804   "TARGET_ARM && TARGET_SOFT_FLOAT
4805    && !TARGET_CIRRUS
4806   "
4807   "* return output_move_double (operands);"
4808   [(set_attr "length" "8,8,8")
4809    (set_attr "type" "*,load,store2")
4810    (set_attr "pool_range" "1020")
4811    (set_attr "neg_pool_range" "1008")]
4812 )
4813
4814 ;;; ??? This should have alternatives for constants.
4815 ;;; ??? This was originally identical to the movdi_insn pattern.
4816 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4817 ;;; thumb_reorg with a memory reference.
4818 (define_insn "*thumb_movdf_insn"
4819   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4820         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
4821   "TARGET_THUMB
4822    && (   register_operand (operands[0], DFmode)
4823        || register_operand (operands[1], DFmode))"
4824   "*
4825   switch (which_alternative)
4826     {
4827     default:
4828     case 0:
4829       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4830         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4831       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4832     case 1:
4833       return \"ldmia\\t%1, {%0, %H0}\";
4834     case 2:
4835       return \"stmia\\t%0, {%1, %H1}\";
4836     case 3:
4837       return thumb_load_double_from_address (operands);
4838     case 4:
4839       operands[2] = gen_rtx (MEM, SImode,
4840                              plus_constant (XEXP (operands[0], 0), 4));
4841       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4842       return \"\";
4843     case 5:
4844       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4845         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4846       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4847     }
4848   "
4849   [(set_attr "length" "4,2,2,6,4,4")
4850    (set_attr "type" "*,load,store2,load,store2,*")
4851    (set_attr "pool_range" "*,*,*,1020,*,*")]
4852 )
4853
4854 ;; Vector Moves
4855 (define_expand "movv2si"
4856   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
4857         (match_operand:V2SI 1 "general_operand" ""))]
4858   "TARGET_REALLY_IWMMXT"
4859 {
4860 })
4861
4862 (define_expand "movv4hi"
4863   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
4864         (match_operand:V4HI 1 "general_operand" ""))]
4865   "TARGET_REALLY_IWMMXT"
4866 {
4867 })
4868
4869 (define_expand "movv8qi"
4870   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
4871         (match_operand:V8QI 1 "general_operand" ""))]
4872   "TARGET_REALLY_IWMMXT"
4873 {
4874 })
4875 \f
4876
4877 ;; load- and store-multiple insns
4878 ;; The arm can load/store any set of registers, provided that they are in
4879 ;; ascending order; but that is beyond GCC so stick with what it knows.
4880
4881 (define_expand "load_multiple"
4882   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4883                           (match_operand:SI 1 "" ""))
4884                      (use (match_operand:SI 2 "" ""))])]
4885   "TARGET_ARM"
4886   "
4887   /* Support only fixed point registers.  */
4888   if (GET_CODE (operands[2]) != CONST_INT
4889       || INTVAL (operands[2]) > 14
4890       || INTVAL (operands[2]) < 2
4891       || GET_CODE (operands[1]) != MEM
4892       || GET_CODE (operands[0]) != REG
4893       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
4894       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4895     FAIL;
4896
4897   operands[3]
4898     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
4899                              force_reg (SImode, XEXP (operands[1], 0)),
4900                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
4901                              MEM_IN_STRUCT_P(operands[1]),
4902                              MEM_SCALAR_P (operands[1]));
4903   "
4904 )
4905
4906 ;; Load multiple with write-back
4907
4908 (define_insn "*ldmsi_postinc4"
4909   [(match_parallel 0 "load_multiple_operation"
4910     [(set (match_operand:SI 1 "s_register_operand" "=r")
4911           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4912                    (const_int 16)))
4913      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4914           (mem:SI (match_dup 2)))
4915      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4916           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4917      (set (match_operand:SI 5 "arm_hard_register_operand" "")
4918           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
4919      (set (match_operand:SI 6 "arm_hard_register_operand" "")
4920           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
4921   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4922   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
4923   [(set_attr "type" "load")
4924    (set_attr "predicable" "yes")]
4925 )
4926
4927 (define_insn "*ldmsi_postinc3"
4928   [(match_parallel 0 "load_multiple_operation"
4929     [(set (match_operand:SI 1 "s_register_operand" "=r")
4930           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4931                    (const_int 12)))
4932      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4933           (mem:SI (match_dup 2)))
4934      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4935           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4936      (set (match_operand:SI 5 "arm_hard_register_operand" "")
4937           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
4938   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4939   "ldm%?ia\\t%1!, {%3, %4, %5}"
4940   [(set_attr "type" "load")
4941    (set_attr "predicable" "yes")]
4942 )
4943
4944 (define_insn "*ldmsi_postinc2"
4945   [(match_parallel 0 "load_multiple_operation"
4946     [(set (match_operand:SI 1 "s_register_operand" "=r")
4947           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4948                    (const_int 8)))
4949      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4950           (mem:SI (match_dup 2)))
4951      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4952           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
4953   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4954   "ldm%?ia\\t%1!, {%3, %4}"
4955   [(set_attr "type" "load")
4956    (set_attr "predicable" "yes")]
4957 )
4958
4959 ;; Ordinary load multiple
4960
4961 (define_insn "*ldmsi4"
4962   [(match_parallel 0 "load_multiple_operation"
4963     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4964           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4965      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4966           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4967      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4968           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4969      (set (match_operand:SI 5 "arm_hard_register_operand" "")
4970           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
4971   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4972   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
4973   [(set_attr "type" "load")
4974    (set_attr "predicable" "yes")]
4975 )
4976
4977 (define_insn "*ldmsi3"
4978   [(match_parallel 0 "load_multiple_operation"
4979     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4980           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4981      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4982           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4983      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4984           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
4985   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4986   "ldm%?ia\\t%1, {%2, %3, %4}"
4987   [(set_attr "type" "load")
4988    (set_attr "predicable" "yes")]
4989 )
4990
4991 (define_insn "*ldmsi2"
4992   [(match_parallel 0 "load_multiple_operation"
4993     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4994           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4995      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4996           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
4997   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4998   "ldm%?ia\\t%1, {%2, %3}"
4999   [(set_attr "type" "load")
5000    (set_attr "predicable" "yes")]
5001 )
5002
5003 (define_expand "store_multiple"
5004   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5005                           (match_operand:SI 1 "" ""))
5006                      (use (match_operand:SI 2 "" ""))])]
5007   "TARGET_ARM"
5008   "
5009   /* Support only fixed point registers */
5010   if (GET_CODE (operands[2]) != CONST_INT
5011       || INTVAL (operands[2]) > 14
5012       || INTVAL (operands[2]) < 2
5013       || GET_CODE (operands[1]) != REG
5014       || GET_CODE (operands[0]) != MEM
5015       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5016       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5017     FAIL;
5018
5019   operands[3]
5020     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5021                               force_reg (SImode, XEXP (operands[0], 0)),
5022                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5023                               MEM_IN_STRUCT_P(operands[0]), 
5024                               MEM_SCALAR_P (operands[0]));
5025   "
5026 )
5027
5028 ;; Store multiple with write-back
5029
5030 (define_insn "*stmsi_postinc4"
5031   [(match_parallel 0 "store_multiple_operation"
5032     [(set (match_operand:SI 1 "s_register_operand" "=r")
5033           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5034                    (const_int 16)))
5035      (set (mem:SI (match_dup 2))
5036           (match_operand:SI 3 "arm_hard_register_operand" ""))
5037      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5038           (match_operand:SI 4 "arm_hard_register_operand" ""))
5039      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5040           (match_operand:SI 5 "arm_hard_register_operand" ""))
5041      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5042           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5043   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5044   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5045   [(set_attr "predicable" "yes")
5046    (set_attr "type" "store4")]
5047 )
5048
5049 (define_insn "*stmsi_postinc3"
5050   [(match_parallel 0 "store_multiple_operation"
5051     [(set (match_operand:SI 1 "s_register_operand" "=r")
5052           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5053                    (const_int 12)))
5054      (set (mem:SI (match_dup 2))
5055           (match_operand:SI 3 "arm_hard_register_operand" ""))
5056      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5057           (match_operand:SI 4 "arm_hard_register_operand" ""))
5058      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5059           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5060   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5061   "stm%?ia\\t%1!, {%3, %4, %5}"
5062   [(set_attr "predicable" "yes")
5063    (set_attr "type" "store3")]
5064 )
5065
5066 (define_insn "*stmsi_postinc2"
5067   [(match_parallel 0 "store_multiple_operation"
5068     [(set (match_operand:SI 1 "s_register_operand" "=r")
5069           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5070                    (const_int 8)))
5071      (set (mem:SI (match_dup 2))
5072           (match_operand:SI 3 "arm_hard_register_operand" ""))
5073      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5074           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5075   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5076   "stm%?ia\\t%1!, {%3, %4}"
5077   [(set_attr "predicable" "yes")
5078    (set_attr "type" "store2")]
5079 )
5080
5081 ;; Ordinary store multiple
5082
5083 (define_insn "*stmsi4"
5084   [(match_parallel 0 "store_multiple_operation"
5085     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5086           (match_operand:SI 2 "arm_hard_register_operand" ""))
5087      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5088           (match_operand:SI 3 "arm_hard_register_operand" ""))
5089      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5090           (match_operand:SI 4 "arm_hard_register_operand" ""))
5091      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5092           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5093   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5094   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5095   [(set_attr "predicable" "yes")
5096    (set_attr "type" "store4")]
5097 )
5098
5099 (define_insn "*stmsi3"
5100   [(match_parallel 0 "store_multiple_operation"
5101     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5102           (match_operand:SI 2 "arm_hard_register_operand" ""))
5103      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5104           (match_operand:SI 3 "arm_hard_register_operand" ""))
5105      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5106           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5107   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5108   "stm%?ia\\t%1, {%2, %3, %4}"
5109   [(set_attr "predicable" "yes")
5110    (set_attr "type" "store3")]
5111 )
5112
5113 (define_insn "*stmsi2"
5114   [(match_parallel 0 "store_multiple_operation"
5115     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5116           (match_operand:SI 2 "arm_hard_register_operand" ""))
5117      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5118           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5119   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5120   "stm%?ia\\t%1, {%2, %3}"
5121   [(set_attr "predicable" "yes")
5122    (set_attr "type" "store2")]
5123 )
5124
5125 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5126 ;; We could let this apply for blocks of less than this, but it clobbers so
5127 ;; many registers that there is then probably a better way.
5128
5129 (define_expand "movstrqi"
5130   [(match_operand:BLK 0 "general_operand" "")
5131    (match_operand:BLK 1 "general_operand" "")
5132    (match_operand:SI 2 "const_int_operand" "")
5133    (match_operand:SI 3 "const_int_operand" "")]
5134   "TARGET_EITHER"
5135   "
5136   if (TARGET_ARM)
5137     {
5138       if (arm_gen_movstrqi (operands))
5139         DONE;
5140       FAIL;
5141     }
5142   else /* TARGET_THUMB */
5143     {
5144       if (   INTVAL (operands[3]) != 4
5145           || INTVAL (operands[2]) > 48)
5146         FAIL;
5147
5148       thumb_expand_movstrqi (operands);
5149       DONE;
5150     }
5151   "
5152 )
5153
5154 ;; Thumb block-move insns
5155
5156 (define_insn "movmem12b"
5157   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5158         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5159    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5160         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5161    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5162         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5163    (set (match_operand:SI 0 "register_operand" "=l")
5164         (plus:SI (match_dup 2) (const_int 12)))
5165    (set (match_operand:SI 1 "register_operand" "=l")
5166         (plus:SI (match_dup 3) (const_int 12)))
5167    (clobber (match_scratch:SI 4 "=&l"))
5168    (clobber (match_scratch:SI 5 "=&l"))
5169    (clobber (match_scratch:SI 6 "=&l"))]
5170   "TARGET_THUMB"
5171   "* return thumb_output_move_mem_multiple (3, operands);"
5172   [(set_attr "length" "4")
5173    ; This isn't entirely accurate...  It loads as well, but in terms of
5174    ; scheduling the following insn it is better to consider it as a store
5175    (set_attr "type" "store3")]
5176 )
5177
5178 (define_insn "movmem8b"
5179   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5180         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5181    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5182         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5183    (set (match_operand:SI 0 "register_operand" "=l")
5184         (plus:SI (match_dup 2) (const_int 8)))
5185    (set (match_operand:SI 1 "register_operand" "=l")
5186         (plus:SI (match_dup 3) (const_int 8)))
5187    (clobber (match_scratch:SI 4 "=&l"))
5188    (clobber (match_scratch:SI 5 "=&l"))]
5189   "TARGET_THUMB"
5190   "* return thumb_output_move_mem_multiple (2, operands);"
5191   [(set_attr "length" "4")
5192    ; This isn't entirely accurate...  It loads as well, but in terms of
5193    ; scheduling the following insn it is better to consider it as a store
5194    (set_attr "type" "store2")]
5195 )
5196
5197 \f
5198
5199 ;; Compare & branch insns
5200 ;; The range calculations are based as follows:
5201 ;; For forward branches, the address calculation returns the address of
5202 ;; the next instruction.  This is 2 beyond the branch instruction.
5203 ;; For backward branches, the address calculation returns the address of
5204 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5205 ;; instruction for the shortest sequence, and 4 before the branch instruction
5206 ;; if we have to jump around an unconditional branch.
5207 ;; To the basic branch range the PC offset must be added (this is +4).
5208 ;; So for forward branches we have 
5209 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5210 ;; And for backward branches we have 
5211 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5212 ;;
5213 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5214 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5215
5216 (define_expand "cbranchsi4"
5217   [(set (pc) (if_then_else
5218               (match_operator 0 "arm_comparison_operator"
5219                [(match_operand:SI 1 "s_register_operand" "")
5220                 (match_operand:SI 2 "nonmemory_operand" "")])
5221               (label_ref (match_operand 3 "" ""))
5222               (pc)))]
5223   "TARGET_THUMB"
5224   "
5225   if (thumb_cmpneg_operand (operands[2], SImode))
5226     {
5227       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5228                                               operands[3], operands[0]));
5229       DONE;
5230     }
5231   if (!thumb_cmp_operand (operands[2], SImode))
5232     operands[2] = force_reg (SImode, operands[2]);
5233   ")
5234
5235 (define_insn "*cbranchsi4_insn"
5236   [(set (pc) (if_then_else
5237               (match_operator 0 "arm_comparison_operator"
5238                [(match_operand:SI 1 "s_register_operand" "l,*h")
5239                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5240               (label_ref (match_operand 3 "" ""))
5241               (pc)))]
5242   "TARGET_THUMB"
5243   "*
5244   output_asm_insn (\"cmp\\t%1, %2\", operands);
5245
5246   switch (get_attr_length (insn))
5247     {
5248     case 4:  return \"b%d0\\t%l3\";
5249     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5250     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5251     }
5252   "
5253   [(set (attr "far_jump")
5254         (if_then_else
5255             (eq_attr "length" "8")
5256             (const_string "yes")
5257             (const_string "no")))
5258    (set (attr "length") 
5259         (if_then_else
5260             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5261                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5262             (const_int 4)
5263             (if_then_else
5264                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5265                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5266                 (const_int 6)
5267                 (const_int 8))))]
5268 )
5269
5270 (define_insn "cbranchsi4_scratch"
5271   [(set (pc) (if_then_else
5272               (match_operator 4 "arm_comparison_operator"
5273                [(match_operand:SI 1 "s_register_operand" "l,0")
5274                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5275               (label_ref (match_operand 3 "" ""))
5276               (pc)))
5277    (clobber (match_scratch:SI 0 "=l,l"))]
5278   "TARGET_THUMB"
5279   "*
5280   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5281
5282   switch (get_attr_length (insn))
5283     {
5284     case 4:  return \"b%d4\\t%l3\";
5285     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5286     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5287     }
5288   "
5289   [(set (attr "far_jump")
5290         (if_then_else
5291             (eq_attr "length" "8")
5292             (const_string "yes")
5293             (const_string "no")))
5294    (set (attr "length") 
5295         (if_then_else
5296             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5297                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5298             (const_int 4)
5299             (if_then_else
5300                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5301                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5302                 (const_int 6)
5303                 (const_int 8))))]
5304 )
5305 (define_insn "*movsi_cbranchsi4"
5306   [(set (pc)
5307         (if_then_else
5308          (match_operator 3 "arm_comparison_operator"
5309           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5310            (const_int 0)])
5311          (label_ref (match_operand 2 "" ""))
5312          (pc)))
5313    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5314         (match_dup 1))]
5315   "TARGET_THUMB"
5316   "*{
5317   if (which_alternative == 0)
5318     output_asm_insn (\"cmp\t%0, #0\", operands);
5319   else if (which_alternative == 1)
5320     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5321   else
5322     {
5323       output_asm_insn (\"cmp\t%1, #0\", operands);
5324       if (which_alternative == 2)
5325         output_asm_insn (\"mov\t%0, %1\", operands);
5326       else
5327         output_asm_insn (\"str\t%1, %0\", operands);
5328     }
5329   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5330     {
5331     case 4:  return \"b%d3\\t%l2\";
5332     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5333     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5334     }
5335   }"
5336   [(set (attr "far_jump")
5337         (if_then_else
5338             (ior (and (gt (symbol_ref ("which_alternative"))
5339                           (const_int 1))
5340                       (eq_attr "length" "8"))
5341                  (eq_attr "length" "10"))
5342             (const_string "yes")
5343             (const_string "no")))
5344    (set (attr "length")
5345      (if_then_else
5346        (le (symbol_ref ("which_alternative"))
5347                        (const_int 1))
5348        (if_then_else
5349          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5350               (le (minus (match_dup 2) (pc)) (const_int 256)))
5351          (const_int 4)
5352          (if_then_else
5353            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5354                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5355            (const_int 6)
5356            (const_int 8)))
5357        (if_then_else
5358          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5359               (le (minus (match_dup 2) (pc)) (const_int 256)))
5360          (const_int 6)
5361          (if_then_else
5362            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5363                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5364            (const_int 8)
5365            (const_int 10)))))]
5366 )
5367
5368 (define_insn "*negated_cbranchsi4"
5369   [(set (pc)
5370         (if_then_else
5371          (match_operator 0 "arm_comparison_operator"
5372           [(match_operand:SI 1 "s_register_operand" "l")
5373            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5374          (label_ref (match_operand 3 "" ""))
5375          (pc)))]
5376   "TARGET_THUMB"
5377   "*
5378   output_asm_insn (\"cmn\\t%1, %2\", operands);
5379   switch (get_attr_length (insn))
5380     {
5381     case 4:  return \"b%d0\\t%l3\";
5382     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5383     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5384     }
5385   "
5386   [(set (attr "far_jump")
5387         (if_then_else
5388             (eq_attr "length" "8")
5389             (const_string "yes")
5390             (const_string "no")))
5391    (set (attr "length") 
5392         (if_then_else
5393             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5394                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5395             (const_int 4)
5396             (if_then_else
5397                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5398                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5399                 (const_int 6)
5400                 (const_int 8))))]
5401 )
5402
5403 (define_insn "*tbit_cbranch"
5404   [(set (pc)
5405         (if_then_else
5406          (match_operator 0 "equality_operator"
5407           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5408                             (const_int 1)
5409                             (match_operand:SI 2 "const_int_operand" "i"))
5410            (const_int 0)])
5411          (label_ref (match_operand 3 "" ""))
5412          (pc)))
5413    (clobber (match_scratch:SI 4 "=l"))]
5414   "TARGET_THUMB"
5415   "*
5416   {
5417   rtx op[3];
5418   op[0] = operands[4];
5419   op[1] = operands[1];
5420   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5421
5422   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5423   switch (get_attr_length (insn))
5424     {
5425     case 4:  return \"b%d0\\t%l3\";
5426     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5427     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5428     }
5429   }"
5430   [(set (attr "far_jump")
5431         (if_then_else
5432             (eq_attr "length" "8")
5433             (const_string "yes")
5434             (const_string "no")))
5435    (set (attr "length") 
5436         (if_then_else
5437             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5438                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5439             (const_int 4)
5440             (if_then_else
5441                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5442                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5443                 (const_int 6)
5444                 (const_int 8))))]
5445 )
5446   
5447 (define_insn "*tstsi3_cbranch"
5448   [(set (pc)
5449         (if_then_else
5450          (match_operator 3 "equality_operator"
5451           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5452                    (match_operand:SI 1 "s_register_operand" "l"))
5453            (const_int 0)])
5454          (label_ref (match_operand 2 "" ""))
5455          (pc)))]
5456   "TARGET_THUMB"
5457   "*
5458   {
5459   output_asm_insn (\"tst\\t%0, %1\", operands);
5460   switch (get_attr_length (insn))
5461     {
5462     case 4:  return \"b%d3\\t%l2\";
5463     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5464     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5465     }
5466   }"
5467   [(set (attr "far_jump")
5468         (if_then_else
5469             (eq_attr "length" "8")
5470             (const_string "yes")
5471             (const_string "no")))
5472    (set (attr "length") 
5473         (if_then_else
5474             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5475                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5476             (const_int 4)
5477             (if_then_else
5478                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5479                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5480                 (const_int 6)
5481                 (const_int 8))))]
5482 )
5483   
5484 (define_insn "*andsi3_cbranch"
5485   [(set (pc)
5486         (if_then_else
5487          (match_operator 5 "equality_operator"
5488           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5489                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5490            (const_int 0)])
5491          (label_ref (match_operand 4 "" ""))
5492          (pc)))
5493    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5494         (and:SI (match_dup 2) (match_dup 3)))
5495    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5496   "TARGET_THUMB"
5497   "*
5498   {
5499   if (which_alternative == 0)
5500     output_asm_insn (\"and\\t%0, %3\", operands);
5501   else if (which_alternative == 1)
5502     {
5503       output_asm_insn (\"and\\t%1, %3\", operands);
5504       output_asm_insn (\"mov\\t%0, %1\", operands);
5505     }
5506   else
5507     {
5508       output_asm_insn (\"and\\t%1, %3\", operands);
5509       output_asm_insn (\"str\\t%1, %0\", operands);
5510     }
5511
5512   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5513     {
5514     case 4:  return \"b%d5\\t%l4\";
5515     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5516     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5517     }
5518   }"
5519   [(set (attr "far_jump")
5520         (if_then_else
5521             (ior (and (eq (symbol_ref ("which_alternative"))
5522                           (const_int 0))
5523                       (eq_attr "length" "8"))
5524                  (eq_attr "length" "10"))
5525             (const_string "yes")
5526             (const_string "no")))
5527    (set (attr "length")
5528      (if_then_else
5529        (eq (symbol_ref ("which_alternative"))
5530                        (const_int 0))
5531        (if_then_else
5532          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5533               (le (minus (match_dup 4) (pc)) (const_int 256)))
5534          (const_int 4)
5535          (if_then_else
5536            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5537                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5538            (const_int 6)
5539            (const_int 8)))
5540        (if_then_else
5541          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5542               (le (minus (match_dup 4) (pc)) (const_int 256)))
5543          (const_int 6)
5544          (if_then_else
5545            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5546                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5547            (const_int 8)
5548            (const_int 10)))))]
5549 )
5550
5551 (define_insn "*orrsi3_cbranch_scratch"
5552   [(set (pc)
5553         (if_then_else
5554          (match_operator 4 "equality_operator"
5555           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5556                    (match_operand:SI 2 "s_register_operand" "l"))
5557            (const_int 0)])
5558          (label_ref (match_operand 3 "" ""))
5559          (pc)))
5560    (clobber (match_scratch:SI 0 "=l"))]
5561   "TARGET_THUMB"
5562   "*
5563   {
5564   output_asm_insn (\"orr\\t%0, %2\", operands);
5565   switch (get_attr_length (insn))
5566     {
5567     case 4:  return \"b%d4\\t%l3\";
5568     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5569     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5570     }
5571   }"
5572   [(set (attr "far_jump")
5573         (if_then_else
5574             (eq_attr "length" "8")
5575             (const_string "yes")
5576             (const_string "no")))
5577    (set (attr "length") 
5578         (if_then_else
5579             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5580                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5581             (const_int 4)
5582             (if_then_else
5583                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5584                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5585                 (const_int 6)
5586                 (const_int 8))))]
5587 )
5588   
5589 (define_insn "*orrsi3_cbranch"
5590   [(set (pc)
5591         (if_then_else
5592          (match_operator 5 "equality_operator"
5593           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5594                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5595            (const_int 0)])
5596          (label_ref (match_operand 4 "" ""))
5597          (pc)))
5598    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5599         (ior:SI (match_dup 2) (match_dup 3)))
5600    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5601   "TARGET_THUMB"
5602   "*
5603   {
5604   if (which_alternative == 0)
5605     output_asm_insn (\"orr\\t%0, %3\", operands);
5606   else if (which_alternative == 1)
5607     {
5608       output_asm_insn (\"orr\\t%1, %3\", operands);
5609       output_asm_insn (\"mov\\t%0, %1\", operands);
5610     }
5611   else
5612     {
5613       output_asm_insn (\"orr\\t%1, %3\", operands);
5614       output_asm_insn (\"str\\t%1, %0\", operands);
5615     }
5616
5617   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5618     {
5619     case 4:  return \"b%d5\\t%l4\";
5620     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5621     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5622     }
5623   }"
5624   [(set (attr "far_jump")
5625         (if_then_else
5626             (ior (and (eq (symbol_ref ("which_alternative"))
5627                           (const_int 0))
5628                       (eq_attr "length" "8"))
5629                  (eq_attr "length" "10"))
5630             (const_string "yes")
5631             (const_string "no")))
5632    (set (attr "length")
5633      (if_then_else
5634        (eq (symbol_ref ("which_alternative"))
5635                        (const_int 0))
5636        (if_then_else
5637          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5638               (le (minus (match_dup 4) (pc)) (const_int 256)))
5639          (const_int 4)
5640          (if_then_else
5641            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5642                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5643            (const_int 6)
5644            (const_int 8)))
5645        (if_then_else
5646          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5647               (le (minus (match_dup 4) (pc)) (const_int 256)))
5648          (const_int 6)
5649          (if_then_else
5650            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5651                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5652            (const_int 8)
5653            (const_int 10)))))]
5654 )
5655
5656 (define_insn "*xorsi3_cbranch_scratch"
5657   [(set (pc)
5658         (if_then_else
5659          (match_operator 4 "equality_operator"
5660           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
5661                    (match_operand:SI 2 "s_register_operand" "l"))
5662            (const_int 0)])
5663          (label_ref (match_operand 3 "" ""))
5664          (pc)))
5665    (clobber (match_scratch:SI 0 "=l"))]
5666   "TARGET_THUMB"
5667   "*
5668   {
5669   output_asm_insn (\"eor\\t%0, %2\", operands);
5670   switch (get_attr_length (insn))
5671     {
5672     case 4:  return \"b%d4\\t%l3\";
5673     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5674     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5675     }
5676   }"
5677   [(set (attr "far_jump")
5678         (if_then_else
5679             (eq_attr "length" "8")
5680             (const_string "yes")
5681             (const_string "no")))
5682    (set (attr "length") 
5683         (if_then_else
5684             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5685                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5686             (const_int 4)
5687             (if_then_else
5688                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5689                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5690                 (const_int 6)
5691                 (const_int 8))))]
5692 )
5693   
5694 (define_insn "*xorsi3_cbranch"
5695   [(set (pc)
5696         (if_then_else
5697          (match_operator 5 "equality_operator"
5698           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5699                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5700            (const_int 0)])
5701          (label_ref (match_operand 4 "" ""))
5702          (pc)))
5703    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5704         (xor:SI (match_dup 2) (match_dup 3)))
5705    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5706   "TARGET_THUMB"
5707   "*
5708   {
5709   if (which_alternative == 0)
5710     output_asm_insn (\"eor\\t%0, %3\", operands);
5711   else if (which_alternative == 1)
5712     {
5713       output_asm_insn (\"eor\\t%1, %3\", operands);
5714       output_asm_insn (\"mov\\t%0, %1\", operands);
5715     }
5716   else
5717     {
5718       output_asm_insn (\"eor\\t%1, %3\", operands);
5719       output_asm_insn (\"str\\t%1, %0\", operands);
5720     }
5721
5722   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5723     {
5724     case 4:  return \"b%d5\\t%l4\";
5725     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5726     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5727     }
5728   }"
5729   [(set (attr "far_jump")
5730         (if_then_else
5731             (ior (and (eq (symbol_ref ("which_alternative"))
5732                           (const_int 0))
5733                       (eq_attr "length" "8"))
5734                  (eq_attr "length" "10"))
5735             (const_string "yes")
5736             (const_string "no")))
5737    (set (attr "length")
5738      (if_then_else
5739        (eq (symbol_ref ("which_alternative"))
5740                        (const_int 0))
5741        (if_then_else
5742          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5743               (le (minus (match_dup 4) (pc)) (const_int 256)))
5744          (const_int 4)
5745          (if_then_else
5746            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5747                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5748            (const_int 6)
5749            (const_int 8)))
5750        (if_then_else
5751          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5752               (le (minus (match_dup 4) (pc)) (const_int 256)))
5753          (const_int 6)
5754          (if_then_else
5755            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5756                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5757            (const_int 8)
5758            (const_int 10)))))]
5759 )
5760
5761 (define_insn "*bicsi3_cbranch_scratch"
5762   [(set (pc)
5763         (if_then_else
5764          (match_operator 4 "equality_operator"
5765           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
5766                    (match_operand:SI 1 "s_register_operand" "0"))
5767            (const_int 0)])
5768          (label_ref (match_operand 3 "" ""))
5769          (pc)))
5770    (clobber (match_scratch:SI 0 "=l"))]
5771   "TARGET_THUMB"
5772   "*
5773   {
5774   output_asm_insn (\"bic\\t%0, %2\", operands);
5775   switch (get_attr_length (insn))
5776     {
5777     case 4:  return \"b%d4\\t%l3\";
5778     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5779     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5780     }
5781   }"
5782   [(set (attr "far_jump")
5783         (if_then_else
5784             (eq_attr "length" "8")
5785             (const_string "yes")
5786             (const_string "no")))
5787    (set (attr "length") 
5788         (if_then_else
5789             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5790                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5791             (const_int 4)
5792             (if_then_else
5793                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5794                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5795                 (const_int 6)
5796                 (const_int 8))))]
5797 )
5798   
5799 (define_insn "*bicsi3_cbranch"
5800   [(set (pc)
5801         (if_then_else
5802          (match_operator 5 "equality_operator"
5803           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5804                    (match_operand:SI 2 "s_register_operand" "0,1,1,1"))
5805            (const_int 0)])
5806          (label_ref (match_operand 4 "" ""))
5807          (pc)))
5808    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5809         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
5810    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5811   "TARGET_THUMB"
5812   "*
5813   {
5814   if (which_alternative == 0)
5815     output_asm_insn (\"bic\\t%0, %3\", operands);
5816   else if (which_alternative == 1)
5817     {
5818       output_asm_insn (\"bic\\t%1, %3\", operands);
5819       output_asm_insn (\"mov\\t%0, %1\", operands);
5820     }
5821   else
5822     {
5823       output_asm_insn (\"bic\\t%1, %3\", operands);
5824       output_asm_insn (\"str\\t%1, %0\", operands);
5825     }
5826
5827   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5828     {
5829     case 4:  return \"b%d5\\t%l4\";
5830     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5831     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5832     }
5833   }"
5834   [(set (attr "far_jump")
5835         (if_then_else
5836             (ior (and (eq (symbol_ref ("which_alternative"))
5837                           (const_int 0))
5838                       (eq_attr "length" "8"))
5839                  (eq_attr "length" "10"))
5840             (const_string "yes")
5841             (const_string "no")))
5842    (set (attr "length")
5843      (if_then_else
5844        (eq (symbol_ref ("which_alternative"))
5845                        (const_int 0))
5846        (if_then_else
5847          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5848               (le (minus (match_dup 4) (pc)) (const_int 256)))
5849          (const_int 4)
5850          (if_then_else
5851            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5852                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5853            (const_int 6)
5854            (const_int 8)))
5855        (if_then_else
5856          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5857               (le (minus (match_dup 4) (pc)) (const_int 256)))
5858          (const_int 6)
5859          (if_then_else
5860            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5861                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5862            (const_int 8)
5863            (const_int 10)))))]
5864 )
5865
5866 (define_insn "*cbranchne_decr1"
5867   [(set (pc)
5868         (if_then_else (match_operator 3 "equality_operator"
5869                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
5870                         (const_int 0)])
5871                       (label_ref (match_operand 4 "" ""))
5872                       (pc)))
5873    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5874         (plus:SI (match_dup 2) (const_int -1)))
5875    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5876   "TARGET_THUMB"
5877   "*
5878    {
5879      rtx cond[2];
5880      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
5881                                 ? GEU : LTU),
5882                                VOIDmode, operands[2], const1_rtx);
5883      cond[1] = operands[4];
5884
5885      if (which_alternative == 0)
5886        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
5887      else if (which_alternative == 1)
5888        {
5889          /* We must provide an alternative for a hi reg because reload 
5890             cannot handle output reloads on a jump instruction, but we
5891             can't subtract into that.  Fortunately a mov from lo to hi
5892             does not clobber the condition codes.  */
5893          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
5894          output_asm_insn (\"mov\\t%0, %1\", operands);
5895        }
5896      else
5897        {
5898          /* Similarly, but the target is memory.  */
5899          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
5900          output_asm_insn (\"str\\t%1, %0\", operands);
5901        }
5902
5903      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5904        {
5905          case 4:
5906            output_asm_insn (\"b%d0\\t%l1\", cond);
5907            return \"\";
5908          case 6:
5909            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
5910            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
5911          default:
5912            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
5913            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5914        }
5915    }
5916   "
5917   [(set (attr "far_jump")
5918         (if_then_else
5919             (ior (and (eq (symbol_ref ("which_alternative"))
5920                           (const_int 0))
5921                       (eq_attr "length" "8"))
5922                  (eq_attr "length" "10"))
5923             (const_string "yes")
5924             (const_string "no")))
5925    (set_attr_alternative "length"
5926       [
5927        ;; Alternative 0
5928        (if_then_else
5929          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5930               (le (minus (match_dup 4) (pc)) (const_int 256)))
5931          (const_int 4)
5932          (if_then_else
5933            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5934                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5935            (const_int 6)
5936            (const_int 8)))
5937        ;; Alternative 1
5938        (if_then_else
5939          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5940               (le (minus (match_dup 4) (pc)) (const_int 256)))
5941          (const_int 6)
5942          (if_then_else
5943            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5944                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5945            (const_int 8)
5946            (const_int 10)))
5947        ;; Alternative 2
5948        (if_then_else
5949          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5950               (le (minus (match_dup 4) (pc)) (const_int 256)))
5951          (const_int 6)
5952          (if_then_else
5953            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5954                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5955            (const_int 8)
5956            (const_int 10)))
5957        ;; Alternative 3
5958        (if_then_else
5959          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5960               (le (minus (match_dup 4) (pc)) (const_int 256)))
5961          (const_int 6)
5962          (if_then_else
5963            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5964                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5965            (const_int 8)
5966            (const_int 10)))])]
5967 )
5968
5969 (define_insn "*addsi3_cbranch"
5970   [(set (pc)
5971         (if_then_else
5972          (match_operator 4 "comparison_operator"
5973           [(plus:SI
5974             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
5975             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
5976            (const_int 0)])
5977          (label_ref (match_operand 5 "" ""))
5978          (pc)))
5979    (set
5980     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
5981     (plus:SI (match_dup 2) (match_dup 3)))
5982    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
5983   "TARGET_THUMB
5984    && (GET_CODE (operands[4]) == EQ
5985        || GET_CODE (operands[4]) == NE
5986        || GET_CODE (operands[4]) == GE
5987        || GET_CODE (operands[4]) == LT)"
5988   "*
5989    {
5990      rtx cond[3];
5991
5992      
5993      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
5994      cond[1] = operands[2];
5995      cond[2] = operands[3];
5996
5997      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
5998        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
5999      else
6000        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6001
6002      if (which_alternative >= 3
6003          && which_alternative < 4)
6004        output_asm_insn (\"mov\\t%0, %1\", operands);
6005      else if (which_alternative >= 4)
6006        output_asm_insn (\"str\\t%1, %0\", operands);
6007
6008      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6009        {
6010          case 4:
6011            return \"b%d4\\t%l5\";
6012          case 6:
6013            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6014          default:
6015            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6016        }
6017    }
6018   "
6019   [(set (attr "far_jump")
6020         (if_then_else
6021             (ior (and (lt (symbol_ref ("which_alternative"))
6022                           (const_int 3))
6023                       (eq_attr "length" "8"))
6024                  (eq_attr "length" "10"))
6025             (const_string "yes")
6026             (const_string "no")))
6027    (set (attr "length")
6028      (if_then_else
6029        (lt (symbol_ref ("which_alternative"))
6030                        (const_int 3))
6031        (if_then_else
6032          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6033               (le (minus (match_dup 5) (pc)) (const_int 256)))
6034          (const_int 4)
6035          (if_then_else
6036            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6037                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6038            (const_int 6)
6039            (const_int 8)))
6040        (if_then_else
6041          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6042               (le (minus (match_dup 5) (pc)) (const_int 256)))
6043          (const_int 6)
6044          (if_then_else
6045            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6046                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6047            (const_int 8)
6048            (const_int 10)))))]
6049 )
6050
6051 (define_insn "*addsi3_cbranch_scratch"
6052   [(set (pc)
6053         (if_then_else
6054          (match_operator 3 "comparison_operator"
6055           [(plus:SI
6056             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6057             (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6058            (const_int 0)])
6059          (label_ref (match_operand 4 "" ""))
6060          (pc)))
6061    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6062   "TARGET_THUMB
6063    && (GET_CODE (operands[3]) == EQ
6064        || GET_CODE (operands[3]) == NE
6065        || GET_CODE (operands[3]) == GE
6066        || GET_CODE (operands[3]) == LT)"
6067   "*
6068    {
6069      switch (which_alternative)
6070        {
6071        case 0:
6072          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6073          break;
6074        case 1:
6075          output_asm_insn (\"cmn\t%1, %2\", operands);
6076          break;
6077        case 3:
6078          output_asm_insn (\"add\t%0, %1, %2\", operands);
6079          break;
6080        case 4:
6081          output_asm_insn (\"add\t%0, %0, %2\", operands);
6082          break;
6083        }
6084
6085      switch (get_attr_length (insn))
6086        {
6087          case 4:
6088            return \"b%d3\\t%l4\";
6089          case 6:
6090            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6091          default:
6092            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6093        }
6094    }
6095   "
6096   [(set (attr "far_jump")
6097         (if_then_else
6098             (eq_attr "length" "8")
6099             (const_string "yes")
6100             (const_string "no")))
6101    (set (attr "length")
6102        (if_then_else
6103          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6104               (le (minus (match_dup 4) (pc)) (const_int 256)))
6105          (const_int 4)
6106          (if_then_else
6107            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6108                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6109            (const_int 6)
6110            (const_int 8))))]
6111 )
6112
6113 (define_insn "*subsi3_cbranch"
6114   [(set (pc)
6115         (if_then_else
6116          (match_operator 4 "comparison_operator"
6117           [(minus:SI
6118             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6119             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6120            (const_int 0)])
6121          (label_ref (match_operand 5 "" ""))
6122          (pc)))
6123    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6124         (minus:SI (match_dup 2) (match_dup 3)))
6125    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6126   "TARGET_THUMB
6127    && (GET_CODE (operands[4]) == EQ
6128        || GET_CODE (operands[4]) == NE
6129        || GET_CODE (operands[4]) == GE
6130        || GET_CODE (operands[4]) == LT)"
6131   "*
6132    {
6133      if (which_alternative == 0)
6134        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6135      else if (which_alternative == 1)
6136        {
6137          /* We must provide an alternative for a hi reg because reload 
6138             cannot handle output reloads on a jump instruction, but we
6139             can't subtract into that.  Fortunately a mov from lo to hi
6140             does not clobber the condition codes.  */
6141          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6142          output_asm_insn (\"mov\\t%0, %1\", operands);
6143        }
6144      else
6145        {
6146          /* Similarly, but the target is memory.  */
6147          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6148          output_asm_insn (\"str\\t%1, %0\", operands);
6149        }
6150
6151      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6152        {
6153          case 4:
6154            return \"b%d4\\t%l5\";
6155          case 6:
6156            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6157          default:
6158            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6159        }
6160    }
6161   "
6162   [(set (attr "far_jump")
6163         (if_then_else
6164             (ior (and (eq (symbol_ref ("which_alternative"))
6165                           (const_int 0))
6166                       (eq_attr "length" "8"))
6167                  (eq_attr "length" "10"))
6168             (const_string "yes")
6169             (const_string "no")))
6170    (set (attr "length")
6171      (if_then_else
6172        (eq (symbol_ref ("which_alternative"))
6173                        (const_int 0))
6174        (if_then_else
6175          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6176               (le (minus (match_dup 5) (pc)) (const_int 256)))
6177          (const_int 4)
6178          (if_then_else
6179            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6180                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6181            (const_int 6)
6182            (const_int 8)))
6183        (if_then_else
6184          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6185               (le (minus (match_dup 5) (pc)) (const_int 256)))
6186          (const_int 6)
6187          (if_then_else
6188            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6189                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6190            (const_int 8)
6191            (const_int 10)))))]
6192 )
6193
6194 (define_insn "*subsi3_cbranch_scratch"
6195   [(set (pc)
6196         (if_then_else
6197          (match_operator 0 "arm_comparison_operator"
6198           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6199                      (match_operand:SI 2 "nonmemory_operand" "l"))
6200            (const_int 0)])
6201          (label_ref (match_operand 3 "" ""))
6202          (pc)))]
6203   "TARGET_THUMB
6204    && (GET_CODE (operands[0]) == EQ
6205        || GET_CODE (operands[0]) == NE
6206        || GET_CODE (operands[0]) == GE
6207        || GET_CODE (operands[0]) == LT)"
6208   "*
6209   output_asm_insn (\"cmp\\t%1, %2\", operands);
6210   switch (get_attr_length (insn))
6211     {
6212     case 4:  return \"b%d0\\t%l3\";
6213     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6214     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6215     }
6216   "
6217   [(set (attr "far_jump")
6218         (if_then_else
6219             (eq_attr "length" "8")
6220             (const_string "yes")
6221             (const_string "no")))
6222    (set (attr "length") 
6223         (if_then_else
6224             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6225                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6226             (const_int 4)
6227             (if_then_else
6228                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6229                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6230                 (const_int 6)
6231                 (const_int 8))))]
6232 )
6233
6234 ;; Comparison and test insns
6235
6236 (define_expand "cmpsi"
6237   [(match_operand:SI 0 "s_register_operand" "")
6238    (match_operand:SI 1 "arm_add_operand" "")]
6239   "TARGET_ARM"
6240   "{
6241     arm_compare_op0 = operands[0];
6242     arm_compare_op1 = operands[1];
6243     DONE;
6244   }"
6245 )
6246
6247 (define_expand "cmpsf"
6248   [(match_operand:SF 0 "s_register_operand" "")
6249    (match_operand:SF 1 "fpa_rhs_operand" "")]
6250   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6251   "
6252   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
6253     operands[1] = force_reg (SFmode, operands[1]);
6254
6255   arm_compare_op0 = operands[0];
6256   arm_compare_op1 = operands[1];
6257   DONE;
6258   "
6259 )
6260
6261 (define_expand "cmpdf"
6262   [(match_operand:DF 0 "s_register_operand" "")
6263    (match_operand:DF 1 "fpa_rhs_operand" "")]
6264   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6265   "
6266   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
6267     operands[1] = force_reg (DFmode, operands[1]);
6268
6269   arm_compare_op0 = operands[0];
6270   arm_compare_op1 = operands[1];
6271   DONE;
6272   "
6273 )
6274
6275 (define_insn "*arm_cmpsi_insn"
6276   [(set (reg:CC CC_REGNUM)
6277         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6278                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6279   "TARGET_ARM"
6280   "@
6281    cmp%?\\t%0, %1
6282    cmn%?\\t%0, #%n1"
6283   [(set_attr "conds" "set")]
6284 )
6285
6286 (define_insn "*cmpsi_shiftsi"
6287   [(set (reg:CC CC_REGNUM)
6288         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6289                     (match_operator:SI  3 "shift_operator"
6290                      [(match_operand:SI 1 "s_register_operand" "r")
6291                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6292   "TARGET_ARM"
6293   "cmp%?\\t%0, %1%S3"
6294   [(set_attr "conds" "set")
6295    (set_attr "shift" "1")
6296    ]
6297 )
6298
6299 (define_insn "*cmpsi_shiftsi_swp"
6300   [(set (reg:CC_SWP CC_REGNUM)
6301         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6302                          [(match_operand:SI 1 "s_register_operand" "r")
6303                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6304                         (match_operand:SI 0 "s_register_operand" "r")))]
6305   "TARGET_ARM"
6306   "cmp%?\\t%0, %1%S3"
6307   [(set_attr "conds" "set")
6308    (set_attr "shift" "1")
6309    ]
6310 )
6311
6312 (define_insn "*cmpsi_neg_shiftsi"
6313   [(set (reg:CC CC_REGNUM)
6314         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6315                     (neg:SI (match_operator:SI 3 "shift_operator"
6316                              [(match_operand:SI 1 "s_register_operand" "r")
6317                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6318   "TARGET_ARM"
6319   "cmn%?\\t%0, %1%S3"
6320   [(set_attr "conds" "set")
6321    (set_attr "shift" "1")
6322    ]
6323 )
6324
6325 ;; Cirrus SF compare instruction
6326 (define_insn "*cirrus_cmpsf"
6327   [(set (reg:CCFP CC_REGNUM)
6328         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6329                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6330   "TARGET_ARM && TARGET_CIRRUS"
6331   "cfcmps%?\\tr15, %V0, %V1"
6332   [(set_attr "type"   "mav_farith")
6333    (set_attr "cirrus" "compare")]
6334 )
6335
6336 ;; Cirrus DF compare instruction
6337 (define_insn "*cirrus_cmpdf"
6338   [(set (reg:CCFP CC_REGNUM)
6339         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6340                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6341   "TARGET_ARM && TARGET_CIRRUS"
6342   "cfcmpd%?\\tr15, %V0, %V1"
6343   [(set_attr "type"   "mav_farith")
6344    (set_attr "cirrus" "compare")]
6345 )
6346
6347 ;; Cirrus DI compare instruction
6348 (define_expand "cmpdi"
6349   [(match_operand:DI 0 "cirrus_fp_register" "")
6350    (match_operand:DI 1 "cirrus_fp_register" "")]
6351   "TARGET_ARM && TARGET_CIRRUS"
6352   "{
6353      arm_compare_op0 = operands[0];
6354      arm_compare_op1 = operands[1];
6355      DONE;
6356    }")
6357
6358 (define_insn "*cirrus_cmpdi"
6359   [(set (reg:CC CC_REGNUM)
6360         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6361                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6362   "TARGET_ARM && TARGET_CIRRUS"
6363   "cfcmp64%?\\tr15, %V0, %V1"
6364   [(set_attr "type"   "mav_farith")
6365    (set_attr "cirrus" "compare")]
6366 )
6367
6368 ; This insn allows redundant compares to be removed by cse, nothing should
6369 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6370 ; is deleted later on. The match_dup will match the mode here, so that
6371 ; mode changes of the condition codes aren't lost by this even though we don't
6372 ; specify what they are.
6373
6374 (define_insn "*deleted_compare"
6375   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6376   "TARGET_ARM"
6377   "\\t%@ deleted compare"
6378   [(set_attr "conds" "set")
6379    (set_attr "length" "0")]
6380 )
6381
6382 \f
6383 ;; Conditional branch insns
6384
6385 (define_expand "beq"
6386   [(set (pc)
6387         (if_then_else (eq (match_dup 1) (const_int 0))
6388                       (label_ref (match_operand 0 "" ""))
6389                       (pc)))]
6390   "TARGET_ARM"
6391   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6392 )
6393
6394 (define_expand "bne"
6395   [(set (pc)
6396         (if_then_else (ne (match_dup 1) (const_int 0))
6397                       (label_ref (match_operand 0 "" ""))
6398                       (pc)))]
6399   "TARGET_ARM"
6400   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6401 )
6402
6403 (define_expand "bgt"
6404   [(set (pc)
6405         (if_then_else (gt (match_dup 1) (const_int 0))
6406                       (label_ref (match_operand 0 "" ""))
6407                       (pc)))]
6408   "TARGET_ARM"
6409   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6410 )
6411
6412 (define_expand "ble"
6413   [(set (pc)
6414         (if_then_else (le (match_dup 1) (const_int 0))
6415                       (label_ref (match_operand 0 "" ""))
6416                       (pc)))]
6417   "TARGET_ARM"
6418   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6419 )
6420
6421 (define_expand "bge"
6422   [(set (pc)
6423         (if_then_else (ge (match_dup 1) (const_int 0))
6424                       (label_ref (match_operand 0 "" ""))
6425                       (pc)))]
6426   "TARGET_ARM"
6427   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6428 )
6429
6430 (define_expand "blt"
6431   [(set (pc)
6432         (if_then_else (lt (match_dup 1) (const_int 0))
6433                       (label_ref (match_operand 0 "" ""))
6434                       (pc)))]
6435   "TARGET_ARM"
6436   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6437 )
6438
6439 (define_expand "bgtu"
6440   [(set (pc)
6441         (if_then_else (gtu (match_dup 1) (const_int 0))
6442                       (label_ref (match_operand 0 "" ""))
6443                       (pc)))]
6444   "TARGET_ARM"
6445   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6446 )
6447
6448 (define_expand "bleu"
6449   [(set (pc)
6450         (if_then_else (leu (match_dup 1) (const_int 0))
6451                       (label_ref (match_operand 0 "" ""))
6452                       (pc)))]
6453   "TARGET_ARM"
6454   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6455 )
6456
6457 (define_expand "bgeu"
6458   [(set (pc)
6459         (if_then_else (geu (match_dup 1) (const_int 0))
6460                       (label_ref (match_operand 0 "" ""))
6461                       (pc)))]
6462   "TARGET_ARM"
6463   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6464 )
6465
6466 (define_expand "bltu"
6467   [(set (pc)
6468         (if_then_else (ltu (match_dup 1) (const_int 0))
6469                       (label_ref (match_operand 0 "" ""))
6470                       (pc)))]
6471   "TARGET_ARM"
6472   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6473 )
6474
6475 (define_expand "bunordered"
6476   [(set (pc)
6477         (if_then_else (unordered (match_dup 1) (const_int 0))
6478                       (label_ref (match_operand 0 "" ""))
6479                       (pc)))]
6480   "TARGET_ARM && TARGET_HARD_FLOAT"
6481   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6482                                       arm_compare_op1);"
6483 )
6484
6485 (define_expand "bordered"
6486   [(set (pc)
6487         (if_then_else (ordered (match_dup 1) (const_int 0))
6488                       (label_ref (match_operand 0 "" ""))
6489                       (pc)))]
6490   "TARGET_ARM && TARGET_HARD_FLOAT"
6491   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6492                                       arm_compare_op1);"
6493 )
6494
6495 (define_expand "bungt"
6496   [(set (pc)
6497         (if_then_else (ungt (match_dup 1) (const_int 0))
6498                       (label_ref (match_operand 0 "" ""))
6499                       (pc)))]
6500   "TARGET_ARM && TARGET_HARD_FLOAT"
6501   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6502 )
6503
6504 (define_expand "bunlt"
6505   [(set (pc)
6506         (if_then_else (unlt (match_dup 1) (const_int 0))
6507                       (label_ref (match_operand 0 "" ""))
6508                       (pc)))]
6509   "TARGET_ARM && TARGET_HARD_FLOAT"
6510   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6511 )
6512
6513 (define_expand "bunge"
6514   [(set (pc)
6515         (if_then_else (unge (match_dup 1) (const_int 0))
6516                       (label_ref (match_operand 0 "" ""))
6517                       (pc)))]
6518   "TARGET_ARM && TARGET_HARD_FLOAT"
6519   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6520 )
6521
6522 (define_expand "bunle"
6523   [(set (pc)
6524         (if_then_else (unle (match_dup 1) (const_int 0))
6525                       (label_ref (match_operand 0 "" ""))
6526                       (pc)))]
6527   "TARGET_ARM && TARGET_HARD_FLOAT"
6528   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6529 )
6530
6531 ;; The following two patterns need two branch instructions, since there is
6532 ;; no single instruction that will handle all cases.
6533 (define_expand "buneq"
6534   [(set (pc)
6535         (if_then_else (uneq (match_dup 1) (const_int 0))
6536                       (label_ref (match_operand 0 "" ""))
6537                       (pc)))]
6538   "TARGET_ARM && TARGET_HARD_FLOAT"
6539   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6540 )
6541
6542 (define_expand "bltgt"
6543   [(set (pc)
6544         (if_then_else (ltgt (match_dup 1) (const_int 0))
6545                       (label_ref (match_operand 0 "" ""))
6546                       (pc)))]
6547   "TARGET_ARM && TARGET_HARD_FLOAT"
6548   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6549 )
6550
6551 ;;
6552 ;; Patterns to match conditional branch insns.
6553 ;;
6554
6555 ; Special pattern to match UNEQ.
6556 (define_insn "*arm_buneq"
6557   [(set (pc)
6558         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6559                       (label_ref (match_operand 0 "" ""))
6560                       (pc)))]
6561   "TARGET_ARM && TARGET_HARD_FLOAT"
6562   "*
6563   if (arm_ccfsm_state != 0)
6564     abort ();
6565
6566   return \"bvs\\t%l0\;beq\\t%l0\";
6567   "
6568   [(set_attr "conds" "jump_clob")
6569    (set_attr "length" "8")]
6570 )
6571
6572 ; Special pattern to match LTGT.
6573 (define_insn "*arm_bltgt"
6574   [(set (pc)
6575         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6576                       (label_ref (match_operand 0 "" ""))
6577                       (pc)))]
6578   "TARGET_ARM && TARGET_HARD_FLOAT"
6579   "*
6580   if (arm_ccfsm_state != 0)
6581     abort ();
6582
6583   return \"bmi\\t%l0\;bgt\\t%l0\";
6584   "
6585   [(set_attr "conds" "jump_clob")
6586    (set_attr "length" "8")]
6587 )
6588
6589 (define_insn "*arm_cond_branch"
6590   [(set (pc)
6591         (if_then_else (match_operator 1 "arm_comparison_operator"
6592                        [(match_operand 2 "cc_register" "") (const_int 0)])
6593                       (label_ref (match_operand 0 "" ""))
6594                       (pc)))]
6595   "TARGET_ARM"
6596   "*
6597   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6598     {
6599       arm_ccfsm_state += 2;
6600       return \"\";
6601     }
6602   return \"b%d1\\t%l0\";
6603   "
6604   [(set_attr "conds" "use")]
6605 )
6606
6607 ; Special pattern to match reversed UNEQ.
6608 (define_insn "*arm_buneq_reversed"
6609   [(set (pc)
6610         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6611                       (pc)
6612                       (label_ref (match_operand 0 "" ""))))]
6613   "TARGET_ARM && TARGET_HARD_FLOAT"
6614   "*
6615   if (arm_ccfsm_state != 0)
6616     abort ();
6617
6618   return \"bmi\\t%l0\;bgt\\t%l0\";
6619   "
6620   [(set_attr "conds" "jump_clob")
6621    (set_attr "length" "8")]
6622 )
6623
6624 ; Special pattern to match reversed LTGT.
6625 (define_insn "*arm_bltgt_reversed"
6626   [(set (pc)
6627         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6628                       (pc)
6629                       (label_ref (match_operand 0 "" ""))))]
6630   "TARGET_ARM && TARGET_HARD_FLOAT"
6631   "*
6632   if (arm_ccfsm_state != 0)
6633     abort ();
6634
6635   return \"bvs\\t%l0\;beq\\t%l0\";
6636   "
6637   [(set_attr "conds" "jump_clob")
6638    (set_attr "length" "8")]
6639 )
6640
6641 (define_insn "*arm_cond_branch_reversed"
6642   [(set (pc)
6643         (if_then_else (match_operator 1 "arm_comparison_operator"
6644                        [(match_operand 2 "cc_register" "") (const_int 0)])
6645                       (pc)
6646                       (label_ref (match_operand 0 "" ""))))]
6647   "TARGET_ARM"
6648   "*
6649   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6650     {
6651       arm_ccfsm_state += 2;
6652       return \"\";
6653     }
6654   return \"b%D1\\t%l0\";
6655   "
6656   [(set_attr "conds" "use")]
6657 )
6658
6659 \f
6660
6661 ; scc insns
6662
6663 (define_expand "seq"
6664   [(set (match_operand:SI 0 "s_register_operand" "")
6665         (eq:SI (match_dup 1) (const_int 0)))]
6666   "TARGET_ARM"
6667   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6668 )
6669
6670 (define_expand "sne"
6671   [(set (match_operand:SI 0 "s_register_operand" "")
6672         (ne:SI (match_dup 1) (const_int 0)))]
6673   "TARGET_ARM"
6674   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6675 )
6676
6677 (define_expand "sgt"
6678   [(set (match_operand:SI 0 "s_register_operand" "")
6679         (gt:SI (match_dup 1) (const_int 0)))]
6680   "TARGET_ARM"
6681   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6682 )
6683
6684 (define_expand "sle"
6685   [(set (match_operand:SI 0 "s_register_operand" "")
6686         (le:SI (match_dup 1) (const_int 0)))]
6687   "TARGET_ARM"
6688   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6689 )
6690
6691 (define_expand "sge"
6692   [(set (match_operand:SI 0 "s_register_operand" "")
6693         (ge:SI (match_dup 1) (const_int 0)))]
6694   "TARGET_ARM"
6695   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6696 )
6697
6698 (define_expand "slt"
6699   [(set (match_operand:SI 0 "s_register_operand" "")
6700         (lt:SI (match_dup 1) (const_int 0)))]
6701   "TARGET_ARM"
6702   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6703 )
6704
6705 (define_expand "sgtu"
6706   [(set (match_operand:SI 0 "s_register_operand" "")
6707         (gtu:SI (match_dup 1) (const_int 0)))]
6708   "TARGET_ARM"
6709   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6710 )
6711
6712 (define_expand "sleu"
6713   [(set (match_operand:SI 0 "s_register_operand" "")
6714         (leu:SI (match_dup 1) (const_int 0)))]
6715   "TARGET_ARM"
6716   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6717 )
6718
6719 (define_expand "sgeu"
6720   [(set (match_operand:SI 0 "s_register_operand" "")
6721         (geu:SI (match_dup 1) (const_int 0)))]
6722   "TARGET_ARM"
6723   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6724 )
6725
6726 (define_expand "sltu"
6727   [(set (match_operand:SI 0 "s_register_operand" "")
6728         (ltu:SI (match_dup 1) (const_int 0)))]
6729   "TARGET_ARM"
6730   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6731 )
6732
6733 (define_expand "sunordered"
6734   [(set (match_operand:SI 0 "s_register_operand" "")
6735         (unordered:SI (match_dup 1) (const_int 0)))]
6736   "TARGET_ARM && TARGET_HARD_FLOAT"
6737   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6738                                       arm_compare_op1);"
6739 )
6740
6741 (define_expand "sordered"
6742   [(set (match_operand:SI 0 "s_register_operand" "")
6743         (ordered:SI (match_dup 1) (const_int 0)))]
6744   "TARGET_ARM && TARGET_HARD_FLOAT"
6745   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6746                                       arm_compare_op1);"
6747 )
6748
6749 (define_expand "sungt"
6750   [(set (match_operand:SI 0 "s_register_operand" "")
6751         (ungt:SI (match_dup 1) (const_int 0)))]
6752   "TARGET_ARM && TARGET_HARD_FLOAT"
6753   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6754                                       arm_compare_op1);"
6755 )
6756
6757 (define_expand "sunge"
6758   [(set (match_operand:SI 0 "s_register_operand" "")
6759         (unge:SI (match_dup 1) (const_int 0)))]
6760   "TARGET_ARM && TARGET_HARD_FLOAT"
6761   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6762                                       arm_compare_op1);"
6763 )
6764
6765 (define_expand "sunlt"
6766   [(set (match_operand:SI 0 "s_register_operand" "")
6767         (unlt:SI (match_dup 1) (const_int 0)))]
6768   "TARGET_ARM && TARGET_HARD_FLOAT"
6769   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6770                                       arm_compare_op1);"
6771 )
6772
6773 (define_expand "sunle"
6774   [(set (match_operand:SI 0 "s_register_operand" "")
6775         (unle:SI (match_dup 1) (const_int 0)))]
6776   "TARGET_ARM && TARGET_HARD_FLOAT"
6777   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6778                                       arm_compare_op1);"
6779 )
6780
6781 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6782 ;;; simple ARM instructions. 
6783 ;
6784 ; (define_expand "suneq"
6785 ;   [(set (match_operand:SI 0 "s_register_operand" "")
6786 ;       (uneq:SI (match_dup 1) (const_int 0)))]
6787 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6788 ;   "abort ();"
6789 ; )
6790 ;
6791 ; (define_expand "sltgt"
6792 ;   [(set (match_operand:SI 0 "s_register_operand" "")
6793 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
6794 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6795 ;   "abort ();"
6796 ; )
6797
6798 (define_insn "*mov_scc"
6799   [(set (match_operand:SI 0 "s_register_operand" "=r")
6800         (match_operator:SI 1 "arm_comparison_operator"
6801          [(match_operand 2 "cc_register" "") (const_int 0)]))]
6802   "TARGET_ARM"
6803   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6804   [(set_attr "conds" "use")
6805    (set_attr "length" "8")]
6806 )
6807
6808 (define_insn "*mov_negscc"
6809   [(set (match_operand:SI 0 "s_register_operand" "=r")
6810         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6811                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6812   "TARGET_ARM"
6813   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6814   [(set_attr "conds" "use")
6815    (set_attr "length" "8")]
6816 )
6817
6818 (define_insn "*mov_notscc"
6819   [(set (match_operand:SI 0 "s_register_operand" "=r")
6820         (not:SI (match_operator:SI 1 "arm_comparison_operator"
6821                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6822   "TARGET_ARM"
6823   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6824   [(set_attr "conds" "use")
6825    (set_attr "length" "8")]
6826 )
6827
6828 \f
6829 ;; Conditional move insns
6830
6831 (define_expand "movsicc"
6832   [(set (match_operand:SI 0 "s_register_operand" "")
6833         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6834                          (match_operand:SI 2 "arm_not_operand" "")
6835                          (match_operand:SI 3 "arm_not_operand" "")))]
6836   "TARGET_ARM"
6837   "
6838   {
6839     enum rtx_code code = GET_CODE (operands[1]);
6840     rtx ccreg;
6841
6842     if (code == UNEQ || code == LTGT)
6843       FAIL;
6844
6845     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6846     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6847   }"
6848 )
6849
6850 (define_expand "movsfcc"
6851   [(set (match_operand:SF 0 "s_register_operand" "")
6852         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6853                          (match_operand:SF 2 "s_register_operand" "")
6854                          (match_operand:SF 3 "nonmemory_operand" "")))]
6855   "TARGET_ARM"
6856   "
6857   {
6858     enum rtx_code code = GET_CODE (operands[1]);
6859     rtx ccreg;
6860
6861     if (code == UNEQ || code == LTGT)
6862       FAIL;
6863
6864     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
6865        Otherwise, ensure it is a valid FP add operand */
6866     if ((!TARGET_HARD_FLOAT)
6867         || (!fpa_add_operand (operands[3], SFmode)))
6868       operands[3] = force_reg (SFmode, operands[3]);
6869
6870     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6871     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6872   }"
6873 )
6874
6875 (define_expand "movdfcc"
6876   [(set (match_operand:DF 0 "s_register_operand" "")
6877         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6878                          (match_operand:DF 2 "s_register_operand" "")
6879                          (match_operand:DF 3 "fpa_add_operand" "")))]
6880   "TARGET_ARM && TARGET_HARD_FLOAT"
6881   "
6882   {
6883     enum rtx_code code = GET_CODE (operands[1]);
6884     rtx ccreg;
6885
6886     if (code == UNEQ || code == LTGT)
6887       FAIL;
6888
6889     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6890     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6891   }"
6892 )
6893
6894 (define_insn "*movsicc_insn"
6895   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6896         (if_then_else:SI
6897          (match_operator 3 "arm_comparison_operator"
6898           [(match_operand 4 "cc_register" "") (const_int 0)])
6899          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6900          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6901   "TARGET_ARM"
6902   "@
6903    mov%D3\\t%0, %2
6904    mvn%D3\\t%0, #%B2
6905    mov%d3\\t%0, %1
6906    mvn%d3\\t%0, #%B1
6907    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6908    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6909    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6910    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6911   [(set_attr "length" "4,4,4,4,8,8,8,8")
6912    (set_attr "conds" "use")]
6913 )
6914
6915 (define_insn "*movsfcc_soft_insn"
6916   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6917         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6918                           [(match_operand 4 "cc_register" "") (const_int 0)])
6919                          (match_operand:SF 1 "s_register_operand" "0,r")
6920                          (match_operand:SF 2 "s_register_operand" "r,0")))]
6921   "TARGET_ARM && TARGET_SOFT_FLOAT"
6922   "@
6923    mov%D3\\t%0, %2
6924    mov%d3\\t%0, %1"
6925   [(set_attr "conds" "use")]
6926 )
6927
6928 \f
6929 ;; Jump and linkage insns
6930
6931 (define_expand "jump"
6932   [(set (pc)
6933         (label_ref (match_operand 0 "" "")))]
6934   "TARGET_EITHER"
6935   ""
6936 )
6937
6938 (define_insn "*arm_jump"
6939   [(set (pc)
6940         (label_ref (match_operand 0 "" "")))]
6941   "TARGET_ARM"
6942   "*
6943   {
6944     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6945       {
6946         arm_ccfsm_state += 2;
6947         return \"\";
6948       }
6949     return \"b%?\\t%l0\";
6950   }
6951   "
6952   [(set_attr "predicable" "yes")]
6953 )
6954
6955 (define_insn "*thumb_jump"
6956   [(set (pc)
6957         (label_ref (match_operand 0 "" "")))]
6958   "TARGET_THUMB"
6959   "*
6960   if (get_attr_length (insn) == 2)
6961     return \"b\\t%l0\";
6962   return \"bl\\t%l0\\t%@ far jump\";
6963   "
6964   [(set (attr "far_jump")
6965         (if_then_else
6966             (eq_attr "length" "4")
6967             (const_string "yes")
6968             (const_string "no")))
6969    (set (attr "length") 
6970         (if_then_else
6971             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6972                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
6973             (const_int 2)
6974             (const_int 4)))]
6975 )
6976
6977 (define_expand "call"
6978   [(parallel [(call (match_operand 0 "memory_operand" "")
6979                     (match_operand 1 "general_operand" ""))
6980               (use (match_operand 2 "" ""))
6981               (clobber (reg:SI LR_REGNUM))])]
6982   "TARGET_EITHER"
6983   "
6984   {
6985     rtx callee;
6986     
6987     /* In an untyped call, we can get NULL for operand 2.  */
6988     if (operands[2] == NULL_RTX)
6989       operands[2] = const0_rtx;
6990       
6991     /* This is to decide if we should generate indirect calls by loading the
6992        32 bit address of the callee into a register before performing the
6993        branch and link.  operand[2] encodes the long_call/short_call
6994        attribute of the function being called.  This attribute is set whenever
6995        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6996        is used, and the short_call attribute can also be set if function is
6997        declared as static or if it has already been defined in the current
6998        compilation unit.  See arm.c and arm.h for info about this.  The third
6999        parameter to arm_is_longcall_p is used to tell it which pattern
7000        invoked it.  */
7001     callee  = XEXP (operands[0], 0);
7002     
7003     if (GET_CODE (callee) != REG
7004        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7005       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7006   }"
7007 )
7008
7009 (define_insn "*call_reg"
7010   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7011          (match_operand 1 "" ""))
7012    (use (match_operand 2 "" ""))
7013    (clobber (reg:SI LR_REGNUM))]
7014   "TARGET_ARM"
7015   "*
7016   return output_call (operands);
7017   "
7018   ;; length is worst case, normally it is only two
7019   [(set_attr "length" "12")
7020    (set_attr "type" "call")]
7021 )
7022
7023 (define_insn "*call_mem"
7024   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7025          (match_operand 1 "" ""))
7026    (use (match_operand 2 "" ""))
7027    (clobber (reg:SI LR_REGNUM))]
7028   "TARGET_ARM"
7029   "*
7030   return output_call_mem (operands);
7031   "
7032   [(set_attr "length" "12")
7033    (set_attr "type" "call")]
7034 )
7035
7036 (define_insn "*call_indirect"
7037   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7038          (match_operand 1 "" ""))
7039    (use (match_operand 2 "" ""))
7040    (clobber (reg:SI LR_REGNUM))]
7041   "TARGET_THUMB"
7042   "*
7043   {
7044     if (TARGET_CALLER_INTERWORKING)
7045       return \"bl\\t%__interwork_call_via_%0\";
7046     else
7047       return \"bl\\t%__call_via_%0\";
7048   }"
7049   [(set_attr "type" "call")]
7050 )
7051
7052 (define_insn "*call_value_indirect"
7053   [(set (match_operand 0 "" "")
7054         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7055               (match_operand 2 "" "")))
7056    (use (match_operand 3 "" ""))
7057    (clobber (reg:SI LR_REGNUM))]
7058   "TARGET_THUMB"
7059   "*
7060   {
7061     if (TARGET_CALLER_INTERWORKING)
7062       return \"bl\\t%__interwork_call_via_%1\";
7063     else
7064       return \"bl\\t%__call_via_%1\";
7065   }"
7066   [(set_attr "type" "call")]
7067 )
7068
7069 (define_expand "call_value"
7070   [(parallel [(set (match_operand       0 "" "")
7071                    (call (match_operand 1 "memory_operand" "")
7072                          (match_operand 2 "general_operand" "")))
7073               (use (match_operand 3 "" ""))
7074               (clobber (reg:SI LR_REGNUM))])]
7075   "TARGET_EITHER"
7076   "
7077   {
7078     rtx callee = XEXP (operands[1], 0);
7079     
7080     /* In an untyped call, we can get NULL for operand 2.  */
7081     if (operands[3] == 0)
7082       operands[3] = const0_rtx;
7083       
7084     /* See the comment in define_expand \"call\".  */
7085     if (GET_CODE (callee) != REG
7086         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7087       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7088   }"
7089 )
7090
7091 (define_insn "*call_value_reg"
7092   [(set (match_operand 0 "" "")
7093         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7094               (match_operand 2 "" "")))
7095    (use (match_operand 3 "" ""))
7096    (clobber (reg:SI LR_REGNUM))]
7097   "TARGET_ARM"
7098   "*
7099   return output_call (&operands[1]);
7100   "
7101   [(set_attr "length" "12")
7102    (set_attr "type" "call")]
7103 )
7104
7105 (define_insn "*call_value_mem"
7106   [(set (match_operand 0 "" "")
7107         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7108               (match_operand 2 "" "")))
7109    (use (match_operand 3 "" ""))
7110    (clobber (reg:SI LR_REGNUM))]
7111   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7112   "*
7113   return output_call_mem (&operands[1]);
7114   "
7115   [(set_attr "length" "12")
7116    (set_attr "type" "call")]
7117 )
7118
7119 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7120 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7121
7122 (define_insn "*call_symbol"
7123   [(call (mem:SI (match_operand:SI 0 "" ""))
7124          (match_operand 1 "" ""))
7125    (use (match_operand 2 "" ""))
7126    (clobber (reg:SI LR_REGNUM))]
7127   "TARGET_ARM
7128    && (GET_CODE (operands[0]) == SYMBOL_REF)
7129    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7130   "*
7131   {
7132     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7133   }"
7134   [(set_attr "type" "call")]
7135 )
7136
7137 (define_insn "*call_value_symbol"
7138   [(set (match_operand 0 "s_register_operand" "")
7139         (call (mem:SI (match_operand:SI 1 "" ""))
7140         (match_operand:SI 2 "" "")))
7141    (use (match_operand 3 "" ""))
7142    (clobber (reg:SI LR_REGNUM))]
7143   "TARGET_ARM
7144    && (GET_CODE (operands[1]) == SYMBOL_REF)
7145    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7146   "*
7147   {
7148     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7149   }"
7150   [(set_attr "type" "call")]
7151 )
7152
7153 (define_insn "*call_insn"
7154   [(call (mem:SI (match_operand:SI 0 "" ""))
7155          (match_operand:SI 1 "" ""))
7156    (use (match_operand 2 "" ""))
7157    (clobber (reg:SI LR_REGNUM))]
7158   "TARGET_THUMB
7159    && GET_CODE (operands[0]) == SYMBOL_REF
7160    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7161   "bl\\t%a0"
7162   [(set_attr "length" "4")
7163    (set_attr "type" "call")]
7164 )
7165
7166 (define_insn "*call_value_insn"
7167   [(set (match_operand 0 "register_operand" "")
7168         (call (mem:SI (match_operand 1 "" ""))
7169               (match_operand 2 "" "")))
7170    (use (match_operand 3 "" ""))
7171    (clobber (reg:SI LR_REGNUM))]
7172   "TARGET_THUMB
7173    && GET_CODE (operands[1]) == SYMBOL_REF
7174    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7175   "bl\\t%a1"
7176   [(set_attr "length" "4")
7177    (set_attr "type" "call")]
7178 )
7179
7180 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7181 (define_expand "sibcall"
7182   [(parallel [(call (match_operand 0 "memory_operand" "")
7183                     (match_operand 1 "general_operand" ""))
7184               (return)
7185               (use (match_operand 2 "" ""))])]
7186   "TARGET_ARM"
7187   "
7188   {
7189     if (operands[2] == NULL_RTX)
7190       operands[2] = const0_rtx;
7191   }"
7192 )
7193
7194 (define_expand "sibcall_value"
7195   [(parallel [(set (match_operand 0 "register_operand" "")
7196                    (call (match_operand 1 "memory_operand" "")
7197                          (match_operand 2 "general_operand" "")))
7198               (return)
7199               (use (match_operand 3 "" ""))])]
7200   "TARGET_ARM"
7201   "
7202   {
7203     if (operands[3] == NULL_RTX)
7204       operands[3] = const0_rtx;
7205   }"
7206 )
7207
7208 (define_insn "*sibcall_insn"
7209  [(call (mem:SI (match_operand:SI 0 "" "X"))
7210         (match_operand 1 "" ""))
7211   (return)
7212   (use (match_operand 2 "" ""))]
7213   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7214   "*
7215   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7216   "
7217   [(set_attr "type" "call")]
7218 )
7219
7220 (define_insn "*sibcall_value_insn"
7221  [(set (match_operand 0 "s_register_operand" "")
7222        (call (mem:SI (match_operand:SI 1 "" "X"))
7223              (match_operand 2 "" "")))
7224   (return)
7225   (use (match_operand 3 "" ""))]
7226   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7227   "*
7228   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7229   "
7230   [(set_attr "type" "call")]
7231 )
7232
7233 ;; Often the return insn will be the same as loading from memory, so set attr
7234 (define_insn "return"
7235   [(return)]
7236   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7237   "*
7238   {
7239     if (arm_ccfsm_state == 2)
7240       {
7241         arm_ccfsm_state += 2;
7242         return \"\";
7243       }
7244     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7245   }"
7246   [(set_attr "type" "load")
7247    (set_attr "length" "12")
7248    (set_attr "predicable" "yes")]
7249 )
7250
7251 (define_insn "*cond_return"
7252   [(set (pc)
7253         (if_then_else (match_operator 0 "arm_comparison_operator"
7254                        [(match_operand 1 "cc_register" "") (const_int 0)])
7255                       (return)
7256                       (pc)))]
7257   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7258   "*
7259   {
7260     if (arm_ccfsm_state == 2)
7261       {
7262         arm_ccfsm_state += 2;
7263         return \"\";
7264       }
7265     return output_return_instruction (operands[0], TRUE, FALSE);
7266   }"
7267   [(set_attr "conds" "use")
7268    (set_attr "length" "12")
7269    (set_attr "type" "load")]
7270 )
7271
7272 (define_insn "*cond_return_inverted"
7273   [(set (pc)
7274         (if_then_else (match_operator 0 "arm_comparison_operator"
7275                        [(match_operand 1 "cc_register" "") (const_int 0)])
7276                       (pc)
7277                       (return)))]
7278   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7279   "*
7280   {
7281     if (arm_ccfsm_state == 2)
7282       {
7283         arm_ccfsm_state += 2;
7284         return \"\";
7285       }
7286     return output_return_instruction (operands[0], TRUE, TRUE);
7287   }"
7288   [(set_attr "conds" "use")
7289    (set_attr "type" "load")]
7290 )
7291
7292 ;; Generate a sequence of instructions to determine if the processor is
7293 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7294 ;; mask.
7295
7296 (define_expand "return_addr_mask"
7297   [(set (match_dup 1)
7298       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7299                        (const_int 0)))
7300    (set (match_operand:SI 0 "s_register_operand" "")
7301       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7302                        (const_int -1)
7303                        (const_int 67108860)))] ; 0x03fffffc
7304   "TARGET_ARM"
7305   "
7306   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7307   ")
7308
7309 (define_insn "*check_arch2"
7310   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7311       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7312                        (const_int 0)))]
7313   "TARGET_ARM"
7314   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7315   [(set_attr "length" "8")
7316    (set_attr "conds" "set")]
7317 )
7318
7319 ;; Call subroutine returning any type.
7320
7321 (define_expand "untyped_call"
7322   [(parallel [(call (match_operand 0 "" "")
7323                     (const_int 0))
7324               (match_operand 1 "" "")
7325               (match_operand 2 "" "")])]
7326   "TARGET_ARM"
7327   "
7328   {
7329     int i;
7330
7331     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7332
7333     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7334       {
7335         rtx set = XVECEXP (operands[2], 0, i);
7336
7337         emit_move_insn (SET_DEST (set), SET_SRC (set));
7338       }
7339
7340     /* The optimizer does not know that the call sets the function value
7341        registers we stored in the result block.  We avoid problems by
7342        claiming that all hard registers are used and clobbered at this
7343        point.  */
7344     emit_insn (gen_blockage ());
7345
7346     DONE;
7347   }"
7348 )
7349
7350 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7351 ;; all of memory.  This blocks insns from being moved across this point.
7352
7353 (define_insn "blockage"
7354   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7355   "TARGET_EITHER"
7356   ""
7357   [(set_attr "length" "0")
7358    (set_attr "type" "block")]
7359 )
7360
7361 (define_expand "casesi"
7362   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7363    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7364    (match_operand:SI 2 "const_int_operand" "")  ; total range
7365    (match_operand:SI 3 "" "")                   ; table label
7366    (match_operand:SI 4 "" "")]                  ; Out of range label
7367   "TARGET_ARM"
7368   "
7369   {
7370     rtx reg;
7371     if (operands[1] != const0_rtx)
7372       {
7373         reg = gen_reg_rtx (SImode);
7374
7375         emit_insn (gen_addsi3 (reg, operands[0],
7376                                GEN_INT (-INTVAL (operands[1]))));
7377         operands[0] = reg;
7378       }
7379
7380     if (!const_ok_for_arm (INTVAL (operands[2])))
7381       operands[2] = force_reg (SImode, operands[2]);
7382
7383     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7384                                          operands[4]));
7385     DONE;
7386   }"
7387 )
7388
7389 ;; The USE in this pattern is needed to tell flow analysis that this is
7390 ;; a CASESI insn.  It has no other purpose.
7391 (define_insn "casesi_internal"
7392   [(parallel [(set (pc)
7393                (if_then_else
7394                 (leu (match_operand:SI 0 "s_register_operand" "r")
7395                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7396                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7397                                  (label_ref (match_operand 2 "" ""))))
7398                 (label_ref (match_operand 3 "" ""))))
7399               (clobber (reg:CC CC_REGNUM))
7400               (use (label_ref (match_dup 2)))])]
7401   "TARGET_ARM"
7402   "*
7403     if (flag_pic)
7404       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7405     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7406   "
7407   [(set_attr "conds" "clob")
7408    (set_attr "length" "12")]
7409 )
7410
7411 (define_expand "indirect_jump"
7412   [(set (pc)
7413         (match_operand:SI 0 "s_register_operand" ""))]
7414   "TARGET_EITHER"
7415   ""
7416 )
7417
7418 (define_insn "*arm_indirect_jump"
7419   [(set (pc)
7420         (match_operand:SI 0 "s_register_operand" "r"))]
7421   "TARGET_ARM"
7422   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7423   [(set_attr "predicable" "yes")]
7424 )
7425
7426 ;; Although not supported by the define_expand above,
7427 ;; cse/combine may generate this form.
7428 (define_insn "*load_indirect_jump"
7429   [(set (pc)
7430         (match_operand:SI 0 "memory_operand" "m"))]
7431   "TARGET_ARM"
7432   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7433   [(set_attr "type" "load")
7434    (set_attr "pool_range" "4096")
7435    (set_attr "neg_pool_range" "4084")
7436    (set_attr "predicable" "yes")]
7437 )
7438
7439 (define_insn "*thumb_indirect_jump"
7440   [(set (pc)
7441         (match_operand:SI 0 "register_operand" "l*r"))]
7442   "TARGET_THUMB"
7443   "mov\\tpc, %0"
7444   [(set_attr "conds" "clob")
7445    (set_attr "length" "2")]
7446 )
7447
7448 \f
7449 ;; Misc insns
7450
7451 (define_insn "nop"
7452   [(const_int 0)]
7453   "TARGET_EITHER"
7454   "*
7455   if (TARGET_ARM)
7456     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7457   return  \"mov\\tr8, r8\";
7458   "
7459   [(set (attr "length")
7460         (if_then_else (eq_attr "is_thumb" "yes")
7461                       (const_int 2)
7462                       (const_int 4)))]
7463 )
7464
7465 \f
7466 ;; Patterns to allow combination of arithmetic, cond code and shifts
7467
7468 (define_insn "*arith_shiftsi"
7469   [(set (match_operand:SI 0 "s_register_operand" "=r")
7470         (match_operator:SI 1 "shiftable_operator"
7471           [(match_operator:SI 3 "shift_operator"
7472              [(match_operand:SI 4 "s_register_operand" "r")
7473               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7474            (match_operand:SI 2 "s_register_operand" "r")]))]
7475   "TARGET_ARM"
7476   "%i1%?\\t%0, %2, %4%S3"
7477   [(set_attr "predicable" "yes")
7478    (set_attr "shift" "4")
7479    ]
7480 )
7481
7482 (define_insn "*arith_shiftsi_compare0"
7483   [(set (reg:CC_NOOV CC_REGNUM)
7484         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7485                           [(match_operator:SI 3 "shift_operator"
7486                             [(match_operand:SI 4 "s_register_operand" "r")
7487                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7488                            (match_operand:SI 2 "s_register_operand" "r")])
7489                          (const_int 0)))
7490    (set (match_operand:SI 0 "s_register_operand" "=r")
7491         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7492                          (match_dup 2)]))]
7493   "TARGET_ARM"
7494   "%i1%?s\\t%0, %2, %4%S3"
7495   [(set_attr "conds" "set")
7496    (set_attr "shift" "4")
7497    ]
7498 )
7499
7500 (define_insn "*arith_shiftsi_compare0_scratch"
7501   [(set (reg:CC_NOOV CC_REGNUM)
7502         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7503                           [(match_operator:SI 3 "shift_operator"
7504                             [(match_operand:SI 4 "s_register_operand" "r")
7505                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7506                            (match_operand:SI 2 "s_register_operand" "r")])
7507                          (const_int 0)))
7508    (clobber (match_scratch:SI 0 "=r"))]
7509   "TARGET_ARM"
7510   "%i1%?s\\t%0, %2, %4%S3"
7511   [(set_attr "conds" "set")
7512    (set_attr "shift" "4")
7513    ]
7514 )
7515
7516 (define_insn "*sub_shiftsi"
7517   [(set (match_operand:SI 0 "s_register_operand" "=r")
7518         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7519                   (match_operator:SI 2 "shift_operator"
7520                    [(match_operand:SI 3 "s_register_operand" "r")
7521                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7522   "TARGET_ARM"
7523   "sub%?\\t%0, %1, %3%S2"
7524   [(set_attr "predicable" "yes")
7525    (set_attr "shift" "3")
7526    ]
7527 )
7528
7529 (define_insn "*sub_shiftsi_compare0"
7530   [(set (reg:CC_NOOV CC_REGNUM)
7531         (compare:CC_NOOV
7532          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7533                    (match_operator:SI 2 "shift_operator"
7534                     [(match_operand:SI 3 "s_register_operand" "r")
7535                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7536          (const_int 0)))
7537    (set (match_operand:SI 0 "s_register_operand" "=r")
7538         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7539                                                  (match_dup 4)])))]
7540   "TARGET_ARM"
7541   "sub%?s\\t%0, %1, %3%S2"
7542   [(set_attr "conds" "set")
7543    (set_attr "shift" "3") 
7544    ]
7545 )
7546
7547 (define_insn "*sub_shiftsi_compare0_scratch"
7548   [(set (reg:CC_NOOV CC_REGNUM)
7549         (compare:CC_NOOV
7550          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7551                    (match_operator:SI 2 "shift_operator"
7552                     [(match_operand:SI 3 "s_register_operand" "r")
7553                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7554          (const_int 0)))
7555    (clobber (match_scratch:SI 0 "=r"))]
7556   "TARGET_ARM"
7557   "sub%?s\\t%0, %1, %3%S2"
7558   [(set_attr "conds" "set")
7559    (set_attr "shift" "3") 
7560    ]
7561 )
7562
7563 \f
7564
7565 (define_insn "*and_scc"
7566   [(set (match_operand:SI 0 "s_register_operand" "=r")
7567         (and:SI (match_operator:SI 1 "arm_comparison_operator"
7568                  [(match_operand 3 "cc_register" "") (const_int 0)])
7569                 (match_operand:SI 2 "s_register_operand" "r")))]
7570   "TARGET_ARM"
7571   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7572   [(set_attr "conds" "use")
7573    (set_attr "length" "8")]
7574 )
7575
7576 (define_insn "*ior_scc"
7577   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7578         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7579                  [(match_operand 3 "cc_register" "") (const_int 0)])
7580                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7581   "TARGET_ARM"
7582   "@
7583    orr%d2\\t%0, %1, #1
7584    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7585   [(set_attr "conds" "use")
7586    (set_attr "length" "4,8")]
7587 )
7588
7589 (define_insn "*compare_scc"
7590   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7591         (match_operator:SI 1 "arm_comparison_operator"
7592          [(match_operand:SI 2 "s_register_operand" "r,r")
7593           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7594    (clobber (reg:CC CC_REGNUM))]
7595   "TARGET_ARM"
7596   "*
7597     if (operands[3] == const0_rtx)
7598       {
7599         if (GET_CODE (operands[1]) == LT)
7600           return \"mov\\t%0, %2, lsr #31\";
7601
7602         if (GET_CODE (operands[1]) == GE)
7603           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7604
7605         if (GET_CODE (operands[1]) == EQ)
7606           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
7607       }
7608
7609     if (GET_CODE (operands[1]) == NE)
7610       {
7611         if (which_alternative == 1)
7612           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7613         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7614       }
7615     if (which_alternative == 1)
7616       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7617     else
7618       output_asm_insn (\"cmp\\t%2, %3\", operands);
7619     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7620   "
7621   [(set_attr "conds" "clob")
7622    (set_attr "length" "12")]
7623 )
7624
7625 (define_insn "*cond_move"
7626   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7627         (if_then_else:SI (match_operator 3 "equality_operator"
7628                           [(match_operator 4 "arm_comparison_operator"
7629                             [(match_operand 5 "cc_register" "") (const_int 0)])
7630                            (const_int 0)])
7631                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7632                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7633   "TARGET_ARM"
7634   "*
7635     if (GET_CODE (operands[3]) == NE)
7636       {
7637         if (which_alternative != 1)
7638           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7639         if (which_alternative != 0)
7640           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7641         return \"\";
7642       }
7643     if (which_alternative != 0)
7644       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7645     if (which_alternative != 1)
7646       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7647     return \"\";
7648   "
7649   [(set_attr "conds" "use")
7650    (set_attr "length" "4,4,8")]
7651 )
7652
7653 (define_insn "*cond_arith"
7654   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7655         (match_operator:SI 5 "shiftable_operator" 
7656          [(match_operator:SI 4 "arm_comparison_operator"
7657            [(match_operand:SI 2 "s_register_operand" "r,r")
7658             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7659           (match_operand:SI 1 "s_register_operand" "0,?r")]))
7660    (clobber (reg:CC CC_REGNUM))]
7661   "TARGET_ARM"
7662   "*
7663     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7664       return \"%i5\\t%0, %1, %2, lsr #31\";
7665
7666     output_asm_insn (\"cmp\\t%2, %3\", operands);
7667     if (GET_CODE (operands[5]) == AND)
7668       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7669     else if (GET_CODE (operands[5]) == MINUS)
7670       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7671     else if (which_alternative != 0)
7672       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7673     return \"%i5%d4\\t%0, %1, #1\";
7674   "
7675   [(set_attr "conds" "clob")
7676    (set_attr "length" "12")]
7677 )
7678
7679 (define_insn "*cond_sub"
7680   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7681         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7682                   (match_operator:SI 4 "arm_comparison_operator"
7683                    [(match_operand:SI 2 "s_register_operand" "r,r")
7684                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7685    (clobber (reg:CC CC_REGNUM))]
7686   "TARGET_ARM"
7687   "*
7688     output_asm_insn (\"cmp\\t%2, %3\", operands);
7689     if (which_alternative != 0)
7690       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7691     return \"sub%d4\\t%0, %1, #1\";
7692   "
7693   [(set_attr "conds" "clob")
7694    (set_attr "length" "8,12")]
7695 )
7696
7697 (define_insn "*cmp_ite0"
7698   [(set (match_operand 6 "dominant_cc_register" "")
7699         (compare
7700          (if_then_else:SI
7701           (match_operator 4 "arm_comparison_operator"
7702            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7703             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7704           (match_operator:SI 5 "arm_comparison_operator"
7705            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7706             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7707           (const_int 0))
7708          (const_int 0)))]
7709   "TARGET_ARM"
7710   "*
7711   {
7712     static const char * const opcodes[4][2] =
7713     {
7714       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7715        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7716       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7717        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7718       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7719        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7720       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7721        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7722     };
7723     int swap =
7724       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7725
7726     return opcodes[which_alternative][swap];
7727   }"
7728   [(set_attr "conds" "set")
7729    (set_attr "length" "8")]
7730 )
7731
7732 (define_insn "*cmp_ite1"
7733   [(set (match_operand 6 "dominant_cc_register" "")
7734         (compare
7735          (if_then_else:SI
7736           (match_operator 4 "arm_comparison_operator"
7737            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7738             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7739           (match_operator:SI 5 "arm_comparison_operator"
7740            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7741             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7742           (const_int 1))
7743          (const_int 0)))]
7744   "TARGET_ARM"
7745   "*
7746   {
7747     static const char * const opcodes[4][2] =
7748     {
7749       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7750        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7751       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7752        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7753       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7754        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7755       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7756        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7757     };
7758     int swap =
7759       comparison_dominates_p (GET_CODE (operands[5]),
7760                               reverse_condition (GET_CODE (operands[4])));
7761
7762     return opcodes[which_alternative][swap];
7763   }"
7764   [(set_attr "conds" "set")
7765    (set_attr "length" "8")]
7766 )
7767
7768 (define_insn "*cmp_and"
7769   [(set (match_operand 6 "dominant_cc_register" "")
7770         (compare
7771          (and:SI
7772           (match_operator 4 "arm_comparison_operator"
7773            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7774             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7775           (match_operator:SI 5 "arm_comparison_operator"
7776            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7777             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7778          (const_int 0)))]
7779   "TARGET_ARM"
7780   "*
7781   {
7782     static const char *const opcodes[4][2] =
7783     {
7784       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7785        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7786       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7787        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7788       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7789        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7790       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7791        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7792     };
7793     int swap =
7794       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7795
7796     return opcodes[which_alternative][swap];
7797   }"
7798   [(set_attr "conds" "set")
7799    (set_attr "predicable" "no")
7800    (set_attr "length" "8")]
7801 )
7802
7803 (define_insn "*cmp_ior"
7804   [(set (match_operand 6 "dominant_cc_register" "")
7805         (compare
7806          (ior:SI
7807           (match_operator 4 "arm_comparison_operator"
7808            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7809             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7810           (match_operator:SI 5 "arm_comparison_operator"
7811            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7812             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7813          (const_int 0)))]
7814   "TARGET_ARM"
7815   "*
7816 {
7817   static const char *const opcodes[4][2] =
7818   {
7819     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7820      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7821     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7822      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7823     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7824      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7825     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7826      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7827   };
7828   int swap =
7829     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7830
7831   return opcodes[which_alternative][swap];
7832 }
7833 "
7834   [(set_attr "conds" "set")
7835    (set_attr "length" "8")]
7836 )
7837
7838 (define_insn_and_split "*ior_scc_scc"
7839   [(set (match_operand:SI 0 "s_register_operand" "=r")
7840         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
7841                  [(match_operand:SI 1 "s_register_operand" "r")
7842                   (match_operand:SI 2 "arm_add_operand" "rIL")])
7843                 (match_operator:SI 6 "arm_comparison_operator"
7844                  [(match_operand:SI 4 "s_register_operand" "r")
7845                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
7846    (clobber (reg:CC CC_REGNUM))]
7847   "TARGET_ARM
7848    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
7849        != CCmode)"
7850   "#"
7851   "TARGET_ARM && reload_completed"
7852   [(set (match_dup 7)
7853         (compare
7854          (ior:SI
7855           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7856           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7857          (const_int 0)))
7858    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
7859   "operands[7]
7860      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
7861                                                   DOM_CC_X_OR_Y),
7862                     CC_REGNUM);"
7863   [(set_attr "conds" "clob")
7864    (set_attr "length" "16")])
7865
7866 ; If the above pattern is followed by a CMP insn, then the compare is 
7867 ; redundant, since we can rework the conditional instruction that follows.
7868 (define_insn_and_split "*ior_scc_scc_cmp"
7869   [(set (match_operand 0 "dominant_cc_register" "")
7870         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
7871                           [(match_operand:SI 1 "s_register_operand" "r")
7872                            (match_operand:SI 2 "arm_add_operand" "rIL")])
7873                          (match_operator:SI 6 "arm_comparison_operator"
7874                           [(match_operand:SI 4 "s_register_operand" "r")
7875                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
7876                  (const_int 0)))
7877    (set (match_operand:SI 7 "s_register_operand" "=r")
7878         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7879                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
7880   "TARGET_ARM"
7881   "#"
7882   "TARGET_ARM && reload_completed"
7883   [(set (match_dup 0)
7884         (compare
7885          (ior:SI
7886           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7887           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7888          (const_int 0)))
7889    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
7890   ""
7891   [(set_attr "conds" "set")
7892    (set_attr "length" "16")])
7893
7894 (define_insn_and_split "*and_scc_scc"
7895   [(set (match_operand:SI 0 "s_register_operand" "=r")
7896         (and:SI (match_operator:SI 3 "arm_comparison_operator"
7897                  [(match_operand:SI 1 "s_register_operand" "r")
7898                   (match_operand:SI 2 "arm_add_operand" "rIL")])
7899                 (match_operator:SI 6 "arm_comparison_operator"
7900                  [(match_operand:SI 4 "s_register_operand" "r")
7901                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
7902    (clobber (reg:CC CC_REGNUM))]
7903   "TARGET_ARM
7904    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7905        != CCmode)"
7906   "#"
7907   "TARGET_ARM && reload_completed
7908    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7909        != CCmode)"
7910   [(set (match_dup 7)
7911         (compare
7912          (and:SI
7913           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7914           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7915          (const_int 0)))
7916    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
7917   "operands[7]
7918      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
7919                                                   DOM_CC_X_AND_Y),
7920                     CC_REGNUM);"
7921   [(set_attr "conds" "clob")
7922    (set_attr "length" "16")])
7923
7924 ; If the above pattern is followed by a CMP insn, then the compare is 
7925 ; redundant, since we can rework the conditional instruction that follows.
7926 (define_insn_and_split "*and_scc_scc_cmp"
7927   [(set (match_operand 0 "dominant_cc_register" "")
7928         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
7929                           [(match_operand:SI 1 "s_register_operand" "r")
7930                            (match_operand:SI 2 "arm_add_operand" "rIL")])
7931                          (match_operator:SI 6 "arm_comparison_operator"
7932                           [(match_operand:SI 4 "s_register_operand" "r")
7933                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
7934                  (const_int 0)))
7935    (set (match_operand:SI 7 "s_register_operand" "=r")
7936         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7937                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
7938   "TARGET_ARM"
7939   "#"
7940   "TARGET_ARM && reload_completed"
7941   [(set (match_dup 0)
7942         (compare
7943          (and:SI
7944           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7945           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7946          (const_int 0)))
7947    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
7948   ""
7949   [(set_attr "conds" "set")
7950    (set_attr "length" "16")])
7951
7952 ;; If there is no dominance in the comparison, then we can still save an
7953 ;; instruction in the AND case, since we can know that the second compare
7954 ;; need only zero the value if false (if true, then the value is already
7955 ;; correct).
7956 (define_insn_and_split "*and_scc_scc_nodom"
7957   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
7958         (and:SI (match_operator:SI 3 "arm_comparison_operator"
7959                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
7960                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
7961                 (match_operator:SI 6 "arm_comparison_operator"
7962                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
7963                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
7964    (clobber (reg:CC CC_REGNUM))]
7965   "TARGET_ARM
7966    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7967        == CCmode)"
7968   "#"
7969   "TARGET_ARM && reload_completed"
7970   [(parallel [(set (match_dup 0)
7971                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
7972               (clobber (reg:CC CC_REGNUM))])
7973    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
7974    (set (match_dup 0)
7975         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
7976                          (match_dup 0)
7977                          (const_int 0)))]
7978   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
7979                                               operands[4], operands[5]),
7980                               CC_REGNUM);
7981    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
7982                                   operands[5]);"
7983   [(set_attr "conds" "clob")
7984    (set_attr "length" "20")])
7985
7986 (define_insn "*negscc"
7987   [(set (match_operand:SI 0 "s_register_operand" "=r")
7988         (neg:SI (match_operator 3 "arm_comparison_operator"
7989                  [(match_operand:SI 1 "s_register_operand" "r")
7990                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7991    (clobber (reg:CC CC_REGNUM))]
7992   "TARGET_ARM"
7993   "*
7994   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7995     return \"mov\\t%0, %1, asr #31\";
7996
7997   if (GET_CODE (operands[3]) == NE)
7998     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7999
8000   if (GET_CODE (operands[3]) == GT)
8001     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8002
8003   output_asm_insn (\"cmp\\t%1, %2\", operands);
8004   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8005   return \"mvn%d3\\t%0, #0\";
8006   "
8007   [(set_attr "conds" "clob")
8008    (set_attr "length" "12")]
8009 )
8010
8011 (define_insn "movcond"
8012   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8013         (if_then_else:SI
8014          (match_operator 5 "arm_comparison_operator"
8015           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8016            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8017          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8018          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8019    (clobber (reg:CC CC_REGNUM))]
8020   "TARGET_ARM"
8021   "*
8022   if (GET_CODE (operands[5]) == LT
8023       && (operands[4] == const0_rtx))
8024     {
8025       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8026         {
8027           if (operands[2] == const0_rtx)
8028             return \"and\\t%0, %1, %3, asr #31\";
8029           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8030         }
8031       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8032         {
8033           if (operands[1] == const0_rtx)
8034             return \"bic\\t%0, %2, %3, asr #31\";
8035           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8036         }
8037       /* The only case that falls through to here is when both ops 1 & 2
8038          are constants */
8039     }
8040
8041   if (GET_CODE (operands[5]) == GE
8042       && (operands[4] == const0_rtx))
8043     {
8044       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8045         {
8046           if (operands[2] == const0_rtx)
8047             return \"bic\\t%0, %1, %3, asr #31\";
8048           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8049         }
8050       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8051         {
8052           if (operands[1] == const0_rtx)
8053             return \"and\\t%0, %2, %3, asr #31\";
8054           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8055         }
8056       /* The only case that falls through to here is when both ops 1 & 2
8057          are constants */
8058     }
8059   if (GET_CODE (operands[4]) == CONST_INT
8060       && !const_ok_for_arm (INTVAL (operands[4])))
8061     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8062   else
8063     output_asm_insn (\"cmp\\t%3, %4\", operands);
8064   if (which_alternative != 0)
8065     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8066   if (which_alternative != 1)
8067     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8068   return \"\";
8069   "
8070   [(set_attr "conds" "clob")
8071    (set_attr "length" "8,8,12")]
8072 )
8073
8074 (define_insn "*ifcompare_plus_move"
8075   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8076         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8077                           [(match_operand:SI 4 "s_register_operand" "r,r")
8078                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8079                          (plus:SI
8080                           (match_operand:SI 2 "s_register_operand" "r,r")
8081                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8082                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8083    (clobber (reg:CC CC_REGNUM))]
8084   "TARGET_ARM"
8085   "#"
8086   [(set_attr "conds" "clob")
8087    (set_attr "length" "8,12")]
8088 )
8089
8090 (define_insn "*if_plus_move"
8091   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8092         (if_then_else:SI
8093          (match_operator 4 "arm_comparison_operator"
8094           [(match_operand 5 "cc_register" "") (const_int 0)])
8095          (plus:SI
8096           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8097           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8098          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8099   "TARGET_ARM"
8100   "@
8101    add%d4\\t%0, %2, %3
8102    sub%d4\\t%0, %2, #%n3
8103    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8104    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8105   [(set_attr "conds" "use")
8106    (set_attr "length" "4,4,8,8")
8107    (set_attr "type" "*,*,*,*")]
8108 )
8109
8110 (define_insn "*ifcompare_move_plus"
8111   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8112         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8113                           [(match_operand:SI 4 "s_register_operand" "r,r")
8114                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8115                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8116                          (plus:SI
8117                           (match_operand:SI 2 "s_register_operand" "r,r")
8118                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8119    (clobber (reg:CC CC_REGNUM))]
8120   "TARGET_ARM"
8121   "#"
8122   [(set_attr "conds" "clob")
8123    (set_attr "length" "8,12")]
8124 )
8125
8126 (define_insn "*if_move_plus"
8127   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8128         (if_then_else:SI
8129          (match_operator 4 "arm_comparison_operator"
8130           [(match_operand 5 "cc_register" "") (const_int 0)])
8131          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8132          (plus:SI
8133           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8134           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8135   "TARGET_ARM"
8136   "@
8137    add%D4\\t%0, %2, %3
8138    sub%D4\\t%0, %2, #%n3
8139    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8140    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8141   [(set_attr "conds" "use")
8142    (set_attr "length" "4,4,8,8")
8143    (set_attr "type" "*,*,*,*")]
8144 )
8145
8146 (define_insn "*ifcompare_arith_arith"
8147   [(set (match_operand:SI 0 "s_register_operand" "=r")
8148         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8149                           [(match_operand:SI 5 "s_register_operand" "r")
8150                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8151                          (match_operator:SI 8 "shiftable_operator"
8152                           [(match_operand:SI 1 "s_register_operand" "r")
8153                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8154                          (match_operator:SI 7 "shiftable_operator"
8155                           [(match_operand:SI 3 "s_register_operand" "r")
8156                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8157    (clobber (reg:CC CC_REGNUM))]
8158   "TARGET_ARM"
8159   "#"
8160   [(set_attr "conds" "clob")
8161    (set_attr "length" "12")]
8162 )
8163
8164 (define_insn "*if_arith_arith"
8165   [(set (match_operand:SI 0 "s_register_operand" "=r")
8166         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8167                           [(match_operand 8 "cc_register" "") (const_int 0)])
8168                          (match_operator:SI 6 "shiftable_operator"
8169                           [(match_operand:SI 1 "s_register_operand" "r")
8170                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8171                          (match_operator:SI 7 "shiftable_operator"
8172                           [(match_operand:SI 3 "s_register_operand" "r")
8173                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8174   "TARGET_ARM"
8175   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8176   [(set_attr "conds" "use")
8177    (set_attr "length" "8")]
8178 )
8179
8180 (define_insn "*ifcompare_arith_move"
8181   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8182         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8183                           [(match_operand:SI 2 "s_register_operand" "r,r")
8184                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8185                          (match_operator:SI 7 "shiftable_operator"
8186                           [(match_operand:SI 4 "s_register_operand" "r,r")
8187                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8188                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8189    (clobber (reg:CC CC_REGNUM))]
8190   "TARGET_ARM"
8191   "*
8192   /* If we have an operation where (op x 0) is the identity operation and
8193      the conditional operator is LT or GE and we are comparing against zero and
8194      everything is in registers then we can do this in two instructions */
8195   if (operands[3] == const0_rtx
8196       && GET_CODE (operands[7]) != AND
8197       && GET_CODE (operands[5]) == REG
8198       && GET_CODE (operands[1]) == REG 
8199       && REGNO (operands[1]) == REGNO (operands[4])
8200       && REGNO (operands[4]) != REGNO (operands[0]))
8201     {
8202       if (GET_CODE (operands[6]) == LT)
8203         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8204       else if (GET_CODE (operands[6]) == GE)
8205         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8206     }
8207   if (GET_CODE (operands[3]) == CONST_INT
8208       && !const_ok_for_arm (INTVAL (operands[3])))
8209     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8210   else
8211     output_asm_insn (\"cmp\\t%2, %3\", operands);
8212   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8213   if (which_alternative != 0)
8214     return \"mov%D6\\t%0, %1\";
8215   return \"\";
8216   "
8217   [(set_attr "conds" "clob")
8218    (set_attr "length" "8,12")]
8219 )
8220
8221 (define_insn "*if_arith_move"
8222   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8223         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8224                           [(match_operand 6 "cc_register" "") (const_int 0)])
8225                          (match_operator:SI 5 "shiftable_operator"
8226                           [(match_operand:SI 2 "s_register_operand" "r,r")
8227                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8228                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8229   "TARGET_ARM"
8230   "@
8231    %I5%d4\\t%0, %2, %3
8232    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8233   [(set_attr "conds" "use")
8234    (set_attr "length" "4,8")
8235    (set_attr "type" "*,*")]
8236 )
8237
8238 (define_insn "*ifcompare_move_arith"
8239   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8240         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8241                           [(match_operand:SI 4 "s_register_operand" "r,r")
8242                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8243                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8244                          (match_operator:SI 7 "shiftable_operator"
8245                           [(match_operand:SI 2 "s_register_operand" "r,r")
8246                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8247    (clobber (reg:CC CC_REGNUM))]
8248   "TARGET_ARM"
8249   "*
8250   /* If we have an operation where (op x 0) is the identity operation and
8251      the conditional operator is LT or GE and we are comparing against zero and
8252      everything is in registers then we can do this in two instructions */
8253   if (operands[5] == const0_rtx
8254       && GET_CODE (operands[7]) != AND
8255       && GET_CODE (operands[3]) == REG
8256       && GET_CODE (operands[1]) == REG 
8257       && REGNO (operands[1]) == REGNO (operands[2])
8258       && REGNO (operands[2]) != REGNO (operands[0]))
8259     {
8260       if (GET_CODE (operands[6]) == GE)
8261         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8262       else if (GET_CODE (operands[6]) == LT)
8263         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8264     }
8265
8266   if (GET_CODE (operands[5]) == CONST_INT
8267       && !const_ok_for_arm (INTVAL (operands[5])))
8268     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8269   else
8270     output_asm_insn (\"cmp\\t%4, %5\", operands);
8271
8272   if (which_alternative != 0)
8273     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8274   return \"%I7%D6\\t%0, %2, %3\";
8275   "
8276   [(set_attr "conds" "clob")
8277    (set_attr "length" "8,12")]
8278 )
8279
8280 (define_insn "*if_move_arith"
8281   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8282         (if_then_else:SI
8283          (match_operator 4 "arm_comparison_operator"
8284           [(match_operand 6 "cc_register" "") (const_int 0)])
8285          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8286          (match_operator:SI 5 "shiftable_operator"
8287           [(match_operand:SI 2 "s_register_operand" "r,r")
8288            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8289   "TARGET_ARM"
8290   "@
8291    %I5%D4\\t%0, %2, %3
8292    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8293   [(set_attr "conds" "use")
8294    (set_attr "length" "4,8")
8295    (set_attr "type" "*,*")]
8296 )
8297
8298 (define_insn "*ifcompare_move_not"
8299   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8300         (if_then_else:SI
8301          (match_operator 5 "arm_comparison_operator"
8302           [(match_operand:SI 3 "s_register_operand" "r,r")
8303            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8304          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8305          (not:SI
8306           (match_operand:SI 2 "s_register_operand" "r,r"))))
8307    (clobber (reg:CC CC_REGNUM))]
8308   "TARGET_ARM"
8309   "#"
8310   [(set_attr "conds" "clob")
8311    (set_attr "length" "8,12")]
8312 )
8313
8314 (define_insn "*if_move_not"
8315   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8316         (if_then_else:SI
8317          (match_operator 4 "arm_comparison_operator"
8318           [(match_operand 3 "cc_register" "") (const_int 0)])
8319          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8320          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8321   "TARGET_ARM"
8322   "@
8323    mvn%D4\\t%0, %2
8324    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8325    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8326   [(set_attr "conds" "use")
8327    (set_attr "length" "4,8,8")]
8328 )
8329
8330 (define_insn "*ifcompare_not_move"
8331   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8332         (if_then_else:SI 
8333          (match_operator 5 "arm_comparison_operator"
8334           [(match_operand:SI 3 "s_register_operand" "r,r")
8335            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8336          (not:SI
8337           (match_operand:SI 2 "s_register_operand" "r,r"))
8338          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8339    (clobber (reg:CC CC_REGNUM))]
8340   "TARGET_ARM"
8341   "#"
8342   [(set_attr "conds" "clob")
8343    (set_attr "length" "8,12")]
8344 )
8345
8346 (define_insn "*if_not_move"
8347   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8348         (if_then_else:SI
8349          (match_operator 4 "arm_comparison_operator"
8350           [(match_operand 3 "cc_register" "") (const_int 0)])
8351          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8352          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8353   "TARGET_ARM"
8354   "@
8355    mvn%d4\\t%0, %2
8356    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8357    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8358   [(set_attr "conds" "use")
8359    (set_attr "length" "4,8,8")]
8360 )
8361
8362 (define_insn "*ifcompare_shift_move"
8363   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8364         (if_then_else:SI
8365          (match_operator 6 "arm_comparison_operator"
8366           [(match_operand:SI 4 "s_register_operand" "r,r")
8367            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8368          (match_operator:SI 7 "shift_operator"
8369           [(match_operand:SI 2 "s_register_operand" "r,r")
8370            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8371          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8372    (clobber (reg:CC CC_REGNUM))]
8373   "TARGET_ARM"
8374   "#"
8375   [(set_attr "conds" "clob")
8376    (set_attr "length" "8,12")]
8377 )
8378
8379 (define_insn "*if_shift_move"
8380   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8381         (if_then_else:SI
8382          (match_operator 5 "arm_comparison_operator"
8383           [(match_operand 6 "cc_register" "") (const_int 0)])
8384          (match_operator:SI 4 "shift_operator"
8385           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8386            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8387          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8388   "TARGET_ARM"
8389   "@
8390    mov%d5\\t%0, %2%S4
8391    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8392    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8393   [(set_attr "conds" "use")
8394    (set_attr "shift" "2")
8395    (set_attr "length" "4,8,8")]
8396 )
8397
8398 (define_insn "*ifcompare_move_shift"
8399   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8400         (if_then_else:SI
8401          (match_operator 6 "arm_comparison_operator"
8402           [(match_operand:SI 4 "s_register_operand" "r,r")
8403            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8404          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8405          (match_operator:SI 7 "shift_operator"
8406           [(match_operand:SI 2 "s_register_operand" "r,r")
8407            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8408    (clobber (reg:CC CC_REGNUM))]
8409   "TARGET_ARM"
8410   "#"
8411   [(set_attr "conds" "clob")
8412    (set_attr "length" "8,12")]
8413 )
8414
8415 (define_insn "*if_move_shift"
8416   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8417         (if_then_else:SI
8418          (match_operator 5 "arm_comparison_operator"
8419           [(match_operand 6 "cc_register" "") (const_int 0)])
8420          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8421          (match_operator:SI 4 "shift_operator"
8422           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8423            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8424   "TARGET_ARM"
8425   "@
8426    mov%D5\\t%0, %2%S4
8427    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8428    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8429   [(set_attr "conds" "use")
8430    (set_attr "shift" "2")
8431    (set_attr "length" "4,8,8")]
8432 )
8433
8434 (define_insn "*ifcompare_shift_shift"
8435   [(set (match_operand:SI 0 "s_register_operand" "=r")
8436         (if_then_else:SI
8437          (match_operator 7 "arm_comparison_operator"
8438           [(match_operand:SI 5 "s_register_operand" "r")
8439            (match_operand:SI 6 "arm_add_operand" "rIL")])
8440          (match_operator:SI 8 "shift_operator"
8441           [(match_operand:SI 1 "s_register_operand" "r")
8442            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8443          (match_operator:SI 9 "shift_operator"
8444           [(match_operand:SI 3 "s_register_operand" "r")
8445            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8446    (clobber (reg:CC CC_REGNUM))]
8447   "TARGET_ARM"
8448   "#"
8449   [(set_attr "conds" "clob")
8450    (set_attr "length" "12")]
8451 )
8452
8453 (define_insn "*if_shift_shift"
8454   [(set (match_operand:SI 0 "s_register_operand" "=r")
8455         (if_then_else:SI
8456          (match_operator 5 "arm_comparison_operator"
8457           [(match_operand 8 "cc_register" "") (const_int 0)])
8458          (match_operator:SI 6 "shift_operator"
8459           [(match_operand:SI 1 "s_register_operand" "r")
8460            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8461          (match_operator:SI 7 "shift_operator"
8462           [(match_operand:SI 3 "s_register_operand" "r")
8463            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8464   "TARGET_ARM"
8465   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8466   [(set_attr "conds" "use")
8467    (set_attr "shift" "1")
8468    (set_attr "length" "8")]
8469 )
8470
8471 (define_insn "*ifcompare_not_arith"
8472   [(set (match_operand:SI 0 "s_register_operand" "=r")
8473         (if_then_else:SI
8474          (match_operator 6 "arm_comparison_operator"
8475           [(match_operand:SI 4 "s_register_operand" "r")
8476            (match_operand:SI 5 "arm_add_operand" "rIL")])
8477          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8478          (match_operator:SI 7 "shiftable_operator"
8479           [(match_operand:SI 2 "s_register_operand" "r")
8480            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8481    (clobber (reg:CC CC_REGNUM))]
8482   "TARGET_ARM"
8483   "#"
8484   [(set_attr "conds" "clob")
8485    (set_attr "length" "12")]
8486 )
8487
8488 (define_insn "*if_not_arith"
8489   [(set (match_operand:SI 0 "s_register_operand" "=r")
8490         (if_then_else:SI
8491          (match_operator 5 "arm_comparison_operator"
8492           [(match_operand 4 "cc_register" "") (const_int 0)])
8493          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8494          (match_operator:SI 6 "shiftable_operator"
8495           [(match_operand:SI 2 "s_register_operand" "r")
8496            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8497   "TARGET_ARM"
8498   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8499   [(set_attr "conds" "use")
8500    (set_attr "length" "8")]
8501 )
8502
8503 (define_insn "*ifcompare_arith_not"
8504   [(set (match_operand:SI 0 "s_register_operand" "=r")
8505         (if_then_else:SI
8506          (match_operator 6 "arm_comparison_operator"
8507           [(match_operand:SI 4 "s_register_operand" "r")
8508            (match_operand:SI 5 "arm_add_operand" "rIL")])
8509          (match_operator:SI 7 "shiftable_operator"
8510           [(match_operand:SI 2 "s_register_operand" "r")
8511            (match_operand:SI 3 "arm_rhs_operand" "rI")])
8512          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8513    (clobber (reg:CC CC_REGNUM))]
8514   "TARGET_ARM"
8515   "#"
8516   [(set_attr "conds" "clob")
8517    (set_attr "length" "12")]
8518 )
8519
8520 (define_insn "*if_arith_not"
8521   [(set (match_operand:SI 0 "s_register_operand" "=r")
8522         (if_then_else:SI
8523          (match_operator 5 "arm_comparison_operator"
8524           [(match_operand 4 "cc_register" "") (const_int 0)])
8525          (match_operator:SI 6 "shiftable_operator"
8526           [(match_operand:SI 2 "s_register_operand" "r")
8527            (match_operand:SI 3 "arm_rhs_operand" "rI")])
8528          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
8529   "TARGET_ARM"
8530   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8531   [(set_attr "conds" "use")
8532    (set_attr "length" "8")]
8533 )
8534
8535 (define_insn "*ifcompare_neg_move"
8536   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8537         (if_then_else:SI
8538          (match_operator 5 "arm_comparison_operator"
8539           [(match_operand:SI 3 "s_register_operand" "r,r")
8540            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8541          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
8542          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8543    (clobber (reg:CC CC_REGNUM))]
8544   "TARGET_ARM"
8545   "#"
8546   [(set_attr "conds" "clob")
8547    (set_attr "length" "8,12")]
8548 )
8549
8550 (define_insn "*if_neg_move"
8551   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8552         (if_then_else:SI
8553          (match_operator 4 "arm_comparison_operator"
8554           [(match_operand 3 "cc_register" "") (const_int 0)])
8555          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8556          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8557   "TARGET_ARM"
8558   "@
8559    rsb%d4\\t%0, %2, #0
8560    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8561    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8562   [(set_attr "conds" "use")
8563    (set_attr "length" "4,8,8")]
8564 )
8565
8566 (define_insn "*ifcompare_move_neg"
8567   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8568         (if_then_else:SI
8569          (match_operator 5 "arm_comparison_operator"
8570           [(match_operand:SI 3 "s_register_operand" "r,r")
8571            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8572          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8573          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8574    (clobber (reg:CC CC_REGNUM))]
8575   "TARGET_ARM"
8576   "#"
8577   [(set_attr "conds" "clob")
8578    (set_attr "length" "8,12")]
8579 )
8580
8581 (define_insn "*if_move_neg"
8582   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8583         (if_then_else:SI
8584          (match_operator 4 "arm_comparison_operator"
8585           [(match_operand 3 "cc_register" "") (const_int 0)])
8586          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8587          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8588   "TARGET_ARM"
8589   "@
8590    rsb%D4\\t%0, %2, #0
8591    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8592    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8593   [(set_attr "conds" "use")
8594    (set_attr "length" "4,8,8")]
8595 )
8596
8597 (define_insn "*arith_adjacentmem"
8598   [(set (match_operand:SI 0 "s_register_operand" "=r")
8599         (match_operator:SI 1 "shiftable_operator"
8600          [(match_operand:SI 2 "memory_operand" "m")
8601           (match_operand:SI 3 "memory_operand" "m")]))
8602    (clobber (match_scratch:SI 4 "=r"))]
8603   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8604   "*
8605   {
8606     rtx ldm[3];
8607     rtx arith[4];
8608     int val1 = 0, val2 = 0;
8609
8610     if (REGNO (operands[0]) > REGNO (operands[4]))
8611       {
8612         ldm[1] = operands[4];
8613         ldm[2] = operands[0];
8614       }
8615     else
8616       {
8617         ldm[1] = operands[0];
8618         ldm[2] = operands[4];
8619       }
8620     if (GET_CODE (XEXP (operands[2], 0)) != REG)
8621       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8622     if (GET_CODE (XEXP (operands[3], 0)) != REG)
8623       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8624     arith[0] = operands[0];
8625     arith[3] = operands[1];
8626     if (val1 < val2)
8627       {
8628         arith[1] = ldm[1];
8629         arith[2] = ldm[2];
8630       }
8631     else
8632       {
8633         arith[1] = ldm[2];
8634         arith[2] = ldm[1];
8635       }
8636    if (val1 && val2)
8637       {
8638         rtx ops[3];
8639         ldm[0] = ops[0] = operands[4];
8640         ops[1] = XEXP (XEXP (operands[2], 0), 0);
8641         ops[2] = XEXP (XEXP (operands[2], 0), 1);
8642         output_add_immediate (ops);
8643         if (val1 < val2)
8644           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8645         else
8646           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8647       }
8648     else if (val1)
8649       {
8650         ldm[0] = XEXP (operands[3], 0);
8651         if (val1 < val2)
8652           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8653         else
8654           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8655       }
8656     else
8657       {
8658         ldm[0] = XEXP (operands[2], 0);
8659         if (val1 < val2)
8660           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8661         else
8662           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8663       }
8664     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8665     return \"\";
8666   }"
8667   [(set_attr "length" "12")
8668    (set_attr "predicable" "yes")
8669    (set_attr "type" "load")]
8670 )
8671
8672 ;; the arm can support extended pre-inc instructions
8673
8674 ;; In all these cases, we use operands 0 and 1 for the register being
8675 ;; incremented because those are the operands that local-alloc will
8676 ;; tie and these are the pair most likely to be tieable (and the ones
8677 ;; that will benefit the most).
8678
8679 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8680 ;; elimination will cause too many headaches.
8681
8682 (define_insn "*strqi_preinc"
8683   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8684                          (match_operand:SI 2 "index_operand" "rJ")))
8685         (match_operand:QI 3 "s_register_operand" "r"))
8686    (set (match_operand:SI 0 "s_register_operand" "=r")
8687         (plus:SI (match_dup 1) (match_dup 2)))]
8688   "TARGET_ARM
8689    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8690    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8691    && (GET_CODE (operands[2]) != REG
8692        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8693   "str%?b\\t%3, [%0, %2]!"
8694   [(set_attr "type" "store1")
8695    (set_attr "predicable" "yes")]
8696 )
8697
8698 (define_insn "*strqi_predec"
8699   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8700                           (match_operand:SI 2 "s_register_operand" "r")))
8701         (match_operand:QI 3 "s_register_operand" "r"))
8702    (set (match_operand:SI 0 "s_register_operand" "=r")
8703         (minus:SI (match_dup 1) (match_dup 2)))]
8704   "TARGET_ARM
8705    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8706    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8707    && (GET_CODE (operands[2]) != REG
8708        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8709   "str%?b\\t%3, [%0, -%2]!"
8710   [(set_attr "type" "store1")
8711    (set_attr "predicable" "yes")]
8712 )
8713
8714 (define_insn "*loadqi_preinc"
8715   [(set (match_operand:QI 3 "s_register_operand" "=r")
8716         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8717                          (match_operand:SI 2 "index_operand" "rJ"))))
8718    (set (match_operand:SI 0 "s_register_operand" "=r")
8719         (plus:SI (match_dup 1) (match_dup 2)))]
8720   "TARGET_ARM
8721    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8722    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8723    && (GET_CODE (operands[2]) != REG
8724        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8725   "ldr%?b\\t%3, [%0, %2]!"
8726   [(set_attr "type" "load")
8727    (set_attr "predicable" "yes")]
8728 )
8729
8730 (define_insn "*loadqi_predec"
8731   [(set (match_operand:QI 3 "s_register_operand" "=r")
8732         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8733                           (match_operand:SI 2 "s_register_operand" "r"))))
8734    (set (match_operand:SI 0 "s_register_operand" "=r")
8735         (minus:SI (match_dup 1) (match_dup 2)))]
8736   "TARGET_ARM
8737    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8738    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8739    && (GET_CODE (operands[2]) != REG
8740        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8741   "ldr%?b\\t%3, [%0, -%2]!"
8742   [(set_attr "type" "load")
8743    (set_attr "predicable" "yes")]
8744 )
8745
8746 (define_insn "*loadqisi_preinc"
8747   [(set (match_operand:SI 3 "s_register_operand" "=r")
8748         (zero_extend:SI
8749          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8750                           (match_operand:SI 2 "index_operand" "rJ")))))
8751    (set (match_operand:SI 0 "s_register_operand" "=r")
8752         (plus:SI (match_dup 1) (match_dup 2)))]
8753   "TARGET_ARM
8754    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8755    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8756    && (GET_CODE (operands[2]) != REG
8757        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8758   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8759   [(set_attr "type" "load")
8760    (set_attr "predicable" "yes")]
8761 )
8762
8763 (define_insn "*loadqisi_predec"
8764   [(set (match_operand:SI 3 "s_register_operand" "=r")
8765         (zero_extend:SI
8766          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8767                            (match_operand:SI 2 "s_register_operand" "r")))))
8768    (set (match_operand:SI 0 "s_register_operand" "=r")
8769         (minus:SI (match_dup 1) (match_dup 2)))]
8770   "TARGET_ARM
8771    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8772    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8773    && (GET_CODE (operands[2]) != REG
8774        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8775   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8776   [(set_attr "type" "load")
8777    (set_attr "predicable" "yes")]
8778 )
8779
8780 (define_insn "*strsi_preinc"
8781   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8782                          (match_operand:SI 2 "index_operand" "rJ")))
8783         (match_operand:SI 3 "s_register_operand" "r"))
8784    (set (match_operand:SI 0 "s_register_operand" "=r")
8785         (plus:SI (match_dup 1) (match_dup 2)))]
8786   "TARGET_ARM
8787    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8788    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8789    && (GET_CODE (operands[2]) != REG
8790        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8791   "str%?\\t%3, [%0, %2]!"
8792   [(set_attr "type" "store1")
8793    (set_attr "predicable" "yes")]
8794 )
8795
8796 (define_insn "*strsi_predec"
8797   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8798                           (match_operand:SI 2 "s_register_operand" "r")))
8799         (match_operand:SI 3 "s_register_operand" "r"))
8800    (set (match_operand:SI 0 "s_register_operand" "=r")
8801         (minus:SI (match_dup 1) (match_dup 2)))]
8802   "TARGET_ARM
8803    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8804    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8805    && (GET_CODE (operands[2]) != REG
8806        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8807   "str%?\\t%3, [%0, -%2]!"
8808   [(set_attr "type" "store1")
8809    (set_attr "predicable" "yes")]
8810 )
8811
8812 (define_insn "*loadsi_preinc"
8813   [(set (match_operand:SI 3 "s_register_operand" "=r")
8814         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8815                          (match_operand:SI 2 "index_operand" "rJ"))))
8816    (set (match_operand:SI 0 "s_register_operand" "=r")
8817         (plus:SI (match_dup 1) (match_dup 2)))]
8818   "TARGET_ARM
8819    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8820    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8821    && (GET_CODE (operands[2]) != REG
8822        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8823   "ldr%?\\t%3, [%0, %2]!"
8824   [(set_attr "type" "load")
8825    (set_attr "predicable" "yes")]
8826 )
8827
8828 (define_insn "*loadsi_predec"
8829   [(set (match_operand:SI 3 "s_register_operand" "=r")
8830         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8831                           (match_operand:SI 2 "s_register_operand" "r"))))
8832    (set (match_operand:SI 0 "s_register_operand" "=r")
8833         (minus:SI (match_dup 1) (match_dup 2)))]
8834   "TARGET_ARM
8835    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8836    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8837    && (GET_CODE (operands[2]) != REG
8838        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8839   "ldr%?\\t%3, [%0, -%2]!"
8840   [(set_attr "type" "load")
8841    (set_attr "predicable" "yes")]
8842 )
8843
8844 (define_insn "*loadhi_preinc"
8845   [(set (match_operand:HI 3 "s_register_operand" "=r")
8846         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8847                          (match_operand:SI 2 "index_operand" "rJ"))))
8848    (set (match_operand:SI 0 "s_register_operand" "=r")
8849         (plus:SI (match_dup 1) (match_dup 2)))]
8850   "TARGET_ARM
8851    && !BYTES_BIG_ENDIAN
8852    && !TARGET_MMU_TRAPS
8853    && !arm_arch4
8854    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8855    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8856    && (GET_CODE (operands[2]) != REG
8857        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8858   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8859   [(set_attr "type" "load")
8860    (set_attr "predicable" "yes")]
8861 )
8862
8863 (define_insn "*loadhi_predec"
8864   [(set (match_operand:HI 3 "s_register_operand" "=r")
8865         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8866                           (match_operand:SI 2 "s_register_operand" "r"))))
8867    (set (match_operand:SI 0 "s_register_operand" "=r")
8868         (minus:SI (match_dup 1) (match_dup 2)))]
8869   "TARGET_ARM
8870    && !BYTES_BIG_ENDIAN
8871    && !TARGET_MMU_TRAPS
8872    && !arm_arch4
8873    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8874    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8875    && (GET_CODE (operands[2]) != REG
8876        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8877   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8878   [(set_attr "type" "load")
8879    (set_attr "predicable" "yes")]
8880 )
8881
8882 (define_insn "*strqi_shiftpreinc"
8883   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8884                           [(match_operand:SI 3 "s_register_operand" "r")
8885                            (match_operand:SI 4 "const_shift_operand" "n")])
8886                          (match_operand:SI 1 "s_register_operand" "0")))
8887         (match_operand:QI 5 "s_register_operand" "r"))
8888    (set (match_operand:SI 0 "s_register_operand" "=r")
8889         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8890                  (match_dup 1)))]
8891   "TARGET_ARM
8892    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8893    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8894    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8895   "str%?b\\t%5, [%0, %3%S2]!"
8896   [(set_attr "type" "store1")
8897    (set_attr "predicable" "yes")]
8898 )
8899
8900 (define_insn "*strqi_shiftpredec"
8901   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8902                           (match_operator:SI 2 "shift_operator"
8903                            [(match_operand:SI 3 "s_register_operand" "r")
8904                             (match_operand:SI 4 "const_shift_operand" "n")])))
8905         (match_operand:QI 5 "s_register_operand" "r"))
8906    (set (match_operand:SI 0 "s_register_operand" "=r")
8907         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8908                                                  (match_dup 4)])))]
8909   "TARGET_ARM
8910    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8911    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8912    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8913   "str%?b\\t%5, [%0, -%3%S2]!"
8914   [(set_attr "type" "store1")
8915    (set_attr "predicable" "yes")]
8916 )
8917
8918 (define_insn "*loadqi_shiftpreinc"
8919   [(set (match_operand:QI 5 "s_register_operand" "=r")
8920         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8921                           [(match_operand:SI 3 "s_register_operand" "r")
8922                            (match_operand:SI 4 "const_shift_operand" "n")])
8923                          (match_operand:SI 1 "s_register_operand" "0"))))
8924    (set (match_operand:SI 0 "s_register_operand" "=r")
8925         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8926                  (match_dup 1)))]
8927   "TARGET_ARM
8928    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8929    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8930    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8931   "ldr%?b\\t%5, [%0, %3%S2]!"
8932   [(set_attr "type" "load")
8933    (set_attr "predicable" "yes")]
8934 )
8935
8936 (define_insn "*loadqi_shiftpredec"
8937   [(set (match_operand:QI 5 "s_register_operand" "=r")
8938         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8939                           (match_operator:SI 2 "shift_operator"
8940                            [(match_operand:SI 3 "s_register_operand" "r")
8941                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8942    (set (match_operand:SI 0 "s_register_operand" "=r")
8943         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8944                                                  (match_dup 4)])))]
8945   "TARGET_ARM
8946    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8947    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8948    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8949   "ldr%?b\\t%5, [%0, -%3%S2]!"
8950   [(set_attr "type" "load")
8951    (set_attr "predicable" "yes")]
8952 )
8953
8954 (define_insn "*strsi_shiftpreinc"
8955   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8956                           [(match_operand:SI 3 "s_register_operand" "r")
8957                            (match_operand:SI 4 "const_shift_operand" "n")])
8958                          (match_operand:SI 1 "s_register_operand" "0")))
8959         (match_operand:SI 5 "s_register_operand" "r"))
8960    (set (match_operand:SI 0 "s_register_operand" "=r")
8961         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8962                  (match_dup 1)))]
8963   "TARGET_ARM
8964    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8965    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8966    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8967   "str%?\\t%5, [%0, %3%S2]!"
8968   [(set_attr "type" "store1")
8969    (set_attr "predicable" "yes")]
8970 )
8971
8972 (define_insn "*strsi_shiftpredec"
8973   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8974                           (match_operator:SI 2 "shift_operator"
8975                            [(match_operand:SI 3 "s_register_operand" "r")
8976                             (match_operand:SI 4 "const_shift_operand" "n")])))
8977         (match_operand:SI 5 "s_register_operand" "r"))
8978    (set (match_operand:SI 0 "s_register_operand" "=r")
8979         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8980                                                  (match_dup 4)])))]
8981   "TARGET_ARM
8982    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8983    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8984    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8985   "str%?\\t%5, [%0, -%3%S2]!"
8986   [(set_attr "type" "store1")
8987    (set_attr "predicable" "yes")]
8988 )
8989
8990 (define_insn "*loadsi_shiftpreinc"
8991   [(set (match_operand:SI 5 "s_register_operand" "=r")
8992         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8993                           [(match_operand:SI 3 "s_register_operand" "r")
8994                            (match_operand:SI 4 "const_shift_operand" "n")])
8995                          (match_operand:SI 1 "s_register_operand" "0"))))
8996    (set (match_operand:SI 0 "s_register_operand" "=r")
8997         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8998                  (match_dup 1)))]
8999   "TARGET_ARM
9000    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9001    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9002    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9003   "ldr%?\\t%5, [%0, %3%S2]!"
9004   [(set_attr "type" "load")
9005    (set_attr "predicable" "yes")]
9006 )
9007
9008 (define_insn "*loadsi_shiftpredec"
9009   [(set (match_operand:SI 5 "s_register_operand" "=r")
9010         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9011                           (match_operator:SI 2 "shift_operator"
9012                            [(match_operand:SI 3 "s_register_operand" "r")
9013                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9014    (set (match_operand:SI 0 "s_register_operand" "=r")
9015         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9016                                                  (match_dup 4)])))]
9017   "TARGET_ARM
9018    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9019    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9020    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9021   "ldr%?\\t%5, [%0, -%3%S2]!"
9022   [(set_attr "type" "load")
9023    (set_attr "predicable" "yes")])
9024
9025 (define_insn "*loadhi_shiftpreinc"
9026   [(set (match_operand:HI 5 "s_register_operand" "=r")
9027         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
9028                           [(match_operand:SI 3 "s_register_operand" "r")
9029                            (match_operand:SI 4 "const_shift_operand" "n")])
9030                          (match_operand:SI 1 "s_register_operand" "0"))))
9031    (set (match_operand:SI 0 "s_register_operand" "=r")
9032         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9033                  (match_dup 1)))]
9034   "TARGET_ARM
9035    && !BYTES_BIG_ENDIAN
9036    && !TARGET_MMU_TRAPS
9037    && !arm_arch4
9038    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9039    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9040    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9041   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
9042   [(set_attr "type" "load")
9043    (set_attr "predicable" "yes")]
9044 )
9045
9046 (define_insn "*loadhi_shiftpredec"
9047   [(set (match_operand:HI 5 "s_register_operand" "=r")
9048         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9049                           (match_operator:SI 2 "shift_operator"
9050                            [(match_operand:SI 3 "s_register_operand" "r")
9051                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9052    (set (match_operand:SI 0 "s_register_operand" "=r")
9053         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9054                                                  (match_dup 4)])))]
9055   "TARGET_ARM
9056    && !BYTES_BIG_ENDIAN
9057    && !TARGET_MMU_TRAPS
9058    && !arm_arch4
9059    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9060    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9061    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9062   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
9063   [(set_attr "type" "load")
9064    (set_attr "predicable" "yes")]
9065 )
9066
9067 ; It can also support extended post-inc expressions, but combine doesn't
9068 ; try these....
9069 ; It doesn't seem worth adding peepholes for anything but the most common
9070 ; cases since, unlike combine, the increment must immediately follow the load
9071 ; for this pattern to match.
9072 ; We must watch to see that the source/destination register isn't also the
9073 ; same as the base address register, and that if the index is a register,
9074 ; that it is not the same as the base address register.  In such cases the
9075 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9076 ; we cannot use it.
9077
9078 (define_peephole
9079   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9080         (match_operand:QI 2 "s_register_operand" "r"))
9081    (set (match_dup 0)
9082         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9083   "TARGET_ARM
9084    && (REGNO (operands[2]) != REGNO (operands[0]))
9085    && (GET_CODE (operands[1]) != REG
9086        || (REGNO (operands[1]) != REGNO (operands[0])))"
9087   "str%?b\\t%2, [%0], %1"
9088 )
9089
9090 (define_peephole
9091   [(set (match_operand:QI 0 "s_register_operand" "=r")
9092         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9093    (set (match_dup 1)
9094         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9095   "TARGET_ARM
9096    && REGNO (operands[0]) != REGNO(operands[1])
9097    && (GET_CODE (operands[2]) != REG
9098        || REGNO(operands[0]) != REGNO (operands[2]))"
9099   "ldr%?b\\t%0, [%1], %2"
9100 )
9101
9102 (define_peephole
9103   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9104         (match_operand:SI 2 "s_register_operand" "r"))
9105    (set (match_dup 0)
9106         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9107   "TARGET_ARM
9108    && (REGNO (operands[2]) != REGNO (operands[0]))
9109    && (GET_CODE (operands[1]) != REG
9110        || (REGNO (operands[1]) != REGNO (operands[0])))"
9111   "str%?\\t%2, [%0], %1"
9112 )
9113
9114 (define_peephole
9115   [(set (match_operand:HI 0 "s_register_operand" "=r")
9116         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
9117    (set (match_dup 1)
9118         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9119   "TARGET_ARM
9120    && !BYTES_BIG_ENDIAN
9121    && !TARGET_MMU_TRAPS
9122    && !arm_arch4
9123    && REGNO (operands[0]) != REGNO(operands[1])
9124    && (GET_CODE (operands[2]) != REG
9125        || REGNO(operands[0]) != REGNO (operands[2]))"
9126   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
9127 )
9128
9129 (define_peephole
9130   [(set (match_operand:SI 0 "s_register_operand" "=r")
9131         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9132    (set (match_dup 1)
9133         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9134   "TARGET_ARM
9135    && REGNO (operands[0]) != REGNO(operands[1])
9136    && (GET_CODE (operands[2]) != REG
9137        || REGNO(operands[0]) != REGNO (operands[2]))"
9138   "ldr%?\\t%0, [%1], %2"
9139 )
9140
9141 (define_peephole
9142   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9143                          (match_operand:SI 1 "index_operand" "rJ")))
9144         (match_operand:QI 2 "s_register_operand" "r"))
9145    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9146   "TARGET_ARM
9147    && (REGNO (operands[2]) != REGNO (operands[0]))
9148    && (GET_CODE (operands[1]) != REG
9149        || (REGNO (operands[1]) != REGNO (operands[0])))"
9150   "str%?b\\t%2, [%0, %1]!"
9151 )
9152
9153 (define_peephole
9154   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9155                           [(match_operand:SI 0 "s_register_operand" "r")
9156                            (match_operand:SI 1 "const_int_operand" "n")])
9157                          (match_operand:SI 2 "s_register_operand" "+r")))
9158         (match_operand:QI 3 "s_register_operand" "r"))
9159    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9160                                (match_dup 2)))]
9161   "TARGET_ARM
9162    && (REGNO (operands[3]) != REGNO (operands[2]))
9163    && (REGNO (operands[0]) != REGNO (operands[2]))"
9164   "str%?b\\t%3, [%2, %0%S4]!"
9165 )
9166
9167 ; This pattern is never tried by combine, so do it as a peephole
9168
9169 (define_peephole2
9170   [(set (match_operand:SI 0 "s_register_operand" "")
9171         (match_operand:SI 1 "s_register_operand" ""))
9172    (set (reg:CC CC_REGNUM)
9173         (compare:CC (match_dup 1) (const_int 0)))]
9174   "TARGET_ARM
9175    && (!TARGET_CIRRUS
9176        || (!cirrus_fp_register (operands[0], SImode)
9177            && !cirrus_fp_register (operands[1], SImode)))
9178   "
9179   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9180               (set (match_dup 0) (match_dup 1))])]
9181   ""
9182 )
9183
9184 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9185 ; reversed, check that the memory references aren't volatile.
9186
9187 (define_peephole
9188   [(set (match_operand:SI 0 "s_register_operand" "=r")
9189         (match_operand:SI 4 "memory_operand" "m"))
9190    (set (match_operand:SI 1 "s_register_operand" "=r")
9191         (match_operand:SI 5 "memory_operand" "m"))
9192    (set (match_operand:SI 2 "s_register_operand" "=r")
9193         (match_operand:SI 6 "memory_operand" "m"))
9194    (set (match_operand:SI 3 "s_register_operand" "=r")
9195         (match_operand:SI 7 "memory_operand" "m"))]
9196   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9197   "*
9198   return emit_ldm_seq (operands, 4);
9199   "
9200 )
9201
9202 (define_peephole
9203   [(set (match_operand:SI 0 "s_register_operand" "=r")
9204         (match_operand:SI 3 "memory_operand" "m"))
9205    (set (match_operand:SI 1 "s_register_operand" "=r")
9206         (match_operand:SI 4 "memory_operand" "m"))
9207    (set (match_operand:SI 2 "s_register_operand" "=r")
9208         (match_operand:SI 5 "memory_operand" "m"))]
9209   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9210   "*
9211   return emit_ldm_seq (operands, 3);
9212   "
9213 )
9214
9215 (define_peephole
9216   [(set (match_operand:SI 0 "s_register_operand" "=r")
9217         (match_operand:SI 2 "memory_operand" "m"))
9218    (set (match_operand:SI 1 "s_register_operand" "=r")
9219         (match_operand:SI 3 "memory_operand" "m"))]
9220   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9221   "*
9222   return emit_ldm_seq (operands, 2);
9223   "
9224 )
9225
9226 (define_peephole
9227   [(set (match_operand:SI 4 "memory_operand" "=m")
9228         (match_operand:SI 0 "s_register_operand" "r"))
9229    (set (match_operand:SI 5 "memory_operand" "=m")
9230         (match_operand:SI 1 "s_register_operand" "r"))
9231    (set (match_operand:SI 6 "memory_operand" "=m")
9232         (match_operand:SI 2 "s_register_operand" "r"))
9233    (set (match_operand:SI 7 "memory_operand" "=m")
9234         (match_operand:SI 3 "s_register_operand" "r"))]
9235   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9236   "*
9237   return emit_stm_seq (operands, 4);
9238   "
9239 )
9240
9241 (define_peephole
9242   [(set (match_operand:SI 3 "memory_operand" "=m")
9243         (match_operand:SI 0 "s_register_operand" "r"))
9244    (set (match_operand:SI 4 "memory_operand" "=m")
9245         (match_operand:SI 1 "s_register_operand" "r"))
9246    (set (match_operand:SI 5 "memory_operand" "=m")
9247         (match_operand:SI 2 "s_register_operand" "r"))]
9248   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9249   "*
9250   return emit_stm_seq (operands, 3);
9251   "
9252 )
9253
9254 (define_peephole
9255   [(set (match_operand:SI 2 "memory_operand" "=m")
9256         (match_operand:SI 0 "s_register_operand" "r"))
9257    (set (match_operand:SI 3 "memory_operand" "=m")
9258         (match_operand:SI 1 "s_register_operand" "r"))]
9259   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9260   "*
9261   return emit_stm_seq (operands, 2);
9262   "
9263 )
9264
9265 (define_split
9266   [(set (match_operand:SI 0 "s_register_operand" "")
9267         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9268                        (const_int 0))
9269                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9270                          [(match_operand:SI 3 "s_register_operand" "")
9271                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9272    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9273   "TARGET_ARM"
9274   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9275    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9276                               (match_dup 5)))]
9277   ""
9278 )
9279
9280 ;; This split can be used because CC_Z mode implies that the following
9281 ;; branch will be an equality, or an unsigned inequality, so the sign
9282 ;; extension is not needed.
9283
9284 (define_split
9285   [(set (reg:CC_Z CC_REGNUM)
9286         (compare:CC_Z
9287          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9288                     (const_int 24))
9289          (match_operand 1 "const_int_operand" "")))
9290    (clobber (match_scratch:SI 2 ""))]
9291   "TARGET_ARM
9292    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9293        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9294   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9295    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9296   "
9297   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9298   "
9299 )
9300
9301 (define_expand "prologue"
9302   [(clobber (const_int 0))]
9303   "TARGET_EITHER"
9304   "if (TARGET_ARM)
9305      arm_expand_prologue ();
9306    else
9307      thumb_expand_prologue ();
9308   DONE;
9309   "
9310 )
9311
9312 (define_expand "epilogue"
9313   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9314   "TARGET_EITHER"
9315   "
9316   if (TARGET_THUMB)
9317     thumb_expand_epilogue ();
9318   else if (USE_RETURN_INSN (FALSE))
9319     {
9320       emit_jump_insn (gen_return ());
9321       DONE;
9322     }
9323   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9324         gen_rtvec (1,
9325                 gen_rtx_RETURN (VOIDmode)),
9326         VUNSPEC_EPILOGUE));
9327   DONE;
9328   "
9329 )
9330
9331 ;; Note - although unspec_volatile's USE all hard registers,
9332 ;; USEs are ignored after relaod has completed.  Thus we need
9333 ;; to add an unspec of the link register to ensure that flow
9334 ;; does not think that it is unused by the sibcall branch that
9335 ;; will replace the standard function epilogue.
9336 (define_insn "sibcall_epilogue"
9337   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9338               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9339   "TARGET_ARM"
9340   "*
9341   if (USE_RETURN_INSN (FALSE))
9342     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9343   return arm_output_epilogue (FALSE);
9344   "
9345 ;; Length is absolute worst case
9346   [(set_attr "length" "44")
9347    (set_attr "type" "block")
9348    ;; We don't clobber the conditions, but the potential length of this
9349    ;; operation is sufficient to make conditionalizing the sequence 
9350    ;; unlikely to be profitable.
9351    (set_attr "conds" "clob")]
9352 )
9353
9354 (define_insn "*epilogue_insns"
9355   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9356   "TARGET_EITHER"
9357   "*
9358   if (TARGET_ARM)
9359     return arm_output_epilogue (TRUE);
9360   else /* TARGET_THUMB */
9361     return thumb_unexpanded_epilogue ();
9362   "
9363   ; Length is absolute worst case
9364   [(set_attr "length" "44")
9365    (set_attr "type" "block")
9366    ;; We don't clobber the conditions, but the potential length of this
9367    ;; operation is sufficient to make conditionalizing the sequence 
9368    ;; unlikely to be profitable.
9369    (set_attr "conds" "clob")]
9370 )
9371
9372 (define_expand "eh_epilogue"
9373   [(use (match_operand:SI 0 "register_operand" ""))
9374    (use (match_operand:SI 1 "register_operand" ""))
9375    (use (match_operand:SI 2 "register_operand" ""))]
9376   "TARGET_EITHER"
9377   "
9378   {
9379     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9380     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9381       {
9382         rtx ra = gen_rtx_REG (Pmode, 2);
9383
9384         emit_move_insn (ra, operands[2]);
9385         operands[2] = ra;
9386       }
9387     /* This is a hack -- we may have crystalized the function type too
9388        early.  */
9389     cfun->machine->func_type = 0;
9390   }"
9391 )
9392
9393 ;; This split is only used during output to reduce the number of patterns
9394 ;; that need assembler instructions adding to them.  We allowed the setting
9395 ;; of the conditions to be implicit during rtl generation so that
9396 ;; the conditional compare patterns would work.  However this conflicts to
9397 ;; some extent with the conditional data operations, so we have to split them
9398 ;; up again here.
9399
9400 (define_split
9401   [(set (match_operand:SI 0 "s_register_operand" "")
9402         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9403                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9404                          (match_dup 0)
9405                          (match_operand 4 "" "")))
9406    (clobber (reg:CC CC_REGNUM))]
9407   "TARGET_ARM && reload_completed"
9408   [(set (match_dup 5) (match_dup 6))
9409    (cond_exec (match_dup 7)
9410               (set (match_dup 0) (match_dup 4)))]
9411   "
9412   {
9413     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9414                                              operands[2], operands[3]);
9415     enum rtx_code rc = GET_CODE (operands[1]);
9416
9417     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9418     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9419     if (mode == CCFPmode || mode == CCFPEmode)
9420       rc = reverse_condition_maybe_unordered (rc);
9421     else
9422       rc = reverse_condition (rc);
9423
9424     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9425   }"
9426 )
9427
9428 (define_split
9429   [(set (match_operand:SI 0 "s_register_operand" "")
9430         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9431                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9432                          (match_operand 4 "" "")
9433                          (match_dup 0)))
9434    (clobber (reg:CC CC_REGNUM))]
9435   "TARGET_ARM && reload_completed"
9436   [(set (match_dup 5) (match_dup 6))
9437    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9438               (set (match_dup 0) (match_dup 4)))]
9439   "
9440   {
9441     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9442                                              operands[2], operands[3]);
9443
9444     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9445     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9446   }"
9447 )
9448
9449 (define_split
9450   [(set (match_operand:SI 0 "s_register_operand" "")
9451         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9452                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9453                          (match_operand 4 "" "")
9454                          (match_operand 5 "" "")))
9455    (clobber (reg:CC CC_REGNUM))]
9456   "TARGET_ARM && reload_completed"
9457   [(set (match_dup 6) (match_dup 7))
9458    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9459               (set (match_dup 0) (match_dup 4)))
9460    (cond_exec (match_dup 8)
9461               (set (match_dup 0) (match_dup 5)))]
9462   "
9463   {
9464     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9465                                              operands[2], operands[3]);
9466     enum rtx_code rc = GET_CODE (operands[1]);
9467
9468     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9469     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9470     if (mode == CCFPmode || mode == CCFPEmode)
9471       rc = reverse_condition_maybe_unordered (rc);
9472     else
9473       rc = reverse_condition (rc);
9474
9475     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9476   }"
9477 )
9478
9479 (define_split
9480   [(set (match_operand:SI 0 "s_register_operand" "")
9481         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9482                           [(match_operand:SI 2 "s_register_operand" "")
9483                            (match_operand:SI 3 "arm_add_operand" "")])
9484                          (match_operand:SI 4 "arm_rhs_operand" "")
9485                          (not:SI
9486                           (match_operand:SI 5 "s_register_operand" ""))))
9487    (clobber (reg:CC CC_REGNUM))]
9488   "TARGET_ARM && reload_completed"
9489   [(set (match_dup 6) (match_dup 7))
9490    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9491               (set (match_dup 0) (match_dup 4)))
9492    (cond_exec (match_dup 8)
9493               (set (match_dup 0) (not:SI (match_dup 5))))]
9494   "
9495   {
9496     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9497                                              operands[2], operands[3]);
9498     enum rtx_code rc = GET_CODE (operands[1]);
9499
9500     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9501     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
9502     if (mode == CCFPmode || mode == CCFPEmode)
9503       rc = reverse_condition_maybe_unordered (rc);
9504     else
9505       rc = reverse_condition (rc);
9506
9507     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9508   }"
9509 )
9510
9511 (define_insn "*cond_move_not"
9512   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9513         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9514                           [(match_operand 3 "cc_register" "") (const_int 0)])
9515                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9516                          (not:SI
9517                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9518   "TARGET_ARM"
9519   "@
9520    mvn%D4\\t%0, %2
9521    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9522   [(set_attr "conds" "use")
9523    (set_attr "length" "4,8")]
9524 )
9525
9526 ;; The next two patterns occur when an AND operation is followed by a
9527 ;; scc insn sequence 
9528
9529 (define_insn "*sign_extract_onebit"
9530   [(set (match_operand:SI 0 "s_register_operand" "=r")
9531         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9532                          (const_int 1)
9533                          (match_operand:SI 2 "const_int_operand" "n")))
9534     (clobber (reg:CC CC_REGNUM))]
9535   "TARGET_ARM"
9536   "*
9537     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9538     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9539     return \"mvnne\\t%0, #0\";
9540   "
9541   [(set_attr "conds" "clob")
9542    (set_attr "length" "8")]
9543 )
9544
9545 (define_insn "*not_signextract_onebit"
9546   [(set (match_operand:SI 0 "s_register_operand" "=r")
9547         (not:SI
9548          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9549                           (const_int 1)
9550                           (match_operand:SI 2 "const_int_operand" "n"))))
9551    (clobber (reg:CC CC_REGNUM))]
9552   "TARGET_ARM"
9553   "*
9554     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9555     output_asm_insn (\"tst\\t%1, %2\", operands);
9556     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9557     return \"movne\\t%0, #0\";
9558   "
9559   [(set_attr "conds" "clob")
9560    (set_attr "length" "12")]
9561 )
9562
9563 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9564 ;; expressions.  For simplicity, the first register is also in the unspec
9565 ;; part.
9566 (define_insn "*push_multi"
9567   [(match_parallel 2 "multi_register_push"
9568     [(set (match_operand:BLK 0 "memory_operand" "=m")
9569           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9570                       UNSPEC_PUSH_MULT))])]
9571   "TARGET_ARM"
9572   "*
9573   {
9574     int num_saves = XVECLEN (operands[2], 0);
9575      
9576     /* For the StrongARM at least it is faster to
9577        use STR to store only a single register.  */
9578     if (num_saves == 1)
9579       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9580     else
9581       {
9582         int i;
9583         char pattern[100];
9584
9585         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9586
9587         for (i = 1; i < num_saves; i++)
9588           {
9589             strcat (pattern, \", %|\");
9590             strcat (pattern,
9591                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9592           }
9593
9594         strcat (pattern, \"}\");
9595         output_asm_insn (pattern, operands);
9596       }
9597
9598     return \"\";
9599   }"
9600   [(set_attr "type" "store4")]
9601 )
9602
9603 (define_insn "stack_tie"
9604   [(set (mem:BLK (scratch))
9605         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9606                      (match_operand:SI 1 "s_register_operand" "r")]
9607                     UNSPEC_PRLG_STK))]
9608   ""
9609   ""
9610   [(set_attr "length" "0")]
9611 )
9612
9613 ;; Similarly for the floating point registers
9614 (define_insn "*push_fp_multi"
9615   [(match_parallel 2 "multi_register_push"
9616     [(set (match_operand:BLK 0 "memory_operand" "=m")
9617           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9618                       UNSPEC_PUSH_MULT))])]
9619   "TARGET_ARM"
9620   "*
9621   {
9622     char pattern[100];
9623
9624     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9625     output_asm_insn (pattern, operands);
9626     return \"\";
9627   }"
9628   [(set_attr "type" "f_store")]
9629 )
9630
9631 ;; Special patterns for dealing with the constant pool
9632
9633 (define_insn "align_4"
9634   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9635   "TARGET_EITHER"
9636   "*
9637   assemble_align (32);
9638   return \"\";
9639   "
9640 )
9641
9642 (define_insn "align_8"
9643   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9644   "TARGET_REALLY_IWMMXT"
9645   "*
9646   assemble_align (64);
9647   return \"\";
9648   "
9649 )
9650
9651 (define_insn "consttable_end"
9652   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9653   "TARGET_EITHER"
9654   "*
9655   making_const_table = FALSE;
9656   return \"\";
9657   "
9658 )
9659
9660 (define_insn "consttable_1"
9661   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9662   "TARGET_THUMB"
9663   "*
9664   making_const_table = TRUE;
9665   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9666   assemble_zeros (3);
9667   return \"\";
9668   "
9669   [(set_attr "length" "4")]
9670 )
9671
9672 (define_insn "consttable_2"
9673   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9674   "TARGET_THUMB"
9675   "*
9676   making_const_table = TRUE;
9677   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9678   assemble_zeros (2);
9679   return \"\";
9680   "
9681   [(set_attr "length" "4")]
9682 )
9683
9684 (define_insn "consttable_4"
9685   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9686   "TARGET_EITHER"
9687   "*
9688   {
9689     making_const_table = TRUE;
9690     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9691       {
9692       case MODE_FLOAT:
9693       {
9694         REAL_VALUE_TYPE r;
9695         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9696         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9697         break;
9698       }
9699       default:
9700         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9701         break;
9702       }
9703     return \"\";
9704   }"
9705   [(set_attr "length" "4")]
9706 )
9707
9708 (define_insn "consttable_8"
9709   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9710   "TARGET_EITHER"
9711   "*
9712   {
9713     making_const_table = TRUE;
9714     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9715       {
9716        case MODE_FLOAT:
9717         {
9718           REAL_VALUE_TYPE r;
9719           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9720           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9721           break;
9722         }
9723       default:
9724         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9725         break;
9726       }
9727     return \"\";
9728   }"
9729   [(set_attr "length" "8")]
9730 )
9731
9732 ;; Miscellaneous Thumb patterns
9733
9734 (define_expand "tablejump"
9735   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9736               (use (label_ref (match_operand 1 "" "")))])]
9737   "TARGET_THUMB"
9738   "
9739   if (flag_pic)
9740     {
9741       /* Hopefully, CSE will eliminate this copy.  */
9742       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9743       rtx reg2 = gen_reg_rtx (SImode);
9744
9745       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9746       operands[0] = reg2;
9747     }
9748   "
9749 )
9750
9751 (define_insn "*thumb_tablejump"
9752   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9753    (use (label_ref (match_operand 1 "" "")))]
9754   "TARGET_THUMB"
9755   "mov\\t%|pc, %0"
9756   [(set_attr "length" "2")]
9757 )
9758
9759 ;; V5 Instructions,
9760
9761 (define_insn "clzsi2"
9762   [(set (match_operand:SI 0 "s_register_operand" "=r")
9763         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
9764   "TARGET_ARM && arm_arch5"
9765   "clz%?\\t%0, %1"
9766   [(set_attr "predicable" "yes")])
9767
9768 (define_expand "ffssi2"
9769   [(set (match_operand:SI 0 "s_register_operand" "")
9770         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9771   "TARGET_ARM && arm_arch5"
9772   "
9773   {
9774     rtx t1, t2, t3;
9775
9776     t1 = gen_reg_rtx (SImode);
9777     t2 = gen_reg_rtx (SImode);
9778     t3 = gen_reg_rtx (SImode);
9779
9780     emit_insn (gen_negsi2 (t1, operands[1]));
9781     emit_insn (gen_andsi3 (t2, operands[1], t1));
9782     emit_insn (gen_clzsi2 (t3, t2));
9783     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9784     DONE;
9785   }"
9786 )
9787
9788 (define_expand "ctzsi2"
9789   [(set (match_operand:SI 0 "s_register_operand" "")
9790         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
9791   "TARGET_ARM && arm_arch5"
9792   "
9793   {
9794     rtx t1, t2, t3;
9795
9796     t1 = gen_reg_rtx (SImode);
9797     t2 = gen_reg_rtx (SImode);
9798     t3 = gen_reg_rtx (SImode);
9799
9800     emit_insn (gen_negsi2 (t1, operands[1]));
9801     emit_insn (gen_andsi3 (t2, operands[1], t1));
9802     emit_insn (gen_clzsi2 (t3, t2));
9803     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
9804     DONE;
9805   }"
9806 )
9807
9808 ;; V5E instructions.
9809
9810 (define_insn "prefetch"
9811   [(prefetch (match_operand:SI 0 "address_operand" "p")
9812              (match_operand:SI 1 "" "")
9813              (match_operand:SI 2 "" ""))]
9814   "TARGET_ARM && arm_arch5e"
9815   "pld\\t%a0")
9816
9817 ;; General predication pattern
9818
9819 (define_cond_exec
9820   [(match_operator 0 "arm_comparison_operator"
9821     [(match_operand 1 "cc_register" "")
9822      (const_int 0)])]
9823   "TARGET_ARM"
9824   ""
9825 )
9826
9827 (define_insn "prologue_use"
9828   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9829   ""
9830   "%@ %0 needed for prologue"
9831 )
9832
9833 ;; Load the FPA co-processor patterns
9834 (include "fpa.md")
9835 ;; Load the Maverick co-processor patterns
9836 (include "cirrus.md")
9837 ;; Load the Intel Wireless Multimedia Extension patterns
9838 (include "iwmmxt.md")