OSDN Git Service

* arm.md (addsi3_carryin_shift): Add missing register constraints.
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
7
8 ;; This file is part of GCC.
9
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
14
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18 ;; License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 \f
28 ;;---------------------------------------------------------------------------
29 ;; Constants
30
31 ;; Register numbers
32 (define_constants
33   [(IP_REGNUM       12)         ; Scratch register
34    (SP_REGNUM       13)         ; Stack pointer
35    (LR_REGNUM       14)         ; Return address register
36    (PC_REGNUM       15)         ; Program counter
37    (CC_REGNUM       24)         ; Condition code pseudo register
38    (LAST_ARM_REGNUM 15)
39   ]
40 )
41 ;; 3rd operand to select_dominance_cc_mode
42 (define_constants
43   [(DOM_CC_X_AND_Y  0)
44    (DOM_CC_NX_OR_Y  1)
45    (DOM_CC_X_OR_Y   2)
46   ]
47 )
48
49 ;; UNSPEC Usage:
50 ;; Note: sin and cos are no-longer used.
51
52 (define_constants
53   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
54                         ;   operand 0 is the result,
55                         ;   operand 1 the parameter.
56    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60                         ;   operand 0 is the first register,
61                         ;   subsequent registers are in parallel (use ...)
62                         ;   expressions.
63    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
64                         ;   usage, that is, we will add the pic_register
65                         ;   value to it before trying to dereference it.
66    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
67                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
68                         ;   described by the RTL but must be wrapped to
69                         ;   prevent combine from trying to rip it apart.
70    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
71                         ;   being scheduled before the stack adjustment insn.
72    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73                         ; this unspec is used to prevent the deletion of
74                         ; instructions setting registers for EH handling
75                         ; and stack frame generation.  Operand 0 is the
76                         ; register to "use".
77    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
90   ]
91 )
92
93 ;; UNSPEC_VOLATILE Usage:
94
95 (define_constants
96   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
97                         ;   insn in the code.
98    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99                         ;   instruction epilogue sequence that isn't expanded
100                         ;   into normal RTL.  Used for both normal and sibcall
101                         ;   epilogues.
102    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
103                         ;   for inlined constants.
104    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
105                         ;   table.
106    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
107                         ;   an 8-bit object.
108    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
109                         ;   a 16-bit object.
110    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
111                         ;   a 32-bit object.
112    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
113                         ;   a 64-bit object.
114    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
115    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
116    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
117    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
118    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
120   ]
121 )
122 \f
123 ;;---------------------------------------------------------------------------
124 ;; Attributes
125
126 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127 ; generating ARM code.  This is used to control the length of some insn
128 ; patterns that share the same RTL in both ARM and Thumb code.
129 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
130
131 ; PROG_MODE attribute is used to determine whether condition codes are
132 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
133 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
134 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
135
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
139
140 ;; Operand number of an input operand that is shifted.  Zero if the
141 ;; given instruction does not shift one of its input operands.
142 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 (define_attr "shift" "" (const_int 0))
144
145 ; Floating Point Unit.  If we only have floating point emulation, then there
146 ; is no point in scheduling the floating point insns.  (Well, for best
147 ; performance we should try and group them together).
148 (define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
149   (const (symbol_ref "arm_fpu_attr")))
150
151 ; LENGTH of an instruction (in bytes)
152 (define_attr "length" "" (const_int 4))
153
154 ; POOL_RANGE is how far away from a constant pool entry that this insn
155 ; can be placed.  If the distance is zero, then this insn will never
156 ; reference the pool.
157 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
158 ; before its address.
159 (define_attr "pool_range" "" (const_int 0))
160 (define_attr "neg_pool_range" "" (const_int 0))
161
162 ; An assembler sequence may clobber the condition codes without us knowing.
163 ; If such an insn references the pool, then we have no way of knowing how,
164 ; so use the most conservative value for pool_range.
165 (define_asm_attributes
166  [(set_attr "conds" "clob")
167   (set_attr "length" "4")
168   (set_attr "pool_range" "250")])
169
170 ; TYPE attribute is used to detect floating point instructions which, if
171 ; running on a co-processor can run in parallel with other, basic instructions
172 ; If write-buffer scheduling is enabled then it can also be used in the
173 ; scheduling of writes.
174
175 ; Classification of each insn
176 ; normal        any data instruction that doesn't hit memory or fp regs
177 ; mult          a multiply instruction
178 ; block         blockage insn, this blocks all functional units
179 ; float         a floating point arithmetic operation (subject to expansion)
180 ; fdivd         DFmode floating point division
181 ; fdivs         SFmode floating point division
182 ; fmul          Floating point multiply
183 ; ffmul         Fast floating point multiply
184 ; farith        Floating point arithmetic (4 cycle)
185 ; ffarith       Fast floating point arithmetic (2 cycle)
186 ; float_em      a floating point arithmetic operation that is normally emulated
187 ;               even on a machine with an fpa.
188 ; f_load        a floating point load from memory
189 ; f_store       a floating point store to memory
190 ; f_mem_r       a transfer of a floating point register to a real reg via mem
191 ; r_mem_f       the reverse of f_mem_r
192 ; f_2_r         fast transfer float to arm (no memory needed)
193 ; r_2_f         fast transfer arm to float
194 ; call          a subroutine call
195 ; load          any load from memory
196 ; store1        store 1 word to memory from arm registers
197 ; store2        store 2 words
198 ; store3        store 3 words
199 ; store4        store 4 words
200 ;  Additions for Cirrus Maverick co-processor:
201 ; mav_farith    Floating point arithmetic (4 cycle)
202 ; mav_dmult     Double multiplies (7 cycle)
203 ;
204 (define_attr "type"
205         "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4,mav_farith,mav_dmult" 
206         (const_string "normal"))
207
208 ; Load scheduling, set from the arm_ld_sched variable
209 ; initialized by arm_override_options() 
210 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
211
212 ; condition codes: this one is used by final_prescan_insn to speed up
213 ; conditionalizing instructions.  It saves having to scan the rtl to see if
214 ; it uses or alters the condition codes.
215
216 ; USE means that the condition codes are used by the insn in the process of
217 ;   outputting code, this means (at present) that we can't use the insn in
218 ;   inlined branches
219 ;
220 ; SET means that the purpose of the insn is to set the condition codes in a
221 ;   well defined manner.
222 ;
223 ; CLOB means that the condition codes are altered in an undefined manner, if
224 ;   they are altered at all
225 ;
226 ; JUMP_CLOB is used when the condition cannot be represented by a single
227 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
228 ;
229 ; NOCOND means that the condition codes are neither altered nor affect the
230 ;   output of this insn
231
232 (define_attr "conds" "use,set,clob,jump_clob,nocond"
233         (if_then_else (eq_attr "type" "call")
234          (if_then_else (eq_attr "prog_mode" "prog32")
235           (const_string "clob") (const_string "nocond"))
236          (const_string "nocond")))
237
238 ; Predicable means that the insn can be conditionally executed based on
239 ; an automatically added predicate (additional patterns are generated by 
240 ; gen...).  We default to 'no' because no Thumb patterns match this rule
241 ; and not all ARM patterns do.
242 (define_attr "predicable" "no,yes" (const_string "no"))
243
244 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
245 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
246 ; suffer blockages enough to warrant modelling this (and it can adversely
247 ; affect the schedule).
248 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
249
250 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
251 ; to stall the processor.  Used with model_wbuf above.
252 (define_attr "write_conflict" "no,yes"
253   (if_then_else (eq_attr "type"
254                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
255                 (const_string "yes")
256                 (const_string "no")))
257
258 ; Classify the insns into those that take one cycle and those that take more
259 ; than one on the main cpu execution unit.
260 (define_attr "core_cycles" "single,multi"
261   (if_then_else (eq_attr "type"
262                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
263                 (const_string "single")
264                 (const_string "multi")))
265
266 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
267 ;; distant label.  Only applicable to Thumb code.
268 (define_attr "far_jump" "yes,no" (const_string "no"))
269
270 (define_automaton "arm")
271
272 ;; Write buffer
273 ;
274 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
275 ;
276 ; The write buffer on some of the arm6 processors is hard to model exactly.
277 ; There is room in the buffer for up to two addresses and up to eight words
278 ; of memory, but the two needn't be split evenly.  When writing the two
279 ; addresses are fully pipelined.  However, a read from memory that is not
280 ; currently in the cache will block until the writes have completed.
281 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
282 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
283 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
284 ; cycle to add as well.
285 (define_cpu_unit "write_buf" "arm")
286
287 ;; Write blockage unit
288 ;
289 ; The write_blockage unit models (partially), the fact that reads will stall
290 ; until the write buffer empties.
291 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
292 ; so we don't model them here
293 (define_cpu_unit "write_blockage" "arm")
294
295 ;; Core
296 ;
297 (define_cpu_unit "core" "arm")
298
299 (define_insn_reservation "r_mem_f_wbuf" 5
300   (and (eq_attr "model_wbuf" "yes")
301        (eq_attr "type" "r_mem_f"))
302   "core+write_buf*3")
303
304 (define_insn_reservation "store1_wbuf" 5
305   (and (eq_attr "model_wbuf" "yes")
306        (eq_attr "type" "store1"))
307   "core+write_buf*3+write_blockage*5")
308
309 (define_insn_reservation "store2_wbuf" 7
310   (and (eq_attr "model_wbuf" "yes")
311        (eq_attr "type" "store2"))
312   "core+write_buf*4+write_blockage*7")
313
314 (define_insn_reservation "store3_wbuf" 9
315   (and (eq_attr "model_wbuf" "yes")
316        (eq_attr "type" "store3"))
317   "core+write_buf*5+write_blockage*9")
318
319 (define_insn_reservation "store4_wbuf" 11
320   (and (eq_attr "model_wbuf" "yes")
321        (eq_attr "type" "store4"))
322   "core+write_buf*6+write_blockage*11")
323
324 (define_insn_reservation "store2" 3
325   (and (eq_attr "model_wbuf" "no")
326        (eq_attr "type" "store2"))
327   "core*3")
328
329 (define_insn_reservation "store3" 4
330   (and (eq_attr "model_wbuf" "no")
331        (eq_attr "type" "store3"))
332   "core*4")
333
334 (define_insn_reservation "store4" 5
335   (and (eq_attr "model_wbuf" "no")
336        (eq_attr "type" "store4"))
337   "core*5")
338
339 (define_insn_reservation "store1_ldsched" 1
340   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1"))
341   "core")
342
343 (define_insn_reservation "load_ldsched_xscale" 3
344   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
345        (eq_attr "is_xscale" "yes"))
346   "core")
347
348 (define_insn_reservation "load_ldsched" 2
349   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
350        (eq_attr "is_xscale" "no"))
351   "core")
352
353 (define_insn_reservation "load_or_store" 2
354   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1"))
355   "core*2")
356
357 (define_insn_reservation "mult" 16
358   (and (eq_attr "ldsched" "no") (eq_attr "type" "mult"))
359   "core*16")
360
361 (define_insn_reservation "mult_ldsched_strongarm" 3
362   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
363        (eq_attr "type" "mult"))
364   "core*2")
365
366 (define_insn_reservation "mult_ldsched" 4
367   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
368        (eq_attr "type" "mult"))
369   "core*4")
370
371 (define_insn_reservation "multi_cycle" 32
372   (and (eq_attr "core_cycles" "multi")
373        (eq_attr "type" "!mult,load,store1,store2,store3,store4"))
374   "core*32")
375
376 (define_insn_reservation "single_cycle" 1
377   (eq_attr "core_cycles" "single")
378   "core")
379
380 \f
381 ;;---------------------------------------------------------------------------
382 ;; Insn patterns
383 ;;
384 ;; Addition insns.
385
386 ;; Note: For DImode insns, there is normally no reason why operands should
387 ;; not be in the same register, what we don't want is for something being
388 ;; written to partially overlap something that is an input.
389 ;; Cirrus 64bit additions should not be split because we have a native
390 ;; 64bit addition instructions.
391
392 (define_expand "adddi3"
393  [(parallel
394    [(set (match_operand:DI           0 "s_register_operand" "")
395           (plus:DI (match_operand:DI 1 "s_register_operand" "")
396                    (match_operand:DI 2 "s_register_operand" "")))
397     (clobber (reg:CC CC_REGNUM))])]
398   "TARGET_EITHER"
399   "
400   if (TARGET_CIRRUS)
401     {
402       if (!cirrus_fp_register (operands[0], DImode))
403         operands[0] = force_reg (DImode, operands[0]);
404       if (!cirrus_fp_register (operands[1], DImode))
405         operands[1] = force_reg (DImode, operands[1]);
406       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
407       DONE;
408     }
409
410   if (TARGET_THUMB)
411     {
412       if (GET_CODE (operands[1]) != REG)
413         operands[1] = force_reg (SImode, operands[1]);
414       if (GET_CODE (operands[2]) != REG)
415         operands[2] = force_reg (SImode, operands[2]);
416      }
417   "
418 )
419
420 (define_insn "*thumb_adddi3"
421   [(set (match_operand:DI          0 "register_operand" "=l")
422         (plus:DI (match_operand:DI 1 "register_operand" "%0")
423                  (match_operand:DI 2 "register_operand" "l")))
424    (clobber (reg:CC CC_REGNUM))
425   ]
426   "TARGET_THUMB"
427   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
428   [(set_attr "length" "4")]
429 )
430
431 (define_insn_and_split "*arm_adddi3"
432   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
433         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
434                  (match_operand:DI 2 "s_register_operand" "r,  0")))
435    (clobber (reg:CC CC_REGNUM))]
436   "TARGET_ARM && !TARGET_CIRRUS"
437   "#"
438   "TARGET_ARM && reload_completed"
439   [(parallel [(set (reg:CC_C CC_REGNUM)
440                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
441                                  (match_dup 1)))
442               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
443    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
444                                (plus:SI (match_dup 4) (match_dup 5))))]
445   "
446   {
447     operands[3] = gen_highpart (SImode, operands[0]);
448     operands[0] = gen_lowpart (SImode, operands[0]);
449     operands[4] = gen_highpart (SImode, operands[1]);
450     operands[1] = gen_lowpart (SImode, operands[1]);
451     operands[5] = gen_highpart (SImode, operands[2]);
452     operands[2] = gen_lowpart (SImode, operands[2]);
453   }"
454   [(set_attr "conds" "clob")
455    (set_attr "length" "8")]
456 )
457
458 (define_insn_and_split "*adddi_sesidi_di"
459   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
460         (plus:DI (sign_extend:DI
461                   (match_operand:SI 2 "s_register_operand" "r,r"))
462                  (match_operand:DI 1 "s_register_operand" "r,0")))
463    (clobber (reg:CC CC_REGNUM))]
464   "TARGET_ARM && !TARGET_CIRRUS"
465   "#"
466   "TARGET_ARM && reload_completed"
467   [(parallel [(set (reg:CC_C CC_REGNUM)
468                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
469                                  (match_dup 1)))
470               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
471    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
472                                (plus:SI (ashiftrt:SI (match_dup 2)
473                                                      (const_int 31))
474                                         (match_dup 4))))]
475   "
476   {
477     operands[3] = gen_highpart (SImode, operands[0]);
478     operands[0] = gen_lowpart (SImode, operands[0]);
479     operands[4] = gen_highpart (SImode, operands[1]);
480     operands[1] = gen_lowpart (SImode, operands[1]);
481     operands[2] = gen_lowpart (SImode, operands[2]);
482   }"
483   [(set_attr "conds" "clob")
484    (set_attr "length" "8")]
485 )
486
487 (define_insn_and_split "*adddi_zesidi_di"
488   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
489         (plus:DI (zero_extend:DI
490                   (match_operand:SI 2 "s_register_operand" "r,r"))
491                  (match_operand:DI 1 "s_register_operand" "r,0")))
492    (clobber (reg:CC CC_REGNUM))]
493   "TARGET_ARM && !TARGET_CIRRUS"
494   "#"
495   "TARGET_ARM && reload_completed"
496   [(parallel [(set (reg:CC_C CC_REGNUM)
497                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
498                                  (match_dup 1)))
499               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
500    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
501                                (plus:SI (match_dup 4) (const_int 0))))]
502   "
503   {
504     operands[3] = gen_highpart (SImode, operands[0]);
505     operands[0] = gen_lowpart (SImode, operands[0]);
506     operands[4] = gen_highpart (SImode, operands[1]);
507     operands[1] = gen_lowpart (SImode, operands[1]);
508     operands[2] = gen_lowpart (SImode, operands[2]);
509   }"
510   [(set_attr "conds" "clob")
511    (set_attr "length" "8")]
512 )
513
514 (define_expand "addsi3"
515   [(set (match_operand:SI          0 "s_register_operand" "")
516         (plus:SI (match_operand:SI 1 "s_register_operand" "")
517                  (match_operand:SI 2 "reg_or_int_operand" "")))]
518   "TARGET_EITHER"
519   "
520   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
521     {
522       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
523                           operands[1],
524                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
525       DONE;
526     }
527   "
528 )
529
530 ; If there is a scratch available, this will be faster than synthesizing the
531 ; addition.
532 (define_peephole2
533   [(match_scratch:SI 3 "r")
534    (set (match_operand:SI          0 "s_register_operand" "")
535         (plus:SI (match_operand:SI 1 "s_register_operand" "")
536                  (match_operand:SI 2 "const_int_operand"  "")))]
537   "TARGET_ARM &&
538    !(const_ok_for_arm (INTVAL (operands[2]))
539      || const_ok_for_arm (-INTVAL (operands[2])))
540     && const_ok_for_arm (~INTVAL (operands[2]))"
541   [(set (match_dup 3) (match_dup 2))
542    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
543   ""
544 )
545
546 (define_insn_and_split "*arm_addsi3"
547   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
548         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
549                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
550   "TARGET_ARM"
551   "@
552    add%?\\t%0, %1, %2
553    sub%?\\t%0, %1, #%n2
554    #"
555   "TARGET_ARM &&
556    GET_CODE (operands[2]) == CONST_INT
557    && !(const_ok_for_arm (INTVAL (operands[2]))
558         || const_ok_for_arm (-INTVAL (operands[2])))"
559   [(clobber (const_int 0))]
560   "
561   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
562                       operands[1], 0);
563   DONE;
564   "
565   [(set_attr "length" "4,4,16")
566    (set_attr "predicable" "yes")]
567 )
568
569 ;; Register group 'k' is a single register group containing only the stack
570 ;; register.  Trying to reload it will always fail catastrophically,
571 ;; so never allow those alternatives to match if reloading is needed.
572
573 (define_insn "*thumb_addsi3"
574   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
575         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
576                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
577   "TARGET_THUMB"
578   "*
579    static const char * const asms[] = 
580    {
581      \"add\\t%0, %0, %2\",
582      \"sub\\t%0, %0, #%n2\",
583      \"add\\t%0, %1, %2\",
584      \"add\\t%0, %0, %2\",
585      \"add\\t%0, %0, %2\",
586      \"add\\t%0, %1, %2\",
587      \"add\\t%0, %1, %2\"
588    };
589    if ((which_alternative == 2 || which_alternative == 6)
590        && GET_CODE (operands[2]) == CONST_INT
591        && INTVAL (operands[2]) < 0)
592      return \"sub\\t%0, %1, #%n2\";
593    return asms[which_alternative];
594   "
595   [(set_attr "length" "2")]
596 )
597
598 ;; Reloading and elimination of the frame pointer can
599 ;; sometimes cause this optimization to be missed.
600 (define_peephole2
601   [(set (match_operand:SI 0 "register_operand" "")
602         (match_operand:SI 1 "const_int_operand" ""))
603    (set (match_dup 0)
604         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
605   "TARGET_THUMB
606    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
607    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
608    && (INTVAL (operands[1]) & 3) == 0"
609   [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
610   ""
611 )
612
613 (define_insn "*addsi3_compare0"
614   [(set (reg:CC_NOOV CC_REGNUM)
615         (compare:CC_NOOV
616          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
617                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
618          (const_int 0)))
619    (set (match_operand:SI 0 "s_register_operand" "=r,r")
620         (plus:SI (match_dup 1) (match_dup 2)))]
621   "TARGET_ARM"
622   "@
623    add%?s\\t%0, %1, %2
624    sub%?s\\t%0, %1, #%n2"
625   [(set_attr "conds" "set")]
626 )
627
628 (define_insn "*addsi3_compare0_scratch"
629   [(set (reg:CC_NOOV CC_REGNUM)
630         (compare:CC_NOOV
631          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
632                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
633          (const_int 0)))]
634   "TARGET_ARM"
635   "@
636    cmn%?\\t%0, %1
637    cmp%?\\t%0, #%n1"
638   [(set_attr "conds" "set")]
639 )
640
641 ;; These patterns are the same ones as the two regular addsi3_compare0
642 ;; patterns, except we write them slightly different - the combiner
643 ;; tends to generate them this way.
644 (define_insn "*addsi3_compare0_for_combiner"
645   [(set (reg:CC CC_REGNUM)
646         (compare:CC
647          (match_operand:SI 1 "s_register_operand" "r,r")
648          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
649    (set (match_operand:SI 0 "s_register_operand" "=r,r")
650         (plus:SI (match_dup 1) (match_dup 2)))]
651   "TARGET_ARM"
652   "@
653    add%?s\\t%0, %1, %2
654    sub%?s\\t%0, %1, #%n2"
655   [(set_attr "conds" "set")]
656 )
657
658 (define_insn "*addsi3_compare0_scratch_for_combiner"
659   [(set (reg:CC CC_REGNUM)
660         (compare:CC
661          (match_operand:SI 0 "s_register_operand" "r,r")
662          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
663   "TARGET_ARM"
664   "@
665    cmn%?\\t%0, %1
666    cmp%?\\t%0, #%n1"
667   [(set_attr "conds" "set")]
668 )
669
670 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
671 ;; addend is a constant.
672 (define_insn "*cmpsi2_addneg"
673   [(set (reg:CC CC_REGNUM)
674         (compare:CC
675          (match_operand:SI 1 "s_register_operand" "r,r")
676          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
677    (set (match_operand:SI 0 "s_register_operand" "=r,r")
678         (plus:SI (match_dup 1)
679                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
680   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
681   "@
682    sub%?s\\t%0, %1, %2
683    add%?s\\t%0, %1, #%n2"
684   [(set_attr "conds" "set")]
685 )
686
687 ;; Convert the sequence
688 ;;  sub  rd, rn, #1
689 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
690 ;;  bne  dest
691 ;; into
692 ;;  subs rd, rn, #1
693 ;;  bcs  dest   ((unsigned)rn >= 1)
694 ;; similarly for the beq variant using bcc.
695 ;; This is a common looping idiom (while (n--))
696 (define_peephole2
697   [(set (match_operand:SI 0 "s_register_operand" "")
698         (plus:SI (match_operand:SI 1 "s_register_operand" "")
699                  (const_int -1)))
700    (set (match_operand 2 "cc_register" "")
701         (compare (match_dup 0) (const_int -1)))
702    (set (pc)
703         (if_then_else (match_operator 3 "equality_operator"
704                        [(match_dup 2) (const_int 0)])
705                       (match_operand 4 "" "")
706                       (match_operand 5 "" "")))]
707   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
708   [(parallel[
709     (set (match_dup 2)
710          (compare:CC
711           (match_dup 1) (const_int 1)))
712     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
713    (set (pc)
714         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
715                       (match_dup 4)
716                       (match_dup 5)))]
717   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
718    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
719                                   ? GEU : LTU),
720                                  VOIDmode, 
721                                  operands[2], const0_rtx);"
722 )
723
724 ;; The next four insns work because they compare the result with one of
725 ;; the operands, and we know that the use of the condition code is
726 ;; either GEU or LTU, so we can use the carry flag from the addition
727 ;; instead of doing the compare a second time.
728 (define_insn "*addsi3_compare_op1"
729   [(set (reg:CC_C CC_REGNUM)
730         (compare:CC_C
731          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
732                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
733          (match_dup 1)))
734    (set (match_operand:SI 0 "s_register_operand" "=r,r")
735         (plus:SI (match_dup 1) (match_dup 2)))]
736   "TARGET_ARM"
737   "@
738    add%?s\\t%0, %1, %2
739    sub%?s\\t%0, %1, #%n2"
740   [(set_attr "conds" "set")]
741 )
742
743 (define_insn "*addsi3_compare_op2"
744   [(set (reg:CC_C CC_REGNUM)
745         (compare:CC_C
746          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
747                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
748          (match_dup 2)))
749    (set (match_operand:SI 0 "s_register_operand" "=r,r")
750         (plus:SI (match_dup 1) (match_dup 2)))]
751   "TARGET_ARM"
752   "@
753    add%?s\\t%0, %1, %2
754    sub%?s\\t%0, %1, #%n2"
755   [(set_attr "conds" "set")]
756 )
757
758 (define_insn "*compare_addsi2_op0"
759   [(set (reg:CC_C CC_REGNUM)
760         (compare:CC_C
761          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
762                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
763          (match_dup 0)))]
764   "TARGET_ARM"
765   "@
766    cmn%?\\t%0, %1
767    cmp%?\\t%0, #%n1"
768   [(set_attr "conds" "set")]
769 )
770
771 (define_insn "*compare_addsi2_op1"
772   [(set (reg:CC_C CC_REGNUM)
773         (compare:CC_C
774          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
775                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
776          (match_dup 1)))]
777   "TARGET_ARM"
778   "@
779    cmn%?\\t%0, %1
780    cmp%?\\t%0, #%n1"
781   [(set_attr "conds" "set")]
782 )
783
784 (define_insn "*addsi3_carryin"
785   [(set (match_operand:SI 0 "s_register_operand" "=r")
786         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
787                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
788                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
789   "TARGET_ARM"
790   "adc%?\\t%0, %1, %2"
791   [(set_attr "conds" "use")]
792 )
793
794 (define_insn "*addsi3_carryin_shift"
795   [(set (match_operand:SI 0 "s_register_operand" "=r")
796         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
797                  (plus:SI
798                    (match_operator:SI 2 "shift_operator"
799                       [(match_operand:SI 3 "s_register_operand" "r")
800                        (match_operand:SI 4 "reg_or_int_operand" "rM")])
801                     (match_operand:SI 1 "s_register_operand" "r"))))]
802   "TARGET_ARM"
803   "adc%?\\t%0, %1, %3%S2"
804   [(set_attr "conds" "use")]
805 )
806
807 (define_insn "*addsi3_carryin_alt1"
808   [(set (match_operand:SI 0 "s_register_operand" "=r")
809         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
810                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
811                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
812   "TARGET_ARM"
813   "adc%?\\t%0, %1, %2"
814   [(set_attr "conds" "use")]
815 )
816
817 (define_insn "*addsi3_carryin_alt2"
818   [(set (match_operand:SI 0 "s_register_operand" "=r")
819         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
820                           (match_operand:SI 1 "s_register_operand" "r"))
821                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
822   "TARGET_ARM"
823   "adc%?\\t%0, %1, %2"
824   [(set_attr "conds" "use")]
825 )
826
827 (define_insn "*addsi3_carryin_alt3"
828   [(set (match_operand:SI 0 "s_register_operand" "=r")
829         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
830                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
831                  (match_operand:SI 1 "s_register_operand" "r")))]
832   "TARGET_ARM"
833   "adc%?\\t%0, %1, %2"
834   [(set_attr "conds" "use")]
835 )
836
837 (define_insn "incscc"
838   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
839         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
840                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
841                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
842   "TARGET_ARM"
843   "@
844   add%d2\\t%0, %1, #1
845   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
846   [(set_attr "conds" "use")
847    (set_attr "length" "4,8")]
848 )
849
850 ; transform ((x << y) - 1) to ~(~(x-1) << y)  Where X is a constant.
851 (define_split
852   [(set (match_operand:SI 0 "s_register_operand" "")
853         (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
854                             (match_operand:SI 2 "s_register_operand" ""))
855                  (const_int -1)))
856    (clobber (match_operand:SI 3 "s_register_operand" ""))]
857   "TARGET_ARM"
858   [(set (match_dup 3) (match_dup 1))
859    (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
860   "
861   operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
862 ")
863
864 (define_expand "addsf3"
865   [(set (match_operand:SF          0 "s_register_operand" "")
866         (plus:SF (match_operand:SF 1 "s_register_operand" "")
867                  (match_operand:SF 2 "fpa_add_operand" "")))]
868   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
869   "
870   if (TARGET_CIRRUS
871       && !cirrus_fp_register (operands[2], SFmode))
872     operands[2] = force_reg (SFmode, operands[2]);
873 ")
874
875 (define_expand "adddf3"
876   [(set (match_operand:DF          0 "s_register_operand" "")
877         (plus:DF (match_operand:DF 1 "s_register_operand" "")
878                  (match_operand:DF 2 "fpa_add_operand" "")))]
879   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
880   "
881   if (TARGET_CIRRUS
882       && !cirrus_fp_register (operands[2], DFmode))
883     operands[2] = force_reg (DFmode, operands[2]);
884 ")
885
886 (define_expand "subdi3"
887  [(parallel
888    [(set (match_operand:DI            0 "s_register_operand" "")
889           (minus:DI (match_operand:DI 1 "s_register_operand" "")
890                     (match_operand:DI 2 "s_register_operand" "")))
891     (clobber (reg:CC CC_REGNUM))])]
892   "TARGET_EITHER"
893   "
894   if (TARGET_CIRRUS
895       && TARGET_ARM
896       && cirrus_fp_register (operands[0], DImode)
897       && cirrus_fp_register (operands[1], DImode))
898     {
899       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
900       DONE;
901     }
902
903   if (TARGET_THUMB)
904     {
905       if (GET_CODE (operands[1]) != REG)
906         operands[1] = force_reg (SImode, operands[1]);
907       if (GET_CODE (operands[2]) != REG)
908         operands[2] = force_reg (SImode, operands[2]);
909      }  
910   "
911 )
912
913 (define_insn "*arm_subdi3"
914   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
915         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
916                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
917    (clobber (reg:CC CC_REGNUM))]
918   "TARGET_ARM"
919   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
920   [(set_attr "conds" "clob")
921    (set_attr "length" "8")]
922 )
923
924 (define_insn "*thumb_subdi3"
925   [(set (match_operand:DI           0 "register_operand" "=l")
926         (minus:DI (match_operand:DI 1 "register_operand"  "0")
927                   (match_operand:DI 2 "register_operand"  "l")))
928    (clobber (reg:CC CC_REGNUM))]
929   "TARGET_THUMB"
930   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
931   [(set_attr "length" "4")]
932 )
933
934 (define_insn "*subdi_di_zesidi"
935   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
936         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
937                   (zero_extend:DI
938                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
939    (clobber (reg:CC CC_REGNUM))]
940   "TARGET_ARM"
941   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
942   [(set_attr "conds" "clob")
943    (set_attr "length" "8")]
944 )
945
946 (define_insn "*subdi_di_sesidi"
947   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
948         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
949                   (sign_extend:DI
950                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
951    (clobber (reg:CC CC_REGNUM))]
952   "TARGET_ARM"
953   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
954   [(set_attr "conds" "clob")
955    (set_attr "length" "8")]
956 )
957
958 (define_insn "*subdi_zesidi_di"
959   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
960         (minus:DI (zero_extend:DI
961                    (match_operand:SI 2 "s_register_operand"  "r,r"))
962                   (match_operand:DI  1 "s_register_operand" "?r,0")))
963    (clobber (reg:CC CC_REGNUM))]
964   "TARGET_ARM"
965   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
966   [(set_attr "conds" "clob")
967    (set_attr "length" "8")]
968 )
969
970 (define_insn "*subdi_sesidi_di"
971   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
972         (minus:DI (sign_extend:DI
973                    (match_operand:SI 2 "s_register_operand"   "r,r"))
974                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
975    (clobber (reg:CC CC_REGNUM))]
976   "TARGET_ARM"
977   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
978   [(set_attr "conds" "clob")
979    (set_attr "length" "8")]
980 )
981
982 (define_insn "*subdi_zesidi_zesidi"
983   [(set (match_operand:DI            0 "s_register_operand" "=r")
984         (minus:DI (zero_extend:DI
985                    (match_operand:SI 1 "s_register_operand"  "r"))
986                   (zero_extend:DI
987                    (match_operand:SI 2 "s_register_operand"  "r"))))
988    (clobber (reg:CC CC_REGNUM))]
989   "TARGET_ARM"
990   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
991   [(set_attr "conds" "clob")
992    (set_attr "length" "8")]
993 )
994
995 (define_expand "subsi3"
996   [(set (match_operand:SI           0 "s_register_operand" "")
997         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
998                   (match_operand:SI 2 "s_register_operand" "")))]
999   "TARGET_EITHER"
1000   "
1001   if (GET_CODE (operands[1]) == CONST_INT)
1002     {
1003       if (TARGET_ARM)
1004         {
1005           arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1006                               operands[2],
1007                               (no_new_pseudos ? 0
1008                                :  preserve_subexpressions_p ()));
1009           DONE;
1010         }
1011       else /* TARGET_THUMB */
1012         operands[1] = force_reg (SImode, operands[1]);
1013     }
1014   "
1015 )
1016
1017 (define_insn "*thumb_subsi3_insn"
1018   [(set (match_operand:SI           0 "register_operand" "=l")
1019         (minus:SI (match_operand:SI 1 "register_operand" "l")
1020                   (match_operand:SI 2 "register_operand" "l")))]
1021   "TARGET_THUMB"
1022   "sub\\t%0, %1, %2"
1023   [(set_attr "length" "2")]
1024 )
1025
1026 (define_insn_and_split "*arm_subsi3_insn"
1027   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
1028         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1029                   (match_operand:SI 2 "s_register_operand" "r,r")))]
1030   "TARGET_ARM"
1031   "@
1032    rsb%?\\t%0, %2, %1
1033    #"
1034   "TARGET_ARM
1035    && GET_CODE (operands[1]) == CONST_INT
1036    && !const_ok_for_arm (INTVAL (operands[1]))"
1037   [(clobber (const_int 0))]
1038   "
1039   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1040                       operands[2], 0);
1041   DONE;
1042   "
1043   [(set_attr "length" "4,16")
1044    (set_attr "predicable" "yes")]
1045 )
1046
1047 (define_peephole2
1048   [(match_scratch:SI 3 "r")
1049    (set (match_operand:SI           0 "s_register_operand" "")
1050         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1051                   (match_operand:SI 2 "s_register_operand" "")))]
1052   "TARGET_ARM
1053    && !const_ok_for_arm (INTVAL (operands[1]))
1054    && const_ok_for_arm (~INTVAL (operands[1]))"
1055   [(set (match_dup 3) (match_dup 1))
1056    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1057   ""
1058 )
1059
1060 (define_insn "*subsi3_compare0"
1061   [(set (reg:CC_NOOV CC_REGNUM)
1062         (compare:CC_NOOV
1063          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1064                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1065          (const_int 0)))
1066    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1067         (minus:SI (match_dup 1) (match_dup 2)))]
1068   "TARGET_ARM"
1069   "@
1070    sub%?s\\t%0, %1, %2
1071    rsb%?s\\t%0, %2, %1"
1072   [(set_attr "conds" "set")]
1073 )
1074
1075 (define_insn "decscc"
1076   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1077         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1078                   (match_operator:SI 2 "arm_comparison_operator"
1079                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1080   "TARGET_ARM"
1081   "@
1082    sub%d2\\t%0, %1, #1
1083    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1084   [(set_attr "conds" "use")
1085    (set_attr "length" "*,8")]
1086 )
1087
1088 (define_expand "subsf3"
1089   [(set (match_operand:SF           0 "s_register_operand" "")
1090         (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1091                   (match_operand:SF 2 "fpa_rhs_operand" "")))]
1092   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1093   "
1094   if (TARGET_CIRRUS)
1095     {
1096       if (!cirrus_fp_register (operands[1], SFmode))
1097         operands[1] = force_reg (SFmode, operands[1]);
1098       if (!cirrus_fp_register (operands[2], SFmode))
1099         operands[2] = force_reg (SFmode, operands[2]);
1100     }
1101 ")
1102
1103 (define_expand "subdf3"
1104   [(set (match_operand:DF           0 "s_register_operand" "")
1105         (minus:DF (match_operand:DF 1 "fpa_rhs_operand"     "")
1106                   (match_operand:DF 2 "fpa_rhs_operand"    "")))]
1107   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1108   "
1109   if (TARGET_CIRRUS)
1110     {
1111        if (!cirrus_fp_register (operands[1], DFmode))
1112          operands[1] = force_reg (DFmode, operands[1]);
1113        if (!cirrus_fp_register (operands[2], DFmode))
1114          operands[2] = force_reg (DFmode, operands[2]);
1115     }
1116 ")
1117
1118 \f
1119 ;; Multiplication insns
1120
1121 (define_expand "mulsi3"
1122   [(set (match_operand:SI          0 "s_register_operand" "")
1123         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1124                  (match_operand:SI 1 "s_register_operand" "")))]
1125   "TARGET_EITHER"
1126   ""
1127 )
1128
1129 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1130 (define_insn "*arm_mulsi3"
1131   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1132         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1133                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1134   "TARGET_ARM"
1135   "mul%?\\t%0, %2, %1"
1136   [(set_attr "type" "mult")
1137    (set_attr "predicable" "yes")]
1138 )
1139
1140 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1141 ; 1 and 2; are the same, because reload will make operand 0 match 
1142 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1143 ; this by adding another alternative to match this case, and then `reload' 
1144 ; it ourselves.  This alternative must come first.
1145 (define_insn "*thumb_mulsi3"
1146   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1147         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1148                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1149   "TARGET_THUMB"
1150   "*
1151   if (which_alternative < 2)
1152     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1153   else
1154     return \"mul\\t%0, %0, %2\";
1155   "
1156   [(set_attr "length" "4,4,2")
1157    (set_attr "type" "mult")]
1158 )
1159
1160 (define_insn "*mulsi3_compare0"
1161   [(set (reg:CC_NOOV CC_REGNUM)
1162         (compare:CC_NOOV (mult:SI
1163                           (match_operand:SI 2 "s_register_operand" "r,r")
1164                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1165                          (const_int 0)))
1166    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1167         (mult:SI (match_dup 2) (match_dup 1)))]
1168   "TARGET_ARM && !arm_arch_xscale"
1169   "mul%?s\\t%0, %2, %1"
1170   [(set_attr "conds" "set")
1171    (set_attr "type" "mult")]
1172 )
1173
1174 (define_insn "*mulsi_compare0_scratch"
1175   [(set (reg:CC_NOOV CC_REGNUM)
1176         (compare:CC_NOOV (mult:SI
1177                           (match_operand:SI 2 "s_register_operand" "r,r")
1178                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1179                          (const_int 0)))
1180    (clobber (match_scratch:SI 0 "=&r,&r"))]
1181   "TARGET_ARM && !arm_arch_xscale"
1182   "mul%?s\\t%0, %2, %1"
1183   [(set_attr "conds" "set")
1184    (set_attr "type" "mult")]
1185 )
1186
1187 ;; Unnamed templates to match MLA instruction.
1188
1189 (define_insn "*mulsi3addsi"
1190   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1191         (plus:SI
1192           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1193                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1194           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1195   "TARGET_ARM"
1196   "mla%?\\t%0, %2, %1, %3"
1197   [(set_attr "type" "mult")
1198    (set_attr "predicable" "yes")]
1199 )
1200
1201 (define_insn "*mulsi3addsi_compare0"
1202   [(set (reg:CC_NOOV CC_REGNUM)
1203         (compare:CC_NOOV
1204          (plus:SI (mult:SI
1205                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1206                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1207                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1208          (const_int 0)))
1209    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1210         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1211                  (match_dup 3)))]
1212   "TARGET_ARM && !arm_arch_xscale"
1213   "mla%?s\\t%0, %2, %1, %3"
1214   [(set_attr "conds" "set")
1215    (set_attr "type" "mult")]
1216 )
1217
1218 (define_insn "*mulsi3addsi_compare0_scratch"
1219   [(set (reg:CC_NOOV CC_REGNUM)
1220         (compare:CC_NOOV
1221          (plus:SI (mult:SI
1222                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1223                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1224                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1225          (const_int 0)))
1226    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1227   "TARGET_ARM && !arm_arch_xscale"
1228   "mla%?s\\t%0, %2, %1, %3"
1229   [(set_attr "conds" "set")
1230    (set_attr "type" "mult")]
1231 )
1232
1233 ;; Unnamed template to match long long multiply-accumulate (smlal)
1234
1235 (define_insn "*mulsidi3adddi"
1236   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1237         (plus:DI
1238          (mult:DI
1239           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1240           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1241          (match_operand:DI 1 "s_register_operand" "0")))]
1242   "TARGET_ARM && arm_fast_multiply"
1243   "smlal%?\\t%Q0, %R0, %3, %2"
1244   [(set_attr "type" "mult")
1245    (set_attr "predicable" "yes")]
1246 )
1247
1248 (define_insn "mulsidi3"
1249   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1250         (mult:DI
1251          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1252          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1253   "TARGET_ARM && arm_fast_multiply"
1254   "smull%?\\t%Q0, %R0, %1, %2"
1255   [(set_attr "type" "mult")
1256    (set_attr "predicable" "yes")]
1257 )
1258
1259 (define_insn "umulsidi3"
1260   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1261         (mult:DI
1262          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1263          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1264   "TARGET_ARM && arm_fast_multiply"
1265   "umull%?\\t%Q0, %R0, %1, %2"
1266   [(set_attr "type" "mult")
1267    (set_attr "predicable" "yes")]
1268 )
1269
1270 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1271
1272 (define_insn "*umulsidi3adddi"
1273   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1274         (plus:DI
1275          (mult:DI
1276           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1277           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1278          (match_operand:DI 1 "s_register_operand" "0")))]
1279   "TARGET_ARM && arm_fast_multiply"
1280   "umlal%?\\t%Q0, %R0, %3, %2"
1281   [(set_attr "type" "mult")
1282    (set_attr "predicable" "yes")]
1283 )
1284
1285 (define_insn "smulsi3_highpart"
1286   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1287         (truncate:SI
1288          (lshiftrt:DI
1289           (mult:DI
1290            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1291            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1292           (const_int 32))))
1293    (clobber (match_scratch:SI 3 "=&r,&r"))]
1294   "TARGET_ARM && arm_fast_multiply"
1295   "smull%?\\t%3, %0, %2, %1"
1296   [(set_attr "type" "mult")
1297    (set_attr "predicable" "yes")]
1298 )
1299
1300 (define_insn "umulsi3_highpart"
1301   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1302         (truncate:SI
1303          (lshiftrt:DI
1304           (mult:DI
1305            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1306            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1307           (const_int 32))))
1308    (clobber (match_scratch:SI 3 "=&r,&r"))]
1309   "TARGET_ARM && arm_fast_multiply"
1310   "umull%?\\t%3, %0, %2, %1"
1311   [(set_attr "type" "mult")
1312    (set_attr "predicable" "yes")]
1313 )
1314
1315 (define_insn "mulhisi3"
1316   [(set (match_operand:SI 0 "s_register_operand" "=r")
1317         (mult:SI (sign_extend:SI
1318                   (match_operand:HI 1 "s_register_operand" "%r"))
1319                  (sign_extend:SI
1320                   (match_operand:HI 2 "s_register_operand" "r"))))]
1321   "TARGET_ARM && arm_arch5e"
1322   "smulbb%?\\t%0, %1, %2"
1323   [(set_attr "type" "mult")
1324    (set_attr "predicable" "yes")]
1325 )
1326
1327 (define_insn "*mulhisi3tb"
1328   [(set (match_operand:SI 0 "s_register_operand" "=r")
1329         (mult:SI (ashiftrt:SI
1330                   (match_operand:SI 1 "s_register_operand" "r")
1331                   (const_int 16))
1332                  (sign_extend:SI
1333                   (match_operand:HI 2 "s_register_operand" "r"))))]
1334   "TARGET_ARM && arm_arch5e"
1335   "smultb%?\\t%0, %1, %2"
1336   [(set_attr "type" "mult")
1337    (set_attr "predicable" "yes")]
1338 )
1339
1340 (define_insn "*mulhisi3bt"
1341   [(set (match_operand:SI 0 "s_register_operand" "=r")
1342         (mult:SI (sign_extend:SI
1343                   (match_operand:HI 1 "s_register_operand" "r"))
1344                  (ashiftrt:SI
1345                   (match_operand:SI 2 "s_register_operand" "r")
1346                   (const_int 16))))]
1347   "TARGET_ARM && arm_arch5e"
1348   "smulbt%?\\t%0, %1, %2"
1349   [(set_attr "type" "mult")
1350    (set_attr "predicable" "yes")]
1351 )
1352
1353 (define_insn "*mulhisi3tt"
1354   [(set (match_operand:SI 0 "s_register_operand" "=r")
1355         (mult:SI (ashiftrt:SI
1356                   (match_operand:SI 1 "s_register_operand" "r")
1357                   (const_int 16))
1358                  (ashiftrt:SI
1359                   (match_operand:SI 2 "s_register_operand" "r")
1360                   (const_int 16))))]
1361   "TARGET_ARM && arm_arch5e"
1362   "smultt%?\\t%0, %1, %2"
1363   [(set_attr "type" "mult")
1364    (set_attr "predicable" "yes")]
1365 )
1366
1367 (define_insn "*mulhisi3addsi"
1368   [(set (match_operand:SI 0 "s_register_operand" "=r")
1369         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1370                  (mult:SI (sign_extend:SI
1371                            (match_operand:HI 2 "s_register_operand" "%r"))
1372                           (sign_extend:SI
1373                            (match_operand:HI 3 "s_register_operand" "r")))))]
1374   "TARGET_ARM && arm_arch5e"
1375   "smlabb%?\\t%0, %2, %3, %1"
1376   [(set_attr "type" "mult")
1377    (set_attr "predicable" "yes")]
1378 )
1379
1380 (define_insn "*mulhidi3adddi"
1381   [(set (match_operand:DI 0 "s_register_operand" "=r")
1382         (plus:DI
1383           (match_operand:DI 1 "s_register_operand" "0")
1384           (mult:DI (sign_extend:DI
1385                     (match_operand:HI 2 "s_register_operand" "%r"))
1386                    (sign_extend:DI
1387                     (match_operand:HI 3 "s_register_operand" "r")))))]
1388   "TARGET_ARM && arm_arch5e"
1389   "smlalbb%?\\t%Q0, %R0, %2, %3"
1390   [(set_attr "type" "mult")
1391    (set_attr "predicable" "yes")])
1392
1393 (define_expand "mulsf3"
1394   [(set (match_operand:SF          0 "s_register_operand" "")
1395         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1396                  (match_operand:SF 2 "fpa_rhs_operand" "")))]
1397   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1398   "
1399   if (TARGET_CIRRUS
1400       && !cirrus_fp_register (operands[2], SFmode))
1401     operands[2] = force_reg (SFmode, operands[2]);
1402 ")
1403
1404 (define_expand "muldf3"
1405   [(set (match_operand:DF          0 "s_register_operand" "")
1406         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1407                  (match_operand:DF 2 "fpa_rhs_operand" "")))]
1408   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1409   "
1410   if (TARGET_CIRRUS
1411       && !cirrus_fp_register (operands[2], DFmode))
1412     operands[2] = force_reg (DFmode, operands[2]);
1413 ")
1414 \f
1415 ;; Division insns
1416
1417 (define_expand "divsf3"
1418   [(set (match_operand:SF 0 "s_register_operand" "")
1419         (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1420                 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1421   "TARGET_ARM && TARGET_HARD_FLOAT"
1422   "")
1423
1424 (define_expand "divdf3"
1425   [(set (match_operand:DF 0 "s_register_operand" "")
1426         (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1427                 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1428   "TARGET_ARM && TARGET_HARD_FLOAT"
1429   "")
1430 \f
1431 ;; Modulo insns
1432
1433 (define_expand "modsf3"
1434   [(set (match_operand:SF 0 "s_register_operand" "")
1435         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1436                 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1437   "TARGET_ARM && TARGET_HARD_FLOAT"
1438   "")
1439
1440 (define_expand "moddf3"
1441   [(set (match_operand:DF 0 "s_register_operand" "")
1442         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1443                 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1444   "TARGET_ARM && TARGET_HARD_FLOAT"
1445   "")
1446 \f
1447 ;; Boolean and,ior,xor insns
1448
1449 ;; Split up double word logical operations
1450
1451 ;; Split up simple DImode logical operations.  Simply perform the logical
1452 ;; operation on the upper and lower halves of the registers.
1453 (define_split
1454   [(set (match_operand:DI 0 "s_register_operand" "")
1455         (match_operator:DI 6 "logical_binary_operator"
1456           [(match_operand:DI 1 "s_register_operand" "")
1457            (match_operand:DI 2 "s_register_operand" "")]))]
1458   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1459   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1460    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1461   "
1462   {
1463     operands[3] = gen_highpart (SImode, operands[0]);
1464     operands[0] = gen_lowpart (SImode, operands[0]);
1465     operands[4] = gen_highpart (SImode, operands[1]);
1466     operands[1] = gen_lowpart (SImode, operands[1]);
1467     operands[5] = gen_highpart (SImode, operands[2]);
1468     operands[2] = gen_lowpart (SImode, operands[2]);
1469   }"
1470 )
1471
1472 (define_split
1473   [(set (match_operand:DI 0 "s_register_operand" "")
1474         (match_operator:DI 6 "logical_binary_operator"
1475           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1476            (match_operand:DI 1 "s_register_operand" "")]))]
1477   "TARGET_ARM && reload_completed"
1478   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1479    (set (match_dup 3) (match_op_dup:SI 6
1480                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1481                          (match_dup 4)]))]
1482   "
1483   {
1484     operands[3] = gen_highpart (SImode, operands[0]);
1485     operands[0] = gen_lowpart (SImode, operands[0]);
1486     operands[4] = gen_highpart (SImode, operands[1]);
1487     operands[1] = gen_lowpart (SImode, operands[1]);
1488     operands[5] = gen_highpart (SImode, operands[2]);
1489     operands[2] = gen_lowpart (SImode, operands[2]);
1490   }"
1491 )
1492
1493 ;; The zero extend of operand 2 means we can just copy the high part of
1494 ;; operand1 into operand0.
1495 (define_split
1496   [(set (match_operand:DI 0 "s_register_operand" "")
1497         (ior:DI
1498           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1499           (match_operand:DI 1 "s_register_operand" "")))]
1500   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1501   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1502    (set (match_dup 3) (match_dup 4))]
1503   "
1504   {
1505     operands[4] = gen_highpart (SImode, operands[1]);
1506     operands[3] = gen_highpart (SImode, operands[0]);
1507     operands[0] = gen_lowpart (SImode, operands[0]);
1508     operands[1] = gen_lowpart (SImode, operands[1]);
1509   }"
1510 )
1511
1512 ;; The zero extend of operand 2 means we can just copy the high part of
1513 ;; operand1 into operand0.
1514 (define_split
1515   [(set (match_operand:DI 0 "s_register_operand" "")
1516         (xor:DI
1517           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1518           (match_operand:DI 1 "s_register_operand" "")))]
1519   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1520   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1521    (set (match_dup 3) (match_dup 4))]
1522   "
1523   {
1524     operands[4] = gen_highpart (SImode, operands[1]);
1525     operands[3] = gen_highpart (SImode, operands[0]);
1526     operands[0] = gen_lowpart (SImode, operands[0]);
1527     operands[1] = gen_lowpart (SImode, operands[1]);
1528   }"
1529 )
1530
1531 (define_insn "anddi3"
1532   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1533         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1534                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1535   "TARGET_ARM && ! TARGET_IWMMXT"
1536   "#"
1537   [(set_attr "length" "8")]
1538 )
1539
1540 (define_insn_and_split "*anddi_zesidi_di"
1541   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1542         (and:DI (zero_extend:DI
1543                  (match_operand:SI 2 "s_register_operand" "r,r"))
1544                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1545   "TARGET_ARM"
1546   "#"
1547   "TARGET_ARM && reload_completed"
1548   ; The zero extend of operand 2 clears the high word of the output
1549   ; operand.
1550   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1551    (set (match_dup 3) (const_int 0))]
1552   "
1553   {
1554     operands[3] = gen_highpart (SImode, operands[0]);
1555     operands[0] = gen_lowpart (SImode, operands[0]);
1556     operands[1] = gen_lowpart (SImode, operands[1]);
1557   }"
1558   [(set_attr "length" "8")]
1559 )
1560
1561 (define_insn "*anddi_sesdi_di"
1562   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1563         (and:DI (sign_extend:DI
1564                  (match_operand:SI 2 "s_register_operand" "r,r"))
1565                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1566   "TARGET_ARM"
1567   "#"
1568   [(set_attr "length" "8")]
1569 )
1570
1571 (define_expand "andsi3"
1572   [(set (match_operand:SI         0 "s_register_operand" "")
1573         (and:SI (match_operand:SI 1 "s_register_operand" "")
1574                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1575   "TARGET_EITHER"
1576   "
1577   if (TARGET_ARM)
1578     {
1579       if (GET_CODE (operands[2]) == CONST_INT)
1580         {
1581           arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1582                               operands[1],
1583                               (no_new_pseudos
1584                                ? 0 : preserve_subexpressions_p ()));
1585           DONE;
1586         }
1587     }
1588   else /* TARGET_THUMB */
1589     {
1590       if (GET_CODE (operands[2]) != CONST_INT)
1591         operands[2] = force_reg (SImode, operands[2]);
1592       else
1593         {
1594           int i;
1595           
1596           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1597             {
1598               operands[2] = force_reg (SImode,
1599                                        GEN_INT (~INTVAL (operands[2])));
1600               
1601               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1602               
1603               DONE;
1604             }
1605
1606           for (i = 9; i <= 31; i++)
1607             {
1608               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1609                 {
1610                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1611                                         const0_rtx));
1612                   DONE;
1613                 }
1614               else if ((((HOST_WIDE_INT) 1) << i) - 1
1615                        == ~INTVAL (operands[2]))
1616                 {
1617                   rtx shift = GEN_INT (i);
1618                   rtx reg = gen_reg_rtx (SImode);
1619                 
1620                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1621                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1622                   
1623                   DONE;
1624                 }
1625             }
1626
1627           operands[2] = force_reg (SImode, operands[2]);
1628         }
1629     }
1630   "
1631 )
1632
1633 (define_insn_and_split "*arm_andsi3_insn"
1634   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1635         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1636                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1637   "TARGET_ARM"
1638   "@
1639    and%?\\t%0, %1, %2
1640    bic%?\\t%0, %1, #%B2
1641    #"
1642   "TARGET_ARM
1643    && GET_CODE (operands[2]) == CONST_INT
1644    && !(const_ok_for_arm (INTVAL (operands[2]))
1645         || const_ok_for_arm (~INTVAL (operands[2])))"
1646   [(clobber (const_int 0))]
1647   "
1648   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1649                        operands[1], 0);
1650   DONE;
1651   "
1652   [(set_attr "length" "4,4,16")
1653    (set_attr "predicable" "yes")]
1654 )
1655
1656 (define_insn "*thumb_andsi3_insn"
1657   [(set (match_operand:SI         0 "register_operand" "=l")
1658         (and:SI (match_operand:SI 1 "register_operand" "%0")
1659                 (match_operand:SI 2 "register_operand" "l")))]
1660   "TARGET_THUMB"
1661   "and\\t%0, %0, %2"
1662   [(set_attr "length" "2")]
1663 )
1664
1665 (define_insn "*andsi3_compare0"
1666   [(set (reg:CC_NOOV CC_REGNUM)
1667         (compare:CC_NOOV
1668          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1669                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1670          (const_int 0)))
1671    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1672         (and:SI (match_dup 1) (match_dup 2)))]
1673   "TARGET_ARM"
1674   "@
1675    and%?s\\t%0, %1, %2
1676    bic%?s\\t%0, %1, #%B2"
1677   [(set_attr "conds" "set")]
1678 )
1679
1680 (define_insn "*andsi3_compare0_scratch"
1681   [(set (reg:CC_NOOV CC_REGNUM)
1682         (compare:CC_NOOV
1683          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1684                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1685          (const_int 0)))
1686    (clobber (match_scratch:SI 2 "=X,r"))]
1687   "TARGET_ARM"
1688   "@
1689    tst%?\\t%0, %1
1690    bic%?s\\t%2, %0, #%B1"
1691   [(set_attr "conds" "set")]
1692 )
1693
1694 (define_insn "*zeroextractsi_compare0_scratch"
1695   [(set (reg:CC_NOOV CC_REGNUM)
1696         (compare:CC_NOOV (zero_extract:SI
1697                           (match_operand:SI 0 "s_register_operand" "r")
1698                           (match_operand 1 "const_int_operand" "n")
1699                           (match_operand 2 "const_int_operand" "n"))
1700                          (const_int 0)))]
1701   "TARGET_ARM
1702   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1703       && INTVAL (operands[1]) > 0 
1704       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1705       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1706   "*
1707   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1708                          << INTVAL (operands[2]));
1709   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1710   return \"\";
1711   "
1712   [(set_attr "conds" "set")]
1713 )
1714
1715 (define_insn "*ne_zeroextractsi"
1716   [(set (match_operand:SI 0 "s_register_operand" "=r")
1717         (ne:SI (zero_extract:SI
1718                 (match_operand:SI 1 "s_register_operand" "r")
1719                 (match_operand:SI 2 "const_int_operand" "n")
1720                 (match_operand:SI 3 "const_int_operand" "n"))
1721                (const_int 0)))
1722    (clobber (reg:CC CC_REGNUM))]
1723   "TARGET_ARM
1724    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1725        && INTVAL (operands[2]) > 0 
1726        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1727        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1728   "*
1729   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1730                          << INTVAL (operands[3]));
1731   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1732   return \"movne\\t%0, #1\";
1733   "
1734   [(set_attr "conds" "clob")
1735    (set_attr "length" "8")]
1736 )
1737
1738 (define_split
1739   [(set (match_operand:SI 0 "s_register_operand" "")
1740         (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1741                          (match_operand:SI 2 "const_int_operand" "")
1742                          (match_operand:SI 3 "const_int_operand" "")))
1743    (clobber (match_operand:SI 4 "s_register_operand" ""))]
1744   "TARGET_THUMB"
1745   [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1746    (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1747   "{
1748      HOST_WIDE_INT temp = INTVAL (operands[2]);
1749
1750      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1751      operands[3] = GEN_INT (32 - temp);
1752    }"
1753 )
1754
1755 (define_split
1756   [(set (match_operand:SI 0 "s_register_operand" "")
1757         (match_operator:SI 1 "shiftable_operator"
1758          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1759                            (match_operand:SI 3 "const_int_operand" "")
1760                            (match_operand:SI 4 "const_int_operand" ""))
1761           (match_operand:SI 5 "s_register_operand" "")]))
1762    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1763   "TARGET_ARM"
1764   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1765    (set (match_dup 0)
1766         (match_op_dup 1
1767          [(lshiftrt:SI (match_dup 6) (match_dup 4))
1768           (match_dup 5)]))]
1769   "{
1770      HOST_WIDE_INT temp = INTVAL (operands[3]);
1771
1772      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1773      operands[4] = GEN_INT (32 - temp);
1774    }"
1775 )
1776   
1777 (define_split
1778   [(set (match_operand:SI 0 "s_register_operand" "")
1779         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1780                          (match_operand:SI 2 "const_int_operand" "")
1781                          (match_operand:SI 3 "const_int_operand" "")))]
1782   "TARGET_THUMB"
1783   [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1784    (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1785   "{
1786      HOST_WIDE_INT temp = INTVAL (operands[2]);
1787
1788      operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1789      operands[3] = GEN_INT (32 - temp);
1790    }"
1791 )
1792
1793 (define_split
1794   [(set (match_operand:SI 0 "s_register_operand" "")
1795         (match_operator:SI 1 "shiftable_operator"
1796          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1797                            (match_operand:SI 3 "const_int_operand" "")
1798                            (match_operand:SI 4 "const_int_operand" ""))
1799           (match_operand:SI 5 "s_register_operand" "")]))
1800    (clobber (match_operand:SI 6 "s_register_operand" ""))]
1801   "TARGET_ARM"
1802   [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1803    (set (match_dup 0)
1804         (match_op_dup 1
1805          [(ashiftrt:SI (match_dup 6) (match_dup 4))
1806           (match_dup 5)]))]
1807   "{
1808      HOST_WIDE_INT temp = INTVAL (operands[3]);
1809
1810      operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1811      operands[4] = GEN_INT (32 - temp);
1812    }"
1813 )
1814   
1815 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1816 ;;; represented by the bitfield, then this will produce incorrect results.
1817 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1818 ;;; which have a real bit-field insert instruction, the truncation happens
1819 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1820 ;;; bit-field insert instruction, we would have to emit code here to truncate
1821 ;;; the value before we insert.  This loses some of the advantage of having
1822 ;;; this insv pattern, so this pattern needs to be reevalutated.
1823
1824 (define_expand "insv"
1825   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1826                          (match_operand:SI 1 "general_operand" "")
1827                          (match_operand:SI 2 "general_operand" ""))
1828         (match_operand:SI 3 "reg_or_int_operand" ""))]
1829   "TARGET_ARM"
1830   "
1831   {
1832     int start_bit = INTVAL (operands[2]);
1833     int width = INTVAL (operands[1]);
1834     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1835     rtx target, subtarget;
1836
1837     target = operands[0];
1838     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1839        subreg as the final target.  */
1840     if (GET_CODE (target) == SUBREG)
1841       {
1842         subtarget = gen_reg_rtx (SImode);
1843         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1844             < GET_MODE_SIZE (SImode))
1845           target = SUBREG_REG (target);
1846       }
1847     else
1848       subtarget = target;    
1849
1850     if (GET_CODE (operands[3]) == CONST_INT)
1851       {
1852         /* Since we are inserting a known constant, we may be able to
1853            reduce the number of bits that we have to clear so that
1854            the mask becomes simple.  */
1855         /* ??? This code does not check to see if the new mask is actually
1856            simpler.  It may not be.  */
1857         rtx op1 = gen_reg_rtx (SImode);
1858         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1859            start of this pattern.  */
1860         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1861         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1862
1863         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1864         emit_insn (gen_iorsi3 (subtarget, op1,
1865                                GEN_INT (op3_value << start_bit)));
1866       }
1867     else if (start_bit == 0
1868              && !(const_ok_for_arm (mask)
1869                   || const_ok_for_arm (~mask)))
1870       {
1871         /* A Trick, since we are setting the bottom bits in the word,
1872            we can shift operand[3] up, operand[0] down, OR them together
1873            and rotate the result back again.  This takes 3 insns, and
1874            the third might be mergeable into another op.  */
1875         /* The shift up copes with the possibility that operand[3] is
1876            wider than the bitfield.  */
1877         rtx op0 = gen_reg_rtx (SImode);
1878         rtx op1 = gen_reg_rtx (SImode);
1879
1880         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1881         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1882         emit_insn (gen_iorsi3  (op1, op1, op0));
1883         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1884       }
1885     else if ((width + start_bit == 32)
1886              && !(const_ok_for_arm (mask)
1887                   || const_ok_for_arm (~mask)))
1888       {
1889         /* Similar trick, but slightly less efficient.  */
1890
1891         rtx op0 = gen_reg_rtx (SImode);
1892         rtx op1 = gen_reg_rtx (SImode);
1893
1894         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1895         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1896         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1897         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1898       }
1899     else
1900       {
1901         rtx op0 = GEN_INT (mask);
1902         rtx op1 = gen_reg_rtx (SImode);
1903         rtx op2 = gen_reg_rtx (SImode);
1904
1905         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1906           {
1907             rtx tmp = gen_reg_rtx (SImode);
1908
1909             emit_insn (gen_movsi (tmp, op0));
1910             op0 = tmp;
1911           }
1912
1913         /* Mask out any bits in operand[3] that are not needed.  */
1914            emit_insn (gen_andsi3 (op1, operands[3], op0));
1915
1916         if (GET_CODE (op0) == CONST_INT
1917             && (const_ok_for_arm (mask << start_bit)
1918                 || const_ok_for_arm (~(mask << start_bit))))
1919           {
1920             op0 = GEN_INT (~(mask << start_bit));
1921             emit_insn (gen_andsi3 (op2, operands[0], op0));
1922           }
1923         else
1924           {
1925             if (GET_CODE (op0) == CONST_INT)
1926               {
1927                 rtx tmp = gen_reg_rtx (SImode);
1928
1929                 emit_insn (gen_movsi (tmp, op0));
1930                 op0 = tmp;
1931               }
1932
1933             if (start_bit != 0)
1934               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1935             
1936             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1937           }
1938
1939         if (start_bit != 0)
1940           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1941
1942         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1943       }
1944
1945     if (subtarget != target)
1946       {
1947         /* If TARGET is still a SUBREG, then it must be wider than a word,
1948            so we must be careful only to set the subword we were asked to.  */
1949         if (GET_CODE (target) == SUBREG)
1950           emit_move_insn (target, subtarget);
1951         else
1952           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1953       }
1954
1955     DONE;
1956   }"
1957 )
1958
1959 ; constants for op 2 will never be given to these patterns.
1960 (define_insn_and_split "*anddi_notdi_di"
1961   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1962         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1963                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1964   "TARGET_ARM"
1965   "#"
1966   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1967   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1968    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1969   "
1970   {
1971     operands[3] = gen_highpart (SImode, operands[0]);
1972     operands[0] = gen_lowpart (SImode, operands[0]);
1973     operands[4] = gen_highpart (SImode, operands[1]);
1974     operands[1] = gen_lowpart (SImode, operands[1]);
1975     operands[5] = gen_highpart (SImode, operands[2]);
1976     operands[2] = gen_lowpart (SImode, operands[2]);
1977   }"
1978   [(set_attr "length" "8")
1979    (set_attr "predicable" "yes")]
1980 )
1981   
1982 (define_insn_and_split "*anddi_notzesidi_di"
1983   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1984         (and:DI (not:DI (zero_extend:DI
1985                          (match_operand:SI 2 "s_register_operand" "r,r")))
1986                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1987   "TARGET_ARM"
1988   "@
1989    bic%?\\t%Q0, %Q1, %2
1990    #"
1991   ; (not (zero_extend ...)) allows us to just copy the high word from
1992   ; operand1 to operand0.
1993   "TARGET_ARM
1994    && reload_completed
1995    && operands[0] != operands[1]"
1996   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1997    (set (match_dup 3) (match_dup 4))]
1998   "
1999   {
2000     operands[3] = gen_highpart (SImode, operands[0]);
2001     operands[0] = gen_lowpart (SImode, operands[0]);
2002     operands[4] = gen_highpart (SImode, operands[1]);
2003     operands[1] = gen_lowpart (SImode, operands[1]);
2004   }"
2005   [(set_attr "length" "4,8")
2006    (set_attr "predicable" "yes")]
2007 )
2008   
2009 (define_insn_and_split "*anddi_notsesidi_di"
2010   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2011         (and:DI (not:DI (sign_extend:DI
2012                          (match_operand:SI 2 "s_register_operand" "r,r")))
2013                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2014   "TARGET_ARM"
2015   "#"
2016   "TARGET_ARM && reload_completed"
2017   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2018    (set (match_dup 3) (and:SI (not:SI
2019                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2020                                (match_dup 4)))]
2021   "
2022   {
2023     operands[3] = gen_highpart (SImode, operands[0]);
2024     operands[0] = gen_lowpart (SImode, operands[0]);
2025     operands[4] = gen_highpart (SImode, operands[1]);
2026     operands[1] = gen_lowpart (SImode, operands[1]);
2027   }"
2028   [(set_attr "length" "8")
2029    (set_attr "predicable" "yes")]
2030 )
2031   
2032 (define_insn "andsi_notsi_si"
2033   [(set (match_operand:SI 0 "s_register_operand" "=r")
2034         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2035                 (match_operand:SI 1 "s_register_operand" "r")))]
2036   "TARGET_ARM"
2037   "bic%?\\t%0, %1, %2"
2038   [(set_attr "predicable" "yes")]
2039 )
2040
2041 (define_insn "bicsi3"
2042   [(set (match_operand:SI                 0 "register_operand" "=l")
2043         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2044                 (match_operand:SI         2 "register_operand" "0")))]
2045   "TARGET_THUMB"
2046   "bic\\t%0, %0, %1"
2047   [(set_attr "length" "2")]
2048 )
2049
2050 (define_insn "andsi_not_shiftsi_si"
2051   [(set (match_operand:SI                   0 "s_register_operand" "=r")
2052         (and:SI (not:SI (match_operator:SI  4 "shift_operator"
2053                          [(match_operand:SI 2 "s_register_operand"  "r")
2054                           (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
2055                 (match_operand:SI           1 "s_register_operand"  "r")))]
2056   "TARGET_ARM"
2057   "bic%?\\t%0, %1, %2%S4"
2058   [(set_attr "predicable" "yes")
2059    (set_attr "shift" "2")
2060    ]
2061 )
2062
2063 (define_insn "*andsi_notsi_si_compare0"
2064   [(set (reg:CC_NOOV CC_REGNUM)
2065         (compare:CC_NOOV
2066          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2067                  (match_operand:SI 1 "s_register_operand" "r"))
2068          (const_int 0)))
2069    (set (match_operand:SI 0 "s_register_operand" "=r")
2070         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2071   "TARGET_ARM"
2072   "bic%?s\\t%0, %1, %2"
2073   [(set_attr "conds" "set")]
2074 )
2075
2076 (define_insn "*andsi_notsi_si_compare0_scratch"
2077   [(set (reg:CC_NOOV CC_REGNUM)
2078         (compare:CC_NOOV
2079          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080                  (match_operand:SI 1 "s_register_operand" "r"))
2081          (const_int 0)))
2082    (clobber (match_scratch:SI 0 "=r"))]
2083   "TARGET_ARM"
2084   "bic%?s\\t%0, %1, %2"
2085   [(set_attr "conds" "set")]
2086 )
2087
2088 (define_insn "iordi3"
2089   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2090         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2091                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2092   "TARGET_ARM && ! TARGET_IWMMXT"
2093   "#"
2094   [(set_attr "length" "8")
2095    (set_attr "predicable" "yes")]
2096 )
2097
2098 (define_insn "*iordi_zesidi_di"
2099   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2100         (ior:DI (zero_extend:DI
2101                  (match_operand:SI 2 "s_register_operand" "r,r"))
2102                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2103   "TARGET_ARM"
2104   "@
2105    orr%?\\t%Q0, %Q1, %2
2106    #"
2107   [(set_attr "length" "4,8")
2108    (set_attr "predicable" "yes")]
2109 )
2110
2111 (define_insn "*iordi_sesidi_di"
2112   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2113         (ior:DI (sign_extend:DI
2114                  (match_operand:SI 2 "s_register_operand" "r,r"))
2115                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2116   "TARGET_ARM"
2117   "#"
2118   [(set_attr "length" "8")
2119    (set_attr "predicable" "yes")]
2120 )
2121
2122 (define_expand "iorsi3"
2123   [(set (match_operand:SI         0 "s_register_operand" "")
2124         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2125                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2126   "TARGET_EITHER"
2127   "
2128   if (GET_CODE (operands[2]) == CONST_INT)
2129     {
2130       if (TARGET_ARM)
2131         {
2132           arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2133                               operands[1],
2134                               (no_new_pseudos
2135                               ? 0 : preserve_subexpressions_p ()));
2136           DONE;
2137         }
2138       else /* TARGET_THUMB */
2139         operands [2] = force_reg (SImode, operands [2]);
2140     }
2141   "
2142 )
2143
2144 (define_insn_and_split "*arm_iorsi3"
2145   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2146         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2147                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2148   "TARGET_ARM"
2149   "@
2150    orr%?\\t%0, %1, %2
2151    #"
2152   "TARGET_ARM
2153    && GET_CODE (operands[2]) == CONST_INT
2154    && !const_ok_for_arm (INTVAL (operands[2]))"
2155   [(clobber (const_int 0))]
2156   "
2157   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2158                       operands[1], 0);
2159   DONE;
2160   "
2161   [(set_attr "length" "4,16")
2162    (set_attr "predicable" "yes")]
2163 )
2164
2165 (define_insn "*thumb_iorsi3"
2166   [(set (match_operand:SI         0 "register_operand" "=l")
2167         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2168                 (match_operand:SI 2 "register_operand" "l")))]
2169   "TARGET_THUMB"
2170   "orr\\t%0, %0, %2"
2171   [(set_attr "length" "2")]
2172 )
2173
2174 (define_peephole2
2175   [(match_scratch:SI 3 "r")
2176    (set (match_operand:SI         0 "s_register_operand" "")
2177         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2178                 (match_operand:SI 2 "const_int_operand" "")))]
2179   "TARGET_ARM
2180    && !const_ok_for_arm (INTVAL (operands[2]))
2181    && const_ok_for_arm (~INTVAL (operands[2]))"
2182   [(set (match_dup 3) (match_dup 2))
2183    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2184   ""
2185 )
2186
2187 (define_insn "*iorsi3_compare0"
2188   [(set (reg:CC_NOOV CC_REGNUM)
2189         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2190                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2191                          (const_int 0)))
2192    (set (match_operand:SI 0 "s_register_operand" "=r")
2193         (ior:SI (match_dup 1) (match_dup 2)))]
2194   "TARGET_ARM"
2195   "orr%?s\\t%0, %1, %2"
2196   [(set_attr "conds" "set")]
2197 )
2198
2199 (define_insn "*iorsi3_compare0_scratch"
2200   [(set (reg:CC_NOOV CC_REGNUM)
2201         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2202                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2203                          (const_int 0)))
2204    (clobber (match_scratch:SI 0 "=r"))]
2205   "TARGET_ARM"
2206   "orr%?s\\t%0, %1, %2"
2207   [(set_attr "conds" "set")]
2208 )
2209
2210 (define_insn "xordi3"
2211   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2212         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2213                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2214   "TARGET_ARM && !TARGET_IWMMXT"
2215   "#"
2216   [(set_attr "length" "8")
2217    (set_attr "predicable" "yes")]
2218 )
2219
2220 (define_insn "*xordi_zesidi_di"
2221   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2222         (xor:DI (zero_extend:DI
2223                  (match_operand:SI 2 "s_register_operand" "r,r"))
2224                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2225   "TARGET_ARM"
2226   "@
2227    eor%?\\t%Q0, %Q1, %2
2228    #"
2229   [(set_attr "length" "4,8")
2230    (set_attr "predicable" "yes")]
2231 )
2232
2233 (define_insn "*xordi_sesidi_di"
2234   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2235         (xor:DI (sign_extend:DI
2236                  (match_operand:SI 2 "s_register_operand" "r,r"))
2237                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2238   "TARGET_ARM"
2239   "#"
2240   [(set_attr "length" "8")
2241    (set_attr "predicable" "yes")]
2242 )
2243
2244 (define_expand "xorsi3"
2245   [(set (match_operand:SI         0 "s_register_operand" "")
2246         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2247                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2248   "TARGET_EITHER"
2249   "if (TARGET_THUMB)
2250      if (GET_CODE (operands[2]) == CONST_INT)
2251        operands[2] = force_reg (SImode, operands[2]);
2252   "
2253 )
2254
2255 (define_insn "*arm_xorsi3"
2256   [(set (match_operand:SI         0 "s_register_operand" "=r")
2257         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2258                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2259   "TARGET_ARM"
2260   "eor%?\\t%0, %1, %2"
2261   [(set_attr "predicable" "yes")]
2262 )
2263
2264 (define_insn "*thumb_xorsi3"
2265   [(set (match_operand:SI         0 "register_operand" "=l")
2266         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2267                 (match_operand:SI 2 "register_operand" "l")))]
2268   "TARGET_THUMB"
2269   "eor\\t%0, %0, %2"
2270   [(set_attr "length" "2")]
2271 )
2272
2273 (define_insn "*xorsi3_compare0"
2274   [(set (reg:CC_NOOV CC_REGNUM)
2275         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2276                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2277                          (const_int 0)))
2278    (set (match_operand:SI 0 "s_register_operand" "=r")
2279         (xor:SI (match_dup 1) (match_dup 2)))]
2280   "TARGET_ARM"
2281   "eor%?s\\t%0, %1, %2"
2282   [(set_attr "conds" "set")]
2283 )
2284
2285 (define_insn "*xorsi3_compare0_scratch"
2286   [(set (reg:CC_NOOV CC_REGNUM)
2287         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2288                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2289                          (const_int 0)))]
2290   "TARGET_ARM"
2291   "teq%?\\t%0, %1"
2292   [(set_attr "conds" "set")]
2293 )
2294
2295 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2296 ; (NOT D) we can sometimes merge the final NOT into one of the following
2297 ; insns.
2298
2299 (define_split
2300   [(set (match_operand:SI 0 "s_register_operand" "")
2301         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2302                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2303                 (match_operand:SI 3 "arm_rhs_operand" "")))
2304    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2305   "TARGET_ARM"
2306   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2307                               (not:SI (match_dup 3))))
2308    (set (match_dup 0) (not:SI (match_dup 4)))]
2309   ""
2310 )
2311
2312 (define_insn "*andsi_iorsi3_notsi"
2313   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2314         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2315                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2316                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2317   "TARGET_ARM"
2318   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2319   [(set_attr "length" "8")
2320    (set_attr "predicable" "yes")]
2321 )
2322
2323 (define_split
2324   [(set (match_operand:SI 0 "s_register_operand" "")
2325         (match_operator:SI 1 "logical_binary_operator"
2326          [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2327                            (match_operand:SI 3 "const_int_operand" "")
2328                            (match_operand:SI 4 "const_int_operand" ""))
2329           (match_operator:SI 9 "logical_binary_operator"
2330            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2331                          (match_operand:SI 6 "const_int_operand" ""))
2332             (match_operand:SI 7 "s_register_operand" "")])]))
2333    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2334   "TARGET_ARM
2335    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2336    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2337   [(set (match_dup 8)
2338         (match_op_dup 1
2339          [(ashift:SI (match_dup 2) (match_dup 4))
2340           (match_dup 5)]))
2341    (set (match_dup 0)
2342         (match_op_dup 1
2343          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2344           (match_dup 7)]))]
2345   "
2346   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2347 ")
2348
2349 (define_split
2350   [(set (match_operand:SI 0 "s_register_operand" "")
2351         (match_operator:SI 1 "logical_binary_operator"
2352          [(match_operator:SI 9 "logical_binary_operator"
2353            [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2354                          (match_operand:SI 6 "const_int_operand" ""))
2355             (match_operand:SI 7 "s_register_operand" "")])
2356           (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2357                            (match_operand:SI 3 "const_int_operand" "")
2358                            (match_operand:SI 4 "const_int_operand" ""))]))
2359    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2360   "TARGET_ARM
2361    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2362    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2363   [(set (match_dup 8)
2364         (match_op_dup 1
2365          [(ashift:SI (match_dup 2) (match_dup 4))
2366           (match_dup 5)]))
2367    (set (match_dup 0)
2368         (match_op_dup 1
2369          [(lshiftrt:SI (match_dup 8) (match_dup 6))
2370           (match_dup 7)]))]
2371   "
2372   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2373 ")
2374
2375 (define_split
2376   [(set (match_operand:SI 0 "s_register_operand" "")
2377         (match_operator:SI 1 "logical_binary_operator"
2378          [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2379                            (match_operand:SI 3 "const_int_operand" "")
2380                            (match_operand:SI 4 "const_int_operand" ""))
2381           (match_operator:SI 9 "logical_binary_operator"
2382            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2383                          (match_operand:SI 6 "const_int_operand" ""))
2384             (match_operand:SI 7 "s_register_operand" "")])]))
2385    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2386   "TARGET_ARM
2387    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2388    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2389   [(set (match_dup 8)
2390         (match_op_dup 1
2391          [(ashift:SI (match_dup 2) (match_dup 4))
2392           (match_dup 5)]))
2393    (set (match_dup 0)
2394         (match_op_dup 1
2395          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2396           (match_dup 7)]))]
2397   "
2398   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2399 ")
2400
2401 (define_split
2402   [(set (match_operand:SI 0 "s_register_operand" "")
2403         (match_operator:SI 1 "logical_binary_operator"
2404          [(match_operator:SI 9 "logical_binary_operator"
2405            [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2406                          (match_operand:SI 6 "const_int_operand" ""))
2407             (match_operand:SI 7 "s_register_operand" "")])
2408           (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2409                            (match_operand:SI 3 "const_int_operand" "")
2410                            (match_operand:SI 4 "const_int_operand" ""))]))
2411    (clobber (match_operand:SI 8 "s_register_operand" ""))]
2412   "TARGET_ARM
2413    && GET_CODE (operands[1]) == GET_CODE (operands[9])
2414    && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2415   [(set (match_dup 8)
2416         (match_op_dup 1
2417          [(ashift:SI (match_dup 2) (match_dup 4))
2418           (match_dup 5)]))
2419    (set (match_dup 0)
2420         (match_op_dup 1
2421          [(ashiftrt:SI (match_dup 8) (match_dup 6))
2422           (match_dup 7)]))]
2423   "
2424   operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2425 ")
2426 \f
2427
2428 ;; Minimum and maximum insns
2429
2430 (define_insn "smaxsi3"
2431   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2432         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2433                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2434    (clobber (reg:CC CC_REGNUM))]
2435   "TARGET_ARM"
2436   "@
2437    cmp\\t%1, %2\;movlt\\t%0, %2
2438    cmp\\t%1, %2\;movge\\t%0, %1
2439    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2440   [(set_attr "conds" "clob")
2441    (set_attr "length" "8,8,12")]
2442 )
2443
2444 (define_insn "sminsi3"
2445   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2446         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2447                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2448    (clobber (reg:CC CC_REGNUM))]
2449   "TARGET_ARM"
2450   "@
2451    cmp\\t%1, %2\;movge\\t%0, %2
2452    cmp\\t%1, %2\;movlt\\t%0, %1
2453    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2454   [(set_attr "conds" "clob")
2455    (set_attr "length" "8,8,12")]
2456 )
2457
2458 (define_insn "umaxsi3"
2459   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2460         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2461                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2462    (clobber (reg:CC CC_REGNUM))]
2463   "TARGET_ARM"
2464   "@
2465    cmp\\t%1, %2\;movcc\\t%0, %2
2466    cmp\\t%1, %2\;movcs\\t%0, %1
2467    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2468   [(set_attr "conds" "clob")
2469    (set_attr "length" "8,8,12")]
2470 )
2471
2472 (define_insn "uminsi3"
2473   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2474         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2475                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2476    (clobber (reg:CC CC_REGNUM))]
2477   "TARGET_ARM"
2478   "@
2479    cmp\\t%1, %2\;movcs\\t%0, %2
2480    cmp\\t%1, %2\;movcc\\t%0, %1
2481    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2482   [(set_attr "conds" "clob")
2483    (set_attr "length" "8,8,12")]
2484 )
2485
2486 (define_insn "*store_minmaxsi"
2487   [(set (match_operand:SI 0 "memory_operand" "=m")
2488         (match_operator:SI 3 "minmax_operator"
2489          [(match_operand:SI 1 "s_register_operand" "r")
2490           (match_operand:SI 2 "s_register_operand" "r")]))
2491    (clobber (reg:CC CC_REGNUM))]
2492   "TARGET_ARM"
2493   "*
2494   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2495                          operands[2]);
2496   output_asm_insn (\"cmp\\t%1, %2\", operands);
2497   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2498   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2499   return \"\";
2500   "
2501   [(set_attr "conds" "clob")
2502    (set_attr "length" "12")
2503    (set_attr "type" "store1")]
2504 )
2505
2506 ; Reject the frame pointer in operand[1], since reloading this after
2507 ; it has been eliminated can cause carnage.
2508 (define_insn "*minmax_arithsi"
2509   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2510         (match_operator:SI 4 "shiftable_operator"
2511          [(match_operator:SI 5 "minmax_operator"
2512            [(match_operand:SI 2 "s_register_operand" "r,r")
2513             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2514           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2515    (clobber (reg:CC CC_REGNUM))]
2516   "TARGET_ARM
2517    && (GET_CODE (operands[1]) != REG
2518        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2519            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2520   "*
2521   {
2522     enum rtx_code code = GET_CODE (operands[4]);
2523
2524     operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2525                            operands[3]);
2526     output_asm_insn (\"cmp\\t%2, %3\", operands);
2527     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2528     if (which_alternative != 0 || operands[3] != const0_rtx
2529         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2530       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2531     return \"\";
2532   }"
2533   [(set_attr "conds" "clob")
2534    (set_attr "length" "12")]
2535 )
2536
2537 \f
2538 ;; Shift and rotation insns
2539
2540 (define_expand "ashlsi3"
2541   [(set (match_operand:SI            0 "s_register_operand" "")
2542         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2543                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2544   "TARGET_EITHER"
2545   "
2546   if (GET_CODE (operands[2]) == CONST_INT
2547       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2548     {
2549       emit_insn (gen_movsi (operands[0], const0_rtx));
2550       DONE;
2551     }
2552   "
2553 )
2554
2555 (define_insn "*thumb_ashlsi3"
2556   [(set (match_operand:SI            0 "register_operand" "=l,l")
2557         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2558                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2559   "TARGET_THUMB"
2560   "lsl\\t%0, %1, %2"
2561   [(set_attr "length" "2")]
2562 )
2563
2564 (define_expand "ashrsi3"
2565   [(set (match_operand:SI              0 "s_register_operand" "")
2566         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2567                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2568   "TARGET_EITHER"
2569   "
2570   if (GET_CODE (operands[2]) == CONST_INT
2571       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2572     operands[2] = GEN_INT (31);
2573   "
2574 )
2575
2576 (define_insn "*thumb_ashrsi3"
2577   [(set (match_operand:SI              0 "register_operand" "=l,l")
2578         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2579                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2580   "TARGET_THUMB"
2581   "asr\\t%0, %1, %2"
2582   [(set_attr "length" "2")]
2583 )
2584
2585 (define_expand "lshrsi3"
2586   [(set (match_operand:SI              0 "s_register_operand" "")
2587         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2588                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2589   "TARGET_EITHER"
2590   "
2591   if (GET_CODE (operands[2]) == CONST_INT
2592       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2593     {
2594       emit_insn (gen_movsi (operands[0], const0_rtx));
2595       DONE;
2596     }
2597   "
2598 )
2599
2600 (define_insn "*thumb_lshrsi3"
2601   [(set (match_operand:SI              0 "register_operand" "=l,l")
2602         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2603                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2604   "TARGET_THUMB"
2605   "lsr\\t%0, %1, %2"
2606   [(set_attr "length" "2")]
2607 )
2608
2609 (define_expand "rotlsi3"
2610   [(set (match_operand:SI              0 "s_register_operand" "")
2611         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2612                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2613   "TARGET_ARM"
2614   "
2615   if (GET_CODE (operands[2]) == CONST_INT)
2616     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2617   else
2618     {
2619       rtx reg = gen_reg_rtx (SImode);
2620       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2621       operands[2] = reg;
2622     }
2623   "
2624 )
2625
2626 (define_expand "rotrsi3"
2627   [(set (match_operand:SI              0 "s_register_operand" "")
2628         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2629                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2630   "TARGET_EITHER"
2631   "
2632   if (TARGET_ARM)
2633     {
2634       if (GET_CODE (operands[2]) == CONST_INT
2635           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2636         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2637     }
2638   else /* TARGET_THUMB */
2639     {
2640       if (GET_CODE (operands [2]) == CONST_INT)
2641         operands [2] = force_reg (SImode, operands[2]);
2642     }
2643   "
2644 )
2645
2646 (define_insn "*thumb_rotrsi3"
2647   [(set (match_operand:SI              0 "register_operand" "=l")
2648         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2649                      (match_operand:SI 2 "register_operand" "l")))]
2650   "TARGET_THUMB"
2651   "ror\\t%0, %0, %2"
2652   [(set_attr "length" "2")]
2653 )
2654
2655 (define_expand "ashldi3"
2656   [(set (match_operand:DI            0 "s_register_operand" "")
2657         (ashift:DI (match_operand:DI 1 "general_operand"    "")
2658                    (match_operand:SI 2 "general_operand"    "")))]
2659   "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)"
2660   "
2661   if (! s_register_operand (operands[1], DImode))
2662     operands[1] = copy_to_mode_reg (DImode, operands[1]);
2663   if (! s_register_operand (operands[2], SImode))
2664     operands[2] = copy_to_mode_reg (SImode, operands[2]);
2665   "
2666 )
2667
2668 (define_insn "*arm_shiftsi3"
2669   [(set (match_operand:SI   0 "s_register_operand" "=r")
2670         (match_operator:SI  3 "shift_operator"
2671          [(match_operand:SI 1 "s_register_operand"  "r")
2672           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2673   "TARGET_ARM"
2674   "mov%?\\t%0, %1%S3"
2675   [(set_attr "predicable" "yes")
2676    (set_attr "shift" "1")
2677    ]
2678 )
2679
2680 (define_insn "*shiftsi3_compare0"
2681   [(set (reg:CC_NOOV CC_REGNUM)
2682         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2683                           [(match_operand:SI 1 "s_register_operand" "r")
2684                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2685                          (const_int 0)))
2686    (set (match_operand:SI 0 "s_register_operand" "=r")
2687         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2688   "TARGET_ARM"
2689   "mov%?s\\t%0, %1%S3"
2690   [(set_attr "conds" "set")
2691    (set_attr "shift" "1")
2692    ]
2693 )
2694
2695 (define_insn "*shiftsi3_compare0_scratch"
2696   [(set (reg:CC_NOOV CC_REGNUM)
2697         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2698                           [(match_operand:SI 1 "s_register_operand" "r")
2699                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2700                          (const_int 0)))
2701    (clobber (match_scratch:SI 0 "=r"))]
2702   "TARGET_ARM"
2703   "mov%?s\\t%0, %1%S3"
2704   [(set_attr "conds" "set")
2705    (set_attr "shift" "1")
2706    ]
2707 )
2708
2709 (define_insn "*notsi_shiftsi"
2710   [(set (match_operand:SI 0 "s_register_operand" "=r")
2711         (not:SI (match_operator:SI 3 "shift_operator"
2712                  [(match_operand:SI 1 "s_register_operand" "r")
2713                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2714   "TARGET_ARM"
2715   "mvn%?\\t%0, %1%S3"
2716   [(set_attr "predicable" "yes")
2717    (set_attr "shift" "1")
2718    ]
2719 )
2720
2721 (define_insn "*notsi_shiftsi_compare0"
2722   [(set (reg:CC_NOOV CC_REGNUM)
2723         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2724                           [(match_operand:SI 1 "s_register_operand" "r")
2725                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2726                          (const_int 0)))
2727    (set (match_operand:SI 0 "s_register_operand" "=r")
2728         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2729   "TARGET_ARM"
2730   "mvn%?s\\t%0, %1%S3"
2731   [(set_attr "conds" "set")
2732    (set_attr "shift" "1")
2733    ]
2734 )
2735
2736 (define_insn "*not_shiftsi_compare0_scratch"
2737   [(set (reg:CC_NOOV CC_REGNUM)
2738         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2739                           [(match_operand:SI 1 "s_register_operand" "r")
2740                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2741                          (const_int 0)))
2742    (clobber (match_scratch:SI 0 "=r"))]
2743   "TARGET_ARM"
2744   "mvn%?s\\t%0, %1%S3"
2745   [(set_attr "conds" "set")
2746    (set_attr "shift" "1")
2747   ]
2748 )
2749
2750 ;; We don't really have extzv, but defining this using shifts helps
2751 ;; to reduce register pressure later on.
2752
2753 (define_expand "extzv"
2754   [(set (match_dup 4)
2755         (ashift:SI (match_operand:SI   1 "register_operand" "")
2756                    (match_operand:SI   2 "const_int_operand" "")))
2757    (set (match_operand:SI              0 "register_operand" "")
2758         (lshiftrt:SI (match_dup 4)
2759                      (match_operand:SI 3 "const_int_operand" "")))]
2760   "TARGET_THUMB"
2761   "
2762   {
2763     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2764     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2765     
2766     operands[3] = GEN_INT (rshift);
2767     
2768     if (lshift == 0)
2769       {
2770         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2771         DONE;
2772       }
2773       
2774     operands[2] = GEN_INT (lshift);
2775     operands[4] = gen_reg_rtx (SImode);
2776   }"
2777 )
2778
2779 \f
2780 ;; Unary arithmetic insns
2781
2782 (define_expand "negdi2"
2783  [(parallel
2784    [(set (match_operand:DI          0 "s_register_operand" "")
2785           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2786     (clobber (reg:CC CC_REGNUM))])]
2787   "TARGET_EITHER"
2788   "
2789   if (TARGET_THUMB)
2790     {
2791       if (GET_CODE (operands[1]) != REG)
2792         operands[1] = force_reg (SImode, operands[1]);
2793      }
2794   "
2795 )
2796
2797 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2798 ;; The second alternative is to allow the common case of a *full* overlap.
2799 (define_insn "*arm_negdi2"
2800   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2801         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2802    (clobber (reg:CC CC_REGNUM))]
2803   "TARGET_ARM"
2804   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2805   [(set_attr "conds" "clob")
2806    (set_attr "length" "8")]
2807 )
2808
2809 (define_insn "*thumb_negdi2"
2810   [(set (match_operand:DI         0 "register_operand" "=&l")
2811         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2812    (clobber (reg:CC CC_REGNUM))]
2813   "TARGET_THUMB"
2814   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2815   [(set_attr "length" "6")]
2816 )
2817
2818 (define_expand "negsi2"
2819   [(set (match_operand:SI         0 "s_register_operand" "")
2820         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2821   "TARGET_EITHER"
2822   ""
2823 )
2824
2825 (define_insn "*arm_negsi2"
2826   [(set (match_operand:SI         0 "s_register_operand" "=r")
2827         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2828   "TARGET_ARM"
2829   "rsb%?\\t%0, %1, #0"
2830   [(set_attr "predicable" "yes")]
2831 )
2832
2833 (define_insn "*thumb_negsi2"
2834   [(set (match_operand:SI         0 "register_operand" "=l")
2835         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2836   "TARGET_THUMB"
2837   "neg\\t%0, %1"
2838   [(set_attr "length" "2")]
2839 )
2840
2841 (define_expand "negsf2"
2842   [(set (match_operand:SF         0 "s_register_operand" "")
2843         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2844   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2845   ""
2846 )
2847
2848 (define_expand "negdf2"
2849   [(set (match_operand:DF         0 "s_register_operand" "")
2850         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2851   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2852   "")
2853
2854 ;; abssi2 doesn't really clobber the condition codes if a different register
2855 ;; is being set.  To keep things simple, assume during rtl manipulations that
2856 ;; it does, but tell the final scan operator the truth.  Similarly for
2857 ;; (neg (abs...))
2858
2859 (define_expand "abssi2"
2860   [(parallel
2861     [(set (match_operand:SI         0 "s_register_operand" "")
2862           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2863      (clobber (reg:CC CC_REGNUM))])]
2864   "TARGET_ARM"
2865   "")
2866
2867 (define_insn "*arm_abssi2"
2868   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2869         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2870    (clobber (reg:CC CC_REGNUM))]
2871   "TARGET_ARM"
2872   "@
2873    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2874    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2875   [(set_attr "conds" "clob,*")
2876    (set_attr "shift" "1")
2877    ;; predicable can't be set based on the variant, so left as no
2878    (set_attr "length" "8")]
2879 )
2880
2881 (define_insn "*neg_abssi2"
2882   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2883         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2884    (clobber (reg:CC CC_REGNUM))]
2885   "TARGET_ARM"
2886   "@
2887    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2888    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2889   [(set_attr "conds" "clob,*")
2890    (set_attr "shift" "1")
2891    ;; predicable can't be set based on the variant, so left as no
2892    (set_attr "length" "8")]
2893 )
2894
2895 (define_expand "abssf2"
2896   [(set (match_operand:SF         0 "s_register_operand" "")
2897         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2898   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2899   "")
2900
2901 (define_expand "absdf2"
2902   [(set (match_operand:DF         0 "s_register_operand" "")
2903         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2904   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2905   "")
2906
2907 (define_expand "sqrtsf2"
2908   [(set (match_operand:SF 0 "s_register_operand" "")
2909         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2910   "TARGET_ARM && TARGET_HARD_FLOAT"
2911   "")
2912
2913 (define_expand "sqrtdf2"
2914   [(set (match_operand:DF 0 "s_register_operand" "")
2915         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2916   "TARGET_ARM && TARGET_HARD_FLOAT"
2917   "")
2918
2919 (define_insn_and_split "one_cmpldi2"
2920   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2921         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2922   "TARGET_ARM"
2923   "#"
2924   "TARGET_ARM && reload_completed"
2925   [(set (match_dup 0) (not:SI (match_dup 1)))
2926    (set (match_dup 2) (not:SI (match_dup 3)))]
2927   "
2928   {
2929     operands[2] = gen_highpart (SImode, operands[0]);
2930     operands[0] = gen_lowpart (SImode, operands[0]);
2931     operands[3] = gen_highpart (SImode, operands[1]);
2932     operands[1] = gen_lowpart (SImode, operands[1]);
2933   }"
2934   [(set_attr "length" "8")
2935    (set_attr "predicable" "yes")]
2936 )
2937
2938 (define_expand "one_cmplsi2"
2939   [(set (match_operand:SI         0 "s_register_operand" "")
2940         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2941   "TARGET_EITHER"
2942   ""
2943 )
2944
2945 (define_insn "*arm_one_cmplsi2"
2946   [(set (match_operand:SI         0 "s_register_operand" "=r")
2947         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2948   "TARGET_ARM"
2949   "mvn%?\\t%0, %1"
2950   [(set_attr "predicable" "yes")]
2951 )
2952
2953 (define_insn "*thumb_one_cmplsi2"
2954   [(set (match_operand:SI         0 "register_operand" "=l")
2955         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
2956   "TARGET_THUMB"
2957   "mvn\\t%0, %1"
2958   [(set_attr "length" "2")]
2959 )
2960
2961 (define_insn "*notsi_compare0"
2962   [(set (reg:CC_NOOV CC_REGNUM)
2963         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2964                          (const_int 0)))
2965    (set (match_operand:SI 0 "s_register_operand" "=r")
2966         (not:SI (match_dup 1)))]
2967   "TARGET_ARM"
2968   "mvn%?s\\t%0, %1"
2969   [(set_attr "conds" "set")]
2970 )
2971
2972 (define_insn "*notsi_compare0_scratch"
2973   [(set (reg:CC_NOOV CC_REGNUM)
2974         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2975                          (const_int 0)))
2976    (clobber (match_scratch:SI 0 "=r"))]
2977   "TARGET_ARM"
2978   "mvn%?s\\t%0, %1"
2979   [(set_attr "conds" "set")]
2980 )
2981 \f
2982 ;; Fixed <--> Floating conversion insns
2983
2984 (define_expand "floatsisf2"
2985   [(set (match_operand:SF           0 "s_register_operand" "")
2986         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2987   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2988   "
2989   if (TARGET_CIRRUS)
2990     {
2991       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2992       DONE;
2993     }
2994 ")
2995
2996 (define_expand "floatsidf2"
2997   [(set (match_operand:DF           0 "s_register_operand" "")
2998         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2999   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3000   "
3001   if (TARGET_CIRRUS)
3002     {
3003       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3004       DONE;
3005     }
3006 ")
3007
3008 (define_expand "fix_truncsfsi2"
3009   [(set (match_operand:SI         0 "s_register_operand" "")
3010         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
3011   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3012   "
3013   if (TARGET_CIRRUS)
3014     {
3015       if (!cirrus_fp_register (operands[0], SImode))
3016         operands[0] = force_reg (SImode, operands[0]);
3017       if (!cirrus_fp_register (operands[1], SFmode))
3018         operands[1] = force_reg (SFmode, operands[0]);
3019       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3020       DONE;
3021     }
3022 ")
3023
3024 (define_expand "fix_truncdfsi2"
3025   [(set (match_operand:SI         0 "s_register_operand" "")
3026         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
3027   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3028   "
3029   if (TARGET_CIRRUS)
3030     {
3031       if (!cirrus_fp_register (operands[1], DFmode))
3032         operands[1] = force_reg (DFmode, operands[0]);
3033       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3034       DONE;
3035     }
3036 ")
3037
3038 ;; Truncation insns
3039
3040 (define_expand "truncdfsf2"
3041   [(set (match_operand:SF  0 "s_register_operand" "")
3042         (float_truncate:SF
3043          (match_operand:DF 1 "s_register_operand" "")))]
3044   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3045   ""
3046 )
3047 \f
3048 ;; Zero and sign extension instructions.
3049
3050 (define_insn "zero_extendsidi2"
3051   [(set (match_operand:DI 0 "s_register_operand" "=r")
3052         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3053   "TARGET_ARM"
3054   "*
3055     if (REGNO (operands[1])
3056         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3057       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3058     return \"mov%?\\t%R0, #0\";
3059   "
3060   [(set_attr "length" "8")
3061    (set_attr "predicable" "yes")]
3062 )
3063
3064 (define_insn "zero_extendqidi2"
3065   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3066         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3067   "TARGET_ARM"
3068   "@
3069    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3070    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3071   [(set_attr "length" "8")
3072    (set_attr "predicable" "yes")
3073    (set_attr "type" "*,load")
3074    (set_attr "pool_range" "*,4092")
3075    (set_attr "neg_pool_range" "*,4084")]
3076 )
3077
3078 (define_insn "extendsidi2"
3079   [(set (match_operand:DI 0 "s_register_operand" "=r")
3080         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3081   "TARGET_ARM"
3082   "*
3083     if (REGNO (operands[1])
3084         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3085       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3086     return \"mov%?\\t%R0, %Q0, asr #31\";
3087   "
3088   [(set_attr "length" "8")
3089    (set_attr "shift" "1")
3090    (set_attr "predicable" "yes")]
3091 )
3092
3093 (define_expand "zero_extendhisi2"
3094   [(set (match_dup 2)
3095         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3096                    (const_int 16)))
3097    (set (match_operand:SI 0 "s_register_operand" "")
3098         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3099   "TARGET_EITHER"
3100   "
3101   {
3102     if (TARGET_ARM)
3103       {
3104         if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3105           {
3106            /* Note: We do not have to worry about TARGET_MMU_TRAPS
3107               here because the insn below will generate an LDRH instruction
3108               rather than an LDR instruction, so we cannot get an unaligned
3109               word access.  */
3110             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3111                                     gen_rtx_ZERO_EXTEND (SImode,
3112                                                          operands[1])));
3113             DONE;
3114           }
3115         if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3116           {
3117             emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3118             DONE;
3119           }
3120         if (!s_register_operand (operands[1], HImode))
3121           operands[1] = copy_to_mode_reg (HImode, operands[1]);
3122         operands[1] = gen_lowpart (SImode, operands[1]);
3123         operands[2] = gen_reg_rtx (SImode);
3124       }
3125     else /* TARGET_THUMB */
3126       {
3127         if (GET_CODE (operands[1]) == MEM)
3128           {
3129             rtx tmp;
3130
3131             tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3132             tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3133             emit_insn (tmp);
3134           }
3135         else
3136           {
3137             rtx ops[3];
3138             
3139             if (!s_register_operand (operands[1], HImode))
3140               operands[1] = copy_to_mode_reg (HImode, operands[1]);
3141             operands[1] = gen_lowpart (SImode, operands[1]);
3142             operands[2] = gen_reg_rtx (SImode);
3143             
3144             ops[0] = operands[2];
3145             ops[1] = operands[1];
3146             ops[2] = GEN_INT (16);
3147             
3148             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3149                                     gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3150
3151             ops[0] = operands[0];
3152             ops[1] = operands[2];
3153             ops[2] = GEN_INT (16);
3154
3155             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3156                                     gen_rtx_LSHIFTRT (SImode, ops[1],
3157                                                       ops[2])));
3158           }
3159         DONE; 
3160       }
3161   }"
3162 )
3163
3164 (define_insn "*thumb_zero_extendhisi2"
3165   [(set (match_operand:SI                 0 "register_operand" "=l")
3166         (zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3167   "TARGET_THUMB"
3168   "*
3169   rtx mem = XEXP (operands[1], 0);
3170
3171   if (GET_CODE (mem) == CONST)
3172     mem = XEXP (mem, 0);
3173     
3174   if (GET_CODE (mem) == LABEL_REF)
3175     return \"ldr\\t%0, %1\";
3176     
3177   if (GET_CODE (mem) == PLUS)
3178     {
3179       rtx a = XEXP (mem, 0);
3180       rtx b = XEXP (mem, 1);
3181
3182       /* This can happen due to bugs in reload.  */
3183       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3184         {
3185           rtx ops[2];
3186           ops[0] = operands[0];
3187           ops[1] = a;
3188       
3189           output_asm_insn (\"mov        %0, %1\", ops);
3190
3191           XEXP (mem, 0) = operands[0];
3192        }
3193
3194       else if (   GET_CODE (a) == LABEL_REF
3195                && GET_CODE (b) == CONST_INT)
3196         return \"ldr\\t%0, %1\";
3197     }
3198     
3199   return \"ldrh\\t%0, %1\";
3200   "
3201   [(set_attr "length" "4")
3202    (set_attr "type" "load")
3203    (set_attr "pool_range" "60")]
3204 )
3205
3206 (define_insn "*arm_zero_extendhisi2"
3207   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3208         (zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3209   "TARGET_ARM && arm_arch4"
3210   "ldr%?h\\t%0, %1"
3211   [(set_attr "type" "load")
3212    (set_attr "predicable" "yes")
3213    (set_attr "pool_range" "256")
3214    (set_attr "neg_pool_range" "244")]
3215 )
3216
3217 (define_split
3218   [(set (match_operand:SI 0 "s_register_operand" "")
3219         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3220    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3221   "TARGET_ARM && (!arm_arch4)"
3222   [(set (match_dup 2) (match_dup 1))
3223    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3224   "
3225   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3226     FAIL;
3227   "
3228 )
3229
3230 (define_split
3231   [(set (match_operand:SI 0 "s_register_operand" "")
3232         (match_operator:SI 3 "shiftable_operator"
3233          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3234           (match_operand:SI 4 "s_register_operand" "")]))
3235    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3236   "TARGET_ARM && (!arm_arch4)"
3237   [(set (match_dup 2) (match_dup 1))
3238    (set (match_dup 0)
3239         (match_op_dup 3
3240          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3241   "
3242   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3243     FAIL;
3244   "
3245 )
3246
3247 (define_expand "zero_extendqisi2"
3248   [(set (match_operand:SI 0 "s_register_operand" "")
3249         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3250   "TARGET_EITHER"
3251   "
3252   if (GET_CODE (operands[1]) != MEM)
3253     {
3254       if (TARGET_ARM)
3255         {
3256           emit_insn (gen_andsi3 (operands[0],
3257                                  gen_lowpart (SImode, operands[1]),
3258                                  GEN_INT (255)));
3259         }
3260       else /* TARGET_THUMB */
3261         {
3262           rtx temp = gen_reg_rtx (SImode);
3263           rtx ops[3];
3264           
3265           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3266           operands[1] = gen_lowpart (SImode, operands[1]);
3267
3268           ops[0] = temp;
3269           ops[1] = operands[1];
3270           ops[2] = GEN_INT (24);
3271
3272           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3273                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3274           
3275           ops[0] = operands[0];
3276           ops[1] = temp;
3277           ops[2] = GEN_INT (24);
3278
3279           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3280                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3281         }
3282       DONE;
3283     }
3284   "
3285 )
3286
3287 (define_insn "*thumb_zero_extendqisi2"
3288   [(set (match_operand:SI                 0 "register_operand" "=l")
3289         (zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3290   "TARGET_THUMB"
3291   "ldrb\\t%0, %1"
3292   [(set_attr "length" "2")
3293    (set_attr "type" "load")
3294    (set_attr "pool_range" "32")]
3295 )
3296
3297 (define_insn "*arm_zero_extendqisi2"
3298   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3299         (zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3300   "TARGET_ARM"
3301   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3302   [(set_attr "type" "load")
3303    (set_attr "predicable" "yes")
3304    (set_attr "pool_range" "4096")
3305    (set_attr "neg_pool_range" "4084")]
3306 )
3307
3308 (define_split
3309   [(set (match_operand:SI 0 "s_register_operand" "")
3310         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3311    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3312   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3313   [(set (match_dup 2) (match_dup 1))
3314    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3315   ""
3316 )
3317
3318 (define_insn "*compareqi_eq0"
3319   [(set (reg:CC_Z CC_REGNUM)
3320         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3321                          (const_int 0)))]
3322   "TARGET_ARM"
3323   "tst\\t%0, #255"
3324   [(set_attr "conds" "set")]
3325 )
3326
3327 (define_expand "extendhisi2"
3328   [(set (match_dup 2)
3329         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3330                    (const_int 16)))
3331    (set (match_operand:SI 0 "s_register_operand" "")
3332         (ashiftrt:SI (match_dup 2)
3333                      (const_int 16)))]
3334   "TARGET_EITHER"
3335   "
3336   {
3337     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3338       {
3339        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3340           here because the insn below will generate an LDRH instruction
3341           rather than an LDR instruction, so we cannot get an unaligned
3342           word access.  */
3343         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3344                    gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3345         DONE;
3346       }
3347
3348     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3349       {
3350         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3351         DONE;
3352       }
3353     if (!s_register_operand (operands[1], HImode))
3354       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3355     operands[1] = gen_lowpart (SImode, operands[1]);
3356     operands[2] = gen_reg_rtx (SImode);
3357
3358     if (TARGET_THUMB)
3359       {
3360         rtx ops[3];
3361         
3362         ops[0] = operands[2];
3363         ops[1] = operands[1];
3364         ops[2] = GEN_INT (16);
3365         
3366         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3367                                 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3368             
3369         ops[0] = operands[0];
3370         ops[1] = operands[2];
3371         ops[2] = GEN_INT (16);
3372         
3373         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3374                                 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3375         
3376         DONE;
3377       }
3378   }"
3379 )
3380
3381 (define_insn "*thumb_extendhisi2_insn"
3382   [(set (match_operand:SI                 0 "register_operand" "=l")
3383         (sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3384    (clobber (match_scratch:SI             2                   "=&l"))]
3385   "TARGET_THUMB"
3386   "*
3387   {
3388     rtx ops[4];
3389     rtx mem = XEXP (operands[1], 0);
3390
3391     /* This code used to try to use 'V', and fix the address only if it was
3392        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3393        range of QImode offsets, and offsettable_address_p does a QImode
3394        address check.  */
3395        
3396     if (GET_CODE (mem) == CONST)
3397       mem = XEXP (mem, 0);
3398     
3399     if (GET_CODE (mem) == LABEL_REF)
3400       return \"ldr\\t%0, %1\";
3401     
3402     if (GET_CODE (mem) == PLUS)
3403       {
3404         rtx a = XEXP (mem, 0);
3405         rtx b = XEXP (mem, 1);
3406
3407         if (GET_CODE (a) == LABEL_REF
3408             && GET_CODE (b) == CONST_INT)
3409           return \"ldr\\t%0, %1\";
3410
3411         if (GET_CODE (b) == REG)
3412           return \"ldrsh\\t%0, %1\";
3413           
3414         ops[1] = a;
3415         ops[2] = b;
3416       }
3417     else
3418       {
3419         ops[1] = mem;
3420         ops[2] = const0_rtx;
3421       }
3422       
3423     if (GET_CODE (ops[1]) != REG)
3424       {
3425         debug_rtx (ops[1]);
3426         abort ();
3427       }
3428
3429     ops[0] = operands[0];
3430     ops[3] = operands[2];
3431     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3432     return \"\";
3433   }"
3434   [(set_attr "length" "4")
3435    (set_attr "type" "load")
3436    (set_attr "pool_range" "1020")]
3437 )
3438
3439 (define_expand "extendhisi2_mem"
3440   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3441    (set (match_dup 3)
3442         (zero_extend:SI (match_dup 7)))
3443    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3444    (set (match_operand:SI 0 "" "")
3445         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3446   "TARGET_ARM"
3447   "
3448   {
3449     rtx mem1, mem2;
3450     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3451
3452     mem1 = gen_rtx_MEM (QImode, addr);
3453     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3454     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3455     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3456     operands[0] = gen_lowpart (SImode, operands[0]);
3457     operands[1] = mem1;
3458     operands[2] = gen_reg_rtx (SImode);
3459     operands[3] = gen_reg_rtx (SImode);
3460     operands[6] = gen_reg_rtx (SImode);
3461     operands[7] = mem2;
3462
3463     if (BYTES_BIG_ENDIAN)
3464       {
3465         operands[4] = operands[2];
3466         operands[5] = operands[3];
3467       }
3468     else
3469       {
3470         operands[4] = operands[3];
3471         operands[5] = operands[2];
3472       }
3473   }"
3474 )
3475
3476 (define_insn "*arm_extendhisi_insn"
3477   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3478         (sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3479   "TARGET_ARM && arm_arch4"
3480   "ldr%?sh\\t%0, %1"
3481   [(set_attr "type" "load")
3482    (set_attr "predicable" "yes")
3483    (set_attr "pool_range" "256")
3484    (set_attr "neg_pool_range" "244")]
3485 )
3486
3487 (define_split
3488   [(set (match_operand:SI                 0 "s_register_operand" "")
3489         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3490    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3491   "TARGET_ARM && (!arm_arch4)"
3492   [(set (match_dup 2) (match_dup 1))
3493    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3494   "
3495   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3496     FAIL;
3497   "
3498 )
3499
3500 (define_split
3501   [(set (match_operand:SI                   0 "s_register_operand" "")
3502         (match_operator:SI                  3 "shiftable_operator"
3503          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3504           (match_operand:SI                 4 "s_register_operand" "")]))
3505    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3506   "TARGET_ARM && (!arm_arch4)"
3507   [(set (match_dup 2) (match_dup 1))
3508    (set (match_dup 0)
3509         (match_op_dup 3
3510          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3511   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3512      FAIL;
3513   "
3514 )
3515
3516 (define_expand "extendqihi2"
3517   [(set (match_dup 2)
3518         (ashift:SI (match_operand:QI 1 "general_operand" "")
3519                    (const_int 24)))
3520    (set (match_operand:HI 0 "s_register_operand" "")
3521         (ashiftrt:SI (match_dup 2)
3522                      (const_int 24)))]
3523   "TARGET_ARM"
3524   "
3525   {
3526     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3527       {
3528         emit_insn (gen_rtx_SET (VOIDmode,
3529                                 operands[0],
3530                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3531         DONE;
3532       }
3533     if (!s_register_operand (operands[1], QImode))
3534       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3535     operands[0] = gen_lowpart (SImode, operands[0]);
3536     operands[1] = gen_lowpart (SImode, operands[1]);
3537     operands[2] = gen_reg_rtx (SImode);
3538   }"
3539 )
3540
3541 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3542 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3543 (define_insn "*extendqihi_insn"
3544   [(set (match_operand:HI                 0 "s_register_operand" "=r")
3545         (sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3546   "TARGET_ARM && arm_arch4"
3547   "*
3548   /* If the address is invalid, this will split the instruction into two. */
3549   if (bad_signed_byte_operand (operands[1], VOIDmode))
3550     return \"#\";
3551   return \"ldr%?sb\\t%0, %1\";
3552   "
3553   [(set_attr "type" "load")
3554    (set_attr "predicable" "yes")
3555    (set_attr "length" "8")
3556    (set_attr "pool_range" "256")
3557    (set_attr "neg_pool_range" "244")]
3558 )
3559
3560 (define_split
3561   [(set (match_operand:HI 0 "s_register_operand" "")
3562         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3563   "TARGET_ARM && arm_arch4 && reload_completed"
3564   [(set (match_dup 3) (match_dup 1))
3565    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3566   "
3567   {
3568     HOST_WIDE_INT offset;
3569
3570     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3571     operands[2] = gen_rtx_MEM (QImode, operands[3]);
3572     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3573     operands[1] = XEXP (operands[1], 0);
3574     if (GET_CODE (operands[1]) == PLUS
3575         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3576         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3577              || const_ok_for_arm (-offset)))
3578       {
3579         HOST_WIDE_INT low = (offset > 0
3580                              ? (offset & 0xff) : -((-offset) & 0xff));
3581         XEXP (operands[2], 0) = plus_constant (operands[3], low);
3582         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3583       }
3584     /* Ensure the sum is in correct canonical form */
3585     else if (GET_CODE (operands[1]) == PLUS
3586              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3587              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3588       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3589                                            XEXP (operands[1], 1),
3590                                            XEXP (operands[1], 0));
3591   }"
3592 )
3593
3594 (define_expand "extendqisi2"
3595   [(set (match_dup 2)
3596         (ashift:SI (match_operand:QI 1 "general_operand" "")
3597                    (const_int 24)))
3598    (set (match_operand:SI 0 "s_register_operand" "")
3599         (ashiftrt:SI (match_dup 2)
3600                      (const_int 24)))]
3601   "TARGET_EITHER"
3602   "
3603   {
3604     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3605       {
3606         emit_insn (gen_rtx_SET (VOIDmode,
3607                                 operands[0],
3608                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3609         DONE;
3610       }
3611     if (!s_register_operand (operands[1], QImode))
3612       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3613     operands[1] = gen_lowpart (SImode, operands[1]);
3614     operands[2] = gen_reg_rtx (SImode);
3615     
3616     if (TARGET_THUMB)
3617       {
3618         rtx ops[3];
3619         
3620         ops[0] = operands[2];
3621         ops[1] = operands[1];
3622         ops[2] = GEN_INT (24);
3623         
3624         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3625                    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3626
3627         ops[0] = operands[0];
3628         ops[1] = operands[2];
3629         ops[2] = GEN_INT (24);
3630         
3631         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3632                    gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3633         
3634         DONE;
3635       }
3636   }"
3637 )
3638
3639 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3640 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3641 (define_insn "*arm_extendqisi_insn"
3642   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3643         (sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3644   "TARGET_ARM && arm_arch4"
3645   "*
3646   /* If the address is invalid, this will split the instruction into two. */
3647   if (bad_signed_byte_operand (operands[1], VOIDmode))
3648     return \"#\";
3649   return \"ldr%?sb\\t%0, %1\";
3650   "
3651   [(set_attr "type" "load")
3652    (set_attr "predicable" "yes")
3653    (set_attr "length" "8")
3654    (set_attr "pool_range" "256")
3655    (set_attr "neg_pool_range" "244")]
3656 )
3657
3658 (define_split
3659   [(set (match_operand:SI 0 "s_register_operand" "")
3660         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3661   "TARGET_ARM && arm_arch4 && reload_completed"
3662   [(set (match_dup 0) (match_dup 1))
3663    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3664   "
3665   {
3666     HOST_WIDE_INT offset;
3667
3668     operands[2] = gen_rtx_MEM (QImode, operands[0]);
3669     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3670     operands[1] = XEXP (operands[1], 0);
3671     if (GET_CODE (operands[1]) == PLUS
3672         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3673         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3674              || const_ok_for_arm (-offset)))
3675       {
3676         HOST_WIDE_INT low = (offset > 0
3677                              ? (offset & 0xff) : -((-offset) & 0xff));
3678         XEXP (operands[2], 0) = plus_constant (operands[0], low);
3679         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3680       }
3681     /* Ensure the sum is in correct canonical form */
3682     else if (GET_CODE (operands[1]) == PLUS
3683              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3684              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3685       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3686                                            XEXP (operands[1], 1),
3687                                            XEXP (operands[1], 0));
3688   }"
3689 )
3690
3691 (define_insn "*thumb_extendqisi2_insn"
3692   [(set (match_operand:SI                 0 "register_operand" "=l,l")
3693         (sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3694   "TARGET_THUMB"
3695   "*
3696   {
3697     rtx ops[3];
3698     rtx mem = XEXP (operands[1], 0);
3699     
3700     if (GET_CODE (mem) == CONST)
3701       mem = XEXP (mem, 0);
3702     
3703     if (GET_CODE (mem) == LABEL_REF)
3704       return \"ldr\\t%0, %1\";
3705
3706     if (GET_CODE (mem) == PLUS
3707         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3708       return \"ldr\\t%0, %1\";
3709       
3710     if (which_alternative == 0)
3711       return \"ldrsb\\t%0, %1\";
3712       
3713     ops[0] = operands[0];
3714     
3715     if (GET_CODE (mem) == PLUS)
3716       {
3717         rtx a = XEXP (mem, 0);
3718         rtx b = XEXP (mem, 1);
3719         
3720         ops[1] = a;
3721         ops[2] = b;
3722
3723         if (GET_CODE (a) == REG)
3724           {
3725             if (GET_CODE (b) == REG)
3726               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3727             else if (REGNO (a) == REGNO (ops[0]))
3728               {
3729                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3730                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3731                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3732               }
3733             else
3734               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3735           }
3736         else if (GET_CODE (b) != REG)
3737           abort ();
3738         else
3739           {
3740             if (REGNO (b) == REGNO (ops[0]))
3741               {
3742                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3743                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3744                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3745               }
3746             else
3747               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3748           }
3749       }
3750     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3751       {
3752         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3753         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3754         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3755       }
3756     else
3757       {
3758         ops[1] = mem;
3759         ops[2] = const0_rtx;
3760         
3761         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3762       }
3763     return \"\";
3764   }"
3765   [(set_attr "length" "2,6")
3766    (set_attr "type" "load,load")
3767    (set_attr "pool_range" "32,32")]
3768 )
3769
3770 (define_expand "extendsfdf2"
3771   [(set (match_operand:DF                  0 "s_register_operand" "")
3772         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
3773   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3774   ""
3775 )
3776 \f
3777 ;; Move insns (including loads and stores)
3778
3779 ;; XXX Just some ideas about movti.
3780 ;; I don't think these are a good idea on the arm, there just aren't enough
3781 ;; registers
3782 ;;(define_expand "loadti"
3783 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3784 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3785 ;;  "" "")
3786
3787 ;;(define_expand "storeti"
3788 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3789 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3790 ;;  "" "")
3791
3792 ;;(define_expand "movti"
3793 ;;  [(set (match_operand:TI 0 "general_operand" "")
3794 ;;      (match_operand:TI 1 "general_operand" ""))]
3795 ;;  ""
3796 ;;  "
3797 ;;{
3798 ;;  rtx insn;
3799 ;;
3800 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3801 ;;    operands[1] = copy_to_reg (operands[1]);
3802 ;;  if (GET_CODE (operands[0]) == MEM)
3803 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3804 ;;  else if (GET_CODE (operands[1]) == MEM)
3805 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3806 ;;  else
3807 ;;    FAIL;
3808 ;;
3809 ;;  emit_insn (insn);
3810 ;;  DONE;
3811 ;;}")
3812
3813 ;; Recognize garbage generated above.
3814
3815 ;;(define_insn ""
3816 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3817 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3818 ;;  ""
3819 ;;  "*
3820 ;;  {
3821 ;;    register mem = (which_alternative < 3);
3822 ;;    register const char *template;
3823 ;;
3824 ;;    operands[mem] = XEXP (operands[mem], 0);
3825 ;;    switch (which_alternative)
3826 ;;      {
3827 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3828 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3829 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3830 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3831 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3832 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3833 ;;      }
3834 ;;    output_asm_insn (template, operands);
3835 ;;    return \"\";
3836 ;;  }")
3837
3838 (define_expand "movdi"
3839   [(set (match_operand:DI 0 "general_operand" "")
3840         (match_operand:DI 1 "general_operand" ""))]
3841   "TARGET_EITHER"
3842   "
3843   if (TARGET_THUMB)
3844     {
3845       if (!no_new_pseudos)
3846         {
3847           if (GET_CODE (operands[0]) != REG)
3848             operands[1] = force_reg (DImode, operands[1]);
3849         }
3850     }
3851   "
3852 )
3853
3854 (define_insn "*arm_movdi"
3855   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3856         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3857   "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT"
3858   "*
3859   return (output_move_double (operands));
3860   "
3861   [(set_attr "length" "8")
3862    (set_attr "type" "*,load,store2")
3863    (set_attr "pool_range" "*,1020,*")
3864    (set_attr "neg_pool_range" "*,1008,*")]
3865 )
3866
3867 ;;; ??? This should have alternatives for constants.
3868 ;;; ??? This was originally identical to the movdf_insn pattern.
3869 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3870 ;;; thumb_reorg with a memory reference.
3871 (define_insn "*thumb_movdi_insn"
3872   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3873         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3874   "TARGET_THUMB
3875    && !TARGET_CIRRUS
3876    && (   register_operand (operands[0], DImode)
3877        || register_operand (operands[1], DImode))"
3878   "*
3879   {
3880   switch (which_alternative)
3881     {
3882     default:
3883     case 0:
3884       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3885         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3886       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3887     case 1:
3888       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3889     case 2:
3890       operands[1] = GEN_INT (- INTVAL (operands[1]));
3891       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3892     case 3:
3893       return \"ldmia\\t%1, {%0, %H0}\";
3894     case 4:
3895       return \"stmia\\t%0, {%1, %H1}\";
3896     case 5:
3897       return thumb_load_double_from_address (operands);
3898     case 6:
3899       operands[2] = gen_rtx (MEM, SImode,
3900                              plus_constant (XEXP (operands[0], 0), 4));
3901       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3902       return \"\";
3903     case 7:
3904       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3905         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3906       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3907     }
3908   }"
3909   [(set_attr "length" "4,4,6,2,2,6,4,4")
3910    (set_attr "type" "*,*,*,load,store2,load,store2,*")
3911    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3912 )
3913
3914 (define_expand "movsi"
3915   [(set (match_operand:SI 0 "general_operand" "")
3916         (match_operand:SI 1 "general_operand" ""))]
3917   "TARGET_EITHER"
3918   "
3919   if (TARGET_ARM)
3920     {
3921       /* Everything except mem = const or mem = mem can be done easily */
3922       if (GET_CODE (operands[0]) == MEM)
3923         operands[1] = force_reg (SImode, operands[1]);
3924       if (GET_CODE (operands[1]) == CONST_INT
3925           && !(const_ok_for_arm (INTVAL (operands[1]))
3926                || const_ok_for_arm (~INTVAL (operands[1]))))
3927         {
3928            arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3929                               NULL_RTX,
3930                               (no_new_pseudos ? 0
3931                                : preserve_subexpressions_p ()));
3932           DONE;
3933         }
3934     }
3935   else /* TARGET_THUMB.... */
3936     {
3937       if (!no_new_pseudos)
3938         {
3939           if (GET_CODE (operands[0]) != REG)
3940             operands[1] = force_reg (SImode, operands[1]);
3941         }
3942     }
3943     
3944   if (flag_pic
3945       && (CONSTANT_P (operands[1])
3946          || symbol_mentioned_p (operands[1])
3947          || label_mentioned_p (operands[1])))
3948     operands[1] = legitimize_pic_address (operands[1], SImode,
3949                                           (no_new_pseudos ? operands[0] : 0));
3950   "
3951 )
3952
3953 (define_insn "*arm_movsi_insn"
3954   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3955         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
3956   "TARGET_ARM && ! TARGET_IWMMXT
3957    && (   register_operand (operands[0], SImode)
3958        || register_operand (operands[1], SImode))"
3959   "@
3960    mov%?\\t%0, %1
3961    mvn%?\\t%0, #%B1
3962    ldr%?\\t%0, %1
3963    str%?\\t%1, %0"
3964   [(set_attr "type" "*,*,load,store1")
3965    (set_attr "predicable" "yes")
3966    (set_attr "pool_range" "*,*,4096,*")
3967    (set_attr "neg_pool_range" "*,*,4084,*")]
3968 )
3969
3970 (define_split
3971   [(set (match_operand:SI 0 "s_register_operand" "")
3972         (match_operand:SI 1 "const_int_operand" ""))]
3973   "TARGET_ARM
3974   && (!(const_ok_for_arm (INTVAL (operands[1]))
3975         || const_ok_for_arm (~INTVAL (operands[1]))))"
3976   [(clobber (const_int 0))]
3977   "
3978   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3979                       NULL_RTX, 0);
3980   DONE;
3981   "
3982 )
3983
3984 (define_insn "*thumb_movsi_insn"
3985   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3986         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
3987   "TARGET_THUMB
3988    && (   register_operand (operands[0], SImode) 
3989        || register_operand (operands[1], SImode))"
3990   "@
3991    mov  %0, %1
3992    mov  %0, %1
3993    #
3994    #
3995    ldmia\\t%1, {%0}
3996    stmia\\t%0, {%1}
3997    ldr\\t%0, %1
3998    str\\t%1, %0
3999    mov\\t%0, %1"
4000   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4001    (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4002    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4003 )
4004
4005 (define_split 
4006   [(set (match_operand:SI 0 "register_operand" "")
4007         (match_operand:SI 1 "const_int_operand" ""))]
4008   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4009   [(set (match_dup 0) (match_dup 1))
4010    (set (match_dup 0) (neg:SI (match_dup 0)))]
4011   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4012 )
4013
4014 (define_split 
4015   [(set (match_operand:SI 0 "register_operand" "")
4016         (match_operand:SI 1 "const_int_operand" ""))]
4017   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4018   [(set (match_dup 0) (match_dup 1))
4019    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4020   "
4021   {
4022     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4023     unsigned HOST_WIDE_INT mask = 0xff;
4024     int i;
4025     
4026     for (i = 0; i < 25; i++)
4027       if ((val & (mask << i)) == val)
4028         break;
4029
4030     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4031     if (i == 0)
4032       FAIL;
4033
4034     operands[1] = GEN_INT (val >> i);
4035     operands[2] = GEN_INT (i);
4036   }"
4037 )
4038
4039 ;; When generating pic, we need to load the symbol offset into a register.
4040 ;; So that the optimizer does not confuse this with a normal symbol load
4041 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4042 ;; since that is the only type of relocation we can use.
4043
4044 ;; The rather odd constraints on the following are to force reload to leave
4045 ;; the insn alone, and to force the minipool generation pass to then move
4046 ;; the GOT symbol to memory.
4047
4048 (define_insn "pic_load_addr_arm"
4049   [(set (match_operand:SI 0 "s_register_operand" "=r")
4050         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4051   "TARGET_ARM && flag_pic"
4052   "ldr%?\\t%0, %1"
4053   [(set_attr "type" "load")
4054    (set (attr "pool_range")     (const_int 4096))
4055    (set (attr "neg_pool_range") (const_int 4084))]
4056 )
4057
4058 (define_insn "pic_load_addr_thumb"
4059   [(set (match_operand:SI 0 "s_register_operand" "=l")
4060         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4061   "TARGET_THUMB && flag_pic"
4062   "ldr\\t%0, %1"
4063   [(set_attr "type" "load")
4064    (set (attr "pool_range") (const_int 1024))]
4065 )
4066
4067 ;; This variant is used for AOF assembly, since it needs to mention the
4068 ;; pic register in the rtl.
4069 (define_expand "pic_load_addr_based"
4070   [(set (match_operand:SI 0 "s_register_operand" "")
4071         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4072   "TARGET_ARM && flag_pic"
4073   "operands[2] = pic_offset_table_rtx;"
4074 )
4075
4076 (define_insn "*pic_load_addr_based_insn"
4077   [(set (match_operand:SI 0 "s_register_operand" "=r")
4078         (unspec:SI [(match_operand 1 "" "")
4079                     (match_operand 2 "s_register_operand" "r")]
4080                    UNSPEC_PIC_SYM))]
4081   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4082   "*
4083 #ifdef AOF_ASSEMBLER
4084   operands[1] = aof_pic_entry (operands[1]);
4085 #endif
4086   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4087   return \"\";
4088   "
4089   [(set_attr "type" "load")
4090    (set (attr "pool_range")
4091         (if_then_else (eq_attr "is_thumb" "yes")
4092                       (const_int 1024)
4093                       (const_int 4096)))
4094    (set (attr "neg_pool_range")
4095         (if_then_else (eq_attr "is_thumb" "yes")
4096                       (const_int 0)
4097                       (const_int 4084)))]
4098 )
4099
4100 (define_insn "pic_add_dot_plus_four"
4101   [(set (match_operand:SI 0 "register_operand" "+r")
4102         (unspec:SI [(plus:SI (match_dup 0)
4103                              (const (plus:SI (pc) (const_int 4))))]
4104                    UNSPEC_PIC_BASE))
4105    (use (label_ref (match_operand 1 "" "")))]
4106   "TARGET_THUMB && flag_pic"
4107   "*
4108   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4109                              CODE_LABEL_NUMBER (operands[1]));
4110   return \"add\\t%0, %|pc\";
4111   "
4112   [(set_attr "length" "2")]
4113 )
4114
4115 (define_insn "pic_add_dot_plus_eight"
4116   [(set (match_operand:SI 0 "register_operand" "+r")
4117         (unspec:SI [(plus:SI (match_dup 0)
4118                              (const (plus:SI (pc) (const_int 8))))]
4119                    UNSPEC_PIC_BASE))
4120    (use (label_ref (match_operand 1 "" "")))]
4121   "TARGET_ARM && flag_pic"
4122   "*
4123     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4124                                CODE_LABEL_NUMBER (operands[1]));
4125     return \"add%?\\t%0, %|pc, %0\";
4126   "
4127   [(set_attr "predicable" "yes")]
4128 )
4129
4130 (define_expand "builtin_setjmp_receiver"
4131   [(label_ref (match_operand 0 "" ""))]
4132   "flag_pic"
4133   "
4134 {
4135   arm_finalize_pic (0);
4136   DONE;
4137 }")
4138
4139 ;; If copying one reg to another we can set the condition codes according to
4140 ;; its value.  Such a move is common after a return from subroutine and the
4141 ;; result is being tested against zero.
4142
4143 (define_insn "*movsi_compare0"
4144   [(set (reg:CC CC_REGNUM)
4145         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4146                     (const_int 0)))
4147    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4148         (match_dup 1))]
4149   "TARGET_ARM"
4150   "@
4151    cmp%?\\t%0, #0
4152    sub%?s\\t%0, %1, #0"
4153   [(set_attr "conds" "set")]
4154 )
4155
4156 ;; Subroutine to store a half word from a register into memory.
4157 ;; Operand 0 is the source register (HImode)
4158 ;; Operand 1 is the destination address in a register (SImode)
4159
4160 ;; In both this routine and the next, we must be careful not to spill
4161 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4162 ;; can generate unrecognizable rtl.
4163
4164 (define_expand "storehi"
4165   [;; store the low byte
4166    (set (match_operand 1 "" "") (match_dup 3))
4167    ;; extract the high byte
4168    (set (match_dup 2)
4169         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4170    ;; store the high byte
4171    (set (match_dup 4) (match_dup 5))]
4172   "TARGET_ARM"
4173   "
4174   {
4175     rtx op1 = operands[1];
4176     rtx addr = XEXP (op1, 0);
4177     enum rtx_code code = GET_CODE (addr);
4178
4179     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4180         || code == MINUS)
4181       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4182
4183     operands[4] = adjust_address (op1, QImode, 1);
4184     operands[1] = adjust_address (operands[1], QImode, 0);
4185     operands[3] = gen_lowpart (QImode, operands[0]);
4186     operands[0] = gen_lowpart (SImode, operands[0]);
4187     operands[2] = gen_reg_rtx (SImode);
4188     operands[5] = gen_lowpart (QImode, operands[2]);
4189   }"
4190 )
4191
4192 (define_expand "storehi_bigend"
4193   [(set (match_dup 4) (match_dup 3))
4194    (set (match_dup 2)
4195         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4196    (set (match_operand 1 "" "") (match_dup 5))]
4197   "TARGET_ARM"
4198   "
4199   {
4200     rtx op1 = operands[1];
4201     rtx addr = XEXP (op1, 0);
4202     enum rtx_code code = GET_CODE (addr);
4203
4204     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4205         || code == MINUS)
4206       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4207
4208     operands[4] = adjust_address (op1, QImode, 1);
4209     operands[1] = adjust_address (operands[1], QImode, 0);
4210     operands[3] = gen_lowpart (QImode, operands[0]);
4211     operands[0] = gen_lowpart (SImode, operands[0]);
4212     operands[2] = gen_reg_rtx (SImode);
4213     operands[5] = gen_lowpart (QImode, operands[2]);
4214   }"
4215 )
4216
4217 ;; Subroutine to store a half word integer constant into memory.
4218 (define_expand "storeinthi"
4219   [(set (match_operand 0 "" "")
4220         (match_operand 1 "" ""))
4221    (set (match_dup 3) (match_dup 2))]
4222   "TARGET_ARM"
4223   "
4224   {
4225     HOST_WIDE_INT value = INTVAL (operands[1]);
4226     rtx addr = XEXP (operands[0], 0);
4227     rtx op0 = operands[0];
4228     enum rtx_code code = GET_CODE (addr);
4229
4230     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4231         || code == MINUS)
4232       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4233
4234     operands[1] = gen_reg_rtx (SImode);
4235     if (BYTES_BIG_ENDIAN)
4236       {
4237         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4238         if ((value & 255) == ((value >> 8) & 255))
4239           operands[2] = operands[1];
4240         else
4241           {
4242             operands[2] = gen_reg_rtx (SImode);
4243             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4244           }
4245       }
4246     else
4247       {
4248         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4249         if ((value & 255) == ((value >> 8) & 255))
4250           operands[2] = operands[1];
4251         else
4252           {
4253             operands[2] = gen_reg_rtx (SImode);
4254             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4255           }
4256       }
4257
4258     operands[3] = adjust_address (op0, QImode, 1);
4259     operands[0] = adjust_address (operands[0], QImode, 0);
4260     operands[2] = gen_lowpart (QImode, operands[2]);
4261     operands[1] = gen_lowpart (QImode, operands[1]);
4262   }"
4263 )
4264
4265 (define_expand "storehi_single_op"
4266   [(set (match_operand:HI 0 "memory_operand" "")
4267         (match_operand:HI 1 "general_operand" ""))]
4268   "TARGET_ARM && arm_arch4"
4269   "
4270   if (!s_register_operand (operands[1], HImode))
4271     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4272   "
4273 )
4274
4275 (define_expand "movhi"
4276   [(set (match_operand:HI 0 "general_operand" "")
4277         (match_operand:HI 1 "general_operand" ""))]
4278   "TARGET_EITHER"
4279   "
4280   if (TARGET_ARM)
4281     {
4282       if (!no_new_pseudos)
4283         {
4284           if (GET_CODE (operands[0]) == MEM)
4285             {
4286               if (arm_arch4)
4287                 {
4288                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4289                   DONE;
4290                 }
4291               if (GET_CODE (operands[1]) == CONST_INT)
4292                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4293               else
4294                 {
4295                   if (GET_CODE (operands[1]) == MEM)
4296                     operands[1] = force_reg (HImode, operands[1]);
4297                   if (BYTES_BIG_ENDIAN)
4298                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4299                   else
4300                    emit_insn (gen_storehi (operands[1], operands[0]));
4301                 }
4302               DONE;
4303             }
4304           /* Sign extend a constant, and keep it in an SImode reg.  */
4305           else if (GET_CODE (operands[1]) == CONST_INT)
4306             {
4307               rtx reg = gen_reg_rtx (SImode);
4308               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4309
4310               /* If the constant is already valid, leave it alone.  */
4311               if (!const_ok_for_arm (val))
4312                 {
4313                   /* If setting all the top bits will make the constant 
4314                      loadable in a single instruction, then set them.  
4315                      Otherwise, sign extend the number.  */
4316
4317                   if (const_ok_for_arm (~(val | ~0xffff)))
4318                     val |= ~0xffff;
4319                   else if (val & 0x8000)
4320                     val |= ~0xffff;
4321                 }
4322
4323               emit_insn (gen_movsi (reg, GEN_INT (val)));
4324               operands[1] = gen_lowpart (HImode, reg);
4325             }
4326           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4327                    && GET_CODE (operands[1]) == MEM)
4328             {
4329               rtx reg = gen_reg_rtx (SImode);
4330
4331               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4332               operands[1] = gen_lowpart (HImode, reg);
4333             }
4334           else if (!arm_arch4)
4335             {
4336              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4337                 for v4 and up architectures because LDRH instructions will
4338                 be used to access the HI values, and these cannot generate
4339                 unaligned word access faults in the MMU.  */
4340               if (GET_CODE (operands[1]) == MEM)
4341                 {
4342                   if (TARGET_MMU_TRAPS)
4343                     {
4344                       rtx base;
4345                       rtx offset = const0_rtx;
4346                       rtx reg = gen_reg_rtx (SImode);
4347
4348                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4349                            || (GET_CODE (base) == PLUS
4350                                && (GET_CODE (offset = XEXP (base, 1))
4351                                    == CONST_INT)
4352                                && ((INTVAL(offset) & 1) != 1)
4353                                && GET_CODE (base = XEXP (base, 0)) == REG))
4354                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4355                         {
4356                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4357                           rtx new;
4358
4359                           new = gen_rtx_MEM (SImode,
4360                                              plus_constant (base, new_offset));
4361                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4362                           emit_insn (gen_movsi (reg, new));
4363                           if (((INTVAL (offset) & 2) != 0)
4364                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4365                             {
4366                               rtx reg2 = gen_reg_rtx (SImode);
4367
4368                               emit_insn (gen_lshrsi3 (reg2, reg,
4369                                          GEN_INT (16)));
4370                               reg = reg2;
4371                             }
4372                         }
4373                       else
4374                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4375
4376                       operands[1] = gen_lowpart (HImode, reg);
4377                     }
4378                   else if (BYTES_BIG_ENDIAN)
4379                     {
4380                       rtx base;
4381                       rtx offset = const0_rtx;
4382
4383                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4384                            || (GET_CODE (base) == PLUS
4385                               && (GET_CODE (offset = XEXP (base, 1))
4386                                   == CONST_INT)
4387                               && GET_CODE (base = XEXP (base, 0)) == REG))
4388                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4389                         {
4390                           rtx reg = gen_reg_rtx (SImode);
4391                           rtx new;
4392
4393                           if ((INTVAL (offset) & 2) == 2)
4394                             {
4395                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4396                               new = gen_rtx_MEM (SImode,
4397                                                  plus_constant (base,
4398                                                                 new_offset));
4399                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4400                               emit_insn (gen_movsi (reg, new));
4401                             }
4402                           else
4403                             {
4404                               new = gen_rtx_MEM (SImode,
4405                                                  XEXP (operands[1], 0));
4406                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4407                               emit_insn (gen_rotated_loadsi (reg, new));
4408                             }
4409
4410                           operands[1] = gen_lowpart (HImode, reg);
4411                         }
4412                       else
4413                         {
4414                           emit_insn (gen_movhi_bigend (operands[0],
4415                                                        operands[1]));
4416                           DONE;
4417                         }
4418                     }
4419                }
4420            }
4421         }
4422       /* Handle loading a large integer during reload */
4423       else if (GET_CODE (operands[1]) == CONST_INT
4424                && !const_ok_for_arm (INTVAL (operands[1]))
4425                && !const_ok_for_arm (~INTVAL (operands[1])))
4426         {
4427           /* Writing a constant to memory needs a scratch, which should
4428              be handled with SECONDARY_RELOADs.  */
4429           if (GET_CODE (operands[0]) != REG)
4430             abort ();
4431
4432           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4433           emit_insn (gen_movsi (operands[0], operands[1]));
4434           DONE;
4435        }
4436     }
4437   else /* TARGET_THUMB */
4438     {
4439       if (!no_new_pseudos)
4440         {
4441           if (GET_CODE (operands[0]) != REG)
4442             operands[1] = force_reg (HImode, operands[1]);
4443
4444           /* ??? We shouldn't really get invalid addresses here, but this can
4445              happen if we are passed a SP (never OK for HImode/QImode) or 
4446              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4447              HImode/QImode) relative address.  */
4448           /* ??? This should perhaps be fixed elsewhere, for instance, in
4449              fixup_stack_1, by checking for other kinds of invalid addresses,
4450              e.g. a bare reference to a virtual register.  This may confuse the
4451              alpha though, which must handle this case differently.  */
4452           if (GET_CODE (operands[0]) == MEM
4453               && !memory_address_p (GET_MODE (operands[0]),
4454                                     XEXP (operands[0], 0)))
4455             operands[0]
4456               = replace_equiv_address (operands[0],
4457                                        copy_to_reg (XEXP (operands[0], 0)));
4458    
4459           if (GET_CODE (operands[1]) == MEM
4460               && !memory_address_p (GET_MODE (operands[1]),
4461                                     XEXP (operands[1], 0)))
4462             operands[1]
4463               = replace_equiv_address (operands[1],
4464                                        copy_to_reg (XEXP (operands[1], 0)));
4465         }
4466       /* Handle loading a large integer during reload */
4467       else if (GET_CODE (operands[1]) == CONST_INT
4468                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4469         {
4470           /* Writing a constant to memory needs a scratch, which should
4471              be handled with SECONDARY_RELOADs.  */
4472           if (GET_CODE (operands[0]) != REG)
4473             abort ();
4474
4475           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4476           emit_insn (gen_movsi (operands[0], operands[1]));
4477           DONE;
4478         }
4479     }
4480   "
4481 )
4482
4483 (define_insn "*thumb_movhi_insn"
4484   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4485         (match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4486   "TARGET_THUMB
4487    && (   register_operand (operands[0], HImode)
4488        || register_operand (operands[1], HImode))"
4489   "*
4490   switch (which_alternative)
4491     {
4492     case 0: return \"add        %0, %1, #0\";
4493     case 2: return \"strh       %1, %0\";
4494     case 3: return \"mov        %0, %1\";
4495     case 4: return \"mov        %0, %1\";
4496     case 5: return \"mov        %0, %1\";
4497     default: abort ();
4498     case 1:
4499       /* The stack pointer can end up being taken as an index register.
4500           Catch this case here and deal with it.  */
4501       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4502           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4503           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4504         {
4505           rtx ops[2];
4506           ops[0] = operands[0];
4507           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4508       
4509           output_asm_insn (\"mov        %0, %1\", ops);
4510
4511           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4512     
4513         }
4514       return \"ldrh     %0, %1\";
4515     }"
4516   [(set_attr "length" "2,4,2,2,2,2")
4517    (set_attr "type" "*,load,store1,*,*,*")
4518    (set_attr "pool_range" "*,64,*,*,*,*")]
4519 )
4520
4521
4522 (define_insn "rotated_loadsi"
4523   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4524         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4525                    (const_int 16)))]
4526   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4527   "*
4528   {
4529     rtx ops[2];
4530
4531     ops[0] = operands[0];
4532     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4533     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4534     return \"\";
4535   }"
4536   [(set_attr "type" "load")
4537    (set_attr "predicable" "yes")]
4538 )
4539
4540 (define_expand "movhi_bytes"
4541   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4542    (set (match_dup 3)
4543         (zero_extend:SI (match_dup 6)))
4544    (set (match_operand:SI 0 "" "")
4545          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4546   "TARGET_ARM"
4547   "
4548   {
4549     rtx mem1, mem2;
4550     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4551
4552     mem1 = gen_rtx_MEM (QImode, addr);
4553     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4554     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4555     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4556     operands[0] = gen_lowpart (SImode, operands[0]);
4557     operands[1] = mem1;
4558     operands[2] = gen_reg_rtx (SImode);
4559     operands[3] = gen_reg_rtx (SImode);
4560     operands[6] = mem2;
4561
4562     if (BYTES_BIG_ENDIAN)
4563       {
4564         operands[4] = operands[2];
4565         operands[5] = operands[3];
4566       }
4567     else
4568       {
4569         operands[4] = operands[3];
4570         operands[5] = operands[2];
4571       }
4572   }"
4573 )
4574
4575 (define_expand "movhi_bigend"
4576   [(set (match_dup 2)
4577         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4578                    (const_int 16)))
4579    (set (match_dup 3)
4580         (ashiftrt:SI (match_dup 2) (const_int 16)))
4581    (set (match_operand:HI 0 "s_register_operand" "")
4582         (match_dup 4))]
4583   "TARGET_ARM"
4584   "
4585   operands[2] = gen_reg_rtx (SImode);
4586   operands[3] = gen_reg_rtx (SImode);
4587   operands[4] = gen_lowpart (HImode, operands[3]);
4588   "
4589 )
4590
4591 ;; Pattern to recognize insn generated default case above
4592 (define_insn "*movhi_insn_arch4"
4593   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4594         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4595   "TARGET_ARM
4596    && arm_arch4
4597    && (GET_CODE (operands[1]) != CONST_INT
4598        || const_ok_for_arm (INTVAL (operands[1]))
4599        || const_ok_for_arm (~INTVAL (operands[1])))"
4600   "@
4601    mov%?\\t%0, %1\\t%@ movhi
4602    mvn%?\\t%0, #%B1\\t%@ movhi
4603    str%?h\\t%1, %0\\t%@ movhi 
4604    ldr%?h\\t%0, %1\\t%@ movhi"
4605   [(set_attr "type" "*,*,store1,load")
4606    (set_attr "predicable" "yes")
4607    (set_attr "pool_range" "*,*,*,256")
4608    (set_attr "neg_pool_range" "*,*,*,244")]
4609 )
4610
4611 (define_insn "*movhi_insn_littleend"
4612   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4613         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4614   "TARGET_ARM
4615    && !arm_arch4
4616    && !BYTES_BIG_ENDIAN
4617    && !TARGET_MMU_TRAPS
4618    && (GET_CODE (operands[1]) != CONST_INT
4619        || const_ok_for_arm (INTVAL (operands[1]))
4620        || const_ok_for_arm (~INTVAL (operands[1])))"
4621   "@
4622    mov%?\\t%0, %1\\t%@ movhi
4623    mvn%?\\t%0, #%B1\\t%@ movhi
4624    ldr%?\\t%0, %1\\t%@ movhi"
4625   [(set_attr "type" "*,*,load")
4626    (set_attr "predicable" "yes")
4627    (set_attr "pool_range" "4096")
4628    (set_attr "neg_pool_range" "4084")]
4629 )
4630
4631 (define_insn "*movhi_insn_bigend"
4632   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4633         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4634   "TARGET_ARM
4635    && !arm_arch4
4636    && BYTES_BIG_ENDIAN
4637    && !TARGET_MMU_TRAPS
4638    && (GET_CODE (operands[1]) != CONST_INT
4639        || const_ok_for_arm (INTVAL (operands[1]))
4640        || const_ok_for_arm (~INTVAL (operands[1])))"
4641   "@
4642    mov%?\\t%0, %1\\t%@ movhi
4643    mvn%?\\t%0, #%B1\\t%@ movhi
4644    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4645   [(set_attr "type" "*,*,load")
4646    (set_attr "predicable" "yes")
4647    (set_attr "length" "4,4,8")
4648    (set_attr "pool_range" "*,*,4092")
4649    (set_attr "neg_pool_range" "*,*,4084")]
4650 )
4651
4652 (define_insn "*loadhi_si_bigend"
4653   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4654         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4655                    (const_int 16)))]
4656   "TARGET_ARM
4657    && BYTES_BIG_ENDIAN
4658    && !TARGET_MMU_TRAPS"
4659   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4660   [(set_attr "type" "load")
4661    (set_attr "predicable" "yes")
4662    (set_attr "pool_range" "4096")
4663    (set_attr "neg_pool_range" "4084")]
4664 )
4665
4666 (define_insn "*movhi_bytes"
4667   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4668         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4669   "TARGET_ARM && TARGET_MMU_TRAPS"
4670   "@
4671    mov%?\\t%0, %1\\t%@ movhi
4672    mvn%?\\t%0, #%B1\\t%@ movhi"
4673   [(set_attr "predicable" "yes")]
4674 )
4675
4676 (define_insn "thumb_movhi_clobber"
4677   [(set (match_operand:HI     0 "memory_operand"   "=m")
4678         (match_operand:HI     1 "register_operand" "l"))
4679    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4680   "TARGET_THUMB"
4681   "*
4682   abort ();"
4683 )
4684         
4685 ;; We use a DImode scratch because we may occasionally need an additional
4686 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4687 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4688 (define_expand "reload_outhi"
4689   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4690               (match_operand:HI 1 "s_register_operand"        "r")
4691               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4692   "TARGET_EITHER"
4693   "if (TARGET_ARM)
4694      arm_reload_out_hi (operands);
4695    else
4696      thumb_reload_out_hi (operands);
4697   DONE;
4698   "
4699 )
4700
4701 (define_expand "reload_inhi"
4702   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4703               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4704               (match_operand:DI 2 "s_register_operand" "=&r")])]
4705   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4706   "
4707   if (TARGET_ARM)
4708     arm_reload_in_hi (operands);
4709   else
4710     thumb_reload_out_hi (operands);
4711   DONE;
4712 ")
4713
4714 (define_expand "movqi"
4715   [(set (match_operand:QI 0 "general_operand" "")
4716         (match_operand:QI 1 "general_operand" ""))]
4717   "TARGET_EITHER"
4718   "
4719   if (TARGET_ARM)
4720     {
4721       /* Everything except mem = const or mem = mem can be done easily */
4722
4723       if (!no_new_pseudos)
4724         {
4725           if (GET_CODE (operands[1]) == CONST_INT)
4726             {
4727               rtx reg = gen_reg_rtx (SImode);
4728
4729               emit_insn (gen_movsi (reg, operands[1]));
4730               operands[1] = gen_lowpart (QImode, reg);
4731             }
4732           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4733             {
4734               rtx reg = gen_reg_rtx (SImode);
4735
4736               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4737               operands[1] = gen_lowpart (QImode, reg);
4738             }
4739           if (GET_CODE (operands[0]) == MEM)
4740             operands[1] = force_reg (QImode, operands[1]);
4741         }
4742     }
4743   else /* TARGET_THUMB */
4744     {
4745       if (!no_new_pseudos)
4746         {
4747           if (GET_CODE (operands[0]) != REG)
4748             operands[1] = force_reg (QImode, operands[1]);
4749
4750           /* ??? We shouldn't really get invalid addresses here, but this can
4751              happen if we are passed a SP (never OK for HImode/QImode) or
4752              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4753              HImode/QImode) relative address.  */
4754           /* ??? This should perhaps be fixed elsewhere, for instance, in
4755              fixup_stack_1, by checking for other kinds of invalid addresses,
4756              e.g. a bare reference to a virtual register.  This may confuse the
4757              alpha though, which must handle this case differently.  */
4758           if (GET_CODE (operands[0]) == MEM
4759               && !memory_address_p (GET_MODE (operands[0]),
4760                                      XEXP (operands[0], 0)))
4761             operands[0]
4762               = replace_equiv_address (operands[0],
4763                                        copy_to_reg (XEXP (operands[0], 0)));
4764           if (GET_CODE (operands[1]) == MEM
4765               && !memory_address_p (GET_MODE (operands[1]),
4766                                     XEXP (operands[1], 0)))
4767              operands[1]
4768                = replace_equiv_address (operands[1],
4769                                         copy_to_reg (XEXP (operands[1], 0)));
4770         }
4771       /* Handle loading a large integer during reload */
4772       else if (GET_CODE (operands[1]) == CONST_INT
4773                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4774         {
4775           /* Writing a constant to memory needs a scratch, which should
4776              be handled with SECONDARY_RELOADs.  */
4777           if (GET_CODE (operands[0]) != REG)
4778             abort ();
4779
4780           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4781           emit_insn (gen_movsi (operands[0], operands[1]));
4782           DONE;
4783        }
4784     }
4785   "
4786 )
4787
4788
4789 (define_insn "*arm_movqi_insn"
4790   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4791         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4792   "TARGET_ARM
4793    && (   register_operand (operands[0], QImode)
4794        || register_operand (operands[1], QImode))"
4795   "@
4796    mov%?\\t%0, %1
4797    mvn%?\\t%0, #%B1
4798    ldr%?b\\t%0, %1
4799    str%?b\\t%1, %0"
4800   [(set_attr "type" "*,*,load,store1")
4801    (set_attr "predicable" "yes")]
4802 )
4803
4804 (define_insn "*thumb_movqi_insn"
4805   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4806         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4807   "TARGET_THUMB
4808    && (   register_operand (operands[0], QImode)
4809        || register_operand (operands[1], QImode))"
4810   "@
4811    add\\t%0, %1, #0
4812    ldrb\\t%0, %1
4813    strb\\t%1, %0
4814    mov\\t%0, %1
4815    mov\\t%0, %1
4816    mov\\t%0, %1"
4817   [(set_attr "length" "2")
4818    (set_attr "type" "*,load,store1,*,*,*")
4819    (set_attr "pool_range" "*,32,*,*,*,*")]
4820 )
4821
4822 (define_expand "movsf"
4823   [(set (match_operand:SF 0 "general_operand" "")
4824         (match_operand:SF 1 "general_operand" ""))]
4825   "TARGET_EITHER"
4826   "
4827   if (TARGET_ARM)
4828     {
4829       if (GET_CODE (operands[0]) == MEM)
4830         operands[1] = force_reg (SFmode, operands[1]);
4831     }
4832   else /* TARGET_THUMB */
4833     {
4834       if (!no_new_pseudos)
4835         {
4836            if (GET_CODE (operands[0]) != REG)
4837              operands[1] = force_reg (SFmode, operands[1]);
4838         }
4839     }
4840   "
4841 )
4842
4843 (define_split
4844   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4845         (match_operand:SF 1 "immediate_operand" ""))]
4846   "TARGET_ARM
4847    && !TARGET_HARD_FLOAT
4848    && reload_completed
4849    && GET_CODE (operands[1]) == CONST_DOUBLE"
4850   [(set (match_dup 2) (match_dup 3))]
4851   "
4852   operands[2] = gen_lowpart (SImode, operands[0]);
4853   operands[3] = gen_lowpart (SImode, operands[1]);
4854   if (operands[2] == 0 || operands[3] == 0)
4855     FAIL;
4856   "
4857 )
4858
4859 (define_insn "*arm_movsf_soft_insn"
4860   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4861         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4862   "TARGET_ARM
4863    && !TARGET_CIRRUS
4864    && TARGET_SOFT_FLOAT
4865    && (GET_CODE (operands[0]) != MEM
4866        || register_operand (operands[1], SFmode))"
4867   "@
4868    mov%?\\t%0, %1
4869    ldr%?\\t%0, %1\\t%@ float
4870    str%?\\t%1, %0\\t%@ float"
4871   [(set_attr "length" "4,4,4")
4872    (set_attr "predicable" "yes")
4873    (set_attr "type" "*,load,store1")
4874    (set_attr "pool_range" "*,4096,*")
4875    (set_attr "neg_pool_range" "*,4084,*")]
4876 )
4877
4878 ;;; ??? This should have alternatives for constants.
4879 (define_insn "*thumb_movsf_insn"
4880   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4881         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4882   "TARGET_THUMB
4883    && (   register_operand (operands[0], SFmode) 
4884        || register_operand (operands[1], SFmode))"
4885   "@
4886    add\\t%0, %1, #0
4887    ldmia\\t%1, {%0}
4888    stmia\\t%0, {%1}
4889    ldr\\t%0, %1
4890    str\\t%1, %0
4891    mov\\t%0, %1
4892    mov\\t%0, %1"
4893   [(set_attr "length" "2")
4894    (set_attr "type" "*,load,store1,load,store1,*,*")
4895    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4896 )
4897
4898 (define_expand "movdf"
4899   [(set (match_operand:DF 0 "general_operand" "")
4900         (match_operand:DF 1 "general_operand" ""))]
4901   "TARGET_EITHER"
4902   "
4903   if (TARGET_ARM)
4904     {
4905       if (GET_CODE (operands[0]) == MEM)
4906         operands[1] = force_reg (DFmode, operands[1]);
4907     }
4908   else /* TARGET_THUMB */
4909     {
4910       if (!no_new_pseudos)
4911         {
4912           if (GET_CODE (operands[0]) != REG)
4913             operands[1] = force_reg (DFmode, operands[1]);
4914         }
4915     }
4916   "
4917 )
4918
4919 ;; Reloading a df mode value stored in integer regs to memory can require a
4920 ;; scratch reg.
4921 (define_expand "reload_outdf"
4922   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4923    (match_operand:DF 1 "s_register_operand" "r")
4924    (match_operand:SI 2 "s_register_operand" "=&r")]
4925   "TARGET_ARM"
4926   "
4927   {
4928     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4929
4930     if (code == REG)
4931       operands[2] = XEXP (operands[0], 0);
4932     else if (code == POST_INC || code == PRE_DEC)
4933       {
4934         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4935         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4936         emit_insn (gen_movdi (operands[0], operands[1]));
4937         DONE;
4938       }
4939     else if (code == PRE_INC)
4940       {
4941         rtx reg = XEXP (XEXP (operands[0], 0), 0);
4942
4943         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4944         operands[2] = reg;
4945       }
4946     else if (code == POST_DEC)
4947       operands[2] = XEXP (XEXP (operands[0], 0), 0);
4948     else
4949       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4950                              XEXP (XEXP (operands[0], 0), 1)));
4951
4952     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4953                             operands[1]));
4954
4955     if (code == POST_DEC)
4956       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4957
4958     DONE;
4959   }"
4960 )
4961
4962 (define_insn "*movdf_soft_insn"
4963   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4964         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4965   "TARGET_ARM && TARGET_SOFT_FLOAT
4966    && !TARGET_CIRRUS
4967   "
4968   "* return output_move_double (operands);"
4969   [(set_attr "length" "8,8,8")
4970    (set_attr "type" "*,load,store2")
4971    (set_attr "pool_range" "1020")
4972    (set_attr "neg_pool_range" "1008")]
4973 )
4974
4975 ;;; ??? This should have alternatives for constants.
4976 ;;; ??? This was originally identical to the movdi_insn pattern.
4977 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4978 ;;; thumb_reorg with a memory reference.
4979 (define_insn "*thumb_movdf_insn"
4980   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4981         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
4982   "TARGET_THUMB
4983    && (   register_operand (operands[0], DFmode)
4984        || register_operand (operands[1], DFmode))"
4985   "*
4986   switch (which_alternative)
4987     {
4988     default:
4989     case 0:
4990       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4991         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4992       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4993     case 1:
4994       return \"ldmia\\t%1, {%0, %H0}\";
4995     case 2:
4996       return \"stmia\\t%0, {%1, %H1}\";
4997     case 3:
4998       return thumb_load_double_from_address (operands);
4999     case 4:
5000       operands[2] = gen_rtx (MEM, SImode,
5001                              plus_constant (XEXP (operands[0], 0), 4));
5002       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5003       return \"\";
5004     case 5:
5005       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5006         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5007       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5008     }
5009   "
5010   [(set_attr "length" "4,2,2,6,4,4")
5011    (set_attr "type" "*,load,store2,load,store2,*")
5012    (set_attr "pool_range" "*,*,*,1020,*,*")]
5013 )
5014
5015 ;; Vector Moves
5016 (define_expand "movv2si"
5017   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5018         (match_operand:V2SI 1 "general_operand" ""))]
5019   "TARGET_REALLY_IWMMXT"
5020 {
5021 })
5022
5023 (define_expand "movv4hi"
5024   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5025         (match_operand:V4HI 1 "general_operand" ""))]
5026   "TARGET_REALLY_IWMMXT"
5027 {
5028 })
5029
5030 (define_expand "movv8qi"
5031   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5032         (match_operand:V8QI 1 "general_operand" ""))]
5033   "TARGET_REALLY_IWMMXT"
5034 {
5035 })
5036 \f
5037
5038 ;; load- and store-multiple insns
5039 ;; The arm can load/store any set of registers, provided that they are in
5040 ;; ascending order; but that is beyond GCC so stick with what it knows.
5041
5042 (define_expand "load_multiple"
5043   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5044                           (match_operand:SI 1 "" ""))
5045                      (use (match_operand:SI 2 "" ""))])]
5046   "TARGET_ARM"
5047   "
5048   /* Support only fixed point registers.  */
5049   if (GET_CODE (operands[2]) != CONST_INT
5050       || INTVAL (operands[2]) > 14
5051       || INTVAL (operands[2]) < 2
5052       || GET_CODE (operands[1]) != MEM
5053       || GET_CODE (operands[0]) != REG
5054       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5055       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5056     FAIL;
5057
5058   operands[3]
5059     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5060                              force_reg (SImode, XEXP (operands[1], 0)),
5061                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5062                              MEM_IN_STRUCT_P(operands[1]),
5063                              MEM_SCALAR_P (operands[1]));
5064   "
5065 )
5066
5067 ;; Load multiple with write-back
5068
5069 (define_insn "*ldmsi_postinc4"
5070   [(match_parallel 0 "load_multiple_operation"
5071     [(set (match_operand:SI 1 "s_register_operand" "=r")
5072           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5073                    (const_int 16)))
5074      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5075           (mem:SI (match_dup 2)))
5076      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5077           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5078      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5079           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5080      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5081           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5082   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5083   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5084   [(set_attr "type" "load")
5085    (set_attr "predicable" "yes")]
5086 )
5087
5088 (define_insn "*ldmsi_postinc3"
5089   [(match_parallel 0 "load_multiple_operation"
5090     [(set (match_operand:SI 1 "s_register_operand" "=r")
5091           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5092                    (const_int 12)))
5093      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5094           (mem:SI (match_dup 2)))
5095      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5096           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5097      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5098           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5099   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5100   "ldm%?ia\\t%1!, {%3, %4, %5}"
5101   [(set_attr "type" "load")
5102    (set_attr "predicable" "yes")]
5103 )
5104
5105 (define_insn "*ldmsi_postinc2"
5106   [(match_parallel 0 "load_multiple_operation"
5107     [(set (match_operand:SI 1 "s_register_operand" "=r")
5108           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5109                    (const_int 8)))
5110      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5111           (mem:SI (match_dup 2)))
5112      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5113           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5114   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5115   "ldm%?ia\\t%1!, {%3, %4}"
5116   [(set_attr "type" "load")
5117    (set_attr "predicable" "yes")]
5118 )
5119
5120 ;; Ordinary load multiple
5121
5122 (define_insn "*ldmsi4"
5123   [(match_parallel 0 "load_multiple_operation"
5124     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5125           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5126      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5127           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5128      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5129           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5130      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5131           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5132   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5133   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5134   [(set_attr "type" "load")
5135    (set_attr "predicable" "yes")]
5136 )
5137
5138 (define_insn "*ldmsi3"
5139   [(match_parallel 0 "load_multiple_operation"
5140     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5141           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5142      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5143           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5144      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5145           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5146   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5147   "ldm%?ia\\t%1, {%2, %3, %4}"
5148   [(set_attr "type" "load")
5149    (set_attr "predicable" "yes")]
5150 )
5151
5152 (define_insn "*ldmsi2"
5153   [(match_parallel 0 "load_multiple_operation"
5154     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5155           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5156      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5157           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5158   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5159   "ldm%?ia\\t%1, {%2, %3}"
5160   [(set_attr "type" "load")
5161    (set_attr "predicable" "yes")]
5162 )
5163
5164 (define_expand "store_multiple"
5165   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5166                           (match_operand:SI 1 "" ""))
5167                      (use (match_operand:SI 2 "" ""))])]
5168   "TARGET_ARM"
5169   "
5170   /* Support only fixed point registers */
5171   if (GET_CODE (operands[2]) != CONST_INT
5172       || INTVAL (operands[2]) > 14
5173       || INTVAL (operands[2]) < 2
5174       || GET_CODE (operands[1]) != REG
5175       || GET_CODE (operands[0]) != MEM
5176       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5177       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5178     FAIL;
5179
5180   operands[3]
5181     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5182                               force_reg (SImode, XEXP (operands[0], 0)),
5183                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5184                               MEM_IN_STRUCT_P(operands[0]), 
5185                               MEM_SCALAR_P (operands[0]));
5186   "
5187 )
5188
5189 ;; Store multiple with write-back
5190
5191 (define_insn "*stmsi_postinc4"
5192   [(match_parallel 0 "store_multiple_operation"
5193     [(set (match_operand:SI 1 "s_register_operand" "=r")
5194           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5195                    (const_int 16)))
5196      (set (mem:SI (match_dup 2))
5197           (match_operand:SI 3 "arm_hard_register_operand" ""))
5198      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5199           (match_operand:SI 4 "arm_hard_register_operand" ""))
5200      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5201           (match_operand:SI 5 "arm_hard_register_operand" ""))
5202      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5203           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5204   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5205   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5206   [(set_attr "predicable" "yes")
5207    (set_attr "type" "store4")]
5208 )
5209
5210 (define_insn "*stmsi_postinc3"
5211   [(match_parallel 0 "store_multiple_operation"
5212     [(set (match_operand:SI 1 "s_register_operand" "=r")
5213           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5214                    (const_int 12)))
5215      (set (mem:SI (match_dup 2))
5216           (match_operand:SI 3 "arm_hard_register_operand" ""))
5217      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5218           (match_operand:SI 4 "arm_hard_register_operand" ""))
5219      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5220           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5221   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5222   "stm%?ia\\t%1!, {%3, %4, %5}"
5223   [(set_attr "predicable" "yes")
5224    (set_attr "type" "store3")]
5225 )
5226
5227 (define_insn "*stmsi_postinc2"
5228   [(match_parallel 0 "store_multiple_operation"
5229     [(set (match_operand:SI 1 "s_register_operand" "=r")
5230           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5231                    (const_int 8)))
5232      (set (mem:SI (match_dup 2))
5233           (match_operand:SI 3 "arm_hard_register_operand" ""))
5234      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5235           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5236   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5237   "stm%?ia\\t%1!, {%3, %4}"
5238   [(set_attr "predicable" "yes")
5239    (set_attr "type" "store2")]
5240 )
5241
5242 ;; Ordinary store multiple
5243
5244 (define_insn "*stmsi4"
5245   [(match_parallel 0 "store_multiple_operation"
5246     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5247           (match_operand:SI 2 "arm_hard_register_operand" ""))
5248      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5249           (match_operand:SI 3 "arm_hard_register_operand" ""))
5250      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5251           (match_operand:SI 4 "arm_hard_register_operand" ""))
5252      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5253           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5254   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5255   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5256   [(set_attr "predicable" "yes")
5257    (set_attr "type" "store4")]
5258 )
5259
5260 (define_insn "*stmsi3"
5261   [(match_parallel 0 "store_multiple_operation"
5262     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5263           (match_operand:SI 2 "arm_hard_register_operand" ""))
5264      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5265           (match_operand:SI 3 "arm_hard_register_operand" ""))
5266      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5267           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5268   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5269   "stm%?ia\\t%1, {%2, %3, %4}"
5270   [(set_attr "predicable" "yes")
5271    (set_attr "type" "store3")]
5272 )
5273
5274 (define_insn "*stmsi2"
5275   [(match_parallel 0 "store_multiple_operation"
5276     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5277           (match_operand:SI 2 "arm_hard_register_operand" ""))
5278      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5279           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5280   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5281   "stm%?ia\\t%1, {%2, %3}"
5282   [(set_attr "predicable" "yes")
5283    (set_attr "type" "store2")]
5284 )
5285
5286 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5287 ;; We could let this apply for blocks of less than this, but it clobbers so
5288 ;; many registers that there is then probably a better way.
5289
5290 (define_expand "movstrqi"
5291   [(match_operand:BLK 0 "general_operand" "")
5292    (match_operand:BLK 1 "general_operand" "")
5293    (match_operand:SI 2 "const_int_operand" "")
5294    (match_operand:SI 3 "const_int_operand" "")]
5295   "TARGET_EITHER"
5296   "
5297   if (TARGET_ARM)
5298     {
5299       if (arm_gen_movstrqi (operands))
5300         DONE;
5301       FAIL;
5302     }
5303   else /* TARGET_THUMB */
5304     {
5305       if (   INTVAL (operands[3]) != 4
5306           || INTVAL (operands[2]) > 48)
5307         FAIL;
5308
5309       thumb_expand_movstrqi (operands);
5310       DONE;
5311     }
5312   "
5313 )
5314
5315 ;; Thumb block-move insns
5316
5317 (define_insn "movmem12b"
5318   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5319         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5320    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5321         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5322    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5323         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5324    (set (match_operand:SI 0 "register_operand" "=l")
5325         (plus:SI (match_dup 2) (const_int 12)))
5326    (set (match_operand:SI 1 "register_operand" "=l")
5327         (plus:SI (match_dup 3) (const_int 12)))
5328    (clobber (match_scratch:SI 4 "=&l"))
5329    (clobber (match_scratch:SI 5 "=&l"))
5330    (clobber (match_scratch:SI 6 "=&l"))]
5331   "TARGET_THUMB"
5332   "* return thumb_output_move_mem_multiple (3, operands);"
5333   [(set_attr "length" "4")
5334    ; This isn't entirely accurate...  It loads as well, but in terms of
5335    ; scheduling the following insn it is better to consider it as a store
5336    (set_attr "type" "store3")]
5337 )
5338
5339 (define_insn "movmem8b"
5340   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5341         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5342    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5343         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5344    (set (match_operand:SI 0 "register_operand" "=l")
5345         (plus:SI (match_dup 2) (const_int 8)))
5346    (set (match_operand:SI 1 "register_operand" "=l")
5347         (plus:SI (match_dup 3) (const_int 8)))
5348    (clobber (match_scratch:SI 4 "=&l"))
5349    (clobber (match_scratch:SI 5 "=&l"))]
5350   "TARGET_THUMB"
5351   "* return thumb_output_move_mem_multiple (2, operands);"
5352   [(set_attr "length" "4")
5353    ; This isn't entirely accurate...  It loads as well, but in terms of
5354    ; scheduling the following insn it is better to consider it as a store
5355    (set_attr "type" "store2")]
5356 )
5357
5358 \f
5359
5360 ;; Compare & branch insns
5361 ;; The range calculations are based as follows:
5362 ;; For forward branches, the address calculation returns the address of
5363 ;; the next instruction.  This is 2 beyond the branch instruction.
5364 ;; For backward branches, the address calculation returns the address of
5365 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5366 ;; instruction for the shortest sequence, and 4 before the branch instruction
5367 ;; if we have to jump around an unconditional branch.
5368 ;; To the basic branch range the PC offset must be added (this is +4).
5369 ;; So for forward branches we have 
5370 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5371 ;; And for backward branches we have 
5372 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5373 ;;
5374 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5375 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5376
5377 (define_expand "cbranchsi4"
5378   [(set (pc) (if_then_else
5379               (match_operator 0 "arm_comparison_operator"
5380                [(match_operand:SI 1 "s_register_operand" "")
5381                 (match_operand:SI 2 "nonmemory_operand" "")])
5382               (label_ref (match_operand 3 "" ""))
5383               (pc)))]
5384   "TARGET_THUMB"
5385   "
5386   if (thumb_cmpneg_operand (operands[2], SImode))
5387     {
5388       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5389                                               operands[3], operands[0]));
5390       DONE;
5391     }
5392   if (!thumb_cmp_operand (operands[2], SImode))
5393     operands[2] = force_reg (SImode, operands[2]);
5394   ")
5395
5396 (define_insn "*cbranchsi4_insn"
5397   [(set (pc) (if_then_else
5398               (match_operator 0 "arm_comparison_operator"
5399                [(match_operand:SI 1 "s_register_operand" "l,*h")
5400                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5401               (label_ref (match_operand 3 "" ""))
5402               (pc)))]
5403   "TARGET_THUMB"
5404   "*
5405   output_asm_insn (\"cmp\\t%1, %2\", operands);
5406
5407   switch (get_attr_length (insn))
5408     {
5409     case 4:  return \"b%d0\\t%l3\";
5410     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5411     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5412     }
5413   "
5414   [(set (attr "far_jump")
5415         (if_then_else
5416             (eq_attr "length" "8")
5417             (const_string "yes")
5418             (const_string "no")))
5419    (set (attr "length") 
5420         (if_then_else
5421             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5422                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5423             (const_int 4)
5424             (if_then_else
5425                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5426                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5427                 (const_int 6)
5428                 (const_int 8))))]
5429 )
5430
5431 (define_insn "cbranchsi4_scratch"
5432   [(set (pc) (if_then_else
5433               (match_operator 4 "arm_comparison_operator"
5434                [(match_operand:SI 1 "s_register_operand" "l,0")
5435                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5436               (label_ref (match_operand 3 "" ""))
5437               (pc)))
5438    (clobber (match_scratch:SI 0 "=l,l"))]
5439   "TARGET_THUMB"
5440   "*
5441   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5442
5443   switch (get_attr_length (insn))
5444     {
5445     case 4:  return \"b%d4\\t%l3\";
5446     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5447     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5448     }
5449   "
5450   [(set (attr "far_jump")
5451         (if_then_else
5452             (eq_attr "length" "8")
5453             (const_string "yes")
5454             (const_string "no")))
5455    (set (attr "length") 
5456         (if_then_else
5457             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5458                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5459             (const_int 4)
5460             (if_then_else
5461                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5462                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5463                 (const_int 6)
5464                 (const_int 8))))]
5465 )
5466 (define_insn "*movsi_cbranchsi4"
5467   [(set (pc)
5468         (if_then_else
5469          (match_operator 3 "arm_comparison_operator"
5470           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5471            (const_int 0)])
5472          (label_ref (match_operand 2 "" ""))
5473          (pc)))
5474    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5475         (match_dup 1))]
5476   "TARGET_THUMB"
5477   "*{
5478   if (which_alternative == 0)
5479     output_asm_insn (\"cmp\t%0, #0\", operands);
5480   else if (which_alternative == 1)
5481     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5482   else
5483     {
5484       output_asm_insn (\"cmp\t%1, #0\", operands);
5485       if (which_alternative == 2)
5486         output_asm_insn (\"mov\t%0, %1\", operands);
5487       else
5488         output_asm_insn (\"str\t%1, %0\", operands);
5489     }
5490   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5491     {
5492     case 4:  return \"b%d3\\t%l2\";
5493     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5494     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5495     }
5496   }"
5497   [(set (attr "far_jump")
5498         (if_then_else
5499             (ior (and (gt (symbol_ref ("which_alternative"))
5500                           (const_int 1))
5501                       (eq_attr "length" "8"))
5502                  (eq_attr "length" "10"))
5503             (const_string "yes")
5504             (const_string "no")))
5505    (set (attr "length")
5506      (if_then_else
5507        (le (symbol_ref ("which_alternative"))
5508                        (const_int 1))
5509        (if_then_else
5510          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5511               (le (minus (match_dup 2) (pc)) (const_int 256)))
5512          (const_int 4)
5513          (if_then_else
5514            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5515                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5516            (const_int 6)
5517            (const_int 8)))
5518        (if_then_else
5519          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5520               (le (minus (match_dup 2) (pc)) (const_int 256)))
5521          (const_int 6)
5522          (if_then_else
5523            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5524                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5525            (const_int 8)
5526            (const_int 10)))))]
5527 )
5528
5529 (define_insn "*negated_cbranchsi4"
5530   [(set (pc)
5531         (if_then_else
5532          (match_operator 0 "arm_comparison_operator"
5533           [(match_operand:SI 1 "s_register_operand" "l")
5534            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5535          (label_ref (match_operand 3 "" ""))
5536          (pc)))]
5537   "TARGET_THUMB"
5538   "*
5539   output_asm_insn (\"cmn\\t%1, %2\", operands);
5540   switch (get_attr_length (insn))
5541     {
5542     case 4:  return \"b%d0\\t%l3\";
5543     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5544     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5545     }
5546   "
5547   [(set (attr "far_jump")
5548         (if_then_else
5549             (eq_attr "length" "8")
5550             (const_string "yes")
5551             (const_string "no")))
5552    (set (attr "length") 
5553         (if_then_else
5554             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5555                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5556             (const_int 4)
5557             (if_then_else
5558                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5559                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5560                 (const_int 6)
5561                 (const_int 8))))]
5562 )
5563
5564 (define_insn "*tbit_cbranch"
5565   [(set (pc)
5566         (if_then_else
5567          (match_operator 0 "equality_operator"
5568           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5569                             (const_int 1)
5570                             (match_operand:SI 2 "const_int_operand" "i"))
5571            (const_int 0)])
5572          (label_ref (match_operand 3 "" ""))
5573          (pc)))
5574    (clobber (match_scratch:SI 4 "=l"))]
5575   "TARGET_THUMB"
5576   "*
5577   {
5578   rtx op[3];
5579   op[0] = operands[4];
5580   op[1] = operands[1];
5581   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5582
5583   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5584   switch (get_attr_length (insn))
5585     {
5586     case 4:  return \"b%d0\\t%l3\";
5587     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5588     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5589     }
5590   }"
5591   [(set (attr "far_jump")
5592         (if_then_else
5593             (eq_attr "length" "8")
5594             (const_string "yes")
5595             (const_string "no")))
5596    (set (attr "length") 
5597         (if_then_else
5598             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5599                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5600             (const_int 4)
5601             (if_then_else
5602                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5603                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5604                 (const_int 6)
5605                 (const_int 8))))]
5606 )
5607   
5608 (define_insn "*tstsi3_cbranch"
5609   [(set (pc)
5610         (if_then_else
5611          (match_operator 3 "equality_operator"
5612           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5613                    (match_operand:SI 1 "s_register_operand" "l"))
5614            (const_int 0)])
5615          (label_ref (match_operand 2 "" ""))
5616          (pc)))]
5617   "TARGET_THUMB"
5618   "*
5619   {
5620   output_asm_insn (\"tst\\t%0, %1\", operands);
5621   switch (get_attr_length (insn))
5622     {
5623     case 4:  return \"b%d3\\t%l2\";
5624     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5625     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5626     }
5627   }"
5628   [(set (attr "far_jump")
5629         (if_then_else
5630             (eq_attr "length" "8")
5631             (const_string "yes")
5632             (const_string "no")))
5633    (set (attr "length") 
5634         (if_then_else
5635             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5636                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5637             (const_int 4)
5638             (if_then_else
5639                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5640                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5641                 (const_int 6)
5642                 (const_int 8))))]
5643 )
5644   
5645 (define_insn "*andsi3_cbranch"
5646   [(set (pc)
5647         (if_then_else
5648          (match_operator 5 "equality_operator"
5649           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5650                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5651            (const_int 0)])
5652          (label_ref (match_operand 4 "" ""))
5653          (pc)))
5654    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5655         (and:SI (match_dup 2) (match_dup 3)))
5656    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5657   "TARGET_THUMB"
5658   "*
5659   {
5660   if (which_alternative == 0)
5661     output_asm_insn (\"and\\t%0, %3\", operands);
5662   else if (which_alternative == 1)
5663     {
5664       output_asm_insn (\"and\\t%1, %3\", operands);
5665       output_asm_insn (\"mov\\t%0, %1\", operands);
5666     }
5667   else
5668     {
5669       output_asm_insn (\"and\\t%1, %3\", operands);
5670       output_asm_insn (\"str\\t%1, %0\", operands);
5671     }
5672
5673   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5674     {
5675     case 4:  return \"b%d5\\t%l4\";
5676     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5677     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5678     }
5679   }"
5680   [(set (attr "far_jump")
5681         (if_then_else
5682             (ior (and (eq (symbol_ref ("which_alternative"))
5683                           (const_int 0))
5684                       (eq_attr "length" "8"))
5685                  (eq_attr "length" "10"))
5686             (const_string "yes")
5687             (const_string "no")))
5688    (set (attr "length")
5689      (if_then_else
5690        (eq (symbol_ref ("which_alternative"))
5691                        (const_int 0))
5692        (if_then_else
5693          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5694               (le (minus (match_dup 4) (pc)) (const_int 256)))
5695          (const_int 4)
5696          (if_then_else
5697            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5698                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5699            (const_int 6)
5700            (const_int 8)))
5701        (if_then_else
5702          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5703               (le (minus (match_dup 4) (pc)) (const_int 256)))
5704          (const_int 6)
5705          (if_then_else
5706            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5707                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5708            (const_int 8)
5709            (const_int 10)))))]
5710 )
5711
5712 (define_insn "*orrsi3_cbranch_scratch"
5713   [(set (pc)
5714         (if_then_else
5715          (match_operator 4 "equality_operator"
5716           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5717                    (match_operand:SI 2 "s_register_operand" "l"))
5718            (const_int 0)])
5719          (label_ref (match_operand 3 "" ""))
5720          (pc)))
5721    (clobber (match_scratch:SI 0 "=l"))]
5722   "TARGET_THUMB"
5723   "*
5724   {
5725   output_asm_insn (\"orr\\t%0, %2\", operands);
5726   switch (get_attr_length (insn))
5727     {
5728     case 4:  return \"b%d4\\t%l3\";
5729     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5730     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5731     }
5732   }"
5733   [(set (attr "far_jump")
5734         (if_then_else
5735             (eq_attr "length" "8")
5736             (const_string "yes")
5737             (const_string "no")))
5738    (set (attr "length") 
5739         (if_then_else
5740             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5741                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5742             (const_int 4)
5743             (if_then_else
5744                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5745                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5746                 (const_int 6)
5747                 (const_int 8))))]
5748 )
5749   
5750 (define_insn "*orrsi3_cbranch"
5751   [(set (pc)
5752         (if_then_else
5753          (match_operator 5 "equality_operator"
5754           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5755                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5756            (const_int 0)])
5757          (label_ref (match_operand 4 "" ""))
5758          (pc)))
5759    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5760         (ior:SI (match_dup 2) (match_dup 3)))
5761    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5762   "TARGET_THUMB"
5763   "*
5764   {
5765   if (which_alternative == 0)
5766     output_asm_insn (\"orr\\t%0, %3\", operands);
5767   else if (which_alternative == 1)
5768     {
5769       output_asm_insn (\"orr\\t%1, %3\", operands);
5770       output_asm_insn (\"mov\\t%0, %1\", operands);
5771     }
5772   else
5773     {
5774       output_asm_insn (\"orr\\t%1, %3\", operands);
5775       output_asm_insn (\"str\\t%1, %0\", operands);
5776     }
5777
5778   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5779     {
5780     case 4:  return \"b%d5\\t%l4\";
5781     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5782     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5783     }
5784   }"
5785   [(set (attr "far_jump")
5786         (if_then_else
5787             (ior (and (eq (symbol_ref ("which_alternative"))
5788                           (const_int 0))
5789                       (eq_attr "length" "8"))
5790                  (eq_attr "length" "10"))
5791             (const_string "yes")
5792             (const_string "no")))
5793    (set (attr "length")
5794      (if_then_else
5795        (eq (symbol_ref ("which_alternative"))
5796                        (const_int 0))
5797        (if_then_else
5798          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5799               (le (minus (match_dup 4) (pc)) (const_int 256)))
5800          (const_int 4)
5801          (if_then_else
5802            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5803                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5804            (const_int 6)
5805            (const_int 8)))
5806        (if_then_else
5807          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5808               (le (minus (match_dup 4) (pc)) (const_int 256)))
5809          (const_int 6)
5810          (if_then_else
5811            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5812                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5813            (const_int 8)
5814            (const_int 10)))))]
5815 )
5816
5817 (define_insn "*xorsi3_cbranch_scratch"
5818   [(set (pc)
5819         (if_then_else
5820          (match_operator 4 "equality_operator"
5821           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
5822                    (match_operand:SI 2 "s_register_operand" "l"))
5823            (const_int 0)])
5824          (label_ref (match_operand 3 "" ""))
5825          (pc)))
5826    (clobber (match_scratch:SI 0 "=l"))]
5827   "TARGET_THUMB"
5828   "*
5829   {
5830   output_asm_insn (\"eor\\t%0, %2\", operands);
5831   switch (get_attr_length (insn))
5832     {
5833     case 4:  return \"b%d4\\t%l3\";
5834     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5835     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5836     }
5837   }"
5838   [(set (attr "far_jump")
5839         (if_then_else
5840             (eq_attr "length" "8")
5841             (const_string "yes")
5842             (const_string "no")))
5843    (set (attr "length") 
5844         (if_then_else
5845             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5846                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5847             (const_int 4)
5848             (if_then_else
5849                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5850                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5851                 (const_int 6)
5852                 (const_int 8))))]
5853 )
5854   
5855 (define_insn "*xorsi3_cbranch"
5856   [(set (pc)
5857         (if_then_else
5858          (match_operator 5 "equality_operator"
5859           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5860                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5861            (const_int 0)])
5862          (label_ref (match_operand 4 "" ""))
5863          (pc)))
5864    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5865         (xor:SI (match_dup 2) (match_dup 3)))
5866    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5867   "TARGET_THUMB"
5868   "*
5869   {
5870   if (which_alternative == 0)
5871     output_asm_insn (\"eor\\t%0, %3\", operands);
5872   else if (which_alternative == 1)
5873     {
5874       output_asm_insn (\"eor\\t%1, %3\", operands);
5875       output_asm_insn (\"mov\\t%0, %1\", operands);
5876     }
5877   else
5878     {
5879       output_asm_insn (\"eor\\t%1, %3\", operands);
5880       output_asm_insn (\"str\\t%1, %0\", operands);
5881     }
5882
5883   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5884     {
5885     case 4:  return \"b%d5\\t%l4\";
5886     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5887     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5888     }
5889   }"
5890   [(set (attr "far_jump")
5891         (if_then_else
5892             (ior (and (eq (symbol_ref ("which_alternative"))
5893                           (const_int 0))
5894                       (eq_attr "length" "8"))
5895                  (eq_attr "length" "10"))
5896             (const_string "yes")
5897             (const_string "no")))
5898    (set (attr "length")
5899      (if_then_else
5900        (eq (symbol_ref ("which_alternative"))
5901                        (const_int 0))
5902        (if_then_else
5903          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5904               (le (minus (match_dup 4) (pc)) (const_int 256)))
5905          (const_int 4)
5906          (if_then_else
5907            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5908                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5909            (const_int 6)
5910            (const_int 8)))
5911        (if_then_else
5912          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5913               (le (minus (match_dup 4) (pc)) (const_int 256)))
5914          (const_int 6)
5915          (if_then_else
5916            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5917                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5918            (const_int 8)
5919            (const_int 10)))))]
5920 )
5921
5922 (define_insn "*bicsi3_cbranch_scratch"
5923   [(set (pc)
5924         (if_then_else
5925          (match_operator 4 "equality_operator"
5926           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
5927                    (match_operand:SI 1 "s_register_operand" "0"))
5928            (const_int 0)])
5929          (label_ref (match_operand 3 "" ""))
5930          (pc)))
5931    (clobber (match_scratch:SI 0 "=l"))]
5932   "TARGET_THUMB"
5933   "*
5934   {
5935   output_asm_insn (\"bic\\t%0, %2\", operands);
5936   switch (get_attr_length (insn))
5937     {
5938     case 4:  return \"b%d4\\t%l3\";
5939     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5940     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5941     }
5942   }"
5943   [(set (attr "far_jump")
5944         (if_then_else
5945             (eq_attr "length" "8")
5946             (const_string "yes")
5947             (const_string "no")))
5948    (set (attr "length") 
5949         (if_then_else
5950             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5951                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5952             (const_int 4)
5953             (if_then_else
5954                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5955                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5956                 (const_int 6)
5957                 (const_int 8))))]
5958 )
5959   
5960 (define_insn "*bicsi3_cbranch"
5961   [(set (pc)
5962         (if_then_else
5963          (match_operator 5 "equality_operator"
5964           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5965                    (match_operand:SI 2 "s_register_operand" "0,1,1,1"))
5966            (const_int 0)])
5967          (label_ref (match_operand 4 "" ""))
5968          (pc)))
5969    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5970         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
5971    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5972   "TARGET_THUMB"
5973   "*
5974   {
5975   if (which_alternative == 0)
5976     output_asm_insn (\"bic\\t%0, %3\", operands);
5977   else if (which_alternative == 1)
5978     {
5979       output_asm_insn (\"bic\\t%1, %3\", operands);
5980       output_asm_insn (\"mov\\t%0, %1\", operands);
5981     }
5982   else
5983     {
5984       output_asm_insn (\"bic\\t%1, %3\", operands);
5985       output_asm_insn (\"str\\t%1, %0\", operands);
5986     }
5987
5988   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5989     {
5990     case 4:  return \"b%d5\\t%l4\";
5991     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5992     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5993     }
5994   }"
5995   [(set (attr "far_jump")
5996         (if_then_else
5997             (ior (and (eq (symbol_ref ("which_alternative"))
5998                           (const_int 0))
5999                       (eq_attr "length" "8"))
6000                  (eq_attr "length" "10"))
6001             (const_string "yes")
6002             (const_string "no")))
6003    (set (attr "length")
6004      (if_then_else
6005        (eq (symbol_ref ("which_alternative"))
6006                        (const_int 0))
6007        (if_then_else
6008          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6009               (le (minus (match_dup 4) (pc)) (const_int 256)))
6010          (const_int 4)
6011          (if_then_else
6012            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6013                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6014            (const_int 6)
6015            (const_int 8)))
6016        (if_then_else
6017          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6018               (le (minus (match_dup 4) (pc)) (const_int 256)))
6019          (const_int 6)
6020          (if_then_else
6021            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6022                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6023            (const_int 8)
6024            (const_int 10)))))]
6025 )
6026
6027 (define_insn "*cbranchne_decr1"
6028   [(set (pc)
6029         (if_then_else (match_operator 3 "equality_operator"
6030                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6031                         (const_int 0)])
6032                       (label_ref (match_operand 4 "" ""))
6033                       (pc)))
6034    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6035         (plus:SI (match_dup 2) (const_int -1)))
6036    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6037   "TARGET_THUMB"
6038   "*
6039    {
6040      rtx cond[2];
6041      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6042                                 ? GEU : LTU),
6043                                VOIDmode, operands[2], const1_rtx);
6044      cond[1] = operands[4];
6045
6046      if (which_alternative == 0)
6047        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6048      else if (which_alternative == 1)
6049        {
6050          /* We must provide an alternative for a hi reg because reload 
6051             cannot handle output reloads on a jump instruction, but we
6052             can't subtract into that.  Fortunately a mov from lo to hi
6053             does not clobber the condition codes.  */
6054          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6055          output_asm_insn (\"mov\\t%0, %1\", operands);
6056        }
6057      else
6058        {
6059          /* Similarly, but the target is memory.  */
6060          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6061          output_asm_insn (\"str\\t%1, %0\", operands);
6062        }
6063
6064      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6065        {
6066          case 4:
6067            output_asm_insn (\"b%d0\\t%l1\", cond);
6068            return \"\";
6069          case 6:
6070            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6071            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6072          default:
6073            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6074            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6075        }
6076    }
6077   "
6078   [(set (attr "far_jump")
6079         (if_then_else
6080             (ior (and (eq (symbol_ref ("which_alternative"))
6081                           (const_int 0))
6082                       (eq_attr "length" "8"))
6083                  (eq_attr "length" "10"))
6084             (const_string "yes")
6085             (const_string "no")))
6086    (set_attr_alternative "length"
6087       [
6088        ;; Alternative 0
6089        (if_then_else
6090          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6091               (le (minus (match_dup 4) (pc)) (const_int 256)))
6092          (const_int 4)
6093          (if_then_else
6094            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6095                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6096            (const_int 6)
6097            (const_int 8)))
6098        ;; Alternative 1
6099        (if_then_else
6100          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6101               (le (minus (match_dup 4) (pc)) (const_int 256)))
6102          (const_int 6)
6103          (if_then_else
6104            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6105                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6106            (const_int 8)
6107            (const_int 10)))
6108        ;; Alternative 2
6109        (if_then_else
6110          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6111               (le (minus (match_dup 4) (pc)) (const_int 256)))
6112          (const_int 6)
6113          (if_then_else
6114            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6115                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6116            (const_int 8)
6117            (const_int 10)))
6118        ;; Alternative 3
6119        (if_then_else
6120          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6121               (le (minus (match_dup 4) (pc)) (const_int 256)))
6122          (const_int 6)
6123          (if_then_else
6124            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6125                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6126            (const_int 8)
6127            (const_int 10)))])]
6128 )
6129
6130 (define_insn "*addsi3_cbranch"
6131   [(set (pc)
6132         (if_then_else
6133          (match_operator 4 "comparison_operator"
6134           [(plus:SI
6135             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6136             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6137            (const_int 0)])
6138          (label_ref (match_operand 5 "" ""))
6139          (pc)))
6140    (set
6141     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6142     (plus:SI (match_dup 2) (match_dup 3)))
6143    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6144   "TARGET_THUMB
6145    && (GET_CODE (operands[4]) == EQ
6146        || GET_CODE (operands[4]) == NE
6147        || GET_CODE (operands[4]) == GE
6148        || GET_CODE (operands[4]) == LT)"
6149   "*
6150    {
6151      rtx cond[3];
6152
6153      
6154      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6155      cond[1] = operands[2];
6156      cond[2] = operands[3];
6157
6158      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6159        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6160      else
6161        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6162
6163      if (which_alternative >= 3
6164          && which_alternative < 4)
6165        output_asm_insn (\"mov\\t%0, %1\", operands);
6166      else if (which_alternative >= 4)
6167        output_asm_insn (\"str\\t%1, %0\", operands);
6168
6169      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6170        {
6171          case 4:
6172            return \"b%d4\\t%l5\";
6173          case 6:
6174            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6175          default:
6176            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6177        }
6178    }
6179   "
6180   [(set (attr "far_jump")
6181         (if_then_else
6182             (ior (and (lt (symbol_ref ("which_alternative"))
6183                           (const_int 3))
6184                       (eq_attr "length" "8"))
6185                  (eq_attr "length" "10"))
6186             (const_string "yes")
6187             (const_string "no")))
6188    (set (attr "length")
6189      (if_then_else
6190        (lt (symbol_ref ("which_alternative"))
6191                        (const_int 3))
6192        (if_then_else
6193          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6194               (le (minus (match_dup 5) (pc)) (const_int 256)))
6195          (const_int 4)
6196          (if_then_else
6197            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6198                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6199            (const_int 6)
6200            (const_int 8)))
6201        (if_then_else
6202          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6203               (le (minus (match_dup 5) (pc)) (const_int 256)))
6204          (const_int 6)
6205          (if_then_else
6206            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6207                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6208            (const_int 8)
6209            (const_int 10)))))]
6210 )
6211
6212 (define_insn "*addsi3_cbranch_scratch"
6213   [(set (pc)
6214         (if_then_else
6215          (match_operator 3 "comparison_operator"
6216           [(plus:SI
6217             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6218             (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6219            (const_int 0)])
6220          (label_ref (match_operand 4 "" ""))
6221          (pc)))
6222    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6223   "TARGET_THUMB
6224    && (GET_CODE (operands[3]) == EQ
6225        || GET_CODE (operands[3]) == NE
6226        || GET_CODE (operands[3]) == GE
6227        || GET_CODE (operands[3]) == LT)"
6228   "*
6229    {
6230      switch (which_alternative)
6231        {
6232        case 0:
6233          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6234          break;
6235        case 1:
6236          output_asm_insn (\"cmn\t%1, %2\", operands);
6237          break;
6238        case 3:
6239          output_asm_insn (\"add\t%0, %1, %2\", operands);
6240          break;
6241        case 4:
6242          output_asm_insn (\"add\t%0, %0, %2\", operands);
6243          break;
6244        }
6245
6246      switch (get_attr_length (insn))
6247        {
6248          case 4:
6249            return \"b%d3\\t%l4\";
6250          case 6:
6251            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6252          default:
6253            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6254        }
6255    }
6256   "
6257   [(set (attr "far_jump")
6258         (if_then_else
6259             (eq_attr "length" "8")
6260             (const_string "yes")
6261             (const_string "no")))
6262    (set (attr "length")
6263        (if_then_else
6264          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6265               (le (minus (match_dup 4) (pc)) (const_int 256)))
6266          (const_int 4)
6267          (if_then_else
6268            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6269                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6270            (const_int 6)
6271            (const_int 8))))]
6272 )
6273
6274 (define_insn "*subsi3_cbranch"
6275   [(set (pc)
6276         (if_then_else
6277          (match_operator 4 "comparison_operator"
6278           [(minus:SI
6279             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6280             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6281            (const_int 0)])
6282          (label_ref (match_operand 5 "" ""))
6283          (pc)))
6284    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6285         (minus:SI (match_dup 2) (match_dup 3)))
6286    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6287   "TARGET_THUMB
6288    && (GET_CODE (operands[4]) == EQ
6289        || GET_CODE (operands[4]) == NE
6290        || GET_CODE (operands[4]) == GE
6291        || GET_CODE (operands[4]) == LT)"
6292   "*
6293    {
6294      if (which_alternative == 0)
6295        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6296      else if (which_alternative == 1)
6297        {
6298          /* We must provide an alternative for a hi reg because reload 
6299             cannot handle output reloads on a jump instruction, but we
6300             can't subtract into that.  Fortunately a mov from lo to hi
6301             does not clobber the condition codes.  */
6302          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6303          output_asm_insn (\"mov\\t%0, %1\", operands);
6304        }
6305      else
6306        {
6307          /* Similarly, but the target is memory.  */
6308          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6309          output_asm_insn (\"str\\t%1, %0\", operands);
6310        }
6311
6312      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6313        {
6314          case 4:
6315            return \"b%d4\\t%l5\";
6316          case 6:
6317            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6318          default:
6319            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6320        }
6321    }
6322   "
6323   [(set (attr "far_jump")
6324         (if_then_else
6325             (ior (and (eq (symbol_ref ("which_alternative"))
6326                           (const_int 0))
6327                       (eq_attr "length" "8"))
6328                  (eq_attr "length" "10"))
6329             (const_string "yes")
6330             (const_string "no")))
6331    (set (attr "length")
6332      (if_then_else
6333        (eq (symbol_ref ("which_alternative"))
6334                        (const_int 0))
6335        (if_then_else
6336          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6337               (le (minus (match_dup 5) (pc)) (const_int 256)))
6338          (const_int 4)
6339          (if_then_else
6340            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6341                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6342            (const_int 6)
6343            (const_int 8)))
6344        (if_then_else
6345          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6346               (le (minus (match_dup 5) (pc)) (const_int 256)))
6347          (const_int 6)
6348          (if_then_else
6349            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6350                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6351            (const_int 8)
6352            (const_int 10)))))]
6353 )
6354
6355 (define_insn "*subsi3_cbranch_scratch"
6356   [(set (pc)
6357         (if_then_else
6358          (match_operator 0 "arm_comparison_operator"
6359           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6360                      (match_operand:SI 2 "nonmemory_operand" "l"))
6361            (const_int 0)])
6362          (label_ref (match_operand 3 "" ""))
6363          (pc)))]
6364   "TARGET_THUMB
6365    && (GET_CODE (operands[0]) == EQ
6366        || GET_CODE (operands[0]) == NE
6367        || GET_CODE (operands[0]) == GE
6368        || GET_CODE (operands[0]) == LT)"
6369   "*
6370   output_asm_insn (\"cmp\\t%1, %2\", operands);
6371   switch (get_attr_length (insn))
6372     {
6373     case 4:  return \"b%d0\\t%l3\";
6374     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6375     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6376     }
6377   "
6378   [(set (attr "far_jump")
6379         (if_then_else
6380             (eq_attr "length" "8")
6381             (const_string "yes")
6382             (const_string "no")))
6383    (set (attr "length") 
6384         (if_then_else
6385             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6386                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6387             (const_int 4)
6388             (if_then_else
6389                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6390                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6391                 (const_int 6)
6392                 (const_int 8))))]
6393 )
6394
6395 ;; Comparison and test insns
6396
6397 (define_expand "cmpsi"
6398   [(match_operand:SI 0 "s_register_operand" "")
6399    (match_operand:SI 1 "arm_add_operand" "")]
6400   "TARGET_ARM"
6401   "{
6402     arm_compare_op0 = operands[0];
6403     arm_compare_op1 = operands[1];
6404     DONE;
6405   }"
6406 )
6407
6408 (define_expand "cmpsf"
6409   [(match_operand:SF 0 "s_register_operand" "")
6410    (match_operand:SF 1 "fpa_rhs_operand" "")]
6411   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6412   "
6413   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
6414     operands[1] = force_reg (SFmode, operands[1]);
6415
6416   arm_compare_op0 = operands[0];
6417   arm_compare_op1 = operands[1];
6418   DONE;
6419   "
6420 )
6421
6422 (define_expand "cmpdf"
6423   [(match_operand:DF 0 "s_register_operand" "")
6424    (match_operand:DF 1 "fpa_rhs_operand" "")]
6425   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6426   "
6427   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
6428     operands[1] = force_reg (DFmode, operands[1]);
6429
6430   arm_compare_op0 = operands[0];
6431   arm_compare_op1 = operands[1];
6432   DONE;
6433   "
6434 )
6435
6436 (define_insn "*arm_cmpsi_insn"
6437   [(set (reg:CC CC_REGNUM)
6438         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6439                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6440   "TARGET_ARM"
6441   "@
6442    cmp%?\\t%0, %1
6443    cmn%?\\t%0, #%n1"
6444   [(set_attr "conds" "set")]
6445 )
6446
6447 (define_insn "*cmpsi_shiftsi"
6448   [(set (reg:CC CC_REGNUM)
6449         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6450                     (match_operator:SI  3 "shift_operator"
6451                      [(match_operand:SI 1 "s_register_operand" "r")
6452                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6453   "TARGET_ARM"
6454   "cmp%?\\t%0, %1%S3"
6455   [(set_attr "conds" "set")
6456    (set_attr "shift" "1")
6457    ]
6458 )
6459
6460 (define_insn "*cmpsi_shiftsi_swp"
6461   [(set (reg:CC_SWP CC_REGNUM)
6462         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6463                          [(match_operand:SI 1 "s_register_operand" "r")
6464                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6465                         (match_operand:SI 0 "s_register_operand" "r")))]
6466   "TARGET_ARM"
6467   "cmp%?\\t%0, %1%S3"
6468   [(set_attr "conds" "set")
6469    (set_attr "shift" "1")
6470    ]
6471 )
6472
6473 (define_insn "*cmpsi_neg_shiftsi"
6474   [(set (reg:CC CC_REGNUM)
6475         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6476                     (neg:SI (match_operator:SI 3 "shift_operator"
6477                              [(match_operand:SI 1 "s_register_operand" "r")
6478                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6479   "TARGET_ARM"
6480   "cmn%?\\t%0, %1%S3"
6481   [(set_attr "conds" "set")
6482    (set_attr "shift" "1")
6483    ]
6484 )
6485
6486 ;; Cirrus SF compare instruction
6487 (define_insn "*cirrus_cmpsf"
6488   [(set (reg:CCFP CC_REGNUM)
6489         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6490                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6491   "TARGET_ARM && TARGET_CIRRUS"
6492   "cfcmps%?\\tr15, %V0, %V1"
6493   [(set_attr "type"   "mav_farith")
6494    (set_attr "cirrus" "compare")]
6495 )
6496
6497 ;; Cirrus DF compare instruction
6498 (define_insn "*cirrus_cmpdf"
6499   [(set (reg:CCFP CC_REGNUM)
6500         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6501                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6502   "TARGET_ARM && TARGET_CIRRUS"
6503   "cfcmpd%?\\tr15, %V0, %V1"
6504   [(set_attr "type"   "mav_farith")
6505    (set_attr "cirrus" "compare")]
6506 )
6507
6508 ;; Cirrus DI compare instruction
6509 (define_expand "cmpdi"
6510   [(match_operand:DI 0 "cirrus_fp_register" "")
6511    (match_operand:DI 1 "cirrus_fp_register" "")]
6512   "TARGET_ARM && TARGET_CIRRUS"
6513   "{
6514      arm_compare_op0 = operands[0];
6515      arm_compare_op1 = operands[1];
6516      DONE;
6517    }")
6518
6519 (define_insn "*cirrus_cmpdi"
6520   [(set (reg:CC CC_REGNUM)
6521         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6522                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6523   "TARGET_ARM && TARGET_CIRRUS"
6524   "cfcmp64%?\\tr15, %V0, %V1"
6525   [(set_attr "type"   "mav_farith")
6526    (set_attr "cirrus" "compare")]
6527 )
6528
6529 ; This insn allows redundant compares to be removed by cse, nothing should
6530 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6531 ; is deleted later on. The match_dup will match the mode here, so that
6532 ; mode changes of the condition codes aren't lost by this even though we don't
6533 ; specify what they are.
6534
6535 (define_insn "*deleted_compare"
6536   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6537   "TARGET_ARM"
6538   "\\t%@ deleted compare"
6539   [(set_attr "conds" "set")
6540    (set_attr "length" "0")]
6541 )
6542
6543 \f
6544 ;; Conditional branch insns
6545
6546 (define_expand "beq"
6547   [(set (pc)
6548         (if_then_else (eq (match_dup 1) (const_int 0))
6549                       (label_ref (match_operand 0 "" ""))
6550                       (pc)))]
6551   "TARGET_ARM"
6552   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6553 )
6554
6555 (define_expand "bne"
6556   [(set (pc)
6557         (if_then_else (ne (match_dup 1) (const_int 0))
6558                       (label_ref (match_operand 0 "" ""))
6559                       (pc)))]
6560   "TARGET_ARM"
6561   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6562 )
6563
6564 (define_expand "bgt"
6565   [(set (pc)
6566         (if_then_else (gt (match_dup 1) (const_int 0))
6567                       (label_ref (match_operand 0 "" ""))
6568                       (pc)))]
6569   "TARGET_ARM"
6570   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6571 )
6572
6573 (define_expand "ble"
6574   [(set (pc)
6575         (if_then_else (le (match_dup 1) (const_int 0))
6576                       (label_ref (match_operand 0 "" ""))
6577                       (pc)))]
6578   "TARGET_ARM"
6579   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6580 )
6581
6582 (define_expand "bge"
6583   [(set (pc)
6584         (if_then_else (ge (match_dup 1) (const_int 0))
6585                       (label_ref (match_operand 0 "" ""))
6586                       (pc)))]
6587   "TARGET_ARM"
6588   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6589 )
6590
6591 (define_expand "blt"
6592   [(set (pc)
6593         (if_then_else (lt (match_dup 1) (const_int 0))
6594                       (label_ref (match_operand 0 "" ""))
6595                       (pc)))]
6596   "TARGET_ARM"
6597   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6598 )
6599
6600 (define_expand "bgtu"
6601   [(set (pc)
6602         (if_then_else (gtu (match_dup 1) (const_int 0))
6603                       (label_ref (match_operand 0 "" ""))
6604                       (pc)))]
6605   "TARGET_ARM"
6606   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6607 )
6608
6609 (define_expand "bleu"
6610   [(set (pc)
6611         (if_then_else (leu (match_dup 1) (const_int 0))
6612                       (label_ref (match_operand 0 "" ""))
6613                       (pc)))]
6614   "TARGET_ARM"
6615   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6616 )
6617
6618 (define_expand "bgeu"
6619   [(set (pc)
6620         (if_then_else (geu (match_dup 1) (const_int 0))
6621                       (label_ref (match_operand 0 "" ""))
6622                       (pc)))]
6623   "TARGET_ARM"
6624   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6625 )
6626
6627 (define_expand "bltu"
6628   [(set (pc)
6629         (if_then_else (ltu (match_dup 1) (const_int 0))
6630                       (label_ref (match_operand 0 "" ""))
6631                       (pc)))]
6632   "TARGET_ARM"
6633   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6634 )
6635
6636 (define_expand "bunordered"
6637   [(set (pc)
6638         (if_then_else (unordered (match_dup 1) (const_int 0))
6639                       (label_ref (match_operand 0 "" ""))
6640                       (pc)))]
6641   "TARGET_ARM && TARGET_HARD_FLOAT"
6642   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6643                                       arm_compare_op1);"
6644 )
6645
6646 (define_expand "bordered"
6647   [(set (pc)
6648         (if_then_else (ordered (match_dup 1) (const_int 0))
6649                       (label_ref (match_operand 0 "" ""))
6650                       (pc)))]
6651   "TARGET_ARM && TARGET_HARD_FLOAT"
6652   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6653                                       arm_compare_op1);"
6654 )
6655
6656 (define_expand "bungt"
6657   [(set (pc)
6658         (if_then_else (ungt (match_dup 1) (const_int 0))
6659                       (label_ref (match_operand 0 "" ""))
6660                       (pc)))]
6661   "TARGET_ARM && TARGET_HARD_FLOAT"
6662   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6663 )
6664
6665 (define_expand "bunlt"
6666   [(set (pc)
6667         (if_then_else (unlt (match_dup 1) (const_int 0))
6668                       (label_ref (match_operand 0 "" ""))
6669                       (pc)))]
6670   "TARGET_ARM && TARGET_HARD_FLOAT"
6671   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6672 )
6673
6674 (define_expand "bunge"
6675   [(set (pc)
6676         (if_then_else (unge (match_dup 1) (const_int 0))
6677                       (label_ref (match_operand 0 "" ""))
6678                       (pc)))]
6679   "TARGET_ARM && TARGET_HARD_FLOAT"
6680   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6681 )
6682
6683 (define_expand "bunle"
6684   [(set (pc)
6685         (if_then_else (unle (match_dup 1) (const_int 0))
6686                       (label_ref (match_operand 0 "" ""))
6687                       (pc)))]
6688   "TARGET_ARM && TARGET_HARD_FLOAT"
6689   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6690 )
6691
6692 ;; The following two patterns need two branch instructions, since there is
6693 ;; no single instruction that will handle all cases.
6694 (define_expand "buneq"
6695   [(set (pc)
6696         (if_then_else (uneq (match_dup 1) (const_int 0))
6697                       (label_ref (match_operand 0 "" ""))
6698                       (pc)))]
6699   "TARGET_ARM && TARGET_HARD_FLOAT"
6700   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6701 )
6702
6703 (define_expand "bltgt"
6704   [(set (pc)
6705         (if_then_else (ltgt (match_dup 1) (const_int 0))
6706                       (label_ref (match_operand 0 "" ""))
6707                       (pc)))]
6708   "TARGET_ARM && TARGET_HARD_FLOAT"
6709   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6710 )
6711
6712 ;;
6713 ;; Patterns to match conditional branch insns.
6714 ;;
6715
6716 ; Special pattern to match UNEQ.
6717 (define_insn "*arm_buneq"
6718   [(set (pc)
6719         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6720                       (label_ref (match_operand 0 "" ""))
6721                       (pc)))]
6722   "TARGET_ARM && TARGET_HARD_FLOAT"
6723   "*
6724   if (arm_ccfsm_state != 0)
6725     abort ();
6726
6727   return \"bvs\\t%l0\;beq\\t%l0\";
6728   "
6729   [(set_attr "conds" "jump_clob")
6730    (set_attr "length" "8")]
6731 )
6732
6733 ; Special pattern to match LTGT.
6734 (define_insn "*arm_bltgt"
6735   [(set (pc)
6736         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6737                       (label_ref (match_operand 0 "" ""))
6738                       (pc)))]
6739   "TARGET_ARM && TARGET_HARD_FLOAT"
6740   "*
6741   if (arm_ccfsm_state != 0)
6742     abort ();
6743
6744   return \"bmi\\t%l0\;bgt\\t%l0\";
6745   "
6746   [(set_attr "conds" "jump_clob")
6747    (set_attr "length" "8")]
6748 )
6749
6750 (define_insn "*arm_cond_branch"
6751   [(set (pc)
6752         (if_then_else (match_operator 1 "arm_comparison_operator"
6753                        [(match_operand 2 "cc_register" "") (const_int 0)])
6754                       (label_ref (match_operand 0 "" ""))
6755                       (pc)))]
6756   "TARGET_ARM"
6757   "*
6758   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6759     {
6760       arm_ccfsm_state += 2;
6761       return \"\";
6762     }
6763   return \"b%d1\\t%l0\";
6764   "
6765   [(set_attr "conds" "use")]
6766 )
6767
6768 ; Special pattern to match reversed UNEQ.
6769 (define_insn "*arm_buneq_reversed"
6770   [(set (pc)
6771         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6772                       (pc)
6773                       (label_ref (match_operand 0 "" ""))))]
6774   "TARGET_ARM && TARGET_HARD_FLOAT"
6775   "*
6776   if (arm_ccfsm_state != 0)
6777     abort ();
6778
6779   return \"bmi\\t%l0\;bgt\\t%l0\";
6780   "
6781   [(set_attr "conds" "jump_clob")
6782    (set_attr "length" "8")]
6783 )
6784
6785 ; Special pattern to match reversed LTGT.
6786 (define_insn "*arm_bltgt_reversed"
6787   [(set (pc)
6788         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6789                       (pc)
6790                       (label_ref (match_operand 0 "" ""))))]
6791   "TARGET_ARM && TARGET_HARD_FLOAT"
6792   "*
6793   if (arm_ccfsm_state != 0)
6794     abort ();
6795
6796   return \"bvs\\t%l0\;beq\\t%l0\";
6797   "
6798   [(set_attr "conds" "jump_clob")
6799    (set_attr "length" "8")]
6800 )
6801
6802 (define_insn "*arm_cond_branch_reversed"
6803   [(set (pc)
6804         (if_then_else (match_operator 1 "arm_comparison_operator"
6805                        [(match_operand 2 "cc_register" "") (const_int 0)])
6806                       (pc)
6807                       (label_ref (match_operand 0 "" ""))))]
6808   "TARGET_ARM"
6809   "*
6810   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6811     {
6812       arm_ccfsm_state += 2;
6813       return \"\";
6814     }
6815   return \"b%D1\\t%l0\";
6816   "
6817   [(set_attr "conds" "use")]
6818 )
6819
6820 \f
6821
6822 ; scc insns
6823
6824 (define_expand "seq"
6825   [(set (match_operand:SI 0 "s_register_operand" "")
6826         (eq:SI (match_dup 1) (const_int 0)))]
6827   "TARGET_ARM"
6828   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6829 )
6830
6831 (define_expand "sne"
6832   [(set (match_operand:SI 0 "s_register_operand" "")
6833         (ne:SI (match_dup 1) (const_int 0)))]
6834   "TARGET_ARM"
6835   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6836 )
6837
6838 (define_expand "sgt"
6839   [(set (match_operand:SI 0 "s_register_operand" "")
6840         (gt:SI (match_dup 1) (const_int 0)))]
6841   "TARGET_ARM"
6842   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6843 )
6844
6845 (define_expand "sle"
6846   [(set (match_operand:SI 0 "s_register_operand" "")
6847         (le:SI (match_dup 1) (const_int 0)))]
6848   "TARGET_ARM"
6849   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6850 )
6851
6852 (define_expand "sge"
6853   [(set (match_operand:SI 0 "s_register_operand" "")
6854         (ge:SI (match_dup 1) (const_int 0)))]
6855   "TARGET_ARM"
6856   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6857 )
6858
6859 (define_expand "slt"
6860   [(set (match_operand:SI 0 "s_register_operand" "")
6861         (lt:SI (match_dup 1) (const_int 0)))]
6862   "TARGET_ARM"
6863   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6864 )
6865
6866 (define_expand "sgtu"
6867   [(set (match_operand:SI 0 "s_register_operand" "")
6868         (gtu:SI (match_dup 1) (const_int 0)))]
6869   "TARGET_ARM"
6870   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6871 )
6872
6873 (define_expand "sleu"
6874   [(set (match_operand:SI 0 "s_register_operand" "")
6875         (leu:SI (match_dup 1) (const_int 0)))]
6876   "TARGET_ARM"
6877   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6878 )
6879
6880 (define_expand "sgeu"
6881   [(set (match_operand:SI 0 "s_register_operand" "")
6882         (geu:SI (match_dup 1) (const_int 0)))]
6883   "TARGET_ARM"
6884   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6885 )
6886
6887 (define_expand "sltu"
6888   [(set (match_operand:SI 0 "s_register_operand" "")
6889         (ltu:SI (match_dup 1) (const_int 0)))]
6890   "TARGET_ARM"
6891   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6892 )
6893
6894 (define_expand "sunordered"
6895   [(set (match_operand:SI 0 "s_register_operand" "")
6896         (unordered:SI (match_dup 1) (const_int 0)))]
6897   "TARGET_ARM && TARGET_HARD_FLOAT"
6898   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6899                                       arm_compare_op1);"
6900 )
6901
6902 (define_expand "sordered"
6903   [(set (match_operand:SI 0 "s_register_operand" "")
6904         (ordered:SI (match_dup 1) (const_int 0)))]
6905   "TARGET_ARM && TARGET_HARD_FLOAT"
6906   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6907                                       arm_compare_op1);"
6908 )
6909
6910 (define_expand "sungt"
6911   [(set (match_operand:SI 0 "s_register_operand" "")
6912         (ungt:SI (match_dup 1) (const_int 0)))]
6913   "TARGET_ARM && TARGET_HARD_FLOAT"
6914   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6915                                       arm_compare_op1);"
6916 )
6917
6918 (define_expand "sunge"
6919   [(set (match_operand:SI 0 "s_register_operand" "")
6920         (unge:SI (match_dup 1) (const_int 0)))]
6921   "TARGET_ARM && TARGET_HARD_FLOAT"
6922   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6923                                       arm_compare_op1);"
6924 )
6925
6926 (define_expand "sunlt"
6927   [(set (match_operand:SI 0 "s_register_operand" "")
6928         (unlt:SI (match_dup 1) (const_int 0)))]
6929   "TARGET_ARM && TARGET_HARD_FLOAT"
6930   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6931                                       arm_compare_op1);"
6932 )
6933
6934 (define_expand "sunle"
6935   [(set (match_operand:SI 0 "s_register_operand" "")
6936         (unle:SI (match_dup 1) (const_int 0)))]
6937   "TARGET_ARM && TARGET_HARD_FLOAT"
6938   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6939                                       arm_compare_op1);"
6940 )
6941
6942 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6943 ;;; simple ARM instructions. 
6944 ;
6945 ; (define_expand "suneq"
6946 ;   [(set (match_operand:SI 0 "s_register_operand" "")
6947 ;       (uneq:SI (match_dup 1) (const_int 0)))]
6948 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6949 ;   "abort ();"
6950 ; )
6951 ;
6952 ; (define_expand "sltgt"
6953 ;   [(set (match_operand:SI 0 "s_register_operand" "")
6954 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
6955 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6956 ;   "abort ();"
6957 ; )
6958
6959 (define_insn "*mov_scc"
6960   [(set (match_operand:SI 0 "s_register_operand" "=r")
6961         (match_operator:SI 1 "arm_comparison_operator"
6962          [(match_operand 2 "cc_register" "") (const_int 0)]))]
6963   "TARGET_ARM"
6964   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6965   [(set_attr "conds" "use")
6966    (set_attr "length" "8")]
6967 )
6968
6969 (define_insn "*mov_negscc"
6970   [(set (match_operand:SI 0 "s_register_operand" "=r")
6971         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6972                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6973   "TARGET_ARM"
6974   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6975   [(set_attr "conds" "use")
6976    (set_attr "length" "8")]
6977 )
6978
6979 (define_insn "*mov_notscc"
6980   [(set (match_operand:SI 0 "s_register_operand" "=r")
6981         (not:SI (match_operator:SI 1 "arm_comparison_operator"
6982                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6983   "TARGET_ARM"
6984   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6985   [(set_attr "conds" "use")
6986    (set_attr "length" "8")]
6987 )
6988
6989 \f
6990 ;; Conditional move insns
6991
6992 (define_expand "movsicc"
6993   [(set (match_operand:SI 0 "s_register_operand" "")
6994         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6995                          (match_operand:SI 2 "arm_not_operand" "")
6996                          (match_operand:SI 3 "arm_not_operand" "")))]
6997   "TARGET_ARM"
6998   "
6999   {
7000     enum rtx_code code = GET_CODE (operands[1]);
7001     rtx ccreg;
7002
7003     if (code == UNEQ || code == LTGT)
7004       FAIL;
7005
7006     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7007     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7008   }"
7009 )
7010
7011 (define_expand "movsfcc"
7012   [(set (match_operand:SF 0 "s_register_operand" "")
7013         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7014                          (match_operand:SF 2 "s_register_operand" "")
7015                          (match_operand:SF 3 "nonmemory_operand" "")))]
7016   "TARGET_ARM"
7017   "
7018   {
7019     enum rtx_code code = GET_CODE (operands[1]);
7020     rtx ccreg;
7021
7022     if (code == UNEQ || code == LTGT)
7023       FAIL;
7024
7025     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7026        Otherwise, ensure it is a valid FP add operand */
7027     if ((!TARGET_HARD_FLOAT)
7028         || (!fpa_add_operand (operands[3], SFmode)))
7029       operands[3] = force_reg (SFmode, operands[3]);
7030
7031     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7032     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7033   }"
7034 )
7035
7036 (define_expand "movdfcc"
7037   [(set (match_operand:DF 0 "s_register_operand" "")
7038         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7039                          (match_operand:DF 2 "s_register_operand" "")
7040                          (match_operand:DF 3 "fpa_add_operand" "")))]
7041   "TARGET_ARM && TARGET_HARD_FLOAT"
7042   "
7043   {
7044     enum rtx_code code = GET_CODE (operands[1]);
7045     rtx ccreg;
7046
7047     if (code == UNEQ || code == LTGT)
7048       FAIL;
7049
7050     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7051     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7052   }"
7053 )
7054
7055 (define_insn "*movsicc_insn"
7056   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7057         (if_then_else:SI
7058          (match_operator 3 "arm_comparison_operator"
7059           [(match_operand 4 "cc_register" "") (const_int 0)])
7060          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7061          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7062   "TARGET_ARM"
7063   "@
7064    mov%D3\\t%0, %2
7065    mvn%D3\\t%0, #%B2
7066    mov%d3\\t%0, %1
7067    mvn%d3\\t%0, #%B1
7068    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7069    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7070    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7071    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7072   [(set_attr "length" "4,4,4,4,8,8,8,8")
7073    (set_attr "conds" "use")]
7074 )
7075
7076 (define_insn "*movsfcc_soft_insn"
7077   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7078         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7079                           [(match_operand 4 "cc_register" "") (const_int 0)])
7080                          (match_operand:SF 1 "s_register_operand" "0,r")
7081                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7082   "TARGET_ARM && TARGET_SOFT_FLOAT"
7083   "@
7084    mov%D3\\t%0, %2
7085    mov%d3\\t%0, %1"
7086   [(set_attr "conds" "use")]
7087 )
7088
7089 \f
7090 ;; Jump and linkage insns
7091
7092 (define_expand "jump"
7093   [(set (pc)
7094         (label_ref (match_operand 0 "" "")))]
7095   "TARGET_EITHER"
7096   ""
7097 )
7098
7099 (define_insn "*arm_jump"
7100   [(set (pc)
7101         (label_ref (match_operand 0 "" "")))]
7102   "TARGET_ARM"
7103   "*
7104   {
7105     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7106       {
7107         arm_ccfsm_state += 2;
7108         return \"\";
7109       }
7110     return \"b%?\\t%l0\";
7111   }
7112   "
7113   [(set_attr "predicable" "yes")]
7114 )
7115
7116 (define_insn "*thumb_jump"
7117   [(set (pc)
7118         (label_ref (match_operand 0 "" "")))]
7119   "TARGET_THUMB"
7120   "*
7121   if (get_attr_length (insn) == 2)
7122     return \"b\\t%l0\";
7123   return \"bl\\t%l0\\t%@ far jump\";
7124   "
7125   [(set (attr "far_jump")
7126         (if_then_else
7127             (eq_attr "length" "4")
7128             (const_string "yes")
7129             (const_string "no")))
7130    (set (attr "length") 
7131         (if_then_else
7132             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
7133                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
7134             (const_int 2)
7135             (const_int 4)))]
7136 )
7137
7138 (define_expand "call"
7139   [(parallel [(call (match_operand 0 "memory_operand" "")
7140                     (match_operand 1 "general_operand" ""))
7141               (use (match_operand 2 "" ""))
7142               (clobber (reg:SI LR_REGNUM))])]
7143   "TARGET_EITHER"
7144   "
7145   {
7146     rtx callee;
7147     
7148     /* In an untyped call, we can get NULL for operand 2.  */
7149     if (operands[2] == NULL_RTX)
7150       operands[2] = const0_rtx;
7151       
7152     /* This is to decide if we should generate indirect calls by loading the
7153        32 bit address of the callee into a register before performing the
7154        branch and link.  operand[2] encodes the long_call/short_call
7155        attribute of the function being called.  This attribute is set whenever
7156        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7157        is used, and the short_call attribute can also be set if function is
7158        declared as static or if it has already been defined in the current
7159        compilation unit.  See arm.c and arm.h for info about this.  The third
7160        parameter to arm_is_longcall_p is used to tell it which pattern
7161        invoked it.  */
7162     callee  = XEXP (operands[0], 0);
7163     
7164     if (GET_CODE (callee) != REG
7165        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7166       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7167   }"
7168 )
7169
7170 (define_insn "*call_reg"
7171   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7172          (match_operand 1 "" ""))
7173    (use (match_operand 2 "" ""))
7174    (clobber (reg:SI LR_REGNUM))]
7175   "TARGET_ARM"
7176   "*
7177   return output_call (operands);
7178   "
7179   ;; length is worst case, normally it is only two
7180   [(set_attr "length" "12")
7181    (set_attr "type" "call")]
7182 )
7183
7184 (define_insn "*call_mem"
7185   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7186          (match_operand 1 "" ""))
7187    (use (match_operand 2 "" ""))
7188    (clobber (reg:SI LR_REGNUM))]
7189   "TARGET_ARM"
7190   "*
7191   return output_call_mem (operands);
7192   "
7193   [(set_attr "length" "12")
7194    (set_attr "type" "call")]
7195 )
7196
7197 (define_insn "*call_indirect"
7198   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7199          (match_operand 1 "" ""))
7200    (use (match_operand 2 "" ""))
7201    (clobber (reg:SI LR_REGNUM))]
7202   "TARGET_THUMB"
7203   "*
7204   {
7205     if (TARGET_CALLER_INTERWORKING)
7206       return \"bl\\t%__interwork_call_via_%0\";
7207     else
7208       return \"bl\\t%__call_via_%0\";
7209   }"
7210   [(set_attr "type" "call")]
7211 )
7212
7213 (define_insn "*call_value_indirect"
7214   [(set (match_operand 0 "" "")
7215         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7216               (match_operand 2 "" "")))
7217    (use (match_operand 3 "" ""))
7218    (clobber (reg:SI LR_REGNUM))]
7219   "TARGET_THUMB"
7220   "*
7221   {
7222     if (TARGET_CALLER_INTERWORKING)
7223       return \"bl\\t%__interwork_call_via_%1\";
7224     else
7225       return \"bl\\t%__call_via_%1\";
7226   }"
7227   [(set_attr "type" "call")]
7228 )
7229
7230 (define_expand "call_value"
7231   [(parallel [(set (match_operand       0 "" "")
7232                    (call (match_operand 1 "memory_operand" "")
7233                          (match_operand 2 "general_operand" "")))
7234               (use (match_operand 3 "" ""))
7235               (clobber (reg:SI LR_REGNUM))])]
7236   "TARGET_EITHER"
7237   "
7238   {
7239     rtx callee = XEXP (operands[1], 0);
7240     
7241     /* In an untyped call, we can get NULL for operand 2.  */
7242     if (operands[3] == 0)
7243       operands[3] = const0_rtx;
7244       
7245     /* See the comment in define_expand \"call\".  */
7246     if (GET_CODE (callee) != REG
7247         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7248       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7249   }"
7250 )
7251
7252 (define_insn "*call_value_reg"
7253   [(set (match_operand 0 "" "")
7254         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7255               (match_operand 2 "" "")))
7256    (use (match_operand 3 "" ""))
7257    (clobber (reg:SI LR_REGNUM))]
7258   "TARGET_ARM"
7259   "*
7260   return output_call (&operands[1]);
7261   "
7262   [(set_attr "length" "12")
7263    (set_attr "type" "call")]
7264 )
7265
7266 (define_insn "*call_value_mem"
7267   [(set (match_operand 0 "" "")
7268         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7269               (match_operand 2 "" "")))
7270    (use (match_operand 3 "" ""))
7271    (clobber (reg:SI LR_REGNUM))]
7272   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7273   "*
7274   return output_call_mem (&operands[1]);
7275   "
7276   [(set_attr "length" "12")
7277    (set_attr "type" "call")]
7278 )
7279
7280 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7281 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7282
7283 (define_insn "*call_symbol"
7284   [(call (mem:SI (match_operand:SI 0 "" ""))
7285          (match_operand 1 "" ""))
7286    (use (match_operand 2 "" ""))
7287    (clobber (reg:SI LR_REGNUM))]
7288   "TARGET_ARM
7289    && (GET_CODE (operands[0]) == SYMBOL_REF)
7290    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7291   "*
7292   {
7293     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7294   }"
7295   [(set_attr "type" "call")]
7296 )
7297
7298 (define_insn "*call_value_symbol"
7299   [(set (match_operand 0 "s_register_operand" "")
7300         (call (mem:SI (match_operand:SI 1 "" ""))
7301         (match_operand:SI 2 "" "")))
7302    (use (match_operand 3 "" ""))
7303    (clobber (reg:SI LR_REGNUM))]
7304   "TARGET_ARM
7305    && (GET_CODE (operands[1]) == SYMBOL_REF)
7306    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7307   "*
7308   {
7309     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7310   }"
7311   [(set_attr "type" "call")]
7312 )
7313
7314 (define_insn "*call_insn"
7315   [(call (mem:SI (match_operand:SI 0 "" ""))
7316          (match_operand:SI 1 "" ""))
7317    (use (match_operand 2 "" ""))
7318    (clobber (reg:SI LR_REGNUM))]
7319   "TARGET_THUMB
7320    && GET_CODE (operands[0]) == SYMBOL_REF
7321    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7322   "bl\\t%a0"
7323   [(set_attr "length" "4")
7324    (set_attr "type" "call")]
7325 )
7326
7327 (define_insn "*call_value_insn"
7328   [(set (match_operand 0 "register_operand" "")
7329         (call (mem:SI (match_operand 1 "" ""))
7330               (match_operand 2 "" "")))
7331    (use (match_operand 3 "" ""))
7332    (clobber (reg:SI LR_REGNUM))]
7333   "TARGET_THUMB
7334    && GET_CODE (operands[1]) == SYMBOL_REF
7335    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7336   "bl\\t%a1"
7337   [(set_attr "length" "4")
7338    (set_attr "type" "call")]
7339 )
7340
7341 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7342 (define_expand "sibcall"
7343   [(parallel [(call (match_operand 0 "memory_operand" "")
7344                     (match_operand 1 "general_operand" ""))
7345               (return)
7346               (use (match_operand 2 "" ""))])]
7347   "TARGET_ARM"
7348   "
7349   {
7350     if (operands[2] == NULL_RTX)
7351       operands[2] = const0_rtx;
7352   }"
7353 )
7354
7355 (define_expand "sibcall_value"
7356   [(parallel [(set (match_operand 0 "register_operand" "")
7357                    (call (match_operand 1 "memory_operand" "")
7358                          (match_operand 2 "general_operand" "")))
7359               (return)
7360               (use (match_operand 3 "" ""))])]
7361   "TARGET_ARM"
7362   "
7363   {
7364     if (operands[3] == NULL_RTX)
7365       operands[3] = const0_rtx;
7366   }"
7367 )
7368
7369 (define_insn "*sibcall_insn"
7370  [(call (mem:SI (match_operand:SI 0 "" "X"))
7371         (match_operand 1 "" ""))
7372   (return)
7373   (use (match_operand 2 "" ""))]
7374   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7375   "*
7376   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7377   "
7378   [(set_attr "type" "call")]
7379 )
7380
7381 (define_insn "*sibcall_value_insn"
7382  [(set (match_operand 0 "s_register_operand" "")
7383        (call (mem:SI (match_operand:SI 1 "" "X"))
7384              (match_operand 2 "" "")))
7385   (return)
7386   (use (match_operand 3 "" ""))]
7387   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7388   "*
7389   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7390   "
7391   [(set_attr "type" "call")]
7392 )
7393
7394 ;; Often the return insn will be the same as loading from memory, so set attr
7395 (define_insn "return"
7396   [(return)]
7397   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7398   "*
7399   {
7400     if (arm_ccfsm_state == 2)
7401       {
7402         arm_ccfsm_state += 2;
7403         return \"\";
7404       }
7405     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7406   }"
7407   [(set_attr "type" "load")
7408    (set_attr "length" "12")
7409    (set_attr "predicable" "yes")]
7410 )
7411
7412 (define_insn "*cond_return"
7413   [(set (pc)
7414         (if_then_else (match_operator 0 "arm_comparison_operator"
7415                        [(match_operand 1 "cc_register" "") (const_int 0)])
7416                       (return)
7417                       (pc)))]
7418   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7419   "*
7420   {
7421     if (arm_ccfsm_state == 2)
7422       {
7423         arm_ccfsm_state += 2;
7424         return \"\";
7425       }
7426     return output_return_instruction (operands[0], TRUE, FALSE);
7427   }"
7428   [(set_attr "conds" "use")
7429    (set_attr "length" "12")
7430    (set_attr "type" "load")]
7431 )
7432
7433 (define_insn "*cond_return_inverted"
7434   [(set (pc)
7435         (if_then_else (match_operator 0 "arm_comparison_operator"
7436                        [(match_operand 1 "cc_register" "") (const_int 0)])
7437                       (pc)
7438                       (return)))]
7439   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7440   "*
7441   {
7442     if (arm_ccfsm_state == 2)
7443       {
7444         arm_ccfsm_state += 2;
7445         return \"\";
7446       }
7447     return output_return_instruction (operands[0], TRUE, TRUE);
7448   }"
7449   [(set_attr "conds" "use")
7450    (set_attr "type" "load")]
7451 )
7452
7453 ;; Generate a sequence of instructions to determine if the processor is
7454 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7455 ;; mask.
7456
7457 (define_expand "return_addr_mask"
7458   [(set (match_dup 1)
7459       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7460                        (const_int 0)))
7461    (set (match_operand:SI 0 "s_register_operand" "")
7462       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7463                        (const_int -1)
7464                        (const_int 67108860)))] ; 0x03fffffc
7465   "TARGET_ARM"
7466   "
7467   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7468   ")
7469
7470 (define_insn "*check_arch2"
7471   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7472       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7473                        (const_int 0)))]
7474   "TARGET_ARM"
7475   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7476   [(set_attr "length" "8")
7477    (set_attr "conds" "set")]
7478 )
7479
7480 ;; Call subroutine returning any type.
7481
7482 (define_expand "untyped_call"
7483   [(parallel [(call (match_operand 0 "" "")
7484                     (const_int 0))
7485               (match_operand 1 "" "")
7486               (match_operand 2 "" "")])]
7487   "TARGET_ARM"
7488   "
7489   {
7490     int i;
7491
7492     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7493
7494     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7495       {
7496         rtx set = XVECEXP (operands[2], 0, i);
7497
7498         emit_move_insn (SET_DEST (set), SET_SRC (set));
7499       }
7500
7501     /* The optimizer does not know that the call sets the function value
7502        registers we stored in the result block.  We avoid problems by
7503        claiming that all hard registers are used and clobbered at this
7504        point.  */
7505     emit_insn (gen_blockage ());
7506
7507     DONE;
7508   }"
7509 )
7510
7511 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7512 ;; all of memory.  This blocks insns from being moved across this point.
7513
7514 (define_insn "blockage"
7515   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7516   "TARGET_EITHER"
7517   ""
7518   [(set_attr "length" "0")
7519    (set_attr "type" "block")]
7520 )
7521
7522 (define_expand "casesi"
7523   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7524    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7525    (match_operand:SI 2 "const_int_operand" "")  ; total range
7526    (match_operand:SI 3 "" "")                   ; table label
7527    (match_operand:SI 4 "" "")]                  ; Out of range label
7528   "TARGET_ARM"
7529   "
7530   {
7531     rtx reg;
7532     if (operands[1] != const0_rtx)
7533       {
7534         reg = gen_reg_rtx (SImode);
7535
7536         emit_insn (gen_addsi3 (reg, operands[0],
7537                                GEN_INT (-INTVAL (operands[1]))));
7538         operands[0] = reg;
7539       }
7540
7541     if (!const_ok_for_arm (INTVAL (operands[2])))
7542       operands[2] = force_reg (SImode, operands[2]);
7543
7544     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7545                                          operands[4]));
7546     DONE;
7547   }"
7548 )
7549
7550 ;; The USE in this pattern is needed to tell flow analysis that this is
7551 ;; a CASESI insn.  It has no other purpose.
7552 (define_insn "casesi_internal"
7553   [(parallel [(set (pc)
7554                (if_then_else
7555                 (leu (match_operand:SI 0 "s_register_operand" "r")
7556                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7557                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7558                                  (label_ref (match_operand 2 "" ""))))
7559                 (label_ref (match_operand 3 "" ""))))
7560               (clobber (reg:CC CC_REGNUM))
7561               (use (label_ref (match_dup 2)))])]
7562   "TARGET_ARM"
7563   "*
7564     if (flag_pic)
7565       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7566     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7567   "
7568   [(set_attr "conds" "clob")
7569    (set_attr "length" "12")]
7570 )
7571
7572 (define_expand "indirect_jump"
7573   [(set (pc)
7574         (match_operand:SI 0 "s_register_operand" ""))]
7575   "TARGET_EITHER"
7576   ""
7577 )
7578
7579 (define_insn "*arm_indirect_jump"
7580   [(set (pc)
7581         (match_operand:SI 0 "s_register_operand" "r"))]
7582   "TARGET_ARM"
7583   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7584   [(set_attr "predicable" "yes")]
7585 )
7586
7587 ;; Although not supported by the define_expand above,
7588 ;; cse/combine may generate this form.
7589 (define_insn "*load_indirect_jump"
7590   [(set (pc)
7591         (match_operand:SI 0 "memory_operand" "m"))]
7592   "TARGET_ARM"
7593   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7594   [(set_attr "type" "load")
7595    (set_attr "pool_range" "4096")
7596    (set_attr "neg_pool_range" "4084")
7597    (set_attr "predicable" "yes")]
7598 )
7599
7600 (define_insn "*thumb_indirect_jump"
7601   [(set (pc)
7602         (match_operand:SI 0 "register_operand" "l*r"))]
7603   "TARGET_THUMB"
7604   "mov\\tpc, %0"
7605   [(set_attr "conds" "clob")
7606    (set_attr "length" "2")]
7607 )
7608
7609 \f
7610 ;; Misc insns
7611
7612 (define_insn "nop"
7613   [(const_int 0)]
7614   "TARGET_EITHER"
7615   "*
7616   if (TARGET_ARM)
7617     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7618   return  \"mov\\tr8, r8\";
7619   "
7620   [(set (attr "length")
7621         (if_then_else (eq_attr "is_thumb" "yes")
7622                       (const_int 2)
7623                       (const_int 4)))]
7624 )
7625
7626 \f
7627 ;; Patterns to allow combination of arithmetic, cond code and shifts
7628
7629 (define_insn "*arith_shiftsi"
7630   [(set (match_operand:SI 0 "s_register_operand" "=r")
7631         (match_operator:SI 1 "shiftable_operator"
7632           [(match_operator:SI 3 "shift_operator"
7633              [(match_operand:SI 4 "s_register_operand" "r")
7634               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7635            (match_operand:SI 2 "s_register_operand" "r")]))]
7636   "TARGET_ARM"
7637   "%i1%?\\t%0, %2, %4%S3"
7638   [(set_attr "predicable" "yes")
7639    (set_attr "shift" "4")
7640    ]
7641 )
7642
7643 (define_split
7644   [(set (match_operand:SI 0 "s_register_operand" "")
7645         (match_operator:SI 1 "shiftable_operator"
7646          [(match_operator:SI 2 "shiftable_operator"
7647            [(match_operator:SI 3 "shift_operator"
7648              [(match_operand:SI 4 "s_register_operand" "")
7649               (match_operand:SI 5 "reg_or_int_operand" "")])
7650             (match_operand:SI 6 "s_register_operand" "")])
7651           (match_operand:SI 7 "arm_rhs_operand" "")]))
7652    (clobber (match_operand:SI 8 "s_register_operand" ""))]
7653   "TARGET_ARM"
7654   [(set (match_dup 8)
7655         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7656                          (match_dup 6)]))
7657    (set (match_dup 0)
7658         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7659   "")
7660
7661 (define_insn "*arith_shiftsi_compare0"
7662   [(set (reg:CC_NOOV CC_REGNUM)
7663         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7664                           [(match_operator:SI 3 "shift_operator"
7665                             [(match_operand:SI 4 "s_register_operand" "r")
7666                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7667                            (match_operand:SI 2 "s_register_operand" "r")])
7668                          (const_int 0)))
7669    (set (match_operand:SI 0 "s_register_operand" "=r")
7670         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7671                          (match_dup 2)]))]
7672   "TARGET_ARM"
7673   "%i1%?s\\t%0, %2, %4%S3"
7674   [(set_attr "conds" "set")
7675    (set_attr "shift" "4")
7676    ]
7677 )
7678
7679 (define_insn "*arith_shiftsi_compare0_scratch"
7680   [(set (reg:CC_NOOV CC_REGNUM)
7681         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7682                           [(match_operator:SI 3 "shift_operator"
7683                             [(match_operand:SI 4 "s_register_operand" "r")
7684                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7685                            (match_operand:SI 2 "s_register_operand" "r")])
7686                          (const_int 0)))
7687    (clobber (match_scratch:SI 0 "=r"))]
7688   "TARGET_ARM"
7689   "%i1%?s\\t%0, %2, %4%S3"
7690   [(set_attr "conds" "set")
7691    (set_attr "shift" "4")
7692    ]
7693 )
7694
7695 (define_insn "*sub_shiftsi"
7696   [(set (match_operand:SI 0 "s_register_operand" "=r")
7697         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7698                   (match_operator:SI 2 "shift_operator"
7699                    [(match_operand:SI 3 "s_register_operand" "r")
7700                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7701   "TARGET_ARM"
7702   "sub%?\\t%0, %1, %3%S2"
7703   [(set_attr "predicable" "yes")
7704    (set_attr "shift" "3")
7705    ]
7706 )
7707
7708 (define_insn "*sub_shiftsi_compare0"
7709   [(set (reg:CC_NOOV CC_REGNUM)
7710         (compare:CC_NOOV
7711          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7712                    (match_operator:SI 2 "shift_operator"
7713                     [(match_operand:SI 3 "s_register_operand" "r")
7714                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7715          (const_int 0)))
7716    (set (match_operand:SI 0 "s_register_operand" "=r")
7717         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7718                                                  (match_dup 4)])))]
7719   "TARGET_ARM"
7720   "sub%?s\\t%0, %1, %3%S2"
7721   [(set_attr "conds" "set")
7722    (set_attr "shift" "3") 
7723    ]
7724 )
7725
7726 (define_insn "*sub_shiftsi_compare0_scratch"
7727   [(set (reg:CC_NOOV CC_REGNUM)
7728         (compare:CC_NOOV
7729          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7730                    (match_operator:SI 2 "shift_operator"
7731                     [(match_operand:SI 3 "s_register_operand" "r")
7732                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7733          (const_int 0)))
7734    (clobber (match_scratch:SI 0 "=r"))]
7735   "TARGET_ARM"
7736   "sub%?s\\t%0, %1, %3%S2"
7737   [(set_attr "conds" "set")
7738    (set_attr "shift" "3") 
7739    ]
7740 )
7741
7742 \f
7743
7744 (define_insn "*and_scc"
7745   [(set (match_operand:SI 0 "s_register_operand" "=r")
7746         (and:SI (match_operator:SI 1 "arm_comparison_operator"
7747                  [(match_operand 3 "cc_register" "") (const_int 0)])
7748                 (match_operand:SI 2 "s_register_operand" "r")))]
7749   "TARGET_ARM"
7750   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7751   [(set_attr "conds" "use")
7752    (set_attr "length" "8")]
7753 )
7754
7755 (define_insn "*ior_scc"
7756   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7757         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7758                  [(match_operand 3 "cc_register" "") (const_int 0)])
7759                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7760   "TARGET_ARM"
7761   "@
7762    orr%d2\\t%0, %1, #1
7763    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7764   [(set_attr "conds" "use")
7765    (set_attr "length" "4,8")]
7766 )
7767
7768 (define_insn "*compare_scc"
7769   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7770         (match_operator:SI 1 "arm_comparison_operator"
7771          [(match_operand:SI 2 "s_register_operand" "r,r")
7772           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7773    (clobber (reg:CC CC_REGNUM))]
7774   "TARGET_ARM"
7775   "*
7776     if (operands[3] == const0_rtx)
7777       {
7778         if (GET_CODE (operands[1]) == LT)
7779           return \"mov\\t%0, %2, lsr #31\";
7780
7781         if (GET_CODE (operands[1]) == GE)
7782           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7783
7784         if (GET_CODE (operands[1]) == EQ)
7785           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
7786       }
7787
7788     if (GET_CODE (operands[1]) == NE)
7789       {
7790         if (which_alternative == 1)
7791           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7792         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7793       }
7794     if (which_alternative == 1)
7795       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7796     else
7797       output_asm_insn (\"cmp\\t%2, %3\", operands);
7798     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7799   "
7800   [(set_attr "conds" "clob")
7801    (set_attr "length" "12")]
7802 )
7803
7804 (define_insn "*cond_move"
7805   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7806         (if_then_else:SI (match_operator 3 "equality_operator"
7807                           [(match_operator 4 "arm_comparison_operator"
7808                             [(match_operand 5 "cc_register" "") (const_int 0)])
7809                            (const_int 0)])
7810                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7811                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7812   "TARGET_ARM"
7813   "*
7814     if (GET_CODE (operands[3]) == NE)
7815       {
7816         if (which_alternative != 1)
7817           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7818         if (which_alternative != 0)
7819           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7820         return \"\";
7821       }
7822     if (which_alternative != 0)
7823       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7824     if (which_alternative != 1)
7825       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7826     return \"\";
7827   "
7828   [(set_attr "conds" "use")
7829    (set_attr "length" "4,4,8")]
7830 )
7831
7832 (define_insn "*cond_arith"
7833   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7834         (match_operator:SI 5 "shiftable_operator" 
7835          [(match_operator:SI 4 "arm_comparison_operator"
7836            [(match_operand:SI 2 "s_register_operand" "r,r")
7837             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7838           (match_operand:SI 1 "s_register_operand" "0,?r")]))
7839    (clobber (reg:CC CC_REGNUM))]
7840   "TARGET_ARM"
7841   "*
7842     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7843       return \"%i5\\t%0, %1, %2, lsr #31\";
7844
7845     output_asm_insn (\"cmp\\t%2, %3\", operands);
7846     if (GET_CODE (operands[5]) == AND)
7847       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7848     else if (GET_CODE (operands[5]) == MINUS)
7849       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7850     else if (which_alternative != 0)
7851       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7852     return \"%i5%d4\\t%0, %1, #1\";
7853   "
7854   [(set_attr "conds" "clob")
7855    (set_attr "length" "12")]
7856 )
7857
7858 (define_insn "*cond_sub"
7859   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7860         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7861                   (match_operator:SI 4 "arm_comparison_operator"
7862                    [(match_operand:SI 2 "s_register_operand" "r,r")
7863                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7864    (clobber (reg:CC CC_REGNUM))]
7865   "TARGET_ARM"
7866   "*
7867     output_asm_insn (\"cmp\\t%2, %3\", operands);
7868     if (which_alternative != 0)
7869       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7870     return \"sub%d4\\t%0, %1, #1\";
7871   "
7872   [(set_attr "conds" "clob")
7873    (set_attr "length" "8,12")]
7874 )
7875
7876 (define_insn "*cmp_ite0"
7877   [(set (match_operand 6 "dominant_cc_register" "")
7878         (compare
7879          (if_then_else:SI
7880           (match_operator 4 "arm_comparison_operator"
7881            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7882             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7883           (match_operator:SI 5 "arm_comparison_operator"
7884            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7885             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7886           (const_int 0))
7887          (const_int 0)))]
7888   "TARGET_ARM"
7889   "*
7890   {
7891     static const char * const opcodes[4][2] =
7892     {
7893       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7894        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7895       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7896        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7897       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7898        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7899       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7900        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7901     };
7902     int swap =
7903       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7904
7905     return opcodes[which_alternative][swap];
7906   }"
7907   [(set_attr "conds" "set")
7908    (set_attr "length" "8")]
7909 )
7910
7911 (define_insn "*cmp_ite1"
7912   [(set (match_operand 6 "dominant_cc_register" "")
7913         (compare
7914          (if_then_else:SI
7915           (match_operator 4 "arm_comparison_operator"
7916            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7917             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7918           (match_operator:SI 5 "arm_comparison_operator"
7919            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7920             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7921           (const_int 1))
7922          (const_int 0)))]
7923   "TARGET_ARM"
7924   "*
7925   {
7926     static const char * const opcodes[4][2] =
7927     {
7928       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7929        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7930       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7931        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7932       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7933        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7934       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7935        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7936     };
7937     int swap =
7938       comparison_dominates_p (GET_CODE (operands[5]),
7939                               reverse_condition (GET_CODE (operands[4])));
7940
7941     return opcodes[which_alternative][swap];
7942   }"
7943   [(set_attr "conds" "set")
7944    (set_attr "length" "8")]
7945 )
7946
7947 (define_insn "*cmp_and"
7948   [(set (match_operand 6 "dominant_cc_register" "")
7949         (compare
7950          (and:SI
7951           (match_operator 4 "arm_comparison_operator"
7952            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7953             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7954           (match_operator:SI 5 "arm_comparison_operator"
7955            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7956             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7957          (const_int 0)))]
7958   "TARGET_ARM"
7959   "*
7960   {
7961     static const char *const opcodes[4][2] =
7962     {
7963       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7964        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7965       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7966        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7967       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7968        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7969       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7970        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7971     };
7972     int swap =
7973       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7974
7975     return opcodes[which_alternative][swap];
7976   }"
7977   [(set_attr "conds" "set")
7978    (set_attr "predicable" "no")
7979    (set_attr "length" "8")]
7980 )
7981
7982 (define_insn "*cmp_ior"
7983   [(set (match_operand 6 "dominant_cc_register" "")
7984         (compare
7985          (ior:SI
7986           (match_operator 4 "arm_comparison_operator"
7987            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7988             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7989           (match_operator:SI 5 "arm_comparison_operator"
7990            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7991             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7992          (const_int 0)))]
7993   "TARGET_ARM"
7994   "*
7995 {
7996   static const char *const opcodes[4][2] =
7997   {
7998     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7999      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8000     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8001      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8002     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8003      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8004     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8005      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8006   };
8007   int swap =
8008     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8009
8010   return opcodes[which_alternative][swap];
8011 }
8012 "
8013   [(set_attr "conds" "set")
8014    (set_attr "length" "8")]
8015 )
8016
8017 (define_insn_and_split "*ior_scc_scc"
8018   [(set (match_operand:SI 0 "s_register_operand" "=r")
8019         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8020                  [(match_operand:SI 1 "s_register_operand" "r")
8021                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8022                 (match_operator:SI 6 "arm_comparison_operator"
8023                  [(match_operand:SI 4 "s_register_operand" "r")
8024                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8025    (clobber (reg:CC CC_REGNUM))]
8026   "TARGET_ARM
8027    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8028        != CCmode)"
8029   "#"
8030   "TARGET_ARM && reload_completed"
8031   [(set (match_dup 7)
8032         (compare
8033          (ior:SI
8034           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8035           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8036          (const_int 0)))
8037    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8038   "operands[7]
8039      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8040                                                   DOM_CC_X_OR_Y),
8041                     CC_REGNUM);"
8042   [(set_attr "conds" "clob")
8043    (set_attr "length" "16")])
8044
8045 ; If the above pattern is followed by a CMP insn, then the compare is 
8046 ; redundant, since we can rework the conditional instruction that follows.
8047 (define_insn_and_split "*ior_scc_scc_cmp"
8048   [(set (match_operand 0 "dominant_cc_register" "")
8049         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8050                           [(match_operand:SI 1 "s_register_operand" "r")
8051                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8052                          (match_operator:SI 6 "arm_comparison_operator"
8053                           [(match_operand:SI 4 "s_register_operand" "r")
8054                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8055                  (const_int 0)))
8056    (set (match_operand:SI 7 "s_register_operand" "=r")
8057         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8058                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8059   "TARGET_ARM"
8060   "#"
8061   "TARGET_ARM && reload_completed"
8062   [(set (match_dup 0)
8063         (compare
8064          (ior:SI
8065           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8066           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8067          (const_int 0)))
8068    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8069   ""
8070   [(set_attr "conds" "set")
8071    (set_attr "length" "16")])
8072
8073 (define_insn_and_split "*and_scc_scc"
8074   [(set (match_operand:SI 0 "s_register_operand" "=r")
8075         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8076                  [(match_operand:SI 1 "s_register_operand" "r")
8077                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8078                 (match_operator:SI 6 "arm_comparison_operator"
8079                  [(match_operand:SI 4 "s_register_operand" "r")
8080                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8081    (clobber (reg:CC CC_REGNUM))]
8082   "TARGET_ARM
8083    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8084        != CCmode)"
8085   "#"
8086   "TARGET_ARM && reload_completed
8087    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8088        != CCmode)"
8089   [(set (match_dup 7)
8090         (compare
8091          (and:SI
8092           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8093           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8094          (const_int 0)))
8095    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8096   "operands[7]
8097      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8098                                                   DOM_CC_X_AND_Y),
8099                     CC_REGNUM);"
8100   [(set_attr "conds" "clob")
8101    (set_attr "length" "16")])
8102
8103 ; If the above pattern is followed by a CMP insn, then the compare is 
8104 ; redundant, since we can rework the conditional instruction that follows.
8105 (define_insn_and_split "*and_scc_scc_cmp"
8106   [(set (match_operand 0 "dominant_cc_register" "")
8107         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8108                           [(match_operand:SI 1 "s_register_operand" "r")
8109                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8110                          (match_operator:SI 6 "arm_comparison_operator"
8111                           [(match_operand:SI 4 "s_register_operand" "r")
8112                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8113                  (const_int 0)))
8114    (set (match_operand:SI 7 "s_register_operand" "=r")
8115         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8116                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8117   "TARGET_ARM"
8118   "#"
8119   "TARGET_ARM && reload_completed"
8120   [(set (match_dup 0)
8121         (compare
8122          (and:SI
8123           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8124           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8125          (const_int 0)))
8126    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8127   ""
8128   [(set_attr "conds" "set")
8129    (set_attr "length" "16")])
8130
8131 ;; If there is no dominance in the comparison, then we can still save an
8132 ;; instruction in the AND case, since we can know that the second compare
8133 ;; need only zero the value if false (if true, then the value is already
8134 ;; correct).
8135 (define_insn_and_split "*and_scc_scc_nodom"
8136   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8137         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8138                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8139                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8140                 (match_operator:SI 6 "arm_comparison_operator"
8141                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8142                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8143    (clobber (reg:CC CC_REGNUM))]
8144   "TARGET_ARM
8145    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8146        == CCmode)"
8147   "#"
8148   "TARGET_ARM && reload_completed"
8149   [(parallel [(set (match_dup 0)
8150                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8151               (clobber (reg:CC CC_REGNUM))])
8152    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8153    (set (match_dup 0)
8154         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8155                          (match_dup 0)
8156                          (const_int 0)))]
8157   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8158                                               operands[4], operands[5]),
8159                               CC_REGNUM);
8160    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8161                                   operands[5]);"
8162   [(set_attr "conds" "clob")
8163    (set_attr "length" "20")])
8164
8165 (define_split
8166   [(set (reg:CC_NOOV CC_REGNUM)
8167         (compare:CC_NOOV (ior:SI
8168                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8169                                   (const_int 1))
8170                           (match_operator:SI 1 "comparison_operator"
8171                            [(match_operand:SI 2 "s_register_operand" "")
8172                             (match_operand:SI 3 "arm_add_operand" "")]))
8173                          (const_int 0)))
8174    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8175   "TARGET_ARM"
8176   [(set (match_dup 4)
8177         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8178                 (match_dup 0)))
8179    (set (reg:CC_NOOV CC_REGNUM)
8180         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8181                          (const_int 0)))]
8182   "")
8183
8184 (define_split
8185   [(set (reg:CC_NOOV CC_REGNUM)
8186         (compare:CC_NOOV (ior:SI
8187                           (match_operator:SI 1 "comparison_operator"
8188                            [(match_operand:SI 2 "s_register_operand" "")
8189                             (match_operand:SI 3 "arm_add_operand" "")])
8190                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8191                                   (const_int 1)))
8192                          (const_int 0)))
8193    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8194   "TARGET_ARM"
8195   [(set (match_dup 4)
8196         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8197                 (match_dup 0)))
8198    (set (reg:CC_NOOV CC_REGNUM)
8199         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8200                          (const_int 0)))]
8201   "")
8202
8203 (define_insn "*negscc"
8204   [(set (match_operand:SI 0 "s_register_operand" "=r")
8205         (neg:SI (match_operator 3 "arm_comparison_operator"
8206                  [(match_operand:SI 1 "s_register_operand" "r")
8207                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8208    (clobber (reg:CC CC_REGNUM))]
8209   "TARGET_ARM"
8210   "*
8211   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8212     return \"mov\\t%0, %1, asr #31\";
8213
8214   if (GET_CODE (operands[3]) == NE)
8215     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8216
8217   if (GET_CODE (operands[3]) == GT)
8218     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8219
8220   output_asm_insn (\"cmp\\t%1, %2\", operands);
8221   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8222   return \"mvn%d3\\t%0, #0\";
8223   "
8224   [(set_attr "conds" "clob")
8225    (set_attr "length" "12")]
8226 )
8227
8228 (define_insn "movcond"
8229   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8230         (if_then_else:SI
8231          (match_operator 5 "arm_comparison_operator"
8232           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8233            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8234          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8235          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8236    (clobber (reg:CC CC_REGNUM))]
8237   "TARGET_ARM"
8238   "*
8239   if (GET_CODE (operands[5]) == LT
8240       && (operands[4] == const0_rtx))
8241     {
8242       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8243         {
8244           if (operands[2] == const0_rtx)
8245             return \"and\\t%0, %1, %3, asr #31\";
8246           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8247         }
8248       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8249         {
8250           if (operands[1] == const0_rtx)
8251             return \"bic\\t%0, %2, %3, asr #31\";
8252           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8253         }
8254       /* The only case that falls through to here is when both ops 1 & 2
8255          are constants */
8256     }
8257
8258   if (GET_CODE (operands[5]) == GE
8259       && (operands[4] == const0_rtx))
8260     {
8261       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8262         {
8263           if (operands[2] == const0_rtx)
8264             return \"bic\\t%0, %1, %3, asr #31\";
8265           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8266         }
8267       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8268         {
8269           if (operands[1] == const0_rtx)
8270             return \"and\\t%0, %2, %3, asr #31\";
8271           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8272         }
8273       /* The only case that falls through to here is when both ops 1 & 2
8274          are constants */
8275     }
8276   if (GET_CODE (operands[4]) == CONST_INT
8277       && !const_ok_for_arm (INTVAL (operands[4])))
8278     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8279   else
8280     output_asm_insn (\"cmp\\t%3, %4\", operands);
8281   if (which_alternative != 0)
8282     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8283   if (which_alternative != 1)
8284     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8285   return \"\";
8286   "
8287   [(set_attr "conds" "clob")
8288    (set_attr "length" "8,8,12")]
8289 )
8290
8291 (define_insn "*ifcompare_plus_move"
8292   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8293         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8294                           [(match_operand:SI 4 "s_register_operand" "r,r")
8295                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8296                          (plus:SI
8297                           (match_operand:SI 2 "s_register_operand" "r,r")
8298                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8299                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8300    (clobber (reg:CC CC_REGNUM))]
8301   "TARGET_ARM"
8302   "#"
8303   [(set_attr "conds" "clob")
8304    (set_attr "length" "8,12")]
8305 )
8306
8307 (define_insn "*if_plus_move"
8308   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8309         (if_then_else:SI
8310          (match_operator 4 "arm_comparison_operator"
8311           [(match_operand 5 "cc_register" "") (const_int 0)])
8312          (plus:SI
8313           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8314           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8315          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8316   "TARGET_ARM"
8317   "@
8318    add%d4\\t%0, %2, %3
8319    sub%d4\\t%0, %2, #%n3
8320    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8321    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8322   [(set_attr "conds" "use")
8323    (set_attr "length" "4,4,8,8")
8324    (set_attr "type" "*,*,*,*")]
8325 )
8326
8327 (define_insn "*ifcompare_move_plus"
8328   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8329         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8330                           [(match_operand:SI 4 "s_register_operand" "r,r")
8331                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8332                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8333                          (plus:SI
8334                           (match_operand:SI 2 "s_register_operand" "r,r")
8335                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8336    (clobber (reg:CC CC_REGNUM))]
8337   "TARGET_ARM"
8338   "#"
8339   [(set_attr "conds" "clob")
8340    (set_attr "length" "8,12")]
8341 )
8342
8343 (define_insn "*if_move_plus"
8344   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8345         (if_then_else:SI
8346          (match_operator 4 "arm_comparison_operator"
8347           [(match_operand 5 "cc_register" "") (const_int 0)])
8348          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8349          (plus:SI
8350           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8351           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8352   "TARGET_ARM"
8353   "@
8354    add%D4\\t%0, %2, %3
8355    sub%D4\\t%0, %2, #%n3
8356    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8357    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8358   [(set_attr "conds" "use")
8359    (set_attr "length" "4,4,8,8")
8360    (set_attr "type" "*,*,*,*")]
8361 )
8362
8363 (define_insn "*ifcompare_arith_arith"
8364   [(set (match_operand:SI 0 "s_register_operand" "=r")
8365         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8366                           [(match_operand:SI 5 "s_register_operand" "r")
8367                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8368                          (match_operator:SI 8 "shiftable_operator"
8369                           [(match_operand:SI 1 "s_register_operand" "r")
8370                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8371                          (match_operator:SI 7 "shiftable_operator"
8372                           [(match_operand:SI 3 "s_register_operand" "r")
8373                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8374    (clobber (reg:CC CC_REGNUM))]
8375   "TARGET_ARM"
8376   "#"
8377   [(set_attr "conds" "clob")
8378    (set_attr "length" "12")]
8379 )
8380
8381 (define_insn "*if_arith_arith"
8382   [(set (match_operand:SI 0 "s_register_operand" "=r")
8383         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8384                           [(match_operand 8 "cc_register" "") (const_int 0)])
8385                          (match_operator:SI 6 "shiftable_operator"
8386                           [(match_operand:SI 1 "s_register_operand" "r")
8387                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8388                          (match_operator:SI 7 "shiftable_operator"
8389                           [(match_operand:SI 3 "s_register_operand" "r")
8390                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8391   "TARGET_ARM"
8392   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8393   [(set_attr "conds" "use")
8394    (set_attr "length" "8")]
8395 )
8396
8397 (define_insn "*ifcompare_arith_move"
8398   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8399         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8400                           [(match_operand:SI 2 "s_register_operand" "r,r")
8401                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8402                          (match_operator:SI 7 "shiftable_operator"
8403                           [(match_operand:SI 4 "s_register_operand" "r,r")
8404                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8405                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8406    (clobber (reg:CC CC_REGNUM))]
8407   "TARGET_ARM"
8408   "*
8409   /* If we have an operation where (op x 0) is the identity operation and
8410      the conditional operator is LT or GE and we are comparing against zero and
8411      everything is in registers then we can do this in two instructions */
8412   if (operands[3] == const0_rtx
8413       && GET_CODE (operands[7]) != AND
8414       && GET_CODE (operands[5]) == REG
8415       && GET_CODE (operands[1]) == REG 
8416       && REGNO (operands[1]) == REGNO (operands[4])
8417       && REGNO (operands[4]) != REGNO (operands[0]))
8418     {
8419       if (GET_CODE (operands[6]) == LT)
8420         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8421       else if (GET_CODE (operands[6]) == GE)
8422         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8423     }
8424   if (GET_CODE (operands[3]) == CONST_INT
8425       && !const_ok_for_arm (INTVAL (operands[3])))
8426     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8427   else
8428     output_asm_insn (\"cmp\\t%2, %3\", operands);
8429   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8430   if (which_alternative != 0)
8431     return \"mov%D6\\t%0, %1\";
8432   return \"\";
8433   "
8434   [(set_attr "conds" "clob")
8435    (set_attr "length" "8,12")]
8436 )
8437
8438 (define_insn "*if_arith_move"
8439   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8440         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8441                           [(match_operand 6 "cc_register" "") (const_int 0)])
8442                          (match_operator:SI 5 "shiftable_operator"
8443                           [(match_operand:SI 2 "s_register_operand" "r,r")
8444                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8445                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8446   "TARGET_ARM"
8447   "@
8448    %I5%d4\\t%0, %2, %3
8449    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8450   [(set_attr "conds" "use")
8451    (set_attr "length" "4,8")
8452    (set_attr "type" "*,*")]
8453 )
8454
8455 (define_insn "*ifcompare_move_arith"
8456   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8457         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8458                           [(match_operand:SI 4 "s_register_operand" "r,r")
8459                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8460                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8461                          (match_operator:SI 7 "shiftable_operator"
8462                           [(match_operand:SI 2 "s_register_operand" "r,r")
8463                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8464    (clobber (reg:CC CC_REGNUM))]
8465   "TARGET_ARM"
8466   "*
8467   /* If we have an operation where (op x 0) is the identity operation and
8468      the conditional operator is LT or GE and we are comparing against zero and
8469      everything is in registers then we can do this in two instructions */
8470   if (operands[5] == const0_rtx
8471       && GET_CODE (operands[7]) != AND
8472       && GET_CODE (operands[3]) == REG
8473       && GET_CODE (operands[1]) == REG 
8474       && REGNO (operands[1]) == REGNO (operands[2])
8475       && REGNO (operands[2]) != REGNO (operands[0]))
8476     {
8477       if (GET_CODE (operands[6]) == GE)
8478         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8479       else if (GET_CODE (operands[6]) == LT)
8480         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8481     }
8482
8483   if (GET_CODE (operands[5]) == CONST_INT
8484       && !const_ok_for_arm (INTVAL (operands[5])))
8485     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8486   else
8487     output_asm_insn (\"cmp\\t%4, %5\", operands);
8488
8489   if (which_alternative != 0)
8490     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8491   return \"%I7%D6\\t%0, %2, %3\";
8492   "
8493   [(set_attr "conds" "clob")
8494    (set_attr "length" "8,12")]
8495 )
8496
8497 (define_insn "*if_move_arith"
8498   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8499         (if_then_else:SI
8500          (match_operator 4 "arm_comparison_operator"
8501           [(match_operand 6 "cc_register" "") (const_int 0)])
8502          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8503          (match_operator:SI 5 "shiftable_operator"
8504           [(match_operand:SI 2 "s_register_operand" "r,r")
8505            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8506   "TARGET_ARM"
8507   "@
8508    %I5%D4\\t%0, %2, %3
8509    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8510   [(set_attr "conds" "use")
8511    (set_attr "length" "4,8")
8512    (set_attr "type" "*,*")]
8513 )
8514
8515 (define_insn "*ifcompare_move_not"
8516   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8517         (if_then_else:SI
8518          (match_operator 5 "arm_comparison_operator"
8519           [(match_operand:SI 3 "s_register_operand" "r,r")
8520            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8521          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8522          (not:SI
8523           (match_operand:SI 2 "s_register_operand" "r,r"))))
8524    (clobber (reg:CC CC_REGNUM))]
8525   "TARGET_ARM"
8526   "#"
8527   [(set_attr "conds" "clob")
8528    (set_attr "length" "8,12")]
8529 )
8530
8531 (define_insn "*if_move_not"
8532   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8533         (if_then_else:SI
8534          (match_operator 4 "arm_comparison_operator"
8535           [(match_operand 3 "cc_register" "") (const_int 0)])
8536          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8537          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8538   "TARGET_ARM"
8539   "@
8540    mvn%D4\\t%0, %2
8541    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8542    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8543   [(set_attr "conds" "use")
8544    (set_attr "length" "4,8,8")]
8545 )
8546
8547 (define_insn "*ifcompare_not_move"
8548   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8549         (if_then_else:SI 
8550          (match_operator 5 "arm_comparison_operator"
8551           [(match_operand:SI 3 "s_register_operand" "r,r")
8552            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8553          (not:SI
8554           (match_operand:SI 2 "s_register_operand" "r,r"))
8555          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8556    (clobber (reg:CC CC_REGNUM))]
8557   "TARGET_ARM"
8558   "#"
8559   [(set_attr "conds" "clob")
8560    (set_attr "length" "8,12")]
8561 )
8562
8563 (define_insn "*if_not_move"
8564   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8565         (if_then_else:SI
8566          (match_operator 4 "arm_comparison_operator"
8567           [(match_operand 3 "cc_register" "") (const_int 0)])
8568          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8569          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8570   "TARGET_ARM"
8571   "@
8572    mvn%d4\\t%0, %2
8573    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8574    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8575   [(set_attr "conds" "use")
8576    (set_attr "length" "4,8,8")]
8577 )
8578
8579 (define_insn "*ifcompare_shift_move"
8580   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8581         (if_then_else:SI
8582          (match_operator 6 "arm_comparison_operator"
8583           [(match_operand:SI 4 "s_register_operand" "r,r")
8584            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8585          (match_operator:SI 7 "shift_operator"
8586           [(match_operand:SI 2 "s_register_operand" "r,r")
8587            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8588          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8589    (clobber (reg:CC CC_REGNUM))]
8590   "TARGET_ARM"
8591   "#"
8592   [(set_attr "conds" "clob")
8593    (set_attr "length" "8,12")]
8594 )
8595
8596 (define_insn "*if_shift_move"
8597   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8598         (if_then_else:SI
8599          (match_operator 5 "arm_comparison_operator"
8600           [(match_operand 6 "cc_register" "") (const_int 0)])
8601          (match_operator:SI 4 "shift_operator"
8602           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8603            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8604          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8605   "TARGET_ARM"
8606   "@
8607    mov%d5\\t%0, %2%S4
8608    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8609    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8610   [(set_attr "conds" "use")
8611    (set_attr "shift" "2")
8612    (set_attr "length" "4,8,8")]
8613 )
8614
8615 (define_insn "*ifcompare_move_shift"
8616   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8617         (if_then_else:SI
8618          (match_operator 6 "arm_comparison_operator"
8619           [(match_operand:SI 4 "s_register_operand" "r,r")
8620            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8621          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8622          (match_operator:SI 7 "shift_operator"
8623           [(match_operand:SI 2 "s_register_operand" "r,r")
8624            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8625    (clobber (reg:CC CC_REGNUM))]
8626   "TARGET_ARM"
8627   "#"
8628   [(set_attr "conds" "clob")
8629    (set_attr "length" "8,12")]
8630 )
8631
8632 (define_insn "*if_move_shift"
8633   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8634         (if_then_else:SI
8635          (match_operator 5 "arm_comparison_operator"
8636           [(match_operand 6 "cc_register" "") (const_int 0)])
8637          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8638          (match_operator:SI 4 "shift_operator"
8639           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8640            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8641   "TARGET_ARM"
8642   "@
8643    mov%D5\\t%0, %2%S4
8644    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8645    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8646   [(set_attr "conds" "use")
8647    (set_attr "shift" "2")
8648    (set_attr "length" "4,8,8")]
8649 )
8650
8651 (define_insn "*ifcompare_shift_shift"
8652   [(set (match_operand:SI 0 "s_register_operand" "=r")
8653         (if_then_else:SI
8654          (match_operator 7 "arm_comparison_operator"
8655           [(match_operand:SI 5 "s_register_operand" "r")
8656            (match_operand:SI 6 "arm_add_operand" "rIL")])
8657          (match_operator:SI 8 "shift_operator"
8658           [(match_operand:SI 1 "s_register_operand" "r")
8659            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8660          (match_operator:SI 9 "shift_operator"
8661           [(match_operand:SI 3 "s_register_operand" "r")
8662            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8663    (clobber (reg:CC CC_REGNUM))]
8664   "TARGET_ARM"
8665   "#"
8666   [(set_attr "conds" "clob")
8667    (set_attr "length" "12")]
8668 )
8669
8670 (define_insn "*if_shift_shift"
8671   [(set (match_operand:SI 0 "s_register_operand" "=r")
8672         (if_then_else:SI
8673          (match_operator 5 "arm_comparison_operator"
8674           [(match_operand 8 "cc_register" "") (const_int 0)])
8675          (match_operator:SI 6 "shift_operator"
8676           [(match_operand:SI 1 "s_register_operand" "r")
8677            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8678          (match_operator:SI 7 "shift_operator"
8679           [(match_operand:SI 3 "s_register_operand" "r")
8680            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8681   "TARGET_ARM"
8682   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8683   [(set_attr "conds" "use")
8684    (set_attr "shift" "1")
8685    (set_attr "length" "8")]
8686 )
8687
8688 (define_insn "*ifcompare_not_arith"
8689   [(set (match_operand:SI 0 "s_register_operand" "=r")
8690         (if_then_else:SI
8691          (match_operator 6 "arm_comparison_operator"
8692           [(match_operand:SI 4 "s_register_operand" "r")
8693            (match_operand:SI 5 "arm_add_operand" "rIL")])
8694          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8695          (match_operator:SI 7 "shiftable_operator"
8696           [(match_operand:SI 2 "s_register_operand" "r")
8697            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8698    (clobber (reg:CC CC_REGNUM))]
8699   "TARGET_ARM"
8700   "#"
8701   [(set_attr "conds" "clob")
8702    (set_attr "length" "12")]
8703 )
8704
8705 (define_insn "*if_not_arith"
8706   [(set (match_operand:SI 0 "s_register_operand" "=r")
8707         (if_then_else:SI
8708          (match_operator 5 "arm_comparison_operator"
8709           [(match_operand 4 "cc_register" "") (const_int 0)])
8710          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8711          (match_operator:SI 6 "shiftable_operator"
8712           [(match_operand:SI 2 "s_register_operand" "r")
8713            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8714   "TARGET_ARM"
8715   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8716   [(set_attr "conds" "use")
8717    (set_attr "length" "8")]
8718 )
8719
8720 (define_insn "*ifcompare_arith_not"
8721   [(set (match_operand:SI 0 "s_register_operand" "=r")
8722         (if_then_else:SI
8723          (match_operator 6 "arm_comparison_operator"
8724           [(match_operand:SI 4 "s_register_operand" "r")
8725            (match_operand:SI 5 "arm_add_operand" "rIL")])
8726          (match_operator:SI 7 "shiftable_operator"
8727           [(match_operand:SI 2 "s_register_operand" "r")
8728            (match_operand:SI 3 "arm_rhs_operand" "rI")])
8729          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8730    (clobber (reg:CC CC_REGNUM))]
8731   "TARGET_ARM"
8732   "#"
8733   [(set_attr "conds" "clob")
8734    (set_attr "length" "12")]
8735 )
8736
8737 (define_insn "*if_arith_not"
8738   [(set (match_operand:SI 0 "s_register_operand" "=r")
8739         (if_then_else:SI
8740          (match_operator 5 "arm_comparison_operator"
8741           [(match_operand 4 "cc_register" "") (const_int 0)])
8742          (match_operator:SI 6 "shiftable_operator"
8743           [(match_operand:SI 2 "s_register_operand" "r")
8744            (match_operand:SI 3 "arm_rhs_operand" "rI")])
8745          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
8746   "TARGET_ARM"
8747   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8748   [(set_attr "conds" "use")
8749    (set_attr "length" "8")]
8750 )
8751
8752 (define_insn "*ifcompare_neg_move"
8753   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8754         (if_then_else:SI
8755          (match_operator 5 "arm_comparison_operator"
8756           [(match_operand:SI 3 "s_register_operand" "r,r")
8757            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8758          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
8759          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8760    (clobber (reg:CC CC_REGNUM))]
8761   "TARGET_ARM"
8762   "#"
8763   [(set_attr "conds" "clob")
8764    (set_attr "length" "8,12")]
8765 )
8766
8767 (define_insn "*if_neg_move"
8768   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8769         (if_then_else:SI
8770          (match_operator 4 "arm_comparison_operator"
8771           [(match_operand 3 "cc_register" "") (const_int 0)])
8772          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8773          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8774   "TARGET_ARM"
8775   "@
8776    rsb%d4\\t%0, %2, #0
8777    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8778    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8779   [(set_attr "conds" "use")
8780    (set_attr "length" "4,8,8")]
8781 )
8782
8783 (define_insn "*ifcompare_move_neg"
8784   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8785         (if_then_else:SI
8786          (match_operator 5 "arm_comparison_operator"
8787           [(match_operand:SI 3 "s_register_operand" "r,r")
8788            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8789          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8790          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8791    (clobber (reg:CC CC_REGNUM))]
8792   "TARGET_ARM"
8793   "#"
8794   [(set_attr "conds" "clob")
8795    (set_attr "length" "8,12")]
8796 )
8797
8798 (define_insn "*if_move_neg"
8799   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8800         (if_then_else:SI
8801          (match_operator 4 "arm_comparison_operator"
8802           [(match_operand 3 "cc_register" "") (const_int 0)])
8803          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8804          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8805   "TARGET_ARM"
8806   "@
8807    rsb%D4\\t%0, %2, #0
8808    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8809    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8810   [(set_attr "conds" "use")
8811    (set_attr "length" "4,8,8")]
8812 )
8813
8814 (define_insn "*arith_adjacentmem"
8815   [(set (match_operand:SI 0 "s_register_operand" "=r")
8816         (match_operator:SI 1 "shiftable_operator"
8817          [(match_operand:SI 2 "memory_operand" "m")
8818           (match_operand:SI 3 "memory_operand" "m")]))
8819    (clobber (match_scratch:SI 4 "=r"))]
8820   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8821   "*
8822   {
8823     rtx ldm[3];
8824     rtx arith[4];
8825     int val1 = 0, val2 = 0;
8826
8827     if (REGNO (operands[0]) > REGNO (operands[4]))
8828       {
8829         ldm[1] = operands[4];
8830         ldm[2] = operands[0];
8831       }
8832     else
8833       {
8834         ldm[1] = operands[0];
8835         ldm[2] = operands[4];
8836       }
8837     if (GET_CODE (XEXP (operands[2], 0)) != REG)
8838       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8839     if (GET_CODE (XEXP (operands[3], 0)) != REG)
8840       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8841     arith[0] = operands[0];
8842     arith[3] = operands[1];
8843     if (val1 < val2)
8844       {
8845         arith[1] = ldm[1];
8846         arith[2] = ldm[2];
8847       }
8848     else
8849       {
8850         arith[1] = ldm[2];
8851         arith[2] = ldm[1];
8852       }
8853    if (val1 && val2)
8854       {
8855         rtx ops[3];
8856         ldm[0] = ops[0] = operands[4];
8857         ops[1] = XEXP (XEXP (operands[2], 0), 0);
8858         ops[2] = XEXP (XEXP (operands[2], 0), 1);
8859         output_add_immediate (ops);
8860         if (val1 < val2)
8861           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8862         else
8863           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8864       }
8865     else if (val1)
8866       {
8867         ldm[0] = XEXP (operands[3], 0);
8868         if (val1 < val2)
8869           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8870         else
8871           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8872       }
8873     else
8874       {
8875         ldm[0] = XEXP (operands[2], 0);
8876         if (val1 < val2)
8877           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8878         else
8879           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8880       }
8881     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8882     return \"\";
8883   }"
8884   [(set_attr "length" "12")
8885    (set_attr "predicable" "yes")
8886    (set_attr "type" "load")]
8887 )
8888
8889 ;; the arm can support extended pre-inc instructions
8890
8891 ;; In all these cases, we use operands 0 and 1 for the register being
8892 ;; incremented because those are the operands that local-alloc will
8893 ;; tie and these are the pair most likely to be tieable (and the ones
8894 ;; that will benefit the most).
8895
8896 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8897 ;; elimination will cause too many headaches.
8898
8899 (define_insn "*strqi_preinc"
8900   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8901                          (match_operand:SI 2 "index_operand" "rJ")))
8902         (match_operand:QI 3 "s_register_operand" "r"))
8903    (set (match_operand:SI 0 "s_register_operand" "=r")
8904         (plus:SI (match_dup 1) (match_dup 2)))]
8905   "TARGET_ARM
8906    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8907    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8908    && (GET_CODE (operands[2]) != REG
8909        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8910   "str%?b\\t%3, [%0, %2]!"
8911   [(set_attr "type" "store1")
8912    (set_attr "predicable" "yes")]
8913 )
8914
8915 (define_insn "*strqi_predec"
8916   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8917                           (match_operand:SI 2 "s_register_operand" "r")))
8918         (match_operand:QI 3 "s_register_operand" "r"))
8919    (set (match_operand:SI 0 "s_register_operand" "=r")
8920         (minus:SI (match_dup 1) (match_dup 2)))]
8921   "TARGET_ARM
8922    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8923    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8924    && (GET_CODE (operands[2]) != REG
8925        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8926   "str%?b\\t%3, [%0, -%2]!"
8927   [(set_attr "type" "store1")
8928    (set_attr "predicable" "yes")]
8929 )
8930
8931 (define_insn "*loadqi_preinc"
8932   [(set (match_operand:QI 3 "s_register_operand" "=r")
8933         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8934                          (match_operand:SI 2 "index_operand" "rJ"))))
8935    (set (match_operand:SI 0 "s_register_operand" "=r")
8936         (plus:SI (match_dup 1) (match_dup 2)))]
8937   "TARGET_ARM
8938    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8939    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8940    && (GET_CODE (operands[2]) != REG
8941        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8942   "ldr%?b\\t%3, [%0, %2]!"
8943   [(set_attr "type" "load")
8944    (set_attr "predicable" "yes")]
8945 )
8946
8947 (define_insn "*loadqi_predec"
8948   [(set (match_operand:QI 3 "s_register_operand" "=r")
8949         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8950                           (match_operand:SI 2 "s_register_operand" "r"))))
8951    (set (match_operand:SI 0 "s_register_operand" "=r")
8952         (minus:SI (match_dup 1) (match_dup 2)))]
8953   "TARGET_ARM
8954    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8955    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8956    && (GET_CODE (operands[2]) != REG
8957        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8958   "ldr%?b\\t%3, [%0, -%2]!"
8959   [(set_attr "type" "load")
8960    (set_attr "predicable" "yes")]
8961 )
8962
8963 (define_insn "*loadqisi_preinc"
8964   [(set (match_operand:SI 3 "s_register_operand" "=r")
8965         (zero_extend:SI
8966          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8967                           (match_operand:SI 2 "index_operand" "rJ")))))
8968    (set (match_operand:SI 0 "s_register_operand" "=r")
8969         (plus:SI (match_dup 1) (match_dup 2)))]
8970   "TARGET_ARM
8971    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8972    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8973    && (GET_CODE (operands[2]) != REG
8974        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8975   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8976   [(set_attr "type" "load")
8977    (set_attr "predicable" "yes")]
8978 )
8979
8980 (define_insn "*loadqisi_predec"
8981   [(set (match_operand:SI 3 "s_register_operand" "=r")
8982         (zero_extend:SI
8983          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8984                            (match_operand:SI 2 "s_register_operand" "r")))))
8985    (set (match_operand:SI 0 "s_register_operand" "=r")
8986         (minus:SI (match_dup 1) (match_dup 2)))]
8987   "TARGET_ARM
8988    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8989    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8990    && (GET_CODE (operands[2]) != REG
8991        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8992   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8993   [(set_attr "type" "load")
8994    (set_attr "predicable" "yes")]
8995 )
8996
8997 (define_insn "*strsi_preinc"
8998   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8999                          (match_operand:SI 2 "index_operand" "rJ")))
9000         (match_operand:SI 3 "s_register_operand" "r"))
9001    (set (match_operand:SI 0 "s_register_operand" "=r")
9002         (plus:SI (match_dup 1) (match_dup 2)))]
9003   "TARGET_ARM
9004    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9005    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9006    && (GET_CODE (operands[2]) != REG
9007        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9008   "str%?\\t%3, [%0, %2]!"
9009   [(set_attr "type" "store1")
9010    (set_attr "predicable" "yes")]
9011 )
9012
9013 (define_insn "*strsi_predec"
9014   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9015                           (match_operand:SI 2 "s_register_operand" "r")))
9016         (match_operand:SI 3 "s_register_operand" "r"))
9017    (set (match_operand:SI 0 "s_register_operand" "=r")
9018         (minus:SI (match_dup 1) (match_dup 2)))]
9019   "TARGET_ARM
9020    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9021    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9022    && (GET_CODE (operands[2]) != REG
9023        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9024   "str%?\\t%3, [%0, -%2]!"
9025   [(set_attr "type" "store1")
9026    (set_attr "predicable" "yes")]
9027 )
9028
9029 (define_insn "*loadsi_preinc"
9030   [(set (match_operand:SI 3 "s_register_operand" "=r")
9031         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9032                          (match_operand:SI 2 "index_operand" "rJ"))))
9033    (set (match_operand:SI 0 "s_register_operand" "=r")
9034         (plus:SI (match_dup 1) (match_dup 2)))]
9035   "TARGET_ARM
9036    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9037    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9038    && (GET_CODE (operands[2]) != REG
9039        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9040   "ldr%?\\t%3, [%0, %2]!"
9041   [(set_attr "type" "load")
9042    (set_attr "predicable" "yes")]
9043 )
9044
9045 (define_insn "*loadsi_predec"
9046   [(set (match_operand:SI 3 "s_register_operand" "=r")
9047         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9048                           (match_operand:SI 2 "s_register_operand" "r"))))
9049    (set (match_operand:SI 0 "s_register_operand" "=r")
9050         (minus:SI (match_dup 1) (match_dup 2)))]
9051   "TARGET_ARM
9052    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9053    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9054    && (GET_CODE (operands[2]) != REG
9055        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9056   "ldr%?\\t%3, [%0, -%2]!"
9057   [(set_attr "type" "load")
9058    (set_attr "predicable" "yes")]
9059 )
9060
9061 (define_insn "*loadhi_preinc"
9062   [(set (match_operand:HI 3 "s_register_operand" "=r")
9063         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9064                          (match_operand:SI 2 "index_operand" "rJ"))))
9065    (set (match_operand:SI 0 "s_register_operand" "=r")
9066         (plus:SI (match_dup 1) (match_dup 2)))]
9067   "TARGET_ARM
9068    && !BYTES_BIG_ENDIAN
9069    && !TARGET_MMU_TRAPS
9070    && !arm_arch4
9071    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9072    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9073    && (GET_CODE (operands[2]) != REG
9074        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9075   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
9076   [(set_attr "type" "load")
9077    (set_attr "predicable" "yes")]
9078 )
9079
9080 (define_insn "*loadhi_predec"
9081   [(set (match_operand:HI 3 "s_register_operand" "=r")
9082         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9083                           (match_operand:SI 2 "s_register_operand" "r"))))
9084    (set (match_operand:SI 0 "s_register_operand" "=r")
9085         (minus:SI (match_dup 1) (match_dup 2)))]
9086   "TARGET_ARM
9087    && !BYTES_BIG_ENDIAN
9088    && !TARGET_MMU_TRAPS
9089    && !arm_arch4
9090    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9091    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9092    && (GET_CODE (operands[2]) != REG
9093        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9094   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
9095   [(set_attr "type" "load")
9096    (set_attr "predicable" "yes")]
9097 )
9098
9099 (define_insn "*strqi_shiftpreinc"
9100   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9101                           [(match_operand:SI 3 "s_register_operand" "r")
9102                            (match_operand:SI 4 "const_shift_operand" "n")])
9103                          (match_operand:SI 1 "s_register_operand" "0")))
9104         (match_operand:QI 5 "s_register_operand" "r"))
9105    (set (match_operand:SI 0 "s_register_operand" "=r")
9106         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9107                  (match_dup 1)))]
9108   "TARGET_ARM
9109    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9110    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9111    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9112   "str%?b\\t%5, [%0, %3%S2]!"
9113   [(set_attr "type" "store1")
9114    (set_attr "predicable" "yes")]
9115 )
9116
9117 (define_insn "*strqi_shiftpredec"
9118   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9119                           (match_operator:SI 2 "shift_operator"
9120                            [(match_operand:SI 3 "s_register_operand" "r")
9121                             (match_operand:SI 4 "const_shift_operand" "n")])))
9122         (match_operand:QI 5 "s_register_operand" "r"))
9123    (set (match_operand:SI 0 "s_register_operand" "=r")
9124         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9125                                                  (match_dup 4)])))]
9126   "TARGET_ARM
9127    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9128    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9129    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9130   "str%?b\\t%5, [%0, -%3%S2]!"
9131   [(set_attr "type" "store1")
9132    (set_attr "predicable" "yes")]
9133 )
9134
9135 (define_insn "*loadqi_shiftpreinc"
9136   [(set (match_operand:QI 5 "s_register_operand" "=r")
9137         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9138                           [(match_operand:SI 3 "s_register_operand" "r")
9139                            (match_operand:SI 4 "const_shift_operand" "n")])
9140                          (match_operand:SI 1 "s_register_operand" "0"))))
9141    (set (match_operand:SI 0 "s_register_operand" "=r")
9142         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9143                  (match_dup 1)))]
9144   "TARGET_ARM
9145    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9146    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9147    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9148   "ldr%?b\\t%5, [%0, %3%S2]!"
9149   [(set_attr "type" "load")
9150    (set_attr "predicable" "yes")]
9151 )
9152
9153 (define_insn "*loadqi_shiftpredec"
9154   [(set (match_operand:QI 5 "s_register_operand" "=r")
9155         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9156                           (match_operator:SI 2 "shift_operator"
9157                            [(match_operand:SI 3 "s_register_operand" "r")
9158                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9159    (set (match_operand:SI 0 "s_register_operand" "=r")
9160         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9161                                                  (match_dup 4)])))]
9162   "TARGET_ARM
9163    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9164    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9165    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9166   "ldr%?b\\t%5, [%0, -%3%S2]!"
9167   [(set_attr "type" "load")
9168    (set_attr "predicable" "yes")]
9169 )
9170
9171 (define_insn "*strsi_shiftpreinc"
9172   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9173                           [(match_operand:SI 3 "s_register_operand" "r")
9174                            (match_operand:SI 4 "const_shift_operand" "n")])
9175                          (match_operand:SI 1 "s_register_operand" "0")))
9176         (match_operand:SI 5 "s_register_operand" "r"))
9177    (set (match_operand:SI 0 "s_register_operand" "=r")
9178         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9179                  (match_dup 1)))]
9180   "TARGET_ARM
9181    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9182    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9183    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9184   "str%?\\t%5, [%0, %3%S2]!"
9185   [(set_attr "type" "store1")
9186    (set_attr "predicable" "yes")]
9187 )
9188
9189 (define_insn "*strsi_shiftpredec"
9190   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9191                           (match_operator:SI 2 "shift_operator"
9192                            [(match_operand:SI 3 "s_register_operand" "r")
9193                             (match_operand:SI 4 "const_shift_operand" "n")])))
9194         (match_operand:SI 5 "s_register_operand" "r"))
9195    (set (match_operand:SI 0 "s_register_operand" "=r")
9196         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9197                                                  (match_dup 4)])))]
9198   "TARGET_ARM
9199    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9200    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9201    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9202   "str%?\\t%5, [%0, -%3%S2]!"
9203   [(set_attr "type" "store1")
9204    (set_attr "predicable" "yes")]
9205 )
9206
9207 (define_insn "*loadsi_shiftpreinc"
9208   [(set (match_operand:SI 5 "s_register_operand" "=r")
9209         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9210                           [(match_operand:SI 3 "s_register_operand" "r")
9211                            (match_operand:SI 4 "const_shift_operand" "n")])
9212                          (match_operand:SI 1 "s_register_operand" "0"))))
9213    (set (match_operand:SI 0 "s_register_operand" "=r")
9214         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9215                  (match_dup 1)))]
9216   "TARGET_ARM
9217    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9218    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9219    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9220   "ldr%?\\t%5, [%0, %3%S2]!"
9221   [(set_attr "type" "load")
9222    (set_attr "predicable" "yes")]
9223 )
9224
9225 (define_insn "*loadsi_shiftpredec"
9226   [(set (match_operand:SI 5 "s_register_operand" "=r")
9227         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9228                           (match_operator:SI 2 "shift_operator"
9229                            [(match_operand:SI 3 "s_register_operand" "r")
9230                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9231    (set (match_operand:SI 0 "s_register_operand" "=r")
9232         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9233                                                  (match_dup 4)])))]
9234   "TARGET_ARM
9235    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9236    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9237    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9238   "ldr%?\\t%5, [%0, -%3%S2]!"
9239   [(set_attr "type" "load")
9240    (set_attr "predicable" "yes")])
9241
9242 (define_insn "*loadhi_shiftpreinc"
9243   [(set (match_operand:HI 5 "s_register_operand" "=r")
9244         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
9245                           [(match_operand:SI 3 "s_register_operand" "r")
9246                            (match_operand:SI 4 "const_shift_operand" "n")])
9247                          (match_operand:SI 1 "s_register_operand" "0"))))
9248    (set (match_operand:SI 0 "s_register_operand" "=r")
9249         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9250                  (match_dup 1)))]
9251   "TARGET_ARM
9252    && !BYTES_BIG_ENDIAN
9253    && !TARGET_MMU_TRAPS
9254    && !arm_arch4
9255    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9256    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9257    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9258   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
9259   [(set_attr "type" "load")
9260    (set_attr "predicable" "yes")]
9261 )
9262
9263 (define_insn "*loadhi_shiftpredec"
9264   [(set (match_operand:HI 5 "s_register_operand" "=r")
9265         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9266                           (match_operator:SI 2 "shift_operator"
9267                            [(match_operand:SI 3 "s_register_operand" "r")
9268                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9269    (set (match_operand:SI 0 "s_register_operand" "=r")
9270         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9271                                                  (match_dup 4)])))]
9272   "TARGET_ARM
9273    && !BYTES_BIG_ENDIAN
9274    && !TARGET_MMU_TRAPS
9275    && !arm_arch4
9276    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9277    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9278    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9279   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
9280   [(set_attr "type" "load")
9281    (set_attr "predicable" "yes")]
9282 )
9283
9284 ; It can also support extended post-inc expressions, but combine doesn't
9285 ; try these....
9286 ; It doesn't seem worth adding peepholes for anything but the most common
9287 ; cases since, unlike combine, the increment must immediately follow the load
9288 ; for this pattern to match.
9289 ; We must watch to see that the source/destination register isn't also the
9290 ; same as the base address register, and that if the index is a register,
9291 ; that it is not the same as the base address register.  In such cases the
9292 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9293 ; we cannot use it.
9294
9295 (define_peephole
9296   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9297         (match_operand:QI 2 "s_register_operand" "r"))
9298    (set (match_dup 0)
9299         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9300   "TARGET_ARM
9301    && (REGNO (operands[2]) != REGNO (operands[0]))
9302    && (GET_CODE (operands[1]) != REG
9303        || (REGNO (operands[1]) != REGNO (operands[0])))"
9304   "str%?b\\t%2, [%0], %1"
9305 )
9306
9307 (define_peephole
9308   [(set (match_operand:QI 0 "s_register_operand" "=r")
9309         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9310    (set (match_dup 1)
9311         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9312   "TARGET_ARM
9313    && REGNO (operands[0]) != REGNO(operands[1])
9314    && (GET_CODE (operands[2]) != REG
9315        || REGNO(operands[0]) != REGNO (operands[2]))"
9316   "ldr%?b\\t%0, [%1], %2"
9317 )
9318
9319 (define_peephole
9320   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9321         (match_operand:SI 2 "s_register_operand" "r"))
9322    (set (match_dup 0)
9323         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9324   "TARGET_ARM
9325    && (REGNO (operands[2]) != REGNO (operands[0]))
9326    && (GET_CODE (operands[1]) != REG
9327        || (REGNO (operands[1]) != REGNO (operands[0])))"
9328   "str%?\\t%2, [%0], %1"
9329 )
9330
9331 (define_peephole
9332   [(set (match_operand:HI 0 "s_register_operand" "=r")
9333         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
9334    (set (match_dup 1)
9335         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9336   "TARGET_ARM
9337    && !BYTES_BIG_ENDIAN
9338    && !TARGET_MMU_TRAPS
9339    && !arm_arch4
9340    && REGNO (operands[0]) != REGNO(operands[1])
9341    && (GET_CODE (operands[2]) != REG
9342        || REGNO(operands[0]) != REGNO (operands[2]))"
9343   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
9344 )
9345
9346 (define_peephole
9347   [(set (match_operand:SI 0 "s_register_operand" "=r")
9348         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9349    (set (match_dup 1)
9350         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9351   "TARGET_ARM
9352    && REGNO (operands[0]) != REGNO(operands[1])
9353    && (GET_CODE (operands[2]) != REG
9354        || REGNO(operands[0]) != REGNO (operands[2]))"
9355   "ldr%?\\t%0, [%1], %2"
9356 )
9357
9358 (define_peephole
9359   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9360                          (match_operand:SI 1 "index_operand" "rJ")))
9361         (match_operand:QI 2 "s_register_operand" "r"))
9362    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9363   "TARGET_ARM
9364    && (REGNO (operands[2]) != REGNO (operands[0]))
9365    && (GET_CODE (operands[1]) != REG
9366        || (REGNO (operands[1]) != REGNO (operands[0])))"
9367   "str%?b\\t%2, [%0, %1]!"
9368 )
9369
9370 (define_peephole
9371   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9372                           [(match_operand:SI 0 "s_register_operand" "r")
9373                            (match_operand:SI 1 "const_int_operand" "n")])
9374                          (match_operand:SI 2 "s_register_operand" "+r")))
9375         (match_operand:QI 3 "s_register_operand" "r"))
9376    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9377                                (match_dup 2)))]
9378   "TARGET_ARM
9379    && (REGNO (operands[3]) != REGNO (operands[2]))
9380    && (REGNO (operands[0]) != REGNO (operands[2]))"
9381   "str%?b\\t%3, [%2, %0%S4]!"
9382 )
9383
9384 ; This pattern is never tried by combine, so do it as a peephole
9385
9386 (define_peephole2
9387   [(set (match_operand:SI 0 "s_register_operand" "")
9388         (match_operand:SI 1 "s_register_operand" ""))
9389    (set (reg:CC CC_REGNUM)
9390         (compare:CC (match_dup 1) (const_int 0)))]
9391   "TARGET_ARM
9392    && (!TARGET_CIRRUS
9393        || (!cirrus_fp_register (operands[0], SImode)
9394            && !cirrus_fp_register (operands[1], SImode)))
9395   "
9396   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9397               (set (match_dup 0) (match_dup 1))])]
9398   ""
9399 )
9400
9401 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9402 ; reversed, check that the memory references aren't volatile.
9403
9404 (define_peephole
9405   [(set (match_operand:SI 0 "s_register_operand" "=r")
9406         (match_operand:SI 4 "memory_operand" "m"))
9407    (set (match_operand:SI 1 "s_register_operand" "=r")
9408         (match_operand:SI 5 "memory_operand" "m"))
9409    (set (match_operand:SI 2 "s_register_operand" "=r")
9410         (match_operand:SI 6 "memory_operand" "m"))
9411    (set (match_operand:SI 3 "s_register_operand" "=r")
9412         (match_operand:SI 7 "memory_operand" "m"))]
9413   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9414   "*
9415   return emit_ldm_seq (operands, 4);
9416   "
9417 )
9418
9419 (define_peephole
9420   [(set (match_operand:SI 0 "s_register_operand" "=r")
9421         (match_operand:SI 3 "memory_operand" "m"))
9422    (set (match_operand:SI 1 "s_register_operand" "=r")
9423         (match_operand:SI 4 "memory_operand" "m"))
9424    (set (match_operand:SI 2 "s_register_operand" "=r")
9425         (match_operand:SI 5 "memory_operand" "m"))]
9426   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9427   "*
9428   return emit_ldm_seq (operands, 3);
9429   "
9430 )
9431
9432 (define_peephole
9433   [(set (match_operand:SI 0 "s_register_operand" "=r")
9434         (match_operand:SI 2 "memory_operand" "m"))
9435    (set (match_operand:SI 1 "s_register_operand" "=r")
9436         (match_operand:SI 3 "memory_operand" "m"))]
9437   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9438   "*
9439   return emit_ldm_seq (operands, 2);
9440   "
9441 )
9442
9443 (define_peephole
9444   [(set (match_operand:SI 4 "memory_operand" "=m")
9445         (match_operand:SI 0 "s_register_operand" "r"))
9446    (set (match_operand:SI 5 "memory_operand" "=m")
9447         (match_operand:SI 1 "s_register_operand" "r"))
9448    (set (match_operand:SI 6 "memory_operand" "=m")
9449         (match_operand:SI 2 "s_register_operand" "r"))
9450    (set (match_operand:SI 7 "memory_operand" "=m")
9451         (match_operand:SI 3 "s_register_operand" "r"))]
9452   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9453   "*
9454   return emit_stm_seq (operands, 4);
9455   "
9456 )
9457
9458 (define_peephole
9459   [(set (match_operand:SI 3 "memory_operand" "=m")
9460         (match_operand:SI 0 "s_register_operand" "r"))
9461    (set (match_operand:SI 4 "memory_operand" "=m")
9462         (match_operand:SI 1 "s_register_operand" "r"))
9463    (set (match_operand:SI 5 "memory_operand" "=m")
9464         (match_operand:SI 2 "s_register_operand" "r"))]
9465   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9466   "*
9467   return emit_stm_seq (operands, 3);
9468   "
9469 )
9470
9471 (define_peephole
9472   [(set (match_operand:SI 2 "memory_operand" "=m")
9473         (match_operand:SI 0 "s_register_operand" "r"))
9474    (set (match_operand:SI 3 "memory_operand" "=m")
9475         (match_operand:SI 1 "s_register_operand" "r"))]
9476   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9477   "*
9478   return emit_stm_seq (operands, 2);
9479   "
9480 )
9481
9482 (define_split
9483   [(set (match_operand:SI 0 "s_register_operand" "")
9484         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9485                        (const_int 0))
9486                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9487                          [(match_operand:SI 3 "s_register_operand" "")
9488                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9489    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9490   "TARGET_ARM"
9491   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9492    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9493                               (match_dup 5)))]
9494   ""
9495 )
9496
9497 ;; This split can be used because CC_Z mode implies that the following
9498 ;; branch will be an equality, or an unsigned inequality, so the sign
9499 ;; extension is not needed.
9500
9501 (define_split
9502   [(set (reg:CC_Z CC_REGNUM)
9503         (compare:CC_Z
9504          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9505                     (const_int 24))
9506          (match_operand 1 "const_int_operand" "")))
9507    (clobber (match_scratch:SI 2 ""))]
9508   "TARGET_ARM
9509    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9510        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9511   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9512    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9513   "
9514   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9515   "
9516 )
9517
9518 (define_expand "prologue"
9519   [(clobber (const_int 0))]
9520   "TARGET_EITHER"
9521   "if (TARGET_ARM)
9522      arm_expand_prologue ();
9523    else
9524      thumb_expand_prologue ();
9525   DONE;
9526   "
9527 )
9528
9529 (define_expand "epilogue"
9530   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9531   "TARGET_EITHER"
9532   "
9533   if (TARGET_THUMB)
9534     thumb_expand_epilogue ();
9535   else if (USE_RETURN_INSN (FALSE))
9536     {
9537       emit_jump_insn (gen_return ());
9538       DONE;
9539     }
9540   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9541         gen_rtvec (1,
9542                 gen_rtx_RETURN (VOIDmode)),
9543         VUNSPEC_EPILOGUE));
9544   DONE;
9545   "
9546 )
9547
9548 ;; Note - although unspec_volatile's USE all hard registers,
9549 ;; USEs are ignored after relaod has completed.  Thus we need
9550 ;; to add an unspec of the link register to ensure that flow
9551 ;; does not think that it is unused by the sibcall branch that
9552 ;; will replace the standard function epilogue.
9553 (define_insn "sibcall_epilogue"
9554   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9555               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9556   "TARGET_ARM"
9557   "*
9558   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9559     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9560   return arm_output_epilogue (next_nonnote_insn (insn));
9561   "
9562 ;; Length is absolute worst case
9563   [(set_attr "length" "44")
9564    (set_attr "type" "block")
9565    ;; We don't clobber the conditions, but the potential length of this
9566    ;; operation is sufficient to make conditionalizing the sequence 
9567    ;; unlikely to be profitable.
9568    (set_attr "conds" "clob")]
9569 )
9570
9571 (define_insn "*epilogue_insns"
9572   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9573   "TARGET_EITHER"
9574   "*
9575   if (TARGET_ARM)
9576     return arm_output_epilogue (NULL);
9577   else /* TARGET_THUMB */
9578     return thumb_unexpanded_epilogue ();
9579   "
9580   ; Length is absolute worst case
9581   [(set_attr "length" "44")
9582    (set_attr "type" "block")
9583    ;; We don't clobber the conditions, but the potential length of this
9584    ;; operation is sufficient to make conditionalizing the sequence 
9585    ;; unlikely to be profitable.
9586    (set_attr "conds" "clob")]
9587 )
9588
9589 (define_expand "eh_epilogue"
9590   [(use (match_operand:SI 0 "register_operand" ""))
9591    (use (match_operand:SI 1 "register_operand" ""))
9592    (use (match_operand:SI 2 "register_operand" ""))]
9593   "TARGET_EITHER"
9594   "
9595   {
9596     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9597     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9598       {
9599         rtx ra = gen_rtx_REG (Pmode, 2);
9600
9601         emit_move_insn (ra, operands[2]);
9602         operands[2] = ra;
9603       }
9604     /* This is a hack -- we may have crystalized the function type too
9605        early.  */
9606     cfun->machine->func_type = 0;
9607   }"
9608 )
9609
9610 ;; This split is only used during output to reduce the number of patterns
9611 ;; that need assembler instructions adding to them.  We allowed the setting
9612 ;; of the conditions to be implicit during rtl generation so that
9613 ;; the conditional compare patterns would work.  However this conflicts to
9614 ;; some extent with the conditional data operations, so we have to split them
9615 ;; up again here.
9616
9617 (define_split
9618   [(set (match_operand:SI 0 "s_register_operand" "")
9619         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9620                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9621                          (match_dup 0)
9622                          (match_operand 4 "" "")))
9623    (clobber (reg:CC CC_REGNUM))]
9624   "TARGET_ARM && reload_completed"
9625   [(set (match_dup 5) (match_dup 6))
9626    (cond_exec (match_dup 7)
9627               (set (match_dup 0) (match_dup 4)))]
9628   "
9629   {
9630     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9631                                              operands[2], operands[3]);
9632     enum rtx_code rc = GET_CODE (operands[1]);
9633
9634     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9635     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9636     if (mode == CCFPmode || mode == CCFPEmode)
9637       rc = reverse_condition_maybe_unordered (rc);
9638     else
9639       rc = reverse_condition (rc);
9640
9641     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9642   }"
9643 )
9644
9645 (define_split
9646   [(set (match_operand:SI 0 "s_register_operand" "")
9647         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9648                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9649                          (match_operand 4 "" "")
9650                          (match_dup 0)))
9651    (clobber (reg:CC CC_REGNUM))]
9652   "TARGET_ARM && reload_completed"
9653   [(set (match_dup 5) (match_dup 6))
9654    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9655               (set (match_dup 0) (match_dup 4)))]
9656   "
9657   {
9658     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9659                                              operands[2], operands[3]);
9660
9661     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9662     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9663   }"
9664 )
9665
9666 (define_split
9667   [(set (match_operand:SI 0 "s_register_operand" "")
9668         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9669                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9670                          (match_operand 4 "" "")
9671                          (match_operand 5 "" "")))
9672    (clobber (reg:CC CC_REGNUM))]
9673   "TARGET_ARM && reload_completed"
9674   [(set (match_dup 6) (match_dup 7))
9675    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9676               (set (match_dup 0) (match_dup 4)))
9677    (cond_exec (match_dup 8)
9678               (set (match_dup 0) (match_dup 5)))]
9679   "
9680   {
9681     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9682                                              operands[2], operands[3]);
9683     enum rtx_code rc = GET_CODE (operands[1]);
9684
9685     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9686     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9687     if (mode == CCFPmode || mode == CCFPEmode)
9688       rc = reverse_condition_maybe_unordered (rc);
9689     else
9690       rc = reverse_condition (rc);
9691
9692     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9693   }"
9694 )
9695
9696 (define_split
9697   [(set (match_operand:SI 0 "s_register_operand" "")
9698         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9699                           [(match_operand:SI 2 "s_register_operand" "")
9700                            (match_operand:SI 3 "arm_add_operand" "")])
9701                          (match_operand:SI 4 "arm_rhs_operand" "")
9702                          (not:SI
9703                           (match_operand:SI 5 "s_register_operand" ""))))
9704    (clobber (reg:CC CC_REGNUM))]
9705   "TARGET_ARM && reload_completed"
9706   [(set (match_dup 6) (match_dup 7))
9707    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9708               (set (match_dup 0) (match_dup 4)))
9709    (cond_exec (match_dup 8)
9710               (set (match_dup 0) (not:SI (match_dup 5))))]
9711   "
9712   {
9713     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9714                                              operands[2], operands[3]);
9715     enum rtx_code rc = GET_CODE (operands[1]);
9716
9717     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9718     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
9719     if (mode == CCFPmode || mode == CCFPEmode)
9720       rc = reverse_condition_maybe_unordered (rc);
9721     else
9722       rc = reverse_condition (rc);
9723
9724     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9725   }"
9726 )
9727
9728 (define_insn "*cond_move_not"
9729   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9730         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9731                           [(match_operand 3 "cc_register" "") (const_int 0)])
9732                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9733                          (not:SI
9734                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9735   "TARGET_ARM"
9736   "@
9737    mvn%D4\\t%0, %2
9738    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9739   [(set_attr "conds" "use")
9740    (set_attr "length" "4,8")]
9741 )
9742
9743 ;; The next two patterns occur when an AND operation is followed by a
9744 ;; scc insn sequence 
9745
9746 (define_insn "*sign_extract_onebit"
9747   [(set (match_operand:SI 0 "s_register_operand" "=r")
9748         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9749                          (const_int 1)
9750                          (match_operand:SI 2 "const_int_operand" "n")))
9751     (clobber (reg:CC CC_REGNUM))]
9752   "TARGET_ARM"
9753   "*
9754     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9755     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9756     return \"mvnne\\t%0, #0\";
9757   "
9758   [(set_attr "conds" "clob")
9759    (set_attr "length" "8")]
9760 )
9761
9762 (define_insn "*not_signextract_onebit"
9763   [(set (match_operand:SI 0 "s_register_operand" "=r")
9764         (not:SI
9765          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9766                           (const_int 1)
9767                           (match_operand:SI 2 "const_int_operand" "n"))))
9768    (clobber (reg:CC CC_REGNUM))]
9769   "TARGET_ARM"
9770   "*
9771     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9772     output_asm_insn (\"tst\\t%1, %2\", operands);
9773     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9774     return \"movne\\t%0, #0\";
9775   "
9776   [(set_attr "conds" "clob")
9777    (set_attr "length" "12")]
9778 )
9779
9780 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9781 ;; expressions.  For simplicity, the first register is also in the unspec
9782 ;; part.
9783 (define_insn "*push_multi"
9784   [(match_parallel 2 "multi_register_push"
9785     [(set (match_operand:BLK 0 "memory_operand" "=m")
9786           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9787                       UNSPEC_PUSH_MULT))])]
9788   "TARGET_ARM"
9789   "*
9790   {
9791     int num_saves = XVECLEN (operands[2], 0);
9792      
9793     /* For the StrongARM at least it is faster to
9794        use STR to store only a single register.  */
9795     if (num_saves == 1)
9796       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9797     else
9798       {
9799         int i;
9800         char pattern[100];
9801
9802         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9803
9804         for (i = 1; i < num_saves; i++)
9805           {
9806             strcat (pattern, \", %|\");
9807             strcat (pattern,
9808                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9809           }
9810
9811         strcat (pattern, \"}\");
9812         output_asm_insn (pattern, operands);
9813       }
9814
9815     return \"\";
9816   }"
9817   [(set_attr "type" "store4")]
9818 )
9819
9820 (define_insn "stack_tie"
9821   [(set (mem:BLK (scratch))
9822         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9823                      (match_operand:SI 1 "s_register_operand" "r")]
9824                     UNSPEC_PRLG_STK))]
9825   ""
9826   ""
9827   [(set_attr "length" "0")]
9828 )
9829
9830 ;; Similarly for the floating point registers
9831 (define_insn "*push_fp_multi"
9832   [(match_parallel 2 "multi_register_push"
9833     [(set (match_operand:BLK 0 "memory_operand" "=m")
9834           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9835                       UNSPEC_PUSH_MULT))])]
9836   "TARGET_ARM"
9837   "*
9838   {
9839     char pattern[100];
9840
9841     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9842     output_asm_insn (pattern, operands);
9843     return \"\";
9844   }"
9845   [(set_attr "type" "f_store")]
9846 )
9847
9848 ;; Special patterns for dealing with the constant pool
9849
9850 (define_insn "align_4"
9851   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9852   "TARGET_EITHER"
9853   "*
9854   assemble_align (32);
9855   return \"\";
9856   "
9857 )
9858
9859 (define_insn "align_8"
9860   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9861   "TARGET_REALLY_IWMMXT"
9862   "*
9863   assemble_align (64);
9864   return \"\";
9865   "
9866 )
9867
9868 (define_insn "consttable_end"
9869   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9870   "TARGET_EITHER"
9871   "*
9872   making_const_table = FALSE;
9873   return \"\";
9874   "
9875 )
9876
9877 (define_insn "consttable_1"
9878   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9879   "TARGET_THUMB"
9880   "*
9881   making_const_table = TRUE;
9882   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9883   assemble_zeros (3);
9884   return \"\";
9885   "
9886   [(set_attr "length" "4")]
9887 )
9888
9889 (define_insn "consttable_2"
9890   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9891   "TARGET_THUMB"
9892   "*
9893   making_const_table = TRUE;
9894   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9895   assemble_zeros (2);
9896   return \"\";
9897   "
9898   [(set_attr "length" "4")]
9899 )
9900
9901 (define_insn "consttable_4"
9902   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9903   "TARGET_EITHER"
9904   "*
9905   {
9906     making_const_table = TRUE;
9907     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9908       {
9909       case MODE_FLOAT:
9910       {
9911         REAL_VALUE_TYPE r;
9912         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9913         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9914         break;
9915       }
9916       default:
9917         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9918         break;
9919       }
9920     return \"\";
9921   }"
9922   [(set_attr "length" "4")]
9923 )
9924
9925 (define_insn "consttable_8"
9926   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9927   "TARGET_EITHER"
9928   "*
9929   {
9930     making_const_table = TRUE;
9931     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9932       {
9933        case MODE_FLOAT:
9934         {
9935           REAL_VALUE_TYPE r;
9936           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9937           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9938           break;
9939         }
9940       default:
9941         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9942         break;
9943       }
9944     return \"\";
9945   }"
9946   [(set_attr "length" "8")]
9947 )
9948
9949 ;; Miscellaneous Thumb patterns
9950
9951 (define_expand "tablejump"
9952   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9953               (use (label_ref (match_operand 1 "" "")))])]
9954   "TARGET_THUMB"
9955   "
9956   if (flag_pic)
9957     {
9958       /* Hopefully, CSE will eliminate this copy.  */
9959       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9960       rtx reg2 = gen_reg_rtx (SImode);
9961
9962       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9963       operands[0] = reg2;
9964     }
9965   "
9966 )
9967
9968 (define_insn "*thumb_tablejump"
9969   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9970    (use (label_ref (match_operand 1 "" "")))]
9971   "TARGET_THUMB"
9972   "mov\\t%|pc, %0"
9973   [(set_attr "length" "2")]
9974 )
9975
9976 ;; V5 Instructions,
9977
9978 (define_insn "clzsi2"
9979   [(set (match_operand:SI 0 "s_register_operand" "=r")
9980         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
9981   "TARGET_ARM && arm_arch5"
9982   "clz%?\\t%0, %1"
9983   [(set_attr "predicable" "yes")])
9984
9985 (define_expand "ffssi2"
9986   [(set (match_operand:SI 0 "s_register_operand" "")
9987         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9988   "TARGET_ARM && arm_arch5"
9989   "
9990   {
9991     rtx t1, t2, t3;
9992
9993     t1 = gen_reg_rtx (SImode);
9994     t2 = gen_reg_rtx (SImode);
9995     t3 = gen_reg_rtx (SImode);
9996
9997     emit_insn (gen_negsi2 (t1, operands[1]));
9998     emit_insn (gen_andsi3 (t2, operands[1], t1));
9999     emit_insn (gen_clzsi2 (t3, t2));
10000     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10001     DONE;
10002   }"
10003 )
10004
10005 (define_expand "ctzsi2"
10006   [(set (match_operand:SI 0 "s_register_operand" "")
10007         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10008   "TARGET_ARM && arm_arch5"
10009   "
10010   {
10011     rtx t1, t2, t3;
10012
10013     t1 = gen_reg_rtx (SImode);
10014     t2 = gen_reg_rtx (SImode);
10015     t3 = gen_reg_rtx (SImode);
10016
10017     emit_insn (gen_negsi2 (t1, operands[1]));
10018     emit_insn (gen_andsi3 (t2, operands[1], t1));
10019     emit_insn (gen_clzsi2 (t3, t2));
10020     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10021     DONE;
10022   }"
10023 )
10024
10025 ;; V5E instructions.
10026
10027 (define_insn "prefetch"
10028   [(prefetch (match_operand:SI 0 "address_operand" "p")
10029              (match_operand:SI 1 "" "")
10030              (match_operand:SI 2 "" ""))]
10031   "TARGET_ARM && arm_arch5e"
10032   "pld\\t%a0")
10033
10034 ;; General predication pattern
10035
10036 (define_cond_exec
10037   [(match_operator 0 "arm_comparison_operator"
10038     [(match_operand 1 "cc_register" "")
10039      (const_int 0)])]
10040   "TARGET_ARM"
10041   ""
10042 )
10043
10044 (define_insn "prologue_use"
10045   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10046   ""
10047   "%@ %0 needed for prologue"
10048 )
10049
10050 ;; Load the FPA co-processor patterns
10051 (include "fpa.md")
10052 ;; Load the Maverick co-processor patterns
10053 (include "cirrus.md")
10054 ;; Load the Intel Wireless Multimedia Extension patterns
10055 (include "iwmmxt.md")