OSDN Git Service

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