OSDN Git Service

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