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