OSDN Git Service

* arm.c (thumb_legitimate_address_p): Only allow constant pool
[pf3gnuchains/gcc-fork.git] / gcc / config / arm / arm.md
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003 2004  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
7
8 ;; This file is part of GCC.
9
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
14
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18 ;; License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26
27 \f
28 ;;---------------------------------------------------------------------------
29 ;; Constants
30
31 ;; Register numbers
32 (define_constants
33   [(IP_REGNUM       12)         ; Scratch register
34    (SP_REGNUM       13)         ; Stack pointer
35    (LR_REGNUM       14)         ; Return address register
36    (PC_REGNUM       15)         ; Program counter
37    (CC_REGNUM       24)         ; Condition code pseudo register
38    (LAST_ARM_REGNUM 15)
39   ]
40 )
41 ;; 3rd operand to select_dominance_cc_mode
42 (define_constants
43   [(DOM_CC_X_AND_Y  0)
44    (DOM_CC_NX_OR_Y  1)
45    (DOM_CC_X_OR_Y   2)
46   ]
47 )
48
49 ;; UNSPEC Usage:
50 ;; Note: sin and cos are no-longer used.
51
52 (define_constants
53   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
54                         ;   operand 0 is the result,
55                         ;   operand 1 the parameter.
56    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60                         ;   operand 0 is the first register,
61                         ;   subsequent registers are in parallel (use ...)
62                         ;   expressions.
63    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
64                         ;   usage, that is, we will add the pic_register
65                         ;   value to it before trying to dereference it.
66    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
67                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
68                         ;   described by the RTL but must be wrapped to
69                         ;   prevent combine from trying to rip it apart.
70    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
71                         ;   being scheduled before the stack adjustment insn.
72    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73                         ; this unspec is used to prevent the deletion of
74                         ; instructions setting registers for EH handling
75                         ; and stack frame generation.  Operand 0 is the
76                         ; register to "use".
77    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78    (UNSPEC_WSHUFH    8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89    (UNSPEC_WMADDU   19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
90   ]
91 )
92
93 ;; UNSPEC_VOLATILE Usage:
94
95 (define_constants
96   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
97                         ;   insn in the code.
98    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99                         ;   instruction epilogue sequence that isn't expanded
100                         ;   into normal RTL.  Used for both normal and sibcall
101                         ;   epilogues.
102    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
103                         ;   for inlined constants.
104    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
105                         ;   table.
106    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
107                         ;   an 8-bit object.
108    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
109                         ;   a 16-bit object.
110    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
111                         ;   a 32-bit object.
112    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
113                         ;   a 64-bit object.
114    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
115    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
116    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
117    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
118    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
120   ]
121 )
122 \f
123 ;;---------------------------------------------------------------------------
124 ;; Attributes
125
126 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127 ; generating ARM code.  This is used to control the length of some insn
128 ; patterns that share the same RTL in both ARM and Thumb code.
129 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
130
131 ; 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,m,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 )
4519
4520
4521 (define_insn "rotated_loadsi"
4522   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4523         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4524                    (const_int 16)))]
4525   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4526   "*
4527   {
4528     rtx ops[2];
4529
4530     ops[0] = operands[0];
4531     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4532     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4533     return \"\";
4534   }"
4535   [(set_attr "type" "load")
4536    (set_attr "predicable" "yes")]
4537 )
4538
4539 (define_expand "movhi_bytes"
4540   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4541    (set (match_dup 3)
4542         (zero_extend:SI (match_dup 6)))
4543    (set (match_operand:SI 0 "" "")
4544          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4545   "TARGET_ARM"
4546   "
4547   {
4548     rtx mem1, mem2;
4549     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4550
4551     mem1 = gen_rtx_MEM (QImode, addr);
4552     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4553     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4554     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4555     operands[0] = gen_lowpart (SImode, operands[0]);
4556     operands[1] = mem1;
4557     operands[2] = gen_reg_rtx (SImode);
4558     operands[3] = gen_reg_rtx (SImode);
4559     operands[6] = mem2;
4560
4561     if (BYTES_BIG_ENDIAN)
4562       {
4563         operands[4] = operands[2];
4564         operands[5] = operands[3];
4565       }
4566     else
4567       {
4568         operands[4] = operands[3];
4569         operands[5] = operands[2];
4570       }
4571   }"
4572 )
4573
4574 (define_expand "movhi_bigend"
4575   [(set (match_dup 2)
4576         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4577                    (const_int 16)))
4578    (set (match_dup 3)
4579         (ashiftrt:SI (match_dup 2) (const_int 16)))
4580    (set (match_operand:HI 0 "s_register_operand" "")
4581         (match_dup 4))]
4582   "TARGET_ARM"
4583   "
4584   operands[2] = gen_reg_rtx (SImode);
4585   operands[3] = gen_reg_rtx (SImode);
4586   operands[4] = gen_lowpart (HImode, operands[3]);
4587   "
4588 )
4589
4590 ;; Pattern to recognize insn generated default case above
4591 (define_insn "*movhi_insn_arch4"
4592   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4593         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4594   "TARGET_ARM
4595    && arm_arch4
4596    && (GET_CODE (operands[1]) != CONST_INT
4597        || const_ok_for_arm (INTVAL (operands[1]))
4598        || const_ok_for_arm (~INTVAL (operands[1])))"
4599   "@
4600    mov%?\\t%0, %1\\t%@ movhi
4601    mvn%?\\t%0, #%B1\\t%@ movhi
4602    str%?h\\t%1, %0\\t%@ movhi 
4603    ldr%?h\\t%0, %1\\t%@ movhi"
4604   [(set_attr "type" "*,*,store1,load")
4605    (set_attr "predicable" "yes")
4606    (set_attr "pool_range" "*,*,*,256")
4607    (set_attr "neg_pool_range" "*,*,*,244")]
4608 )
4609
4610 (define_insn "*movhi_insn_littleend"
4611   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4612         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4613   "TARGET_ARM
4614    && !arm_arch4
4615    && !BYTES_BIG_ENDIAN
4616    && !TARGET_MMU_TRAPS
4617    && (GET_CODE (operands[1]) != CONST_INT
4618        || const_ok_for_arm (INTVAL (operands[1]))
4619        || const_ok_for_arm (~INTVAL (operands[1])))"
4620   "@
4621    mov%?\\t%0, %1\\t%@ movhi
4622    mvn%?\\t%0, #%B1\\t%@ movhi
4623    ldr%?\\t%0, %1\\t%@ movhi"
4624   [(set_attr "type" "*,*,load")
4625    (set_attr "predicable" "yes")
4626    (set_attr "pool_range" "4096")
4627    (set_attr "neg_pool_range" "4084")]
4628 )
4629
4630 (define_insn "*movhi_insn_bigend"
4631   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4632         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4633   "TARGET_ARM
4634    && !arm_arch4
4635    && BYTES_BIG_ENDIAN
4636    && !TARGET_MMU_TRAPS
4637    && (GET_CODE (operands[1]) != CONST_INT
4638        || const_ok_for_arm (INTVAL (operands[1]))
4639        || const_ok_for_arm (~INTVAL (operands[1])))"
4640   "@
4641    mov%?\\t%0, %1\\t%@ movhi
4642    mvn%?\\t%0, #%B1\\t%@ movhi
4643    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4644   [(set_attr "type" "*,*,load")
4645    (set_attr "predicable" "yes")
4646    (set_attr "length" "4,4,8")
4647    (set_attr "pool_range" "*,*,4092")
4648    (set_attr "neg_pool_range" "*,*,4084")]
4649 )
4650
4651 (define_insn "*loadhi_si_bigend"
4652   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4653         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4654                    (const_int 16)))]
4655   "TARGET_ARM
4656    && BYTES_BIG_ENDIAN
4657    && !TARGET_MMU_TRAPS"
4658   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4659   [(set_attr "type" "load")
4660    (set_attr "predicable" "yes")
4661    (set_attr "pool_range" "4096")
4662    (set_attr "neg_pool_range" "4084")]
4663 )
4664
4665 (define_insn "*movhi_bytes"
4666   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4667         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4668   "TARGET_ARM && TARGET_MMU_TRAPS"
4669   "@
4670    mov%?\\t%0, %1\\t%@ movhi
4671    mvn%?\\t%0, #%B1\\t%@ movhi"
4672   [(set_attr "predicable" "yes")]
4673 )
4674
4675 (define_insn "thumb_movhi_clobber"
4676   [(set (match_operand:HI     0 "memory_operand"   "=m")
4677         (match_operand:HI     1 "register_operand" "l"))
4678    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4679   "TARGET_THUMB"
4680   "*
4681   abort ();"
4682 )
4683         
4684 ;; We use a DImode scratch because we may occasionally need an additional
4685 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4686 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4687 (define_expand "reload_outhi"
4688   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4689               (match_operand:HI 1 "s_register_operand"        "r")
4690               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4691   "TARGET_EITHER"
4692   "if (TARGET_ARM)
4693      arm_reload_out_hi (operands);
4694    else
4695      thumb_reload_out_hi (operands);
4696   DONE;
4697   "
4698 )
4699
4700 (define_expand "reload_inhi"
4701   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4702               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4703               (match_operand:DI 2 "s_register_operand" "=&r")])]
4704   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4705   "
4706   if (TARGET_ARM)
4707     arm_reload_in_hi (operands);
4708   else
4709     thumb_reload_out_hi (operands);
4710   DONE;
4711 ")
4712
4713 (define_expand "movqi"
4714   [(set (match_operand:QI 0 "general_operand" "")
4715         (match_operand:QI 1 "general_operand" ""))]
4716   "TARGET_EITHER"
4717   "
4718   if (TARGET_ARM)
4719     {
4720       /* Everything except mem = const or mem = mem can be done easily */
4721
4722       if (!no_new_pseudos)
4723         {
4724           if (GET_CODE (operands[1]) == CONST_INT)
4725             {
4726               rtx reg = gen_reg_rtx (SImode);
4727
4728               emit_insn (gen_movsi (reg, operands[1]));
4729               operands[1] = gen_lowpart (QImode, reg);
4730             }
4731           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4732             {
4733               rtx reg = gen_reg_rtx (SImode);
4734
4735               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4736               operands[1] = gen_lowpart (QImode, reg);
4737             }
4738           if (GET_CODE (operands[0]) == MEM)
4739             operands[1] = force_reg (QImode, operands[1]);
4740         }
4741     }
4742   else /* TARGET_THUMB */
4743     {
4744       if (!no_new_pseudos)
4745         {
4746           if (GET_CODE (operands[0]) != REG)
4747             operands[1] = force_reg (QImode, operands[1]);
4748
4749           /* ??? We shouldn't really get invalid addresses here, but this can
4750              happen if we are passed a SP (never OK for HImode/QImode) or
4751              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4752              HImode/QImode) relative address.  */
4753           /* ??? This should perhaps be fixed elsewhere, for instance, in
4754              fixup_stack_1, by checking for other kinds of invalid addresses,
4755              e.g. a bare reference to a virtual register.  This may confuse the
4756              alpha though, which must handle this case differently.  */
4757           if (GET_CODE (operands[0]) == MEM
4758               && !memory_address_p (GET_MODE (operands[0]),
4759                                      XEXP (operands[0], 0)))
4760             operands[0]
4761               = replace_equiv_address (operands[0],
4762                                        copy_to_reg (XEXP (operands[0], 0)));
4763           if (GET_CODE (operands[1]) == MEM
4764               && !memory_address_p (GET_MODE (operands[1]),
4765                                     XEXP (operands[1], 0)))
4766              operands[1]
4767                = replace_equiv_address (operands[1],
4768                                         copy_to_reg (XEXP (operands[1], 0)));
4769         }
4770       /* Handle loading a large integer during reload.  */
4771       else if (GET_CODE (operands[1]) == CONST_INT
4772                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4773         {
4774           /* Writing a constant to memory needs a scratch, which should
4775              be handled with SECONDARY_RELOADs.  */
4776           if (GET_CODE (operands[0]) != REG)
4777             abort ();
4778
4779           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4780           emit_insn (gen_movsi (operands[0], operands[1]));
4781           DONE;
4782        }
4783     }
4784   "
4785 )
4786
4787
4788 (define_insn "*arm_movqi_insn"
4789   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4790         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4791   "TARGET_ARM
4792    && (   register_operand (operands[0], QImode)
4793        || register_operand (operands[1], QImode))"
4794   "@
4795    mov%?\\t%0, %1
4796    mvn%?\\t%0, #%B1
4797    ldr%?b\\t%0, %1
4798    str%?b\\t%1, %0"
4799   [(set_attr "type" "*,*,load,store1")
4800    (set_attr "predicable" "yes")]
4801 )
4802
4803 (define_insn "*thumb_movqi_insn"
4804   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4805         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4806   "TARGET_THUMB
4807    && (   register_operand (operands[0], QImode)
4808        || register_operand (operands[1], QImode))"
4809   "@
4810    add\\t%0, %1, #0
4811    ldrb\\t%0, %1
4812    strb\\t%1, %0
4813    mov\\t%0, %1
4814    mov\\t%0, %1
4815    mov\\t%0, %1"
4816   [(set_attr "length" "2")
4817    (set_attr "type" "*,load,store1,*,*,*")
4818    (set_attr "pool_range" "*,32,*,*,*,*")]
4819 )
4820
4821 (define_expand "movsf"
4822   [(set (match_operand:SF 0 "general_operand" "")
4823         (match_operand:SF 1 "general_operand" ""))]
4824   "TARGET_EITHER"
4825   "
4826   if (TARGET_ARM)
4827     {
4828       if (GET_CODE (operands[0]) == MEM)
4829         operands[1] = force_reg (SFmode, operands[1]);
4830     }
4831   else /* TARGET_THUMB */
4832     {
4833       if (!no_new_pseudos)
4834         {
4835            if (GET_CODE (operands[0]) != REG)
4836              operands[1] = force_reg (SFmode, operands[1]);
4837         }
4838     }
4839   "
4840 )
4841
4842 (define_split
4843   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4844         (match_operand:SF 1 "immediate_operand" ""))]
4845   "TARGET_ARM
4846    && !TARGET_HARD_FLOAT
4847    && reload_completed
4848    && GET_CODE (operands[1]) == CONST_DOUBLE"
4849   [(set (match_dup 2) (match_dup 3))]
4850   "
4851   operands[2] = gen_lowpart (SImode, operands[0]);
4852   operands[3] = gen_lowpart (SImode, operands[1]);
4853   if (operands[2] == 0 || operands[3] == 0)
4854     FAIL;
4855   "
4856 )
4857
4858 (define_insn "*arm_movsf_soft_insn"
4859   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4860         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4861   "TARGET_ARM
4862    && !TARGET_CIRRUS
4863    && TARGET_SOFT_FLOAT
4864    && (GET_CODE (operands[0]) != MEM
4865        || register_operand (operands[1], SFmode))"
4866   "@
4867    mov%?\\t%0, %1
4868    ldr%?\\t%0, %1\\t%@ float
4869    str%?\\t%1, %0\\t%@ float"
4870   [(set_attr "length" "4,4,4")
4871    (set_attr "predicable" "yes")
4872    (set_attr "type" "*,load,store1")
4873    (set_attr "pool_range" "*,4096,*")
4874    (set_attr "neg_pool_range" "*,4084,*")]
4875 )
4876
4877 ;;; ??? This should have alternatives for constants.
4878 (define_insn "*thumb_movsf_insn"
4879   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4880         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4881   "TARGET_THUMB
4882    && (   register_operand (operands[0], SFmode) 
4883        || register_operand (operands[1], SFmode))"
4884   "@
4885    add\\t%0, %1, #0
4886    ldmia\\t%1, {%0}
4887    stmia\\t%0, {%1}
4888    ldr\\t%0, %1
4889    str\\t%1, %0
4890    mov\\t%0, %1
4891    mov\\t%0, %1"
4892   [(set_attr "length" "2")
4893    (set_attr "type" "*,load,store1,load,store1,*,*")
4894    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4895 )
4896
4897 (define_expand "movdf"
4898   [(set (match_operand:DF 0 "general_operand" "")
4899         (match_operand:DF 1 "general_operand" ""))]
4900   "TARGET_EITHER"
4901   "
4902   if (TARGET_ARM)
4903     {
4904       if (GET_CODE (operands[0]) == MEM)
4905         operands[1] = force_reg (DFmode, operands[1]);
4906     }
4907   else /* TARGET_THUMB */
4908     {
4909       if (!no_new_pseudos)
4910         {
4911           if (GET_CODE (operands[0]) != REG)
4912             operands[1] = force_reg (DFmode, operands[1]);
4913         }
4914     }
4915   "
4916 )
4917
4918 ;; Reloading a df mode value stored in integer regs to memory can require a
4919 ;; scratch reg.
4920 (define_expand "reload_outdf"
4921   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4922    (match_operand:DF 1 "s_register_operand" "r")
4923    (match_operand:SI 2 "s_register_operand" "=&r")]
4924   "TARGET_ARM"
4925   "
4926   {
4927     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4928
4929     if (code == REG)
4930       operands[2] = XEXP (operands[0], 0);
4931     else if (code == POST_INC || code == PRE_DEC)
4932       {
4933         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4934         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4935         emit_insn (gen_movdi (operands[0], operands[1]));
4936         DONE;
4937       }
4938     else if (code == PRE_INC)
4939       {
4940         rtx reg = XEXP (XEXP (operands[0], 0), 0);
4941
4942         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4943         operands[2] = reg;
4944       }
4945     else if (code == POST_DEC)
4946       operands[2] = XEXP (XEXP (operands[0], 0), 0);
4947     else
4948       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4949                              XEXP (XEXP (operands[0], 0), 1)));
4950
4951     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4952                             operands[1]));
4953
4954     if (code == POST_DEC)
4955       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4956
4957     DONE;
4958   }"
4959 )
4960
4961 (define_insn "*movdf_soft_insn"
4962   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4963         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4964   "TARGET_ARM && TARGET_SOFT_FLOAT
4965    && !TARGET_CIRRUS
4966   "
4967   "* return output_move_double (operands);"
4968   [(set_attr "length" "8,8,8")
4969    (set_attr "type" "*,load,store2")
4970    (set_attr "pool_range" "1020")
4971    (set_attr "neg_pool_range" "1008")]
4972 )
4973
4974 ;;; ??? This should have alternatives for constants.
4975 ;;; ??? This was originally identical to the movdi_insn pattern.
4976 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4977 ;;; thumb_reorg with a memory reference.
4978 (define_insn "*thumb_movdf_insn"
4979   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4980         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
4981   "TARGET_THUMB
4982    && (   register_operand (operands[0], DFmode)
4983        || register_operand (operands[1], DFmode))"
4984   "*
4985   switch (which_alternative)
4986     {
4987     default:
4988     case 0:
4989       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4990         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4991       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4992     case 1:
4993       return \"ldmia\\t%1, {%0, %H0}\";
4994     case 2:
4995       return \"stmia\\t%0, {%1, %H1}\";
4996     case 3:
4997       return thumb_load_double_from_address (operands);
4998     case 4:
4999       operands[2] = gen_rtx (MEM, SImode,
5000                              plus_constant (XEXP (operands[0], 0), 4));
5001       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5002       return \"\";
5003     case 5:
5004       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5005         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5006       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5007     }
5008   "
5009   [(set_attr "length" "4,2,2,6,4,4")
5010    (set_attr "type" "*,load,store2,load,store2,*")
5011    (set_attr "pool_range" "*,*,*,1020,*,*")]
5012 )
5013
5014 ;; Vector Moves
5015 (define_expand "movv2si"
5016   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5017         (match_operand:V2SI 1 "general_operand" ""))]
5018   "TARGET_REALLY_IWMMXT"
5019 {
5020 })
5021
5022 (define_expand "movv4hi"
5023   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5024         (match_operand:V4HI 1 "general_operand" ""))]
5025   "TARGET_REALLY_IWMMXT"
5026 {
5027 })
5028
5029 (define_expand "movv8qi"
5030   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5031         (match_operand:V8QI 1 "general_operand" ""))]
5032   "TARGET_REALLY_IWMMXT"
5033 {
5034 })
5035 \f
5036
5037 ;; load- and store-multiple insns
5038 ;; The arm can load/store any set of registers, provided that they are in
5039 ;; ascending order; but that is beyond GCC so stick with what it knows.
5040
5041 (define_expand "load_multiple"
5042   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5043                           (match_operand:SI 1 "" ""))
5044                      (use (match_operand:SI 2 "" ""))])]
5045   "TARGET_ARM"
5046   "
5047   /* Support only fixed point registers.  */
5048   if (GET_CODE (operands[2]) != CONST_INT
5049       || INTVAL (operands[2]) > 14
5050       || INTVAL (operands[2]) < 2
5051       || GET_CODE (operands[1]) != MEM
5052       || GET_CODE (operands[0]) != REG
5053       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5054       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5055     FAIL;
5056
5057   operands[3]
5058     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5059                              force_reg (SImode, XEXP (operands[1], 0)),
5060                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5061                              MEM_IN_STRUCT_P(operands[1]),
5062                              MEM_SCALAR_P (operands[1]));
5063   "
5064 )
5065
5066 ;; Load multiple with write-back
5067
5068 (define_insn "*ldmsi_postinc4"
5069   [(match_parallel 0 "load_multiple_operation"
5070     [(set (match_operand:SI 1 "s_register_operand" "=r")
5071           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5072                    (const_int 16)))
5073      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5074           (mem:SI (match_dup 2)))
5075      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5076           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5077      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5078           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5079      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5080           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5081   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5082   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5083   [(set_attr "type" "load")
5084    (set_attr "predicable" "yes")]
5085 )
5086
5087 (define_insn "*ldmsi_postinc3"
5088   [(match_parallel 0 "load_multiple_operation"
5089     [(set (match_operand:SI 1 "s_register_operand" "=r")
5090           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5091                    (const_int 12)))
5092      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5093           (mem:SI (match_dup 2)))
5094      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5095           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5096      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5097           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5098   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5099   "ldm%?ia\\t%1!, {%3, %4, %5}"
5100   [(set_attr "type" "load")
5101    (set_attr "predicable" "yes")]
5102 )
5103
5104 (define_insn "*ldmsi_postinc2"
5105   [(match_parallel 0 "load_multiple_operation"
5106     [(set (match_operand:SI 1 "s_register_operand" "=r")
5107           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5108                    (const_int 8)))
5109      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5110           (mem:SI (match_dup 2)))
5111      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5112           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5113   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5114   "ldm%?ia\\t%1!, {%3, %4}"
5115   [(set_attr "type" "load")
5116    (set_attr "predicable" "yes")]
5117 )
5118
5119 ;; Ordinary load multiple
5120
5121 (define_insn "*ldmsi4"
5122   [(match_parallel 0 "load_multiple_operation"
5123     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5124           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5125      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5126           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5127      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5128           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5129      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5130           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5131   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5132   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5133   [(set_attr "type" "load")
5134    (set_attr "predicable" "yes")]
5135 )
5136
5137 (define_insn "*ldmsi3"
5138   [(match_parallel 0 "load_multiple_operation"
5139     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5140           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5141      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5142           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5143      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5144           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5145   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5146   "ldm%?ia\\t%1, {%2, %3, %4}"
5147   [(set_attr "type" "load")
5148    (set_attr "predicable" "yes")]
5149 )
5150
5151 (define_insn "*ldmsi2"
5152   [(match_parallel 0 "load_multiple_operation"
5153     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5154           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5155      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5156           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5157   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5158   "ldm%?ia\\t%1, {%2, %3}"
5159   [(set_attr "type" "load")
5160    (set_attr "predicable" "yes")]
5161 )
5162
5163 (define_expand "store_multiple"
5164   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5165                           (match_operand:SI 1 "" ""))
5166                      (use (match_operand:SI 2 "" ""))])]
5167   "TARGET_ARM"
5168   "
5169   /* Support only fixed point registers.  */
5170   if (GET_CODE (operands[2]) != CONST_INT
5171       || INTVAL (operands[2]) > 14
5172       || INTVAL (operands[2]) < 2
5173       || GET_CODE (operands[1]) != REG
5174       || GET_CODE (operands[0]) != MEM
5175       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5176       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5177     FAIL;
5178
5179   operands[3]
5180     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5181                               force_reg (SImode, XEXP (operands[0], 0)),
5182                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5183                               MEM_IN_STRUCT_P(operands[0]), 
5184                               MEM_SCALAR_P (operands[0]));
5185   "
5186 )
5187
5188 ;; Store multiple with write-back
5189
5190 (define_insn "*stmsi_postinc4"
5191   [(match_parallel 0 "store_multiple_operation"
5192     [(set (match_operand:SI 1 "s_register_operand" "=r")
5193           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5194                    (const_int 16)))
5195      (set (mem:SI (match_dup 2))
5196           (match_operand:SI 3 "arm_hard_register_operand" ""))
5197      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5198           (match_operand:SI 4 "arm_hard_register_operand" ""))
5199      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5200           (match_operand:SI 5 "arm_hard_register_operand" ""))
5201      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5202           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5203   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5204   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5205   [(set_attr "predicable" "yes")
5206    (set_attr "type" "store4")]
5207 )
5208
5209 (define_insn "*stmsi_postinc3"
5210   [(match_parallel 0 "store_multiple_operation"
5211     [(set (match_operand:SI 1 "s_register_operand" "=r")
5212           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5213                    (const_int 12)))
5214      (set (mem:SI (match_dup 2))
5215           (match_operand:SI 3 "arm_hard_register_operand" ""))
5216      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5217           (match_operand:SI 4 "arm_hard_register_operand" ""))
5218      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5219           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5220   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5221   "stm%?ia\\t%1!, {%3, %4, %5}"
5222   [(set_attr "predicable" "yes")
5223    (set_attr "type" "store3")]
5224 )
5225
5226 (define_insn "*stmsi_postinc2"
5227   [(match_parallel 0 "store_multiple_operation"
5228     [(set (match_operand:SI 1 "s_register_operand" "=r")
5229           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5230                    (const_int 8)))
5231      (set (mem:SI (match_dup 2))
5232           (match_operand:SI 3 "arm_hard_register_operand" ""))
5233      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5234           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5235   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5236   "stm%?ia\\t%1!, {%3, %4}"
5237   [(set_attr "predicable" "yes")
5238    (set_attr "type" "store2")]
5239 )
5240
5241 ;; Ordinary store multiple
5242
5243 (define_insn "*stmsi4"
5244   [(match_parallel 0 "store_multiple_operation"
5245     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5246           (match_operand:SI 2 "arm_hard_register_operand" ""))
5247      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5248           (match_operand:SI 3 "arm_hard_register_operand" ""))
5249      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5250           (match_operand:SI 4 "arm_hard_register_operand" ""))
5251      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5252           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5253   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5254   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5255   [(set_attr "predicable" "yes")
5256    (set_attr "type" "store4")]
5257 )
5258
5259 (define_insn "*stmsi3"
5260   [(match_parallel 0 "store_multiple_operation"
5261     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5262           (match_operand:SI 2 "arm_hard_register_operand" ""))
5263      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5264           (match_operand:SI 3 "arm_hard_register_operand" ""))
5265      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5266           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5267   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5268   "stm%?ia\\t%1, {%2, %3, %4}"
5269   [(set_attr "predicable" "yes")
5270    (set_attr "type" "store3")]
5271 )
5272
5273 (define_insn "*stmsi2"
5274   [(match_parallel 0 "store_multiple_operation"
5275     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5276           (match_operand:SI 2 "arm_hard_register_operand" ""))
5277      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5278           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5279   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5280   "stm%?ia\\t%1, {%2, %3}"
5281   [(set_attr "predicable" "yes")
5282    (set_attr "type" "store2")]
5283 )
5284
5285 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5286 ;; We could let this apply for blocks of less than this, but it clobbers so
5287 ;; many registers that there is then probably a better way.
5288
5289 (define_expand "movstrqi"
5290   [(match_operand:BLK 0 "general_operand" "")
5291    (match_operand:BLK 1 "general_operand" "")
5292    (match_operand:SI 2 "const_int_operand" "")
5293    (match_operand:SI 3 "const_int_operand" "")]
5294   "TARGET_EITHER"
5295   "
5296   if (TARGET_ARM)
5297     {
5298       if (arm_gen_movstrqi (operands))
5299         DONE;
5300       FAIL;
5301     }
5302   else /* TARGET_THUMB */
5303     {
5304       if (   INTVAL (operands[3]) != 4
5305           || INTVAL (operands[2]) > 48)
5306         FAIL;
5307
5308       thumb_expand_movstrqi (operands);
5309       DONE;
5310     }
5311   "
5312 )
5313
5314 ;; Thumb block-move insns
5315
5316 (define_insn "movmem12b"
5317   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5318         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5319    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5320         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5321    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5322         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5323    (set (match_operand:SI 0 "register_operand" "=l")
5324         (plus:SI (match_dup 2) (const_int 12)))
5325    (set (match_operand:SI 1 "register_operand" "=l")
5326         (plus:SI (match_dup 3) (const_int 12)))
5327    (clobber (match_scratch:SI 4 "=&l"))
5328    (clobber (match_scratch:SI 5 "=&l"))
5329    (clobber (match_scratch:SI 6 "=&l"))]
5330   "TARGET_THUMB"
5331   "* return thumb_output_move_mem_multiple (3, operands);"
5332   [(set_attr "length" "4")
5333    ; This isn't entirely accurate...  It loads as well, but in terms of
5334    ; scheduling the following insn it is better to consider it as a store
5335    (set_attr "type" "store3")]
5336 )
5337
5338 (define_insn "movmem8b"
5339   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5340         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5341    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5342         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5343    (set (match_operand:SI 0 "register_operand" "=l")
5344         (plus:SI (match_dup 2) (const_int 8)))
5345    (set (match_operand:SI 1 "register_operand" "=l")
5346         (plus:SI (match_dup 3) (const_int 8)))
5347    (clobber (match_scratch:SI 4 "=&l"))
5348    (clobber (match_scratch:SI 5 "=&l"))]
5349   "TARGET_THUMB"
5350   "* return thumb_output_move_mem_multiple (2, operands);"
5351   [(set_attr "length" "4")
5352    ; This isn't entirely accurate...  It loads as well, but in terms of
5353    ; scheduling the following insn it is better to consider it as a store
5354    (set_attr "type" "store2")]
5355 )
5356
5357 \f
5358
5359 ;; Compare & branch insns
5360 ;; The range calculations are based as follows:
5361 ;; For forward branches, the address calculation returns the address of
5362 ;; the next instruction.  This is 2 beyond the branch instruction.
5363 ;; For backward branches, the address calculation returns the address of
5364 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5365 ;; instruction for the shortest sequence, and 4 before the branch instruction
5366 ;; if we have to jump around an unconditional branch.
5367 ;; To the basic branch range the PC offset must be added (this is +4).
5368 ;; So for forward branches we have 
5369 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5370 ;; And for backward branches we have 
5371 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5372 ;;
5373 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5374 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5375
5376 (define_expand "cbranchsi4"
5377   [(set (pc) (if_then_else
5378               (match_operator 0 "arm_comparison_operator"
5379                [(match_operand:SI 1 "s_register_operand" "")
5380                 (match_operand:SI 2 "nonmemory_operand" "")])
5381               (label_ref (match_operand 3 "" ""))
5382               (pc)))]
5383   "TARGET_THUMB"
5384   "
5385   if (thumb_cmpneg_operand (operands[2], SImode))
5386     {
5387       emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5388                                               operands[3], operands[0]));
5389       DONE;
5390     }
5391   if (!thumb_cmp_operand (operands[2], SImode))
5392     operands[2] = force_reg (SImode, operands[2]);
5393   ")
5394
5395 (define_insn "*cbranchsi4_insn"
5396   [(set (pc) (if_then_else
5397               (match_operator 0 "arm_comparison_operator"
5398                [(match_operand:SI 1 "s_register_operand" "l,*h")
5399                 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5400               (label_ref (match_operand 3 "" ""))
5401               (pc)))]
5402   "TARGET_THUMB"
5403   "*
5404   output_asm_insn (\"cmp\\t%1, %2\", operands);
5405
5406   switch (get_attr_length (insn))
5407     {
5408     case 4:  return \"b%d0\\t%l3\";
5409     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5410     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5411     }
5412   "
5413   [(set (attr "far_jump")
5414         (if_then_else
5415             (eq_attr "length" "8")
5416             (const_string "yes")
5417             (const_string "no")))
5418    (set (attr "length") 
5419         (if_then_else
5420             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5421                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5422             (const_int 4)
5423             (if_then_else
5424                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5425                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5426                 (const_int 6)
5427                 (const_int 8))))]
5428 )
5429
5430 (define_insn "cbranchsi4_scratch"
5431   [(set (pc) (if_then_else
5432               (match_operator 4 "arm_comparison_operator"
5433                [(match_operand:SI 1 "s_register_operand" "l,0")
5434                 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5435               (label_ref (match_operand 3 "" ""))
5436               (pc)))
5437    (clobber (match_scratch:SI 0 "=l,l"))]
5438   "TARGET_THUMB"
5439   "*
5440   output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5441
5442   switch (get_attr_length (insn))
5443     {
5444     case 4:  return \"b%d4\\t%l3\";
5445     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5446     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5447     }
5448   "
5449   [(set (attr "far_jump")
5450         (if_then_else
5451             (eq_attr "length" "8")
5452             (const_string "yes")
5453             (const_string "no")))
5454    (set (attr "length") 
5455         (if_then_else
5456             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5457                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5458             (const_int 4)
5459             (if_then_else
5460                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5461                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5462                 (const_int 6)
5463                 (const_int 8))))]
5464 )
5465 (define_insn "*movsi_cbranchsi4"
5466   [(set (pc)
5467         (if_then_else
5468          (match_operator 3 "arm_comparison_operator"
5469           [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5470            (const_int 0)])
5471          (label_ref (match_operand 2 "" ""))
5472          (pc)))
5473    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5474         (match_dup 1))]
5475   "TARGET_THUMB"
5476   "*{
5477   if (which_alternative == 0)
5478     output_asm_insn (\"cmp\t%0, #0\", operands);
5479   else if (which_alternative == 1)
5480     output_asm_insn (\"sub\t%0, %1, #0\", operands);
5481   else
5482     {
5483       output_asm_insn (\"cmp\t%1, #0\", operands);
5484       if (which_alternative == 2)
5485         output_asm_insn (\"mov\t%0, %1\", operands);
5486       else
5487         output_asm_insn (\"str\t%1, %0\", operands);
5488     }
5489   switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5490     {
5491     case 4:  return \"b%d3\\t%l2\";
5492     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5493     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5494     }
5495   }"
5496   [(set (attr "far_jump")
5497         (if_then_else
5498             (ior (and (gt (symbol_ref ("which_alternative"))
5499                           (const_int 1))
5500                       (eq_attr "length" "8"))
5501                  (eq_attr "length" "10"))
5502             (const_string "yes")
5503             (const_string "no")))
5504    (set (attr "length")
5505      (if_then_else
5506        (le (symbol_ref ("which_alternative"))
5507                        (const_int 1))
5508        (if_then_else
5509          (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5510               (le (minus (match_dup 2) (pc)) (const_int 256)))
5511          (const_int 4)
5512          (if_then_else
5513            (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5514                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5515            (const_int 6)
5516            (const_int 8)))
5517        (if_then_else
5518          (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5519               (le (minus (match_dup 2) (pc)) (const_int 256)))
5520          (const_int 6)
5521          (if_then_else
5522            (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5523                 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5524            (const_int 8)
5525            (const_int 10)))))]
5526 )
5527
5528 (define_insn "*negated_cbranchsi4"
5529   [(set (pc)
5530         (if_then_else
5531          (match_operator 0 "arm_comparison_operator"
5532           [(match_operand:SI 1 "s_register_operand" "l")
5533            (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5534          (label_ref (match_operand 3 "" ""))
5535          (pc)))]
5536   "TARGET_THUMB"
5537   "*
5538   output_asm_insn (\"cmn\\t%1, %2\", operands);
5539   switch (get_attr_length (insn))
5540     {
5541     case 4:  return \"b%d0\\t%l3\";
5542     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5543     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5544     }
5545   "
5546   [(set (attr "far_jump")
5547         (if_then_else
5548             (eq_attr "length" "8")
5549             (const_string "yes")
5550             (const_string "no")))
5551    (set (attr "length") 
5552         (if_then_else
5553             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5554                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5555             (const_int 4)
5556             (if_then_else
5557                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5558                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5559                 (const_int 6)
5560                 (const_int 8))))]
5561 )
5562
5563 (define_insn "*tbit_cbranch"
5564   [(set (pc)
5565         (if_then_else
5566          (match_operator 0 "equality_operator"
5567           [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5568                             (const_int 1)
5569                             (match_operand:SI 2 "const_int_operand" "i"))
5570            (const_int 0)])
5571          (label_ref (match_operand 3 "" ""))
5572          (pc)))
5573    (clobber (match_scratch:SI 4 "=l"))]
5574   "TARGET_THUMB"
5575   "*
5576   {
5577   rtx op[3];
5578   op[0] = operands[4];
5579   op[1] = operands[1];
5580   op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5581
5582   output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5583   switch (get_attr_length (insn))
5584     {
5585     case 4:  return \"b%d0\\t%l3\";
5586     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5587     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5588     }
5589   }"
5590   [(set (attr "far_jump")
5591         (if_then_else
5592             (eq_attr "length" "8")
5593             (const_string "yes")
5594             (const_string "no")))
5595    (set (attr "length") 
5596         (if_then_else
5597             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5598                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5599             (const_int 4)
5600             (if_then_else
5601                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5602                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5603                 (const_int 6)
5604                 (const_int 8))))]
5605 )
5606   
5607 (define_insn "*tstsi3_cbranch"
5608   [(set (pc)
5609         (if_then_else
5610          (match_operator 3 "equality_operator"
5611           [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5612                    (match_operand:SI 1 "s_register_operand" "l"))
5613            (const_int 0)])
5614          (label_ref (match_operand 2 "" ""))
5615          (pc)))]
5616   "TARGET_THUMB"
5617   "*
5618   {
5619   output_asm_insn (\"tst\\t%0, %1\", operands);
5620   switch (get_attr_length (insn))
5621     {
5622     case 4:  return \"b%d3\\t%l2\";
5623     case 6:  return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5624     default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5625     }
5626   }"
5627   [(set (attr "far_jump")
5628         (if_then_else
5629             (eq_attr "length" "8")
5630             (const_string "yes")
5631             (const_string "no")))
5632    (set (attr "length") 
5633         (if_then_else
5634             (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5635                  (le (minus (match_dup 2) (pc)) (const_int 256)))
5636             (const_int 4)
5637             (if_then_else
5638                 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5639                      (le (minus (match_dup 2) (pc)) (const_int 2048)))
5640                 (const_int 6)
5641                 (const_int 8))))]
5642 )
5643   
5644 (define_insn "*andsi3_cbranch"
5645   [(set (pc)
5646         (if_then_else
5647          (match_operator 5 "equality_operator"
5648           [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5649                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5650            (const_int 0)])
5651          (label_ref (match_operand 4 "" ""))
5652          (pc)))
5653    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5654         (and:SI (match_dup 2) (match_dup 3)))
5655    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5656   "TARGET_THUMB"
5657   "*
5658   {
5659   if (which_alternative == 0)
5660     output_asm_insn (\"and\\t%0, %3\", operands);
5661   else if (which_alternative == 1)
5662     {
5663       output_asm_insn (\"and\\t%1, %3\", operands);
5664       output_asm_insn (\"mov\\t%0, %1\", operands);
5665     }
5666   else
5667     {
5668       output_asm_insn (\"and\\t%1, %3\", operands);
5669       output_asm_insn (\"str\\t%1, %0\", operands);
5670     }
5671
5672   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5673     {
5674     case 4:  return \"b%d5\\t%l4\";
5675     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5676     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5677     }
5678   }"
5679   [(set (attr "far_jump")
5680         (if_then_else
5681             (ior (and (eq (symbol_ref ("which_alternative"))
5682                           (const_int 0))
5683                       (eq_attr "length" "8"))
5684                  (eq_attr "length" "10"))
5685             (const_string "yes")
5686             (const_string "no")))
5687    (set (attr "length")
5688      (if_then_else
5689        (eq (symbol_ref ("which_alternative"))
5690                        (const_int 0))
5691        (if_then_else
5692          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5693               (le (minus (match_dup 4) (pc)) (const_int 256)))
5694          (const_int 4)
5695          (if_then_else
5696            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5697                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5698            (const_int 6)
5699            (const_int 8)))
5700        (if_then_else
5701          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5702               (le (minus (match_dup 4) (pc)) (const_int 256)))
5703          (const_int 6)
5704          (if_then_else
5705            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5706                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5707            (const_int 8)
5708            (const_int 10)))))]
5709 )
5710
5711 (define_insn "*orrsi3_cbranch_scratch"
5712   [(set (pc)
5713         (if_then_else
5714          (match_operator 4 "equality_operator"
5715           [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5716                    (match_operand:SI 2 "s_register_operand" "l"))
5717            (const_int 0)])
5718          (label_ref (match_operand 3 "" ""))
5719          (pc)))
5720    (clobber (match_scratch:SI 0 "=l"))]
5721   "TARGET_THUMB"
5722   "*
5723   {
5724   output_asm_insn (\"orr\\t%0, %2\", operands);
5725   switch (get_attr_length (insn))
5726     {
5727     case 4:  return \"b%d4\\t%l3\";
5728     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5729     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5730     }
5731   }"
5732   [(set (attr "far_jump")
5733         (if_then_else
5734             (eq_attr "length" "8")
5735             (const_string "yes")
5736             (const_string "no")))
5737    (set (attr "length") 
5738         (if_then_else
5739             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5740                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5741             (const_int 4)
5742             (if_then_else
5743                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5744                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5745                 (const_int 6)
5746                 (const_int 8))))]
5747 )
5748   
5749 (define_insn "*orrsi3_cbranch"
5750   [(set (pc)
5751         (if_then_else
5752          (match_operator 5 "equality_operator"
5753           [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5754                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5755            (const_int 0)])
5756          (label_ref (match_operand 4 "" ""))
5757          (pc)))
5758    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5759         (ior:SI (match_dup 2) (match_dup 3)))
5760    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5761   "TARGET_THUMB"
5762   "*
5763   {
5764   if (which_alternative == 0)
5765     output_asm_insn (\"orr\\t%0, %3\", operands);
5766   else if (which_alternative == 1)
5767     {
5768       output_asm_insn (\"orr\\t%1, %3\", operands);
5769       output_asm_insn (\"mov\\t%0, %1\", operands);
5770     }
5771   else
5772     {
5773       output_asm_insn (\"orr\\t%1, %3\", operands);
5774       output_asm_insn (\"str\\t%1, %0\", operands);
5775     }
5776
5777   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5778     {
5779     case 4:  return \"b%d5\\t%l4\";
5780     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5781     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5782     }
5783   }"
5784   [(set (attr "far_jump")
5785         (if_then_else
5786             (ior (and (eq (symbol_ref ("which_alternative"))
5787                           (const_int 0))
5788                       (eq_attr "length" "8"))
5789                  (eq_attr "length" "10"))
5790             (const_string "yes")
5791             (const_string "no")))
5792    (set (attr "length")
5793      (if_then_else
5794        (eq (symbol_ref ("which_alternative"))
5795                        (const_int 0))
5796        (if_then_else
5797          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5798               (le (minus (match_dup 4) (pc)) (const_int 256)))
5799          (const_int 4)
5800          (if_then_else
5801            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5802                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5803            (const_int 6)
5804            (const_int 8)))
5805        (if_then_else
5806          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5807               (le (minus (match_dup 4) (pc)) (const_int 256)))
5808          (const_int 6)
5809          (if_then_else
5810            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5811                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5812            (const_int 8)
5813            (const_int 10)))))]
5814 )
5815
5816 (define_insn "*xorsi3_cbranch_scratch"
5817   [(set (pc)
5818         (if_then_else
5819          (match_operator 4 "equality_operator"
5820           [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
5821                    (match_operand:SI 2 "s_register_operand" "l"))
5822            (const_int 0)])
5823          (label_ref (match_operand 3 "" ""))
5824          (pc)))
5825    (clobber (match_scratch:SI 0 "=l"))]
5826   "TARGET_THUMB"
5827   "*
5828   {
5829   output_asm_insn (\"eor\\t%0, %2\", operands);
5830   switch (get_attr_length (insn))
5831     {
5832     case 4:  return \"b%d4\\t%l3\";
5833     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5834     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5835     }
5836   }"
5837   [(set (attr "far_jump")
5838         (if_then_else
5839             (eq_attr "length" "8")
5840             (const_string "yes")
5841             (const_string "no")))
5842    (set (attr "length") 
5843         (if_then_else
5844             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5845                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5846             (const_int 4)
5847             (if_then_else
5848                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5849                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5850                 (const_int 6)
5851                 (const_int 8))))]
5852 )
5853   
5854 (define_insn "*xorsi3_cbranch"
5855   [(set (pc)
5856         (if_then_else
5857          (match_operator 5 "equality_operator"
5858           [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5859                    (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5860            (const_int 0)])
5861          (label_ref (match_operand 4 "" ""))
5862          (pc)))
5863    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5864         (xor:SI (match_dup 2) (match_dup 3)))
5865    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5866   "TARGET_THUMB"
5867   "*
5868   {
5869   if (which_alternative == 0)
5870     output_asm_insn (\"eor\\t%0, %3\", operands);
5871   else if (which_alternative == 1)
5872     {
5873       output_asm_insn (\"eor\\t%1, %3\", operands);
5874       output_asm_insn (\"mov\\t%0, %1\", operands);
5875     }
5876   else
5877     {
5878       output_asm_insn (\"eor\\t%1, %3\", operands);
5879       output_asm_insn (\"str\\t%1, %0\", operands);
5880     }
5881
5882   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5883     {
5884     case 4:  return \"b%d5\\t%l4\";
5885     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5886     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5887     }
5888   }"
5889   [(set (attr "far_jump")
5890         (if_then_else
5891             (ior (and (eq (symbol_ref ("which_alternative"))
5892                           (const_int 0))
5893                       (eq_attr "length" "8"))
5894                  (eq_attr "length" "10"))
5895             (const_string "yes")
5896             (const_string "no")))
5897    (set (attr "length")
5898      (if_then_else
5899        (eq (symbol_ref ("which_alternative"))
5900                        (const_int 0))
5901        (if_then_else
5902          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5903               (le (minus (match_dup 4) (pc)) (const_int 256)))
5904          (const_int 4)
5905          (if_then_else
5906            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5907                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5908            (const_int 6)
5909            (const_int 8)))
5910        (if_then_else
5911          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5912               (le (minus (match_dup 4) (pc)) (const_int 256)))
5913          (const_int 6)
5914          (if_then_else
5915            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5916                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5917            (const_int 8)
5918            (const_int 10)))))]
5919 )
5920
5921 (define_insn "*bicsi3_cbranch_scratch"
5922   [(set (pc)
5923         (if_then_else
5924          (match_operator 4 "equality_operator"
5925           [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
5926                    (match_operand:SI 1 "s_register_operand" "0"))
5927            (const_int 0)])
5928          (label_ref (match_operand 3 "" ""))
5929          (pc)))
5930    (clobber (match_scratch:SI 0 "=l"))]
5931   "TARGET_THUMB"
5932   "*
5933   {
5934   output_asm_insn (\"bic\\t%0, %2\", operands);
5935   switch (get_attr_length (insn))
5936     {
5937     case 4:  return \"b%d4\\t%l3\";
5938     case 6:  return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5939     default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5940     }
5941   }"
5942   [(set (attr "far_jump")
5943         (if_then_else
5944             (eq_attr "length" "8")
5945             (const_string "yes")
5946             (const_string "no")))
5947    (set (attr "length") 
5948         (if_then_else
5949             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5950                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5951             (const_int 4)
5952             (if_then_else
5953                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5954                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5955                 (const_int 6)
5956                 (const_int 8))))]
5957 )
5958   
5959 (define_insn "*bicsi3_cbranch"
5960   [(set (pc)
5961         (if_then_else
5962          (match_operator 5 "equality_operator"
5963           [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5964                    (match_operand:SI 2 "s_register_operand" "0,1,1,1"))
5965            (const_int 0)])
5966          (label_ref (match_operand 4 "" ""))
5967          (pc)))
5968    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5969         (and:SI (not:SI (match_dup 3)) (match_dup 2)))
5970    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5971   "TARGET_THUMB"
5972   "*
5973   {
5974   if (which_alternative == 0)
5975     output_asm_insn (\"bic\\t%0, %3\", operands);
5976   else if (which_alternative == 1)
5977     {
5978       output_asm_insn (\"bic\\t%1, %3\", operands);
5979       output_asm_insn (\"mov\\t%0, %1\", operands);
5980     }
5981   else
5982     {
5983       output_asm_insn (\"bic\\t%1, %3\", operands);
5984       output_asm_insn (\"str\\t%1, %0\", operands);
5985     }
5986
5987   switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5988     {
5989     case 4:  return \"b%d5\\t%l4\";
5990     case 6:  return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5991     default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5992     }
5993   }"
5994   [(set (attr "far_jump")
5995         (if_then_else
5996             (ior (and (eq (symbol_ref ("which_alternative"))
5997                           (const_int 0))
5998                       (eq_attr "length" "8"))
5999                  (eq_attr "length" "10"))
6000             (const_string "yes")
6001             (const_string "no")))
6002    (set (attr "length")
6003      (if_then_else
6004        (eq (symbol_ref ("which_alternative"))
6005                        (const_int 0))
6006        (if_then_else
6007          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6008               (le (minus (match_dup 4) (pc)) (const_int 256)))
6009          (const_int 4)
6010          (if_then_else
6011            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6012                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6013            (const_int 6)
6014            (const_int 8)))
6015        (if_then_else
6016          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6017               (le (minus (match_dup 4) (pc)) (const_int 256)))
6018          (const_int 6)
6019          (if_then_else
6020            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6021                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6022            (const_int 8)
6023            (const_int 10)))))]
6024 )
6025
6026 (define_insn "*cbranchne_decr1"
6027   [(set (pc)
6028         (if_then_else (match_operator 3 "equality_operator"
6029                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6030                         (const_int 0)])
6031                       (label_ref (match_operand 4 "" ""))
6032                       (pc)))
6033    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6034         (plus:SI (match_dup 2) (const_int -1)))
6035    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6036   "TARGET_THUMB"
6037   "*
6038    {
6039      rtx cond[2];
6040      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6041                                 ? GEU : LTU),
6042                                VOIDmode, operands[2], const1_rtx);
6043      cond[1] = operands[4];
6044
6045      if (which_alternative == 0)
6046        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6047      else if (which_alternative == 1)
6048        {
6049          /* We must provide an alternative for a hi reg because reload 
6050             cannot handle output reloads on a jump instruction, but we
6051             can't subtract into that.  Fortunately a mov from lo to hi
6052             does not clobber the condition codes.  */
6053          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6054          output_asm_insn (\"mov\\t%0, %1\", operands);
6055        }
6056      else
6057        {
6058          /* Similarly, but the target is memory.  */
6059          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6060          output_asm_insn (\"str\\t%1, %0\", operands);
6061        }
6062
6063      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6064        {
6065          case 4:
6066            output_asm_insn (\"b%d0\\t%l1\", cond);
6067            return \"\";
6068          case 6:
6069            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6070            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6071          default:
6072            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6073            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6074        }
6075    }
6076   "
6077   [(set (attr "far_jump")
6078         (if_then_else
6079             (ior (and (eq (symbol_ref ("which_alternative"))
6080                           (const_int 0))
6081                       (eq_attr "length" "8"))
6082                  (eq_attr "length" "10"))
6083             (const_string "yes")
6084             (const_string "no")))
6085    (set_attr_alternative "length"
6086       [
6087        ;; Alternative 0
6088        (if_then_else
6089          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6090               (le (minus (match_dup 4) (pc)) (const_int 256)))
6091          (const_int 4)
6092          (if_then_else
6093            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6094                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6095            (const_int 6)
6096            (const_int 8)))
6097        ;; Alternative 1
6098        (if_then_else
6099          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6100               (le (minus (match_dup 4) (pc)) (const_int 256)))
6101          (const_int 6)
6102          (if_then_else
6103            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6104                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6105            (const_int 8)
6106            (const_int 10)))
6107        ;; Alternative 2
6108        (if_then_else
6109          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6110               (le (minus (match_dup 4) (pc)) (const_int 256)))
6111          (const_int 6)
6112          (if_then_else
6113            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6114                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6115            (const_int 8)
6116            (const_int 10)))
6117        ;; Alternative 3
6118        (if_then_else
6119          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6120               (le (minus (match_dup 4) (pc)) (const_int 256)))
6121          (const_int 6)
6122          (if_then_else
6123            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6124                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6125            (const_int 8)
6126            (const_int 10)))])]
6127 )
6128
6129 (define_insn "*addsi3_cbranch"
6130   [(set (pc)
6131         (if_then_else
6132          (match_operator 4 "comparison_operator"
6133           [(plus:SI
6134             (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6135             (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6136            (const_int 0)])
6137          (label_ref (match_operand 5 "" ""))
6138          (pc)))
6139    (set
6140     (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6141     (plus:SI (match_dup 2) (match_dup 3)))
6142    (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6143   "TARGET_THUMB
6144    && (GET_CODE (operands[4]) == EQ
6145        || GET_CODE (operands[4]) == NE
6146        || GET_CODE (operands[4]) == GE
6147        || GET_CODE (operands[4]) == LT)"
6148   "*
6149    {
6150      rtx cond[3];
6151
6152      
6153      cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6154      cond[1] = operands[2];
6155      cond[2] = operands[3];
6156
6157      if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6158        output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6159      else
6160        output_asm_insn (\"add\\t%0, %1, %2\", cond);
6161
6162      if (which_alternative >= 3
6163          && which_alternative < 4)
6164        output_asm_insn (\"mov\\t%0, %1\", operands);
6165      else if (which_alternative >= 4)
6166        output_asm_insn (\"str\\t%1, %0\", operands);
6167
6168      switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6169        {
6170          case 4:
6171            return \"b%d4\\t%l5\";
6172          case 6:
6173            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6174          default:
6175            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6176        }
6177    }
6178   "
6179   [(set (attr "far_jump")
6180         (if_then_else
6181             (ior (and (lt (symbol_ref ("which_alternative"))
6182                           (const_int 3))
6183                       (eq_attr "length" "8"))
6184                  (eq_attr "length" "10"))
6185             (const_string "yes")
6186             (const_string "no")))
6187    (set (attr "length")
6188      (if_then_else
6189        (lt (symbol_ref ("which_alternative"))
6190                        (const_int 3))
6191        (if_then_else
6192          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6193               (le (minus (match_dup 5) (pc)) (const_int 256)))
6194          (const_int 4)
6195          (if_then_else
6196            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6197                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6198            (const_int 6)
6199            (const_int 8)))
6200        (if_then_else
6201          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6202               (le (minus (match_dup 5) (pc)) (const_int 256)))
6203          (const_int 6)
6204          (if_then_else
6205            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6206                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6207            (const_int 8)
6208            (const_int 10)))))]
6209 )
6210
6211 (define_insn "*addsi3_cbranch_scratch"
6212   [(set (pc)
6213         (if_then_else
6214          (match_operator 3 "comparison_operator"
6215           [(plus:SI
6216             (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6217             (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6218            (const_int 0)])
6219          (label_ref (match_operand 4 "" ""))
6220          (pc)))
6221    (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6222   "TARGET_THUMB
6223    && (GET_CODE (operands[3]) == EQ
6224        || GET_CODE (operands[3]) == NE
6225        || GET_CODE (operands[3]) == GE
6226        || GET_CODE (operands[3]) == LT)"
6227   "*
6228    {
6229      switch (which_alternative)
6230        {
6231        case 0:
6232          output_asm_insn (\"cmp\t%1, #%n2\", operands);
6233          break;
6234        case 1:
6235          output_asm_insn (\"cmn\t%1, %2\", operands);
6236          break;
6237        case 3:
6238          output_asm_insn (\"add\t%0, %1, %2\", operands);
6239          break;
6240        case 4:
6241          output_asm_insn (\"add\t%0, %0, %2\", operands);
6242          break;
6243        }
6244
6245      switch (get_attr_length (insn))
6246        {
6247          case 4:
6248            return \"b%d3\\t%l4\";
6249          case 6:
6250            return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6251          default:
6252            return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6253        }
6254    }
6255   "
6256   [(set (attr "far_jump")
6257         (if_then_else
6258             (eq_attr "length" "8")
6259             (const_string "yes")
6260             (const_string "no")))
6261    (set (attr "length")
6262        (if_then_else
6263          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6264               (le (minus (match_dup 4) (pc)) (const_int 256)))
6265          (const_int 4)
6266          (if_then_else
6267            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6268                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6269            (const_int 6)
6270            (const_int 8))))]
6271 )
6272
6273 (define_insn "*subsi3_cbranch"
6274   [(set (pc)
6275         (if_then_else
6276          (match_operator 4 "comparison_operator"
6277           [(minus:SI
6278             (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6279             (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6280            (const_int 0)])
6281          (label_ref (match_operand 5 "" ""))
6282          (pc)))
6283    (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6284         (minus:SI (match_dup 2) (match_dup 3)))
6285    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6286   "TARGET_THUMB
6287    && (GET_CODE (operands[4]) == EQ
6288        || GET_CODE (operands[4]) == NE
6289        || GET_CODE (operands[4]) == GE
6290        || GET_CODE (operands[4]) == LT)"
6291   "*
6292    {
6293      if (which_alternative == 0)
6294        output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6295      else if (which_alternative == 1)
6296        {
6297          /* We must provide an alternative for a hi reg because reload 
6298             cannot handle output reloads on a jump instruction, but we
6299             can't subtract into that.  Fortunately a mov from lo to hi
6300             does not clobber the condition codes.  */
6301          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6302          output_asm_insn (\"mov\\t%0, %1\", operands);
6303        }
6304      else
6305        {
6306          /* Similarly, but the target is memory.  */
6307          output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6308          output_asm_insn (\"str\\t%1, %0\", operands);
6309        }
6310
6311      switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6312        {
6313          case 4:
6314            return \"b%d4\\t%l5\";
6315          case 6:
6316            return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6317          default:
6318            return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6319        }
6320    }
6321   "
6322   [(set (attr "far_jump")
6323         (if_then_else
6324             (ior (and (eq (symbol_ref ("which_alternative"))
6325                           (const_int 0))
6326                       (eq_attr "length" "8"))
6327                  (eq_attr "length" "10"))
6328             (const_string "yes")
6329             (const_string "no")))
6330    (set (attr "length")
6331      (if_then_else
6332        (eq (symbol_ref ("which_alternative"))
6333                        (const_int 0))
6334        (if_then_else
6335          (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6336               (le (minus (match_dup 5) (pc)) (const_int 256)))
6337          (const_int 4)
6338          (if_then_else
6339            (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6340                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6341            (const_int 6)
6342            (const_int 8)))
6343        (if_then_else
6344          (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6345               (le (minus (match_dup 5) (pc)) (const_int 256)))
6346          (const_int 6)
6347          (if_then_else
6348            (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6349                 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6350            (const_int 8)
6351            (const_int 10)))))]
6352 )
6353
6354 (define_insn "*subsi3_cbranch_scratch"
6355   [(set (pc)
6356         (if_then_else
6357          (match_operator 0 "arm_comparison_operator"
6358           [(minus:SI (match_operand:SI 1 "register_operand" "l")
6359                      (match_operand:SI 2 "nonmemory_operand" "l"))
6360            (const_int 0)])
6361          (label_ref (match_operand 3 "" ""))
6362          (pc)))]
6363   "TARGET_THUMB
6364    && (GET_CODE (operands[0]) == EQ
6365        || GET_CODE (operands[0]) == NE
6366        || GET_CODE (operands[0]) == GE
6367        || GET_CODE (operands[0]) == LT)"
6368   "*
6369   output_asm_insn (\"cmp\\t%1, %2\", operands);
6370   switch (get_attr_length (insn))
6371     {
6372     case 4:  return \"b%d0\\t%l3\";
6373     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6374     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6375     }
6376   "
6377   [(set (attr "far_jump")
6378         (if_then_else
6379             (eq_attr "length" "8")
6380             (const_string "yes")
6381             (const_string "no")))
6382    (set (attr "length") 
6383         (if_then_else
6384             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6385                  (le (minus (match_dup 3) (pc)) (const_int 256)))
6386             (const_int 4)
6387             (if_then_else
6388                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6389                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
6390                 (const_int 6)
6391                 (const_int 8))))]
6392 )
6393
6394 ;; Comparison and test insns
6395
6396 (define_expand "cmpsi"
6397   [(match_operand:SI 0 "s_register_operand" "")
6398    (match_operand:SI 1 "arm_add_operand" "")]
6399   "TARGET_ARM"
6400   "{
6401     arm_compare_op0 = operands[0];
6402     arm_compare_op1 = operands[1];
6403     DONE;
6404   }"
6405 )
6406
6407 (define_expand "cmpsf"
6408   [(match_operand:SF 0 "s_register_operand" "")
6409    (match_operand:SF 1 "fpa_rhs_operand" "")]
6410   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6411   "
6412   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
6413     operands[1] = force_reg (SFmode, operands[1]);
6414
6415   arm_compare_op0 = operands[0];
6416   arm_compare_op1 = operands[1];
6417   DONE;
6418   "
6419 )
6420
6421 (define_expand "cmpdf"
6422   [(match_operand:DF 0 "s_register_operand" "")
6423    (match_operand:DF 1 "fpa_rhs_operand" "")]
6424   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6425   "
6426   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
6427     operands[1] = force_reg (DFmode, operands[1]);
6428
6429   arm_compare_op0 = operands[0];
6430   arm_compare_op1 = operands[1];
6431   DONE;
6432   "
6433 )
6434
6435 (define_insn "*arm_cmpsi_insn"
6436   [(set (reg:CC CC_REGNUM)
6437         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6438                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
6439   "TARGET_ARM"
6440   "@
6441    cmp%?\\t%0, %1
6442    cmn%?\\t%0, #%n1"
6443   [(set_attr "conds" "set")]
6444 )
6445
6446 (define_insn "*cmpsi_shiftsi"
6447   [(set (reg:CC CC_REGNUM)
6448         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
6449                     (match_operator:SI  3 "shift_operator"
6450                      [(match_operand:SI 1 "s_register_operand" "r")
6451                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
6452   "TARGET_ARM"
6453   "cmp%?\\t%0, %1%S3"
6454   [(set_attr "conds" "set")
6455    (set_attr "shift" "1")
6456    ]
6457 )
6458
6459 (define_insn "*cmpsi_shiftsi_swp"
6460   [(set (reg:CC_SWP CC_REGNUM)
6461         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6462                          [(match_operand:SI 1 "s_register_operand" "r")
6463                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
6464                         (match_operand:SI 0 "s_register_operand" "r")))]
6465   "TARGET_ARM"
6466   "cmp%?\\t%0, %1%S3"
6467   [(set_attr "conds" "set")
6468    (set_attr "shift" "1")
6469    ]
6470 )
6471
6472 (define_insn "*cmpsi_neg_shiftsi"
6473   [(set (reg:CC CC_REGNUM)
6474         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6475                     (neg:SI (match_operator:SI 3 "shift_operator"
6476                              [(match_operand:SI 1 "s_register_operand" "r")
6477                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6478   "TARGET_ARM"
6479   "cmn%?\\t%0, %1%S3"
6480   [(set_attr "conds" "set")
6481    (set_attr "shift" "1")
6482    ]
6483 )
6484
6485 ;; Cirrus SF compare instruction
6486 (define_insn "*cirrus_cmpsf"
6487   [(set (reg:CCFP CC_REGNUM)
6488         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6489                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
6490   "TARGET_ARM && TARGET_CIRRUS"
6491   "cfcmps%?\\tr15, %V0, %V1"
6492   [(set_attr "type"   "mav_farith")
6493    (set_attr "cirrus" "compare")]
6494 )
6495
6496 ;; Cirrus DF compare instruction
6497 (define_insn "*cirrus_cmpdf"
6498   [(set (reg:CCFP CC_REGNUM)
6499         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6500                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
6501   "TARGET_ARM && TARGET_CIRRUS"
6502   "cfcmpd%?\\tr15, %V0, %V1"
6503   [(set_attr "type"   "mav_farith")
6504    (set_attr "cirrus" "compare")]
6505 )
6506
6507 ;; Cirrus DI compare instruction
6508 (define_expand "cmpdi"
6509   [(match_operand:DI 0 "cirrus_fp_register" "")
6510    (match_operand:DI 1 "cirrus_fp_register" "")]
6511   "TARGET_ARM && TARGET_CIRRUS"
6512   "{
6513      arm_compare_op0 = operands[0];
6514      arm_compare_op1 = operands[1];
6515      DONE;
6516    }")
6517
6518 (define_insn "*cirrus_cmpdi"
6519   [(set (reg:CC CC_REGNUM)
6520         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6521                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
6522   "TARGET_ARM && TARGET_CIRRUS"
6523   "cfcmp64%?\\tr15, %V0, %V1"
6524   [(set_attr "type"   "mav_farith")
6525    (set_attr "cirrus" "compare")]
6526 )
6527
6528 ; This insn allows redundant compares to be removed by cse, nothing should
6529 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6530 ; is deleted later on. The match_dup will match the mode here, so that
6531 ; mode changes of the condition codes aren't lost by this even though we don't
6532 ; specify what they are.
6533
6534 (define_insn "*deleted_compare"
6535   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6536   "TARGET_ARM"
6537   "\\t%@ deleted compare"
6538   [(set_attr "conds" "set")
6539    (set_attr "length" "0")]
6540 )
6541
6542 \f
6543 ;; Conditional branch insns
6544
6545 (define_expand "beq"
6546   [(set (pc)
6547         (if_then_else (eq (match_dup 1) (const_int 0))
6548                       (label_ref (match_operand 0 "" ""))
6549                       (pc)))]
6550   "TARGET_ARM"
6551   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6552 )
6553
6554 (define_expand "bne"
6555   [(set (pc)
6556         (if_then_else (ne (match_dup 1) (const_int 0))
6557                       (label_ref (match_operand 0 "" ""))
6558                       (pc)))]
6559   "TARGET_ARM"
6560   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6561 )
6562
6563 (define_expand "bgt"
6564   [(set (pc)
6565         (if_then_else (gt (match_dup 1) (const_int 0))
6566                       (label_ref (match_operand 0 "" ""))
6567                       (pc)))]
6568   "TARGET_ARM"
6569   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6570 )
6571
6572 (define_expand "ble"
6573   [(set (pc)
6574         (if_then_else (le (match_dup 1) (const_int 0))
6575                       (label_ref (match_operand 0 "" ""))
6576                       (pc)))]
6577   "TARGET_ARM"
6578   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6579 )
6580
6581 (define_expand "bge"
6582   [(set (pc)
6583         (if_then_else (ge (match_dup 1) (const_int 0))
6584                       (label_ref (match_operand 0 "" ""))
6585                       (pc)))]
6586   "TARGET_ARM"
6587   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6588 )
6589
6590 (define_expand "blt"
6591   [(set (pc)
6592         (if_then_else (lt (match_dup 1) (const_int 0))
6593                       (label_ref (match_operand 0 "" ""))
6594                       (pc)))]
6595   "TARGET_ARM"
6596   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6597 )
6598
6599 (define_expand "bgtu"
6600   [(set (pc)
6601         (if_then_else (gtu (match_dup 1) (const_int 0))
6602                       (label_ref (match_operand 0 "" ""))
6603                       (pc)))]
6604   "TARGET_ARM"
6605   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6606 )
6607
6608 (define_expand "bleu"
6609   [(set (pc)
6610         (if_then_else (leu (match_dup 1) (const_int 0))
6611                       (label_ref (match_operand 0 "" ""))
6612                       (pc)))]
6613   "TARGET_ARM"
6614   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6615 )
6616
6617 (define_expand "bgeu"
6618   [(set (pc)
6619         (if_then_else (geu (match_dup 1) (const_int 0))
6620                       (label_ref (match_operand 0 "" ""))
6621                       (pc)))]
6622   "TARGET_ARM"
6623   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6624 )
6625
6626 (define_expand "bltu"
6627   [(set (pc)
6628         (if_then_else (ltu (match_dup 1) (const_int 0))
6629                       (label_ref (match_operand 0 "" ""))
6630                       (pc)))]
6631   "TARGET_ARM"
6632   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6633 )
6634
6635 (define_expand "bunordered"
6636   [(set (pc)
6637         (if_then_else (unordered (match_dup 1) (const_int 0))
6638                       (label_ref (match_operand 0 "" ""))
6639                       (pc)))]
6640   "TARGET_ARM && TARGET_HARD_FLOAT"
6641   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6642                                       arm_compare_op1);"
6643 )
6644
6645 (define_expand "bordered"
6646   [(set (pc)
6647         (if_then_else (ordered (match_dup 1) (const_int 0))
6648                       (label_ref (match_operand 0 "" ""))
6649                       (pc)))]
6650   "TARGET_ARM && TARGET_HARD_FLOAT"
6651   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6652                                       arm_compare_op1);"
6653 )
6654
6655 (define_expand "bungt"
6656   [(set (pc)
6657         (if_then_else (ungt (match_dup 1) (const_int 0))
6658                       (label_ref (match_operand 0 "" ""))
6659                       (pc)))]
6660   "TARGET_ARM && TARGET_HARD_FLOAT"
6661   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6662 )
6663
6664 (define_expand "bunlt"
6665   [(set (pc)
6666         (if_then_else (unlt (match_dup 1) (const_int 0))
6667                       (label_ref (match_operand 0 "" ""))
6668                       (pc)))]
6669   "TARGET_ARM && TARGET_HARD_FLOAT"
6670   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6671 )
6672
6673 (define_expand "bunge"
6674   [(set (pc)
6675         (if_then_else (unge (match_dup 1) (const_int 0))
6676                       (label_ref (match_operand 0 "" ""))
6677                       (pc)))]
6678   "TARGET_ARM && TARGET_HARD_FLOAT"
6679   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6680 )
6681
6682 (define_expand "bunle"
6683   [(set (pc)
6684         (if_then_else (unle (match_dup 1) (const_int 0))
6685                       (label_ref (match_operand 0 "" ""))
6686                       (pc)))]
6687   "TARGET_ARM && TARGET_HARD_FLOAT"
6688   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6689 )
6690
6691 ;; The following two patterns need two branch instructions, since there is
6692 ;; no single instruction that will handle all cases.
6693 (define_expand "buneq"
6694   [(set (pc)
6695         (if_then_else (uneq (match_dup 1) (const_int 0))
6696                       (label_ref (match_operand 0 "" ""))
6697                       (pc)))]
6698   "TARGET_ARM && TARGET_HARD_FLOAT"
6699   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6700 )
6701
6702 (define_expand "bltgt"
6703   [(set (pc)
6704         (if_then_else (ltgt (match_dup 1) (const_int 0))
6705                       (label_ref (match_operand 0 "" ""))
6706                       (pc)))]
6707   "TARGET_ARM && TARGET_HARD_FLOAT"
6708   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6709 )
6710
6711 ;;
6712 ;; Patterns to match conditional branch insns.
6713 ;;
6714
6715 ; Special pattern to match UNEQ.
6716 (define_insn "*arm_buneq"
6717   [(set (pc)
6718         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6719                       (label_ref (match_operand 0 "" ""))
6720                       (pc)))]
6721   "TARGET_ARM && TARGET_HARD_FLOAT"
6722   "*
6723   if (arm_ccfsm_state != 0)
6724     abort ();
6725
6726   return \"bvs\\t%l0\;beq\\t%l0\";
6727   "
6728   [(set_attr "conds" "jump_clob")
6729    (set_attr "length" "8")]
6730 )
6731
6732 ; Special pattern to match LTGT.
6733 (define_insn "*arm_bltgt"
6734   [(set (pc)
6735         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6736                       (label_ref (match_operand 0 "" ""))
6737                       (pc)))]
6738   "TARGET_ARM && TARGET_HARD_FLOAT"
6739   "*
6740   if (arm_ccfsm_state != 0)
6741     abort ();
6742
6743   return \"bmi\\t%l0\;bgt\\t%l0\";
6744   "
6745   [(set_attr "conds" "jump_clob")
6746    (set_attr "length" "8")]
6747 )
6748
6749 (define_insn "*arm_cond_branch"
6750   [(set (pc)
6751         (if_then_else (match_operator 1 "arm_comparison_operator"
6752                        [(match_operand 2 "cc_register" "") (const_int 0)])
6753                       (label_ref (match_operand 0 "" ""))
6754                       (pc)))]
6755   "TARGET_ARM"
6756   "*
6757   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6758     {
6759       arm_ccfsm_state += 2;
6760       return \"\";
6761     }
6762   return \"b%d1\\t%l0\";
6763   "
6764   [(set_attr "conds" "use")]
6765 )
6766
6767 ; Special pattern to match reversed UNEQ.
6768 (define_insn "*arm_buneq_reversed"
6769   [(set (pc)
6770         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6771                       (pc)
6772                       (label_ref (match_operand 0 "" ""))))]
6773   "TARGET_ARM && TARGET_HARD_FLOAT"
6774   "*
6775   if (arm_ccfsm_state != 0)
6776     abort ();
6777
6778   return \"bmi\\t%l0\;bgt\\t%l0\";
6779   "
6780   [(set_attr "conds" "jump_clob")
6781    (set_attr "length" "8")]
6782 )
6783
6784 ; Special pattern to match reversed LTGT.
6785 (define_insn "*arm_bltgt_reversed"
6786   [(set (pc)
6787         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6788                       (pc)
6789                       (label_ref (match_operand 0 "" ""))))]
6790   "TARGET_ARM && TARGET_HARD_FLOAT"
6791   "*
6792   if (arm_ccfsm_state != 0)
6793     abort ();
6794
6795   return \"bvs\\t%l0\;beq\\t%l0\";
6796   "
6797   [(set_attr "conds" "jump_clob")
6798    (set_attr "length" "8")]
6799 )
6800
6801 (define_insn "*arm_cond_branch_reversed"
6802   [(set (pc)
6803         (if_then_else (match_operator 1 "arm_comparison_operator"
6804                        [(match_operand 2 "cc_register" "") (const_int 0)])
6805                       (pc)
6806                       (label_ref (match_operand 0 "" ""))))]
6807   "TARGET_ARM"
6808   "*
6809   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6810     {
6811       arm_ccfsm_state += 2;
6812       return \"\";
6813     }
6814   return \"b%D1\\t%l0\";
6815   "
6816   [(set_attr "conds" "use")]
6817 )
6818
6819 \f
6820
6821 ; scc insns
6822
6823 (define_expand "seq"
6824   [(set (match_operand:SI 0 "s_register_operand" "")
6825         (eq:SI (match_dup 1) (const_int 0)))]
6826   "TARGET_ARM"
6827   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6828 )
6829
6830 (define_expand "sne"
6831   [(set (match_operand:SI 0 "s_register_operand" "")
6832         (ne:SI (match_dup 1) (const_int 0)))]
6833   "TARGET_ARM"
6834   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6835 )
6836
6837 (define_expand "sgt"
6838   [(set (match_operand:SI 0 "s_register_operand" "")
6839         (gt:SI (match_dup 1) (const_int 0)))]
6840   "TARGET_ARM"
6841   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6842 )
6843
6844 (define_expand "sle"
6845   [(set (match_operand:SI 0 "s_register_operand" "")
6846         (le:SI (match_dup 1) (const_int 0)))]
6847   "TARGET_ARM"
6848   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6849 )
6850
6851 (define_expand "sge"
6852   [(set (match_operand:SI 0 "s_register_operand" "")
6853         (ge:SI (match_dup 1) (const_int 0)))]
6854   "TARGET_ARM"
6855   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6856 )
6857
6858 (define_expand "slt"
6859   [(set (match_operand:SI 0 "s_register_operand" "")
6860         (lt:SI (match_dup 1) (const_int 0)))]
6861   "TARGET_ARM"
6862   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6863 )
6864
6865 (define_expand "sgtu"
6866   [(set (match_operand:SI 0 "s_register_operand" "")
6867         (gtu:SI (match_dup 1) (const_int 0)))]
6868   "TARGET_ARM"
6869   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6870 )
6871
6872 (define_expand "sleu"
6873   [(set (match_operand:SI 0 "s_register_operand" "")
6874         (leu:SI (match_dup 1) (const_int 0)))]
6875   "TARGET_ARM"
6876   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6877 )
6878
6879 (define_expand "sgeu"
6880   [(set (match_operand:SI 0 "s_register_operand" "")
6881         (geu:SI (match_dup 1) (const_int 0)))]
6882   "TARGET_ARM"
6883   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6884 )
6885
6886 (define_expand "sltu"
6887   [(set (match_operand:SI 0 "s_register_operand" "")
6888         (ltu:SI (match_dup 1) (const_int 0)))]
6889   "TARGET_ARM"
6890   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6891 )
6892
6893 (define_expand "sunordered"
6894   [(set (match_operand:SI 0 "s_register_operand" "")
6895         (unordered:SI (match_dup 1) (const_int 0)))]
6896   "TARGET_ARM && TARGET_HARD_FLOAT"
6897   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6898                                       arm_compare_op1);"
6899 )
6900
6901 (define_expand "sordered"
6902   [(set (match_operand:SI 0 "s_register_operand" "")
6903         (ordered:SI (match_dup 1) (const_int 0)))]
6904   "TARGET_ARM && TARGET_HARD_FLOAT"
6905   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6906                                       arm_compare_op1);"
6907 )
6908
6909 (define_expand "sungt"
6910   [(set (match_operand:SI 0 "s_register_operand" "")
6911         (ungt:SI (match_dup 1) (const_int 0)))]
6912   "TARGET_ARM && TARGET_HARD_FLOAT"
6913   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6914                                       arm_compare_op1);"
6915 )
6916
6917 (define_expand "sunge"
6918   [(set (match_operand:SI 0 "s_register_operand" "")
6919         (unge:SI (match_dup 1) (const_int 0)))]
6920   "TARGET_ARM && TARGET_HARD_FLOAT"
6921   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6922                                       arm_compare_op1);"
6923 )
6924
6925 (define_expand "sunlt"
6926   [(set (match_operand:SI 0 "s_register_operand" "")
6927         (unlt:SI (match_dup 1) (const_int 0)))]
6928   "TARGET_ARM && TARGET_HARD_FLOAT"
6929   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6930                                       arm_compare_op1);"
6931 )
6932
6933 (define_expand "sunle"
6934   [(set (match_operand:SI 0 "s_register_operand" "")
6935         (unle:SI (match_dup 1) (const_int 0)))]
6936   "TARGET_ARM && TARGET_HARD_FLOAT"
6937   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6938                                       arm_compare_op1);"
6939 )
6940
6941 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6942 ;;; simple ARM instructions. 
6943 ;
6944 ; (define_expand "suneq"
6945 ;   [(set (match_operand:SI 0 "s_register_operand" "")
6946 ;       (uneq:SI (match_dup 1) (const_int 0)))]
6947 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6948 ;   "abort ();"
6949 ; )
6950 ;
6951 ; (define_expand "sltgt"
6952 ;   [(set (match_operand:SI 0 "s_register_operand" "")
6953 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
6954 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6955 ;   "abort ();"
6956 ; )
6957
6958 (define_insn "*mov_scc"
6959   [(set (match_operand:SI 0 "s_register_operand" "=r")
6960         (match_operator:SI 1 "arm_comparison_operator"
6961          [(match_operand 2 "cc_register" "") (const_int 0)]))]
6962   "TARGET_ARM"
6963   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6964   [(set_attr "conds" "use")
6965    (set_attr "length" "8")]
6966 )
6967
6968 (define_insn "*mov_negscc"
6969   [(set (match_operand:SI 0 "s_register_operand" "=r")
6970         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6971                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6972   "TARGET_ARM"
6973   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6974   [(set_attr "conds" "use")
6975    (set_attr "length" "8")]
6976 )
6977
6978 (define_insn "*mov_notscc"
6979   [(set (match_operand:SI 0 "s_register_operand" "=r")
6980         (not:SI (match_operator:SI 1 "arm_comparison_operator"
6981                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6982   "TARGET_ARM"
6983   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6984   [(set_attr "conds" "use")
6985    (set_attr "length" "8")]
6986 )
6987
6988 \f
6989 ;; Conditional move insns
6990
6991 (define_expand "movsicc"
6992   [(set (match_operand:SI 0 "s_register_operand" "")
6993         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6994                          (match_operand:SI 2 "arm_not_operand" "")
6995                          (match_operand:SI 3 "arm_not_operand" "")))]
6996   "TARGET_ARM"
6997   "
6998   {
6999     enum rtx_code code = GET_CODE (operands[1]);
7000     rtx ccreg;
7001
7002     if (code == UNEQ || code == LTGT)
7003       FAIL;
7004
7005     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7006     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7007   }"
7008 )
7009
7010 (define_expand "movsfcc"
7011   [(set (match_operand:SF 0 "s_register_operand" "")
7012         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7013                          (match_operand:SF 2 "s_register_operand" "")
7014                          (match_operand:SF 3 "nonmemory_operand" "")))]
7015   "TARGET_ARM"
7016   "
7017   {
7018     enum rtx_code code = GET_CODE (operands[1]);
7019     rtx ccreg;
7020
7021     if (code == UNEQ || code == LTGT)
7022       FAIL;
7023
7024     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
7025        Otherwise, ensure it is a valid FP add operand.  */
7026     if ((!TARGET_HARD_FLOAT)
7027         || (!fpa_add_operand (operands[3], SFmode)))
7028       operands[3] = force_reg (SFmode, operands[3]);
7029
7030     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7031     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7032   }"
7033 )
7034
7035 (define_expand "movdfcc"
7036   [(set (match_operand:DF 0 "s_register_operand" "")
7037         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7038                          (match_operand:DF 2 "s_register_operand" "")
7039                          (match_operand:DF 3 "fpa_add_operand" "")))]
7040   "TARGET_ARM && TARGET_HARD_FLOAT"
7041   "
7042   {
7043     enum rtx_code code = GET_CODE (operands[1]);
7044     rtx ccreg;
7045
7046     if (code == UNEQ || code == LTGT)
7047       FAIL;
7048
7049     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7050     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7051   }"
7052 )
7053
7054 (define_insn "*movsicc_insn"
7055   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7056         (if_then_else:SI
7057          (match_operator 3 "arm_comparison_operator"
7058           [(match_operand 4 "cc_register" "") (const_int 0)])
7059          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7060          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7061   "TARGET_ARM"
7062   "@
7063    mov%D3\\t%0, %2
7064    mvn%D3\\t%0, #%B2
7065    mov%d3\\t%0, %1
7066    mvn%d3\\t%0, #%B1
7067    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7068    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7069    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7070    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7071   [(set_attr "length" "4,4,4,4,8,8,8,8")
7072    (set_attr "conds" "use")]
7073 )
7074
7075 (define_insn "*movsfcc_soft_insn"
7076   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7077         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7078                           [(match_operand 4 "cc_register" "") (const_int 0)])
7079                          (match_operand:SF 1 "s_register_operand" "0,r")
7080                          (match_operand:SF 2 "s_register_operand" "r,0")))]
7081   "TARGET_ARM && TARGET_SOFT_FLOAT"
7082   "@
7083    mov%D3\\t%0, %2
7084    mov%d3\\t%0, %1"
7085   [(set_attr "conds" "use")]
7086 )
7087
7088 \f
7089 ;; Jump and linkage insns
7090
7091 (define_expand "jump"
7092   [(set (pc)
7093         (label_ref (match_operand 0 "" "")))]
7094   "TARGET_EITHER"
7095   ""
7096 )
7097
7098 (define_insn "*arm_jump"
7099   [(set (pc)
7100         (label_ref (match_operand 0 "" "")))]
7101   "TARGET_ARM"
7102   "*
7103   {
7104     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7105       {
7106         arm_ccfsm_state += 2;
7107         return \"\";
7108       }
7109     return \"b%?\\t%l0\";
7110   }
7111   "
7112   [(set_attr "predicable" "yes")]
7113 )
7114
7115 (define_insn "*thumb_jump"
7116   [(set (pc)
7117         (label_ref (match_operand 0 "" "")))]
7118   "TARGET_THUMB"
7119   "*
7120   if (get_attr_length (insn) == 2)
7121     return \"b\\t%l0\";
7122   return \"bl\\t%l0\\t%@ far jump\";
7123   "
7124   [(set (attr "far_jump")
7125         (if_then_else
7126             (eq_attr "length" "4")
7127             (const_string "yes")
7128             (const_string "no")))
7129    (set (attr "length") 
7130         (if_then_else
7131             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
7132                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
7133             (const_int 2)
7134             (const_int 4)))]
7135 )
7136
7137 (define_expand "call"
7138   [(parallel [(call (match_operand 0 "memory_operand" "")
7139                     (match_operand 1 "general_operand" ""))
7140               (use (match_operand 2 "" ""))
7141               (clobber (reg:SI LR_REGNUM))])]
7142   "TARGET_EITHER"
7143   "
7144   {
7145     rtx callee;
7146     
7147     /* In an untyped call, we can get NULL for operand 2.  */
7148     if (operands[2] == NULL_RTX)
7149       operands[2] = const0_rtx;
7150       
7151     /* This is to decide if we should generate indirect calls by loading the
7152        32 bit address of the callee into a register before performing the
7153        branch and link.  operand[2] encodes the long_call/short_call
7154        attribute of the function being called.  This attribute is set whenever
7155        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7156        is used, and the short_call attribute can also be set if function is
7157        declared as static or if it has already been defined in the current
7158        compilation unit.  See arm.c and arm.h for info about this.  The third
7159        parameter to arm_is_longcall_p is used to tell it which pattern
7160        invoked it.  */
7161     callee  = XEXP (operands[0], 0);
7162     
7163     if (GET_CODE (callee) != REG
7164        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7165       XEXP (operands[0], 0) = force_reg (Pmode, callee);
7166   }"
7167 )
7168
7169 (define_insn "*call_reg"
7170   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7171          (match_operand 1 "" ""))
7172    (use (match_operand 2 "" ""))
7173    (clobber (reg:SI LR_REGNUM))]
7174   "TARGET_ARM"
7175   "*
7176   return output_call (operands);
7177   "
7178   ;; length is worst case, normally it is only two
7179   [(set_attr "length" "12")
7180    (set_attr "type" "call")]
7181 )
7182
7183 (define_insn "*call_mem"
7184   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7185          (match_operand 1 "" ""))
7186    (use (match_operand 2 "" ""))
7187    (clobber (reg:SI LR_REGNUM))]
7188   "TARGET_ARM"
7189   "*
7190   return output_call_mem (operands);
7191   "
7192   [(set_attr "length" "12")
7193    (set_attr "type" "call")]
7194 )
7195
7196 (define_insn "*call_indirect"
7197   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7198          (match_operand 1 "" ""))
7199    (use (match_operand 2 "" ""))
7200    (clobber (reg:SI LR_REGNUM))]
7201   "TARGET_THUMB"
7202   "*
7203   {
7204     if (TARGET_CALLER_INTERWORKING)
7205       return \"bl\\t%__interwork_call_via_%0\";
7206     else
7207       return \"bl\\t%__call_via_%0\";
7208   }"
7209   [(set_attr "type" "call")]
7210 )
7211
7212 (define_insn "*call_value_indirect"
7213   [(set (match_operand 0 "" "")
7214         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7215               (match_operand 2 "" "")))
7216    (use (match_operand 3 "" ""))
7217    (clobber (reg:SI LR_REGNUM))]
7218   "TARGET_THUMB"
7219   "*
7220   {
7221     if (TARGET_CALLER_INTERWORKING)
7222       return \"bl\\t%__interwork_call_via_%1\";
7223     else
7224       return \"bl\\t%__call_via_%1\";
7225   }"
7226   [(set_attr "type" "call")]
7227 )
7228
7229 (define_expand "call_value"
7230   [(parallel [(set (match_operand       0 "" "")
7231                    (call (match_operand 1 "memory_operand" "")
7232                          (match_operand 2 "general_operand" "")))
7233               (use (match_operand 3 "" ""))
7234               (clobber (reg:SI LR_REGNUM))])]
7235   "TARGET_EITHER"
7236   "
7237   {
7238     rtx callee = XEXP (operands[1], 0);
7239     
7240     /* In an untyped call, we can get NULL for operand 2.  */
7241     if (operands[3] == 0)
7242       operands[3] = const0_rtx;
7243       
7244     /* See the comment in define_expand \"call\".  */
7245     if (GET_CODE (callee) != REG
7246         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7247       XEXP (operands[1], 0) = force_reg (Pmode, callee);
7248   }"
7249 )
7250
7251 (define_insn "*call_value_reg"
7252   [(set (match_operand 0 "" "")
7253         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7254               (match_operand 2 "" "")))
7255    (use (match_operand 3 "" ""))
7256    (clobber (reg:SI LR_REGNUM))]
7257   "TARGET_ARM"
7258   "*
7259   return output_call (&operands[1]);
7260   "
7261   [(set_attr "length" "12")
7262    (set_attr "type" "call")]
7263 )
7264
7265 (define_insn "*call_value_mem"
7266   [(set (match_operand 0 "" "")
7267         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7268               (match_operand 2 "" "")))
7269    (use (match_operand 3 "" ""))
7270    (clobber (reg:SI LR_REGNUM))]
7271   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7272   "*
7273   return output_call_mem (&operands[1]);
7274   "
7275   [(set_attr "length" "12")
7276    (set_attr "type" "call")]
7277 )
7278
7279 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7280 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7281
7282 (define_insn "*call_symbol"
7283   [(call (mem:SI (match_operand:SI 0 "" ""))
7284          (match_operand 1 "" ""))
7285    (use (match_operand 2 "" ""))
7286    (clobber (reg:SI LR_REGNUM))]
7287   "TARGET_ARM
7288    && (GET_CODE (operands[0]) == SYMBOL_REF)
7289    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7290   "*
7291   {
7292     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7293   }"
7294   [(set_attr "type" "call")]
7295 )
7296
7297 (define_insn "*call_value_symbol"
7298   [(set (match_operand 0 "s_register_operand" "")
7299         (call (mem:SI (match_operand:SI 1 "" ""))
7300         (match_operand:SI 2 "" "")))
7301    (use (match_operand 3 "" ""))
7302    (clobber (reg:SI LR_REGNUM))]
7303   "TARGET_ARM
7304    && (GET_CODE (operands[1]) == SYMBOL_REF)
7305    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7306   "*
7307   {
7308     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7309   }"
7310   [(set_attr "type" "call")]
7311 )
7312
7313 (define_insn "*call_insn"
7314   [(call (mem:SI (match_operand:SI 0 "" ""))
7315          (match_operand:SI 1 "" ""))
7316    (use (match_operand 2 "" ""))
7317    (clobber (reg:SI LR_REGNUM))]
7318   "TARGET_THUMB
7319    && GET_CODE (operands[0]) == SYMBOL_REF
7320    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7321   "bl\\t%a0"
7322   [(set_attr "length" "4")
7323    (set_attr "type" "call")]
7324 )
7325
7326 (define_insn "*call_value_insn"
7327   [(set (match_operand 0 "register_operand" "")
7328         (call (mem:SI (match_operand 1 "" ""))
7329               (match_operand 2 "" "")))
7330    (use (match_operand 3 "" ""))
7331    (clobber (reg:SI LR_REGNUM))]
7332   "TARGET_THUMB
7333    && GET_CODE (operands[1]) == SYMBOL_REF
7334    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7335   "bl\\t%a1"
7336   [(set_attr "length" "4")
7337    (set_attr "type" "call")]
7338 )
7339
7340 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7341 (define_expand "sibcall"
7342   [(parallel [(call (match_operand 0 "memory_operand" "")
7343                     (match_operand 1 "general_operand" ""))
7344               (return)
7345               (use (match_operand 2 "" ""))])]
7346   "TARGET_ARM"
7347   "
7348   {
7349     if (operands[2] == NULL_RTX)
7350       operands[2] = const0_rtx;
7351   }"
7352 )
7353
7354 (define_expand "sibcall_value"
7355   [(parallel [(set (match_operand 0 "register_operand" "")
7356                    (call (match_operand 1 "memory_operand" "")
7357                          (match_operand 2 "general_operand" "")))
7358               (return)
7359               (use (match_operand 3 "" ""))])]
7360   "TARGET_ARM"
7361   "
7362   {
7363     if (operands[3] == NULL_RTX)
7364       operands[3] = const0_rtx;
7365   }"
7366 )
7367
7368 (define_insn "*sibcall_insn"
7369  [(call (mem:SI (match_operand:SI 0 "" "X"))
7370         (match_operand 1 "" ""))
7371   (return)
7372   (use (match_operand 2 "" ""))]
7373   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7374   "*
7375   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7376   "
7377   [(set_attr "type" "call")]
7378 )
7379
7380 (define_insn "*sibcall_value_insn"
7381  [(set (match_operand 0 "s_register_operand" "")
7382        (call (mem:SI (match_operand:SI 1 "" "X"))
7383              (match_operand 2 "" "")))
7384   (return)
7385   (use (match_operand 3 "" ""))]
7386   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7387   "*
7388   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7389   "
7390   [(set_attr "type" "call")]
7391 )
7392
7393 ;; Often the return insn will be the same as loading from memory, so set attr
7394 (define_insn "return"
7395   [(return)]
7396   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7397   "*
7398   {
7399     if (arm_ccfsm_state == 2)
7400       {
7401         arm_ccfsm_state += 2;
7402         return \"\";
7403       }
7404     return output_return_instruction (const_true_rtx, TRUE, FALSE);
7405   }"
7406   [(set_attr "type" "load")
7407    (set_attr "length" "12")
7408    (set_attr "predicable" "yes")]
7409 )
7410
7411 (define_insn "*cond_return"
7412   [(set (pc)
7413         (if_then_else (match_operator 0 "arm_comparison_operator"
7414                        [(match_operand 1 "cc_register" "") (const_int 0)])
7415                       (return)
7416                       (pc)))]
7417   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7418   "*
7419   {
7420     if (arm_ccfsm_state == 2)
7421       {
7422         arm_ccfsm_state += 2;
7423         return \"\";
7424       }
7425     return output_return_instruction (operands[0], TRUE, FALSE);
7426   }"
7427   [(set_attr "conds" "use")
7428    (set_attr "length" "12")
7429    (set_attr "type" "load")]
7430 )
7431
7432 (define_insn "*cond_return_inverted"
7433   [(set (pc)
7434         (if_then_else (match_operator 0 "arm_comparison_operator"
7435                        [(match_operand 1 "cc_register" "") (const_int 0)])
7436                       (pc)
7437                       (return)))]
7438   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7439   "*
7440   {
7441     if (arm_ccfsm_state == 2)
7442       {
7443         arm_ccfsm_state += 2;
7444         return \"\";
7445       }
7446     return output_return_instruction (operands[0], TRUE, TRUE);
7447   }"
7448   [(set_attr "conds" "use")
7449    (set_attr "type" "load")]
7450 )
7451
7452 ;; Generate a sequence of instructions to determine if the processor is
7453 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7454 ;; mask.
7455
7456 (define_expand "return_addr_mask"
7457   [(set (match_dup 1)
7458       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7459                        (const_int 0)))
7460    (set (match_operand:SI 0 "s_register_operand" "")
7461       (if_then_else:SI (eq (match_dup 1) (const_int 0))
7462                        (const_int -1)
7463                        (const_int 67108860)))] ; 0x03fffffc
7464   "TARGET_ARM"
7465   "
7466   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7467   ")
7468
7469 (define_insn "*check_arch2"
7470   [(set (match_operand:CC_NOOV 0 "cc_register" "")
7471       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7472                        (const_int 0)))]
7473   "TARGET_ARM"
7474   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7475   [(set_attr "length" "8")
7476    (set_attr "conds" "set")]
7477 )
7478
7479 ;; Call subroutine returning any type.
7480
7481 (define_expand "untyped_call"
7482   [(parallel [(call (match_operand 0 "" "")
7483                     (const_int 0))
7484               (match_operand 1 "" "")
7485               (match_operand 2 "" "")])]
7486   "TARGET_ARM"
7487   "
7488   {
7489     int i;
7490
7491     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7492
7493     for (i = 0; i < XVECLEN (operands[2], 0); i++)
7494       {
7495         rtx set = XVECEXP (operands[2], 0, i);
7496
7497         emit_move_insn (SET_DEST (set), SET_SRC (set));
7498       }
7499
7500     /* The optimizer does not know that the call sets the function value
7501        registers we stored in the result block.  We avoid problems by
7502        claiming that all hard registers are used and clobbered at this
7503        point.  */
7504     emit_insn (gen_blockage ());
7505
7506     DONE;
7507   }"
7508 )
7509
7510 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7511 ;; all of memory.  This blocks insns from being moved across this point.
7512
7513 (define_insn "blockage"
7514   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7515   "TARGET_EITHER"
7516   ""
7517   [(set_attr "length" "0")
7518    (set_attr "type" "block")]
7519 )
7520
7521 (define_expand "casesi"
7522   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7523    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
7524    (match_operand:SI 2 "const_int_operand" "")  ; total range
7525    (match_operand:SI 3 "" "")                   ; table label
7526    (match_operand:SI 4 "" "")]                  ; Out of range label
7527   "TARGET_ARM"
7528   "
7529   {
7530     rtx reg;
7531     if (operands[1] != const0_rtx)
7532       {
7533         reg = gen_reg_rtx (SImode);
7534
7535         emit_insn (gen_addsi3 (reg, operands[0],
7536                                GEN_INT (-INTVAL (operands[1]))));
7537         operands[0] = reg;
7538       }
7539
7540     if (!const_ok_for_arm (INTVAL (operands[2])))
7541       operands[2] = force_reg (SImode, operands[2]);
7542
7543     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7544                                          operands[4]));
7545     DONE;
7546   }"
7547 )
7548
7549 ;; The USE in this pattern is needed to tell flow analysis that this is
7550 ;; a CASESI insn.  It has no other purpose.
7551 (define_insn "casesi_internal"
7552   [(parallel [(set (pc)
7553                (if_then_else
7554                 (leu (match_operand:SI 0 "s_register_operand" "r")
7555                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
7556                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7557                                  (label_ref (match_operand 2 "" ""))))
7558                 (label_ref (match_operand 3 "" ""))))
7559               (clobber (reg:CC CC_REGNUM))
7560               (use (label_ref (match_dup 2)))])]
7561   "TARGET_ARM"
7562   "*
7563     if (flag_pic)
7564       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7565     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7566   "
7567   [(set_attr "conds" "clob")
7568    (set_attr "length" "12")]
7569 )
7570
7571 (define_expand "indirect_jump"
7572   [(set (pc)
7573         (match_operand:SI 0 "s_register_operand" ""))]
7574   "TARGET_EITHER"
7575   ""
7576 )
7577
7578 (define_insn "*arm_indirect_jump"
7579   [(set (pc)
7580         (match_operand:SI 0 "s_register_operand" "r"))]
7581   "TARGET_ARM"
7582   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7583   [(set_attr "predicable" "yes")]
7584 )
7585
7586 ;; Although not supported by the define_expand above,
7587 ;; cse/combine may generate this form.
7588 (define_insn "*load_indirect_jump"
7589   [(set (pc)
7590         (match_operand:SI 0 "memory_operand" "m"))]
7591   "TARGET_ARM"
7592   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7593   [(set_attr "type" "load")
7594    (set_attr "pool_range" "4096")
7595    (set_attr "neg_pool_range" "4084")
7596    (set_attr "predicable" "yes")]
7597 )
7598
7599 (define_insn "*thumb_indirect_jump"
7600   [(set (pc)
7601         (match_operand:SI 0 "register_operand" "l*r"))]
7602   "TARGET_THUMB"
7603   "mov\\tpc, %0"
7604   [(set_attr "conds" "clob")
7605    (set_attr "length" "2")]
7606 )
7607
7608 \f
7609 ;; Misc insns
7610
7611 (define_insn "nop"
7612   [(const_int 0)]
7613   "TARGET_EITHER"
7614   "*
7615   if (TARGET_ARM)
7616     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7617   return  \"mov\\tr8, r8\";
7618   "
7619   [(set (attr "length")
7620         (if_then_else (eq_attr "is_thumb" "yes")
7621                       (const_int 2)
7622                       (const_int 4)))]
7623 )
7624
7625 \f
7626 ;; Patterns to allow combination of arithmetic, cond code and shifts
7627
7628 (define_insn "*arith_shiftsi"
7629   [(set (match_operand:SI 0 "s_register_operand" "=r")
7630         (match_operator:SI 1 "shiftable_operator"
7631           [(match_operator:SI 3 "shift_operator"
7632              [(match_operand:SI 4 "s_register_operand" "r")
7633               (match_operand:SI 5 "reg_or_int_operand" "rI")])
7634            (match_operand:SI 2 "s_register_operand" "r")]))]
7635   "TARGET_ARM"
7636   "%i1%?\\t%0, %2, %4%S3"
7637   [(set_attr "predicable" "yes")
7638    (set_attr "shift" "4")
7639    ]
7640 )
7641
7642 (define_split
7643   [(set (match_operand:SI 0 "s_register_operand" "")
7644         (match_operator:SI 1 "shiftable_operator"
7645          [(match_operator:SI 2 "shiftable_operator"
7646            [(match_operator:SI 3 "shift_operator"
7647              [(match_operand:SI 4 "s_register_operand" "")
7648               (match_operand:SI 5 "reg_or_int_operand" "")])
7649             (match_operand:SI 6 "s_register_operand" "")])
7650           (match_operand:SI 7 "arm_rhs_operand" "")]))
7651    (clobber (match_operand:SI 8 "s_register_operand" ""))]
7652   "TARGET_ARM"
7653   [(set (match_dup 8)
7654         (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7655                          (match_dup 6)]))
7656    (set (match_dup 0)
7657         (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7658   "")
7659
7660 (define_insn "*arith_shiftsi_compare0"
7661   [(set (reg:CC_NOOV CC_REGNUM)
7662         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7663                           [(match_operator:SI 3 "shift_operator"
7664                             [(match_operand:SI 4 "s_register_operand" "r")
7665                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7666                            (match_operand:SI 2 "s_register_operand" "r")])
7667                          (const_int 0)))
7668    (set (match_operand:SI 0 "s_register_operand" "=r")
7669         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7670                          (match_dup 2)]))]
7671   "TARGET_ARM"
7672   "%i1%?s\\t%0, %2, %4%S3"
7673   [(set_attr "conds" "set")
7674    (set_attr "shift" "4")
7675    ]
7676 )
7677
7678 (define_insn "*arith_shiftsi_compare0_scratch"
7679   [(set (reg:CC_NOOV CC_REGNUM)
7680         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7681                           [(match_operator:SI 3 "shift_operator"
7682                             [(match_operand:SI 4 "s_register_operand" "r")
7683                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7684                            (match_operand:SI 2 "s_register_operand" "r")])
7685                          (const_int 0)))
7686    (clobber (match_scratch:SI 0 "=r"))]
7687   "TARGET_ARM"
7688   "%i1%?s\\t%0, %2, %4%S3"
7689   [(set_attr "conds" "set")
7690    (set_attr "shift" "4")
7691    ]
7692 )
7693
7694 (define_insn "*sub_shiftsi"
7695   [(set (match_operand:SI 0 "s_register_operand" "=r")
7696         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7697                   (match_operator:SI 2 "shift_operator"
7698                    [(match_operand:SI 3 "s_register_operand" "r")
7699                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7700   "TARGET_ARM"
7701   "sub%?\\t%0, %1, %3%S2"
7702   [(set_attr "predicable" "yes")
7703    (set_attr "shift" "3")
7704    ]
7705 )
7706
7707 (define_insn "*sub_shiftsi_compare0"
7708   [(set (reg:CC_NOOV CC_REGNUM)
7709         (compare:CC_NOOV
7710          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7711                    (match_operator:SI 2 "shift_operator"
7712                     [(match_operand:SI 3 "s_register_operand" "r")
7713                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7714          (const_int 0)))
7715    (set (match_operand:SI 0 "s_register_operand" "=r")
7716         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7717                                                  (match_dup 4)])))]
7718   "TARGET_ARM"
7719   "sub%?s\\t%0, %1, %3%S2"
7720   [(set_attr "conds" "set")
7721    (set_attr "shift" "3") 
7722    ]
7723 )
7724
7725 (define_insn "*sub_shiftsi_compare0_scratch"
7726   [(set (reg:CC_NOOV CC_REGNUM)
7727         (compare:CC_NOOV
7728          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7729                    (match_operator:SI 2 "shift_operator"
7730                     [(match_operand:SI 3 "s_register_operand" "r")
7731                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7732          (const_int 0)))
7733    (clobber (match_scratch:SI 0 "=r"))]
7734   "TARGET_ARM"
7735   "sub%?s\\t%0, %1, %3%S2"
7736   [(set_attr "conds" "set")
7737    (set_attr "shift" "3") 
7738    ]
7739 )
7740
7741 \f
7742
7743 (define_insn "*and_scc"
7744   [(set (match_operand:SI 0 "s_register_operand" "=r")
7745         (and:SI (match_operator:SI 1 "arm_comparison_operator"
7746                  [(match_operand 3 "cc_register" "") (const_int 0)])
7747                 (match_operand:SI 2 "s_register_operand" "r")))]
7748   "TARGET_ARM"
7749   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7750   [(set_attr "conds" "use")
7751    (set_attr "length" "8")]
7752 )
7753
7754 (define_insn "*ior_scc"
7755   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7756         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7757                  [(match_operand 3 "cc_register" "") (const_int 0)])
7758                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7759   "TARGET_ARM"
7760   "@
7761    orr%d2\\t%0, %1, #1
7762    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7763   [(set_attr "conds" "use")
7764    (set_attr "length" "4,8")]
7765 )
7766
7767 (define_insn "*compare_scc"
7768   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7769         (match_operator:SI 1 "arm_comparison_operator"
7770          [(match_operand:SI 2 "s_register_operand" "r,r")
7771           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7772    (clobber (reg:CC CC_REGNUM))]
7773   "TARGET_ARM"
7774   "*
7775     if (operands[3] == const0_rtx)
7776       {
7777         if (GET_CODE (operands[1]) == LT)
7778           return \"mov\\t%0, %2, lsr #31\";
7779
7780         if (GET_CODE (operands[1]) == GE)
7781           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7782
7783         if (GET_CODE (operands[1]) == EQ)
7784           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
7785       }
7786
7787     if (GET_CODE (operands[1]) == NE)
7788       {
7789         if (which_alternative == 1)
7790           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7791         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7792       }
7793     if (which_alternative == 1)
7794       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7795     else
7796       output_asm_insn (\"cmp\\t%2, %3\", operands);
7797     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7798   "
7799   [(set_attr "conds" "clob")
7800    (set_attr "length" "12")]
7801 )
7802
7803 (define_insn "*cond_move"
7804   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7805         (if_then_else:SI (match_operator 3 "equality_operator"
7806                           [(match_operator 4 "arm_comparison_operator"
7807                             [(match_operand 5 "cc_register" "") (const_int 0)])
7808                            (const_int 0)])
7809                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7810                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7811   "TARGET_ARM"
7812   "*
7813     if (GET_CODE (operands[3]) == NE)
7814       {
7815         if (which_alternative != 1)
7816           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7817         if (which_alternative != 0)
7818           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7819         return \"\";
7820       }
7821     if (which_alternative != 0)
7822       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7823     if (which_alternative != 1)
7824       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7825     return \"\";
7826   "
7827   [(set_attr "conds" "use")
7828    (set_attr "length" "4,4,8")]
7829 )
7830
7831 (define_insn "*cond_arith"
7832   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7833         (match_operator:SI 5 "shiftable_operator" 
7834          [(match_operator:SI 4 "arm_comparison_operator"
7835            [(match_operand:SI 2 "s_register_operand" "r,r")
7836             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7837           (match_operand:SI 1 "s_register_operand" "0,?r")]))
7838    (clobber (reg:CC CC_REGNUM))]
7839   "TARGET_ARM"
7840   "*
7841     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7842       return \"%i5\\t%0, %1, %2, lsr #31\";
7843
7844     output_asm_insn (\"cmp\\t%2, %3\", operands);
7845     if (GET_CODE (operands[5]) == AND)
7846       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7847     else if (GET_CODE (operands[5]) == MINUS)
7848       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7849     else if (which_alternative != 0)
7850       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7851     return \"%i5%d4\\t%0, %1, #1\";
7852   "
7853   [(set_attr "conds" "clob")
7854    (set_attr "length" "12")]
7855 )
7856
7857 (define_insn "*cond_sub"
7858   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7859         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7860                   (match_operator:SI 4 "arm_comparison_operator"
7861                    [(match_operand:SI 2 "s_register_operand" "r,r")
7862                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7863    (clobber (reg:CC CC_REGNUM))]
7864   "TARGET_ARM"
7865   "*
7866     output_asm_insn (\"cmp\\t%2, %3\", operands);
7867     if (which_alternative != 0)
7868       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7869     return \"sub%d4\\t%0, %1, #1\";
7870   "
7871   [(set_attr "conds" "clob")
7872    (set_attr "length" "8,12")]
7873 )
7874
7875 (define_insn "*cmp_ite0"
7876   [(set (match_operand 6 "dominant_cc_register" "")
7877         (compare
7878          (if_then_else:SI
7879           (match_operator 4 "arm_comparison_operator"
7880            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7881             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7882           (match_operator:SI 5 "arm_comparison_operator"
7883            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7884             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7885           (const_int 0))
7886          (const_int 0)))]
7887   "TARGET_ARM"
7888   "*
7889   {
7890     static const char * const opcodes[4][2] =
7891     {
7892       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7893        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7894       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7895        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7896       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7897        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7898       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7899        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7900     };
7901     int swap =
7902       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7903
7904     return opcodes[which_alternative][swap];
7905   }"
7906   [(set_attr "conds" "set")
7907    (set_attr "length" "8")]
7908 )
7909
7910 (define_insn "*cmp_ite1"
7911   [(set (match_operand 6 "dominant_cc_register" "")
7912         (compare
7913          (if_then_else:SI
7914           (match_operator 4 "arm_comparison_operator"
7915            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7916             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7917           (match_operator:SI 5 "arm_comparison_operator"
7918            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7919             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7920           (const_int 1))
7921          (const_int 0)))]
7922   "TARGET_ARM"
7923   "*
7924   {
7925     static const char * const opcodes[4][2] =
7926     {
7927       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7928        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7929       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7930        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7931       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7932        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7933       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7934        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7935     };
7936     int swap =
7937       comparison_dominates_p (GET_CODE (operands[5]),
7938                               reverse_condition (GET_CODE (operands[4])));
7939
7940     return opcodes[which_alternative][swap];
7941   }"
7942   [(set_attr "conds" "set")
7943    (set_attr "length" "8")]
7944 )
7945
7946 (define_insn "*cmp_and"
7947   [(set (match_operand 6 "dominant_cc_register" "")
7948         (compare
7949          (and:SI
7950           (match_operator 4 "arm_comparison_operator"
7951            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7952             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7953           (match_operator:SI 5 "arm_comparison_operator"
7954            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7955             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7956          (const_int 0)))]
7957   "TARGET_ARM"
7958   "*
7959   {
7960     static const char *const opcodes[4][2] =
7961     {
7962       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7963        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7964       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7965        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7966       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7967        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7968       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7969        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7970     };
7971     int swap =
7972       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7973
7974     return opcodes[which_alternative][swap];
7975   }"
7976   [(set_attr "conds" "set")
7977    (set_attr "predicable" "no")
7978    (set_attr "length" "8")]
7979 )
7980
7981 (define_insn "*cmp_ior"
7982   [(set (match_operand 6 "dominant_cc_register" "")
7983         (compare
7984          (ior:SI
7985           (match_operator 4 "arm_comparison_operator"
7986            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7987             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7988           (match_operator:SI 5 "arm_comparison_operator"
7989            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7990             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7991          (const_int 0)))]
7992   "TARGET_ARM"
7993   "*
7994 {
7995   static const char *const opcodes[4][2] =
7996   {
7997     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7998      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7999     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8000      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8001     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8002      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8003     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8004      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8005   };
8006   int swap =
8007     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8008
8009   return opcodes[which_alternative][swap];
8010 }
8011 "
8012   [(set_attr "conds" "set")
8013    (set_attr "length" "8")]
8014 )
8015
8016 (define_insn_and_split "*ior_scc_scc"
8017   [(set (match_operand:SI 0 "s_register_operand" "=r")
8018         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8019                  [(match_operand:SI 1 "s_register_operand" "r")
8020                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8021                 (match_operator:SI 6 "arm_comparison_operator"
8022                  [(match_operand:SI 4 "s_register_operand" "r")
8023                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8024    (clobber (reg:CC CC_REGNUM))]
8025   "TARGET_ARM
8026    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8027        != CCmode)"
8028   "#"
8029   "TARGET_ARM && reload_completed"
8030   [(set (match_dup 7)
8031         (compare
8032          (ior:SI
8033           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8034           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8035          (const_int 0)))
8036    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8037   "operands[7]
8038      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8039                                                   DOM_CC_X_OR_Y),
8040                     CC_REGNUM);"
8041   [(set_attr "conds" "clob")
8042    (set_attr "length" "16")])
8043
8044 ; If the above pattern is followed by a CMP insn, then the compare is 
8045 ; redundant, since we can rework the conditional instruction that follows.
8046 (define_insn_and_split "*ior_scc_scc_cmp"
8047   [(set (match_operand 0 "dominant_cc_register" "")
8048         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8049                           [(match_operand:SI 1 "s_register_operand" "r")
8050                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8051                          (match_operator:SI 6 "arm_comparison_operator"
8052                           [(match_operand:SI 4 "s_register_operand" "r")
8053                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8054                  (const_int 0)))
8055    (set (match_operand:SI 7 "s_register_operand" "=r")
8056         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8057                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8058   "TARGET_ARM"
8059   "#"
8060   "TARGET_ARM && reload_completed"
8061   [(set (match_dup 0)
8062         (compare
8063          (ior:SI
8064           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8065           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8066          (const_int 0)))
8067    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8068   ""
8069   [(set_attr "conds" "set")
8070    (set_attr "length" "16")])
8071
8072 (define_insn_and_split "*and_scc_scc"
8073   [(set (match_operand:SI 0 "s_register_operand" "=r")
8074         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8075                  [(match_operand:SI 1 "s_register_operand" "r")
8076                   (match_operand:SI 2 "arm_add_operand" "rIL")])
8077                 (match_operator:SI 6 "arm_comparison_operator"
8078                  [(match_operand:SI 4 "s_register_operand" "r")
8079                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
8080    (clobber (reg:CC CC_REGNUM))]
8081   "TARGET_ARM
8082    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8083        != CCmode)"
8084   "#"
8085   "TARGET_ARM && reload_completed
8086    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8087        != CCmode)"
8088   [(set (match_dup 7)
8089         (compare
8090          (and:SI
8091           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8092           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8093          (const_int 0)))
8094    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8095   "operands[7]
8096      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8097                                                   DOM_CC_X_AND_Y),
8098                     CC_REGNUM);"
8099   [(set_attr "conds" "clob")
8100    (set_attr "length" "16")])
8101
8102 ; If the above pattern is followed by a CMP insn, then the compare is 
8103 ; redundant, since we can rework the conditional instruction that follows.
8104 (define_insn_and_split "*and_scc_scc_cmp"
8105   [(set (match_operand 0 "dominant_cc_register" "")
8106         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8107                           [(match_operand:SI 1 "s_register_operand" "r")
8108                            (match_operand:SI 2 "arm_add_operand" "rIL")])
8109                          (match_operator:SI 6 "arm_comparison_operator"
8110                           [(match_operand:SI 4 "s_register_operand" "r")
8111                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
8112                  (const_int 0)))
8113    (set (match_operand:SI 7 "s_register_operand" "=r")
8114         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8115                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8116   "TARGET_ARM"
8117   "#"
8118   "TARGET_ARM && reload_completed"
8119   [(set (match_dup 0)
8120         (compare
8121          (and:SI
8122           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8123           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8124          (const_int 0)))
8125    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8126   ""
8127   [(set_attr "conds" "set")
8128    (set_attr "length" "16")])
8129
8130 ;; If there is no dominance in the comparison, then we can still save an
8131 ;; instruction in the AND case, since we can know that the second compare
8132 ;; need only zero the value if false (if true, then the value is already
8133 ;; correct).
8134 (define_insn_and_split "*and_scc_scc_nodom"
8135   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8136         (and:SI (match_operator:SI 3 "arm_comparison_operator"
8137                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
8138                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8139                 (match_operator:SI 6 "arm_comparison_operator"
8140                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
8141                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8142    (clobber (reg:CC CC_REGNUM))]
8143   "TARGET_ARM
8144    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8145        == CCmode)"
8146   "#"
8147   "TARGET_ARM && reload_completed"
8148   [(parallel [(set (match_dup 0)
8149                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8150               (clobber (reg:CC CC_REGNUM))])
8151    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8152    (set (match_dup 0)
8153         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8154                          (match_dup 0)
8155                          (const_int 0)))]
8156   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8157                                               operands[4], operands[5]),
8158                               CC_REGNUM);
8159    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8160                                   operands[5]);"
8161   [(set_attr "conds" "clob")
8162    (set_attr "length" "20")])
8163
8164 (define_split
8165   [(set (reg:CC_NOOV CC_REGNUM)
8166         (compare:CC_NOOV (ior:SI
8167                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8168                                   (const_int 1))
8169                           (match_operator:SI 1 "comparison_operator"
8170                            [(match_operand:SI 2 "s_register_operand" "")
8171                             (match_operand:SI 3 "arm_add_operand" "")]))
8172                          (const_int 0)))
8173    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8174   "TARGET_ARM"
8175   [(set (match_dup 4)
8176         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8177                 (match_dup 0)))
8178    (set (reg:CC_NOOV CC_REGNUM)
8179         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8180                          (const_int 0)))]
8181   "")
8182
8183 (define_split
8184   [(set (reg:CC_NOOV CC_REGNUM)
8185         (compare:CC_NOOV (ior:SI
8186                           (match_operator:SI 1 "comparison_operator"
8187                            [(match_operand:SI 2 "s_register_operand" "")
8188                             (match_operand:SI 3 "arm_add_operand" "")])
8189                           (and:SI (match_operand:SI 0 "s_register_operand" "")
8190                                   (const_int 1)))
8191                          (const_int 0)))
8192    (clobber (match_operand:SI 4 "s_register_operand" ""))]
8193   "TARGET_ARM"
8194   [(set (match_dup 4)
8195         (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8196                 (match_dup 0)))
8197    (set (reg:CC_NOOV CC_REGNUM)
8198         (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8199                          (const_int 0)))]
8200   "")
8201
8202 (define_insn "*negscc"
8203   [(set (match_operand:SI 0 "s_register_operand" "=r")
8204         (neg:SI (match_operator 3 "arm_comparison_operator"
8205                  [(match_operand:SI 1 "s_register_operand" "r")
8206                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8207    (clobber (reg:CC CC_REGNUM))]
8208   "TARGET_ARM"
8209   "*
8210   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8211     return \"mov\\t%0, %1, asr #31\";
8212
8213   if (GET_CODE (operands[3]) == NE)
8214     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8215
8216   if (GET_CODE (operands[3]) == GT)
8217     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8218
8219   output_asm_insn (\"cmp\\t%1, %2\", operands);
8220   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8221   return \"mvn%d3\\t%0, #0\";
8222   "
8223   [(set_attr "conds" "clob")
8224    (set_attr "length" "12")]
8225 )
8226
8227 (define_insn "movcond"
8228   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8229         (if_then_else:SI
8230          (match_operator 5 "arm_comparison_operator"
8231           [(match_operand:SI 3 "s_register_operand" "r,r,r")
8232            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8233          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8234          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8235    (clobber (reg:CC CC_REGNUM))]
8236   "TARGET_ARM"
8237   "*
8238   if (GET_CODE (operands[5]) == LT
8239       && (operands[4] == const0_rtx))
8240     {
8241       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8242         {
8243           if (operands[2] == const0_rtx)
8244             return \"and\\t%0, %1, %3, asr #31\";
8245           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8246         }
8247       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8248         {
8249           if (operands[1] == const0_rtx)
8250             return \"bic\\t%0, %2, %3, asr #31\";
8251           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8252         }
8253       /* The only case that falls through to here is when both ops 1 & 2
8254          are constants.  */
8255     }
8256
8257   if (GET_CODE (operands[5]) == GE
8258       && (operands[4] == const0_rtx))
8259     {
8260       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8261         {
8262           if (operands[2] == const0_rtx)
8263             return \"bic\\t%0, %1, %3, asr #31\";
8264           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8265         }
8266       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8267         {
8268           if (operands[1] == const0_rtx)
8269             return \"and\\t%0, %2, %3, asr #31\";
8270           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8271         }
8272       /* The only case that falls through to here is when both ops 1 & 2
8273          are constants.  */
8274     }
8275   if (GET_CODE (operands[4]) == CONST_INT
8276       && !const_ok_for_arm (INTVAL (operands[4])))
8277     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8278   else
8279     output_asm_insn (\"cmp\\t%3, %4\", operands);
8280   if (which_alternative != 0)
8281     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8282   if (which_alternative != 1)
8283     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8284   return \"\";
8285   "
8286   [(set_attr "conds" "clob")
8287    (set_attr "length" "8,8,12")]
8288 )
8289
8290 (define_insn "*ifcompare_plus_move"
8291   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8292         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8293                           [(match_operand:SI 4 "s_register_operand" "r,r")
8294                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8295                          (plus:SI
8296                           (match_operand:SI 2 "s_register_operand" "r,r")
8297                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8298                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8299    (clobber (reg:CC CC_REGNUM))]
8300   "TARGET_ARM"
8301   "#"
8302   [(set_attr "conds" "clob")
8303    (set_attr "length" "8,12")]
8304 )
8305
8306 (define_insn "*if_plus_move"
8307   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8308         (if_then_else:SI
8309          (match_operator 4 "arm_comparison_operator"
8310           [(match_operand 5 "cc_register" "") (const_int 0)])
8311          (plus:SI
8312           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8313           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8314          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8315   "TARGET_ARM"
8316   "@
8317    add%d4\\t%0, %2, %3
8318    sub%d4\\t%0, %2, #%n3
8319    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8320    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8321   [(set_attr "conds" "use")
8322    (set_attr "length" "4,4,8,8")
8323    (set_attr "type" "*,*,*,*")]
8324 )
8325
8326 (define_insn "*ifcompare_move_plus"
8327   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8328         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8329                           [(match_operand:SI 4 "s_register_operand" "r,r")
8330                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8331                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8332                          (plus:SI
8333                           (match_operand:SI 2 "s_register_operand" "r,r")
8334                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8335    (clobber (reg:CC CC_REGNUM))]
8336   "TARGET_ARM"
8337   "#"
8338   [(set_attr "conds" "clob")
8339    (set_attr "length" "8,12")]
8340 )
8341
8342 (define_insn "*if_move_plus"
8343   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8344         (if_then_else:SI
8345          (match_operator 4 "arm_comparison_operator"
8346           [(match_operand 5 "cc_register" "") (const_int 0)])
8347          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8348          (plus:SI
8349           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8350           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8351   "TARGET_ARM"
8352   "@
8353    add%D4\\t%0, %2, %3
8354    sub%D4\\t%0, %2, #%n3
8355    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8356    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8357   [(set_attr "conds" "use")
8358    (set_attr "length" "4,4,8,8")
8359    (set_attr "type" "*,*,*,*")]
8360 )
8361
8362 (define_insn "*ifcompare_arith_arith"
8363   [(set (match_operand:SI 0 "s_register_operand" "=r")
8364         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8365                           [(match_operand:SI 5 "s_register_operand" "r")
8366                            (match_operand:SI 6 "arm_add_operand" "rIL")])
8367                          (match_operator:SI 8 "shiftable_operator"
8368                           [(match_operand:SI 1 "s_register_operand" "r")
8369                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8370                          (match_operator:SI 7 "shiftable_operator"
8371                           [(match_operand:SI 3 "s_register_operand" "r")
8372                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8373    (clobber (reg:CC CC_REGNUM))]
8374   "TARGET_ARM"
8375   "#"
8376   [(set_attr "conds" "clob")
8377    (set_attr "length" "12")]
8378 )
8379
8380 (define_insn "*if_arith_arith"
8381   [(set (match_operand:SI 0 "s_register_operand" "=r")
8382         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8383                           [(match_operand 8 "cc_register" "") (const_int 0)])
8384                          (match_operator:SI 6 "shiftable_operator"
8385                           [(match_operand:SI 1 "s_register_operand" "r")
8386                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
8387                          (match_operator:SI 7 "shiftable_operator"
8388                           [(match_operand:SI 3 "s_register_operand" "r")
8389                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8390   "TARGET_ARM"
8391   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8392   [(set_attr "conds" "use")
8393    (set_attr "length" "8")]
8394 )
8395
8396 (define_insn "*ifcompare_arith_move"
8397   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8398         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8399                           [(match_operand:SI 2 "s_register_operand" "r,r")
8400                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8401                          (match_operator:SI 7 "shiftable_operator"
8402                           [(match_operand:SI 4 "s_register_operand" "r,r")
8403                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8404                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8405    (clobber (reg:CC CC_REGNUM))]
8406   "TARGET_ARM"
8407   "*
8408   /* If we have an operation where (op x 0) is the identity operation and
8409      the conditional operator is LT or GE and we are comparing against zero and
8410      everything is in registers then we can do this in two instructions.  */
8411   if (operands[3] == const0_rtx
8412       && GET_CODE (operands[7]) != AND
8413       && GET_CODE (operands[5]) == REG
8414       && GET_CODE (operands[1]) == REG 
8415       && REGNO (operands[1]) == REGNO (operands[4])
8416       && REGNO (operands[4]) != REGNO (operands[0]))
8417     {
8418       if (GET_CODE (operands[6]) == LT)
8419         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8420       else if (GET_CODE (operands[6]) == GE)
8421         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8422     }
8423   if (GET_CODE (operands[3]) == CONST_INT
8424       && !const_ok_for_arm (INTVAL (operands[3])))
8425     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8426   else
8427     output_asm_insn (\"cmp\\t%2, %3\", operands);
8428   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8429   if (which_alternative != 0)
8430     return \"mov%D6\\t%0, %1\";
8431   return \"\";
8432   "
8433   [(set_attr "conds" "clob")
8434    (set_attr "length" "8,12")]
8435 )
8436
8437 (define_insn "*if_arith_move"
8438   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8439         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8440                           [(match_operand 6 "cc_register" "") (const_int 0)])
8441                          (match_operator:SI 5 "shiftable_operator"
8442                           [(match_operand:SI 2 "s_register_operand" "r,r")
8443                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8444                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8445   "TARGET_ARM"
8446   "@
8447    %I5%d4\\t%0, %2, %3
8448    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8449   [(set_attr "conds" "use")
8450    (set_attr "length" "4,8")
8451    (set_attr "type" "*,*")]
8452 )
8453
8454 (define_insn "*ifcompare_move_arith"
8455   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8456         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8457                           [(match_operand:SI 4 "s_register_operand" "r,r")
8458                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8459                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8460                          (match_operator:SI 7 "shiftable_operator"
8461                           [(match_operand:SI 2 "s_register_operand" "r,r")
8462                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8463    (clobber (reg:CC CC_REGNUM))]
8464   "TARGET_ARM"
8465   "*
8466   /* If we have an operation where (op x 0) is the identity operation and
8467      the conditional operator is LT or GE and we are comparing against zero and
8468      everything is in registers then we can do this in two instructions */
8469   if (operands[5] == const0_rtx
8470       && GET_CODE (operands[7]) != AND
8471       && GET_CODE (operands[3]) == REG
8472       && GET_CODE (operands[1]) == REG 
8473       && REGNO (operands[1]) == REGNO (operands[2])
8474       && REGNO (operands[2]) != REGNO (operands[0]))
8475     {
8476       if (GET_CODE (operands[6]) == GE)
8477         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8478       else if (GET_CODE (operands[6]) == LT)
8479         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8480     }
8481
8482   if (GET_CODE (operands[5]) == CONST_INT
8483       && !const_ok_for_arm (INTVAL (operands[5])))
8484     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8485   else
8486     output_asm_insn (\"cmp\\t%4, %5\", operands);
8487
8488   if (which_alternative != 0)
8489     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8490   return \"%I7%D6\\t%0, %2, %3\";
8491   "
8492   [(set_attr "conds" "clob")
8493    (set_attr "length" "8,12")]
8494 )
8495
8496 (define_insn "*if_move_arith"
8497   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8498         (if_then_else:SI
8499          (match_operator 4 "arm_comparison_operator"
8500           [(match_operand 6 "cc_register" "") (const_int 0)])
8501          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8502          (match_operator:SI 5 "shiftable_operator"
8503           [(match_operand:SI 2 "s_register_operand" "r,r")
8504            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8505   "TARGET_ARM"
8506   "@
8507    %I5%D4\\t%0, %2, %3
8508    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8509   [(set_attr "conds" "use")
8510    (set_attr "length" "4,8")
8511    (set_attr "type" "*,*")]
8512 )
8513
8514 (define_insn "*ifcompare_move_not"
8515   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8516         (if_then_else:SI
8517          (match_operator 5 "arm_comparison_operator"
8518           [(match_operand:SI 3 "s_register_operand" "r,r")
8519            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8520          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8521          (not:SI
8522           (match_operand:SI 2 "s_register_operand" "r,r"))))
8523    (clobber (reg:CC CC_REGNUM))]
8524   "TARGET_ARM"
8525   "#"
8526   [(set_attr "conds" "clob")
8527    (set_attr "length" "8,12")]
8528 )
8529
8530 (define_insn "*if_move_not"
8531   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8532         (if_then_else:SI
8533          (match_operator 4 "arm_comparison_operator"
8534           [(match_operand 3 "cc_register" "") (const_int 0)])
8535          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8536          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8537   "TARGET_ARM"
8538   "@
8539    mvn%D4\\t%0, %2
8540    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8541    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8542   [(set_attr "conds" "use")
8543    (set_attr "length" "4,8,8")]
8544 )
8545
8546 (define_insn "*ifcompare_not_move"
8547   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8548         (if_then_else:SI 
8549          (match_operator 5 "arm_comparison_operator"
8550           [(match_operand:SI 3 "s_register_operand" "r,r")
8551            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8552          (not:SI
8553           (match_operand:SI 2 "s_register_operand" "r,r"))
8554          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8555    (clobber (reg:CC CC_REGNUM))]
8556   "TARGET_ARM"
8557   "#"
8558   [(set_attr "conds" "clob")
8559    (set_attr "length" "8,12")]
8560 )
8561
8562 (define_insn "*if_not_move"
8563   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8564         (if_then_else:SI
8565          (match_operator 4 "arm_comparison_operator"
8566           [(match_operand 3 "cc_register" "") (const_int 0)])
8567          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8568          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8569   "TARGET_ARM"
8570   "@
8571    mvn%d4\\t%0, %2
8572    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8573    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8574   [(set_attr "conds" "use")
8575    (set_attr "length" "4,8,8")]
8576 )
8577
8578 (define_insn "*ifcompare_shift_move"
8579   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8580         (if_then_else:SI
8581          (match_operator 6 "arm_comparison_operator"
8582           [(match_operand:SI 4 "s_register_operand" "r,r")
8583            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8584          (match_operator:SI 7 "shift_operator"
8585           [(match_operand:SI 2 "s_register_operand" "r,r")
8586            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8587          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8588    (clobber (reg:CC CC_REGNUM))]
8589   "TARGET_ARM"
8590   "#"
8591   [(set_attr "conds" "clob")
8592    (set_attr "length" "8,12")]
8593 )
8594
8595 (define_insn "*if_shift_move"
8596   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8597         (if_then_else:SI
8598          (match_operator 5 "arm_comparison_operator"
8599           [(match_operand 6 "cc_register" "") (const_int 0)])
8600          (match_operator:SI 4 "shift_operator"
8601           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8602            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8603          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8604   "TARGET_ARM"
8605   "@
8606    mov%d5\\t%0, %2%S4
8607    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8608    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8609   [(set_attr "conds" "use")
8610    (set_attr "shift" "2")
8611    (set_attr "length" "4,8,8")]
8612 )
8613
8614 (define_insn "*ifcompare_move_shift"
8615   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8616         (if_then_else:SI
8617          (match_operator 6 "arm_comparison_operator"
8618           [(match_operand:SI 4 "s_register_operand" "r,r")
8619            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8620          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8621          (match_operator:SI 7 "shift_operator"
8622           [(match_operand:SI 2 "s_register_operand" "r,r")
8623            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8624    (clobber (reg:CC CC_REGNUM))]
8625   "TARGET_ARM"
8626   "#"
8627   [(set_attr "conds" "clob")
8628    (set_attr "length" "8,12")]
8629 )
8630
8631 (define_insn "*if_move_shift"
8632   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8633         (if_then_else:SI
8634          (match_operator 5 "arm_comparison_operator"
8635           [(match_operand 6 "cc_register" "") (const_int 0)])
8636          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8637          (match_operator:SI 4 "shift_operator"
8638           [(match_operand:SI 2 "s_register_operand" "r,r,r")
8639            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8640   "TARGET_ARM"
8641   "@
8642    mov%D5\\t%0, %2%S4
8643    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8644    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8645   [(set_attr "conds" "use")
8646    (set_attr "shift" "2")
8647    (set_attr "length" "4,8,8")]
8648 )
8649
8650 (define_insn "*ifcompare_shift_shift"
8651   [(set (match_operand:SI 0 "s_register_operand" "=r")
8652         (if_then_else:SI
8653          (match_operator 7 "arm_comparison_operator"
8654           [(match_operand:SI 5 "s_register_operand" "r")
8655            (match_operand:SI 6 "arm_add_operand" "rIL")])
8656          (match_operator:SI 8 "shift_operator"
8657           [(match_operand:SI 1 "s_register_operand" "r")
8658            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8659          (match_operator:SI 9 "shift_operator"
8660           [(match_operand:SI 3 "s_register_operand" "r")
8661            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8662    (clobber (reg:CC CC_REGNUM))]
8663   "TARGET_ARM"
8664   "#"
8665   [(set_attr "conds" "clob")
8666    (set_attr "length" "12")]
8667 )
8668
8669 (define_insn "*if_shift_shift"
8670   [(set (match_operand:SI 0 "s_register_operand" "=r")
8671         (if_then_else:SI
8672          (match_operator 5 "arm_comparison_operator"
8673           [(match_operand 8 "cc_register" "") (const_int 0)])
8674          (match_operator:SI 6 "shift_operator"
8675           [(match_operand:SI 1 "s_register_operand" "r")
8676            (match_operand:SI 2 "arm_rhs_operand" "rM")])
8677          (match_operator:SI 7 "shift_operator"
8678           [(match_operand:SI 3 "s_register_operand" "r")
8679            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8680   "TARGET_ARM"
8681   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8682   [(set_attr "conds" "use")
8683    (set_attr "shift" "1")
8684    (set_attr "length" "8")]
8685 )
8686
8687 (define_insn "*ifcompare_not_arith"
8688   [(set (match_operand:SI 0 "s_register_operand" "=r")
8689         (if_then_else:SI
8690          (match_operator 6 "arm_comparison_operator"
8691           [(match_operand:SI 4 "s_register_operand" "r")
8692            (match_operand:SI 5 "arm_add_operand" "rIL")])
8693          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8694          (match_operator:SI 7 "shiftable_operator"
8695           [(match_operand:SI 2 "s_register_operand" "r")
8696            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8697    (clobber (reg:CC CC_REGNUM))]
8698   "TARGET_ARM"
8699   "#"
8700   [(set_attr "conds" "clob")
8701    (set_attr "length" "12")]
8702 )
8703
8704 (define_insn "*if_not_arith"
8705   [(set (match_operand:SI 0 "s_register_operand" "=r")
8706         (if_then_else:SI
8707          (match_operator 5 "arm_comparison_operator"
8708           [(match_operand 4 "cc_register" "") (const_int 0)])
8709          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8710          (match_operator:SI 6 "shiftable_operator"
8711           [(match_operand:SI 2 "s_register_operand" "r")
8712            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8713   "TARGET_ARM"
8714   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8715   [(set_attr "conds" "use")
8716    (set_attr "length" "8")]
8717 )
8718
8719 (define_insn "*ifcompare_arith_not"
8720   [(set (match_operand:SI 0 "s_register_operand" "=r")
8721         (if_then_else:SI
8722          (match_operator 6 "arm_comparison_operator"
8723           [(match_operand:SI 4 "s_register_operand" "r")
8724            (match_operand:SI 5 "arm_add_operand" "rIL")])
8725          (match_operator:SI 7 "shiftable_operator"
8726           [(match_operand:SI 2 "s_register_operand" "r")
8727            (match_operand:SI 3 "arm_rhs_operand" "rI")])
8728          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8729    (clobber (reg:CC CC_REGNUM))]
8730   "TARGET_ARM"
8731   "#"
8732   [(set_attr "conds" "clob")
8733    (set_attr "length" "12")]
8734 )
8735
8736 (define_insn "*if_arith_not"
8737   [(set (match_operand:SI 0 "s_register_operand" "=r")
8738         (if_then_else:SI
8739          (match_operator 5 "arm_comparison_operator"
8740           [(match_operand 4 "cc_register" "") (const_int 0)])
8741          (match_operator:SI 6 "shiftable_operator"
8742           [(match_operand:SI 2 "s_register_operand" "r")
8743            (match_operand:SI 3 "arm_rhs_operand" "rI")])
8744          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
8745   "TARGET_ARM"
8746   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8747   [(set_attr "conds" "use")
8748    (set_attr "length" "8")]
8749 )
8750
8751 (define_insn "*ifcompare_neg_move"
8752   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8753         (if_then_else:SI
8754          (match_operator 5 "arm_comparison_operator"
8755           [(match_operand:SI 3 "s_register_operand" "r,r")
8756            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8757          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
8758          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8759    (clobber (reg:CC CC_REGNUM))]
8760   "TARGET_ARM"
8761   "#"
8762   [(set_attr "conds" "clob")
8763    (set_attr "length" "8,12")]
8764 )
8765
8766 (define_insn "*if_neg_move"
8767   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8768         (if_then_else:SI
8769          (match_operator 4 "arm_comparison_operator"
8770           [(match_operand 3 "cc_register" "") (const_int 0)])
8771          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8772          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8773   "TARGET_ARM"
8774   "@
8775    rsb%d4\\t%0, %2, #0
8776    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8777    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8778   [(set_attr "conds" "use")
8779    (set_attr "length" "4,8,8")]
8780 )
8781
8782 (define_insn "*ifcompare_move_neg"
8783   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8784         (if_then_else:SI
8785          (match_operator 5 "arm_comparison_operator"
8786           [(match_operand:SI 3 "s_register_operand" "r,r")
8787            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8788          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8789          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8790    (clobber (reg:CC CC_REGNUM))]
8791   "TARGET_ARM"
8792   "#"
8793   [(set_attr "conds" "clob")
8794    (set_attr "length" "8,12")]
8795 )
8796
8797 (define_insn "*if_move_neg"
8798   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8799         (if_then_else:SI
8800          (match_operator 4 "arm_comparison_operator"
8801           [(match_operand 3 "cc_register" "") (const_int 0)])
8802          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8803          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8804   "TARGET_ARM"
8805   "@
8806    rsb%D4\\t%0, %2, #0
8807    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8808    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8809   [(set_attr "conds" "use")
8810    (set_attr "length" "4,8,8")]
8811 )
8812
8813 (define_insn "*arith_adjacentmem"
8814   [(set (match_operand:SI 0 "s_register_operand" "=r")
8815         (match_operator:SI 1 "shiftable_operator"
8816          [(match_operand:SI 2 "memory_operand" "m")
8817           (match_operand:SI 3 "memory_operand" "m")]))
8818    (clobber (match_scratch:SI 4 "=r"))]
8819   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8820   "*
8821   {
8822     rtx ldm[3];
8823     rtx arith[4];
8824     int val1 = 0, val2 = 0;
8825
8826     if (REGNO (operands[0]) > REGNO (operands[4]))
8827       {
8828         ldm[1] = operands[4];
8829         ldm[2] = operands[0];
8830       }
8831     else
8832       {
8833         ldm[1] = operands[0];
8834         ldm[2] = operands[4];
8835       }
8836     if (GET_CODE (XEXP (operands[2], 0)) != REG)
8837       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8838     if (GET_CODE (XEXP (operands[3], 0)) != REG)
8839       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8840     arith[0] = operands[0];
8841     arith[3] = operands[1];
8842     if (val1 < val2)
8843       {
8844         arith[1] = ldm[1];
8845         arith[2] = ldm[2];
8846       }
8847     else
8848       {
8849         arith[1] = ldm[2];
8850         arith[2] = ldm[1];
8851       }
8852    if (val1 && val2)
8853       {
8854         rtx ops[3];
8855         ldm[0] = ops[0] = operands[4];
8856         ops[1] = XEXP (XEXP (operands[2], 0), 0);
8857         ops[2] = XEXP (XEXP (operands[2], 0), 1);
8858         output_add_immediate (ops);
8859         if (val1 < val2)
8860           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8861         else
8862           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8863       }
8864     else if (val1)
8865       {
8866         ldm[0] = XEXP (operands[3], 0);
8867         if (val1 < val2)
8868           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8869         else
8870           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8871       }
8872     else
8873       {
8874         ldm[0] = XEXP (operands[2], 0);
8875         if (val1 < val2)
8876           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8877         else
8878           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8879       }
8880     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8881     return \"\";
8882   }"
8883   [(set_attr "length" "12")
8884    (set_attr "predicable" "yes")
8885    (set_attr "type" "load")]
8886 )
8887
8888 ;; the arm can support extended pre-inc instructions
8889
8890 ;; In all these cases, we use operands 0 and 1 for the register being
8891 ;; incremented because those are the operands that local-alloc will
8892 ;; tie and these are the pair most likely to be tieable (and the ones
8893 ;; that will benefit the most).
8894
8895 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8896 ;; elimination will cause too many headaches.
8897
8898 (define_insn "*strqi_preinc"
8899   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8900                          (match_operand:SI 2 "index_operand" "rJ")))
8901         (match_operand:QI 3 "s_register_operand" "r"))
8902    (set (match_operand:SI 0 "s_register_operand" "=r")
8903         (plus:SI (match_dup 1) (match_dup 2)))]
8904   "TARGET_ARM
8905    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8906    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8907    && (GET_CODE (operands[2]) != REG
8908        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8909   "str%?b\\t%3, [%0, %2]!"
8910   [(set_attr "type" "store1")
8911    (set_attr "predicable" "yes")]
8912 )
8913
8914 (define_insn "*strqi_predec"
8915   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8916                           (match_operand:SI 2 "s_register_operand" "r")))
8917         (match_operand:QI 3 "s_register_operand" "r"))
8918    (set (match_operand:SI 0 "s_register_operand" "=r")
8919         (minus:SI (match_dup 1) (match_dup 2)))]
8920   "TARGET_ARM
8921    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8922    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8923    && (GET_CODE (operands[2]) != REG
8924        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8925   "str%?b\\t%3, [%0, -%2]!"
8926   [(set_attr "type" "store1")
8927    (set_attr "predicable" "yes")]
8928 )
8929
8930 (define_insn "*loadqi_preinc"
8931   [(set (match_operand:QI 3 "s_register_operand" "=r")
8932         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8933                          (match_operand:SI 2 "index_operand" "rJ"))))
8934    (set (match_operand:SI 0 "s_register_operand" "=r")
8935         (plus:SI (match_dup 1) (match_dup 2)))]
8936   "TARGET_ARM
8937    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8938    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8939    && (GET_CODE (operands[2]) != REG
8940        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8941   "ldr%?b\\t%3, [%0, %2]!"
8942   [(set_attr "type" "load")
8943    (set_attr "predicable" "yes")]
8944 )
8945
8946 (define_insn "*loadqi_predec"
8947   [(set (match_operand:QI 3 "s_register_operand" "=r")
8948         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8949                           (match_operand:SI 2 "s_register_operand" "r"))))
8950    (set (match_operand:SI 0 "s_register_operand" "=r")
8951         (minus:SI (match_dup 1) (match_dup 2)))]
8952   "TARGET_ARM
8953    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8954    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8955    && (GET_CODE (operands[2]) != REG
8956        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8957   "ldr%?b\\t%3, [%0, -%2]!"
8958   [(set_attr "type" "load")
8959    (set_attr "predicable" "yes")]
8960 )
8961
8962 (define_insn "*loadqisi_preinc"
8963   [(set (match_operand:SI 3 "s_register_operand" "=r")
8964         (zero_extend:SI
8965          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8966                           (match_operand:SI 2 "index_operand" "rJ")))))
8967    (set (match_operand:SI 0 "s_register_operand" "=r")
8968         (plus:SI (match_dup 1) (match_dup 2)))]
8969   "TARGET_ARM
8970    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8971    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8972    && (GET_CODE (operands[2]) != REG
8973        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8974   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8975   [(set_attr "type" "load")
8976    (set_attr "predicable" "yes")]
8977 )
8978
8979 (define_insn "*loadqisi_predec"
8980   [(set (match_operand:SI 3 "s_register_operand" "=r")
8981         (zero_extend:SI
8982          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8983                            (match_operand:SI 2 "s_register_operand" "r")))))
8984    (set (match_operand:SI 0 "s_register_operand" "=r")
8985         (minus:SI (match_dup 1) (match_dup 2)))]
8986   "TARGET_ARM
8987    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8988    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8989    && (GET_CODE (operands[2]) != REG
8990        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8991   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8992   [(set_attr "type" "load")
8993    (set_attr "predicable" "yes")]
8994 )
8995
8996 (define_insn "*strsi_preinc"
8997   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8998                          (match_operand:SI 2 "index_operand" "rJ")))
8999         (match_operand:SI 3 "s_register_operand" "r"))
9000    (set (match_operand:SI 0 "s_register_operand" "=r")
9001         (plus:SI (match_dup 1) (match_dup 2)))]
9002   "TARGET_ARM
9003    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9004    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9005    && (GET_CODE (operands[2]) != REG
9006        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9007   "str%?\\t%3, [%0, %2]!"
9008   [(set_attr "type" "store1")
9009    (set_attr "predicable" "yes")]
9010 )
9011
9012 (define_insn "*strsi_predec"
9013   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9014                           (match_operand:SI 2 "s_register_operand" "r")))
9015         (match_operand:SI 3 "s_register_operand" "r"))
9016    (set (match_operand:SI 0 "s_register_operand" "=r")
9017         (minus:SI (match_dup 1) (match_dup 2)))]
9018   "TARGET_ARM
9019    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9020    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9021    && (GET_CODE (operands[2]) != REG
9022        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9023   "str%?\\t%3, [%0, -%2]!"
9024   [(set_attr "type" "store1")
9025    (set_attr "predicable" "yes")]
9026 )
9027
9028 (define_insn "*loadsi_preinc"
9029   [(set (match_operand:SI 3 "s_register_operand" "=r")
9030         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9031                          (match_operand:SI 2 "index_operand" "rJ"))))
9032    (set (match_operand:SI 0 "s_register_operand" "=r")
9033         (plus:SI (match_dup 1) (match_dup 2)))]
9034   "TARGET_ARM
9035    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9036    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9037    && (GET_CODE (operands[2]) != REG
9038        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9039   "ldr%?\\t%3, [%0, %2]!"
9040   [(set_attr "type" "load")
9041    (set_attr "predicable" "yes")]
9042 )
9043
9044 (define_insn "*loadsi_predec"
9045   [(set (match_operand:SI 3 "s_register_operand" "=r")
9046         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9047                           (match_operand:SI 2 "s_register_operand" "r"))))
9048    (set (match_operand:SI 0 "s_register_operand" "=r")
9049         (minus:SI (match_dup 1) (match_dup 2)))]
9050   "TARGET_ARM
9051    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9052    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9053    && (GET_CODE (operands[2]) != REG
9054        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9055   "ldr%?\\t%3, [%0, -%2]!"
9056   [(set_attr "type" "load")
9057    (set_attr "predicable" "yes")]
9058 )
9059
9060 (define_insn "*loadhi_preinc"
9061   [(set (match_operand:HI 3 "s_register_operand" "=r")
9062         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9063                          (match_operand:SI 2 "index_operand" "rJ"))))
9064    (set (match_operand:SI 0 "s_register_operand" "=r")
9065         (plus:SI (match_dup 1) (match_dup 2)))]
9066   "TARGET_ARM
9067    && !BYTES_BIG_ENDIAN
9068    && !TARGET_MMU_TRAPS
9069    && !arm_arch4
9070    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9071    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9072    && (GET_CODE (operands[2]) != REG
9073        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9074   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
9075   [(set_attr "type" "load")
9076    (set_attr "predicable" "yes")]
9077 )
9078
9079 (define_insn "*loadhi_predec"
9080   [(set (match_operand:HI 3 "s_register_operand" "=r")
9081         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9082                           (match_operand:SI 2 "s_register_operand" "r"))))
9083    (set (match_operand:SI 0 "s_register_operand" "=r")
9084         (minus:SI (match_dup 1) (match_dup 2)))]
9085   "TARGET_ARM
9086    && !BYTES_BIG_ENDIAN
9087    && !TARGET_MMU_TRAPS
9088    && !arm_arch4
9089    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9090    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9091    && (GET_CODE (operands[2]) != REG
9092        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9093   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
9094   [(set_attr "type" "load")
9095    (set_attr "predicable" "yes")]
9096 )
9097
9098 (define_insn "*strqi_shiftpreinc"
9099   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9100                           [(match_operand:SI 3 "s_register_operand" "r")
9101                            (match_operand:SI 4 "const_shift_operand" "n")])
9102                          (match_operand:SI 1 "s_register_operand" "0")))
9103         (match_operand:QI 5 "s_register_operand" "r"))
9104    (set (match_operand:SI 0 "s_register_operand" "=r")
9105         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9106                  (match_dup 1)))]
9107   "TARGET_ARM
9108    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9109    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9110    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9111   "str%?b\\t%5, [%0, %3%S2]!"
9112   [(set_attr "type" "store1")
9113    (set_attr "predicable" "yes")]
9114 )
9115
9116 (define_insn "*strqi_shiftpredec"
9117   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9118                           (match_operator:SI 2 "shift_operator"
9119                            [(match_operand:SI 3 "s_register_operand" "r")
9120                             (match_operand:SI 4 "const_shift_operand" "n")])))
9121         (match_operand:QI 5 "s_register_operand" "r"))
9122    (set (match_operand:SI 0 "s_register_operand" "=r")
9123         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9124                                                  (match_dup 4)])))]
9125   "TARGET_ARM
9126    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9127    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9128    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9129   "str%?b\\t%5, [%0, -%3%S2]!"
9130   [(set_attr "type" "store1")
9131    (set_attr "predicable" "yes")]
9132 )
9133
9134 (define_insn "*loadqi_shiftpreinc"
9135   [(set (match_operand:QI 5 "s_register_operand" "=r")
9136         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9137                           [(match_operand:SI 3 "s_register_operand" "r")
9138                            (match_operand:SI 4 "const_shift_operand" "n")])
9139                          (match_operand:SI 1 "s_register_operand" "0"))))
9140    (set (match_operand:SI 0 "s_register_operand" "=r")
9141         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9142                  (match_dup 1)))]
9143   "TARGET_ARM
9144    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9145    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9146    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9147   "ldr%?b\\t%5, [%0, %3%S2]!"
9148   [(set_attr "type" "load")
9149    (set_attr "predicable" "yes")]
9150 )
9151
9152 (define_insn "*loadqi_shiftpredec"
9153   [(set (match_operand:QI 5 "s_register_operand" "=r")
9154         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9155                           (match_operator:SI 2 "shift_operator"
9156                            [(match_operand:SI 3 "s_register_operand" "r")
9157                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9158    (set (match_operand:SI 0 "s_register_operand" "=r")
9159         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9160                                                  (match_dup 4)])))]
9161   "TARGET_ARM
9162    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9163    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9164    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9165   "ldr%?b\\t%5, [%0, -%3%S2]!"
9166   [(set_attr "type" "load")
9167    (set_attr "predicable" "yes")]
9168 )
9169
9170 (define_insn "*strsi_shiftpreinc"
9171   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9172                           [(match_operand:SI 3 "s_register_operand" "r")
9173                            (match_operand:SI 4 "const_shift_operand" "n")])
9174                          (match_operand:SI 1 "s_register_operand" "0")))
9175         (match_operand:SI 5 "s_register_operand" "r"))
9176    (set (match_operand:SI 0 "s_register_operand" "=r")
9177         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9178                  (match_dup 1)))]
9179   "TARGET_ARM
9180    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9181    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9182    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9183   "str%?\\t%5, [%0, %3%S2]!"
9184   [(set_attr "type" "store1")
9185    (set_attr "predicable" "yes")]
9186 )
9187
9188 (define_insn "*strsi_shiftpredec"
9189   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9190                           (match_operator:SI 2 "shift_operator"
9191                            [(match_operand:SI 3 "s_register_operand" "r")
9192                             (match_operand:SI 4 "const_shift_operand" "n")])))
9193         (match_operand:SI 5 "s_register_operand" "r"))
9194    (set (match_operand:SI 0 "s_register_operand" "=r")
9195         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9196                                                  (match_dup 4)])))]
9197   "TARGET_ARM
9198    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9199    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9200    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9201   "str%?\\t%5, [%0, -%3%S2]!"
9202   [(set_attr "type" "store1")
9203    (set_attr "predicable" "yes")]
9204 )
9205
9206 (define_insn "*loadsi_shiftpreinc"
9207   [(set (match_operand:SI 5 "s_register_operand" "=r")
9208         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9209                           [(match_operand:SI 3 "s_register_operand" "r")
9210                            (match_operand:SI 4 "const_shift_operand" "n")])
9211                          (match_operand:SI 1 "s_register_operand" "0"))))
9212    (set (match_operand:SI 0 "s_register_operand" "=r")
9213         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9214                  (match_dup 1)))]
9215   "TARGET_ARM
9216    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9217    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9218    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9219   "ldr%?\\t%5, [%0, %3%S2]!"
9220   [(set_attr "type" "load")
9221    (set_attr "predicable" "yes")]
9222 )
9223
9224 (define_insn "*loadsi_shiftpredec"
9225   [(set (match_operand:SI 5 "s_register_operand" "=r")
9226         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9227                           (match_operator:SI 2 "shift_operator"
9228                            [(match_operand:SI 3 "s_register_operand" "r")
9229                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9230    (set (match_operand:SI 0 "s_register_operand" "=r")
9231         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9232                                                  (match_dup 4)])))]
9233   "TARGET_ARM
9234    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9235    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9236    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9237   "ldr%?\\t%5, [%0, -%3%S2]!"
9238   [(set_attr "type" "load")
9239    (set_attr "predicable" "yes")])
9240
9241 (define_insn "*loadhi_shiftpreinc"
9242   [(set (match_operand:HI 5 "s_register_operand" "=r")
9243         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
9244                           [(match_operand:SI 3 "s_register_operand" "r")
9245                            (match_operand:SI 4 "const_shift_operand" "n")])
9246                          (match_operand:SI 1 "s_register_operand" "0"))))
9247    (set (match_operand:SI 0 "s_register_operand" "=r")
9248         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9249                  (match_dup 1)))]
9250   "TARGET_ARM
9251    && !BYTES_BIG_ENDIAN
9252    && !TARGET_MMU_TRAPS
9253    && !arm_arch4
9254    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9255    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9256    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9257   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
9258   [(set_attr "type" "load")
9259    (set_attr "predicable" "yes")]
9260 )
9261
9262 (define_insn "*loadhi_shiftpredec"
9263   [(set (match_operand:HI 5 "s_register_operand" "=r")
9264         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9265                           (match_operator:SI 2 "shift_operator"
9266                            [(match_operand:SI 3 "s_register_operand" "r")
9267                             (match_operand:SI 4 "const_shift_operand" "n")]))))
9268    (set (match_operand:SI 0 "s_register_operand" "=r")
9269         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9270                                                  (match_dup 4)])))]
9271   "TARGET_ARM
9272    && !BYTES_BIG_ENDIAN
9273    && !TARGET_MMU_TRAPS
9274    && !arm_arch4
9275    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9276    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9277    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9278   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
9279   [(set_attr "type" "load")
9280    (set_attr "predicable" "yes")]
9281 )
9282
9283 ; It can also support extended post-inc expressions, but combine doesn't
9284 ; try these....
9285 ; It doesn't seem worth adding peepholes for anything but the most common
9286 ; cases since, unlike combine, the increment must immediately follow the load
9287 ; for this pattern to match.
9288 ; We must watch to see that the source/destination register isn't also the
9289 ; same as the base address register, and that if the index is a register,
9290 ; that it is not the same as the base address register.  In such cases the
9291 ; instruction that we would generate would have UNPREDICTABLE behavior so 
9292 ; we cannot use it.
9293
9294 (define_peephole
9295   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9296         (match_operand:QI 2 "s_register_operand" "r"))
9297    (set (match_dup 0)
9298         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9299   "TARGET_ARM
9300    && (REGNO (operands[2]) != REGNO (operands[0]))
9301    && (GET_CODE (operands[1]) != REG
9302        || (REGNO (operands[1]) != REGNO (operands[0])))"
9303   "str%?b\\t%2, [%0], %1"
9304 )
9305
9306 (define_peephole
9307   [(set (match_operand:QI 0 "s_register_operand" "=r")
9308         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9309    (set (match_dup 1)
9310         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9311   "TARGET_ARM
9312    && REGNO (operands[0]) != REGNO(operands[1])
9313    && (GET_CODE (operands[2]) != REG
9314        || REGNO(operands[0]) != REGNO (operands[2]))"
9315   "ldr%?b\\t%0, [%1], %2"
9316 )
9317
9318 (define_peephole
9319   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9320         (match_operand:SI 2 "s_register_operand" "r"))
9321    (set (match_dup 0)
9322         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9323   "TARGET_ARM
9324    && (REGNO (operands[2]) != REGNO (operands[0]))
9325    && (GET_CODE (operands[1]) != REG
9326        || (REGNO (operands[1]) != REGNO (operands[0])))"
9327   "str%?\\t%2, [%0], %1"
9328 )
9329
9330 (define_peephole
9331   [(set (match_operand:HI 0 "s_register_operand" "=r")
9332         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
9333    (set (match_dup 1)
9334         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9335   "TARGET_ARM
9336    && !BYTES_BIG_ENDIAN
9337    && !TARGET_MMU_TRAPS
9338    && !arm_arch4
9339    && REGNO (operands[0]) != REGNO(operands[1])
9340    && (GET_CODE (operands[2]) != REG
9341        || REGNO(operands[0]) != REGNO (operands[2]))"
9342   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
9343 )
9344
9345 (define_peephole
9346   [(set (match_operand:SI 0 "s_register_operand" "=r")
9347         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9348    (set (match_dup 1)
9349         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9350   "TARGET_ARM
9351    && REGNO (operands[0]) != REGNO(operands[1])
9352    && (GET_CODE (operands[2]) != REG
9353        || REGNO(operands[0]) != REGNO (operands[2]))"
9354   "ldr%?\\t%0, [%1], %2"
9355 )
9356
9357 (define_peephole
9358   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9359                          (match_operand:SI 1 "index_operand" "rJ")))
9360         (match_operand:QI 2 "s_register_operand" "r"))
9361    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9362   "TARGET_ARM
9363    && (REGNO (operands[2]) != REGNO (operands[0]))
9364    && (GET_CODE (operands[1]) != REG
9365        || (REGNO (operands[1]) != REGNO (operands[0])))"
9366   "str%?b\\t%2, [%0, %1]!"
9367 )
9368
9369 (define_peephole
9370   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9371                           [(match_operand:SI 0 "s_register_operand" "r")
9372                            (match_operand:SI 1 "const_int_operand" "n")])
9373                          (match_operand:SI 2 "s_register_operand" "+r")))
9374         (match_operand:QI 3 "s_register_operand" "r"))
9375    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9376                                (match_dup 2)))]
9377   "TARGET_ARM
9378    && (REGNO (operands[3]) != REGNO (operands[2]))
9379    && (REGNO (operands[0]) != REGNO (operands[2]))"
9380   "str%?b\\t%3, [%2, %0%S4]!"
9381 )
9382
9383 ; This pattern is never tried by combine, so do it as a peephole
9384
9385 (define_peephole2
9386   [(set (match_operand:SI 0 "s_register_operand" "")
9387         (match_operand:SI 1 "s_register_operand" ""))
9388    (set (reg:CC CC_REGNUM)
9389         (compare:CC (match_dup 1) (const_int 0)))]
9390   "TARGET_ARM
9391    && (!TARGET_CIRRUS
9392        || (!cirrus_fp_register (operands[0], SImode)
9393            && !cirrus_fp_register (operands[1], SImode)))
9394   "
9395   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9396               (set (match_dup 0) (match_dup 1))])]
9397   ""
9398 )
9399
9400 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9401 ; reversed, check that the memory references aren't volatile.
9402
9403 (define_peephole
9404   [(set (match_operand:SI 0 "s_register_operand" "=r")
9405         (match_operand:SI 4 "memory_operand" "m"))
9406    (set (match_operand:SI 1 "s_register_operand" "=r")
9407         (match_operand:SI 5 "memory_operand" "m"))
9408    (set (match_operand:SI 2 "s_register_operand" "=r")
9409         (match_operand:SI 6 "memory_operand" "m"))
9410    (set (match_operand:SI 3 "s_register_operand" "=r")
9411         (match_operand:SI 7 "memory_operand" "m"))]
9412   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9413   "*
9414   return emit_ldm_seq (operands, 4);
9415   "
9416 )
9417
9418 (define_peephole
9419   [(set (match_operand:SI 0 "s_register_operand" "=r")
9420         (match_operand:SI 3 "memory_operand" "m"))
9421    (set (match_operand:SI 1 "s_register_operand" "=r")
9422         (match_operand:SI 4 "memory_operand" "m"))
9423    (set (match_operand:SI 2 "s_register_operand" "=r")
9424         (match_operand:SI 5 "memory_operand" "m"))]
9425   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9426   "*
9427   return emit_ldm_seq (operands, 3);
9428   "
9429 )
9430
9431 (define_peephole
9432   [(set (match_operand:SI 0 "s_register_operand" "=r")
9433         (match_operand:SI 2 "memory_operand" "m"))
9434    (set (match_operand:SI 1 "s_register_operand" "=r")
9435         (match_operand:SI 3 "memory_operand" "m"))]
9436   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9437   "*
9438   return emit_ldm_seq (operands, 2);
9439   "
9440 )
9441
9442 (define_peephole
9443   [(set (match_operand:SI 4 "memory_operand" "=m")
9444         (match_operand:SI 0 "s_register_operand" "r"))
9445    (set (match_operand:SI 5 "memory_operand" "=m")
9446         (match_operand:SI 1 "s_register_operand" "r"))
9447    (set (match_operand:SI 6 "memory_operand" "=m")
9448         (match_operand:SI 2 "s_register_operand" "r"))
9449    (set (match_operand:SI 7 "memory_operand" "=m")
9450         (match_operand:SI 3 "s_register_operand" "r"))]
9451   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9452   "*
9453   return emit_stm_seq (operands, 4);
9454   "
9455 )
9456
9457 (define_peephole
9458   [(set (match_operand:SI 3 "memory_operand" "=m")
9459         (match_operand:SI 0 "s_register_operand" "r"))
9460    (set (match_operand:SI 4 "memory_operand" "=m")
9461         (match_operand:SI 1 "s_register_operand" "r"))
9462    (set (match_operand:SI 5 "memory_operand" "=m")
9463         (match_operand:SI 2 "s_register_operand" "r"))]
9464   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9465   "*
9466   return emit_stm_seq (operands, 3);
9467   "
9468 )
9469
9470 (define_peephole
9471   [(set (match_operand:SI 2 "memory_operand" "=m")
9472         (match_operand:SI 0 "s_register_operand" "r"))
9473    (set (match_operand:SI 3 "memory_operand" "=m")
9474         (match_operand:SI 1 "s_register_operand" "r"))]
9475   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9476   "*
9477   return emit_stm_seq (operands, 2);
9478   "
9479 )
9480
9481 (define_split
9482   [(set (match_operand:SI 0 "s_register_operand" "")
9483         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9484                        (const_int 0))
9485                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9486                          [(match_operand:SI 3 "s_register_operand" "")
9487                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
9488    (clobber (match_operand:SI 5 "s_register_operand" ""))]
9489   "TARGET_ARM"
9490   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9491    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9492                               (match_dup 5)))]
9493   ""
9494 )
9495
9496 ;; This split can be used because CC_Z mode implies that the following
9497 ;; branch will be an equality, or an unsigned inequality, so the sign
9498 ;; extension is not needed.
9499
9500 (define_split
9501   [(set (reg:CC_Z CC_REGNUM)
9502         (compare:CC_Z
9503          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9504                     (const_int 24))
9505          (match_operand 1 "const_int_operand" "")))
9506    (clobber (match_scratch:SI 2 ""))]
9507   "TARGET_ARM
9508    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9509        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9510   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9511    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9512   "
9513   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9514   "
9515 )
9516
9517 (define_expand "prologue"
9518   [(clobber (const_int 0))]
9519   "TARGET_EITHER"
9520   "if (TARGET_ARM)
9521      arm_expand_prologue ();
9522    else
9523      thumb_expand_prologue ();
9524   DONE;
9525   "
9526 )
9527
9528 (define_expand "epilogue"
9529   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9530   "TARGET_EITHER"
9531   "
9532   if (TARGET_THUMB)
9533     thumb_expand_epilogue ();
9534   else if (USE_RETURN_INSN (FALSE))
9535     {
9536       emit_jump_insn (gen_return ());
9537       DONE;
9538     }
9539   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9540         gen_rtvec (1,
9541                 gen_rtx_RETURN (VOIDmode)),
9542         VUNSPEC_EPILOGUE));
9543   DONE;
9544   "
9545 )
9546
9547 ;; Note - although unspec_volatile's USE all hard registers,
9548 ;; USEs are ignored after relaod has completed.  Thus we need
9549 ;; to add an unspec of the link register to ensure that flow
9550 ;; does not think that it is unused by the sibcall branch that
9551 ;; will replace the standard function epilogue.
9552 (define_insn "sibcall_epilogue"
9553   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9554               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9555   "TARGET_ARM"
9556   "*
9557   if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9558     return output_return_instruction (const_true_rtx, FALSE, FALSE);
9559   return arm_output_epilogue (next_nonnote_insn (insn));
9560   "
9561 ;; Length is absolute worst case
9562   [(set_attr "length" "44")
9563    (set_attr "type" "block")
9564    ;; We don't clobber the conditions, but the potential length of this
9565    ;; operation is sufficient to make conditionalizing the sequence 
9566    ;; unlikely to be profitable.
9567    (set_attr "conds" "clob")]
9568 )
9569
9570 (define_insn "*epilogue_insns"
9571   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9572   "TARGET_EITHER"
9573   "*
9574   if (TARGET_ARM)
9575     return arm_output_epilogue (NULL);
9576   else /* TARGET_THUMB */
9577     return thumb_unexpanded_epilogue ();
9578   "
9579   ; Length is absolute worst case
9580   [(set_attr "length" "44")
9581    (set_attr "type" "block")
9582    ;; We don't clobber the conditions, but the potential length of this
9583    ;; operation is sufficient to make conditionalizing the sequence 
9584    ;; unlikely to be profitable.
9585    (set_attr "conds" "clob")]
9586 )
9587
9588 (define_expand "eh_epilogue"
9589   [(use (match_operand:SI 0 "register_operand" ""))
9590    (use (match_operand:SI 1 "register_operand" ""))
9591    (use (match_operand:SI 2 "register_operand" ""))]
9592   "TARGET_EITHER"
9593   "
9594   {
9595     cfun->machine->eh_epilogue_sp_ofs = operands[1];
9596     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9597       {
9598         rtx ra = gen_rtx_REG (Pmode, 2);
9599
9600         emit_move_insn (ra, operands[2]);
9601         operands[2] = ra;
9602       }
9603     /* This is a hack -- we may have crystalized the function type too
9604        early.  */
9605     cfun->machine->func_type = 0;
9606   }"
9607 )
9608
9609 ;; This split is only used during output to reduce the number of patterns
9610 ;; that need assembler instructions adding to them.  We allowed the setting
9611 ;; of the conditions to be implicit during rtl generation so that
9612 ;; the conditional compare patterns would work.  However this conflicts to
9613 ;; some extent with the conditional data operations, so we have to split them
9614 ;; up again here.
9615
9616 (define_split
9617   [(set (match_operand:SI 0 "s_register_operand" "")
9618         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9619                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9620                          (match_dup 0)
9621                          (match_operand 4 "" "")))
9622    (clobber (reg:CC CC_REGNUM))]
9623   "TARGET_ARM && reload_completed"
9624   [(set (match_dup 5) (match_dup 6))
9625    (cond_exec (match_dup 7)
9626               (set (match_dup 0) (match_dup 4)))]
9627   "
9628   {
9629     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9630                                              operands[2], operands[3]);
9631     enum rtx_code rc = GET_CODE (operands[1]);
9632
9633     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9634     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9635     if (mode == CCFPmode || mode == CCFPEmode)
9636       rc = reverse_condition_maybe_unordered (rc);
9637     else
9638       rc = reverse_condition (rc);
9639
9640     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9641   }"
9642 )
9643
9644 (define_split
9645   [(set (match_operand:SI 0 "s_register_operand" "")
9646         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9647                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9648                          (match_operand 4 "" "")
9649                          (match_dup 0)))
9650    (clobber (reg:CC CC_REGNUM))]
9651   "TARGET_ARM && reload_completed"
9652   [(set (match_dup 5) (match_dup 6))
9653    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9654               (set (match_dup 0) (match_dup 4)))]
9655   "
9656   {
9657     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9658                                              operands[2], operands[3]);
9659
9660     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9661     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9662   }"
9663 )
9664
9665 (define_split
9666   [(set (match_operand:SI 0 "s_register_operand" "")
9667         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9668                           [(match_operand 2 "" "") (match_operand 3 "" "")])
9669                          (match_operand 4 "" "")
9670                          (match_operand 5 "" "")))
9671    (clobber (reg:CC CC_REGNUM))]
9672   "TARGET_ARM && reload_completed"
9673   [(set (match_dup 6) (match_dup 7))
9674    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9675               (set (match_dup 0) (match_dup 4)))
9676    (cond_exec (match_dup 8)
9677               (set (match_dup 0) (match_dup 5)))]
9678   "
9679   {
9680     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9681                                              operands[2], operands[3]);
9682     enum rtx_code rc = GET_CODE (operands[1]);
9683
9684     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9685     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9686     if (mode == CCFPmode || mode == CCFPEmode)
9687       rc = reverse_condition_maybe_unordered (rc);
9688     else
9689       rc = reverse_condition (rc);
9690
9691     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9692   }"
9693 )
9694
9695 (define_split
9696   [(set (match_operand:SI 0 "s_register_operand" "")
9697         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9698                           [(match_operand:SI 2 "s_register_operand" "")
9699                            (match_operand:SI 3 "arm_add_operand" "")])
9700                          (match_operand:SI 4 "arm_rhs_operand" "")
9701                          (not:SI
9702                           (match_operand:SI 5 "s_register_operand" ""))))
9703    (clobber (reg:CC CC_REGNUM))]
9704   "TARGET_ARM && reload_completed"
9705   [(set (match_dup 6) (match_dup 7))
9706    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9707               (set (match_dup 0) (match_dup 4)))
9708    (cond_exec (match_dup 8)
9709               (set (match_dup 0) (not:SI (match_dup 5))))]
9710   "
9711   {
9712     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9713                                              operands[2], operands[3]);
9714     enum rtx_code rc = GET_CODE (operands[1]);
9715
9716     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9717     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
9718     if (mode == CCFPmode || mode == CCFPEmode)
9719       rc = reverse_condition_maybe_unordered (rc);
9720     else
9721       rc = reverse_condition (rc);
9722
9723     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9724   }"
9725 )
9726
9727 (define_insn "*cond_move_not"
9728   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9729         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9730                           [(match_operand 3 "cc_register" "") (const_int 0)])
9731                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9732                          (not:SI
9733                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
9734   "TARGET_ARM"
9735   "@
9736    mvn%D4\\t%0, %2
9737    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9738   [(set_attr "conds" "use")
9739    (set_attr "length" "4,8")]
9740 )
9741
9742 ;; The next two patterns occur when an AND operation is followed by a
9743 ;; scc insn sequence 
9744
9745 (define_insn "*sign_extract_onebit"
9746   [(set (match_operand:SI 0 "s_register_operand" "=r")
9747         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9748                          (const_int 1)
9749                          (match_operand:SI 2 "const_int_operand" "n")))
9750     (clobber (reg:CC CC_REGNUM))]
9751   "TARGET_ARM"
9752   "*
9753     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9754     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9755     return \"mvnne\\t%0, #0\";
9756   "
9757   [(set_attr "conds" "clob")
9758    (set_attr "length" "8")]
9759 )
9760
9761 (define_insn "*not_signextract_onebit"
9762   [(set (match_operand:SI 0 "s_register_operand" "=r")
9763         (not:SI
9764          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9765                           (const_int 1)
9766                           (match_operand:SI 2 "const_int_operand" "n"))))
9767    (clobber (reg:CC CC_REGNUM))]
9768   "TARGET_ARM"
9769   "*
9770     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9771     output_asm_insn (\"tst\\t%1, %2\", operands);
9772     output_asm_insn (\"mvneq\\t%0, #0\", operands);
9773     return \"movne\\t%0, #0\";
9774   "
9775   [(set_attr "conds" "clob")
9776    (set_attr "length" "12")]
9777 )
9778
9779 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
9780 ;; expressions.  For simplicity, the first register is also in the unspec
9781 ;; part.
9782 (define_insn "*push_multi"
9783   [(match_parallel 2 "multi_register_push"
9784     [(set (match_operand:BLK 0 "memory_operand" "=m")
9785           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9786                       UNSPEC_PUSH_MULT))])]
9787   "TARGET_ARM"
9788   "*
9789   {
9790     int num_saves = XVECLEN (operands[2], 0);
9791      
9792     /* For the StrongARM at least it is faster to
9793        use STR to store only a single register.  */
9794     if (num_saves == 1)
9795       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9796     else
9797       {
9798         int i;
9799         char pattern[100];
9800
9801         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9802
9803         for (i = 1; i < num_saves; i++)
9804           {
9805             strcat (pattern, \", %|\");
9806             strcat (pattern,
9807                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9808           }
9809
9810         strcat (pattern, \"}\");
9811         output_asm_insn (pattern, operands);
9812       }
9813
9814     return \"\";
9815   }"
9816   [(set_attr "type" "store4")]
9817 )
9818
9819 (define_insn "stack_tie"
9820   [(set (mem:BLK (scratch))
9821         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9822                      (match_operand:SI 1 "s_register_operand" "r")]
9823                     UNSPEC_PRLG_STK))]
9824   ""
9825   ""
9826   [(set_attr "length" "0")]
9827 )
9828
9829 ;; Similarly for the floating point registers
9830 (define_insn "*push_fp_multi"
9831   [(match_parallel 2 "multi_register_push"
9832     [(set (match_operand:BLK 0 "memory_operand" "=m")
9833           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9834                       UNSPEC_PUSH_MULT))])]
9835   "TARGET_ARM"
9836   "*
9837   {
9838     char pattern[100];
9839
9840     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9841     output_asm_insn (pattern, operands);
9842     return \"\";
9843   }"
9844   [(set_attr "type" "f_store")]
9845 )
9846
9847 ;; Special patterns for dealing with the constant pool
9848
9849 (define_insn "align_4"
9850   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9851   "TARGET_EITHER"
9852   "*
9853   assemble_align (32);
9854   return \"\";
9855   "
9856 )
9857
9858 (define_insn "align_8"
9859   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9860   "TARGET_REALLY_IWMMXT"
9861   "*
9862   assemble_align (64);
9863   return \"\";
9864   "
9865 )
9866
9867 (define_insn "consttable_end"
9868   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9869   "TARGET_EITHER"
9870   "*
9871   making_const_table = FALSE;
9872   return \"\";
9873   "
9874 )
9875
9876 (define_insn "consttable_1"
9877   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9878   "TARGET_THUMB"
9879   "*
9880   making_const_table = TRUE;
9881   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9882   assemble_zeros (3);
9883   return \"\";
9884   "
9885   [(set_attr "length" "4")]
9886 )
9887
9888 (define_insn "consttable_2"
9889   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9890   "TARGET_THUMB"
9891   "*
9892   making_const_table = TRUE;
9893   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9894   assemble_zeros (2);
9895   return \"\";
9896   "
9897   [(set_attr "length" "4")]
9898 )
9899
9900 (define_insn "consttable_4"
9901   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9902   "TARGET_EITHER"
9903   "*
9904   {
9905     making_const_table = TRUE;
9906     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9907       {
9908       case MODE_FLOAT:
9909       {
9910         REAL_VALUE_TYPE r;
9911         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9912         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9913         break;
9914       }
9915       default:
9916         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9917         break;
9918       }
9919     return \"\";
9920   }"
9921   [(set_attr "length" "4")]
9922 )
9923
9924 (define_insn "consttable_8"
9925   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9926   "TARGET_EITHER"
9927   "*
9928   {
9929     making_const_table = TRUE;
9930     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9931       {
9932        case MODE_FLOAT:
9933         {
9934           REAL_VALUE_TYPE r;
9935           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9936           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9937           break;
9938         }
9939       default:
9940         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9941         break;
9942       }
9943     return \"\";
9944   }"
9945   [(set_attr "length" "8")]
9946 )
9947
9948 ;; Miscellaneous Thumb patterns
9949
9950 (define_expand "tablejump"
9951   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9952               (use (label_ref (match_operand 1 "" "")))])]
9953   "TARGET_THUMB"
9954   "
9955   if (flag_pic)
9956     {
9957       /* Hopefully, CSE will eliminate this copy.  */
9958       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9959       rtx reg2 = gen_reg_rtx (SImode);
9960
9961       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9962       operands[0] = reg2;
9963     }
9964   "
9965 )
9966
9967 (define_insn "*thumb_tablejump"
9968   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9969    (use (label_ref (match_operand 1 "" "")))]
9970   "TARGET_THUMB"
9971   "mov\\t%|pc, %0"
9972   [(set_attr "length" "2")]
9973 )
9974
9975 ;; V5 Instructions,
9976
9977 (define_insn "clzsi2"
9978   [(set (match_operand:SI 0 "s_register_operand" "=r")
9979         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
9980   "TARGET_ARM && arm_arch5"
9981   "clz%?\\t%0, %1"
9982   [(set_attr "predicable" "yes")])
9983
9984 (define_expand "ffssi2"
9985   [(set (match_operand:SI 0 "s_register_operand" "")
9986         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9987   "TARGET_ARM && arm_arch5"
9988   "
9989   {
9990     rtx t1, t2, t3;
9991
9992     t1 = gen_reg_rtx (SImode);
9993     t2 = gen_reg_rtx (SImode);
9994     t3 = gen_reg_rtx (SImode);
9995
9996     emit_insn (gen_negsi2 (t1, operands[1]));
9997     emit_insn (gen_andsi3 (t2, operands[1], t1));
9998     emit_insn (gen_clzsi2 (t3, t2));
9999     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10000     DONE;
10001   }"
10002 )
10003
10004 (define_expand "ctzsi2"
10005   [(set (match_operand:SI 0 "s_register_operand" "")
10006         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10007   "TARGET_ARM && arm_arch5"
10008   "
10009   {
10010     rtx t1, t2, t3;
10011
10012     t1 = gen_reg_rtx (SImode);
10013     t2 = gen_reg_rtx (SImode);
10014     t3 = gen_reg_rtx (SImode);
10015
10016     emit_insn (gen_negsi2 (t1, operands[1]));
10017     emit_insn (gen_andsi3 (t2, operands[1], t1));
10018     emit_insn (gen_clzsi2 (t3, t2));
10019     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10020     DONE;
10021   }"
10022 )
10023
10024 ;; V5E instructions.
10025
10026 (define_insn "prefetch"
10027   [(prefetch (match_operand:SI 0 "address_operand" "p")
10028              (match_operand:SI 1 "" "")
10029              (match_operand:SI 2 "" ""))]
10030   "TARGET_ARM && arm_arch5e"
10031   "pld\\t%a0")
10032
10033 ;; General predication pattern
10034
10035 (define_cond_exec
10036   [(match_operator 0 "arm_comparison_operator"
10037     [(match_operand 1 "cc_register" "")
10038      (const_int 0)])]
10039   "TARGET_ARM"
10040   ""
10041 )
10042
10043 (define_insn "prologue_use"
10044   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10045   ""
10046   "%@ %0 needed for prologue"
10047 )
10048
10049 ;; Load the FPA co-processor patterns
10050 (include "fpa.md")
10051 ;; Load the Maverick co-processor patterns
10052 (include "cirrus.md")
10053 ;; Load the Intel Wireless Multimedia Extension patterns
10054 (include "iwmmxt.md")