OSDN Git Service

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