OSDN Git Service

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