OSDN Git Service

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