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