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