OSDN Git Service

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