2002-02-19 Philip Blundell <pb@nexus.co.uk>
[official-gcc.git] / gcc / config / arm / arm.md
blobd1259d472b7727c08920cf73b953a720c6450a9d
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" "=l")
600         (match_operand:SI 1 "const_int_operand" "M"))
601    (set (match_dup 0)
602         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
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" "=r")
2338         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2339                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
2340                 (match_operand:SI 3 "arm_rhs_operand" "rI")))
2341    (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
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)"
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     if (i == 0)
4128       FAIL;
4130     operands[1] = GEN_INT (val >> i);
4131     operands[2] = GEN_INT (i);
4132   }"
4135 (define_expand "movaddr"
4136   [(set (match_operand:SI 0 "s_register_operand" "")
4137         (match_operand:DI 1 "address_operand" ""))]
4138   "TARGET_ARM"
4139   ""
4142 (define_insn "*movaddr_insn"
4143   [(set (match_operand:SI 0 "s_register_operand" "=r")
4144         (match_operand:DI 1 "address_operand" "p"))]
4145   "TARGET_ARM
4146    && reload_completed
4147    && (GET_CODE (operands[1]) == LABEL_REF
4148        || (GET_CODE (operands[1]) == CONST
4149            && GET_CODE (XEXP (operands[1], 0)) == PLUS
4150            && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
4151            && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
4152   "adr%?\\t%0, %a1"
4153   [(set_attr "predicable" "yes")]
4156 ;; When generating pic, we need to load the symbol offset into a register.
4157 ;; So that the optimizer does not confuse this with a normal symbol load
4158 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4159 ;; since that is the only type of relocation we can use.
4161 ;; The rather odd constraints on the following are to force reload to leave
4162 ;; the insn alone, and to force the minipool generation pass to then move
4163 ;; the GOT symbol to memory.
4165 (define_insn "pic_load_addr_arm"
4166   [(set (match_operand:SI 0 "s_register_operand" "=r")
4167         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4168   "TARGET_ARM && flag_pic"
4169   "ldr%?\\t%0, %1"
4170   [(set_attr "type" "load")
4171    (set (attr "pool_range")     (const_int 4096))
4172    (set (attr "neg_pool_range") (const_int 4084))]
4175 (define_insn "pic_load_addr_thumb"
4176   [(set (match_operand:SI 0 "s_register_operand" "=l")
4177         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4178   "TARGET_THUMB && flag_pic"
4179   "ldr\\t%0, %1"
4180   [(set_attr "type" "load")
4181    (set (attr "pool_range") (const_int 1024))]
4184 ;; This variant is used for AOF assembly, since it needs to mention the
4185 ;; pic register in the rtl.
4186 (define_expand "pic_load_addr_based"
4187   [(set (match_operand:SI 0 "s_register_operand" "=r")
4188         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4189   "TARGET_ARM && flag_pic"
4190   "operands[2] = pic_offset_table_rtx;"
4193 (define_insn "*pic_load_addr_based_insn"
4194   [(set (match_operand:SI 0 "s_register_operand" "=r")
4195         (unspec:SI [(match_operand 1 "" "")
4196                     (match_operand 2 "s_register_operand" "r")]
4197                    UNSPEC_PIC_SYM))]
4198   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4199   "*
4200 #ifdef AOF_ASSEMBLER
4201   operands[1] = aof_pic_entry (operands[1]);
4202 #endif
4203   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4204   return \"\";
4205   "
4206   [(set_attr "type" "load")
4207    (set (attr "pool_range")
4208         (if_then_else (eq_attr "is_thumb" "yes")
4209                       (const_int 1024)
4210                       (const_int 4096)))
4211    (set (attr "neg_pool_range")
4212         (if_then_else (eq_attr "is_thumb" "yes")
4213                       (const_int 0)
4214                       (const_int 4084)))]
4217 (define_insn "pic_add_dot_plus_four"
4218   [(set (match_operand:SI 0 "register_operand" "+r")
4219         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4220    (use (label_ref (match_operand 1 "" "")))]
4221   "TARGET_THUMB && flag_pic"
4222   "*
4223   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4224                              CODE_LABEL_NUMBER (operands[1]));
4225   return \"add\\t%0, %|pc\";
4226   "
4227   [(set_attr "length" "2")]
4230 (define_insn "pic_add_dot_plus_eight"
4231   [(set (match_operand:SI 0 "register_operand" "+r")
4232         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4233    (use (label_ref (match_operand 1 "" "")))]
4234   "TARGET_ARM && flag_pic"
4235   "*
4236     ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4237                                CODE_LABEL_NUMBER (operands[1]));
4238     return \"add%?\\t%0, %|pc, %0\";
4239   "
4240   [(set_attr "predicable" "yes")]
4243 (define_expand "builtin_setjmp_receiver"
4244   [(label_ref (match_operand 0 "" ""))]
4245   "flag_pic"
4246   "
4248   arm_finalize_pic (0);
4249   DONE;
4252 ;; If copying one reg to another we can set the condition codes according to
4253 ;; its value.  Such a move is common after a return from subroutine and the
4254 ;; result is being tested against zero.
4256 (define_insn "*movsi_compare0"
4257   [(set (reg:CC CC_REGNUM)
4258         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4259                     (const_int 0)))
4260    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4261         (match_dup 1))]
4262   "TARGET_ARM"
4263   "@
4264    cmp%?\\t%0, #0
4265    sub%?s\\t%0, %1, #0"
4266   [(set_attr "conds" "set")]
4269 ;; Subroutine to store a half word from a register into memory.
4270 ;; Operand 0 is the source register (HImode)
4271 ;; Operand 1 is the destination address in a register (SImode)
4273 ;; In both this routine and the next, we must be careful not to spill
4274 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4275 ;; can generate unrecognizable rtl.
4277 (define_expand "storehi"
4278   [;; store the low byte
4279    (set (match_operand 1 "" "") (match_dup 3))
4280    ;; extract the high byte
4281    (set (match_dup 2)
4282         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4283    ;; store the high byte
4284    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
4285   "TARGET_ARM"
4286   "
4287   {
4288     rtx op1 = operands[1];
4289     rtx addr = XEXP (op1, 0);
4290     enum rtx_code code = GET_CODE (addr);
4292     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4293         || code == MINUS)
4294       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4296     operands[4] = adjust_address (op1, QImode, 1);
4297     operands[1] = adjust_address (operands[1], QImode, 0);
4298     operands[3] = gen_lowpart (QImode, operands[0]);
4299     operands[0] = gen_lowpart (SImode, operands[0]);
4300     operands[2] = gen_reg_rtx (SImode); 
4301   }"
4304 (define_expand "storehi_bigend"
4305   [(set (match_dup 4) (match_dup 3))
4306    (set (match_dup 2)
4307         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4308    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
4309   "TARGET_ARM"
4310   "
4311   {
4312     rtx op1 = operands[1];
4313     rtx addr = XEXP (op1, 0);
4314     enum rtx_code code = GET_CODE (addr);
4316     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4317         || code == MINUS)
4318       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4320     operands[4] = adjust_address (op1, QImode, 1);
4321     operands[1] = adjust_address (operands[1], QImode, 0);
4322     operands[3] = gen_lowpart (QImode, operands[0]);
4323     operands[0] = gen_lowpart (SImode, operands[0]);
4324     operands[2] = gen_reg_rtx (SImode);
4325   }"
4328 ;; Subroutine to store a half word integer constant into memory.
4329 (define_expand "storeinthi"
4330   [(set (match_operand 0 "" "")
4331         (subreg:QI (match_operand 1 "" "") 0))
4332    (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
4333   "TARGET_ARM"
4334   "
4335   {
4336     HOST_WIDE_INT value = INTVAL (operands[1]);
4337     rtx addr = XEXP (operands[0], 0);
4338     rtx op0 = operands[0];
4339     enum rtx_code code = GET_CODE (addr);
4341     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4342         || code == MINUS)
4343       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4345     operands[1] = gen_reg_rtx (SImode);
4346     if (BYTES_BIG_ENDIAN)
4347       {
4348         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4349         if ((value & 255) == ((value >> 8) & 255))
4350           operands[2] = operands[1];
4351         else
4352           {
4353             operands[2] = gen_reg_rtx (SImode);
4354             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4355           }
4356       }
4357     else
4358       {
4359         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4360         if ((value & 255) == ((value >> 8) & 255))
4361           operands[2] = operands[1];
4362         else
4363           {
4364             operands[2] = gen_reg_rtx (SImode);
4365             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4366           }
4367       }
4369     operands[3] = adjust_address (op0, QImode, 1);
4370     operands[0] = adjust_address (operands[0], QImode, 0);
4371   }"
4374 (define_expand "storehi_single_op"
4375   [(set (match_operand:HI 0 "memory_operand" "")
4376         (match_operand:HI 1 "general_operand" ""))]
4377   "TARGET_ARM && arm_arch4"
4378   "
4379   if (!s_register_operand (operands[1], HImode))
4380     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4381   "
4384 (define_expand "movhi"
4385   [(set (match_operand:HI 0 "general_operand" "")
4386         (match_operand:HI 1 "general_operand" ""))]
4387   "TARGET_EITHER"
4388   "
4389   if (TARGET_ARM)
4390     {
4391       if (!no_new_pseudos)
4392         {
4393           if (GET_CODE (operands[0]) == MEM)
4394             {
4395               if (arm_arch4)
4396                 {
4397                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4398                   DONE;
4399                 }
4400               if (GET_CODE (operands[1]) == CONST_INT)
4401                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4402               else
4403                 {
4404                   if (GET_CODE (operands[1]) == MEM)
4405                     operands[1] = force_reg (HImode, operands[1]);
4406                   if (BYTES_BIG_ENDIAN)
4407                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4408                   else
4409                    emit_insn (gen_storehi (operands[1], operands[0]));
4410                 }
4411               DONE;
4412             }
4413           /* Sign extend a constant, and keep it in an SImode reg.  */
4414           else if (GET_CODE (operands[1]) == CONST_INT)
4415             {
4416               rtx reg = gen_reg_rtx (SImode);
4417               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4419               /* If the constant is already valid, leave it alone.  */
4420               if (!const_ok_for_arm (val))
4421                 {
4422                   /* If setting all the top bits will make the constant 
4423                      loadable in a single instruction, then set them.  
4424                      Otherwise, sign extend the number.  */
4426                   if (const_ok_for_arm (~(val | ~0xffff)))
4427                     val |= ~0xffff;
4428                   else if (val & 0x8000)
4429                     val |= ~0xffff;
4430                 }
4432               emit_insn (gen_movsi (reg, GEN_INT (val)));
4433               operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
4434             }
4435           else if (!arm_arch4)
4436             {
4437              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4438                 for v4 and up architectures because LDRH instructions will
4439                 be used to access the HI values, and these cannot generate
4440                 unaligned word access faults in the MMU.  */
4441               if (GET_CODE (operands[1]) == MEM)
4442                 {
4443                   if (TARGET_MMU_TRAPS)
4444                     {
4445                       rtx base;
4446                       rtx offset = const0_rtx;
4447                       rtx reg = gen_reg_rtx (SImode);
4449                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4450                            || (GET_CODE (base) == PLUS
4451                                && (GET_CODE (offset = XEXP (base, 1))
4452                                    == CONST_INT)
4453                                && ((INTVAL(offset) & 1) != 1)
4454                                && GET_CODE (base = XEXP (base, 0)) == REG))
4455                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4456                         {
4457                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4458                           rtx new;
4460                           new = gen_rtx_MEM (SImode,
4461                                              plus_constant (base, new_offset));
4462                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4463                           emit_insn (gen_movsi (reg, new));
4464                           if (((INTVAL (offset) & 2) != 0)
4465                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4466                             {
4467                               rtx reg2 = gen_reg_rtx (SImode);
4469                               emit_insn (gen_lshrsi3 (reg2, reg,
4470                                          GEN_INT (16)));
4471                               reg = reg2;
4472                             }
4473                         }
4474                       else
4475                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4477                       operands[1] = gen_lowpart (HImode, reg);
4478                     }
4479                   else if (BYTES_BIG_ENDIAN)
4480                     {
4481                       rtx base;
4482                       rtx offset = const0_rtx;
4484                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4485                            || (GET_CODE (base) == PLUS
4486                               && (GET_CODE (offset = XEXP (base, 1))
4487                                   == CONST_INT)
4488                               && GET_CODE (base = XEXP (base, 0)) == REG))
4489                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4490                         {
4491                           rtx reg = gen_reg_rtx (SImode);
4492                           rtx new;
4494                           if ((INTVAL (offset) & 2) == 2)
4495                             {
4496                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4497                               new = gen_rtx_MEM (SImode,
4498                                                  plus_constant (base,
4499                                                                 new_offset));
4500                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4501                               emit_insn (gen_movsi (reg, new));
4502                             }
4503                           else
4504                             {
4505                               new = gen_rtx_MEM (SImode,
4506                                                  XEXP (operands[1], 0));
4507                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4508                               emit_insn (gen_rotated_loadsi (reg, new));
4509                             }
4511                           operands[1] = gen_lowpart (HImode, reg);
4512                         }
4513                       else
4514                         {
4515                           emit_insn (gen_movhi_bigend (operands[0],
4516                                                        operands[1]));
4517                           DONE;
4518                         }
4519                     }
4520                }
4521            }
4522         }
4523       /* Handle loading a large integer during reload */
4524       else if (GET_CODE (operands[1]) == CONST_INT
4525                && !const_ok_for_arm (INTVAL (operands[1]))
4526                && !const_ok_for_arm (~INTVAL (operands[1])))
4527         {
4528           /* Writing a constant to memory needs a scratch, which should
4529              be handled with SECONDARY_RELOADs.  */
4530           if (GET_CODE (operands[0]) != REG)
4531             abort ();
4533           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4534           emit_insn (gen_movsi (operands[0], operands[1]));
4535           DONE;
4536        }
4537     }
4538   else /* TARGET_THUMB */
4539     {
4540       if (!no_new_pseudos)
4541         {
4542           if (GET_CODE (operands[0]) != REG)
4543             operands[1] = force_reg (HImode, operands[1]);
4545           /* ??? We shouldn't really get invalid addresses here, but this can
4546              happen if we are passed a SP (never OK for HImode/QImode) or 
4547              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4548              HImode/QImode) relative address.  */
4549           /* ??? This should perhaps be fixed elsewhere, for instance, in
4550              fixup_stack_1, by checking for other kinds of invalid addresses,
4551              e.g. a bare reference to a virtual register.  This may confuse the
4552              alpha though, which must handle this case differently.  */
4553           if (GET_CODE (operands[0]) == MEM
4554               && !memory_address_p (GET_MODE (operands[0]),
4555                                     XEXP (operands[0], 0)))
4556             operands[0]
4557               = replace_equiv_address (operands[0],
4558                                        copy_to_reg (XEXP (operands[0], 0)));
4559    
4560           if (GET_CODE (operands[1]) == MEM
4561               && !memory_address_p (GET_MODE (operands[1]),
4562                                     XEXP (operands[1], 0)))
4563             operands[1]
4564               = replace_equiv_address (operands[1],
4565                                        copy_to_reg (XEXP (operands[1], 0)));
4566         }
4567       /* Handle loading a large integer during reload */
4568       else if (GET_CODE (operands[1]) == CONST_INT
4569                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4570         {
4571           /* Writing a constant to memory needs a scratch, which should
4572              be handled with SECONDARY_RELOADs.  */
4573           if (GET_CODE (operands[0]) != REG)
4574             abort ();
4576           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4577           emit_insn (gen_movsi (operands[0], operands[1]));
4578           DONE;
4579         }
4580     }
4581   "
4584 (define_insn "*thumb_movhi_insn"
4585   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4586         (match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4587   "TARGET_THUMB
4588    && (   register_operand (operands[0], HImode)
4589        || register_operand (operands[1], HImode))"
4590   "*
4591   switch (which_alternative)
4592     {
4593     case 0: return \"add        %0, %1, #0\";
4594     case 2: return \"strh       %1, %0\";
4595     case 3: return \"mov        %0, %1\";
4596     case 4: return \"mov        %0, %1\";
4597     case 5: return \"mov        %0, %1\";
4598     default: abort ();
4599     case 1:
4600       /* The stack pointer can end up being taken as an index register.
4601           Catch this case here and deal with it.  */
4602       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4603           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4604           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4605         {
4606           rtx ops[2];
4607           ops[0] = operands[0];
4608           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4609       
4610           output_asm_insn (\"mov        %0, %1\", ops);
4612           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4613     
4614         }
4615       return \"ldrh     %0, %1\";
4616     }"
4617   [(set_attr "length" "2,4,2,2,2,2")
4618    (set_attr "type" "*,load,store1,*,*,*")
4619    (set_attr "pool_range" "*,64,*,*,*,*")]
4623 (define_insn "rotated_loadsi"
4624   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4625         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4626                    (const_int 16)))]
4627   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4628   "*
4629   {
4630     rtx ops[2];
4632     ops[0] = operands[0];
4633     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4634     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4635     return \"\";
4636   }"
4637   [(set_attr "type" "load")
4638    (set_attr "predicable" "yes")]
4641 (define_expand "movhi_bytes"
4642   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4643    (set (match_dup 3)
4644         (zero_extend:SI (match_dup 6)))
4645    (set (match_operand:SI 0 "" "")
4646          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4647   "TARGET_ARM"
4648   "
4649   {
4650     rtx mem1, mem2;
4651     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4653     mem1 = gen_rtx_MEM (QImode, addr);
4654     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4655     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4656     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4657     operands[0] = gen_lowpart (SImode, operands[0]);
4658     operands[1] = mem1;
4659     operands[2] = gen_reg_rtx (SImode);
4660     operands[3] = gen_reg_rtx (SImode);
4661     operands[6] = mem2;
4663     if (BYTES_BIG_ENDIAN)
4664       {
4665         operands[4] = operands[2];
4666         operands[5] = operands[3];
4667       }
4668     else
4669       {
4670         operands[4] = operands[3];
4671         operands[5] = operands[2];
4672       }
4673   }"
4676 (define_expand "movhi_bigend"
4677   [(set (match_dup 2)
4678         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4679                    (const_int 16)))
4680    (set (match_dup 3)
4681         (ashiftrt:SI (match_dup 2) (const_int 16)))
4682    (set (match_operand:HI 0 "s_register_operand" "")
4683         (subreg:HI (match_dup 3) 0))]
4684   "TARGET_ARM"
4685   "
4686   operands[2] = gen_reg_rtx (SImode);
4687   operands[3] = gen_reg_rtx (SImode);
4688   "
4691 ;; Pattern to recognise insn generated default case above
4692 (define_insn "*movhi_insn_arch4"
4693   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4694         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4695   "TARGET_ARM
4696    && arm_arch4
4697    && (GET_CODE (operands[1]) != CONST_INT
4698        || const_ok_for_arm (INTVAL (operands[1]))
4699        || const_ok_for_arm (~INTVAL (operands[1])))"
4700   "@
4701    mov%?\\t%0, %1\\t%@ movhi
4702    mvn%?\\t%0, #%B1\\t%@ movhi
4703    str%?h\\t%1, %0\\t%@ movhi 
4704    ldr%?h\\t%0, %1\\t%@ movhi"
4705   [(set_attr "type" "*,*,store1,load")
4706    (set_attr "predicable" "yes")
4707    (set_attr "pool_range" "*,*,*,256")
4708    (set_attr "neg_pool_range" "*,*,*,244")]
4711 (define_insn "*movhi_insn_littleend"
4712   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4713         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4714   "TARGET_ARM
4715    && !arm_arch4
4716    && !BYTES_BIG_ENDIAN
4717    && !TARGET_MMU_TRAPS
4718    && (GET_CODE (operands[1]) != CONST_INT
4719        || const_ok_for_arm (INTVAL (operands[1]))
4720        || const_ok_for_arm (~INTVAL (operands[1])))"
4721   "@
4722    mov%?\\t%0, %1\\t%@ movhi
4723    mvn%?\\t%0, #%B1\\t%@ movhi
4724    ldr%?\\t%0, %1\\t%@ movhi"
4725   [(set_attr "type" "*,*,load")
4726    (set_attr "predicable" "yes")
4727    (set_attr "pool_range" "4096")
4728    (set_attr "neg_pool_range" "4084")]
4731 (define_insn "*movhi_insn_bigend"
4732   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4733         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4734   "TARGET_ARM
4735    && !arm_arch4
4736    && BYTES_BIG_ENDIAN
4737    && !TARGET_MMU_TRAPS
4738    && (GET_CODE (operands[1]) != CONST_INT
4739        || const_ok_for_arm (INTVAL (operands[1]))
4740        || const_ok_for_arm (~INTVAL (operands[1])))"
4741   "@
4742    mov%?\\t%0, %1\\t%@ movhi
4743    mvn%?\\t%0, #%B1\\t%@ movhi
4744    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4745   [(set_attr "type" "*,*,load")
4746    (set_attr "predicable" "yes")
4747    (set_attr "length" "4,4,8")
4748    (set_attr "pool_range" "*,*,4092")
4749    (set_attr "neg_pool_range" "*,*,4084")]
4752 (define_insn "*loadhi_si_bigend"
4753   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4754         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4755                    (const_int 16)))]
4756   "TARGET_ARM
4757    && BYTES_BIG_ENDIAN
4758    && !TARGET_MMU_TRAPS"
4759   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4760   [(set_attr "type" "load")
4761    (set_attr "predicable" "yes")
4762    (set_attr "pool_range" "4096")
4763    (set_attr "neg_pool_range" "4084")]
4766 (define_insn "*movhi_bytes"
4767   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4768         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4769   "TARGET_ARM && TARGET_MMU_TRAPS"
4770   "@
4771    mov%?\\t%0, %1\\t%@ movhi
4772    mvn%?\\t%0, #%B1\\t%@ movhi"
4773   [(set_attr "predicable" "yes")]
4776 (define_insn "thumb_movhi_clobber"
4777   [(set (match_operand:HI     0 "memory_operand"   "=m")
4778         (match_operand:HI     1 "register_operand" "l"))
4779    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4780   "TARGET_THUMB"
4781   "*
4782   abort ();"
4784         
4785 ;; We use a DImode scratch because we may occasionally need an additional
4786 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4787 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4788 (define_expand "reload_outhi"
4789   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4790               (match_operand:HI 1 "s_register_operand"        "r")
4791               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4792   "TARGET_EITHER"
4793   "if (TARGET_ARM)
4794      arm_reload_out_hi (operands);
4795    else
4796      thumb_reload_out_hi (operands);
4797   DONE;
4798   "
4801 (define_expand "reload_inhi"
4802   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4803               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4804               (match_operand:DI 2 "s_register_operand" "=&r")])]
4805   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4806   "
4807   if (TARGET_ARM)
4808     arm_reload_in_hi (operands);
4809   else
4810     thumb_reload_out_hi (operands);
4811   DONE;
4814 (define_expand "movqi"
4815   [(set (match_operand:QI 0 "general_operand" "")
4816         (match_operand:QI 1 "general_operand" ""))]
4817   "TARGET_EITHER"
4818   "
4819   if (TARGET_ARM)
4820     {
4821       /* Everything except mem = const or mem = mem can be done easily */
4823       if (!no_new_pseudos)
4824         {
4825           if (GET_CODE (operands[1]) == CONST_INT)
4826             {
4827               rtx reg = gen_reg_rtx (SImode);
4829               emit_insn (gen_movsi (reg, operands[1]));
4830               operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
4831             }
4832          if (GET_CODE (operands[0]) == MEM)
4833            operands[1] = force_reg (QImode, operands[1]);
4834        }
4835     }
4836   else /* TARGET_THUMB */
4837     {
4838       if (!no_new_pseudos)
4839         {
4840           if (GET_CODE (operands[0]) != REG)
4841             operands[1] = force_reg (QImode, operands[1]);
4843           /* ??? We shouldn't really get invalid addresses here, but this can
4844              happen if we are passed a SP (never OK for HImode/QImode) or
4845              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4846              HImode/QImode) relative address.  */
4847           /* ??? This should perhaps be fixed elsewhere, for instance, in
4848              fixup_stack_1, by checking for other kinds of invalid addresses,
4849              e.g. a bare reference to a virtual register.  This may confuse the
4850              alpha though, which must handle this case differently.  */
4851           if (GET_CODE (operands[0]) == MEM
4852               && !memory_address_p (GET_MODE (operands[0]),
4853                                      XEXP (operands[0], 0)))
4854             operands[0]
4855               = replace_equiv_address (operands[0],
4856                                        copy_to_reg (XEXP (operands[0], 0)));
4857           if (GET_CODE (operands[1]) == MEM
4858               && !memory_address_p (GET_MODE (operands[1]),
4859                                     XEXP (operands[1], 0)))
4860              operands[1]
4861                = replace_equiv_address (operands[1],
4862                                         copy_to_reg (XEXP (operands[1], 0)));
4863         }
4864       /* Handle loading a large integer during reload */
4865       else if (GET_CODE (operands[1]) == CONST_INT
4866                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4867         {
4868           /* Writing a constant to memory needs a scratch, which should
4869              be handled with SECONDARY_RELOADs.  */
4870           if (GET_CODE (operands[0]) != REG)
4871             abort ();
4873           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4874           emit_insn (gen_movsi (operands[0], operands[1]));
4875           DONE;
4876        }
4877     }
4878   "
4882 (define_insn "*arm_movqi_insn"
4883   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4884         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4885   "TARGET_ARM
4886    && (   register_operand (operands[0], QImode)
4887        || register_operand (operands[1], QImode))"
4888   "@
4889    mov%?\\t%0, %1
4890    mvn%?\\t%0, #%B1
4891    ldr%?b\\t%0, %1
4892    str%?b\\t%1, %0"
4893   [(set_attr "type" "*,*,load,store1")
4894    (set_attr "predicable" "yes")]
4897 (define_insn "*thumb_movqi_insn"
4898   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4899         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4900   "TARGET_THUMB
4901    && (   register_operand (operands[0], QImode)
4902        || register_operand (operands[1], QImode))"
4903   "@
4904    add\\t%0, %1, #0
4905    ldrb\\t%0, %1
4906    strb\\t%1, %0
4907    mov\\t%0, %1
4908    mov\\t%0, %1
4909    mov\\t%0, %1"
4910   [(set_attr "length" "2")
4911    (set_attr "type" "*,load,store1,*,*,*")
4912    (set_attr "pool_range" "*,32,*,*,*,*")]
4915 (define_expand "movsf"
4916   [(set (match_operand:SF 0 "general_operand" "")
4917         (match_operand:SF 1 "general_operand" ""))]
4918   "TARGET_EITHER"
4919   "
4920   if (TARGET_ARM)
4921     {
4922       if (GET_CODE (operands[0]) == MEM)
4923         operands[1] = force_reg (SFmode, operands[1]);
4924     }
4925   else /* TARGET_THUMB */
4926     {
4927       if (!no_new_pseudos)
4928         {
4929            if (GET_CODE (operands[0]) != REG)
4930              operands[1] = force_reg (SFmode, operands[1]);
4931         }
4932     }
4933   "
4936 (define_split
4937   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4938         (match_operand:SF 1 "immediate_operand" ""))]
4939   "TARGET_ARM
4940    && !TARGET_HARD_FLOAT
4941    && reload_completed
4942    && GET_CODE (operands[1]) == CONST_DOUBLE"
4943   [(set (match_dup 2) (match_dup 3))]
4944   "
4945   operands[2] = gen_lowpart (SImode, operands[0]);
4946   operands[3] = gen_lowpart (SImode, operands[1]);
4947   if (operands[2] == 0 || operands[3] == 0)
4948     FAIL;
4949   "
4952 (define_insn "*arm_movsf_hard_insn"
4953   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4954         (match_operand:SF 1 "general_operand"      "fG,H,mE,f,r,f,r,mE,r"))]
4955   "TARGET_ARM
4956    && TARGET_HARD_FLOAT
4957    && (GET_CODE (operands[0]) != MEM
4958        || register_operand (operands[1], SFmode))"
4959   "@
4960    mvf%?s\\t%0, %1
4961    mnf%?s\\t%0, #%N1
4962    ldf%?s\\t%0, %1
4963    stf%?s\\t%1, %0
4964    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4965    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4966    mov%?\\t%0, %1
4967    ldr%?\\t%0, %1\\t%@ float
4968    str%?\\t%1, %0\\t%@ float"
4969   [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4970    (set_attr "predicable" "yes")
4971    (set_attr "type"
4972          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4973    (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4974    (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4977 ;; Exactly the same as above, except that all `f' cases are deleted.
4978 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4979 ;; when -msoft-float.
4981 (define_insn "*arm_movsf_soft_insn"
4982   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4983         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4984   "TARGET_ARM
4985    && TARGET_SOFT_FLOAT
4986    && (GET_CODE (operands[0]) != MEM
4987        || register_operand (operands[1], SFmode))"
4988   "@
4989    mov%?\\t%0, %1
4990    ldr%?\\t%0, %1\\t%@ float
4991    str%?\\t%1, %0\\t%@ float"
4992   [(set_attr "length" "4,4,4")
4993    (set_attr "predicable" "yes")
4994    (set_attr "type" "*,load,store1")
4995    (set_attr "pool_range" "*,4096,*")
4996    (set_attr "neg_pool_range" "*,4084,*")]
4999 ;;; ??? This should have alternatives for constants.
5000 (define_insn "*thumb_movsf_insn"
5001   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5002         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5003   "TARGET_THUMB
5004    && (   register_operand (operands[0], SFmode) 
5005        || register_operand (operands[1], SFmode))"
5006   "@
5007    add\\t%0, %1, #0
5008    ldmia\\t%1, {%0}
5009    stmia\\t%0, {%1}
5010    ldr\\t%0, %1
5011    str\\t%1, %0
5012    mov\\t%0, %1
5013    mov\\t%0, %1"
5014   [(set_attr "length" "2")
5015    (set_attr "type" "*,load,store1,load,store1,*,*")
5016    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5019 (define_expand "movdf"
5020   [(set (match_operand:DF 0 "general_operand" "")
5021         (match_operand:DF 1 "general_operand" ""))]
5022   "TARGET_EITHER"
5023   "
5024   if (TARGET_ARM)
5025     {
5026       if (GET_CODE (operands[0]) == MEM)
5027         operands[1] = force_reg (DFmode, operands[1]);
5028     }
5029   else /* TARGET_THUMB */
5030     {
5031       if (!no_new_pseudos)
5032         {
5033           if (GET_CODE (operands[0]) != REG)
5034             operands[1] = force_reg (DFmode, operands[1]);
5035         }
5036     }
5037   "
5040 ;; Reloading a df mode value stored in integer regs to memory can require a
5041 ;; scratch reg.
5042 (define_expand "reload_outdf"
5043   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5044    (match_operand:DF 1 "s_register_operand" "r")
5045    (match_operand:SI 2 "s_register_operand" "=&r")]
5046   "TARGET_ARM"
5047   "
5048   {
5049     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5051     if (code == REG)
5052       operands[2] = XEXP (operands[0], 0);
5053     else if (code == POST_INC || code == PRE_DEC)
5054       {
5055         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5056         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5057         emit_insn (gen_movdi (operands[0], operands[1]));
5058         DONE;
5059       }
5060     else if (code == PRE_INC)
5061       {
5062         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5064         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5065         operands[2] = reg;
5066       }
5067     else if (code == POST_DEC)
5068       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5069     else
5070       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5071                              XEXP (XEXP (operands[0], 0), 1)));
5073     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5074                             operands[1]));
5076     if (code == POST_DEC)
5077       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5079     DONE;
5080   }"
5083 (define_insn "*movdf_hard_insn"
5084   [(set (match_operand:DF 0 "nonimmediate_operand"
5085                                                 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5086         (match_operand:DF 1 "general_operand"
5087                                                 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5088   "TARGET_ARM
5089    && TARGET_HARD_FLOAT
5090    && (GET_CODE (operands[0]) != MEM
5091        || register_operand (operands[1], DFmode))"
5092   "*
5093   {
5094   switch (which_alternative)
5095     {
5096     default:
5097     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5098     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5099     case 2: case 3: case 4: return output_move_double (operands);
5100     case 5: return \"mvf%?d\\t%0, %1\";
5101     case 6: return \"mnf%?d\\t%0, #%N1\";
5102     case 7: return \"ldf%?d\\t%0, %1\";
5103     case 8: return \"stf%?d\\t%1, %0\";
5104     case 9: return output_mov_double_fpu_from_arm (operands);
5105     case 10: return output_mov_double_arm_from_fpu (operands);
5106     }
5107   }
5108   "
5109   [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5110    (set_attr "predicable" "yes")
5111    (set_attr "type"
5112     "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5113    (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")
5114    (set_attr "neg_pool_range" "*,*,*,*,244,*,*,1012,*,*,*")]
5117 ;; Software floating point version.  This is essentially the same as movdi.
5118 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5119 ;; an `f' reg.
5121 (define_insn "*movdf_soft_insn"
5122   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5123         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5124   "TARGET_ARM && TARGET_SOFT_FLOAT
5125   "
5126   "* return output_move_double (operands);"
5127   [(set_attr "length" "8,8,8")
5128    (set_attr "type" "*,load,store2")
5129    (set_attr "pool_range" "252")
5130    (set_attr "neg_pool_range" "244")]
5133 ;;; ??? This should have alternatives for constants.
5134 ;;; ??? This was originally identical to the movdi_insn pattern.
5135 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5136 ;;; thumb_reorg with a memory reference.
5137 (define_insn "*thumb_movdf_insn"
5138   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5139         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5140   "TARGET_THUMB
5141    && (   register_operand (operands[0], DFmode)
5142        || register_operand (operands[1], DFmode))"
5143   "*
5144   switch (which_alternative)
5145     {
5146     default:
5147     case 0:
5148       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5149         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5150       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5151     case 1:
5152       return \"ldmia\\t%1, {%0, %H0}\";
5153     case 2:
5154       return \"stmia\\t%0, {%1, %H1}\";
5155     case 3:
5156       return thumb_load_double_from_address (operands);
5157     case 4:
5158       operands[2] = gen_rtx (MEM, SImode,
5159                              plus_constant (XEXP (operands[0], 0), 4));
5160       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5161       return \"\";
5162     case 5:
5163       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5164         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5165       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5166     }
5167   "
5168   [(set_attr "length" "4,2,2,6,4,4")
5169    (set_attr "type" "*,load,store2,load,store2,*")
5170    (set_attr "pool_range" "*,*,*,1020,*,*")]
5174 (define_expand "movxf"
5175   [(set (match_operand:XF 0 "general_operand" "")
5176         (match_operand:XF 1 "general_operand" ""))]
5177   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5178   "")
5180 ;; Even when the XFmode patterns aren't enabled, we enable this after
5181 ;; reloading so that we can push floating point registers in the prologue.
5183 (define_insn "*movxf_hard_insn"
5184   [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5185         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5186   "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5187   "*
5188   switch (which_alternative)
5189     {
5190     default:
5191     case 0: return \"mvf%?e\\t%0, %1\";
5192     case 1: return \"mnf%?e\\t%0, #%N1\";
5193     case 2: return \"ldf%?e\\t%0, %1\";
5194     case 3: return \"stf%?e\\t%1, %0\";
5195     case 4: return output_mov_long_double_fpu_from_arm (operands);
5196     case 5: return output_mov_long_double_arm_from_fpu (operands);
5197     case 6: return output_mov_long_double_arm_from_arm (operands);
5198     }
5199   "
5200   [(set_attr "length" "4,4,4,4,8,8,12")
5201    (set_attr "predicable" "yes")
5202    (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5203    (set_attr "pool_range" "*,*,1024,*,*,*,*")
5204    (set_attr "neg_pool_range" "*,*,1012,*,*,*,*")]
5208 ;; load- and store-multiple insns
5209 ;; The arm can load/store any set of registers, provided that they are in
5210 ;; ascending order; but that is beyond GCC so stick with what it knows.
5212 (define_expand "load_multiple"
5213   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5214                           (match_operand:SI 1 "" ""))
5215                      (use (match_operand:SI 2 "" ""))])]
5216   "TARGET_ARM"
5217   "
5218   /* Support only fixed point registers.  */
5219   if (GET_CODE (operands[2]) != CONST_INT
5220       || INTVAL (operands[2]) > 14
5221       || INTVAL (operands[2]) < 2
5222       || GET_CODE (operands[1]) != MEM
5223       || GET_CODE (operands[0]) != REG
5224       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5225       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5226     FAIL;
5228   operands[3]
5229     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5230                              force_reg (SImode, XEXP (operands[1], 0)),
5231                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5232                              MEM_IN_STRUCT_P(operands[1]),
5233                              MEM_SCALAR_P (operands[1]));
5234   "
5237 ;; Load multiple with write-back
5239 (define_insn "*ldmsi_postinc4"
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 16)))
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      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5251           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5252   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5253   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5254   [(set_attr "type" "load")
5255    (set_attr "predicable" "yes")]
5258 (define_insn "*ldmsi_postinc3"
5259   [(match_parallel 0 "load_multiple_operation"
5260     [(set (match_operand:SI 1 "s_register_operand" "=r")
5261           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5262                    (const_int 12)))
5263      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5264           (mem:SI (match_dup 2)))
5265      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5266           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5267      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5268           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5269   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5270   "ldm%?ia\\t%1!, {%3, %4, %5}"
5271   [(set_attr "type" "load")
5272    (set_attr "predicable" "yes")]
5275 (define_insn "*ldmsi_postinc2"
5276   [(match_parallel 0 "load_multiple_operation"
5277     [(set (match_operand:SI 1 "s_register_operand" "=r")
5278           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5279                    (const_int 8)))
5280      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5281           (mem:SI (match_dup 2)))
5282      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5283           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5284   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5285   "ldm%?ia\\t%1!, {%3, %4}"
5286   [(set_attr "type" "load")
5287    (set_attr "predicable" "yes")]
5290 ;; Ordinary load multiple
5292 (define_insn "*ldmsi4"
5293   [(match_parallel 0 "load_multiple_operation"
5294     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5295           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5296      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5297           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5298      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5299           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5300      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5301           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5302   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5303   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5304   [(set_attr "type" "load")
5305    (set_attr "predicable" "yes")]
5308 (define_insn "*ldmsi3"
5309   [(match_parallel 0 "load_multiple_operation"
5310     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5311           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5312      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5313           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5314      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5315           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5316   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5317   "ldm%?ia\\t%1, {%2, %3, %4}"
5318   [(set_attr "type" "load")
5319    (set_attr "predicable" "yes")]
5322 (define_insn "*ldmsi2"
5323   [(match_parallel 0 "load_multiple_operation"
5324     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5325           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5326      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5327           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5328   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5329   "ldm%?ia\\t%1, {%2, %3}"
5330   [(set_attr "type" "load")
5331    (set_attr "predicable" "yes")]
5334 (define_expand "store_multiple"
5335   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5336                           (match_operand:SI 1 "" ""))
5337                      (use (match_operand:SI 2 "" ""))])]
5338   "TARGET_ARM"
5339   "
5340   /* Support only fixed point registers */
5341   if (GET_CODE (operands[2]) != CONST_INT
5342       || INTVAL (operands[2]) > 14
5343       || INTVAL (operands[2]) < 2
5344       || GET_CODE (operands[1]) != REG
5345       || GET_CODE (operands[0]) != MEM
5346       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5347       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5348     FAIL;
5350   operands[3]
5351     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5352                               force_reg (SImode, XEXP (operands[0], 0)),
5353                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5354                               MEM_IN_STRUCT_P(operands[0]), 
5355                               MEM_SCALAR_P (operands[0]));
5356   "
5359 ;; Store multiple with write-back
5361 (define_insn "*stmsi_postinc4"
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 16)))
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      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5373           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5374   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5375   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5376   [(set_attr "predicable" "yes")
5377    (set_attr "type" "store4")]
5380 (define_insn "*stmsi_postinc3"
5381   [(match_parallel 0 "store_multiple_operation"
5382     [(set (match_operand:SI 1 "s_register_operand" "=r")
5383           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5384                    (const_int 12)))
5385      (set (mem:SI (match_dup 2))
5386           (match_operand:SI 3 "arm_hard_register_operand" ""))
5387      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5388           (match_operand:SI 4 "arm_hard_register_operand" ""))
5389      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5390           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5391   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5392   "stm%?ia\\t%1!, {%3, %4, %5}"
5393   [(set_attr "predicable" "yes")
5394    (set_attr "type" "store3")]
5397 (define_insn "*stmsi_postinc2"
5398   [(match_parallel 0 "store_multiple_operation"
5399     [(set (match_operand:SI 1 "s_register_operand" "=r")
5400           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5401                    (const_int 8)))
5402      (set (mem:SI (match_dup 2))
5403           (match_operand:SI 3 "arm_hard_register_operand" ""))
5404      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5405           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5406   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5407   "stm%?ia\\t%1!, {%3, %4}"
5408   [(set_attr "predicable" "yes")
5409    (set_attr "type" "store2")]
5412 ;; Ordinary store multiple
5414 (define_insn "*stmsi4"
5415   [(match_parallel 0 "store_multiple_operation"
5416     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5417           (match_operand:SI 2 "arm_hard_register_operand" ""))
5418      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5419           (match_operand:SI 3 "arm_hard_register_operand" ""))
5420      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5421           (match_operand:SI 4 "arm_hard_register_operand" ""))
5422      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5423           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5424   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5425   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5426   [(set_attr "predicable" "yes")
5427    (set_attr "type" "store4")]
5430 (define_insn "*stmsi3"
5431   [(match_parallel 0 "store_multiple_operation"
5432     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5433           (match_operand:SI 2 "arm_hard_register_operand" ""))
5434      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5435           (match_operand:SI 3 "arm_hard_register_operand" ""))
5436      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5437           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5438   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5439   "stm%?ia\\t%1, {%2, %3, %4}"
5440   [(set_attr "predicable" "yes")
5441    (set_attr "type" "store3")]
5444 (define_insn "*stmsi2"
5445   [(match_parallel 0 "store_multiple_operation"
5446     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5447           (match_operand:SI 2 "arm_hard_register_operand" ""))
5448      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5449           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5450   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5451   "stm%?ia\\t%1, {%2, %3}"
5452   [(set_attr "predicable" "yes")
5453    (set_attr "type" "store2")]
5456 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5457 ;; We could let this apply for blocks of less than this, but it clobbers so
5458 ;; many registers that there is then probably a better way.
5460 (define_expand "movstrqi"
5461   [(match_operand:BLK 0 "general_operand" "")
5462    (match_operand:BLK 1 "general_operand" "")
5463    (match_operand:SI 2 "const_int_operand" "")
5464    (match_operand:SI 3 "const_int_operand" "")]
5465   "TARGET_EITHER"
5466   "
5467   if (TARGET_ARM)
5468     {
5469       if (arm_gen_movstrqi (operands))
5470         DONE;
5471       FAIL;
5472     }
5473   else /* TARGET_THUMB */
5474     {
5475       if (   INTVAL (operands[3]) != 4
5476           || INTVAL (operands[2]) > 48)
5477         FAIL;
5479       thumb_expand_movstrqi (operands);
5480       DONE;
5481     }
5482   "
5485 ;; Thumb block-move insns
5487 (define_insn "movmem12b"
5488   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5489         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5490    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5491         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5492    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5493         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5494    (set (match_operand:SI 0 "register_operand" "=l")
5495         (plus:SI (match_dup 2) (const_int 12)))
5496    (set (match_operand:SI 1 "register_operand" "=l")
5497         (plus:SI (match_dup 3) (const_int 12)))
5498    (clobber (match_scratch:SI 4 "=&l"))
5499    (clobber (match_scratch:SI 5 "=&l"))
5500    (clobber (match_scratch:SI 6 "=&l"))]
5501   "TARGET_THUMB"
5502   "* return thumb_output_move_mem_multiple (3, 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" "store3")]
5509 (define_insn "movmem8b"
5510   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5511         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5512    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5513         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5514    (set (match_operand:SI 0 "register_operand" "=l")
5515         (plus:SI (match_dup 2) (const_int 8)))
5516    (set (match_operand:SI 1 "register_operand" "=l")
5517         (plus:SI (match_dup 3) (const_int 8)))
5518    (clobber (match_scratch:SI 4 "=&l"))
5519    (clobber (match_scratch:SI 5 "=&l"))]
5520   "TARGET_THUMB"
5521   "* return thumb_output_move_mem_multiple (2, operands);"
5522   [(set_attr "length" "4")
5523    ; This isn't entirely accurate...  It loads as well, but in terms of
5524    ; scheduling the following insn it is better to consider it as a store
5525    (set_attr "type" "store2")]
5530 ;; Compare & branch insns
5531 ;; The range calcualations are based as follows:
5532 ;; For forward branches, the address calculation returns the address of
5533 ;; the next instruction.  This is 2 beyond the branch instruction.
5534 ;; For backward branches, the address calculation returns the address of
5535 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5536 ;; instruction for the shortest sequence, and 4 before the branch instruction
5537 ;; if we have to jump around an unconditional branch.
5538 ;; To the basic branch range the PC offset must be added (this is +4).
5539 ;; So for forward branches we have 
5540 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5541 ;; And for backward branches we have 
5542 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5544 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5545 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5547 (define_insn "cbranchsi4"
5548   [(set (pc)
5549         (if_then_else
5550             (match_operator                    0 "arm_comparison_operator"
5551                             [(match_operand:SI 1 "register_operand"   "l,r")
5552                              (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5553             (label_ref       (match_operand    3 "" ""))
5554             (pc)))]
5555   "TARGET_THUMB"
5556   "*
5557   output_asm_insn (\"cmp\\t%1, %2\", operands);
5558   switch (get_attr_length (insn))
5559     {
5560     case 4:  return \"b%d0\\t%l3\";
5561     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5562     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5563     }
5564   "
5565   [(set (attr "far_jump")
5566         (if_then_else
5567             (eq_attr "length" "8")
5568             (const_string "yes")
5569             (const_string "no")))
5570    (set (attr "length") 
5571         (if_then_else
5572             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5573                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5574             (const_int 4)
5575             (if_then_else
5576                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5577                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5578                 (const_int 6)
5579                 (const_int 8))))]
5582 (define_insn "*negated_cbranchsi4"
5583   [(set (pc)
5584         (if_then_else
5585          (match_operator             0 "arm_comparison_operator"
5586           [(match_operand:SI         1 "register_operand"  "l")
5587            (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5588          (label_ref (match_operand   3 "" ""))
5589          (pc)))]
5590   "TARGET_THUMB"
5591   "*
5592   output_asm_insn (\"cmn\\t%1, %2\", operands);
5593   switch (get_attr_length (insn))
5594     {
5595     case 4:  return \"b%d0\\t%l3\";
5596     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5597     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5598     }
5599   "
5600   [(set (attr "far_jump")
5601         (if_then_else
5602             (eq_attr "length" "8")
5603             (const_string "yes")
5604             (const_string "no")))
5605    (set (attr "length") 
5606         (if_then_else
5607             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5608                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5609             (const_int 4)
5610             (if_then_else
5611                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5612                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5613                 (const_int 6)
5614                 (const_int 8))))]
5618 ;; Comparison and test insns
5620 (define_expand "cmpsi"
5621   [(match_operand:SI 0 "s_register_operand" "")
5622    (match_operand:SI 1 "arm_add_operand" "")]
5623   "TARGET_ARM"
5624   "{
5625     arm_compare_op0 = operands[0];
5626     arm_compare_op1 = operands[1];
5627     DONE;
5628   }"
5631 (define_expand "cmpsf"
5632   [(match_operand:SF 0 "s_register_operand" "")
5633    (match_operand:SF 1 "fpu_rhs_operand" "")]
5634   "TARGET_ARM && TARGET_HARD_FLOAT"
5635   "
5636   arm_compare_op0 = operands[0];
5637   arm_compare_op1 = operands[1];
5638   DONE;
5639   "
5642 (define_expand "cmpdf"
5643   [(match_operand:DF 0 "s_register_operand" "")
5644    (match_operand:DF 1 "fpu_rhs_operand" "")]
5645   "TARGET_ARM && TARGET_HARD_FLOAT"
5646   "
5647   arm_compare_op0 = operands[0];
5648   arm_compare_op1 = operands[1];
5649   DONE;
5650   "
5653 (define_expand "cmpxf"
5654   [(match_operand:XF 0 "s_register_operand" "")
5655    (match_operand:XF 1 "fpu_rhs_operand" "")]
5656   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5657   "
5658   arm_compare_op0 = operands[0];
5659   arm_compare_op1 = operands[1];
5660   DONE;
5661   "
5664 (define_insn "*arm_cmpsi_insn"
5665   [(set (reg:CC CC_REGNUM)
5666         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5667                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5668   "TARGET_ARM"
5669   "@
5670    cmp%?\\t%0, %1
5671    cmn%?\\t%0, #%n1"
5672   [(set_attr "conds" "set")]
5675 (define_insn "*cmpsi_shiftsi"
5676   [(set (reg:CC CC_REGNUM)
5677         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
5678                     (match_operator:SI  3 "shift_operator"
5679                      [(match_operand:SI 1 "s_register_operand" "r")
5680                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5681   "TARGET_ARM"
5682   "cmp%?\\t%0, %1%S3"
5683   [(set_attr "conds" "set")
5684    (set_attr "shift" "1")
5685    ]
5688 (define_insn "*cmpsi_shiftsi_swp"
5689   [(set (reg:CC_SWP CC_REGNUM)
5690         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5691                          [(match_operand:SI 1 "s_register_operand" "r")
5692                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
5693                         (match_operand:SI 0 "s_register_operand" "r")))]
5694   "TARGET_ARM"
5695   "cmp%?\\t%0, %1%S3"
5696   [(set_attr "conds" "set")
5697    (set_attr "shift" "1")
5698    ]
5701 (define_insn "*cmpsi_neg_shiftsi"
5702   [(set (reg:CC CC_REGNUM)
5703         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5704                     (neg:SI (match_operator:SI 3 "shift_operator"
5705                              [(match_operand:SI 1 "s_register_operand" "r")
5706                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5707   "TARGET_ARM"
5708   "cmn%?\\t%0, %1%S3"
5709   [(set_attr "conds" "set")
5710    (set_attr "shift" "1")
5711    ]
5714 (define_insn "*cmpsf_insn"
5715   [(set (reg:CCFP CC_REGNUM)
5716         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5717                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5718   "TARGET_ARM && TARGET_HARD_FLOAT"
5719   "@
5720    cmf%?\\t%0, %1
5721    cnf%?\\t%0, #%N1"
5722   [(set_attr "conds" "set")
5723    (set_attr "type" "f_2_r")]
5726 (define_insn "*cmpdf_insn"
5727   [(set (reg:CCFP CC_REGNUM)
5728         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5729                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5730   "TARGET_ARM && TARGET_HARD_FLOAT"
5731   "@
5732    cmf%?\\t%0, %1
5733    cnf%?\\t%0, #%N1"
5734   [(set_attr "conds" "set")
5735    (set_attr "type" "f_2_r")]
5738 (define_insn "*cmpesfdf_df"
5739   [(set (reg:CCFP CC_REGNUM)
5740         (compare:CCFP (float_extend:DF
5741                        (match_operand:SF 0 "s_register_operand" "f,f"))
5742                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5743   "TARGET_ARM && TARGET_HARD_FLOAT"
5744   "@
5745    cmf%?\\t%0, %1
5746    cnf%?\\t%0, #%N1"
5747   [(set_attr "conds" "set")
5748    (set_attr "type" "f_2_r")]
5751 (define_insn "*cmpdf_esfdf"
5752   [(set (reg:CCFP CC_REGNUM)
5753         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5754                       (float_extend:DF
5755                        (match_operand:SF 1 "s_register_operand" "f"))))]
5756   "TARGET_ARM && TARGET_HARD_FLOAT"
5757   "cmf%?\\t%0, %1"
5758   [(set_attr "conds" "set")
5759    (set_attr "type" "f_2_r")]
5762 (define_insn "*cmpxf_insn"
5763   [(set (reg:CCFP CC_REGNUM)
5764         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5765                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5766   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5767   "@
5768    cmf%?\\t%0, %1
5769    cnf%?\\t%0, #%N1"
5770   [(set_attr "conds" "set")
5771    (set_attr "type" "f_2_r")]
5774 (define_insn "*cmpsf_trap"
5775   [(set (reg:CCFPE CC_REGNUM)
5776         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5777                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5778   "TARGET_ARM && TARGET_HARD_FLOAT"
5779   "@
5780    cmf%?e\\t%0, %1
5781    cnf%?e\\t%0, #%N1"
5782   [(set_attr "conds" "set")
5783    (set_attr "type" "f_2_r")]
5786 (define_insn "*cmpdf_trap"
5787   [(set (reg:CCFPE CC_REGNUM)
5788         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5789                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5790   "TARGET_ARM && TARGET_HARD_FLOAT"
5791   "@
5792    cmf%?e\\t%0, %1
5793    cnf%?e\\t%0, #%N1"
5794   [(set_attr "conds" "set")
5795    (set_attr "type" "f_2_r")]
5798 (define_insn "*cmp_esfdf_df_trap"
5799   [(set (reg:CCFPE CC_REGNUM)
5800         (compare:CCFPE (float_extend:DF
5801                         (match_operand:SF 0 "s_register_operand" "f,f"))
5802                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5803   "TARGET_ARM && TARGET_HARD_FLOAT"
5804   "@
5805    cmf%?e\\t%0, %1
5806    cnf%?e\\t%0, #%N1"
5807   [(set_attr "conds" "set")
5808    (set_attr "type" "f_2_r")]
5811 (define_insn "*cmp_df_esfdf_trap"
5812   [(set (reg:CCFPE CC_REGNUM)
5813         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5814                        (float_extend:DF
5815                         (match_operand:SF 1 "s_register_operand" "f"))))]
5816   "TARGET_ARM && TARGET_HARD_FLOAT"
5817   "cmf%?e\\t%0, %1"
5818   [(set_attr "conds" "set")
5819    (set_attr "type" "f_2_r")]
5822 (define_insn "*cmpxf_trap"
5823   [(set (reg:CCFPE CC_REGNUM)
5824         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5825                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5826   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5827   "@
5828    cmf%?e\\t%0, %1
5829    cnf%?e\\t%0, #%N1"
5830   [(set_attr "conds" "set")
5831    (set_attr "type" "f_2_r")]
5834 ; This insn allows redundant compares to be removed by cse, nothing should
5835 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5836 ; is deleted later on. The match_dup will match the mode here, so that
5837 ; mode changes of the condition codes aren't lost by this even though we don't
5838 ; specify what they are.
5840 (define_insn "*deleted_compare"
5841   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5842   "TARGET_ARM"
5843   "\\t%@ deleted compare"
5844   [(set_attr "conds" "set")
5845    (set_attr "length" "0")]
5849 ;; Conditional branch insns
5851 (define_expand "beq"
5852   [(set (pc)
5853         (if_then_else (eq (match_dup 1) (const_int 0))
5854                       (label_ref (match_operand 0 "" ""))
5855                       (pc)))]
5856   "TARGET_ARM"
5857   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5860 (define_expand "bne"
5861   [(set (pc)
5862         (if_then_else (ne (match_dup 1) (const_int 0))
5863                       (label_ref (match_operand 0 "" ""))
5864                       (pc)))]
5865   "TARGET_ARM"
5866   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5869 (define_expand "bgt"
5870   [(set (pc)
5871         (if_then_else (gt (match_dup 1) (const_int 0))
5872                       (label_ref (match_operand 0 "" ""))
5873                       (pc)))]
5874   "TARGET_ARM"
5875   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5878 (define_expand "ble"
5879   [(set (pc)
5880         (if_then_else (le (match_dup 1) (const_int 0))
5881                       (label_ref (match_operand 0 "" ""))
5882                       (pc)))]
5883   "TARGET_ARM"
5884   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5887 (define_expand "bge"
5888   [(set (pc)
5889         (if_then_else (ge (match_dup 1) (const_int 0))
5890                       (label_ref (match_operand 0 "" ""))
5891                       (pc)))]
5892   "TARGET_ARM"
5893   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5896 (define_expand "blt"
5897   [(set (pc)
5898         (if_then_else (lt (match_dup 1) (const_int 0))
5899                       (label_ref (match_operand 0 "" ""))
5900                       (pc)))]
5901   "TARGET_ARM"
5902   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5905 (define_expand "bgtu"
5906   [(set (pc)
5907         (if_then_else (gtu (match_dup 1) (const_int 0))
5908                       (label_ref (match_operand 0 "" ""))
5909                       (pc)))]
5910   "TARGET_ARM"
5911   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5914 (define_expand "bleu"
5915   [(set (pc)
5916         (if_then_else (leu (match_dup 1) (const_int 0))
5917                       (label_ref (match_operand 0 "" ""))
5918                       (pc)))]
5919   "TARGET_ARM"
5920   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5923 (define_expand "bgeu"
5924   [(set (pc)
5925         (if_then_else (geu (match_dup 1) (const_int 0))
5926                       (label_ref (match_operand 0 "" ""))
5927                       (pc)))]
5928   "TARGET_ARM"
5929   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5932 (define_expand "bltu"
5933   [(set (pc)
5934         (if_then_else (ltu (match_dup 1) (const_int 0))
5935                       (label_ref (match_operand 0 "" ""))
5936                       (pc)))]
5937   "TARGET_ARM"
5938   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5941 (define_expand "bunordered"
5942   [(set (pc)
5943         (if_then_else (unordered (match_dup 1) (const_int 0))
5944                       (label_ref (match_operand 0 "" ""))
5945                       (pc)))]
5946   "TARGET_ARM && TARGET_HARD_FLOAT"
5947   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5948                                       arm_compare_op1);"
5951 (define_expand "bordered"
5952   [(set (pc)
5953         (if_then_else (ordered (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 (ORDERED, arm_compare_op0,
5958                                       arm_compare_op1);"
5961 (define_expand "bungt"
5962   [(set (pc)
5963         (if_then_else (ungt (match_dup 1) (const_int 0))
5964                       (label_ref (match_operand 0 "" ""))
5965                       (pc)))]
5966   "TARGET_ARM && TARGET_HARD_FLOAT"
5967   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5970 (define_expand "bunlt"
5971   [(set (pc)
5972         (if_then_else (unlt (match_dup 1) (const_int 0))
5973                       (label_ref (match_operand 0 "" ""))
5974                       (pc)))]
5975   "TARGET_ARM && TARGET_HARD_FLOAT"
5976   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5979 (define_expand "bunge"
5980   [(set (pc)
5981         (if_then_else (unge (match_dup 1) (const_int 0))
5982                       (label_ref (match_operand 0 "" ""))
5983                       (pc)))]
5984   "TARGET_ARM && TARGET_HARD_FLOAT"
5985   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5988 (define_expand "bunle"
5989   [(set (pc)
5990         (if_then_else (unle (match_dup 1) (const_int 0))
5991                       (label_ref (match_operand 0 "" ""))
5992                       (pc)))]
5993   "TARGET_ARM && TARGET_HARD_FLOAT"
5994   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5997 ;; The following two patterns need two branch instructions, since there is
5998 ;; no single instruction that will handle all cases.
5999 (define_expand "buneq"
6000   [(set (pc)
6001         (if_then_else (uneq (match_dup 1) (const_int 0))
6002                       (label_ref (match_operand 0 "" ""))
6003                       (pc)))]
6004   "TARGET_ARM && TARGET_HARD_FLOAT"
6005   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6008 (define_expand "bltgt"
6009   [(set (pc)
6010         (if_then_else (ltgt (match_dup 1) (const_int 0))
6011                       (label_ref (match_operand 0 "" ""))
6012                       (pc)))]
6013   "TARGET_ARM && TARGET_HARD_FLOAT"
6014   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6018 ;; Patterns to match conditional branch insns.
6021 ; Special pattern to match UNEQ.
6022 (define_insn "*arm_buneq"
6023   [(set (pc)
6024         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6025                       (label_ref (match_operand 0 "" ""))
6026                       (pc)))]
6027   "TARGET_ARM && TARGET_HARD_FLOAT"
6028   "*
6029   if (arm_ccfsm_state != 0)
6030     abort ();
6032   return \"bvs\\t%l0;beq\\t%l0\";
6033   "
6034   [(set_attr "conds" "jump_clob")
6035    (set_attr "length" "8")]
6038 ; Special pattern to match LTGT.
6039 (define_insn "*arm_bltgt"
6040   [(set (pc)
6041         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6042                       (label_ref (match_operand 0 "" ""))
6043                       (pc)))]
6044   "TARGET_ARM && TARGET_HARD_FLOAT"
6045   "*
6046   if (arm_ccfsm_state != 0)
6047     abort ();
6049   return \"bmi\\t%l0;bgt\\t%l0\";
6050   "
6051   [(set_attr "conds" "jump_clob")
6052    (set_attr "length" "8")]
6055 (define_insn "*arm_cond_branch"
6056   [(set (pc)
6057         (if_then_else (match_operator 1 "arm_comparison_operator"
6058                        [(match_operand 2 "cc_register" "") (const_int 0)])
6059                       (label_ref (match_operand 0 "" ""))
6060                       (pc)))]
6061   "TARGET_ARM"
6062   "*
6063   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6064     {
6065       arm_ccfsm_state += 2;
6066       return \"\";
6067     }
6068   return \"b%d1\\t%l0\";
6069   "
6070   [(set_attr "conds" "use")]
6073 ; Special pattern to match reversed UNEQ.
6074 (define_insn "*arm_buneq_reversed"
6075   [(set (pc)
6076         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6077                       (pc)
6078                       (label_ref (match_operand 0 "" ""))))]
6079   "TARGET_ARM && TARGET_HARD_FLOAT"
6080   "*
6081   if (arm_ccfsm_state != 0)
6082     abort ();
6084   return \"bmi\\t%l0;bgt\\t%l0\";
6085   "
6086   [(set_attr "conds" "jump_clob")
6087    (set_attr "length" "8")]
6090 ; Special pattern to match reversed LTGT.
6091 (define_insn "*arm_bltgt_reversed"
6092   [(set (pc)
6093         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6094                       (pc)
6095                       (label_ref (match_operand 0 "" ""))))]
6096   "TARGET_ARM && TARGET_HARD_FLOAT"
6097   "*
6098   if (arm_ccfsm_state != 0)
6099     abort ();
6101   return \"bvs\\t%l0;beq\\t%l0\";
6102   "
6103   [(set_attr "conds" "jump_clob")
6104    (set_attr "length" "8")]
6107 (define_insn "*arm_cond_branch_reversed"
6108   [(set (pc)
6109         (if_then_else (match_operator 1 "arm_comparison_operator"
6110                        [(match_operand 2 "cc_register" "") (const_int 0)])
6111                       (pc)
6112                       (label_ref (match_operand 0 "" ""))))]
6113   "TARGET_ARM"
6114   "*
6115   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6116     {
6117       arm_ccfsm_state += 2;
6118       return \"\";
6119     }
6120   return \"b%D1\\t%l0\";
6121   "
6122   [(set_attr "conds" "use")]
6127 ; scc insns
6129 (define_expand "seq"
6130   [(set (match_operand:SI 0 "s_register_operand" "=r")
6131         (eq:SI (match_dup 1) (const_int 0)))]
6132   "TARGET_ARM"
6133   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6136 (define_expand "sne"
6137   [(set (match_operand:SI 0 "s_register_operand" "=r")
6138         (ne:SI (match_dup 1) (const_int 0)))]
6139   "TARGET_ARM"
6140   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6143 (define_expand "sgt"
6144   [(set (match_operand:SI 0 "s_register_operand" "=r")
6145         (gt:SI (match_dup 1) (const_int 0)))]
6146   "TARGET_ARM"
6147   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6150 (define_expand "sle"
6151   [(set (match_operand:SI 0 "s_register_operand" "=r")
6152         (le:SI (match_dup 1) (const_int 0)))]
6153   "TARGET_ARM"
6154   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6157 (define_expand "sge"
6158   [(set (match_operand:SI 0 "s_register_operand" "=r")
6159         (ge:SI (match_dup 1) (const_int 0)))]
6160   "TARGET_ARM"
6161   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6164 (define_expand "slt"
6165   [(set (match_operand:SI 0 "s_register_operand" "=r")
6166         (lt:SI (match_dup 1) (const_int 0)))]
6167   "TARGET_ARM"
6168   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6171 (define_expand "sgtu"
6172   [(set (match_operand:SI 0 "s_register_operand" "=r")
6173         (gtu:SI (match_dup 1) (const_int 0)))]
6174   "TARGET_ARM"
6175   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6178 (define_expand "sleu"
6179   [(set (match_operand:SI 0 "s_register_operand" "=r")
6180         (leu:SI (match_dup 1) (const_int 0)))]
6181   "TARGET_ARM"
6182   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6185 (define_expand "sgeu"
6186   [(set (match_operand:SI 0 "s_register_operand" "=r")
6187         (geu:SI (match_dup 1) (const_int 0)))]
6188   "TARGET_ARM"
6189   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6192 (define_expand "sltu"
6193   [(set (match_operand:SI 0 "s_register_operand" "=r")
6194         (ltu:SI (match_dup 1) (const_int 0)))]
6195   "TARGET_ARM"
6196   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6199 (define_expand "sunordered"
6200   [(set (match_operand:SI 0 "s_register_operand" "=r")
6201         (unordered:SI (match_dup 1) (const_int 0)))]
6202   "TARGET_ARM && TARGET_HARD_FLOAT"
6203   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6204                                       arm_compare_op1);"
6207 (define_expand "sordered"
6208   [(set (match_operand:SI 0 "s_register_operand" "=r")
6209         (ordered:SI (match_dup 1) (const_int 0)))]
6210   "TARGET_ARM && TARGET_HARD_FLOAT"
6211   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6212                                       arm_compare_op1);"
6215 (define_expand "sungt"
6216   [(set (match_operand:SI 0 "s_register_operand" "=r")
6217         (ungt:SI (match_dup 1) (const_int 0)))]
6218   "TARGET_ARM && TARGET_HARD_FLOAT"
6219   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6220                                       arm_compare_op1);"
6223 (define_expand "sunge"
6224   [(set (match_operand:SI 0 "s_register_operand" "=r")
6225         (unge:SI (match_dup 1) (const_int 0)))]
6226   "TARGET_ARM && TARGET_HARD_FLOAT"
6227   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6228                                       arm_compare_op1);"
6231 (define_expand "sunlt"
6232   [(set (match_operand:SI 0 "s_register_operand" "=r")
6233         (unlt:SI (match_dup 1) (const_int 0)))]
6234   "TARGET_ARM && TARGET_HARD_FLOAT"
6235   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6236                                       arm_compare_op1);"
6239 (define_expand "sunle"
6240   [(set (match_operand:SI 0 "s_register_operand" "=r")
6241         (unle:SI (match_dup 1) (const_int 0)))]
6242   "TARGET_ARM && TARGET_HARD_FLOAT"
6243   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6244                                       arm_compare_op1);"
6247 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6248 ;;; simple ARM instructions. 
6250 ; (define_expand "suneq"
6251 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6252 ;       (uneq:SI (match_dup 1) (const_int 0)))]
6253 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6254 ;   "abort ();"
6255 ; )
6257 ; (define_expand "sltgt"
6258 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6259 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
6260 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6261 ;   "abort ();"
6262 ; )
6264 (define_insn "*mov_scc"
6265   [(set (match_operand:SI 0 "s_register_operand" "=r")
6266         (match_operator:SI 1 "arm_comparison_operator"
6267          [(match_operand 2 "cc_register" "") (const_int 0)]))]
6268   "TARGET_ARM"
6269   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6270   [(set_attr "conds" "use")
6271    (set_attr "length" "8")]
6274 (define_insn "*mov_negscc"
6275   [(set (match_operand:SI 0 "s_register_operand" "=r")
6276         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6277                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6278   "TARGET_ARM"
6279   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6280   [(set_attr "conds" "use")
6281    (set_attr "length" "8")]
6284 (define_insn "*mov_notscc"
6285   [(set (match_operand:SI 0 "s_register_operand" "=r")
6286         (not:SI (match_operator:SI 1 "arm_comparison_operator"
6287                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6288   "TARGET_ARM"
6289   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6290   [(set_attr "conds" "use")
6291    (set_attr "length" "8")]
6295 ;; Conditional move insns
6297 (define_expand "movsicc"
6298   [(set (match_operand:SI 0 "s_register_operand" "")
6299         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6300                          (match_operand:SI 2 "arm_not_operand" "")
6301                          (match_operand:SI 3 "arm_not_operand" "")))]
6302   "TARGET_ARM"
6303   "
6304   {
6305     enum rtx_code code = GET_CODE (operands[1]);
6306     rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6308     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6309   }"
6312 (define_expand "movsfcc"
6313   [(set (match_operand:SF 0 "s_register_operand" "")
6314         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6315                          (match_operand:SF 2 "s_register_operand" "")
6316                          (match_operand:SF 3 "nonmemory_operand" "")))]
6317   "TARGET_ARM"
6318   "
6319   {
6320     enum rtx_code code = GET_CODE (operands[1]);
6321     rtx ccreg;
6323     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
6324        Otherwise, ensure it is a valid FP add operand */
6325     if ((!TARGET_HARD_FLOAT)
6326         || (!fpu_add_operand (operands[3], SFmode)))
6327       operands[3] = force_reg (SFmode, operands[3]);
6329     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6330     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6331   }"
6334 (define_expand "movdfcc"
6335   [(set (match_operand:DF 0 "s_register_operand" "")
6336         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6337                          (match_operand:DF 2 "s_register_operand" "")
6338                          (match_operand:DF 3 "fpu_add_operand" "")))]
6339   "TARGET_ARM && TARGET_HARD_FLOAT"
6340   "
6341   {
6342     enum rtx_code code = GET_CODE (operands[1]);
6343     rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6345     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6346   }"
6349 (define_insn "*movsicc_insn"
6350   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6351         (if_then_else:SI
6352          (match_operator 3 "arm_comparison_operator"
6353           [(match_operand 4 "cc_register" "") (const_int 0)])
6354          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6355          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6356   "TARGET_ARM"
6357   "@
6358    mov%D3\\t%0, %2
6359    mvn%D3\\t%0, #%B2
6360    mov%d3\\t%0, %1
6361    mvn%d3\\t%0, #%B1
6362    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6363    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6364    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6365    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6366   [(set_attr "length" "4,4,4,4,8,8,8,8")
6367    (set_attr "conds" "use")]
6370 (define_insn "*movsfcc_hard_insn"
6371   [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6372         (if_then_else:SF
6373          (match_operator 3 "arm_comparison_operator" 
6374           [(match_operand 4 "cc_register" "") (const_int 0)])
6375          (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6376          (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6377   "TARGET_ARM && TARGET_HARD_FLOAT"
6378   "@
6379    mvf%D3s\\t%0, %2
6380    mnf%D3s\\t%0, #%N2
6381    mvf%d3s\\t%0, %1
6382    mnf%d3s\\t%0, #%N1
6383    mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6384    mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6385    mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6386    mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6387   [(set_attr "length" "4,4,4,4,8,8,8,8")
6388    (set_attr "type" "ffarith")
6389    (set_attr "conds" "use")]
6392 (define_insn "*movsfcc_soft_insn"
6393   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6394         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6395                           [(match_operand 4 "cc_register" "") (const_int 0)])
6396                          (match_operand:SF 1 "s_register_operand" "0,r")
6397                          (match_operand:SF 2 "s_register_operand" "r,0")))]
6398   "TARGET_ARM && TARGET_SOFT_FLOAT"
6399   "@
6400    mov%D3\\t%0, %2
6401    mov%d3\\t%0, %1"
6402   [(set_attr "conds" "use")]
6405 (define_insn "*movdfcc_insn"
6406   [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6407         (if_then_else:DF
6408          (match_operator 3 "arm_comparison_operator"
6409           [(match_operand 4 "cc_register" "") (const_int 0)])
6410          (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6411          (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6412   "TARGET_ARM && TARGET_HARD_FLOAT"
6413   "@
6414    mvf%D3d\\t%0, %2
6415    mnf%D3d\\t%0, #%N2
6416    mvf%d3d\\t%0, %1
6417    mnf%d3d\\t%0, #%N1
6418    mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6419    mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6420    mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6421    mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6422   [(set_attr "length" "4,4,4,4,8,8,8,8")
6423    (set_attr "type" "ffarith")
6424    (set_attr "conds" "use")]
6428 ;; Jump and linkage insns
6430 (define_expand "jump"
6431   [(set (pc)
6432         (label_ref (match_operand 0 "" "")))]
6433   "TARGET_EITHER"
6434   ""
6437 (define_insn "*arm_jump"
6438   [(set (pc)
6439         (label_ref (match_operand 0 "" "")))]
6440   "TARGET_ARM"
6441   "*
6442   {
6443     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6444       {
6445         arm_ccfsm_state += 2;
6446         return \"\";
6447       }
6448     return \"b%?\\t%l0\";
6449   }
6450   "
6451   [(set_attr "predicable" "yes")]
6454 (define_insn "*thumb_jump"
6455   [(set (pc)
6456         (label_ref (match_operand 0 "" "")))]
6457   "TARGET_THUMB"
6458   "*
6459   if (get_attr_length (insn) == 2)
6460     return \"b\\t%l0\";
6461   return \"bl\\t%l0\\t%@ far jump\";
6462   "
6463   [(set (attr "far_jump")
6464         (if_then_else
6465             (eq_attr "length" "4")
6466             (const_string "yes")
6467             (const_string "no")))
6468    (set (attr "length") 
6469         (if_then_else
6470             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6471                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
6472             (const_int 2)
6473             (const_int 4)))]
6476 (define_expand "call"
6477   [(parallel [(call (match_operand 0 "memory_operand" "")
6478                     (match_operand 1 "general_operand" ""))
6479               (use (match_operand 2 "" ""))
6480               (clobber (reg:SI LR_REGNUM))])]
6481   "TARGET_EITHER"
6482   "
6483   {
6484     rtx callee;
6485     
6486     /* In an untyped call, we can get NULL for operand 2.  */
6487     if (operands[2] == NULL_RTX)
6488       operands[2] = const0_rtx;
6489       
6490     /* This is to decide if we should generate indirect calls by loading the
6491        32 bit address of the callee into a register before performing the
6492        branch and link.  operand[2] encodes the long_call/short_call
6493        attribute of the function being called.  This attribute is set whenever
6494        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6495        is used, and the short_call attribute can also be set if function is
6496        declared as static or if it has already been defined in the current
6497        compilation unit.  See arm.c and arm.h for info about this.  The third
6498        parameter to arm_is_longcall_p is used to tell it which pattern
6499        invoked it.  */
6500     callee  = XEXP (operands[0], 0);
6501     
6502     if (GET_CODE (callee) != REG
6503        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6504       XEXP (operands[0], 0) = force_reg (Pmode, callee);
6505   }"
6508 (define_insn "*call_reg"
6509   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6510          (match_operand 1 "" ""))
6511    (use (match_operand 2 "" ""))
6512    (clobber (reg:SI LR_REGNUM))]
6513   "TARGET_ARM"
6514   "*
6515   return output_call (operands);
6516   "
6517   ;; length is worst case, normally it is only two
6518   [(set_attr "length" "12")
6519    (set_attr "type" "call")]
6522 (define_insn "*call_mem"
6523   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6524          (match_operand 1 "" ""))
6525    (use (match_operand 2 "" ""))
6526    (clobber (reg:SI LR_REGNUM))]
6527   "TARGET_ARM"
6528   "*
6529   return output_call_mem (operands);
6530   "
6531   [(set_attr "length" "12")
6532    (set_attr "type" "call")]
6535 (define_insn "*call_indirect"
6536   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6537          (match_operand 1 "" ""))
6538    (use (match_operand 2 "" ""))
6539    (clobber (reg:SI LR_REGNUM))]
6540   "TARGET_THUMB"
6541   "*
6542   {
6543     if (TARGET_CALLER_INTERWORKING)
6544       return \"bl\\t%__interwork_call_via_%0\";
6545     else
6546       return \"bl\\t%__call_via_%0\";
6547   }"
6548   [(set_attr "type" "call")]
6551 (define_insn "*call_value_indirect"
6552   [(set (match_operand 0 "" "=l")
6553         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6554               (match_operand 2 "" "")))
6555    (use (match_operand 3 "" ""))
6556    (clobber (reg:SI LR_REGNUM))]
6557   "TARGET_THUMB"
6558   "*
6559   {
6560     if (TARGET_CALLER_INTERWORKING)
6561       return \"bl\\t%__interwork_call_via_%1\";
6562     else
6563       return \"bl\\t%__call_via_%1\";
6564   }"
6565   [(set_attr "type" "call")]
6568 (define_expand "call_value"
6569   [(parallel [(set (match_operand       0 "" "")
6570                    (call (match_operand 1 "memory_operand" "")
6571                          (match_operand 2 "general_operand" "")))
6572               (use (match_operand 3 "" ""))
6573               (clobber (reg:SI LR_REGNUM))])]
6574   "TARGET_EITHER"
6575   "
6576   {
6577     rtx callee = XEXP (operands[1], 0);
6578     
6579     /* In an untyped call, we can get NULL for operand 2.  */
6580     if (operands[3] == 0)
6581       operands[3] = const0_rtx;
6582       
6583     /* See the comment in define_expand \"call\".  */
6584     if (GET_CODE (callee) != REG
6585         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6586       XEXP (operands[1], 0) = force_reg (Pmode, callee);
6587   }"
6590 (define_insn "*call_value_reg"
6591   [(set (match_operand 0 "" "=r,f")
6592         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6593               (match_operand 2 "" "")))
6594    (use (match_operand 3 "" ""))
6595    (clobber (reg:SI LR_REGNUM))]
6596   "TARGET_ARM"
6597   "*
6598   return output_call (&operands[1]);
6599   "
6600   [(set_attr "length" "12")
6601    (set_attr "type" "call")]
6604 (define_insn "*call_value_mem"
6605   [(set (match_operand 0 "" "=r,f")
6606         (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6607               (match_operand 2 "" "")))
6608    (use (match_operand 3 "" ""))
6609    (clobber (reg:SI LR_REGNUM))]
6610   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6611   "*
6612   return output_call_mem (&operands[1]);
6613   "
6614   [(set_attr "length" "12")
6615    (set_attr "type" "call")]
6618 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6619 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6621 (define_insn "*call_symbol"
6622   [(call (mem:SI (match_operand:SI 0 "" "X"))
6623          (match_operand 1 "" ""))
6624    (use (match_operand 2 "" ""))
6625    (clobber (reg:SI LR_REGNUM))]
6626   "TARGET_ARM
6627    && (GET_CODE (operands[0]) == SYMBOL_REF)
6628    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6629   "*
6630   {
6631     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6632   }"
6633   [(set_attr "type" "call")]
6636 (define_insn "*call_value_symbol"
6637   [(set (match_operand 0 "s_register_operand" "=r,f")
6638         (call (mem:SI (match_operand:SI 1 "" "X,X"))
6639         (match_operand:SI 2 "" "")))
6640    (use (match_operand 3 "" ""))
6641    (clobber (reg:SI LR_REGNUM))]
6642   "TARGET_ARM
6643    && (GET_CODE (operands[1]) == SYMBOL_REF)
6644    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6645   "*
6646   {
6647     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6648   }"
6649   [(set_attr "type" "call")]
6652 (define_insn "*call_insn"
6653   [(call (mem:SI (match_operand:SI 0 "" "X"))
6654          (match_operand:SI 1 "" ""))
6655    (use (match_operand 2 "" ""))
6656    (clobber (reg:SI LR_REGNUM))]
6657   "TARGET_THUMB
6658    && GET_CODE (operands[0]) == SYMBOL_REF
6659    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6660   "bl\\t%a0"
6661   [(set_attr "length" "4")
6662    (set_attr "type" "call")]
6665 (define_insn "*call_value_insn"
6666   [(set (match_operand 0 "register_operand" "=l")
6667         (call (mem:SI (match_operand 1 "" "X"))
6668               (match_operand 2 "" "")))
6669    (use (match_operand 3 "" ""))
6670    (clobber (reg:SI LR_REGNUM))]
6671   "TARGET_THUMB
6672    && GET_CODE (operands[1]) == SYMBOL_REF
6673    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6674   "bl\\t%a1"
6675   [(set_attr "length" "4")
6676    (set_attr "type" "call")]
6679 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6680 (define_expand "sibcall"
6681   [(parallel [(call (match_operand 0 "memory_operand" "")
6682                     (match_operand 1 "general_operand" ""))
6683               (use (match_operand 2 "" ""))
6684               (use (reg:SI LR_REGNUM))])]
6685   "TARGET_ARM"
6686   "
6687   {
6688     if (operands[2] == NULL_RTX)
6689       operands[2] = const0_rtx;
6690   }"
6693 (define_expand "sibcall_value"
6694   [(parallel [(set (match_operand 0 "register_operand" "")
6695                    (call (match_operand 1 "memory_operand" "")
6696                          (match_operand 2 "general_operand" "")))
6697               (use (match_operand 3 "" ""))
6698               (use (reg:SI LR_REGNUM))])]
6699   "TARGET_ARM"
6700   "
6701   {
6702     if (operands[3] == NULL_RTX)
6703       operands[3] = const0_rtx;
6704   }"
6707 (define_insn "*sibcall_insn"
6708  [(call (mem:SI (match_operand:SI 0 "" "X"))
6709         (match_operand 1 "" ""))
6710   (use (match_operand 2 "" ""))
6711   (use (reg:SI LR_REGNUM))]
6712   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6713   "*
6714   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6715   "
6716   [(set_attr "type" "call")]
6719 (define_insn "*sibcall_value_insn"
6720  [(set (match_operand 0 "s_register_operand" "=r,f")
6721        (call (mem:SI (match_operand:SI 1 "" "X,X"))
6722              (match_operand 2 "" "")))
6723   (use (match_operand 3 "" ""))
6724   (use (reg:SI LR_REGNUM))]
6725   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6726   "*
6727   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6728   "
6729   [(set_attr "type" "call")]
6732 ;; Often the return insn will be the same as loading from memory, so set attr
6733 (define_insn "return"
6734   [(return)]
6735   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6736   "*
6737   {
6738     if (arm_ccfsm_state == 2)
6739       {
6740         arm_ccfsm_state += 2;
6741         return \"\";
6742       }
6743     return output_return_instruction (NULL, TRUE, FALSE);
6744   }"
6745   [(set_attr "type" "load")
6746    (set_attr "predicable" "yes")]
6749 (define_insn "*cond_return"
6750   [(set (pc)
6751         (if_then_else (match_operator 0 "arm_comparison_operator"
6752                        [(match_operand 1 "cc_register" "") (const_int 0)])
6753                       (return)
6754                       (pc)))]
6755   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6756   "*
6757   {
6758     if (arm_ccfsm_state == 2)
6759       {
6760         arm_ccfsm_state += 2;
6761         return \"\";
6762       }
6763     return output_return_instruction (operands[0], TRUE, FALSE);
6764   }"
6765   [(set_attr "conds" "use")
6766    (set_attr "type" "load")]
6769 (define_insn "*cond_return_inverted"
6770   [(set (pc)
6771         (if_then_else (match_operator 0 "arm_comparison_operator"
6772                        [(match_operand 1 "cc_register" "") (const_int 0)])
6773                       (pc)
6774                       (return)))]
6775   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6776   "*
6777   {
6778     if (arm_ccfsm_state == 2)
6779       {
6780         arm_ccfsm_state += 2;
6781         return \"\";
6782       }
6783     return output_return_instruction (operands[0], TRUE, TRUE);
6784   }"
6785   [(set_attr "conds" "use")
6786    (set_attr "type" "load")]
6789 ;; Call subroutine returning any type.
6791 (define_expand "untyped_call"
6792   [(parallel [(call (match_operand 0 "" "")
6793                     (const_int 0))
6794               (match_operand 1 "" "")
6795               (match_operand 2 "" "")])]
6796   "TARGET_ARM"
6797   "
6798   {
6799     int i;
6801     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6803     for (i = 0; i < XVECLEN (operands[2], 0); i++)
6804       {
6805         rtx set = XVECEXP (operands[2], 0, i);
6807         emit_move_insn (SET_DEST (set), SET_SRC (set));
6808       }
6810     /* The optimizer does not know that the call sets the function value
6811        registers we stored in the result block.  We avoid problems by
6812        claiming that all hard registers are used and clobbered at this
6813        point.  */
6814     emit_insn (gen_blockage ());
6816     DONE;
6817   }"
6820 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6821 ;; all of memory.  This blocks insns from being moved across this point.
6823 (define_insn "blockage"
6824   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6825   "TARGET_EITHER"
6826   ""
6827   [(set_attr "length" "0")
6828    (set_attr "type" "block")]
6831 (define_expand "casesi"
6832   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6833    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
6834    (match_operand:SI 2 "const_int_operand" "")  ; total range
6835    (match_operand:SI 3 "" "")                   ; table label
6836    (match_operand:SI 4 "" "")]                  ; Out of range label
6837   "TARGET_ARM"
6838   "
6839   {
6840     rtx reg;
6841     if (operands[1] != const0_rtx)
6842       {
6843         reg = gen_reg_rtx (SImode);
6845         emit_insn (gen_addsi3 (reg, operands[0],
6846                                GEN_INT (-INTVAL (operands[1]))));
6847         operands[0] = reg;
6848       }
6850     if (!const_ok_for_arm (INTVAL (operands[2])))
6851       operands[2] = force_reg (SImode, operands[2]);
6853     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6854                                          operands[4]));
6855     DONE;
6856   }"
6859 ;; The USE in this pattern is needed to tell flow analysis that this is
6860 ;; a CASESI insn.  It has no other purpose.
6861 (define_insn "casesi_internal"
6862   [(parallel [(set (pc)
6863                (if_then_else
6864                 (leu (match_operand:SI 0 "s_register_operand" "r")
6865                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
6866                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6867                                  (label_ref (match_operand 2 "" ""))))
6868                 (label_ref (match_operand 3 "" ""))))
6869               (clobber (reg:CC CC_REGNUM))
6870               (use (label_ref (match_dup 2)))])]
6871   "TARGET_ARM"
6872   "*
6873     if (flag_pic)
6874       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6875     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6876   "
6877   [(set_attr "conds" "clob")
6878    (set_attr "length" "12")]
6881 (define_expand "indirect_jump"
6882   [(set (pc)
6883         (match_operand:SI 0 "s_register_operand" ""))]
6884   "TARGET_EITHER"
6885   ""
6888 (define_insn "*arm_indirect_jump"
6889   [(set (pc)
6890         (match_operand:SI 0 "s_register_operand" "r"))]
6891   "TARGET_ARM"
6892   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6893   [(set_attr "predicable" "yes")]
6896 ;; Although not supported by the define_expand above,
6897 ;; cse/combine may generate this form.
6898 (define_insn "*load_indirect_jump"
6899   [(set (pc)
6900         (match_operand:SI 0 "memory_operand" "m"))]
6901   "TARGET_ARM"
6902   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6903   [(set_attr "type" "load")
6904    (set_attr "pool_range" "4096")
6905    (set_attr "neg_pool_range" "4084")
6906    (set_attr "predicable" "yes")]
6909 (define_insn "*thumb_indirect_jump"
6910   [(set (pc)
6911         (match_operand:SI 0 "register_operand" "l*r"))]
6912   "TARGET_THUMB"
6913   "mov\\tpc, %0"
6914   [(set_attr "conds" "clob")
6915    (set_attr "length" "2")]
6919 ;; Misc insns
6921 (define_insn "nop"
6922   [(const_int 0)]
6923   "TARGET_EITHER"
6924   "*
6925   if (TARGET_ARM)
6926     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6927   return  \"mov\\tr8, r8\";
6928   "
6929   [(set (attr "length")
6930         (if_then_else (eq_attr "is_thumb" "yes")
6931                       (const_int 2)
6932                       (const_int 4)))]
6936 ;; Patterns to allow combination of arithmetic, cond code and shifts
6938 (define_insn "*arith_shiftsi"
6939   [(set (match_operand:SI 0 "s_register_operand" "=r")
6940         (match_operator:SI 1 "shiftable_operator"
6941           [(match_operator:SI 3 "shift_operator"
6942              [(match_operand:SI 4 "s_register_operand" "r")
6943               (match_operand:SI 5 "reg_or_int_operand" "rI")])
6944            (match_operand:SI 2 "s_register_operand" "r")]))]
6945   "TARGET_ARM"
6946   "%i1%?\\t%0, %2, %4%S3"
6947   [(set_attr "predicable" "yes")
6948    (set_attr "shift" "4")
6949    ]
6952 (define_insn "*arith_shiftsi_compare0"
6953   [(set (reg:CC_NOOV CC_REGNUM)
6954         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6955                           [(match_operator:SI 3 "shift_operator"
6956                             [(match_operand:SI 4 "s_register_operand" "r")
6957                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6958                            (match_operand:SI 2 "s_register_operand" "r")])
6959                          (const_int 0)))
6960    (set (match_operand:SI 0 "s_register_operand" "=r")
6961         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6962                          (match_dup 2)]))]
6963   "TARGET_ARM"
6964   "%i1%?s\\t%0, %2, %4%S3"
6965   [(set_attr "conds" "set")
6966    (set_attr "shift" "4")
6967    ]
6970 (define_insn "*arith_shiftsi_compare0_scratch"
6971   [(set (reg:CC_NOOV CC_REGNUM)
6972         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6973                           [(match_operator:SI 3 "shift_operator"
6974                             [(match_operand:SI 4 "s_register_operand" "r")
6975                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6976                            (match_operand:SI 2 "s_register_operand" "r")])
6977                          (const_int 0)))
6978    (clobber (match_scratch:SI 0 "=r"))]
6979   "TARGET_ARM"
6980   "%i1%?s\\t%0, %2, %4%S3"
6981   [(set_attr "conds" "set")
6982    (set_attr "shift" "4")
6983    ]
6986 (define_insn "*sub_shiftsi"
6987   [(set (match_operand:SI 0 "s_register_operand" "=r")
6988         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6989                   (match_operator:SI 2 "shift_operator"
6990                    [(match_operand:SI 3 "s_register_operand" "r")
6991                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6992   "TARGET_ARM"
6993   "sub%?\\t%0, %1, %3%S2"
6994   [(set_attr "predicable" "yes")
6995    (set_attr "shift" "3")
6996    ]
6999 (define_insn "*sub_shiftsi_compare0"
7000   [(set (reg:CC_NOOV CC_REGNUM)
7001         (compare:CC_NOOV
7002          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7003                    (match_operator:SI 2 "shift_operator"
7004                     [(match_operand:SI 3 "s_register_operand" "r")
7005                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7006          (const_int 0)))
7007    (set (match_operand:SI 0 "s_register_operand" "=r")
7008         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7009                                                  (match_dup 4)])))]
7010   "TARGET_ARM"
7011   "sub%?s\\t%0, %1, %3%S2"
7012   [(set_attr "conds" "set")
7013    (set_attr "shift" "3") 
7014    ]
7017 (define_insn "*sub_shiftsi_compare0_scratch"
7018   [(set (reg:CC_NOOV CC_REGNUM)
7019         (compare:CC_NOOV
7020          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7021                    (match_operator:SI 2 "shift_operator"
7022                     [(match_operand:SI 3 "s_register_operand" "r")
7023                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7024          (const_int 0)))
7025    (clobber (match_scratch:SI 0 "=r"))]
7026   "TARGET_ARM"
7027   "sub%?s\\t%0, %1, %3%S2"
7028   [(set_attr "conds" "set")
7029    (set_attr "shift" "3") 
7030    ]
7033 ;; These variants of the above insns can occur if the first operand is the
7034 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
7035 ;; seem to be a way around it.  Most of the predicates have to be null
7036 ;; because the format can be generated part way through reload, so
7037 ;; if we don't match it as soon as it becomes available, reload doesn't know
7038 ;; how to reload pseudos that haven't got hard registers; the constraints will
7039 ;; sort everything out.
7041 (define_insn "*reload_mulsi3"
7042   [(set (match_operand:SI 0 "" "=&r")
7043         (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
7044                            [(match_operand:SI 3 "" "r")
7045                             (match_operand:SI 4 "" "rM")])
7046                           (match_operand:SI 2 "" "r"))
7047                  (match_operand:SI 1 "const_int_operand" "n")))]
7048   "TARGET_ARM && reload_in_progress"
7049   "*
7050   output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
7051   operands[2] = operands[1];
7052   operands[1] = operands[0];
7053   return output_add_immediate (operands);
7054   "
7055   [
7056    ; we have no idea how long the add_immediate is, it could be up to 4.
7057    (set_attr "length" "20")]
7060 (define_insn "*reload_mulsi_compare0"
7061   [(set (reg:CC_NOOV CC_REGNUM)
7062         (compare:CC_NOOV (plus:SI
7063                           (plus:SI 
7064                            (match_operator:SI 5 "shift_operator"
7065                             [(match_operand:SI 3 "" "r")
7066                              (match_operand:SI 4 "" "rM")])
7067                            (match_operand:SI 1 "" "r"))
7068                           (match_operand:SI 2 "const_int_operand" "n"))
7069                          (const_int 0)))
7070    (set (match_operand:SI 0 "" "=&r")
7071         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
7072                           (match_dup 1))
7073                  (match_dup 2)))]
7074   "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7075   "*
7076     output_add_immediate (operands);
7077     return \"add%?s\\t%0, %0, %3%S5\";
7078   "
7079   [(set_attr "conds" "set")
7080    (set_attr "shift" "3")
7081    (set_attr "length" "20")]
7084 (define_insn "*reload_mulsi_compare0_scratch"
7085   [(set (reg:CC_NOOV CC_REGNUM)
7086         (compare:CC_NOOV (plus:SI
7087                           (plus:SI 
7088                            (match_operator:SI 5 "shift_operator"
7089                             [(match_operand:SI 3 "" "r")
7090                              (match_operand:SI 4 "" "rM")])
7091                            (match_operand:SI 1 "" "r"))
7092                           (match_operand:SI 2 "const_int_operand" "n"))
7093                          (const_int 0)))
7094    (clobber (match_scratch:SI 0 "=&r"))]
7095   "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7096   "*
7097     output_add_immediate (operands);
7098     return \"add%?s\\t%0, %0, %3%S5\";
7099   "
7100   [(set_attr "conds" "set")
7101    (set_attr "shift" "3")
7102    (set_attr "length" "20")]
7105 ;; These are similar, but are needed when the mla pattern contains the
7106 ;; eliminated register as operand 3.
7108 (define_insn "*reload_muladdsi"
7109   [(set (match_operand:SI 0 "" "=&r,&r")
7110         (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
7111                                    (match_operand:SI 2 "" "r,r"))
7112                           (match_operand:SI 3 "" "r,r"))
7113                  (match_operand:SI 4 "const_int_operand" "n,n")))]
7114   "TARGET_ARM && reload_in_progress"
7115   "*
7116   output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
7117   operands[2] = operands[4];
7118   operands[1] = operands[0];
7119   return output_add_immediate (operands);
7120   "
7121   [(set_attr "length" "20")
7122    (set_attr "type" "mult")]
7125 (define_insn "*reload_muladdsi_compare0"
7126   [(set (reg:CC_NOOV CC_REGNUM)
7127         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7128                                             (match_operand:SI 3 "" "r")
7129                                             (match_operand:SI 4 "" "r"))
7130                                            (match_operand:SI 1 "" "r"))
7131                                   (match_operand:SI 2 "const_int_operand" "n"))
7132                          (const_int 0)))
7133    (set (match_operand:SI 0 "" "=&r")
7134         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
7135                  (match_dup 2)))]
7136   "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7137   "*
7138     output_add_immediate (operands);
7139     output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
7140     return \"\";
7141   "
7142   [(set_attr "length" "20")
7143    (set_attr "conds" "set")
7144    (set_attr "type" "mult")]
7147 (define_insn "*reload_muladdsi_compare0_scratch"
7148   [(set (reg:CC_NOOV CC_REGNUM)
7149         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7150                                             (match_operand:SI 3 "" "r")
7151                                             (match_operand:SI 4 "" "r"))
7152                                            (match_operand:SI 1 "" "r"))
7153                                   (match_operand:SI 2 "const_int_operand" "n"))
7154                          (const_int 0)))
7155    (clobber (match_scratch:SI 0 "=&r"))]
7156   "TARGET_ARM && reload_in_progress"
7157   "*
7158     output_add_immediate (operands);
7159     return \"mla%?s\\t%0, %3, %4, %0\";
7160   "
7161   [(set_attr "length" "20")
7162    (set_attr "conds" "set")
7163    (set_attr "type" "mult")]
7168 (define_insn "*and_scc"
7169   [(set (match_operand:SI 0 "s_register_operand" "=r")
7170         (and:SI (match_operator:SI 1 "arm_comparison_operator"
7171                  [(match_operand 3 "cc_register" "") (const_int 0)])
7172                 (match_operand:SI 2 "s_register_operand" "r")))]
7173   "TARGET_ARM"
7174   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7175   [(set_attr "conds" "use")
7176    (set_attr "length" "8")]
7179 (define_insn "*ior_scc"
7180   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7181         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7182                  [(match_operand 3 "cc_register" "") (const_int 0)])
7183                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7184   "TARGET_ARM"
7185   "@
7186    orr%d2\\t%0, %1, #1
7187    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7188   [(set_attr "conds" "use")
7189    (set_attr "length" "4,8")]
7192 (define_insn "*compare_scc"
7193   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7194         (match_operator:SI 1 "arm_comparison_operator"
7195          [(match_operand:SI 2 "s_register_operand" "r,r")
7196           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7197    (clobber (reg:CC CC_REGNUM))]
7198   "TARGET_ARM"
7199   "*
7200     if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7201       return \"mov\\t%0, %2, lsr #31\";
7203     if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7204       return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7206     if (GET_CODE (operands[1]) == NE)
7207       {
7208         if (which_alternative == 1)
7209           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7210         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7211       }
7212     if (which_alternative == 1)
7213       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7214     else
7215       output_asm_insn (\"cmp\\t%2, %3\", operands);
7216     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7217   "
7218   [(set_attr "conds" "clob")
7219    (set_attr "length" "12")]
7222 (define_insn "*cond_move"
7223   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7224         (if_then_else:SI (match_operator 3 "equality_operator"
7225                           [(match_operator 4 "arm_comparison_operator"
7226                             [(match_operand 5 "cc_register" "") (const_int 0)])
7227                            (const_int 0)])
7228                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7229                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7230   "TARGET_ARM"
7231   "*
7232     if (GET_CODE (operands[3]) == NE)
7233       {
7234         if (which_alternative != 1)
7235           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7236         if (which_alternative != 0)
7237           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7238         return \"\";
7239       }
7240     if (which_alternative != 0)
7241       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7242     if (which_alternative != 1)
7243       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7244     return \"\";
7245   "
7246   [(set_attr "conds" "use")
7247    (set_attr "length" "4,4,8")]
7250 (define_insn "*cond_arith"
7251   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7252         (match_operator:SI 5 "shiftable_operator" 
7253          [(match_operator:SI 4 "arm_comparison_operator"
7254            [(match_operand:SI 2 "s_register_operand" "r,r")
7255             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7256           (match_operand:SI 1 "s_register_operand" "0,?r")]))
7257    (clobber (reg:CC CC_REGNUM))]
7258   "TARGET_ARM"
7259   "*
7260     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7261       return \"%i5\\t%0, %1, %2, lsr #31\";
7263     output_asm_insn (\"cmp\\t%2, %3\", operands);
7264     if (GET_CODE (operands[5]) == AND)
7265       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7266     else if (GET_CODE (operands[5]) == MINUS)
7267       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7268     else if (which_alternative != 0)
7269       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7270     return \"%i5%d4\\t%0, %1, #1\";
7271   "
7272   [(set_attr "conds" "clob")
7273    (set_attr "length" "12")]
7276 (define_insn "*cond_sub"
7277   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7278         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7279                   (match_operator:SI 4 "arm_comparison_operator"
7280                    [(match_operand:SI 2 "s_register_operand" "r,r")
7281                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7282    (clobber (reg:CC CC_REGNUM))]
7283   "TARGET_ARM"
7284   "*
7285     output_asm_insn (\"cmp\\t%2, %3\", operands);
7286     if (which_alternative != 0)
7287       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7288     return \"sub%d4\\t%0, %1, #1\";
7289   "
7290   [(set_attr "conds" "clob")
7291    (set_attr "length" "8,12")]
7294 (define_insn "*cmp_ite0"
7295   [(set (match_operand 6 "dominant_cc_register" "")
7296         (compare
7297          (if_then_else:SI
7298           (match_operator 4 "arm_comparison_operator"
7299            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7300             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7301           (match_operator:SI 5 "arm_comparison_operator"
7302            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7303             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7304           (const_int 0))
7305          (const_int 0)))]
7306   "TARGET_ARM"
7307   "*
7308   {
7309     static const char * const opcodes[4][2] =
7310     {
7311       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7312        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7313       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7314        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7315       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7316        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7317       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7318        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7319     };
7320     int swap =
7321       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7323     return opcodes[which_alternative][swap];
7324   }"
7325   [(set_attr "conds" "set")
7326    (set_attr "length" "8")]
7329 (define_insn "*cmp_ite1"
7330   [(set (match_operand 6 "dominant_cc_register" "")
7331         (compare
7332          (if_then_else:SI
7333           (match_operator 4 "arm_comparison_operator"
7334            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7335             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7336           (match_operator:SI 5 "arm_comparison_operator"
7337            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7338             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7339           (const_int 1))
7340          (const_int 0)))]
7341   "TARGET_ARM"
7342   "*
7343   {
7344     static const char * const opcodes[4][2] =
7345     {
7346       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7347        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7348       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7349        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7350       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7351        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7352       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7353        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7354     };
7355     int swap =
7356       comparison_dominates_p (GET_CODE (operands[5]),
7357                               reverse_condition (GET_CODE (operands[4])));
7359     return opcodes[which_alternative][swap];
7360   }"
7361   [(set_attr "conds" "set")
7362    (set_attr "length" "8")]
7365 (define_insn "*cmp_and"
7366   [(set (match_operand 6 "dominant_cc_register" "")
7367         (compare
7368          (and:SI
7369           (match_operator 4 "arm_comparison_operator"
7370            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7371             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7372           (match_operator:SI 5 "arm_comparison_operator"
7373            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7374             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7375          (const_int 0)))]
7376   "TARGET_ARM"
7377   "*
7378   {
7379     static const char *const opcodes[4][2] =
7380     {
7381       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7382        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7383       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7384        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7385       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7386        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7387       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7388        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7389     };
7390     int swap =
7391       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7393     return opcodes[which_alternative][swap];
7394   }"
7395   [(set_attr "conds" "set")
7396    (set_attr "predicable" "no")
7397    (set_attr "length" "8")]
7400 (define_insn "*cmp_ior"
7401   [(set (match_operand 6 "dominant_cc_register" "")
7402         (compare
7403          (ior:SI
7404           (match_operator 4 "arm_comparison_operator"
7405            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7406             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7407           (match_operator:SI 5 "arm_comparison_operator"
7408            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7409             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7410          (const_int 0)))]
7411   "TARGET_ARM"
7412   "*
7414   static const char *const opcodes[4][2] =
7415   {
7416     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7417      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7418     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7419      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7420     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7421      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7422     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7423      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7424   };
7425   int swap =
7426     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7428   return opcodes[which_alternative][swap];
7431   [(set_attr "conds" "set")
7432    (set_attr "length" "8")]
7435 (define_insn "*negscc"
7436   [(set (match_operand:SI 0 "s_register_operand" "=r")
7437         (neg:SI (match_operator 3 "arm_comparison_operator"
7438                  [(match_operand:SI 1 "s_register_operand" "r")
7439                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7440    (clobber (reg:CC CC_REGNUM))]
7441   "TARGET_ARM"
7442   "*
7443   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7444     return \"mov\\t%0, %1, asr #31\";
7446   if (GET_CODE (operands[3]) == NE)
7447     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7449   if (GET_CODE (operands[3]) == GT)
7450     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7452   output_asm_insn (\"cmp\\t%1, %2\", operands);
7453   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7454   return \"mvn%d3\\t%0, #0\";
7455   "
7456   [(set_attr "conds" "clob")
7457    (set_attr "length" "12")]
7460 (define_insn "movcond"
7461   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7462         (if_then_else:SI
7463          (match_operator 5 "arm_comparison_operator"
7464           [(match_operand:SI 3 "s_register_operand" "r,r,r")
7465            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7466          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7467          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7468    (clobber (reg:CC CC_REGNUM))]
7469   "TARGET_ARM"
7470   "*
7471   if (GET_CODE (operands[5]) == LT
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 \"and\\t%0, %1, %3, asr #31\";
7478           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7479         }
7480       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7481         {
7482           if (operands[1] == const0_rtx)
7483             return \"bic\\t%0, %2, %3, asr #31\";
7484           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7485         }
7486       /* The only case that falls through to here is when both ops 1 & 2
7487          are constants */
7488     }
7490   if (GET_CODE (operands[5]) == GE
7491       && (operands[4] == const0_rtx))
7492     {
7493       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7494         {
7495           if (operands[2] == const0_rtx)
7496             return \"bic\\t%0, %1, %3, asr #31\";
7497           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7498         }
7499       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7500         {
7501           if (operands[1] == const0_rtx)
7502             return \"and\\t%0, %2, %3, asr #31\";
7503           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7504         }
7505       /* The only case that falls through to here is when both ops 1 & 2
7506          are constants */
7507     }
7508   if (GET_CODE (operands[4]) == CONST_INT
7509       && !const_ok_for_arm (INTVAL (operands[4])))
7510     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7511   else
7512     output_asm_insn (\"cmp\\t%3, %4\", operands);
7513   if (which_alternative != 0)
7514     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7515   if (which_alternative != 1)
7516     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7517   return \"\";
7518   "
7519   [(set_attr "conds" "clob")
7520    (set_attr "length" "8,8,12")]
7523 (define_insn "*ifcompare_plus_move"
7524   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7525         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7526                           [(match_operand:SI 4 "s_register_operand" "r,r")
7527                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7528                          (plus:SI
7529                           (match_operand:SI 2 "s_register_operand" "r,r")
7530                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7531                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7532    (clobber (reg:CC CC_REGNUM))]
7533   "TARGET_ARM"
7534   "#"
7535   [(set_attr "conds" "clob")
7536    (set_attr "length" "8,12")]
7539 (define_insn "*if_plus_move"
7540   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7541         (if_then_else:SI
7542          (match_operator 4 "arm_comparison_operator"
7543           [(match_operand 5 "cc_register" "") (const_int 0)])
7544          (plus:SI
7545           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7546           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7547          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7548   "TARGET_ARM"
7549   "@
7550    add%d4\\t%0, %2, %3
7551    sub%d4\\t%0, %2, #%n3
7552    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7553    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7554   [(set_attr "conds" "use")
7555    (set_attr "length" "4,4,8,8")
7556    (set_attr "type" "*,*,*,*")]
7559 (define_insn "*ifcompare_move_plus"
7560   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7561         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7562                           [(match_operand:SI 4 "s_register_operand" "r,r")
7563                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7564                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7565                          (plus:SI
7566                           (match_operand:SI 2 "s_register_operand" "r,r")
7567                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7568    (clobber (reg:CC CC_REGNUM))]
7569   "TARGET_ARM"
7570   "#"
7571   [(set_attr "conds" "clob")
7572    (set_attr "length" "8,12")]
7575 (define_insn "*if_move_plus"
7576   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7577         (if_then_else:SI
7578          (match_operator 4 "arm_comparison_operator"
7579           [(match_operand 5 "cc_register" "") (const_int 0)])
7580          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7581          (plus:SI
7582           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7583           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7584   "TARGET_ARM"
7585   "@
7586    add%D4\\t%0, %2, %3
7587    sub%D4\\t%0, %2, #%n3
7588    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7589    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7590   [(set_attr "conds" "use")
7591    (set_attr "length" "4,4,8,8")
7592    (set_attr "type" "*,*,*,*")]
7595 (define_insn "*ifcompare_arith_arith"
7596   [(set (match_operand:SI 0 "s_register_operand" "=r")
7597         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7598                           [(match_operand:SI 5 "s_register_operand" "r")
7599                            (match_operand:SI 6 "arm_add_operand" "rIL")])
7600                          (match_operator:SI 8 "shiftable_operator"
7601                           [(match_operand:SI 1 "s_register_operand" "r")
7602                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7603                          (match_operator:SI 7 "shiftable_operator"
7604                           [(match_operand:SI 3 "s_register_operand" "r")
7605                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7606    (clobber (reg:CC CC_REGNUM))]
7607   "TARGET_ARM"
7608   "#"
7609   [(set_attr "conds" "clob")
7610    (set_attr "length" "12")]
7613 (define_insn "*if_arith_arith"
7614   [(set (match_operand:SI 0 "s_register_operand" "=r")
7615         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7616                           [(match_operand 8 "cc_register" "") (const_int 0)])
7617                          (match_operator:SI 6 "shiftable_operator"
7618                           [(match_operand:SI 1 "s_register_operand" "r")
7619                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7620                          (match_operator:SI 7 "shiftable_operator"
7621                           [(match_operand:SI 3 "s_register_operand" "r")
7622                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7623   "TARGET_ARM"
7624   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7625   [(set_attr "conds" "use")
7626    (set_attr "length" "8")]
7629 (define_insn "*ifcompare_arith_move"
7630   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7631         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7632                           [(match_operand:SI 2 "s_register_operand" "r,r")
7633                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7634                          (match_operator:SI 7 "shiftable_operator"
7635                           [(match_operand:SI 4 "s_register_operand" "r,r")
7636                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7637                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7638    (clobber (reg:CC CC_REGNUM))]
7639   "TARGET_ARM"
7640   "*
7641   /* If we have an operation where (op x 0) is the identity operation and
7642      the conditional operator is LT or GE and we are comparing against zero and
7643      everything is in registers then we can do this in two instructions */
7644   if (operands[3] == const0_rtx
7645       && GET_CODE (operands[7]) != AND
7646       && GET_CODE (operands[5]) == REG
7647       && GET_CODE (operands[1]) == REG 
7648       && REGNO (operands[1]) == REGNO (operands[4])
7649       && REGNO (operands[4]) != REGNO (operands[0]))
7650     {
7651       if (GET_CODE (operands[6]) == LT)
7652         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7653       else if (GET_CODE (operands[6]) == GE)
7654         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7655     }
7656   if (GET_CODE (operands[3]) == CONST_INT
7657       && !const_ok_for_arm (INTVAL (operands[3])))
7658     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7659   else
7660     output_asm_insn (\"cmp\\t%2, %3\", operands);
7661   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7662   if (which_alternative != 0)
7663     return \"mov%D6\\t%0, %1\";
7664   return \"\";
7665   "
7666   [(set_attr "conds" "clob")
7667    (set_attr "length" "8,12")]
7670 (define_insn "*if_arith_move"
7671   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7672         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7673                           [(match_operand 6 "cc_register" "") (const_int 0)])
7674                          (match_operator:SI 5 "shiftable_operator"
7675                           [(match_operand:SI 2 "s_register_operand" "r,r")
7676                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7677                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7678   "TARGET_ARM"
7679   "@
7680    %I5%d4\\t%0, %2, %3
7681    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7682   [(set_attr "conds" "use")
7683    (set_attr "length" "4,8")
7684    (set_attr "type" "*,*")]
7687 (define_insn "*ifcompare_move_arith"
7688   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7689         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7690                           [(match_operand:SI 4 "s_register_operand" "r,r")
7691                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7692                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7693                          (match_operator:SI 7 "shiftable_operator"
7694                           [(match_operand:SI 2 "s_register_operand" "r,r")
7695                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7696    (clobber (reg:CC CC_REGNUM))]
7697   "TARGET_ARM"
7698   "*
7699   /* If we have an operation where (op x 0) is the identity operation and
7700      the conditional operator is LT or GE and we are comparing against zero and
7701      everything is in registers then we can do this in two instructions */
7702   if (operands[5] == const0_rtx
7703       && GET_CODE (operands[7]) != AND
7704       && GET_CODE (operands[3]) == REG
7705       && GET_CODE (operands[1]) == REG 
7706       && REGNO (operands[1]) == REGNO (operands[2])
7707       && REGNO (operands[2]) != REGNO (operands[0]))
7708     {
7709       if (GET_CODE (operands[6]) == GE)
7710         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7711       else if (GET_CODE (operands[6]) == LT)
7712         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7713     }
7715   if (GET_CODE (operands[5]) == CONST_INT
7716       && !const_ok_for_arm (INTVAL (operands[5])))
7717     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7718   else
7719     output_asm_insn (\"cmp\\t%4, %5\", operands);
7721   if (which_alternative != 0)
7722     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7723   return \"%I7%D6\\t%0, %2, %3\";
7724   "
7725   [(set_attr "conds" "clob")
7726    (set_attr "length" "8,12")]
7729 (define_insn "*if_move_arith"
7730   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7731         (if_then_else:SI
7732          (match_operator 4 "arm_comparison_operator"
7733           [(match_operand 6 "cc_register" "") (const_int 0)])
7734          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7735          (match_operator:SI 5 "shiftable_operator"
7736           [(match_operand:SI 2 "s_register_operand" "r,r")
7737            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7738   "TARGET_ARM"
7739   "@
7740    %I5%D4\\t%0, %2, %3
7741    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7742   [(set_attr "conds" "use")
7743    (set_attr "length" "4,8")
7744    (set_attr "type" "*,*")]
7747 (define_insn "*ifcompare_move_not"
7748   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7749         (if_then_else:SI
7750          (match_operator 5 "arm_comparison_operator"
7751           [(match_operand:SI 3 "s_register_operand" "r,r")
7752            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7753          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7754          (not:SI
7755           (match_operand:SI 2 "s_register_operand" "r,r"))))
7756    (clobber (reg:CC CC_REGNUM))]
7757   "TARGET_ARM"
7758   "#"
7759   [(set_attr "conds" "clob")
7760    (set_attr "length" "8,12")]
7763 (define_insn "*if_move_not"
7764   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7765         (if_then_else:SI
7766          (match_operator 4 "arm_comparison_operator"
7767           [(match_operand 3 "cc_register" "") (const_int 0)])
7768          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7769          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7770   "TARGET_ARM"
7771   "@
7772    mvn%D4\\t%0, %2
7773    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7774    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7775   [(set_attr "conds" "use")
7776    (set_attr "length" "4,8,8")]
7779 (define_insn "*ifcompare_not_move"
7780   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7781         (if_then_else:SI 
7782          (match_operator 5 "arm_comparison_operator"
7783           [(match_operand:SI 3 "s_register_operand" "r,r")
7784            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7785          (not:SI
7786           (match_operand:SI 2 "s_register_operand" "r,r"))
7787          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7788    (clobber (reg:CC CC_REGNUM))]
7789   "TARGET_ARM"
7790   "#"
7791   [(set_attr "conds" "clob")
7792    (set_attr "length" "8,12")]
7795 (define_insn "*if_not_move"
7796   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7797         (if_then_else:SI
7798          (match_operator 4 "arm_comparison_operator"
7799           [(match_operand 3 "cc_register" "") (const_int 0)])
7800          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7801          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7802   "TARGET_ARM"
7803   "@
7804    mvn%d4\\t%0, %2
7805    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7806    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7807   [(set_attr "conds" "use")
7808    (set_attr "length" "4,8,8")]
7811 (define_insn "*ifcompare_shift_move"
7812   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7813         (if_then_else:SI
7814          (match_operator 6 "arm_comparison_operator"
7815           [(match_operand:SI 4 "s_register_operand" "r,r")
7816            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7817          (match_operator:SI 7 "shift_operator"
7818           [(match_operand:SI 2 "s_register_operand" "r,r")
7819            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7820          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7821    (clobber (reg:CC CC_REGNUM))]
7822   "TARGET_ARM"
7823   "#"
7824   [(set_attr "conds" "clob")
7825    (set_attr "length" "8,12")]
7828 (define_insn "*if_shift_move"
7829   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7830         (if_then_else:SI
7831          (match_operator 5 "arm_comparison_operator"
7832           [(match_operand 6 "cc_register" "") (const_int 0)])
7833          (match_operator:SI 4 "shift_operator"
7834           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7835            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7836          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7837   "TARGET_ARM"
7838   "@
7839    mov%d5\\t%0, %2%S4
7840    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7841    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7842   [(set_attr "conds" "use")
7843    (set_attr "shift" "2")
7844    (set_attr "length" "4,8,8")]
7847 (define_insn "*ifcompare_move_shift"
7848   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7849         (if_then_else:SI
7850          (match_operator 6 "arm_comparison_operator"
7851           [(match_operand:SI 4 "s_register_operand" "r,r")
7852            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7853          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7854          (match_operator:SI 7 "shift_operator"
7855           [(match_operand:SI 2 "s_register_operand" "r,r")
7856            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7857    (clobber (reg:CC CC_REGNUM))]
7858   "TARGET_ARM"
7859   "#"
7860   [(set_attr "conds" "clob")
7861    (set_attr "length" "8,12")]
7864 (define_insn "*if_move_shift"
7865   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7866         (if_then_else:SI
7867          (match_operator 5 "arm_comparison_operator"
7868           [(match_operand 6 "cc_register" "") (const_int 0)])
7869          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7870          (match_operator:SI 4 "shift_operator"
7871           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7872            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7873   "TARGET_ARM"
7874   "@
7875    mov%D5\\t%0, %2%S4
7876    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7877    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7878   [(set_attr "conds" "use")
7879    (set_attr "shift" "2")
7880    (set_attr "length" "4,8,8")]
7883 (define_insn "*ifcompare_shift_shift"
7884   [(set (match_operand:SI 0 "s_register_operand" "=r")
7885         (if_then_else:SI
7886          (match_operator 7 "arm_comparison_operator"
7887           [(match_operand:SI 5 "s_register_operand" "r")
7888            (match_operand:SI 6 "arm_add_operand" "rIL")])
7889          (match_operator:SI 8 "shift_operator"
7890           [(match_operand:SI 1 "s_register_operand" "r")
7891            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7892          (match_operator:SI 9 "shift_operator"
7893           [(match_operand:SI 3 "s_register_operand" "r")
7894            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7895    (clobber (reg:CC CC_REGNUM))]
7896   "TARGET_ARM"
7897   "#"
7898   [(set_attr "conds" "clob")
7899    (set_attr "length" "12")]
7902 (define_insn "*if_shift_shift"
7903   [(set (match_operand:SI 0 "s_register_operand" "=r")
7904         (if_then_else:SI
7905          (match_operator 5 "arm_comparison_operator"
7906           [(match_operand 8 "cc_register" "") (const_int 0)])
7907          (match_operator:SI 6 "shift_operator"
7908           [(match_operand:SI 1 "s_register_operand" "r")
7909            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7910          (match_operator:SI 7 "shift_operator"
7911           [(match_operand:SI 3 "s_register_operand" "r")
7912            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7913   "TARGET_ARM"
7914   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7915   [(set_attr "conds" "use")
7916    (set_attr "shift" "1")
7917    (set_attr "length" "8")]
7920 (define_insn "*ifcompare_not_arith"
7921   [(set (match_operand:SI 0 "s_register_operand" "=r")
7922         (if_then_else:SI
7923          (match_operator 6 "arm_comparison_operator"
7924           [(match_operand:SI 4 "s_register_operand" "r")
7925            (match_operand:SI 5 "arm_add_operand" "rIL")])
7926          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7927          (match_operator:SI 7 "shiftable_operator"
7928           [(match_operand:SI 2 "s_register_operand" "r")
7929            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7930    (clobber (reg:CC CC_REGNUM))]
7931   "TARGET_ARM"
7932   "#"
7933   [(set_attr "conds" "clob")
7934    (set_attr "length" "12")]
7937 (define_insn "*if_not_arith"
7938   [(set (match_operand:SI 0 "s_register_operand" "=r")
7939         (if_then_else:SI
7940          (match_operator 5 "arm_comparison_operator"
7941           [(match_operand 4 "cc_register" "") (const_int 0)])
7942          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7943          (match_operator:SI 6 "shiftable_operator"
7944           [(match_operand:SI 2 "s_register_operand" "r")
7945            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7946   "TARGET_ARM"
7947   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7948   [(set_attr "conds" "use")
7949    (set_attr "length" "8")]
7952 (define_insn "*ifcompare_arith_not"
7953   [(set (match_operand:SI 0 "s_register_operand" "=r")
7954         (if_then_else:SI
7955          (match_operator 6 "arm_comparison_operator"
7956           [(match_operand:SI 4 "s_register_operand" "r")
7957            (match_operand:SI 5 "arm_add_operand" "rIL")])
7958          (match_operator:SI 7 "shiftable_operator"
7959           [(match_operand:SI 2 "s_register_operand" "r")
7960            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7961          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7962    (clobber (reg:CC CC_REGNUM))]
7963   "TARGET_ARM"
7964   "#"
7965   [(set_attr "conds" "clob")
7966    (set_attr "length" "12")]
7969 (define_insn "*if_arith_not"
7970   [(set (match_operand:SI 0 "s_register_operand" "=r")
7971         (if_then_else:SI
7972          (match_operator 5 "arm_comparison_operator"
7973           [(match_operand 4 "cc_register" "") (const_int 0)])
7974          (match_operator:SI 6 "shiftable_operator"
7975           [(match_operand:SI 2 "s_register_operand" "r")
7976            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7977          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7978   "TARGET_ARM"
7979   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7980   [(set_attr "conds" "use")
7981    (set_attr "length" "8")]
7984 (define_insn "*ifcompare_neg_move"
7985   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7986         (if_then_else:SI
7987          (match_operator 5 "arm_comparison_operator"
7988           [(match_operand:SI 3 "s_register_operand" "r,r")
7989            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7990          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7991          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7992    (clobber (reg:CC CC_REGNUM))]
7993   "TARGET_ARM"
7994   "#"
7995   [(set_attr "conds" "clob")
7996    (set_attr "length" "8,12")]
7999 (define_insn "*if_neg_move"
8000   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8001         (if_then_else:SI
8002          (match_operator 4 "arm_comparison_operator"
8003           [(match_operand 3 "cc_register" "") (const_int 0)])
8004          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8005          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8006   "TARGET_ARM"
8007   "@
8008    rsb%d4\\t%0, %2, #0
8009    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8010    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8011   [(set_attr "conds" "use")
8012    (set_attr "length" "4,8,8")]
8015 (define_insn "*ifcompare_move_neg"
8016   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8017         (if_then_else:SI
8018          (match_operator 5 "arm_comparison_operator"
8019           [(match_operand:SI 3 "s_register_operand" "r,r")
8020            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8021          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8022          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8023    (clobber (reg:CC CC_REGNUM))]
8024   "TARGET_ARM"
8025   "#"
8026   [(set_attr "conds" "clob")
8027    (set_attr "length" "8,12")]
8030 (define_insn "*if_move_neg"
8031   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8032         (if_then_else:SI
8033          (match_operator 4 "arm_comparison_operator"
8034           [(match_operand 3 "cc_register" "") (const_int 0)])
8035          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8036          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8037   "TARGET_ARM"
8038   "@
8039    rsb%D4\\t%0, %2, #0
8040    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8041    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8042   [(set_attr "conds" "use")
8043    (set_attr "length" "4,8,8")]
8046 (define_insn "*arith_adjacentmem"
8047   [(set (match_operand:SI 0 "s_register_operand" "=r")
8048         (match_operator:SI 1 "shiftable_operator"
8049          [(match_operand:SI 2 "memory_operand" "m")
8050           (match_operand:SI 3 "memory_operand" "m")]))
8051    (clobber (match_scratch:SI 4 "=r"))]
8052   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8053   "*
8054   {
8055     rtx ldm[3];
8056     rtx arith[4];
8057     int val1 = 0, val2 = 0;
8059     if (REGNO (operands[0]) > REGNO (operands[4]))
8060       {
8061         ldm[1] = operands[4];
8062         ldm[2] = operands[0];
8063       }
8064     else
8065       {
8066         ldm[1] = operands[0];
8067         ldm[2] = operands[4];
8068       }
8069     if (GET_CODE (XEXP (operands[2], 0)) != REG)
8070       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8071     if (GET_CODE (XEXP (operands[3], 0)) != REG)
8072       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8073     arith[0] = operands[0];
8074     arith[3] = operands[1];
8075     if (val1 < val2)
8076       {
8077         arith[1] = ldm[1];
8078         arith[2] = ldm[2];
8079       }
8080     else
8081       {
8082         arith[1] = ldm[2];
8083         arith[2] = ldm[1];
8084       }
8085    if (val1 && val2)
8086       {
8087         rtx ops[3];
8088         ldm[0] = ops[0] = operands[4];
8089         ops[1] = XEXP (XEXP (operands[2], 0), 0);
8090         ops[2] = XEXP (XEXP (operands[2], 0), 1);
8091         output_add_immediate (ops);
8092         if (val1 < val2)
8093           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8094         else
8095           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8096       }
8097     else if (val1)
8098       {
8099         ldm[0] = XEXP (operands[3], 0);
8100         if (val1 < val2)
8101           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8102         else
8103           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8104       }
8105     else
8106       {
8107         ldm[0] = XEXP (operands[2], 0);
8108         if (val1 < val2)
8109           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8110         else
8111           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8112       }
8113     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8114     return \"\";
8115   }"
8116   [(set_attr "length" "12")
8117    (set_attr "predicable" "yes")
8118    (set_attr "type" "load")]
8121 ;; the arm can support extended pre-inc instructions
8123 ;; In all these cases, we use operands 0 and 1 for the register being
8124 ;; incremented because those are the operands that local-alloc will
8125 ;; tie and these are the pair most likely to be tieable (and the ones
8126 ;; that will benefit the most).
8128 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8129 ;; elimination will cause too many headaches.
8131 (define_insn "*strqi_preinc"
8132   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8133                          (match_operand:SI 2 "index_operand" "rJ")))
8134         (match_operand:QI 3 "s_register_operand" "r"))
8135    (set (match_operand:SI 0 "s_register_operand" "=r")
8136         (plus:SI (match_dup 1) (match_dup 2)))]
8137   "TARGET_ARM
8138    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8139    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8140    && (GET_CODE (operands[2]) != REG
8141        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8142   "str%?b\\t%3, [%0, %2]!"
8143   [(set_attr "type" "store1")
8144    (set_attr "predicable" "yes")]
8147 (define_insn "*strqi_predec"
8148   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8149                           (match_operand:SI 2 "s_register_operand" "r")))
8150         (match_operand:QI 3 "s_register_operand" "r"))
8151    (set (match_operand:SI 0 "s_register_operand" "=r")
8152         (minus:SI (match_dup 1) (match_dup 2)))]
8153   "TARGET_ARM
8154    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8155    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8156    && (GET_CODE (operands[2]) != REG
8157        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8158   "str%?b\\t%3, [%0, -%2]!"
8159   [(set_attr "type" "store1")
8160    (set_attr "predicable" "yes")]
8163 (define_insn "*loadqi_preinc"
8164   [(set (match_operand:QI 3 "s_register_operand" "=r")
8165         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8166                          (match_operand:SI 2 "index_operand" "rJ"))))
8167    (set (match_operand:SI 0 "s_register_operand" "=r")
8168         (plus:SI (match_dup 1) (match_dup 2)))]
8169   "TARGET_ARM
8170    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8171    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8172    && (GET_CODE (operands[2]) != REG
8173        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8174   "ldr%?b\\t%3, [%0, %2]!"
8175   [(set_attr "type" "load")
8176    (set_attr "predicable" "yes")]
8179 (define_insn "*loadqi_predec"
8180   [(set (match_operand:QI 3 "s_register_operand" "=r")
8181         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8182                           (match_operand:SI 2 "s_register_operand" "r"))))
8183    (set (match_operand:SI 0 "s_register_operand" "=r")
8184         (minus:SI (match_dup 1) (match_dup 2)))]
8185   "TARGET_ARM
8186    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8187    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8188    && (GET_CODE (operands[2]) != REG
8189        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8190   "ldr%?b\\t%3, [%0, -%2]!"
8191   [(set_attr "type" "load")
8192    (set_attr "predicable" "yes")]
8195 (define_insn "*loadqisi_preinc"
8196   [(set (match_operand:SI 3 "s_register_operand" "=r")
8197         (zero_extend:SI
8198          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8199                           (match_operand:SI 2 "index_operand" "rJ")))))
8200    (set (match_operand:SI 0 "s_register_operand" "=r")
8201         (plus:SI (match_dup 1) (match_dup 2)))]
8202   "TARGET_ARM
8203    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8204    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8205    && (GET_CODE (operands[2]) != REG
8206        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8207   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8208   [(set_attr "type" "load")
8209    (set_attr "predicable" "yes")]
8212 (define_insn "*loadqisi_predec"
8213   [(set (match_operand:SI 3 "s_register_operand" "=r")
8214         (zero_extend:SI
8215          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8216                            (match_operand:SI 2 "s_register_operand" "r")))))
8217    (set (match_operand:SI 0 "s_register_operand" "=r")
8218         (minus:SI (match_dup 1) (match_dup 2)))]
8219   "TARGET_ARM
8220    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8221    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8222    && (GET_CODE (operands[2]) != REG
8223        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8224   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8225   [(set_attr "type" "load")
8226    (set_attr "predicable" "yes")]
8229 (define_insn "*strsi_preinc"
8230   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8231                          (match_operand:SI 2 "index_operand" "rJ")))
8232         (match_operand:SI 3 "s_register_operand" "r"))
8233    (set (match_operand:SI 0 "s_register_operand" "=r")
8234         (plus:SI (match_dup 1) (match_dup 2)))]
8235   "TARGET_ARM
8236    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8237    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8238    && (GET_CODE (operands[2]) != REG
8239        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8240   "str%?\\t%3, [%0, %2]!"
8241   [(set_attr "type" "store1")
8242    (set_attr "predicable" "yes")]
8245 (define_insn "*strsi_predec"
8246   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8247                           (match_operand:SI 2 "s_register_operand" "r")))
8248         (match_operand:SI 3 "s_register_operand" "r"))
8249    (set (match_operand:SI 0 "s_register_operand" "=r")
8250         (minus:SI (match_dup 1) (match_dup 2)))]
8251   "TARGET_ARM
8252    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8253    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8254    && (GET_CODE (operands[2]) != REG
8255        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8256   "str%?\\t%3, [%0, -%2]!"
8257   [(set_attr "type" "store1")
8258    (set_attr "predicable" "yes")]
8261 (define_insn "*loadsi_preinc"
8262   [(set (match_operand:SI 3 "s_register_operand" "=r")
8263         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8264                          (match_operand:SI 2 "index_operand" "rJ"))))
8265    (set (match_operand:SI 0 "s_register_operand" "=r")
8266         (plus:SI (match_dup 1) (match_dup 2)))]
8267   "TARGET_ARM
8268    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8269    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8270    && (GET_CODE (operands[2]) != REG
8271        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8272   "ldr%?\\t%3, [%0, %2]!"
8273   [(set_attr "type" "load")
8274    (set_attr "predicable" "yes")]
8277 (define_insn "*loadsi_predec"
8278   [(set (match_operand:SI 3 "s_register_operand" "=r")
8279         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8280                           (match_operand:SI 2 "s_register_operand" "r"))))
8281    (set (match_operand:SI 0 "s_register_operand" "=r")
8282         (minus:SI (match_dup 1) (match_dup 2)))]
8283   "TARGET_ARM
8284    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8285    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8286    && (GET_CODE (operands[2]) != REG
8287        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8288   "ldr%?\\t%3, [%0, -%2]!"
8289   [(set_attr "type" "load")
8290    (set_attr "predicable" "yes")]
8293 (define_insn "*loadhi_preinc"
8294   [(set (match_operand:HI 3 "s_register_operand" "=r")
8295         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8296                          (match_operand:SI 2 "index_operand" "rJ"))))
8297    (set (match_operand:SI 0 "s_register_operand" "=r")
8298         (plus:SI (match_dup 1) (match_dup 2)))]
8299   "TARGET_ARM
8300    && !BYTES_BIG_ENDIAN
8301    && !TARGET_MMU_TRAPS
8302    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8303    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8304    && (GET_CODE (operands[2]) != REG
8305        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8306   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8307   [(set_attr "type" "load")
8308    (set_attr "predicable" "yes")]
8311 (define_insn "*loadhi_predec"
8312   [(set (match_operand:HI 3 "s_register_operand" "=r")
8313         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8314                           (match_operand:SI 2 "s_register_operand" "r"))))
8315    (set (match_operand:SI 0 "s_register_operand" "=r")
8316         (minus:SI (match_dup 1) (match_dup 2)))]
8317   "TARGET_ARM
8318    && !BYTES_BIG_ENDIAN
8319    && !TARGET_MMU_TRAPS
8320    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8321    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8322    && (GET_CODE (operands[2]) != REG
8323        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8324   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8325   [(set_attr "type" "load")
8326    (set_attr "predicable" "yes")]
8329 (define_insn "*strqi_shiftpreinc"
8330   [(set (mem:QI (plus:SI (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:SI 1 "s_register_operand" "0")))
8334         (match_operand:QI 5 "s_register_operand" "r"))
8335    (set (match_operand:SI 0 "s_register_operand" "=r")
8336         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8337                  (match_dup 1)))]
8338   "TARGET_ARM
8339    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8340    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8341    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8342   "str%?b\\t%5, [%0, %3%S2]!"
8343   [(set_attr "type" "store1")
8344    (set_attr "predicable" "yes")]
8347 (define_insn "*strqi_shiftpredec"
8348   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8349                           (match_operator:SI 2 "shift_operator"
8350                            [(match_operand:SI 3 "s_register_operand" "r")
8351                             (match_operand:SI 4 "const_shift_operand" "n")])))
8352         (match_operand:QI 5 "s_register_operand" "r"))
8353    (set (match_operand:SI 0 "s_register_operand" "=r")
8354         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8355                                                  (match_dup 4)])))]
8356   "TARGET_ARM
8357    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8358    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8359    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8360   "str%?b\\t%5, [%0, -%3%S2]!"
8361   [(set_attr "type" "store1")
8362    (set_attr "predicable" "yes")]
8365 (define_insn "*loadqi_shiftpreinc"
8366   [(set (match_operand:QI 5 "s_register_operand" "=r")
8367         (mem:QI (plus:SI (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                          (match_operand:SI 1 "s_register_operand" "0"))))
8371    (set (match_operand:SI 0 "s_register_operand" "=r")
8372         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8373                  (match_dup 1)))]
8374   "TARGET_ARM
8375    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8376    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8377    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8378   "ldr%?b\\t%5, [%0, %3%S2]!"
8379   [(set_attr "type" "load")
8380    (set_attr "predicable" "yes")]
8383 (define_insn "*loadqi_shiftpredec"
8384   [(set (match_operand:QI 5 "s_register_operand" "=r")
8385         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8386                           (match_operator:SI 2 "shift_operator"
8387                            [(match_operand:SI 3 "s_register_operand" "r")
8388                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8389    (set (match_operand:SI 0 "s_register_operand" "=r")
8390         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8391                                                  (match_dup 4)])))]
8392   "TARGET_ARM
8393    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8394    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8395    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8396   "ldr%?b\\t%5, [%0, -%3%S2]!"
8397   [(set_attr "type" "load")
8398    (set_attr "predicable" "yes")]
8401 (define_insn "*strsi_shiftpreinc"
8402   [(set (mem:SI (plus:SI (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 1 "s_register_operand" "0")))
8406         (match_operand:SI 5 "s_register_operand" "r"))
8407    (set (match_operand:SI 0 "s_register_operand" "=r")
8408         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8409                  (match_dup 1)))]
8410   "TARGET_ARM
8411    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8412    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8413    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8414   "str%?\\t%5, [%0, %3%S2]!"
8415   [(set_attr "type" "store1")
8416    (set_attr "predicable" "yes")]
8419 (define_insn "*strsi_shiftpredec"
8420   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8421                           (match_operator:SI 2 "shift_operator"
8422                            [(match_operand:SI 3 "s_register_operand" "r")
8423                             (match_operand:SI 4 "const_shift_operand" "n")])))
8424         (match_operand:SI 5 "s_register_operand" "r"))
8425    (set (match_operand:SI 0 "s_register_operand" "=r")
8426         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8427                                                  (match_dup 4)])))]
8428   "TARGET_ARM
8429    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8430    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8431    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8432   "str%?\\t%5, [%0, -%3%S2]!"
8433   [(set_attr "type" "store1")
8434    (set_attr "predicable" "yes")]
8437 (define_insn "*loadsi_shiftpreinc"
8438   [(set (match_operand:SI 5 "s_register_operand" "=r")
8439         (mem:SI (plus:SI (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                          (match_operand:SI 1 "s_register_operand" "0"))))
8443    (set (match_operand:SI 0 "s_register_operand" "=r")
8444         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8445                  (match_dup 1)))]
8446   "TARGET_ARM
8447    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8448    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8449    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8450   "ldr%?\\t%5, [%0, %3%S2]!"
8451   [(set_attr "type" "load")
8452    (set_attr "predicable" "yes")]
8455 (define_insn "*loadsi_shiftpredec"
8456   [(set (match_operand:SI 5 "s_register_operand" "=r")
8457         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8458                           (match_operator:SI 2 "shift_operator"
8459                            [(match_operand:SI 3 "s_register_operand" "r")
8460                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8461    (set (match_operand:SI 0 "s_register_operand" "=r")
8462         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8463                                                  (match_dup 4)])))]
8464   "TARGET_ARM
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]!"
8469   [(set_attr "type" "load")
8470    (set_attr "predicable" "yes")])
8472 (define_insn "*loadhi_shiftpreinc"
8473   [(set (match_operand:HI 5 "s_register_operand" "=r")
8474         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8475                           [(match_operand:SI 3 "s_register_operand" "r")
8476                            (match_operand:SI 4 "const_shift_operand" "n")])
8477                          (match_operand:SI 1 "s_register_operand" "0"))))
8478    (set (match_operand:SI 0 "s_register_operand" "=r")
8479         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8480                  (match_dup 1)))]
8481   "TARGET_ARM
8482    && !BYTES_BIG_ENDIAN
8483    && !TARGET_MMU_TRAPS
8484    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8485    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8486    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8487   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8488   [(set_attr "type" "load")
8489    (set_attr "predicable" "yes")]
8492 (define_insn "*loadhi_shiftpredec"
8493   [(set (match_operand:HI 5 "s_register_operand" "=r")
8494         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8495                           (match_operator:SI 2 "shift_operator"
8496                            [(match_operand:SI 3 "s_register_operand" "r")
8497                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8498    (set (match_operand:SI 0 "s_register_operand" "=r")
8499         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8500                                                  (match_dup 4)])))]
8501   "TARGET_ARM
8502    && !BYTES_BIG_ENDIAN
8503    && !TARGET_MMU_TRAPS
8504    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8505    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8506    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8507   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8508   [(set_attr "type" "load")
8509    (set_attr "predicable" "yes")]
8512 ; It can also support extended post-inc expressions, but combine doesn't
8513 ; try these....
8514 ; It doesn't seem worth adding peepholes for anything but the most common
8515 ; cases since, unlike combine, the increment must immediately follow the load
8516 ; for this pattern to match.
8517 ; We must watch to see that the source/destination register isn't also the
8518 ; same as the base address register, and that if the index is a register,
8519 ; that it is not the same as the base address register.  In such cases the
8520 ; instruction that we would generate would have UNPREDICTABLE behaviour so 
8521 ; we cannot use it.
8523 (define_peephole
8524   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8525         (match_operand:QI 2 "s_register_operand" "r"))
8526    (set (match_dup 0)
8527         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8528   "TARGET_ARM
8529    && (REGNO (operands[2]) != REGNO (operands[0]))
8530    && (GET_CODE (operands[1]) != REG
8531        || (REGNO (operands[1]) != REGNO (operands[0])))"
8532   "str%?b\\t%2, [%0], %1"
8535 (define_peephole
8536   [(set (match_operand:QI 0 "s_register_operand" "=r")
8537         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8538    (set (match_dup 1)
8539         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8540   "TARGET_ARM
8541    && REGNO (operands[0]) != REGNO(operands[1])
8542    && (GET_CODE (operands[2]) != REG
8543        || REGNO(operands[0]) != REGNO (operands[2]))"
8544   "ldr%?b\\t%0, [%1], %2"
8547 (define_peephole
8548   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8549         (match_operand:SI 2 "s_register_operand" "r"))
8550    (set (match_dup 0)
8551         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8552   "TARGET_ARM
8553    && (REGNO (operands[2]) != REGNO (operands[0]))
8554    && (GET_CODE (operands[1]) != REG
8555        || (REGNO (operands[1]) != REGNO (operands[0])))"
8556   "str%?\\t%2, [%0], %1"
8559 (define_peephole
8560   [(set (match_operand:HI 0 "s_register_operand" "=r")
8561         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8562    (set (match_dup 1)
8563         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8564   "TARGET_ARM
8565    && !BYTES_BIG_ENDIAN
8566    && !TARGET_MMU_TRAPS
8567    && REGNO (operands[0]) != REGNO(operands[1])
8568    && (GET_CODE (operands[2]) != REG
8569        || REGNO(operands[0]) != REGNO (operands[2]))"
8570   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8573 (define_peephole
8574   [(set (match_operand:SI 0 "s_register_operand" "=r")
8575         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8576    (set (match_dup 1)
8577         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8578   "TARGET_ARM
8579    && REGNO (operands[0]) != REGNO(operands[1])
8580    && (GET_CODE (operands[2]) != REG
8581        || REGNO(operands[0]) != REGNO (operands[2]))"
8582   "ldr%?\\t%0, [%1], %2"
8585 (define_peephole
8586   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8587                          (match_operand:SI 1 "index_operand" "rJ")))
8588         (match_operand:QI 2 "s_register_operand" "r"))
8589    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8590   "TARGET_ARM
8591    && (REGNO (operands[2]) != REGNO (operands[0]))
8592    && (GET_CODE (operands[1]) != REG
8593        || (REGNO (operands[1]) != REGNO (operands[0])))"
8594   "str%?b\\t%2, [%0, %1]!"
8597 (define_peephole
8598   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8599                           [(match_operand:SI 0 "s_register_operand" "r")
8600                            (match_operand:SI 1 "const_int_operand" "n")])
8601                          (match_operand:SI 2 "s_register_operand" "+r")))
8602         (match_operand:QI 3 "s_register_operand" "r"))
8603    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8604                                (match_dup 2)))]
8605   "TARGET_ARM
8606    && (REGNO (operands[3]) != REGNO (operands[2]))
8607    && (REGNO (operands[0]) != REGNO (operands[2]))"
8608   "str%?b\\t%3, [%2, %0%S4]!"
8611 ; This pattern is never tried by combine, so do it as a peephole
8613 (define_peephole2
8614   [(set (match_operand:SI 0 "s_register_operand" "")
8615         (match_operand:SI 1 "s_register_operand" ""))
8616    (set (reg:CC CC_REGNUM)
8617         (compare:CC (match_dup 1) (const_int 0)))]
8618   "TARGET_ARM
8619   "
8620   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8621               (set (match_dup 0) (match_dup 1))])]
8622   ""
8625 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8626 ; reversed, check that the memory references aren't volatile.
8628 (define_peephole
8629   [(set (match_operand:SI 0 "s_register_operand" "=r")
8630         (match_operand:SI 4 "memory_operand" "m"))
8631    (set (match_operand:SI 1 "s_register_operand" "=r")
8632         (match_operand:SI 5 "memory_operand" "m"))
8633    (set (match_operand:SI 2 "s_register_operand" "=r")
8634         (match_operand:SI 6 "memory_operand" "m"))
8635    (set (match_operand:SI 3 "s_register_operand" "=r")
8636         (match_operand:SI 7 "memory_operand" "m"))]
8637   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8638   "*
8639   return emit_ldm_seq (operands, 4);
8640   "
8643 (define_peephole
8644   [(set (match_operand:SI 0 "s_register_operand" "=r")
8645         (match_operand:SI 3 "memory_operand" "m"))
8646    (set (match_operand:SI 1 "s_register_operand" "=r")
8647         (match_operand:SI 4 "memory_operand" "m"))
8648    (set (match_operand:SI 2 "s_register_operand" "=r")
8649         (match_operand:SI 5 "memory_operand" "m"))]
8650   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8651   "*
8652   return emit_ldm_seq (operands, 3);
8653   "
8656 (define_peephole
8657   [(set (match_operand:SI 0 "s_register_operand" "=r")
8658         (match_operand:SI 2 "memory_operand" "m"))
8659    (set (match_operand:SI 1 "s_register_operand" "=r")
8660         (match_operand:SI 3 "memory_operand" "m"))]
8661   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8662   "*
8663   return emit_ldm_seq (operands, 2);
8664   "
8667 (define_peephole
8668   [(set (match_operand:SI 4 "memory_operand" "=m")
8669         (match_operand:SI 0 "s_register_operand" "r"))
8670    (set (match_operand:SI 5 "memory_operand" "=m")
8671         (match_operand:SI 1 "s_register_operand" "r"))
8672    (set (match_operand:SI 6 "memory_operand" "=m")
8673         (match_operand:SI 2 "s_register_operand" "r"))
8674    (set (match_operand:SI 7 "memory_operand" "=m")
8675         (match_operand:SI 3 "s_register_operand" "r"))]
8676   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8677   "*
8678   return emit_stm_seq (operands, 4);
8679   "
8682 (define_peephole
8683   [(set (match_operand:SI 3 "memory_operand" "=m")
8684         (match_operand:SI 0 "s_register_operand" "r"))
8685    (set (match_operand:SI 4 "memory_operand" "=m")
8686         (match_operand:SI 1 "s_register_operand" "r"))
8687    (set (match_operand:SI 5 "memory_operand" "=m")
8688         (match_operand:SI 2 "s_register_operand" "r"))]
8689   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8690   "*
8691   return emit_stm_seq (operands, 3);
8692   "
8695 (define_peephole
8696   [(set (match_operand:SI 2 "memory_operand" "=m")
8697         (match_operand:SI 0 "s_register_operand" "r"))
8698    (set (match_operand:SI 3 "memory_operand" "=m")
8699         (match_operand:SI 1 "s_register_operand" "r"))]
8700   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8701   "*
8702   return emit_stm_seq (operands, 2);
8703   "
8706 (define_split
8707   [(set (match_operand:SI 0 "s_register_operand" "")
8708         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8709                        (const_int 0))
8710                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8711                          [(match_operand:SI 3 "s_register_operand" "")
8712                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
8713    (clobber (match_operand:SI 5 "s_register_operand" ""))]
8714   "TARGET_ARM"
8715   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8716    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8717                               (match_dup 5)))]
8718   ""
8721 ;; This split can be used because CC_Z mode implies that the following
8722 ;; branch will be an equality, or an unsigned inequality, so the sign
8723 ;; extension is not needed.
8725 (define_split
8726   [(set (reg:CC_Z CC_REGNUM)
8727         (compare:CC_Z
8728          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8729                     (const_int 24))
8730          (match_operand 1 "const_int_operand" "")))
8731    (clobber (match_scratch:SI 2 ""))]
8732   "TARGET_ARM
8733    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8734        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8735   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8736    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8737   "
8738   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8739   "
8742 (define_expand "prologue"
8743   [(clobber (const_int 0))]
8744   "TARGET_EITHER"
8745   "if (TARGET_ARM)
8746      arm_expand_prologue ();
8747    else
8748      thumb_expand_prologue ();
8749   DONE;
8750   "
8753 (define_expand "epilogue"
8754   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8755   "TARGET_EITHER"
8756   "
8757   if (TARGET_THUMB)
8758     thumb_expand_epilogue ();
8759   else if (USE_RETURN_INSN (FALSE))
8760     {
8761       emit_jump_insn (gen_return ());
8762       DONE;
8763     }
8764   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8765         gen_rtvec (1,
8766                 gen_rtx_RETURN (VOIDmode)),
8767         VUNSPEC_EPILOGUE));
8768   DONE;
8769   "
8772 (define_insn "sibcall_epilogue"
8773   [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8774   "TARGET_ARM"
8775   "*
8776   output_asm_insn (\"%@ Sibcall epilogue\", operands);
8777   if (USE_RETURN_INSN (FALSE))
8778     return output_return_instruction (NULL, FALSE, FALSE);
8779   return arm_output_epilogue (FALSE);
8780   "
8781 ;; Length is absolute worst case
8782   [(set_attr "length" "44")
8783    (set_attr "type" "block")]
8786 (define_insn "*epilogue_insns"
8787   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8788   "TARGET_EITHER"
8789   "*
8790   if (TARGET_ARM)
8791     return arm_output_epilogue (TRUE);
8792   else /* TARGET_THUMB */
8793     return thumb_unexpanded_epilogue ();
8794   "
8795   ; Length is absolute worst case
8796   [(set_attr "length" "44")
8797    (set_attr "type" "block")]
8800 (define_expand "eh_epilogue"
8801   [(use (match_operand:SI 0 "register_operand" "r"))
8802    (use (match_operand:SI 1 "register_operand" "r"))
8803    (use (match_operand:SI 2 "register_operand" "r"))]
8804   "TARGET_EITHER"
8805   "
8806   {
8807     cfun->machine->eh_epilogue_sp_ofs = operands[1];
8808     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8809       {
8810         rtx ra = gen_rtx_REG (Pmode, 2);
8812         emit_move_insn (ra, operands[2]);
8813         operands[2] = ra;
8814       }
8815     /* This is a hack -- we may have crystalized the function type too
8816        early.  */
8817     cfun->machine->func_type = 0;
8818   }"
8821 ;; This split is only used during output to reduce the number of patterns
8822 ;; that need assembler instructions adding to them.  We allowed the setting
8823 ;; of the conditions to be implicit during rtl generation so that
8824 ;; the conditional compare patterns would work.  However this conflicts to
8825 ;; some extent with the conditional data operations, so we have to split them
8826 ;; up again here.
8828 (define_split
8829   [(set (match_operand:SI 0 "s_register_operand" "")
8830         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8831                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8832                          (match_dup 0)
8833                          (match_operand 4 "" "")))
8834    (clobber (reg:CC CC_REGNUM))]
8835   "TARGET_ARM && reload_completed"
8836   [(set (match_dup 5) (match_dup 6))
8837    (cond_exec (match_dup 7)
8838               (set (match_dup 0) (match_dup 4)))]
8839   "
8840   {
8841     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8842                                              operands[2], operands[3]);
8843     enum rtx_code rc = GET_CODE (operands[1]);
8845     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8846     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8847     if (mode == CCFPmode || mode == CCFPEmode)
8848       rc = reverse_condition_maybe_unordered (rc);
8849     else
8850       rc = reverse_condition (rc);
8852     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8853   }"
8856 (define_split
8857   [(set (match_operand:SI 0 "s_register_operand" "")
8858         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8859                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8860                          (match_operand 4 "" "")
8861                          (match_dup 0)))
8862    (clobber (reg:CC CC_REGNUM))]
8863   "TARGET_ARM && reload_completed"
8864   [(set (match_dup 5) (match_dup 6))
8865    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8866               (set (match_dup 0) (match_dup 4)))]
8867   "
8868   {
8869     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8870                                              operands[2], operands[3]);
8872     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8873     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8874   }"
8877 (define_split
8878   [(set (match_operand:SI 0 "s_register_operand" "")
8879         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8880                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8881                          (match_operand 4 "" "")
8882                          (match_operand 5 "" "")))
8883    (clobber (reg:CC CC_REGNUM))]
8884   "TARGET_ARM && reload_completed"
8885   [(set (match_dup 6) (match_dup 7))
8886    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8887               (set (match_dup 0) (match_dup 4)))
8888    (cond_exec (match_dup 8)
8889               (set (match_dup 0) (match_dup 5)))]
8890   "
8891   {
8892     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8893                                              operands[2], operands[3]);
8894     enum rtx_code rc = GET_CODE (operands[1]);
8896     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8897     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8898     if (mode == CCFPmode || mode == CCFPEmode)
8899       rc = reverse_condition_maybe_unordered (rc);
8900     else
8901       rc = reverse_condition (rc);
8903     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8904   }"
8907 (define_split
8908   [(set (match_operand:SI 0 "s_register_operand" "")
8909         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8910                           [(match_operand:SI 2 "s_register_operand" "")
8911                            (match_operand:SI 3 "arm_add_operand" "")])
8912                          (match_operand:SI 4 "arm_rhs_operand" "")
8913                          (not:SI
8914                           (match_operand:SI 5 "s_register_operand" ""))))
8915    (clobber (reg:CC CC_REGNUM))]
8916   "TARGET_ARM && reload_completed"
8917   [(set (match_dup 6) (match_dup 7))
8918    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8919               (set (match_dup 0) (match_dup 4)))
8920    (cond_exec (match_dup 8)
8921               (set (match_dup 0) (not:SI (match_dup 5))))]
8922   "
8923   {
8924     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8925                                              operands[2], operands[3]);
8926     enum rtx_code rc = GET_CODE (operands[1]);
8928     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8929     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8930     if (mode == CCFPmode || mode == CCFPEmode)
8931       rc = reverse_condition_maybe_unordered (rc);
8932     else
8933       rc = reverse_condition (rc);
8935     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8936   }"
8939 (define_insn "*cond_move_not"
8940   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8941         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8942                           [(match_operand 3 "cc_register" "") (const_int 0)])
8943                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8944                          (not:SI
8945                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
8946   "TARGET_ARM"
8947   "@
8948    mvn%D4\\t%0, %2
8949    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8950   [(set_attr "conds" "use")
8951    (set_attr "length" "4,8")]
8954 ;; The next two patterns occur when an AND operation is followed by a
8955 ;; scc insn sequence 
8957 (define_insn "*sign_extract_onebit"
8958   [(set (match_operand:SI 0 "s_register_operand" "=r")
8959         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8960                          (const_int 1)
8961                          (match_operand:SI 2 "const_int_operand" "n")))]
8962   "TARGET_ARM"
8963   "*
8964     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8965     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8966     return \"mvnne\\t%0, #0\";
8967   "
8968   [(set_attr "conds" "clob")
8969    (set_attr "length" "8")]
8972 (define_insn "*not_signextract_onebit"
8973   [(set (match_operand:SI 0 "s_register_operand" "=r")
8974         (not:SI
8975          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8976                           (const_int 1)
8977                           (match_operand:SI 2 "const_int_operand" "n"))))]
8978   "TARGET_ARM"
8979   "*
8980     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8981     output_asm_insn (\"tst\\t%1, %2\", operands);
8982     output_asm_insn (\"mvneq\\t%0, #0\", operands);
8983     return \"movne\\t%0, #0\";
8984   "
8985   [(set_attr "conds" "clob")
8986    (set_attr "length" "12")]
8989 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8990 ;; expressions.  For simplicity, the first register is also in the unspec
8991 ;; part.
8992 (define_insn "*push_multi"
8993   [(match_parallel 2 "multi_register_push"
8994     [(set (match_operand:BLK 0 "memory_operand" "=m")
8995           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8996                       UNSPEC_PUSH_MULT))])]
8997   "TARGET_ARM"
8998   "*
8999   {
9000     int num_saves = XVECLEN (operands[2], 0);
9001      
9002     /* For the StrongARM at least it is faster to
9003        use STR to store only a single register.  */
9004     if (num_saves == 1)
9005       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9006     else
9007       {
9008         int i;
9009         char pattern[100];
9011         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9013         for (i = 1; i < num_saves; i++)
9014           {
9015             strcat (pattern, \", %|\");
9016             strcat (pattern,
9017                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9018           }
9020         strcat (pattern, \"}\");
9021         output_asm_insn (pattern, operands);
9022       }
9024     return \"\";
9025   }"
9026   [(set_attr "type" "store4")]
9029 ;; Similarly for the floating point registers
9030 (define_insn "*push_fp_multi"
9031   [(match_parallel 2 "multi_register_push"
9032     [(set (match_operand:BLK 0 "memory_operand" "=m")
9033           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9034                       UNSPEC_PUSH_MULT))])]
9035   "TARGET_ARM"
9036   "*
9037   {
9038     char pattern[100];
9040     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9041     output_asm_insn (pattern, operands);
9042     return \"\";
9043   }"
9044   [(set_attr "type" "f_store")]
9047 ;; Special patterns for dealing with the constant pool
9049 (define_insn "align_4"
9050   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9051   "TARGET_EITHER"
9052   "*
9053   assemble_align (32);
9054   return \"\";
9055   "
9058 (define_insn "consttable_end"
9059   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9060   "TARGET_EITHER"
9061   "*
9062   making_const_table = FALSE;
9063   return \"\";
9064   "
9067 (define_insn "consttable_1"
9068   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9069   "TARGET_THUMB"
9070   "*
9071   making_const_table = TRUE;
9072   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9073   assemble_zeros (3);
9074   return \"\";
9075   "
9076   [(set_attr "length" "4")]
9079 (define_insn "consttable_2"
9080   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9081   "TARGET_THUMB"
9082   "*
9083   making_const_table = TRUE;
9084   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9085   assemble_zeros (2);
9086   return \"\";
9087   "
9088   [(set_attr "length" "4")]
9091 (define_insn "consttable_4"
9092   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9093   "TARGET_EITHER"
9094   "*
9095   {
9096     making_const_table = TRUE;
9097     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9098       {
9099       case MODE_FLOAT:
9100       {
9101         union real_extract u;
9102         memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9103         assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
9104         break;
9105       }
9106       default:
9107         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9108         break;
9109       }
9110     return \"\";
9111   }"
9112   [(set_attr "length" "4")]
9115 (define_insn "consttable_8"
9116   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9117   "TARGET_EITHER"
9118   "*
9119   {
9120     making_const_table = TRUE;
9121     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9122       {
9123        case MODE_FLOAT:
9124         {
9125           union real_extract u;
9126           memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9127           assemble_real (u.d, GET_MODE (operands[0]), BITS_PER_WORD);
9128           break;
9129         }
9130       default:
9131         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9132         break;
9133       }
9134     return \"\";
9135   }"
9136   [(set_attr "length" "8")]
9139 ;; Miscellaneous Thumb patterns
9141 (define_insn "tablejump"
9142   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9143    (use (label_ref (match_operand 1 "" "")))]
9144   "TARGET_THUMB"
9145   "mov  pc, %0"
9146   [(set_attr "length" "2")]
9149 ;; V5 Instructions,
9151 (define_insn "clz"
9152   [(set (match_operand:SI             0 "s_register_operand" "=r")
9153         (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9154                    UNSPEC_CLZ))]
9155   "TARGET_ARM && arm_arch5"
9156   "clz\\t%0, %1")
9158 (define_expand "ffssi2"
9159   [(set (match_operand:SI 0 "s_register_operand" "")
9160         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9161   "TARGET_ARM && arm_arch5"
9162   "
9163   {
9164     rtx t1, t2, t3;
9166     t1 = gen_reg_rtx (SImode);
9167     t2 = gen_reg_rtx (SImode);
9168     t3 = gen_reg_rtx (SImode);
9170     emit_insn (gen_negsi2 (t1, operands[1]));
9171     emit_insn (gen_andsi3 (t2, operands[1], t1));
9172     emit_insn (gen_clz (t3, t2));
9173     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9174     DONE;
9175   }"
9178 ;; V5E instructions.
9180 (define_insn "prefetch"
9181   [(prefetch (match_operand:SI 0 "address_operand" "p")
9182              (match_operand:SI 1 "" "")
9183              (match_operand:SI 2 "" ""))]
9184   "TARGET_ARM && arm_arch5e"
9185   "pld\\t%a0")
9187 ;; General predication pattern
9189 (define_cond_exec
9190   [(match_operator 0 "arm_comparison_operator"
9191     [(match_operand 1 "cc_register" "")
9192      (const_int 0)])]
9193   "TARGET_ARM"
9194   ""
9197 (define_insn "prologue_use"
9198   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9199   ""
9200   "%@ %0 needed for prologue"