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