* arm.md (arm_buneq, arm_bltgt): put '\' before ';' in output
[official-gcc.git] / gcc / config / arm / arm.md
blob091da69c7eaf35c948ce16325568b1f37b817cf7
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GNU CC.
10 ;; GNU CC is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
15 ;; GNU CC is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU CC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
27 ;; There are patterns in this file to support XFmode arithmetic.
28 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
29 ;; (See arm.h)
31 ;;---------------------------------------------------------------------------
32 ;; Constants
34 ;; Register numbers
35 (define_constants
36   [(IP_REGNUM       12)         ; Scratch register
37    (SP_REGNUM       13)         ; Stack pointer
38    (LR_REGNUM       14)         ; Return address register
39    (PC_REGNUM       15)         ; Program counter
40    (CC_REGNUM       24)         ; Condition code pseudo register
41    (LAST_ARM_REGNUM 15)
42   ]
45 ;; UNSPEC Usage:
46 ;; Note: sin and cos are no-longer used.
48 (define_constants
49   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
50                         ;   operand 0 is the result,
51                         ;   operand 1 the parameter.
52    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
53                         ;   operand 0 is the result,
54                         ;   operand 1 the parameter.
55    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
56                         ;   operand 0 is the first register,
57                         ;   subsequent registers are in parallel (use ...)
58                         ;   expressions.
59    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
60                         ;   usage, that is, we will add the pic_register
61                         ;   value to it before trying to dereference it.
62    (UNSPEC_PRLG_STK  4) ; A special barrier that prevents frame accesses 
63                         ;   being scheduled before the stack adjustment insn.
64    (UNSPEC_CLZ       5) ; `clz' instruction, count leading zeros (SImode):
65                         ;   operand 0 is the result,
66                         ;   operand 1 is the parameter.
67    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
68                         ; this unspec is used to prevent the deletion of
69                         ; instructions setting registers for EH handling
70                         ; and stack frame generation.  Operand 0 is the
71                         ; register to "use".
72   ]
75 ;; UNSPEC_VOLATILE Usage:
77 (define_constants
78   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
79                         ;   insn in the code.
80    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
81                         ;   instruction epilogue sequence that isn't expanded
82                         ;   into normal RTL.  Used for both normal and sibcall
83                         ;   epilogues.
84    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
85                         ;   for inlined constants.
86    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
87                         ;   table.
88    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
89                         ;   an 8-bit object.
90    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
91                         ;   a 16-bit object.
92    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
93                         ;   a 32-bit object.
94    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
95                         ;   a 64-bit object.
96   ]
99 ;;---------------------------------------------------------------------------
100 ;; Attributes
102 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
103 ; generating ARM code.  This is used to control the length of some insn
104 ; patterns that share the same RTL in both ARM and Thumb code.
105 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
107 ; PROG_MODE attribute is used to determine whether condition codes are
108 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
109 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
110 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
112 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
113 ; scheduling decisions for the load unit and the multiplier.
114 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
116 ;; Operand number of an input operand that is shifted.  Zero if the
117 ;; given instruction does not shift one of its input operands.
118 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
119 (define_attr "shift" "" (const_int 0))
121 ; Floating Point Unit.  If we only have floating point emulation, then there
122 ; is no point in scheduling the floating point insns.  (Well, for best
123 ; performance we should try and group them together).
124 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
126 ; LENGTH of an instruction (in bytes)
127 (define_attr "length" "" (const_int 4))
129 ; POOL_RANGE is how far away from a constant pool entry that this insn
130 ; can be placed.  If the distance is zero, then this insn will never
131 ; reference the pool.
132 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
133 ; before its address.
134 (define_attr "pool_range" "" (const_int 0))
135 (define_attr "neg_pool_range" "" (const_int 0))
137 ; An assembler sequence may clobber the condition codes without us knowing.
138 ; If such an insn references the pool, then we have no way of knowing how,
139 ; so use the most conservative value for pool_range.
140 (define_asm_attributes
141  [(set_attr "conds" "clob")
142   (set_attr "length" "4")
143   (set_attr "pool_range" "250")])
145 ; TYPE attribute is used to detect floating point instructions which, if
146 ; running on a co-processor can run in parallel with other, basic instructions
147 ; If write-buffer scheduling is enabled then it can also be used in the
148 ; scheduling of writes.
150 ; Classification of each insn
151 ; normal        any data instruction that doesn't hit memory or fp regs
152 ; mult          a multiply instruction
153 ; block         blockage insn, this blocks all functional units
154 ; float         a floating point arithmetic operation (subject to expansion)
155 ; fdivx         XFmode floating point division
156 ; fdivd         DFmode floating point division
157 ; fdivs         SFmode floating point division
158 ; fmul          Floating point multiply
159 ; ffmul         Fast floating point multiply
160 ; farith        Floating point arithmetic (4 cycle)
161 ; ffarith       Fast floating point arithmetic (2 cycle)
162 ; float_em      a floating point arithmetic operation that is normally emulated
163 ;               even on a machine with an fpa.
164 ; f_load        a floating point load from memory
165 ; f_store       a floating point store to memory
166 ; f_mem_r       a transfer of a floating point register to a real reg via mem
167 ; r_mem_f       the reverse of f_mem_r
168 ; f_2_r         fast transfer float to arm (no memory needed)
169 ; r_2_f         fast transfer arm to float
170 ; call          a subroutine call
171 ; load          any load from memory
172 ; store1        store 1 word to memory from arm registers
173 ; store2        store 2 words
174 ; store3        store 3 words
175 ; store4        store 4 words
177 (define_attr "type"
178         "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" 
179         (const_string "normal"))
181 ; Load scheduling, set from the arm_ld_sched variable
182 ; initialised by arm_override_options() 
183 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
185 ; condition codes: this one is used by final_prescan_insn to speed up
186 ; conditionalizing instructions.  It saves having to scan the rtl to see if
187 ; it uses or alters the condition codes.
189 ; USE means that the condition codes are used by the insn in the process of
190 ;   outputting code, this means (at present) that we can't use the insn in
191 ;   inlined branches
193 ; SET means that the purpose of the insn is to set the condition codes in a
194 ;   well defined manner.
196 ; CLOB means that the condition codes are altered in an undefined manner, if
197 ;   they are altered at all
199 ; JUMP_CLOB is used when the condition cannot be represented by a single
200 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
202 ; NOCOND means that the condition codes are neither altered nor affect the
203 ;   output of this insn
205 (define_attr "conds" "use,set,clob,jump_clob,nocond"
206         (if_then_else (eq_attr "type" "call")
207          (if_then_else (eq_attr "prog_mode" "prog32")
208           (const_string "clob") (const_string "nocond"))
209          (const_string "nocond")))
211 ; Predicable means that the insn can be conditionally executed based on
212 ; an automatically added predicate (additional patterns are generated by 
213 ; gen...).  We default to 'no' because no Thumb patterns match this rule
214 ; and not all ARM patterns do.
215 (define_attr "predicable" "no,yes" (const_string "no"))
217 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
218 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
219 ; suffer blockages enough to warrent modelling this (and it can adversely
220 ; affect the schedule).
221 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
223 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
224 ; to stall the processor.  Used with model_wbuf above.
225 (define_attr "write_conflict" "no,yes"
226   (if_then_else (eq_attr "type"
227                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
228                 (const_string "yes")
229                 (const_string "no")))
231 ; Classify the insns into those that take one cycle and those that take more
232 ; than one on the main cpu execution unit.
233 (define_attr "core_cycles" "single,multi"
234   (if_then_else (eq_attr "type"
235                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
236                 (const_string "single")
237                 (const_string "multi")))
239 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
240 ;; distant label.  Only applicable to Thumb code.
241 (define_attr "far_jump" "yes,no" (const_string "no"))
243 ;; (define_function_unit {name} {num-units} {n-users} {test}
244 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
246 ;;--------------------------------------------------------------------
247 ;; Floating point unit (FPA)
248 ;;--------------------------------------------------------------------
249 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
250                                      (eq_attr "type" "fdivx")) 71 69)
252 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
253                                      (eq_attr "type" "fdivd")) 59 57)
255 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
256                                      (eq_attr "type" "fdivs")) 31 29)
258 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
259                                      (eq_attr "type" "fmul")) 9 7)
261 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
262                                      (eq_attr "type" "ffmul")) 6 4)
264 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
265                                      (eq_attr "type" "farith")) 4 2)
267 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
268                                      (eq_attr "type" "ffarith")) 2 2)
270 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
271                                      (eq_attr "type" "r_2_f")) 5 3)
273 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
274                                      (eq_attr "type" "f_2_r")) 1 2)
276 ; The fpa10 doesn't really have a memory read unit, but it can start to
277 ; speculatively execute the instruction in the pipeline, provided the data
278 ; is already loaded, so pretend reads have a delay of 2 (and that the
279 ; pipeline is infinite).
281 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
282                                          (eq_attr "type" "f_load")) 3 1)
284 ;;--------------------------------------------------------------------
285 ;; Write buffer
286 ;;--------------------------------------------------------------------
287 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
289 ; The write buffer on some of the arm6 processors is hard to model exactly.
290 ; There is room in the buffer for up to two addresses and up to eight words
291 ; of memory, but the two needn't be split evenly.  When writing the two
292 ; addresses are fully pipelined.  However, a read from memory that is not
293 ; currently in the cache will block until the writes have completed.
294 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
295 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
296 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
297 ; cycle to add as well.
299 (define_function_unit "write_buf" 1 2
300   (and (eq_attr "model_wbuf" "yes")
301        (eq_attr "type" "store1,r_mem_f")) 5 3)
302 (define_function_unit "write_buf" 1 2 
303   (and (eq_attr "model_wbuf" "yes")
304        (eq_attr "type" "store2")) 7 4)
305 (define_function_unit "write_buf" 1 2
306   (and (eq_attr "model_wbuf" "yes")
307        (eq_attr "type" "store3")) 9 5)
308 (define_function_unit "write_buf" 1 2
309   (and (eq_attr "model_wbuf" "yes")
310        (eq_attr "type" "store4")) 11 6)
312 ;;--------------------------------------------------------------------
313 ;; Write blockage unit
314 ;;--------------------------------------------------------------------
315 ; The write_blockage unit models (partially), the fact that reads will stall
316 ; until the write buffer empties.
317 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
318 ; so we don't model them here
319 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
320                                                 (eq_attr "type" "store1")) 5 5
321         [(eq_attr "write_conflict" "yes")])
322 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
323                                                 (eq_attr "type" "store2")) 7 7
324         [(eq_attr "write_conflict" "yes")])
325 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
326                                                 (eq_attr "type" "store3")) 9 9
327         [(eq_attr "write_conflict" "yes")])
328 (define_function_unit "write_blockage" 1 0
329         (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
330         [(eq_attr "write_conflict" "yes")])
331 (define_function_unit "write_blockage" 1 0
332         (and (eq_attr "model_wbuf" "yes")
333              (eq_attr "write_conflict" "yes")) 1 1)
335 ;;--------------------------------------------------------------------
336 ;; Core unit
337 ;;--------------------------------------------------------------------
338 ; Everything must spend at least one cycle in the core unit
339 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
341 (define_function_unit "core" 1 0
342   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
344 (define_function_unit "core" 1 0
345   (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
347 ;; We do not need to conditionalize the define_function_unit immediately
348 ;; above.  This one will be ignored for anything other than xscale
349 ;; compiles and for xscale compiles it provides a larger delay
350 ;; and the scheduler will DTRT.
351 ;; FIXME: this test needs to be revamped to not depend on this feature 
352 ;; of the scheduler.
354 (define_function_unit "core" 1 0
355   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
356        (eq_attr "is_xscale" "yes"))
357    3 1)
359 (define_function_unit "core" 1 0
360   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
362 (define_function_unit "core" 1 0
363   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
365 (define_function_unit "core" 1 0
366   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
368 (define_function_unit "core" 1 0
369   (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
371 (define_function_unit "core" 1 0
372   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
374 (define_function_unit "core" 1 0
375   (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
377 (define_function_unit "core" 1 0
378   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
379        (eq_attr "type" "mult")) 4 4)
381 (define_function_unit "core" 1 0
382   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
383        (eq_attr "type" "mult")) 3 2)
385 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
387 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
389 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
391 (define_function_unit "core" 1 0
392   (and (eq_attr "core_cycles" "multi")
393        (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
395 ;;---------------------------------------------------------------------------
396 ;; Insn patterns
398 ;; Addition insns.
400 ;; Note: For DImode insns, there is normally no reason why operands should
401 ;; not be in the same register, what we don't want is for something being
402 ;; written to partially overlap something that is an input.
404 (define_expand "adddi3"
405  [(parallel
406    [(set (match_operand:DI           0 "s_register_operand" "")
407           (plus:DI (match_operand:DI 1 "s_register_operand" "")
408                    (match_operand:DI 2 "s_register_operand" "")))
409     (clobber (reg:CC CC_REGNUM))])]
410   "TARGET_EITHER"
411   "
412   if (TARGET_THUMB)
413     {
414       if (GET_CODE (operands[1]) != REG)
415         operands[1] = force_reg (SImode, operands[1]);
416       if (GET_CODE (operands[2]) != REG)
417         operands[2] = force_reg (SImode, operands[2]);
418      }
419   "
422 (define_insn "*thumb_adddi3"
423   [(set (match_operand:DI          0 "register_operand" "=l")
424         (plus:DI (match_operand:DI 1 "register_operand" "%0")
425                  (match_operand:DI 2 "register_operand" "l")))
426    (clobber (reg:CC CC_REGNUM))
427   ]
428   "TARGET_THUMB"
429   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
430   [(set_attr "length" "4")]
433 (define_insn_and_split "*arm_adddi3"
434   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
435         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
436                  (match_operand:DI 2 "s_register_operand" "r,  0")))
437    (clobber (reg:CC CC_REGNUM))]
438   "TARGET_ARM"
439   "#"
440   "TARGET_ARM && reload_completed"
441   [(parallel [(set (reg:CC_C CC_REGNUM)
442                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
443                                  (match_dup 1)))
444               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
445    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
446                                (plus:SI (match_dup 4) (match_dup 5))))]
447   "
448   {
449     operands[3] = gen_highpart (SImode, operands[0]);
450     operands[0] = gen_lowpart (SImode, operands[0]);
451     operands[4] = gen_highpart (SImode, operands[1]);
452     operands[1] = gen_lowpart (SImode, operands[1]);
453     operands[5] = gen_highpart (SImode, operands[2]);
454     operands[2] = gen_lowpart (SImode, operands[2]);
455   }"
456   [(set_attr "conds" "clob")
457    (set_attr "length" "8")]
460 (define_insn_and_split "*adddi_sesidi_di"
461   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
462         (plus:DI (sign_extend:DI
463                   (match_operand:SI 2 "s_register_operand" "r,r"))
464                  (match_operand:DI 1 "s_register_operand" "r,0")))
465    (clobber (reg:CC CC_REGNUM))]
466   "TARGET_ARM"
467   "#"
468   "TARGET_ARM && reload_completed"
469   [(parallel [(set (reg:CC_C CC_REGNUM)
470                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
471                                  (match_dup 1)))
472               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
473    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
474                                (plus:SI (ashiftrt:SI (match_dup 2)
475                                                      (const_int 31))
476                                         (match_dup 4))))]
477   "
478   {
479     operands[3] = gen_highpart (SImode, operands[0]);
480     operands[0] = gen_lowpart (SImode, operands[0]);
481     operands[4] = gen_highpart (SImode, operands[1]);
482     operands[1] = gen_lowpart (SImode, operands[1]);
483     operands[2] = gen_lowpart (SImode, operands[2]);
484   }"
485   [(set_attr "conds" "clob")
486    (set_attr "length" "8")]
489 (define_insn_and_split "*adddi_zesidi_di"
490   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
491         (plus:DI (zero_extend:DI
492                   (match_operand:SI 2 "s_register_operand" "r,r"))
493                  (match_operand:DI 1 "s_register_operand" "r,0")))
494    (clobber (reg:CC CC_REGNUM))]
495   "TARGET_ARM"
496   "#"
497   "TARGET_ARM && reload_completed"
498   [(parallel [(set (reg:CC_C CC_REGNUM)
499                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
500                                  (match_dup 1)))
501               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
502    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
503                                (plus:SI (match_dup 4) (const_int 0))))]
504   "
505   {
506     operands[3] = gen_highpart (SImode, operands[0]);
507     operands[0] = gen_lowpart (SImode, operands[0]);
508     operands[4] = gen_highpart (SImode, operands[1]);
509     operands[1] = gen_lowpart (SImode, operands[1]);
510     operands[2] = gen_lowpart (SImode, operands[2]);
511   }"
512   [(set_attr "conds" "clob")
513    (set_attr "length" "8")]
516 (define_expand "addsi3"
517   [(set (match_operand:SI          0 "s_register_operand" "")
518         (plus:SI (match_operand:SI 1 "s_register_operand" "")
519                  (match_operand:SI 2 "reg_or_int_operand" "")))]
520   "TARGET_EITHER"
521   "
522   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
523     {
524       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
525                           operands[1],
526                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
527       DONE;
528     }
529   "
532 ; If there is a scratch available, this will be faster than synthesising the
533 ; addition.
534 (define_peephole2
535   [(match_scratch:SI 3 "r")
536    (set (match_operand:SI          0 "s_register_operand" "")
537         (plus:SI (match_operand:SI 1 "s_register_operand" "")
538                  (match_operand:SI 2 "const_int_operand"  "")))]
539   "TARGET_ARM &&
540    !(const_ok_for_arm (INTVAL (operands[2]))
541      || const_ok_for_arm (-INTVAL (operands[2])))
542     && const_ok_for_arm (~INTVAL (operands[2]))"
543   [(set (match_dup 3) (match_dup 2))
544    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
545   ""
548 (define_insn_and_split "*arm_addsi3"
549   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
550         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
551                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
552   "TARGET_ARM"
553   "@
554    add%?\\t%0, %1, %2
555    sub%?\\t%0, %1, #%n2
556    #"
557   "TARGET_ARM &&
558    GET_CODE (operands[2]) == CONST_INT
559    && !(const_ok_for_arm (INTVAL (operands[2]))
560         || const_ok_for_arm (-INTVAL (operands[2])))"
561   [(clobber (const_int 0))]
562   "
563   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
564                       operands[1], 0);
565   DONE;
566   "
567   [(set_attr "length" "4,4,16")
568    (set_attr "predicable" "yes")]
571 ;; Register group 'k' is a single register group containing only the stack
572 ;; register.  Trying to reload it will always fail catastrophically,
573 ;; so never allow those alternatives to match if reloading is needed.
575 (define_insn "*thumb_addsi3"
576   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
577         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
578                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
579   "TARGET_THUMB"
580   "*
581    static const char * const asms[] = 
582    {
583      \"add\\t%0, %0, %2\",
584      \"sub\\t%0, %0, #%n2\",
585      \"add\\t%0, %1, %2\",
586      \"add\\t%0, %0, %2\",
587      \"add\\t%0, %0, %2\",
588      \"add\\t%0, %1, %2\",
589      \"add\\t%0, %1, %2\"
590    };
591    if ((which_alternative == 2 || which_alternative == 6)
592        && GET_CODE (operands[2]) == CONST_INT
593        && INTVAL (operands[2]) < 0)
594      return \"sub\\t%0, %1, #%n2\";
595    return asms[which_alternative];
596   "
597   [(set_attr "length" "2")]
600 ;; Reloading and elimination of the frame pointer can
601 ;; sometimes cause this optimization to be missed.
602 (define_peephole2
603   [(set (match_operand:SI 0 "register_operand" "")
604         (match_operand:SI 1 "const_int_operand" ""))
605    (set (match_dup 0)
606         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
607   "TARGET_THUMB
608    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
609    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
610    && (INTVAL (operands[1]) & 3) == 0"
611   [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
612   ""
615 (define_insn "*addsi3_compare0"
616   [(set (reg:CC_NOOV CC_REGNUM)
617         (compare:CC_NOOV
618          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
619                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
620          (const_int 0)))
621    (set (match_operand:SI 0 "s_register_operand" "=r,r")
622         (plus:SI (match_dup 1) (match_dup 2)))]
623   "TARGET_ARM"
624   "@
625    add%?s\\t%0, %1, %2
626    sub%?s\\t%0, %1, #%n2"
627   [(set_attr "conds" "set")]
630 (define_insn "*addsi3_compare0_scratch"
631   [(set (reg:CC_NOOV CC_REGNUM)
632         (compare:CC_NOOV
633          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
634                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
635          (const_int 0)))]
636   "TARGET_ARM"
637   "@
638    cmn%?\\t%0, %1
639    cmp%?\\t%0, #%n1"
640   [(set_attr "conds" "set")]
643 ;; These patterns are the same ones as the two regular addsi3_compare0
644 ;; patterns, except we write them slightly different - the combiner
645 ;; tends to generate them this way.
646 (define_insn "*addsi3_compare0_for_combiner"
647   [(set (reg:CC CC_REGNUM)
648         (compare:CC
649          (match_operand:SI 1 "s_register_operand" "r,r")
650          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
651    (set (match_operand:SI 0 "s_register_operand" "=r,r")
652         (plus:SI (match_dup 1) (match_dup 2)))]
653   "TARGET_ARM"
654   "@
655    add%?s\\t%0, %1, %2
656    sub%?s\\t%0, %1, #%n2"
657   [(set_attr "conds" "set")]
660 (define_insn "*addsi3_compare0_scratch_for_combiner"
661   [(set (reg:CC CC_REGNUM)
662         (compare:CC
663          (match_operand:SI 0 "s_register_operand" "r,r")
664          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
665   "TARGET_ARM"
666   "@
667    cmn%?\\t%0, %1
668    cmp%?\\t%0, #%n1"
669   [(set_attr "conds" "set")]
672 ;; The next four insns work because they compare the result with one of
673 ;; the operands, and we know that the use of the condition code is
674 ;; either GEU or LTU, so we can use the carry flag from the addition
675 ;; instead of doing the compare a second time.
676 (define_insn "*addsi3_compare_op1"
677   [(set (reg:CC_C CC_REGNUM)
678         (compare:CC_C
679          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
680                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
681          (match_dup 1)))
682    (set (match_operand:SI 0 "s_register_operand" "=r,r")
683         (plus:SI (match_dup 1) (match_dup 2)))]
684   "TARGET_ARM"
685   "@
686    add%?s\\t%0, %1, %2
687    sub%?s\\t%0, %1, #%n2"
688   [(set_attr "conds" "set")]
691 (define_insn "*addsi3_compare_op2"
692   [(set (reg:CC_C CC_REGNUM)
693         (compare:CC_C
694          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
695                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
696          (match_dup 2)))
697    (set (match_operand:SI 0 "s_register_operand" "=r,r")
698         (plus:SI (match_dup 1) (match_dup 2)))]
699   "TARGET_ARM"
700   "@
701    add%?s\\t%0, %1, %2
702    sub%?s\\t%0, %1, #%n2"
703   [(set_attr "conds" "set")]
706 (define_insn "*compare_addsi2_op0"
707   [(set (reg:CC_C CC_REGNUM)
708         (compare:CC_C
709          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
710                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
711          (match_dup 0)))]
712   "TARGET_ARM"
713   "@
714    cmn%?\\t%0, %1
715    cmp%?\\t%0, #%n1"
716   [(set_attr "conds" "set")]
719 (define_insn "*compare_addsi2_op1"
720   [(set (reg:CC_C CC_REGNUM)
721         (compare:CC_C
722          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
723                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
724          (match_dup 1)))]
725   "TARGET_ARM"
726   "@
727    cmn%?\\t%0, %1
728    cmp%?\\t%0, #%n1"
729   [(set_attr "conds" "set")]
732 (define_insn "*addsi3_carryin"
733   [(set (match_operand:SI 0 "s_register_operand" "=r")
734         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
735                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
736                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
737   "TARGET_ARM"
738   "adc%?\\t%0, %1, %2"
739   [(set_attr "conds" "use")]
742 (define_insn "*addsi3_carryin_shift"
743   [(set (match_operand:SI 0 "s_register_operand" "")
744         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
745                  (plus:SI
746                    (match_operator:SI 2 "shift_operator"
747                       [(match_operand:SI 3 "s_register_operand" "")
748                        (match_operand:SI 4 "reg_or_int_operand" "")])
749                     (match_operand:SI 1 "s_register_operand" ""))))]
750   "TARGET_ARM"
751   "adc%?\\t%0, %1, %3%S2"
752   [(set_attr "conds" "use")]
755 (define_insn "*addsi3_carryin_alt1"
756   [(set (match_operand:SI 0 "s_register_operand" "=r")
757         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
758                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
759                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
760   "TARGET_ARM"
761   "adc%?\\t%0, %1, %2"
762   [(set_attr "conds" "use")]
765 (define_insn "*addsi3_carryin_alt2"
766   [(set (match_operand:SI 0 "s_register_operand" "=r")
767         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
768                           (match_operand:SI 1 "s_register_operand" "r"))
769                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
770   "TARGET_ARM"
771   "adc%?\\t%0, %1, %2"
772   [(set_attr "conds" "use")]
775 (define_insn "*addsi3_carryin_alt3"
776   [(set (match_operand:SI 0 "s_register_operand" "=r")
777         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
778                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
779                  (match_operand:SI 1 "s_register_operand" "r")))]
780   "TARGET_ARM"
781   "adc%?\\t%0, %1, %2"
782   [(set_attr "conds" "use")]
785 (define_insn "incscc"
786   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
787         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
788                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
789                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
790   "TARGET_ARM"
791   "@
792   add%d2\\t%0, %1, #1
793   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
794   [(set_attr "conds" "use")
795    (set_attr "length" "4,8")]
798 (define_insn "addsf3"
799   [(set (match_operand:SF          0 "s_register_operand" "=f,f")
800         (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
801                  (match_operand:SF 2 "fpu_add_operand"    "fG,H")))]
802   "TARGET_ARM && TARGET_HARD_FLOAT"
803   "@
804    adf%?s\\t%0, %1, %2
805    suf%?s\\t%0, %1, #%N2"
806   [(set_attr "type" "farith")
807    (set_attr "predicable" "yes")]
810 (define_insn "adddf3"
811   [(set (match_operand:DF          0 "s_register_operand" "=f,f")
812         (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
813                  (match_operand:DF 2 "fpu_add_operand"    "fG,H")))]
814   "TARGET_ARM && TARGET_HARD_FLOAT"
815   "@
816    adf%?d\\t%0, %1, %2
817    suf%?d\\t%0, %1, #%N2"
818   [(set_attr "type" "farith")
819    (set_attr "predicable" "yes")]
822 (define_insn "*adddf_esfdf_df"
823   [(set (match_operand:DF           0 "s_register_operand" "=f,f")
824         (plus:DF (float_extend:DF
825                   (match_operand:SF 1 "s_register_operand"  "f,f"))
826                  (match_operand:DF  2 "fpu_add_operand"    "fG,H")))]
827   "TARGET_ARM && TARGET_HARD_FLOAT"
828   "@
829    adf%?d\\t%0, %1, %2
830    suf%?d\\t%0, %1, #%N2"
831   [(set_attr "type" "farith")
832    (set_attr "predicable" "yes")]
835 (define_insn "*adddf_df_esfdf"
836   [(set (match_operand:DF           0 "s_register_operand" "=f")
837         (plus:DF (match_operand:DF  1 "s_register_operand"  "f")
838                  (float_extend:DF
839                   (match_operand:SF 2 "s_register_operand"  "f"))))]
840   "TARGET_ARM && TARGET_HARD_FLOAT"
841   "adf%?d\\t%0, %1, %2"
842   [(set_attr "type" "farith")
843    (set_attr "predicable" "yes")]
846 (define_insn "*adddf_esfdf_esfdf"
847   [(set (match_operand:DF           0 "s_register_operand" "=f")
848         (plus:DF (float_extend:DF 
849                   (match_operand:SF 1 "s_register_operand" "f"))
850                  (float_extend:DF
851                   (match_operand:SF 2 "s_register_operand" "f"))))]
852   "TARGET_ARM && TARGET_HARD_FLOAT"
853   "adf%?d\\t%0, %1, %2"
854   [(set_attr "type" "farith")
855    (set_attr "predicable" "yes")]
858 (define_insn "addxf3"
859   [(set (match_operand:XF          0 "s_register_operand" "=f,f")
860         (plus:XF (match_operand:XF 1 "s_register_operand"  "f,f")
861                  (match_operand:XF 2 "fpu_add_operand"    "fG,H")))]
862   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
863   "@
864    adf%?e\\t%0, %1, %2
865    suf%?e\\t%0, %1, #%N2"
866   [(set_attr "type" "farith")
867    (set_attr "predicable" "yes")]
870 (define_expand "subdi3"
871  [(parallel
872    [(set (match_operand:DI            0 "s_register_operand" "")
873           (minus:DI (match_operand:DI 1 "s_register_operand" "")
874                     (match_operand:DI 2 "s_register_operand" "")))
875     (clobber (reg:CC CC_REGNUM))])]
876   "TARGET_EITHER"
877   "
878   if (TARGET_THUMB)
879     {
880       if (GET_CODE (operands[1]) != REG)
881         operands[1] = force_reg (SImode, operands[1]);
882       if (GET_CODE (operands[2]) != REG)
883         operands[2] = force_reg (SImode, operands[2]);
884      }  
885   "
888 (define_insn "*arm_subdi3"
889   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
890         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
891                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
892    (clobber (reg:CC CC_REGNUM))]
893   "TARGET_ARM"
894   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
895   [(set_attr "conds" "clob")
896    (set_attr "length" "8")]
899 (define_insn "*thumb_subdi3"
900   [(set (match_operand:DI           0 "register_operand" "=l")
901         (minus:DI (match_operand:DI 1 "register_operand"  "0")
902                   (match_operand:DI 2 "register_operand"  "l")))
903    (clobber (reg:CC CC_REGNUM))]
904   "TARGET_THUMB"
905   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
906   [(set_attr "length" "4")]
909 (define_insn "*subdi_di_zesidi"
910   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
911         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
912                   (zero_extend:DI
913                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
914    (clobber (reg:CC CC_REGNUM))]
915   "TARGET_ARM"
916   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
917   [(set_attr "conds" "clob")
918    (set_attr "length" "8")]
921 (define_insn "*subdi_di_sesidi"
922   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
923         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
924                   (sign_extend:DI
925                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
926    (clobber (reg:CC CC_REGNUM))]
927   "TARGET_ARM"
928   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
929   [(set_attr "conds" "clob")
930    (set_attr "length" "8")]
933 (define_insn "*subdi_zesidi_di"
934   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
935         (minus:DI (zero_extend:DI
936                    (match_operand:SI 2 "s_register_operand"  "r,r"))
937                   (match_operand:DI  1 "s_register_operand" "?r,0")))
938    (clobber (reg:CC CC_REGNUM))]
939   "TARGET_ARM"
940   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
941   [(set_attr "conds" "clob")
942    (set_attr "length" "8")]
945 (define_insn "*subdi_sesidi_di"
946   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
947         (minus:DI (sign_extend:DI
948                    (match_operand:SI 2 "s_register_operand"   "r,r"))
949                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
950    (clobber (reg:CC CC_REGNUM))]
951   "TARGET_ARM"
952   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
953   [(set_attr "conds" "clob")
954    (set_attr "length" "8")]
957 (define_insn "*subdi_zesidi_zesidi"
958   [(set (match_operand:DI            0 "s_register_operand" "=r")
959         (minus:DI (zero_extend:DI
960                    (match_operand:SI 1 "s_register_operand"  "r"))
961                   (zero_extend:DI
962                    (match_operand:SI 2 "s_register_operand"  "r"))))
963    (clobber (reg:CC CC_REGNUM))]
964   "TARGET_ARM"
965   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
966   [(set_attr "conds" "clob")
967    (set_attr "length" "8")]
970 (define_expand "subsi3"
971   [(set (match_operand:SI           0 "s_register_operand" "")
972         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
973                   (match_operand:SI 2 "s_register_operand" "")))]
974   "TARGET_EITHER"
975   "
976   if (GET_CODE (operands[1]) == CONST_INT)
977     {
978       if (TARGET_ARM)
979         {
980           arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
981                               operands[2],
982                               (no_new_pseudos ? 0
983                                :  preserve_subexpressions_p ()));
984           DONE;
985         }
986       else /* TARGET_THUMB */
987         operands[1] = force_reg (SImode, operands[1]);
988     }
989   "
992 (define_insn "*thumb_subsi3_insn"
993   [(set (match_operand:SI           0 "register_operand" "=l")
994         (minus:SI (match_operand:SI 1 "register_operand" "l")
995                   (match_operand:SI 2 "register_operand" "l")))]
996   "TARGET_THUMB"
997   "sub\\t%0, %1, %2"
998   [(set_attr "length" "2")]
1001 (define_insn_and_split "*arm_subsi3_insn"
1002   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
1003         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1004                   (match_operand:SI 2 "s_register_operand" "r,r")))]
1005   "TARGET_ARM"
1006   "@
1007    rsb%?\\t%0, %2, %1
1008    #"
1009   "TARGET_ARM
1010    && GET_CODE (operands[1]) == CONST_INT
1011    && !const_ok_for_arm (INTVAL (operands[1]))"
1012   [(clobber (const_int 0))]
1013   "
1014   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1015                       operands[2], 0);
1016   DONE;
1017   "
1018   [(set_attr "length" "4,16")
1019    (set_attr "predicable" "yes")]
1022 (define_peephole2
1023   [(match_scratch:SI 3 "r")
1024    (set (match_operand:SI           0 "s_register_operand" "")
1025         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1026                   (match_operand:SI 2 "s_register_operand" "")))]
1027   "TARGET_ARM
1028    && !const_ok_for_arm (INTVAL (operands[1]))
1029    && const_ok_for_arm (~INTVAL (operands[1]))"
1030   [(set (match_dup 3) (match_dup 1))
1031    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1032   ""
1035 (define_insn "*subsi3_compare0"
1036   [(set (reg:CC_NOOV CC_REGNUM)
1037         (compare:CC_NOOV
1038          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1039                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1040          (const_int 0)))
1041    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1042         (minus:SI (match_dup 1) (match_dup 2)))]
1043   "TARGET_ARM"
1044   "@
1045    sub%?s\\t%0, %1, %2
1046    rsb%?s\\t%0, %2, %1"
1047   [(set_attr "conds" "set")]
1050 (define_insn "decscc"
1051   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1052         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1053                   (match_operator:SI 2 "arm_comparison_operator"
1054                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1055   "TARGET_ARM"
1056   "@
1057    sub%d2\\t%0, %1, #1
1058    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1059   [(set_attr "conds" "use")
1060    (set_attr "length" "*,8")]
1063 (define_insn "subsf3"
1064   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1065         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1066                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1067   "TARGET_ARM && TARGET_HARD_FLOAT"
1068   "@
1069    suf%?s\\t%0, %1, %2
1070    rsf%?s\\t%0, %2, %1"
1071   [(set_attr "type" "farith")]
1074 (define_insn "subdf3"
1075   [(set (match_operand:DF           0 "s_register_operand" "=f,f")
1076         (minus:DF (match_operand:DF 1 "fpu_rhs_operand"     "f,G")
1077                   (match_operand:DF 2 "fpu_rhs_operand"    "fG,f")))]
1078   "TARGET_ARM && TARGET_HARD_FLOAT"
1079   "@
1080    suf%?d\\t%0, %1, %2
1081    rsf%?d\\t%0, %2, %1"
1082   [(set_attr "type" "farith")
1083    (set_attr "predicable" "yes")]
1086 (define_insn "*subdf_esfdf_df"
1087   [(set (match_operand:DF            0 "s_register_operand" "=f")
1088         (minus:DF (float_extend:DF
1089                    (match_operand:SF 1 "s_register_operand"  "f"))
1090                   (match_operand:DF  2 "fpu_rhs_operand"    "fG")))]
1091   "TARGET_ARM && TARGET_HARD_FLOAT"
1092   "suf%?d\\t%0, %1, %2"
1093   [(set_attr "type" "farith")
1094    (set_attr "predicable" "yes")]
1097 (define_insn "*subdf_df_esfdf"
1098   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1099         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1100                   (float_extend:DF
1101                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
1102   "TARGET_ARM && TARGET_HARD_FLOAT"
1103   "@
1104    suf%?d\\t%0, %1, %2
1105    rsf%?d\\t%0, %2, %1"
1106   [(set_attr "type" "farith")
1107    (set_attr "predicable" "yes")]
1110 (define_insn "*subdf_esfdf_esfdf"
1111   [(set (match_operand:DF 0 "s_register_operand" "=f")
1112         (minus:DF (float_extend:DF
1113                    (match_operand:SF 1 "s_register_operand" "f"))
1114                   (float_extend:DF
1115                    (match_operand:SF 2 "s_register_operand" "f"))))]
1116   "TARGET_ARM && TARGET_HARD_FLOAT"
1117   "suf%?d\\t%0, %1, %2"
1118   [(set_attr "type" "farith")
1119    (set_attr "predicable" "yes")]
1122 (define_insn "subxf3"
1123   [(set (match_operand:XF           0 "s_register_operand" "=f,f")
1124         (minus:XF (match_operand:XF 1 "fpu_rhs_operand"     "f,G")
1125                   (match_operand:XF 2 "fpu_rhs_operand"    "fG,f")))]
1126   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1127   "@
1128    suf%?e\\t%0, %1, %2
1129    rsf%?e\\t%0, %2, %1"
1130   [(set_attr "type" "farith")
1131    (set_attr "predicable" "yes")]
1134 ;; Multiplication insns
1136 (define_expand "mulsi3"
1137   [(set (match_operand:SI          0 "s_register_operand" "")
1138         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1139                  (match_operand:SI 1 "s_register_operand" "")))]
1140   "TARGET_EITHER"
1141   ""
1144 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1145 (define_insn "*arm_mulsi3"
1146   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1147         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1148                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1149   "TARGET_ARM"
1150   "mul%?\\t%0, %2, %1"
1151   [(set_attr "type" "mult")
1152    (set_attr "predicable" "yes")]
1155 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1156 ; 1 and 2; are the same, because reload will make operand 0 match 
1157 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1158 ; this by adding another alternative to match this case, and then `reload' 
1159 ; it ourselves.  This alternative must come first.
1160 (define_insn "*thumb_mulsi3"
1161   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1162         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1163                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1164   "TARGET_THUMB"
1165   "*
1166   if (which_alternative < 2)
1167     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1168   else
1169     return \"mul\\t%0, %0, %2\";
1170   "
1171   [(set_attr "length" "4,4,2")
1172    (set_attr "type" "mult")]
1175 (define_insn "*mulsi3_compare0"
1176   [(set (reg:CC_NOOV CC_REGNUM)
1177         (compare:CC_NOOV (mult:SI
1178                           (match_operand:SI 2 "s_register_operand" "r,r")
1179                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1180                          (const_int 0)))
1181    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1182         (mult:SI (match_dup 2) (match_dup 1)))]
1183   "TARGET_ARM && !arm_is_xscale"
1184   "mul%?s\\t%0, %2, %1"
1185   [(set_attr "conds" "set")
1186    (set_attr "type" "mult")]
1189 (define_insn "*mulsi_compare0_scratch"
1190   [(set (reg:CC_NOOV CC_REGNUM)
1191         (compare:CC_NOOV (mult:SI
1192                           (match_operand:SI 2 "s_register_operand" "r,r")
1193                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1194                          (const_int 0)))
1195    (clobber (match_scratch:SI 0 "=&r,&r"))]
1196   "TARGET_ARM && !arm_is_xscale"
1197   "mul%?s\\t%0, %2, %1"
1198   [(set_attr "conds" "set")
1199    (set_attr "type" "mult")]
1202 ;; Unnamed templates to match MLA instruction.
1204 (define_insn "*mulsi3addsi"
1205   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1206         (plus:SI
1207           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1208                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1209           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1210   "TARGET_ARM"
1211   "mla%?\\t%0, %2, %1, %3"
1212   [(set_attr "type" "mult")
1213    (set_attr "predicable" "yes")]
1216 (define_insn "*mulsi3addsi_compare0"
1217   [(set (reg:CC_NOOV CC_REGNUM)
1218         (compare:CC_NOOV
1219          (plus:SI (mult:SI
1220                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1221                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1222                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1223          (const_int 0)))
1224    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1225         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1226                  (match_dup 3)))]
1227   "TARGET_ARM && !arm_is_xscale"
1228   "mla%?s\\t%0, %2, %1, %3"
1229   [(set_attr "conds" "set")
1230    (set_attr "type" "mult")]
1233 (define_insn "*mulsi3addsi_compare0_scratch"
1234   [(set (reg:CC_NOOV CC_REGNUM)
1235         (compare:CC_NOOV
1236          (plus:SI (mult:SI
1237                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1238                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1239                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1240          (const_int 0)))
1241    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1242   "TARGET_ARM && !arm_is_xscale"
1243   "mla%?s\\t%0, %2, %1, %3"
1244   [(set_attr "conds" "set")
1245    (set_attr "type" "mult")]
1248 ;; Unnamed template to match long long multiply-accumlate (smlal)
1250 (define_insn "*mulsidi3adddi"
1251   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1252         (plus:DI
1253          (mult:DI
1254           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1255           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1256          (match_operand:DI 1 "s_register_operand" "0")))]
1257   "TARGET_ARM && arm_fast_multiply"
1258   "smlal%?\\t%Q0, %R0, %3, %2"
1259   [(set_attr "type" "mult")
1260    (set_attr "predicable" "yes")]
1263 (define_insn "mulsidi3"
1264   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1265         (mult:DI
1266          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1267          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1268   "TARGET_ARM && arm_fast_multiply"
1269   "smull%?\\t%Q0, %R0, %1, %2"
1270   [(set_attr "type" "mult")
1271    (set_attr "predicable" "yes")]
1274 (define_insn "umulsidi3"
1275   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1276         (mult:DI
1277          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1278          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1279   "TARGET_ARM && arm_fast_multiply"
1280   "umull%?\\t%Q0, %R0, %1, %2"
1281   [(set_attr "type" "mult")
1282    (set_attr "predicable" "yes")]
1285 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1287 (define_insn "*umulsidi3adddi"
1288   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1289         (plus:DI
1290          (mult:DI
1291           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1292           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1293          (match_operand:DI 1 "s_register_operand" "0")))]
1294   "TARGET_ARM && arm_fast_multiply"
1295   "umlal%?\\t%Q0, %R0, %3, %2"
1296   [(set_attr "type" "mult")
1297    (set_attr "predicable" "yes")]
1300 (define_insn "smulsi3_highpart"
1301   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1302         (truncate:SI
1303          (lshiftrt:DI
1304           (mult:DI
1305            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1306            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1307           (const_int 32))))
1308    (clobber (match_scratch:SI 3 "=&r,&r"))]
1309   "TARGET_ARM && arm_fast_multiply"
1310   "smull%?\\t%3, %0, %2, %1"
1311   [(set_attr "type" "mult")
1312    (set_attr "predicable" "yes")]
1315 (define_insn "umulsi3_highpart"
1316   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1317         (truncate:SI
1318          (lshiftrt:DI
1319           (mult:DI
1320            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1321            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1322           (const_int 32))))
1323    (clobber (match_scratch:SI 3 "=&r,&r"))]
1324   "TARGET_ARM && arm_fast_multiply"
1325   "umull%?\\t%3, %0, %2, %1"
1326   [(set_attr "type" "mult")
1327    (set_attr "predicable" "yes")]
1330 (define_insn "mulhisi3"
1331   [(set (match_operand:SI 0 "s_register_operand" "=r")
1332         (mult:SI (sign_extend:SI
1333                   (match_operand:HI 1 "s_register_operand" "%r"))
1334                  (sign_extend:SI
1335                   (match_operand:HI 2 "s_register_operand" "r"))))]
1336   "TARGET_ARM && arm_is_xscale"
1337   "smulbb%?\\t%0, %1, %2"
1338   [(set_attr "type" "mult")]
1341 (define_insn "*mulhisi3addsi"
1342   [(set (match_operand:SI 0 "s_register_operand" "=r")
1343         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1344                  (mult:SI (sign_extend:SI
1345                            (match_operand:HI 2 "s_register_operand" "%r"))
1346                           (sign_extend:SI
1347                            (match_operand:HI 3 "s_register_operand" "r")))))]
1348   "TARGET_ARM && arm_is_xscale"
1349   "smlabb%?\\t%0, %2, %3, %1"
1350   [(set_attr "type" "mult")]
1353 (define_insn "*mulhidi3adddi"
1354   [(set (match_operand:DI 0 "s_register_operand" "=r")
1355         (plus:DI
1356           (match_operand:DI 1 "s_register_operand" "0")
1357           (mult:DI (sign_extend:DI
1358                     (match_operand:HI 2 "s_register_operand" "%r"))
1359                    (sign_extend:DI
1360                     (match_operand:HI 3 "s_register_operand" "r")))))]
1361   "TARGET_ARM && arm_is_xscale"
1362   "smlalbb%?\\t%Q0, %R0, %2, %3"
1363 [(set_attr "type" "mult")])
1365 (define_insn "mulsf3"
1366   [(set (match_operand:SF 0 "s_register_operand" "=f")
1367         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1368                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1369   "TARGET_ARM && TARGET_HARD_FLOAT"
1370   "fml%?s\\t%0, %1, %2"
1371   [(set_attr "type" "ffmul")
1372    (set_attr "predicable" "yes")]
1375 (define_insn "muldf3"
1376   [(set (match_operand:DF 0 "s_register_operand" "=f")
1377         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1378                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1379   "TARGET_ARM && TARGET_HARD_FLOAT"
1380   "muf%?d\\t%0, %1, %2"
1381   [(set_attr "type" "fmul")
1382    (set_attr "predicable" "yes")]
1385 (define_insn "*muldf_esfdf_df"
1386   [(set (match_operand:DF 0 "s_register_operand" "=f")
1387         (mult:DF (float_extend:DF
1388                   (match_operand:SF 1 "s_register_operand" "f"))
1389                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1390   "TARGET_ARM && TARGET_HARD_FLOAT"
1391   "muf%?d\\t%0, %1, %2"
1392   [(set_attr "type" "fmul")
1393    (set_attr "predicable" "yes")]
1396 (define_insn "*muldf_df_esfdf"
1397   [(set (match_operand:DF 0 "s_register_operand" "=f")
1398         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1399                  (float_extend:DF
1400                   (match_operand:SF 2 "s_register_operand" "f"))))]
1401   "TARGET_ARM && TARGET_HARD_FLOAT"
1402   "muf%?d\\t%0, %1, %2"
1403   [(set_attr "type" "fmul")
1404    (set_attr "predicable" "yes")]
1407 (define_insn "*muldf_esfdf_esfdf"
1408   [(set (match_operand:DF 0 "s_register_operand" "=f")
1409         (mult:DF
1410          (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1411          (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1412   "TARGET_ARM && TARGET_HARD_FLOAT"
1413   "muf%?d\\t%0, %1, %2"
1414   [(set_attr "type" "fmul")
1415    (set_attr "predicable" "yes")]
1418 (define_insn "mulxf3"
1419   [(set (match_operand:XF 0 "s_register_operand" "=f")
1420         (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1421                  (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1422   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1423   "muf%?e\\t%0, %1, %2"
1424   [(set_attr "type" "fmul")
1425    (set_attr "predicable" "yes")]
1428 ;; Division insns
1430 (define_insn "divsf3"
1431   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1432         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1433                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1434   "TARGET_ARM && TARGET_HARD_FLOAT"
1435   "@
1436    fdv%?s\\t%0, %1, %2
1437    frd%?s\\t%0, %2, %1"
1438   [(set_attr "type" "fdivs")
1439    (set_attr "predicable" "yes")]
1442 (define_insn "divdf3"
1443   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1444         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1445                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1446   "TARGET_ARM && TARGET_HARD_FLOAT"
1447   "@
1448    dvf%?d\\t%0, %1, %2
1449    rdf%?d\\t%0, %2, %1"
1450   [(set_attr "type" "fdivd")
1451    (set_attr "predicable" "yes")]
1454 (define_insn "*divdf_esfdf_df"
1455   [(set (match_operand:DF 0 "s_register_operand" "=f")
1456         (div:DF (float_extend:DF
1457                  (match_operand:SF 1 "s_register_operand" "f"))
1458                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1459   "TARGET_ARM && TARGET_HARD_FLOAT"
1460   "dvf%?d\\t%0, %1, %2"
1461   [(set_attr "type" "fdivd")
1462    (set_attr "predicable" "yes")]
1465 (define_insn "*divdf_df_esfdf"
1466   [(set (match_operand:DF 0 "s_register_operand" "=f")
1467         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1468                 (float_extend:DF
1469                  (match_operand:SF 2 "s_register_operand" "f"))))]
1470   "TARGET_ARM && TARGET_HARD_FLOAT"
1471   "rdf%?d\\t%0, %2, %1"
1472   [(set_attr "type" "fdivd")
1473    (set_attr "predicable" "yes")]
1476 (define_insn "*divdf_esfdf_esfdf"
1477   [(set (match_operand:DF 0 "s_register_operand" "=f")
1478         (div:DF (float_extend:DF
1479                  (match_operand:SF 1 "s_register_operand" "f"))
1480                 (float_extend:DF
1481                  (match_operand:SF 2 "s_register_operand" "f"))))]
1482   "TARGET_ARM && TARGET_HARD_FLOAT"
1483   "dvf%?d\\t%0, %1, %2"
1484   [(set_attr "type" "fdivd")
1485    (set_attr "predicable" "yes")]
1488 (define_insn "divxf3"
1489   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1490         (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1491                 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1492   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1493   "@
1494    dvf%?e\\t%0, %1, %2
1495    rdf%?e\\t%0, %2, %1"
1496   [(set_attr "type" "fdivx")
1497    (set_attr "predicable" "yes")]
1500 ;; Modulo insns
1502 (define_insn "modsf3"
1503   [(set (match_operand:SF 0 "s_register_operand" "=f")
1504         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1505                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1506   "TARGET_ARM && TARGET_HARD_FLOAT"
1507   "rmf%?s\\t%0, %1, %2"
1508   [(set_attr "type" "fdivs")
1509    (set_attr "predicable" "yes")]
1512 (define_insn "moddf3"
1513   [(set (match_operand:DF 0 "s_register_operand" "=f")
1514         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1515                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1516   "TARGET_ARM && TARGET_HARD_FLOAT"
1517   "rmf%?d\\t%0, %1, %2"
1518   [(set_attr "type" "fdivd")
1519    (set_attr "predicable" "yes")]
1522 (define_insn "*moddf_esfdf_df"
1523   [(set (match_operand:DF 0 "s_register_operand" "=f")
1524         (mod:DF (float_extend:DF
1525                  (match_operand:SF 1 "s_register_operand" "f"))
1526                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1527   "TARGET_ARM && TARGET_HARD_FLOAT"
1528   "rmf%?d\\t%0, %1, %2"
1529   [(set_attr "type" "fdivd")
1530    (set_attr "predicable" "yes")]
1533 (define_insn "*moddf_df_esfdf"
1534   [(set (match_operand:DF 0 "s_register_operand" "=f")
1535         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1536                 (float_extend:DF
1537                  (match_operand:SF 2 "s_register_operand" "f"))))]
1538   "TARGET_ARM && TARGET_HARD_FLOAT"
1539   "rmf%?d\\t%0, %1, %2"
1540   [(set_attr "type" "fdivd")
1541    (set_attr "predicable" "yes")]
1544 (define_insn "*moddf_esfdf_esfdf"
1545   [(set (match_operand:DF 0 "s_register_operand" "=f")
1546         (mod:DF (float_extend:DF
1547                  (match_operand:SF 1 "s_register_operand" "f"))
1548                 (float_extend:DF
1549                  (match_operand:SF 2 "s_register_operand" "f"))))]
1550   "TARGET_ARM && TARGET_HARD_FLOAT"
1551   "rmf%?d\\t%0, %1, %2"
1552   [(set_attr "type" "fdivd")
1553    (set_attr "predicable" "yes")]
1556 (define_insn "modxf3"
1557   [(set (match_operand:XF 0 "s_register_operand" "=f")
1558         (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1559                 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1560   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1561   "rmf%?e\\t%0, %1, %2"
1562   [(set_attr "type" "fdivx")
1563    (set_attr "predicable" "yes")]
1566 ;; Boolean and,ior,xor insns
1568 ;; Split up double word logical operations
1570 ;; Split up simple DImode logical operations.  Simply perform the logical
1571 ;; operation on the upper and lower halves of the registers.
1572 (define_split
1573   [(set (match_operand:DI 0 "s_register_operand" "")
1574         (match_operator:DI 6 "logical_binary_operator"
1575           [(match_operand:DI 1 "s_register_operand" "")
1576            (match_operand:DI 2 "s_register_operand" "")]))]
1577   "TARGET_ARM && reload_completed"
1578   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1579    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1580   "
1581   {
1582     operands[3] = gen_highpart (SImode, operands[0]);
1583     operands[0] = gen_lowpart (SImode, operands[0]);
1584     operands[4] = gen_highpart (SImode, operands[1]);
1585     operands[1] = gen_lowpart (SImode, operands[1]);
1586     operands[5] = gen_highpart (SImode, operands[2]);
1587     operands[2] = gen_lowpart (SImode, operands[2]);
1588   }"
1591 (define_split
1592   [(set (match_operand:DI 0 "s_register_operand" "")
1593         (match_operator:DI 6 "logical_binary_operator"
1594           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1595            (match_operand:DI 1 "s_register_operand" "")]))]
1596   "TARGET_ARM && reload_completed"
1597   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1598    (set (match_dup 3) (match_op_dup:SI 6
1599                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1600                          (match_dup 4)]))]
1601   "
1602   {
1603     operands[3] = gen_highpart (SImode, operands[0]);
1604     operands[0] = gen_lowpart (SImode, operands[0]);
1605     operands[4] = gen_highpart (SImode, operands[1]);
1606     operands[1] = gen_lowpart (SImode, operands[1]);
1607     operands[5] = gen_highpart (SImode, operands[2]);
1608     operands[2] = gen_lowpart (SImode, operands[2]);
1609   }"
1612 ;; The zero extend of operand 2 means we can just copy the high part of
1613 ;; operand1 into operand0.
1614 (define_split
1615   [(set (match_operand:DI 0 "s_register_operand" "")
1616         (ior:DI
1617           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1618           (match_operand:DI 1 "s_register_operand" "")))]
1619   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1620   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1621    (set (match_dup 3) (match_dup 4))]
1622   "
1623   {
1624     operands[4] = gen_highpart (SImode, operands[1]);
1625     operands[3] = gen_highpart (SImode, operands[0]);
1626     operands[0] = gen_lowpart (SImode, operands[0]);
1627     operands[1] = gen_lowpart (SImode, operands[1]);
1628   }"
1631 ;; The zero extend of operand 2 means we can just copy the high part of
1632 ;; operand1 into operand0.
1633 (define_split
1634   [(set (match_operand:DI 0 "s_register_operand" "")
1635         (xor:DI
1636           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1637           (match_operand:DI 1 "s_register_operand" "")))]
1638   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1639   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1640    (set (match_dup 3) (match_dup 4))]
1641   "
1642   {
1643     operands[4] = gen_highpart (SImode, operands[1]);
1644     operands[3] = gen_highpart (SImode, operands[0]);
1645     operands[0] = gen_lowpart (SImode, operands[0]);
1646     operands[1] = gen_lowpart (SImode, operands[1]);
1647   }"
1650 (define_insn "anddi3"
1651   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1652         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1653                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1654   "TARGET_ARM"
1655   "#"
1656   [(set_attr "length" "8")]
1659 (define_insn_and_split "*anddi_zesidi_di"
1660   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1661         (and:DI (zero_extend:DI
1662                  (match_operand:SI 2 "s_register_operand" "r,r"))
1663                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1664   "TARGET_ARM"
1665   "#"
1666   "TARGET_ARM && reload_completed"
1667   ; The zero extend of operand 2 clears the high word of the output
1668   ; operand.
1669   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1670    (set (match_dup 3) (const_int 0))]
1671   "
1672   {
1673     operands[3] = gen_highpart (SImode, operands[0]);
1674     operands[0] = gen_lowpart (SImode, operands[0]);
1675     operands[1] = gen_lowpart (SImode, operands[1]);
1676   }"
1677   [(set_attr "length" "8")]
1680 (define_insn "*anddi_sesdi_di"
1681   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1682         (and:DI (sign_extend:DI
1683                  (match_operand:SI 2 "s_register_operand" "r,r"))
1684                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1685   "TARGET_ARM"
1686   "#"
1687   [(set_attr "length" "8")]
1690 (define_expand "andsi3"
1691   [(set (match_operand:SI         0 "s_register_operand" "")
1692         (and:SI (match_operand:SI 1 "s_register_operand" "")
1693                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1694   "TARGET_EITHER"
1695   "
1696   if (TARGET_ARM)
1697     {
1698       if (GET_CODE (operands[2]) == CONST_INT)
1699         {
1700           arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1701                               operands[1],
1702                               (no_new_pseudos
1703                                ? 0 : preserve_subexpressions_p ()));
1704           DONE;
1705         }
1706     }
1707   else /* TARGET_THUMB */
1708     {
1709       if (GET_CODE (operands[2]) != CONST_INT)
1710         operands[2] = force_reg (SImode, operands[2]);
1711       else
1712         {
1713           int i;
1714           
1715           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1716             {
1717               operands[2] = force_reg (SImode,
1718                                        GEN_INT (~INTVAL (operands[2])));
1719               
1720               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1721               
1722               DONE;
1723             }
1725           for (i = 9; i <= 31; i++)
1726             {
1727               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1728                 {
1729                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1730                                         const0_rtx));
1731                   DONE;
1732                 }
1733               else if ((((HOST_WIDE_INT) 1) << i) - 1
1734                        == ~INTVAL (operands[2]))
1735                 {
1736                   rtx shift = GEN_INT (i);
1737                   rtx reg = gen_reg_rtx (SImode);
1738                 
1739                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1740                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1741                   
1742                   DONE;
1743                 }
1744             }
1746           operands[2] = force_reg (SImode, operands[2]);
1747         }
1748     }
1749   "
1752 (define_insn_and_split "*arm_andsi3_insn"
1753   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1754         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1755                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1756   "TARGET_ARM"
1757   "@
1758    and%?\\t%0, %1, %2
1759    bic%?\\t%0, %1, #%B2
1760    #"
1761   "TARGET_ARM
1762    && GET_CODE (operands[2]) == CONST_INT
1763    && !(const_ok_for_arm (INTVAL (operands[2]))
1764         || const_ok_for_arm (~INTVAL (operands[2])))"
1765   [(clobber (const_int 0))]
1766   "
1767   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1768                        operands[1], 0);
1769   DONE;
1770   "
1771   [(set_attr "length" "4,4,16")
1772    (set_attr "predicable" "yes")]
1775 (define_insn "*thumb_andsi3_insn"
1776   [(set (match_operand:SI         0 "register_operand" "=l")
1777         (and:SI (match_operand:SI 1 "register_operand" "%0")
1778                 (match_operand:SI 2 "register_operand" "l")))]
1779   "TARGET_THUMB"
1780   "and\\t%0, %0, %2"
1781   [(set_attr "length" "2")]
1784 (define_insn "*andsi3_compare0"
1785   [(set (reg:CC_NOOV CC_REGNUM)
1786         (compare:CC_NOOV
1787          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1788                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1789          (const_int 0)))
1790    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1791         (and:SI (match_dup 1) (match_dup 2)))]
1792   "TARGET_ARM"
1793   "@
1794    and%?s\\t%0, %1, %2
1795    bic%?s\\t%0, %1, #%B2"
1796   [(set_attr "conds" "set")]
1799 (define_insn "*andsi3_compare0_scratch"
1800   [(set (reg:CC_NOOV CC_REGNUM)
1801         (compare:CC_NOOV
1802          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1803                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1804          (const_int 0)))
1805    (clobber (match_scratch:SI 2 "=X,r"))]
1806   "TARGET_ARM"
1807   "@
1808    tst%?\\t%0, %1
1809    bic%?s\\t%2, %0, #%B1"
1810   [(set_attr "conds" "set")]
1813 (define_insn "*zeroextractsi_compare0_scratch"
1814   [(set (reg:CC_NOOV CC_REGNUM)
1815         (compare:CC_NOOV (zero_extract:SI
1816                           (match_operand:SI 0 "s_register_operand" "r")
1817                           (match_operand 1 "const_int_operand" "n")
1818                           (match_operand 2 "const_int_operand" "n"))
1819                          (const_int 0)))]
1820   "TARGET_ARM
1821   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1822       && INTVAL (operands[1]) > 0 
1823       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1824       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1825   "*
1826   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1827                          << INTVAL (operands[2]));
1828   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1829   return \"\";
1830   "
1831   [(set_attr "conds" "set")]
1834 (define_insn "*ne_zeroextractsi"
1835   [(set (match_operand:SI 0 "s_register_operand" "=r")
1836         (ne:SI (zero_extract:SI
1837                 (match_operand:SI 1 "s_register_operand" "r")
1838                 (match_operand:SI 2 "const_int_operand" "n")
1839                 (match_operand:SI 3 "const_int_operand" "n"))
1840                (const_int 0)))]
1841   "TARGET_ARM
1842    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1843        && INTVAL (operands[2]) > 0 
1844        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1845        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1846   "*
1847   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1848                          << INTVAL (operands[3]));
1849   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1850   return \"movne\\t%0, #1\";
1851   "
1852   [(set_attr "conds" "clob")
1853    (set_attr "length" "8")]
1856 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1857 ;;; represented by the bitfield, then this will produce incorrect results.
1858 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1859 ;;; which have a real bitfield insert instruction, the truncation happens
1860 ;;; in the bitfield insert instruction itself.  Since arm does not have a
1861 ;;; bitfield insert instruction, we would have to emit code here to truncate
1862 ;;; the value before we insert.  This loses some of the advantage of having
1863 ;;; this insv pattern, so this pattern needs to be reevalutated.
1865 (define_expand "insv"
1866   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1867                          (match_operand:SI 1 "general_operand" "")
1868                          (match_operand:SI 2 "general_operand" ""))
1869         (match_operand:SI 3 "nonmemory_operand" ""))]
1870   "TARGET_ARM"
1871   "
1872   {
1873     int start_bit = INTVAL (operands[2]);
1874     int width = INTVAL (operands[1]);
1875     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1876     rtx target, subtarget;
1878     target = operands[0];
1879     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1880        subreg as the final target.  */
1881     if (GET_CODE (target) == SUBREG)
1882       {
1883         subtarget = gen_reg_rtx (SImode);
1884         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1885             < GET_MODE_SIZE (SImode))
1886           target = SUBREG_REG (target);
1887       }
1888     else
1889       subtarget = target;    
1891     if (GET_CODE (operands[3]) == CONST_INT)
1892       {
1893         /* Since we are inserting a known constant, we may be able to
1894            reduce the number of bits that we have to clear so that
1895            the mask becomes simple.  */
1896         /* ??? This code does not check to see if the new mask is actually
1897            simpler.  It may not be.  */
1898         rtx op1 = gen_reg_rtx (SImode);
1899         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1900            start of this pattern.  */
1901         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1902         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1904         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1905         emit_insn (gen_iorsi3 (subtarget, op1,
1906                                GEN_INT (op3_value << start_bit)));
1907       }
1908     else if (start_bit == 0
1909              && !(const_ok_for_arm (mask)
1910                   || const_ok_for_arm (~mask)))
1911       {
1912         /* A Trick, since we are setting the bottom bits in the word,
1913            we can shift operand[3] up, operand[0] down, OR them together
1914            and rotate the result back again.  This takes 3 insns, and
1915            the third might be mergable into another op.  */
1916         /* The shift up copes with the possibility that operand[3] is
1917            wider than the bitfield.  */
1918         rtx op0 = gen_reg_rtx (SImode);
1919         rtx op1 = gen_reg_rtx (SImode);
1921         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1922         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1923         emit_insn (gen_iorsi3  (op1, op1, op0));
1924         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1925       }
1926     else if ((width + start_bit == 32)
1927              && !(const_ok_for_arm (mask)
1928                   || const_ok_for_arm (~mask)))
1929       {
1930         /* Similar trick, but slightly less efficient.  */
1932         rtx op0 = gen_reg_rtx (SImode);
1933         rtx op1 = gen_reg_rtx (SImode);
1935         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1936         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1937         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1938         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1939       }
1940     else
1941       {
1942         rtx op0 = GEN_INT (mask);
1943         rtx op1 = gen_reg_rtx (SImode);
1944         rtx op2 = gen_reg_rtx (SImode);
1946         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1947           {
1948             rtx tmp = gen_reg_rtx (SImode);
1950             emit_insn (gen_movsi (tmp, op0));
1951             op0 = tmp;
1952           }
1954         /* Mask out any bits in operand[3] that are not needed.  */
1955            emit_insn (gen_andsi3 (op1, operands[3], op0));
1957         if (GET_CODE (op0) == CONST_INT
1958             && (const_ok_for_arm (mask << start_bit)
1959                 || const_ok_for_arm (~(mask << start_bit))))
1960           {
1961             op0 = GEN_INT (~(mask << start_bit));
1962             emit_insn (gen_andsi3 (op2, operands[0], op0));
1963           }
1964         else
1965           {
1966             if (GET_CODE (op0) == CONST_INT)
1967               {
1968                 rtx tmp = gen_reg_rtx (SImode);
1970                 emit_insn (gen_movsi (tmp, op0));
1971                 op0 = tmp;
1972               }
1974             if (start_bit != 0)
1975               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1976             
1977             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1978           }
1980         if (start_bit != 0)
1981           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1983         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1984       }
1986     if (subtarget != target)
1987       {
1988         /* If TARGET is still a SUBREG, then it must be wider than a word,
1989            so we must be careful only to set the subword we were asked to.  */
1990         if (GET_CODE (target) == SUBREG)
1991           emit_move_insn (target, subtarget);
1992         else
1993           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1994       }
1996     DONE;
1997   }"
2000 ; constants for op 2 will never be given to these patterns.
2001 (define_insn_and_split "*anddi_notdi_di"
2002   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2003         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2004                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2005   "TARGET_ARM"
2006   "#"
2007   "TARGET_ARM && reload_completed"
2008   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2009    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2010   "
2011   {
2012     operands[3] = gen_highpart (SImode, operands[0]);
2013     operands[0] = gen_lowpart (SImode, operands[0]);
2014     operands[4] = gen_highpart (SImode, operands[1]);
2015     operands[1] = gen_lowpart (SImode, operands[1]);
2016     operands[5] = gen_highpart (SImode, operands[2]);
2017     operands[2] = gen_lowpart (SImode, operands[2]);
2018   }"
2019   [(set_attr "length" "8")
2020    (set_attr "predicable" "yes")]
2022   
2023 (define_insn_and_split "*anddi_notzesidi_di"
2024   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2025         (and:DI (not:DI (zero_extend:DI
2026                          (match_operand:SI 2 "s_register_operand" "r,r")))
2027                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2028   "TARGET_ARM"
2029   "@
2030    bic%?\\t%Q0, %Q1, %2
2031    #"
2032   ; (not (zero_extend ...)) allows us to just copy the high word from
2033   ; operand1 to operand0.
2034   "TARGET_ARM
2035    && reload_completed
2036    && operands[0] != operands[1]"
2037   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2038    (set (match_dup 3) (match_dup 4))]
2039   "
2040   {
2041     operands[3] = gen_highpart (SImode, operands[0]);
2042     operands[0] = gen_lowpart (SImode, operands[0]);
2043     operands[4] = gen_highpart (SImode, operands[1]);
2044     operands[1] = gen_lowpart (SImode, operands[1]);
2045   }"
2046   [(set_attr "length" "4,8")
2047    (set_attr "predicable" "yes")]
2049   
2050 (define_insn_and_split "*anddi_notsesidi_di"
2051   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2052         (and:DI (not:DI (sign_extend:DI
2053                          (match_operand:SI 2 "s_register_operand" "r,r")))
2054                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2055   "TARGET_ARM"
2056   "#"
2057   "TARGET_ARM && reload_completed"
2058   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2059    (set (match_dup 3) (and:SI (not:SI
2060                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2061                                (match_dup 4)))]
2062   "
2063   {
2064     operands[3] = gen_highpart (SImode, operands[0]);
2065     operands[0] = gen_lowpart (SImode, operands[0]);
2066     operands[4] = gen_highpart (SImode, operands[1]);
2067     operands[1] = gen_lowpart (SImode, operands[1]);
2068   }"
2069   [(set_attr "length" "8")
2070    (set_attr "predicable" "yes")]
2072   
2073 (define_insn "andsi_notsi_si"
2074   [(set (match_operand:SI 0 "s_register_operand" "=r")
2075         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2076                 (match_operand:SI 1 "s_register_operand" "r")))]
2077   "TARGET_ARM"
2078   "bic%?\\t%0, %1, %2"
2079   [(set_attr "predicable" "yes")]
2082 (define_insn "bicsi3"
2083   [(set (match_operand:SI                 0 "register_operand" "=l")
2084         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2085                 (match_operand:SI         2 "register_operand" "0")))]
2086   "TARGET_THUMB"
2087   "bic\\t%0, %0, %1"
2088   [(set_attr "length" "2")]
2091 (define_insn "andsi_not_shiftsi_si"
2092   [(set (match_operand:SI                   0 "s_register_operand" "=r")
2093         (and:SI (not:SI (match_operator:SI  4 "shift_operator"
2094                          [(match_operand:SI 2 "s_register_operand"  "r")
2095                           (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
2096                 (match_operand:SI           1 "s_register_operand"  "r")))]
2097   "TARGET_ARM"
2098   "bic%?\\t%0, %1, %2%S4"
2099   [(set_attr "predicable" "yes")
2100    (set_attr "shift" "2")
2101    ]
2104 (define_insn "*andsi_notsi_si_compare0"
2105   [(set (reg:CC_NOOV CC_REGNUM)
2106         (compare:CC_NOOV
2107          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2108                  (match_operand:SI 1 "s_register_operand" "r"))
2109          (const_int 0)))
2110    (set (match_operand:SI 0 "s_register_operand" "=r")
2111         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2112   "TARGET_ARM"
2113   "bic%?s\\t%0, %1, %2"
2114   [(set_attr "conds" "set")]
2117 (define_insn "*andsi_notsi_si_compare0_scratch"
2118   [(set (reg:CC_NOOV CC_REGNUM)
2119         (compare:CC_NOOV
2120          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2121                  (match_operand:SI 1 "s_register_operand" "r"))
2122          (const_int 0)))
2123    (clobber (match_scratch:SI 0 "=r"))]
2124   "TARGET_ARM"
2125   "bic%?s\\t%0, %1, %2"
2126   [(set_attr "conds" "set")]
2129 (define_insn "iordi3"
2130   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2131         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2132                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2133   "TARGET_ARM"
2134   "#"
2135   [(set_attr "length" "8")
2136    (set_attr "predicable" "yes")]
2139 (define_insn "*iordi_zesidi_di"
2140   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2141         (ior:DI (zero_extend:DI
2142                  (match_operand:SI 2 "s_register_operand" "r,r"))
2143                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2144   "TARGET_ARM"
2145   "@
2146    orr%?\\t%Q0, %Q1, %2
2147    #"
2148   [(set_attr "length" "4,8")
2149    (set_attr "predicable" "yes")]
2152 (define_insn "*iordi_sesidi_di"
2153   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2154         (ior:DI (sign_extend:DI
2155                  (match_operand:SI 2 "s_register_operand" "r,r"))
2156                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2157   "TARGET_ARM"
2158   "#"
2159   [(set_attr "length" "8")
2160    (set_attr "predicable" "yes")]
2163 (define_expand "iorsi3"
2164   [(set (match_operand:SI         0 "s_register_operand" "")
2165         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2166                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2167   "TARGET_EITHER"
2168   "
2169   if (GET_CODE (operands[2]) == CONST_INT)
2170     {
2171       if (TARGET_ARM)
2172         {
2173           arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2174                               operands[1],
2175                               (no_new_pseudos
2176                               ? 0 : preserve_subexpressions_p ()));
2177           DONE;
2178         }
2179       else /* TARGET_THUMB */
2180         operands [2] = force_reg (SImode, operands [2]);
2181     }
2182   "
2185 (define_insn_and_split "*arm_iorsi3"
2186   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2187         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2188                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2189   "TARGET_ARM"
2190   "@
2191    orr%?\\t%0, %1, %2
2192    #"
2193   "TARGET_ARM
2194    && GET_CODE (operands[2]) == CONST_INT
2195    && !const_ok_for_arm (INTVAL (operands[2]))"
2196   [(clobber (const_int 0))]
2197   "
2198   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2199                       operands[1], 0);
2200   DONE;
2201   "
2202   [(set_attr "length" "4,16")
2203    (set_attr "predicable" "yes")]
2206 (define_insn "*thumb_iorsi3"
2207   [(set (match_operand:SI         0 "register_operand" "=l")
2208         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2209                 (match_operand:SI 2 "register_operand" "l")))]
2210   "TARGET_THUMB"
2211   "orr\\t%0, %0, %2"
2212   [(set_attr "length" "2")]
2215 (define_peephole2
2216   [(match_scratch:SI 3 "r")
2217    (set (match_operand:SI         0 "s_register_operand" "")
2218         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2219                 (match_operand:SI 2 "const_int_operand" "")))]
2220   "TARGET_ARM
2221    && !const_ok_for_arm (INTVAL (operands[2]))
2222    && const_ok_for_arm (~INTVAL (operands[2]))"
2223   [(set (match_dup 3) (match_dup 2))
2224    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2225   ""
2228 (define_insn "*iorsi3_compare0"
2229   [(set (reg:CC_NOOV CC_REGNUM)
2230         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2231                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2232                          (const_int 0)))
2233    (set (match_operand:SI 0 "s_register_operand" "=r")
2234         (ior:SI (match_dup 1) (match_dup 2)))]
2235   "TARGET_ARM"
2236   "orr%?s\\t%0, %1, %2"
2237   [(set_attr "conds" "set")]
2240 (define_insn "*iorsi3_compare0_scratch"
2241   [(set (reg:CC_NOOV CC_REGNUM)
2242         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2243                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2244                          (const_int 0)))
2245    (clobber (match_scratch:SI 0 "=r"))]
2246   "TARGET_ARM"
2247   "orr%?s\\t%0, %1, %2"
2248   [(set_attr "conds" "set")]
2251 (define_insn "xordi3"
2252   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2253         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2254                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2255   "TARGET_ARM"
2256   "#"
2257   [(set_attr "length" "8")
2258    (set_attr "predicable" "yes")]
2261 (define_insn "*xordi_zesidi_di"
2262   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2263         (xor:DI (zero_extend:DI
2264                  (match_operand:SI 2 "s_register_operand" "r,r"))
2265                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2266   "TARGET_ARM"
2267   "@
2268    eor%?\\t%Q0, %Q1, %2
2269    #"
2270   [(set_attr "length" "4,8")
2271    (set_attr "predicable" "yes")]
2274 (define_insn "*xordi_sesidi_di"
2275   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2276         (xor:DI (sign_extend:DI
2277                  (match_operand:SI 2 "s_register_operand" "r,r"))
2278                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2279   "TARGET_ARM"
2280   "#"
2281   [(set_attr "length" "8")
2282    (set_attr "predicable" "yes")]
2285 (define_expand "xorsi3"
2286   [(set (match_operand:SI         0 "s_register_operand" "")
2287         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2288                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2289   "TARGET_EITHER"
2290   "if (TARGET_THUMB)
2291      if (GET_CODE (operands[2]) == CONST_INT)
2292        operands[2] = force_reg (SImode, operands[2]);
2293   "
2296 (define_insn "*arm_xorsi3"
2297   [(set (match_operand:SI         0 "s_register_operand" "=r")
2298         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2299                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2300   "TARGET_ARM"
2301   "eor%?\\t%0, %1, %2"
2302   [(set_attr "predicable" "yes")]
2305 (define_insn "*thumb_xorsi3"
2306   [(set (match_operand:SI         0 "register_operand" "=l")
2307         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2308                 (match_operand:SI 2 "register_operand" "l")))]
2309   "TARGET_THUMB"
2310   "eor\\t%0, %0, %2"
2311   [(set_attr "length" "2")]
2314 (define_insn "*xorsi3_compare0"
2315   [(set (reg:CC_NOOV CC_REGNUM)
2316         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2317                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2318                          (const_int 0)))
2319    (set (match_operand:SI 0 "s_register_operand" "=r")
2320         (xor:SI (match_dup 1) (match_dup 2)))]
2321   "TARGET_ARM"
2322   "eor%?s\\t%0, %1, %2"
2323   [(set_attr "conds" "set")]
2326 (define_insn "*xorsi3_compare0_scratch"
2327   [(set (reg:CC_NOOV CC_REGNUM)
2328         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2329                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2330                          (const_int 0)))]
2331   "TARGET_ARM"
2332   "teq%?\\t%0, %1"
2333   [(set_attr "conds" "set")]
2336 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2337 ; (NOT D) we can sometimes merge the final NOT into one of the following
2338 ; insns.
2340 (define_split
2341   [(set (match_operand:SI 0 "s_register_operand" "")
2342         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2343                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2344                 (match_operand:SI 3 "arm_rhs_operand" "")))
2345    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2346   "TARGET_ARM"
2347   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2348                               (not:SI (match_dup 3))))
2349    (set (match_dup 0) (not:SI (match_dup 4)))]
2350   ""
2353 (define_insn "*andsi_iorsi3_notsi"
2354   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2355         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2356                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2357                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2358   "TARGET_ARM"
2359   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2360   [(set_attr "length" "8")
2361    (set_attr "predicable" "yes")]
2366 ;; Minimum and maximum insns
2368 (define_insn "smaxsi3"
2369   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2370         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2371                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2372    (clobber (reg:CC CC_REGNUM))]
2373   "TARGET_ARM"
2374   "@
2375    cmp\\t%1, %2\;movlt\\t%0, %2
2376    cmp\\t%1, %2\;movge\\t%0, %1
2377    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2378   [(set_attr "conds" "clob")
2379    (set_attr "length" "8,8,12")]
2382 (define_insn "sminsi3"
2383   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2384         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2385                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2386    (clobber (reg:CC CC_REGNUM))]
2387   "TARGET_ARM"
2388   "@
2389    cmp\\t%1, %2\;movge\\t%0, %2
2390    cmp\\t%1, %2\;movlt\\t%0, %1
2391    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2392   [(set_attr "conds" "clob")
2393    (set_attr "length" "8,8,12")]
2396 (define_insn "umaxsi3"
2397   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2398         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2399                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2400    (clobber (reg:CC CC_REGNUM))]
2401   "TARGET_ARM"
2402   "@
2403    cmp\\t%1, %2\;movcc\\t%0, %2
2404    cmp\\t%1, %2\;movcs\\t%0, %1
2405    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2406   [(set_attr "conds" "clob")
2407    (set_attr "length" "8,8,12")]
2410 (define_insn "uminsi3"
2411   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2412         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2413                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2414    (clobber (reg:CC CC_REGNUM))]
2415   "TARGET_ARM"
2416   "@
2417    cmp\\t%1, %2\;movcs\\t%0, %2
2418    cmp\\t%1, %2\;movcc\\t%0, %1
2419    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2420   [(set_attr "conds" "clob")
2421    (set_attr "length" "8,8,12")]
2424 (define_insn "*store_minmaxsi"
2425   [(set (match_operand:SI 0 "memory_operand" "=m")
2426         (match_operator:SI 3 "minmax_operator"
2427          [(match_operand:SI 1 "s_register_operand" "r")
2428           (match_operand:SI 2 "s_register_operand" "r")]))
2429    (clobber (reg:CC CC_REGNUM))]
2430   "TARGET_ARM"
2431   "*
2432   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2433                          operands[2]);
2434   output_asm_insn (\"cmp\\t%1, %2\", operands);
2435   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2436   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2437   return \"\";
2438   "
2439   [(set_attr "conds" "clob")
2440    (set_attr "length" "12")
2441    (set_attr "type" "store1")]
2444 ; Reject the frame pointer in operand[1], since reloading this after
2445 ; it has been eliminated can cause carnage.
2446 (define_insn "*minmax_arithsi"
2447   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2448         (match_operator:SI 4 "shiftable_operator"
2449          [(match_operator:SI 5 "minmax_operator"
2450            [(match_operand:SI 2 "s_register_operand" "r,r")
2451             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2452           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2453    (clobber (reg:CC CC_REGNUM))]
2454   "TARGET_ARM
2455    && (GET_CODE (operands[1]) != REG
2456        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2457            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2458   "*
2459   {
2460     enum rtx_code code = GET_CODE (operands[4]);
2462     operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2463                            operands[3]);
2464     output_asm_insn (\"cmp\\t%2, %3\", operands);
2465     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2466     if (which_alternative != 0 || operands[3] != const0_rtx
2467         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2468       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2469     return \"\";
2470   }"
2471   [(set_attr "conds" "clob")
2472    (set_attr "length" "12")]
2476 ;; Shift and rotation insns
2478 (define_expand "ashlsi3"
2479   [(set (match_operand:SI            0 "s_register_operand" "")
2480         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2481                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2482   "TARGET_EITHER"
2483   "
2484   if (GET_CODE (operands[2]) == CONST_INT
2485       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2486     {
2487       emit_insn (gen_movsi (operands[0], const0_rtx));
2488       DONE;
2489     }
2490   "
2493 (define_insn "*thumb_ashlsi3"
2494   [(set (match_operand:SI            0 "register_operand" "=l,l")
2495         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2496                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2497   "TARGET_THUMB"
2498   "lsl\\t%0, %1, %2"
2499   [(set_attr "length" "2")]
2502 (define_expand "ashrsi3"
2503   [(set (match_operand:SI              0 "s_register_operand" "")
2504         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2505                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2506   "TARGET_EITHER"
2507   "
2508   if (GET_CODE (operands[2]) == CONST_INT
2509       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2510     operands[2] = GEN_INT (31);
2511   "
2514 (define_insn "*thumb_ashrsi3"
2515   [(set (match_operand:SI              0 "register_operand" "=l,l")
2516         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2517                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2518   "TARGET_THUMB"
2519   "asr\\t%0, %1, %2"
2520   [(set_attr "length" "2")]
2523 (define_expand "lshrsi3"
2524   [(set (match_operand:SI              0 "s_register_operand" "")
2525         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2526                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2527   "TARGET_EITHER"
2528   "
2529   if (GET_CODE (operands[2]) == CONST_INT
2530       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2531     {
2532       emit_insn (gen_movsi (operands[0], const0_rtx));
2533       DONE;
2534     }
2535   "
2538 (define_insn "*thumb_lshrsi3"
2539   [(set (match_operand:SI              0 "register_operand" "=l,l")
2540         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2541                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2542   "TARGET_THUMB"
2543   "lsr\\t%0, %1, %2"
2544   [(set_attr "length" "2")]
2547 (define_expand "rotlsi3"
2548   [(set (match_operand:SI              0 "s_register_operand" "")
2549         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2550                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2551   "TARGET_ARM"
2552   "
2553   if (GET_CODE (operands[2]) == CONST_INT)
2554     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2555   else
2556     {
2557       rtx reg = gen_reg_rtx (SImode);
2558       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2559       operands[2] = reg;
2560     }
2561   "
2564 (define_expand "rotrsi3"
2565   [(set (match_operand:SI              0 "s_register_operand" "")
2566         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2567                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2568   "TARGET_EITHER"
2569   "
2570   if (TARGET_ARM)
2571     {
2572       if (GET_CODE (operands[2]) == CONST_INT
2573           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2574         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2575     }
2576   else /* TARGET_THUMB */
2577     {
2578       if (GET_CODE (operands [2]) == CONST_INT)
2579         operands [2] = force_reg (SImode, operands[2]);
2580     }
2581   "
2584 (define_insn "*thumb_rotrsi3"
2585   [(set (match_operand:SI              0 "register_operand" "=l")
2586         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2587                      (match_operand:SI 2 "register_operand" "l")))]
2588   "TARGET_THUMB"
2589   "ror\\t%0, %0, %2"
2590   [(set_attr "length" "2")]
2593 (define_insn "*arm_shiftsi3"
2594   [(set (match_operand:SI   0 "s_register_operand" "=r")
2595         (match_operator:SI  3 "shift_operator"
2596          [(match_operand:SI 1 "s_register_operand"  "r")
2597           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2598   "TARGET_ARM"
2599   "mov%?\\t%0, %1%S3"
2600   [(set_attr "predicable" "yes")
2601    (set_attr "shift" "1")
2602    ]
2605 (define_insn "*shiftsi3_compare0"
2606   [(set (reg:CC_NOOV CC_REGNUM)
2607         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2608                           [(match_operand:SI 1 "s_register_operand" "r")
2609                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2610                          (const_int 0)))
2611    (set (match_operand:SI 0 "s_register_operand" "=r")
2612         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2613   "TARGET_ARM"
2614   "mov%?s\\t%0, %1%S3"
2615   [(set_attr "conds" "set")
2616    (set_attr "shift" "1")
2617    ]
2620 (define_insn "*shiftsi3_compare0_scratch"
2621   [(set (reg:CC_NOOV CC_REGNUM)
2622         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2623                           [(match_operand:SI 1 "s_register_operand" "r")
2624                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2625                          (const_int 0)))
2626    (clobber (match_scratch:SI 0 "=r"))]
2627   "TARGET_ARM"
2628   "mov%?s\\t%0, %1%S3"
2629   [(set_attr "conds" "set")
2630    (set_attr "shift" "1")
2631    ]
2634 (define_insn "*notsi_shiftsi"
2635   [(set (match_operand:SI 0 "s_register_operand" "=r")
2636         (not:SI (match_operator:SI 3 "shift_operator"
2637                  [(match_operand:SI 1 "s_register_operand" "r")
2638                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2639   "TARGET_ARM"
2640   "mvn%?\\t%0, %1%S3"
2641   [(set_attr "predicable" "yes")
2642    (set_attr "shift" "1")
2643    ]
2646 (define_insn "*notsi_shiftsi_compare0"
2647   [(set (reg:CC_NOOV CC_REGNUM)
2648         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2649                           [(match_operand:SI 1 "s_register_operand" "r")
2650                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2651                          (const_int 0)))
2652    (set (match_operand:SI 0 "s_register_operand" "=r")
2653         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2654   "TARGET_ARM"
2655   "mvn%?s\\t%0, %1%S3"
2656   [(set_attr "conds" "set")
2657    (set_attr "shift" "1")
2658    ]
2661 (define_insn "*not_shiftsi_compare0_scratch"
2662   [(set (reg:CC_NOOV CC_REGNUM)
2663         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2664                           [(match_operand:SI 1 "s_register_operand" "r")
2665                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2666                          (const_int 0)))
2667    (clobber (match_scratch:SI 0 "=r"))]
2668   "TARGET_ARM"
2669   "mvn%?s\\t%0, %1%S3"
2670   [(set_attr "conds" "set")
2671    (set_attr "shift" "1")
2672   ]
2675 ;; We don't really have extzv, but defining this using shifts helps
2676 ;; to reduce register pressure later on.
2678 (define_expand "extzv"
2679   [(set (match_dup 4)
2680         (ashift:SI (match_operand:SI   1 "register_operand" "")
2681                    (match_operand:SI   2 "const_int_operand" "")))
2682    (set (match_operand:SI              0 "register_operand" "")
2683         (lshiftrt:SI (match_dup 4)
2684                      (match_operand:SI 3 "const_int_operand" "")))]
2685   "TARGET_THUMB"
2686   "
2687   {
2688     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2689     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2690     
2691     operands[3] = GEN_INT (rshift);
2692     
2693     if (lshift == 0)
2694       {
2695         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2696         DONE;
2697       }
2698       
2699     operands[2] = GEN_INT (lshift);
2700     operands[4] = gen_reg_rtx (SImode);
2701   }"
2705 ;; Unary arithmetic insns
2707 (define_expand "negdi2"
2708  [(parallel
2709    [(set (match_operand:DI          0 "s_register_operand" "")
2710           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2711     (clobber (reg:CC CC_REGNUM))])]
2712   "TARGET_EITHER"
2713   "
2714   if (TARGET_THUMB)
2715     {
2716       if (GET_CODE (operands[1]) != REG)
2717         operands[1] = force_reg (SImode, operands[1]);
2718      }
2719   "
2722 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2723 ;; The second alternative is to allow the common case of a *full* overlap.
2724 (define_insn "*arm_negdi2"
2725   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2726         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2727    (clobber (reg:CC CC_REGNUM))]
2728   "TARGET_ARM"
2729   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2730   [(set_attr "conds" "clob")
2731    (set_attr "length" "8")]
2734 (define_insn "*thumb_negdi2"
2735   [(set (match_operand:DI         0 "register_operand" "=&l")
2736         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2737    (clobber (reg:CC CC_REGNUM))]
2738   "TARGET_THUMB"
2739   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2740   [(set_attr "length" "6")]
2743 (define_expand "negsi2"
2744   [(set (match_operand:SI         0 "s_register_operand" "")
2745         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2746   "TARGET_EITHER"
2747   ""
2750 (define_insn "*arm_negsi2"
2751   [(set (match_operand:SI         0 "s_register_operand" "=r")
2752         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2753   "TARGET_ARM"
2754   "rsb%?\\t%0, %1, #0"
2755   [(set_attr "predicable" "yes")]
2758 (define_insn "*thumb_negsi2"
2759   [(set (match_operand:SI         0 "register_operand" "=l")
2760         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2761   "TARGET_THUMB"
2762   "neg\\t%0, %1"
2763   [(set_attr "length" "2")]
2766 (define_insn "negsf2"
2767   [(set (match_operand:SF         0 "s_register_operand" "=f")
2768         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2769   "TARGET_ARM && TARGET_HARD_FLOAT"
2770   "mnf%?s\\t%0, %1"
2771   [(set_attr "type" "ffarith")
2772    (set_attr "predicable" "yes")]
2775 (define_insn "negdf2"
2776   [(set (match_operand:DF         0 "s_register_operand" "=f")
2777         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2778   "TARGET_ARM && TARGET_HARD_FLOAT"
2779   "mnf%?d\\t%0, %1"
2780   [(set_attr "type" "ffarith")
2781    (set_attr "predicable" "yes")]
2784 (define_insn "*negdf_esfdf"
2785   [(set (match_operand:DF 0 "s_register_operand" "=f")
2786         (neg:DF (float_extend:DF
2787                  (match_operand:SF 1 "s_register_operand" "f"))))]
2788   "TARGET_ARM && TARGET_HARD_FLOAT"
2789   "mnf%?d\\t%0, %1"
2790   [(set_attr "type" "ffarith")
2791    (set_attr "predicable" "yes")]
2794 (define_insn "negxf2"
2795   [(set (match_operand:XF 0 "s_register_operand" "=f")
2796         (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2797   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2798   "mnf%?e\\t%0, %1"
2799   [(set_attr "type" "ffarith")
2800    (set_attr "predicable" "yes")]
2803 ;; abssi2 doesn't really clobber the condition codes if a different register
2804 ;; is being set.  To keep things simple, assume during rtl manipulations that
2805 ;; it does, but tell the final scan operator the truth.  Similarly for
2806 ;; (neg (abs...))
2808 (define_insn "abssi2"
2809   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2810         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2811    (clobber (reg:CC CC_REGNUM))]
2812   "TARGET_ARM"
2813   "@
2814    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2815    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2816   [(set_attr "conds" "clob,*")
2817    (set_attr "shift" "1")
2818    ;; predicable can't be set based on the variant, so left as no
2819    (set_attr "length" "8")]
2822 (define_insn "*neg_abssi2"
2823   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2824         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2825    (clobber (reg:CC CC_REGNUM))]
2826   "TARGET_ARM"
2827   "@
2828    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2829    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2830   [(set_attr "conds" "clob,*")
2831    (set_attr "shift" "1")
2832    ;; predicable can't be set based on the variant, so left as no
2833    (set_attr "length" "8")]
2836 (define_insn "abssf2"
2837   [(set (match_operand:SF          0 "s_register_operand" "=f")
2838          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2839   "TARGET_ARM && TARGET_HARD_FLOAT"
2840   "abs%?s\\t%0, %1"
2841   [(set_attr "type" "ffarith")
2842    (set_attr "predicable" "yes")]
2845 (define_insn "absdf2"
2846   [(set (match_operand:DF         0 "s_register_operand" "=f")
2847         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2848   "TARGET_ARM && TARGET_HARD_FLOAT"
2849   "abs%?d\\t%0, %1"
2850   [(set_attr "type" "ffarith")
2851    (set_attr "predicable" "yes")]
2854 (define_insn "*absdf_esfdf"
2855   [(set (match_operand:DF 0 "s_register_operand" "=f")
2856         (abs:DF (float_extend:DF
2857                  (match_operand:SF 1 "s_register_operand" "f"))))]
2858   "TARGET_ARM && TARGET_HARD_FLOAT"
2859   "abs%?d\\t%0, %1"
2860   [(set_attr "type" "ffarith")
2861    (set_attr "predicable" "yes")]
2864 (define_insn "absxf2"
2865   [(set (match_operand:XF 0 "s_register_operand" "=f")
2866         (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2867   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2868   "abs%?e\\t%0, %1"
2869   [(set_attr "type" "ffarith")
2870    (set_attr "predicable" "yes")]
2873 (define_insn "sqrtsf2"
2874   [(set (match_operand:SF 0 "s_register_operand" "=f")
2875         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2876   "TARGET_ARM && TARGET_HARD_FLOAT"
2877   "sqt%?s\\t%0, %1"
2878   [(set_attr "type" "float_em")
2879    (set_attr "predicable" "yes")]
2882 (define_insn "sqrtdf2"
2883   [(set (match_operand:DF 0 "s_register_operand" "=f")
2884         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2885   "TARGET_ARM && TARGET_HARD_FLOAT"
2886   "sqt%?d\\t%0, %1"
2887   [(set_attr "type" "float_em")
2888    (set_attr "predicable" "yes")]
2891 (define_insn "*sqrtdf_esfdf"
2892   [(set (match_operand:DF 0 "s_register_operand" "=f")
2893         (sqrt:DF (float_extend:DF
2894                   (match_operand:SF 1 "s_register_operand" "f"))))]
2895   "TARGET_ARM && TARGET_HARD_FLOAT"
2896   "sqt%?d\\t%0, %1"
2897   [(set_attr "type" "float_em")
2898    (set_attr "predicable" "yes")]
2901 (define_insn "sqrtxf2"
2902   [(set (match_operand:XF 0 "s_register_operand" "=f")
2903         (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2904   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2905   "sqt%?e\\t%0, %1"
2906   [(set_attr "type" "float_em")
2907    (set_attr "predicable" "yes")]
2910 ;; SIN COS TAN and family are always emulated, so it's probably better
2911 ;; to always call a library function.
2912 ;(define_insn "sinsf2"
2913 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2914 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2915 ;                   UNSPEC_SIN))]
2916 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2917 ;  "sin%?s\\t%0, %1"
2918 ;[(set_attr "type" "float_em")])
2920 ;(define_insn "sindf2"
2921 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2922 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2923 ;                   UNSPEC_SIN))]
2924 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2925 ;  "sin%?d\\t%0, %1"
2926 ;[(set_attr "type" "float_em")])
2928 ;(define_insn "*sindf_esfdf"
2929 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2930 ;       (unspec:DF [(float_extend:DF
2931 ;                    (match_operand:SF 1 "s_register_operand" "f"))]
2932 ;                   UNSPEC_SIN))]
2933 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2934 ;  "sin%?d\\t%0, %1"
2935 ;[(set_attr "type" "float_em")])
2937 ;(define_insn "sinxf2"
2938 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2939 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2940 ;                  UNSPEC_SIN))]
2941 ;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2942 ;  "sin%?e\\t%0, %1"
2943 ;[(set_attr "type" "float_em")])
2945 ;(define_insn "cossf2"
2946 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2947 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2948 ;                  UNSPEC_COS))]
2949 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2950 ;  "cos%?s\\t%0, %1"
2951 ;[(set_attr "type" "float_em")])
2953 ;(define_insn "cosdf2"
2954 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2955 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2956 ;                  UNSPEC_COS))]
2957 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2958 ;  "cos%?d\\t%0, %1"
2959 ;[(set_attr "type" "float_em")])
2961 ;(define_insn "*cosdf_esfdf"
2962 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2963 ;       (unspec:DF [(float_extend:DF
2964 ;                    (match_operand:SF 1 "s_register_operand" "f"))]
2965 ;                  UNSPEC_COS))]
2966 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2967 ;  "cos%?d\\t%0, %1"
2968 ;[(set_attr "type" "float_em")])
2970 ;(define_insn "cosxf2"
2971 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2972 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2973 ;                  UNSEPC_COS))]
2974 ;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2975 ;  "cos%?e\\t%0, %1"
2976 ;[(set_attr "type" "float_em")])
2978 (define_insn_and_split "one_cmpldi2"
2979   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2980         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2981   "TARGET_ARM"
2982   "#"
2983   "TARGET_ARM && reload_completed"
2984   [(set (match_dup 0) (not:SI (match_dup 1)))
2985    (set (match_dup 2) (not:SI (match_dup 3)))]
2986   "
2987   {
2988     operands[2] = gen_highpart (SImode, operands[0]);
2989     operands[0] = gen_lowpart (SImode, operands[0]);
2990     operands[3] = gen_highpart (SImode, operands[1]);
2991     operands[1] = gen_lowpart (SImode, operands[1]);
2992   }"
2993   [(set_attr "length" "8")
2994    (set_attr "predicable" "yes")]
2997 (define_expand "one_cmplsi2"
2998   [(set (match_operand:SI         0 "s_register_operand" "")
2999         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3000   "TARGET_EITHER"
3001   ""
3004 (define_insn "*arm_one_cmplsi2"
3005   [(set (match_operand:SI         0 "s_register_operand" "=r")
3006         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3007   "TARGET_ARM"
3008   "mvn%?\\t%0, %1"
3009   [(set_attr "predicable" "yes")]
3012 (define_insn "*thumb_one_cmplsi2"
3013   [(set (match_operand:SI         0 "register_operand" "=l")
3014         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3015   "TARGET_THUMB"
3016   "mvn\\t%0, %1"
3017   [(set_attr "length" "2")]
3020 (define_insn "*notsi_compare0"
3021   [(set (reg:CC_NOOV CC_REGNUM)
3022         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3023                          (const_int 0)))
3024    (set (match_operand:SI 0 "s_register_operand" "=r")
3025         (not:SI (match_dup 1)))]
3026   "TARGET_ARM"
3027   "mvn%?s\\t%0, %1"
3028   [(set_attr "conds" "set")]
3031 (define_insn "*notsi_compare0_scratch"
3032   [(set (reg:CC_NOOV CC_REGNUM)
3033         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3034                          (const_int 0)))
3035    (clobber (match_scratch:SI 0 "=r"))]
3036   "TARGET_ARM"
3037   "mvn%?s\\t%0, %1"
3038   [(set_attr "conds" "set")]
3041 ;; Fixed <--> Floating conversion insns
3043 (define_insn "floatsisf2"
3044   [(set (match_operand:SF           0 "s_register_operand" "=f")
3045         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3046   "TARGET_ARM && TARGET_HARD_FLOAT"
3047   "flt%?s\\t%0, %1"
3048   [(set_attr "type" "r_2_f")
3049    (set_attr "predicable" "yes")]
3052 (define_insn "floatsidf2"
3053   [(set (match_operand:DF           0 "s_register_operand" "=f")
3054         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3055   "TARGET_ARM && TARGET_HARD_FLOAT"
3056   "flt%?d\\t%0, %1"
3057   [(set_attr "type" "r_2_f")
3058    (set_attr "predicable" "yes")]
3061 (define_insn "floatsixf2"
3062   [(set (match_operand:XF 0 "s_register_operand" "=f")
3063         (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3064   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3065   "flt%?e\\t%0, %1"
3066   [(set_attr "type" "r_2_f")
3067    (set_attr "predicable" "yes")]
3070 (define_insn "fix_truncsfsi2"
3071   [(set (match_operand:SI         0 "s_register_operand" "=r")
3072         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3073   "TARGET_ARM && TARGET_HARD_FLOAT"
3074   "fix%?z\\t%0, %1"
3075   [(set_attr "type" "f_2_r")
3076    (set_attr "predicable" "yes")]
3079 (define_insn "fix_truncdfsi2"
3080   [(set (match_operand:SI         0 "s_register_operand" "=r")
3081         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3082   "TARGET_ARM && TARGET_HARD_FLOAT"
3083   "fix%?z\\t%0, %1"
3084   [(set_attr "type" "f_2_r")
3085    (set_attr "predicable" "yes")]
3088 (define_insn "fix_truncxfsi2"
3089   [(set (match_operand:SI 0 "s_register_operand" "=r")
3090         (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3091   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3092   "fix%?z\\t%0, %1"
3093   [(set_attr "type" "f_2_r")
3094    (set_attr "predicable" "yes")]
3097 ;; Truncation insns
3099 (define_insn "truncdfsf2"
3100   [(set (match_operand:SF 0 "s_register_operand" "=f")
3101         (float_truncate:SF
3102          (match_operand:DF 1 "s_register_operand" "f")))]
3103   "TARGET_ARM && TARGET_HARD_FLOAT"
3104   "mvf%?s\\t%0, %1"
3105   [(set_attr "type" "ffarith")
3106    (set_attr "predicable" "yes")]
3109 (define_insn "truncxfsf2"
3110   [(set (match_operand:SF 0 "s_register_operand" "=f")
3111         (float_truncate:SF
3112          (match_operand:XF 1 "s_register_operand" "f")))]
3113   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3114   "mvf%?s\\t%0, %1"
3115   [(set_attr "type" "ffarith")
3116    (set_attr "predicable" "yes")]
3119 (define_insn "truncxfdf2"
3120   [(set (match_operand:DF 0 "s_register_operand" "=f")
3121         (float_truncate:DF
3122          (match_operand:XF 1 "s_register_operand" "f")))]
3123   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3124   "mvf%?d\\t%0, %1"
3125   [(set_attr "type" "ffarith")
3126    (set_attr "predicable" "yes")]
3129 ;; Zero and sign extension instructions.
3131 (define_insn "zero_extendsidi2"
3132   [(set (match_operand:DI 0 "s_register_operand" "=r")
3133         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3134   "TARGET_ARM"
3135   "*
3136     if (REGNO (operands[1])
3137         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3138       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3139     return \"mov%?\\t%R0, #0\";
3140   "
3141   [(set_attr "length" "8")
3142    (set_attr "predicable" "yes")]
3145 (define_insn "zero_extendqidi2"
3146   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3147         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3148   "TARGET_ARM"
3149   "@
3150    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3151    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3152   [(set_attr "length" "8")
3153    (set_attr "predicable" "yes")
3154    (set_attr "type" "*,load")
3155    (set_attr "pool_range" "*,4092")
3156    (set_attr "neg_pool_range" "*,4084")]
3159 (define_insn "extendsidi2"
3160   [(set (match_operand:DI 0 "s_register_operand" "=r")
3161         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3162   "TARGET_ARM"
3163   "*
3164     if (REGNO (operands[1])
3165         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3166       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3167     return \"mov%?\\t%R0, %Q0, asr #31\";
3168   "
3169   [(set_attr "length" "8")
3170    (set_attr "shift" "1")
3171    (set_attr "predicable" "yes")]
3174 (define_expand "zero_extendhisi2"
3175   [(set (match_dup 2)
3176         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3177                    (const_int 16)))
3178    (set (match_operand:SI 0 "s_register_operand" "")
3179         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3180   "TARGET_EITHER"
3181   "
3182   {
3183     if (TARGET_ARM)
3184       {
3185         if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3186           {
3187            /* Note: We do not have to worry about TARGET_MMU_TRAPS
3188               here because the insn below will generate an LDRH instruction
3189               rather than an LDR instruction, so we cannot get an unaligned
3190               word access.  */
3191             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3192                                     gen_rtx_ZERO_EXTEND (SImode,
3193                                                          operands[1])));
3194             DONE;
3195           }
3196         if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3197           {
3198             emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3199             DONE;
3200           }
3201         if (!s_register_operand (operands[1], HImode))
3202           operands[1] = copy_to_mode_reg (HImode, operands[1]);
3203         operands[1] = gen_lowpart (SImode, operands[1]);
3204         operands[2] = gen_reg_rtx (SImode);
3205       }
3206     else /* TARGET_THUMB */
3207       {
3208         if (GET_CODE (operands[1]) == MEM)
3209           {
3210             rtx tmp;
3212             tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3213             tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3214             emit_insn (tmp);
3215           }
3216         else
3217           {
3218             rtx ops[3];
3219             
3220             if (!s_register_operand (operands[1], HImode))
3221               operands[1] = copy_to_mode_reg (HImode, operands[1]);
3222             operands[1] = gen_lowpart (SImode, operands[1]);
3223             operands[2] = gen_reg_rtx (SImode);
3224             
3225             ops[0] = operands[2];
3226             ops[1] = operands[1];
3227             ops[2] = GEN_INT (16);
3228             
3229             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3230                                     gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3232             ops[0] = operands[0];
3233             ops[1] = operands[2];
3234             ops[2] = GEN_INT (16);
3236             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3237                                     gen_rtx_LSHIFTRT (SImode, ops[1],
3238                                                       ops[2])));
3239           }
3240         DONE; 
3241       }
3242   }"
3245 (define_insn "*thumb_zero_extendhisi2"
3246   [(set (match_operand:SI                 0 "register_operand" "=l")
3247         (zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3248   "TARGET_THUMB"
3249   "*
3250   rtx mem = XEXP (operands[1], 0);
3252   if (GET_CODE (mem) == CONST)
3253     mem = XEXP (mem, 0);
3254     
3255   if (GET_CODE (mem) == LABEL_REF)
3256     return \"ldr\\t%0, %1\";
3257     
3258   if (GET_CODE (mem) == PLUS)
3259     {
3260       rtx a = XEXP (mem, 0);
3261       rtx b = XEXP (mem, 1);
3263       /* This can happen due to bugs in reload.  */
3264       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3265         {
3266           rtx ops[2];
3267           ops[0] = operands[0];
3268           ops[1] = a;
3269       
3270           output_asm_insn (\"mov        %0, %1\", ops);
3272           XEXP (mem, 0) = operands[0];
3273        }
3275       else if (   GET_CODE (a) == LABEL_REF
3276                && GET_CODE (b) == CONST_INT)
3277         return \"ldr\\t%0, %1\";
3278     }
3279     
3280   return \"ldrh\\t%0, %1\";
3281   "
3282   [(set_attr "length" "4")
3283    (set_attr "type" "load")
3284    (set_attr "pool_range" "60")]
3287 (define_insn "*arm_zero_extendhisi2"
3288   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3289         (zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3290   "TARGET_ARM && arm_arch4"
3291   "ldr%?h\\t%0, %1"
3292   [(set_attr "type" "load")
3293    (set_attr "predicable" "yes")
3294    (set_attr "pool_range" "256")
3295    (set_attr "neg_pool_range" "244")]
3298 (define_split
3299   [(set (match_operand:SI 0 "s_register_operand" "")
3300         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3301    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3302   "TARGET_ARM && (!arm_arch4)"
3303   [(set (match_dup 2) (match_dup 1))
3304    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3305   "
3306   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3307     FAIL;
3308   "
3311 (define_split
3312   [(set (match_operand:SI 0 "s_register_operand" "")
3313         (match_operator:SI 3 "shiftable_operator"
3314          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3315           (match_operand:SI 4 "s_register_operand" "")]))
3316    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3317   "TARGET_ARM && (!arm_arch4)"
3318   [(set (match_dup 2) (match_dup 1))
3319    (set (match_dup 0)
3320         (match_op_dup 3
3321          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3322   "
3323   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3324     FAIL;
3325   "
3328 (define_expand "zero_extendqisi2"
3329   [(set (match_operand:SI 0 "s_register_operand" "")
3330         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3331   "TARGET_EITHER"
3332   "
3333   if (GET_CODE (operands[1]) != MEM)
3334     {
3335       if (TARGET_ARM)
3336         {
3337           emit_insn (gen_andsi3 (operands[0],
3338                                  gen_lowpart (SImode, operands[1]),
3339                                  GEN_INT (255)));
3340         }
3341       else /* TARGET_THUMB */
3342         {
3343           rtx temp = gen_reg_rtx (SImode);
3344           rtx ops[3];
3345           
3346           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3347           operands[1] = gen_lowpart (SImode, operands[1]);
3349           ops[0] = temp;
3350           ops[1] = operands[1];
3351           ops[2] = GEN_INT (24);
3353           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3354                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3355           
3356           ops[0] = operands[0];
3357           ops[1] = temp;
3358           ops[2] = GEN_INT (24);
3360           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3361                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3362         }
3363       DONE;
3364     }
3365   "
3368 (define_insn "*thumb_zero_extendqisi2"
3369   [(set (match_operand:SI                 0 "register_operand" "=l")
3370         (zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3371   "TARGET_THUMB"
3372   "ldrb\\t%0, %1"
3373   [(set_attr "length" "2")
3374    (set_attr "type" "load")
3375    (set_attr "pool_range" "32")]
3378 (define_insn "*arm_zero_extendqisi2"
3379   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3380         (zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3381   "TARGET_ARM"
3382   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3383   [(set_attr "type" "load")
3384    (set_attr "predicable" "yes")
3385    (set_attr "pool_range" "4096")
3386    (set_attr "neg_pool_range" "4084")]
3389 (define_split
3390   [(set (match_operand:SI 0 "s_register_operand" "")
3391         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3392    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3393   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3394   [(set (match_dup 2) (match_dup 1))
3395    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3396   ""
3399 (define_insn "*compareqi_eq0"
3400   [(set (reg:CC_Z CC_REGNUM)
3401         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3402                          (const_int 0)))]
3403   "TARGET_ARM"
3404   "tst\\t%0, #255"
3405   [(set_attr "conds" "set")]
3408 (define_expand "extendhisi2"
3409   [(set (match_dup 2)
3410         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3411                    (const_int 16)))
3412    (set (match_operand:SI 0 "s_register_operand" "")
3413         (ashiftrt:SI (match_dup 2)
3414                      (const_int 16)))]
3415   "TARGET_EITHER"
3416   "
3417   {
3418     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3419       {
3420        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3421           here because the insn below will generate an LDRH instruction
3422           rather than an LDR instruction, so we cannot get an unaligned
3423           word access.  */
3424         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3425                    gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3426         DONE;
3427       }
3429     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3430       {
3431         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3432         DONE;
3433       }
3434     if (!s_register_operand (operands[1], HImode))
3435       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3436     operands[1] = gen_lowpart (SImode, operands[1]);
3437     operands[2] = gen_reg_rtx (SImode);
3439     if (TARGET_THUMB)
3440       {
3441         rtx ops[3];
3442         
3443         ops[0] = operands[2];
3444         ops[1] = operands[1];
3445         ops[2] = GEN_INT (16);
3446         
3447         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3448                                 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3449             
3450         ops[0] = operands[0];
3451         ops[1] = operands[2];
3452         ops[2] = GEN_INT (16);
3453         
3454         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3455                                 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3456         
3457         DONE;
3458       }
3459   }"
3462 (define_insn "*thumb_extendhisi2_insn"
3463   [(set (match_operand:SI                 0 "register_operand" "=l")
3464         (sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3465    (clobber (match_scratch:SI             2                   "=&l"))]
3466   "TARGET_THUMB"
3467   "*
3468   {
3469     rtx ops[4];
3470     rtx mem = XEXP (operands[1], 0);
3472     /* This code used to try to use 'V', and fix the address only if it was
3473        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3474        range of QImode offsets, and offsettable_address_p does a QImode
3475        address check.  */
3476        
3477     if (GET_CODE (mem) == CONST)
3478       mem = XEXP (mem, 0);
3479     
3480     if (GET_CODE (mem) == LABEL_REF)
3481       return \"ldr\\t%0, %1\";
3482     
3483     if (GET_CODE (mem) == PLUS)
3484       {
3485         rtx a = XEXP (mem, 0);
3486         rtx b = XEXP (mem, 1);
3488         if (GET_CODE (a) == LABEL_REF
3489             && GET_CODE (b) == CONST_INT)
3490           return \"ldr\\t%0, %1\";
3492         if (GET_CODE (b) == REG)
3493           return \"ldrsh\\t%0, %1\";
3494           
3495         ops[1] = a;
3496         ops[2] = b;
3497       }
3498     else
3499       {
3500         ops[1] = mem;
3501         ops[2] = const0_rtx;
3502       }
3503       
3504     if (GET_CODE (ops[1]) != REG)
3505       {
3506         debug_rtx (ops[1]);
3507         abort ();
3508       }
3510     ops[0] = operands[0];
3511     ops[3] = operands[2];
3512     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3513     return \"\";
3514   }"
3515   [(set_attr "length" "4")
3516    (set_attr "type" "load")
3517    (set_attr "pool_range" "1020")]
3520 (define_expand "extendhisi2_mem"
3521   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3522    (set (match_dup 3)
3523         (zero_extend:SI (match_dup 7)))
3524    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3525    (set (match_operand:SI 0 "" "")
3526         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3527   "TARGET_ARM"
3528   "
3529   {
3530     rtx mem1, mem2;
3531     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3533     mem1 = gen_rtx_MEM (QImode, addr);
3534     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3535     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3536     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3537     operands[0] = gen_lowpart (SImode, operands[0]);
3538     operands[1] = mem1;
3539     operands[2] = gen_reg_rtx (SImode);
3540     operands[3] = gen_reg_rtx (SImode);
3541     operands[6] = gen_reg_rtx (SImode);
3542     operands[7] = mem2;
3544     if (BYTES_BIG_ENDIAN)
3545       {
3546         operands[4] = operands[2];
3547         operands[5] = operands[3];
3548       }
3549     else
3550       {
3551         operands[4] = operands[3];
3552         operands[5] = operands[2];
3553       }
3554   }"
3557 (define_insn "*arm_extendhisi_insn"
3558   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3559         (sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3560   "TARGET_ARM && arm_arch4"
3561   "ldr%?sh\\t%0, %1"
3562   [(set_attr "type" "load")
3563    (set_attr "predicable" "yes")
3564    (set_attr "pool_range" "256")
3565    (set_attr "neg_pool_range" "244")]
3568 (define_split
3569   [(set (match_operand:SI                 0 "s_register_operand" "")
3570         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3571    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3572   "TARGET_ARM && (!arm_arch4)"
3573   [(set (match_dup 2) (match_dup 1))
3574    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3575   "
3576   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3577     FAIL;
3578   "
3581 (define_split
3582   [(set (match_operand:SI                   0 "s_register_operand" "")
3583         (match_operator:SI                  3 "shiftable_operator"
3584          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3585           (match_operand:SI                 4 "s_register_operand" "")]))
3586    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3587   "TARGET_ARM && (!arm_arch4)"
3588   [(set (match_dup 2) (match_dup 1))
3589    (set (match_dup 0)
3590         (match_op_dup 3
3591          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3592   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3593      FAIL;
3594   "
3597 (define_expand "extendqihi2"
3598   [(set (match_dup 2)
3599         (ashift:SI (match_operand:QI 1 "general_operand" "")
3600                    (const_int 24)))
3601    (set (match_operand:HI 0 "s_register_operand" "")
3602         (ashiftrt:SI (match_dup 2)
3603                      (const_int 24)))]
3604   "TARGET_ARM"
3605   "
3606   {
3607     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3608       {
3609         emit_insn (gen_rtx_SET (VOIDmode,
3610                                 operands[0],
3611                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3612         DONE;
3613       }
3614     if (!s_register_operand (operands[1], QImode))
3615       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3616     operands[0] = gen_lowpart (SImode, operands[0]);
3617     operands[1] = gen_lowpart (SImode, operands[1]);
3618     operands[2] = gen_reg_rtx (SImode);
3619   }"
3622 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3623 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3624 (define_insn "*extendqihi_insn"
3625   [(set (match_operand:HI                 0 "s_register_operand" "=r")
3626         (sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3627   "TARGET_ARM && arm_arch4"
3628   "*
3629   /* If the address is invalid, this will split the instruction into two. */
3630   if (bad_signed_byte_operand (operands[1], VOIDmode))
3631     return \"#\";
3632   return \"ldr%?sb\\t%0, %1\";
3633   "
3634   [(set_attr "type" "load")
3635    (set_attr "predicable" "yes")
3636    (set_attr "length" "8")
3637    (set_attr "pool_range" "256")
3638    (set_attr "neg_pool_range" "244")]
3641 (define_split
3642   [(set (match_operand:HI 0 "s_register_operand" "")
3643         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3644   "TARGET_ARM && arm_arch4 && reload_completed"
3645   [(set (match_dup 3) (match_dup 1))
3646    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3647   "
3648   {
3649     HOST_WIDE_INT offset;
3651     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3652     operands[2] = gen_rtx_MEM (QImode, operands[3]);
3653     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3654     operands[1] = XEXP (operands[1], 0);
3655     if (GET_CODE (operands[1]) == PLUS
3656         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3657         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3658              || const_ok_for_arm (-offset)))
3659       {
3660         HOST_WIDE_INT low = (offset > 0
3661                              ? (offset & 0xff) : -((-offset) & 0xff));
3662         XEXP (operands[2], 0) = plus_constant (operands[3], low);
3663         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3664       }
3665     /* Ensure the sum is in correct canonical form */
3666     else if (GET_CODE (operands[1]) == PLUS
3667              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3668              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3669       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3670                                            XEXP (operands[1], 1),
3671                                            XEXP (operands[1], 0));
3672   }"
3675 (define_expand "extendqisi2"
3676   [(set (match_dup 2)
3677         (ashift:SI (match_operand:QI 1 "general_operand" "")
3678                    (const_int 24)))
3679    (set (match_operand:SI 0 "s_register_operand" "")
3680         (ashiftrt:SI (match_dup 2)
3681                      (const_int 24)))]
3682   "TARGET_EITHER"
3683   "
3684   {
3685     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3686       {
3687         emit_insn (gen_rtx_SET (VOIDmode,
3688                                 operands[0],
3689                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3690         DONE;
3691       }
3692     if (!s_register_operand (operands[1], QImode))
3693       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3694     operands[1] = gen_lowpart (SImode, operands[1]);
3695     operands[2] = gen_reg_rtx (SImode);
3696     
3697     if (TARGET_THUMB)
3698       {
3699         rtx ops[3];
3700         
3701         ops[0] = operands[2];
3702         ops[1] = operands[1];
3703         ops[2] = GEN_INT (24);
3704         
3705         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3706                    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3708         ops[0] = operands[0];
3709         ops[1] = operands[2];
3710         ops[2] = GEN_INT (24);
3711         
3712         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3713                    gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3714         
3715         DONE;
3716       }
3717   }"
3720 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3721 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3722 (define_insn "*arm_extendqisi_insn"
3723   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3724         (sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3725   "TARGET_ARM && arm_arch4"
3726   "*
3727   /* If the address is invalid, this will split the instruction into two. */
3728   if (bad_signed_byte_operand (operands[1], VOIDmode))
3729     return \"#\";
3730   return \"ldr%?sb\\t%0, %1\";
3731   "
3732   [(set_attr "type" "load")
3733    (set_attr "predicable" "yes")
3734    (set_attr "length" "8")
3735    (set_attr "pool_range" "256")
3736    (set_attr "neg_pool_range" "244")]
3739 (define_split
3740   [(set (match_operand:SI 0 "s_register_operand" "")
3741         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3742   "TARGET_ARM && arm_arch4 && reload_completed"
3743   [(set (match_dup 0) (match_dup 1))
3744    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3745   "
3746   {
3747     HOST_WIDE_INT offset;
3749     operands[2] = gen_rtx_MEM (QImode, operands[0]);
3750     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3751     operands[1] = XEXP (operands[1], 0);
3752     if (GET_CODE (operands[1]) == PLUS
3753         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3754         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3755              || const_ok_for_arm (-offset)))
3756       {
3757         HOST_WIDE_INT low = (offset > 0
3758                              ? (offset & 0xff) : -((-offset) & 0xff));
3759         XEXP (operands[2], 0) = plus_constant (operands[0], low);
3760         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3761       }
3762     /* Ensure the sum is in correct canonical form */
3763     else if (GET_CODE (operands[1]) == PLUS
3764              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3765              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3766       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3767                                            XEXP (operands[1], 1),
3768                                            XEXP (operands[1], 0));
3769   }"
3772 (define_insn "*thumb_extendqisi2_insn"
3773   [(set (match_operand:SI                 0 "register_operand" "=l,l")
3774         (sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3775   "TARGET_THUMB"
3776   "*
3777   {
3778     rtx ops[3];
3779     rtx mem = XEXP (operands[1], 0);
3780     
3781     if (GET_CODE (mem) == CONST)
3782       mem = XEXP (mem, 0);
3783     
3784     if (GET_CODE (mem) == LABEL_REF)
3785       return \"ldr\\t%0, %1\";
3787     if (GET_CODE (mem) == PLUS
3788         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3789       return \"ldr\\t%0, %1\";
3790       
3791     if (which_alternative == 0)
3792       return \"ldrsb\\t%0, %1\";
3793       
3794     ops[0] = operands[0];
3795     
3796     if (GET_CODE (mem) == PLUS)
3797       {
3798         rtx a = XEXP (mem, 0);
3799         rtx b = XEXP (mem, 1);
3800         
3801         ops[1] = a;
3802         ops[2] = b;
3804         if (GET_CODE (a) == REG)
3805           {
3806             if (GET_CODE (b) == REG)
3807               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3808             else if (REGNO (a) == REGNO (ops[0]))
3809               {
3810                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3811                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3812                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3813               }
3814             else
3815               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3816           }
3817         else if (GET_CODE (b) != REG)
3818           abort ();
3819         else
3820           {
3821             if (REGNO (b) == REGNO (ops[0]))
3822               {
3823                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3824                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3825                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3826               }
3827             else
3828               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3829           }
3830       }
3831     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3832       {
3833         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3834         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3835         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3836       }
3837     else
3838       {
3839         ops[1] = mem;
3840         ops[2] = const0_rtx;
3841         
3842         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3843       }
3844     return \"\";
3845   }"
3846   [(set_attr "length" "2,6")
3847    (set_attr "type" "load,load")
3848    (set_attr "pool_range" "32,32")]
3851 (define_insn "extendsfdf2"
3852   [(set (match_operand:DF                  0 "s_register_operand" "=f")
3853         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "f")))]
3854   "TARGET_ARM && TARGET_HARD_FLOAT"
3855   "mvf%?d\\t%0, %1"
3856   [(set_attr "type" "ffarith")
3857    (set_attr "predicable" "yes")]
3860 (define_insn "extendsfxf2"
3861   [(set (match_operand:XF 0 "s_register_operand" "=f")
3862         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3863   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3864   "mvf%?e\\t%0, %1"
3865   [(set_attr "type" "ffarith")
3866    (set_attr "predicable" "yes")]
3869 (define_insn "extenddfxf2"
3870   [(set (match_operand:XF 0 "s_register_operand" "=f")
3871         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3872   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3873   "mvf%?e\\t%0, %1"
3874   [(set_attr "type" "ffarith")
3875    (set_attr "predicable" "yes")]
3879 ;; Move insns (including loads and stores)
3881 ;; XXX Just some ideas about movti.
3882 ;; I don't think these are a good idea on the arm, there just aren't enough
3883 ;; registers
3884 ;;(define_expand "loadti"
3885 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3886 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3887 ;;  "" "")
3889 ;;(define_expand "storeti"
3890 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3891 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3892 ;;  "" "")
3894 ;;(define_expand "movti"
3895 ;;  [(set (match_operand:TI 0 "general_operand" "")
3896 ;;      (match_operand:TI 1 "general_operand" ""))]
3897 ;;  ""
3898 ;;  "
3900 ;;  rtx insn;
3902 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3903 ;;    operands[1] = copy_to_reg (operands[1]);
3904 ;;  if (GET_CODE (operands[0]) == MEM)
3905 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3906 ;;  else if (GET_CODE (operands[1]) == MEM)
3907 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3908 ;;  else
3909 ;;    FAIL;
3911 ;;  emit_insn (insn);
3912 ;;  DONE;
3913 ;;}")
3915 ;; Recognise garbage generated above.
3917 ;;(define_insn ""
3918 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3919 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3920 ;;  ""
3921 ;;  "*
3922 ;;  {
3923 ;;    register mem = (which_alternative < 3);
3924 ;;    register const char *template;
3926 ;;    operands[mem] = XEXP (operands[mem], 0);
3927 ;;    switch (which_alternative)
3928 ;;      {
3929 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3930 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3931 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3932 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3933 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3934 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3935 ;;      }
3936 ;;    output_asm_insn (template, operands);
3937 ;;    return \"\";
3938 ;;  }")
3940 (define_expand "movdi"
3941   [(set (match_operand:DI 0 "general_operand" "")
3942         (match_operand:DI 1 "general_operand" ""))]
3943   "TARGET_EITHER"
3944   "
3945   if (TARGET_THUMB)
3946     {
3947       if (!no_new_pseudos)
3948         {
3949           if (GET_CODE (operands[0]) != REG)
3950             operands[1] = force_reg (DImode, operands[1]);
3951         }
3952     }
3953   "
3956 (define_insn "*arm_movdi"
3957   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3958         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3959   "TARGET_ARM"
3960   "*
3961   return (output_move_double (operands));
3962   "
3963   [(set_attr "length" "8")
3964    (set_attr "type" "*,load,store2")
3965    (set_attr "pool_range" "*,1020,*")
3966    (set_attr "neg_pool_range" "*,1008,*")]
3969 ;;; ??? This should have alternatives for constants.
3970 ;;; ??? This was originally identical to the movdf_insn pattern.
3971 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3972 ;;; thumb_reorg with a memory reference.
3973 (define_insn "*thumb_movdi_insn"
3974   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3975         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3976   "TARGET_THUMB
3977    && (   register_operand (operands[0], DImode)
3978        || register_operand (operands[1], DImode))"
3979   "*
3980   {
3981   switch (which_alternative)
3982     {
3983     default:
3984     case 0:
3985       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3986         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3987       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3988     case 1:
3989       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3990     case 2:
3991       operands[1] = GEN_INT (- INTVAL (operands[1]));
3992       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3993     case 3:
3994       return \"ldmia\\t%1, {%0, %H0}\";
3995     case 4:
3996       return \"stmia\\t%0, {%1, %H1}\";
3997     case 5:
3998       return thumb_load_double_from_address (operands);
3999     case 6:
4000       operands[2] = gen_rtx (MEM, SImode,
4001                              plus_constant (XEXP (operands[0], 0), 4));
4002       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4003       return \"\";
4004     case 7:
4005       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4006         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4007       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4008     }
4009   }"
4010   [(set_attr "length" "4,4,6,2,2,6,4,4")
4011    (set_attr "type" "*,*,*,load,store2,load,store2,*")
4012    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4015 (define_expand "movsi"
4016   [(set (match_operand:SI 0 "general_operand" "")
4017         (match_operand:SI 1 "general_operand" ""))]
4018   "TARGET_EITHER"
4019   "
4020   if (TARGET_ARM)
4021     {
4022       /* Everything except mem = const or mem = mem can be done easily */
4023       if (GET_CODE (operands[0]) == MEM)
4024         operands[1] = force_reg (SImode, operands[1]);
4025       if (GET_CODE (operands[1]) == CONST_INT
4026           && !(const_ok_for_arm (INTVAL (operands[1]))
4027                || const_ok_for_arm (~INTVAL (operands[1]))))
4028         {
4029            arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4030                               NULL_RTX,
4031                               (no_new_pseudos ? 0
4032                                : preserve_subexpressions_p ()));
4033           DONE;
4034         }
4035     }
4036   else /* TARGET_THUMB.... */
4037     {
4038       if (!no_new_pseudos)
4039         {
4040           if (GET_CODE (operands[0]) != REG)
4041             operands[1] = force_reg (SImode, operands[1]);
4042         }
4043     }
4044     
4045   if (flag_pic
4046       && (CONSTANT_P (operands[1])
4047          || symbol_mentioned_p (operands[1])
4048          || label_mentioned_p (operands[1])))
4049     operands[1] = legitimize_pic_address (operands[1], SImode,
4050                                           (no_new_pseudos ? operands[0] : 0));
4051   "
4054 (define_insn "*arm_movsi_insn"
4055   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4056         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4057   "TARGET_ARM
4058    && (   register_operand (operands[0], SImode)
4059        || register_operand (operands[1], SImode))"
4060   "@
4061    mov%?\\t%0, %1
4062    mvn%?\\t%0, #%B1
4063    ldr%?\\t%0, %1
4064    str%?\\t%1, %0"
4065   [(set_attr "type" "*,*,load,store1")
4066    (set_attr "predicable" "yes")
4067    (set_attr "pool_range" "*,*,4096,*")
4068    (set_attr "neg_pool_range" "*,*,4084,*")]
4071 (define_split
4072   [(set (match_operand:SI 0 "s_register_operand" "")
4073         (match_operand:SI 1 "const_int_operand" ""))]
4074   "TARGET_ARM
4075   && (!(const_ok_for_arm (INTVAL (operands[1]))
4076         || const_ok_for_arm (~INTVAL (operands[1]))))"
4077   [(clobber (const_int 0))]
4078   "
4079   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4080                       NULL_RTX, 0);
4081   DONE;
4082   "
4085 (define_insn "*thumb_movsi_insn"
4086   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4087         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4088   "TARGET_THUMB
4089    && (   register_operand (operands[0], SImode) 
4090        || register_operand (operands[1], SImode))"
4091   "@
4092    mov  %0, %1
4093    mov  %0, %1
4094    #
4095    #
4096    ldmia\\t%1, {%0}
4097    stmia\\t%0, {%1}
4098    ldr\\t%0, %1
4099    str\\t%1, %0
4100    mov\\t%0, %1"
4101   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4102    (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4103    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4106 (define_split 
4107   [(set (match_operand:SI 0 "register_operand" "")
4108         (match_operand:SI 1 "const_int_operand" ""))]
4109   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4110   [(set (match_dup 0) (match_dup 1))
4111    (set (match_dup 0) (neg:SI (match_dup 0)))]
4112   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4115 (define_split 
4116   [(set (match_operand:SI 0 "register_operand" "")
4117         (match_operand:SI 1 "const_int_operand" ""))]
4118   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4119   [(set (match_dup 0) (match_dup 1))
4120    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4121   "
4122   {
4123     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4124     unsigned HOST_WIDE_INT mask = 0xff;
4125     int i;
4126     
4127     for (i = 0; i < 25; i++)
4128       if ((val & (mask << i)) == val)
4129         break;
4131     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4132     if (i == 0)
4133       FAIL;
4135     operands[1] = GEN_INT (val >> i);
4136     operands[2] = GEN_INT (i);
4137   }"
4140 ;; When generating pic, we need to load the symbol offset into a register.
4141 ;; So that the optimizer does not confuse this with a normal symbol load
4142 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4143 ;; since that is the only type of relocation we can use.
4145 ;; The rather odd constraints on the following are to force reload to leave
4146 ;; the insn alone, and to force the minipool generation pass to then move
4147 ;; the GOT symbol to memory.
4149 (define_insn "pic_load_addr_arm"
4150   [(set (match_operand:SI 0 "s_register_operand" "=r")
4151         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4152   "TARGET_ARM && flag_pic"
4153   "ldr%?\\t%0, %1"
4154   [(set_attr "type" "load")
4155    (set (attr "pool_range")     (const_int 4096))
4156    (set (attr "neg_pool_range") (const_int 4084))]
4159 (define_insn "pic_load_addr_thumb"
4160   [(set (match_operand:SI 0 "s_register_operand" "=l")
4161         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4162   "TARGET_THUMB && flag_pic"
4163   "ldr\\t%0, %1"
4164   [(set_attr "type" "load")
4165    (set (attr "pool_range") (const_int 1024))]
4168 ;; This variant is used for AOF assembly, since it needs to mention the
4169 ;; pic register in the rtl.
4170 (define_expand "pic_load_addr_based"
4171   [(set (match_operand:SI 0 "s_register_operand" "=r")
4172         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4173   "TARGET_ARM && flag_pic"
4174   "operands[2] = pic_offset_table_rtx;"
4177 (define_insn "*pic_load_addr_based_insn"
4178   [(set (match_operand:SI 0 "s_register_operand" "=r")
4179         (unspec:SI [(match_operand 1 "" "")
4180                     (match_operand 2 "s_register_operand" "r")]
4181                    UNSPEC_PIC_SYM))]
4182   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4183   "*
4184 #ifdef AOF_ASSEMBLER
4185   operands[1] = aof_pic_entry (operands[1]);
4186 #endif
4187   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4188   return \"\";
4189   "
4190   [(set_attr "type" "load")
4191    (set (attr "pool_range")
4192         (if_then_else (eq_attr "is_thumb" "yes")
4193                       (const_int 1024)
4194                       (const_int 4096)))
4195    (set (attr "neg_pool_range")
4196         (if_then_else (eq_attr "is_thumb" "yes")
4197                       (const_int 0)
4198                       (const_int 4084)))]
4201 (define_insn "pic_add_dot_plus_four"
4202   [(set (match_operand:SI 0 "register_operand" "+r")
4203         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4204    (use (label_ref (match_operand 1 "" "")))]
4205   "TARGET_THUMB && flag_pic"
4206   "*
4207   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4208                              CODE_LABEL_NUMBER (operands[1]));
4209   return \"add\\t%0, %|pc\";
4210   "
4211   [(set_attr "length" "2")]
4214 (define_insn "pic_add_dot_plus_eight"
4215   [(set (match_operand:SI 0 "register_operand" "+r")
4216         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4217    (use (label_ref (match_operand 1 "" "")))]
4218   "TARGET_ARM && flag_pic"
4219   "*
4220     ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4221                                CODE_LABEL_NUMBER (operands[1]));
4222     return \"add%?\\t%0, %|pc, %0\";
4223   "
4224   [(set_attr "predicable" "yes")]
4227 (define_expand "builtin_setjmp_receiver"
4228   [(label_ref (match_operand 0 "" ""))]
4229   "flag_pic"
4230   "
4232   arm_finalize_pic (0);
4233   DONE;
4236 ;; If copying one reg to another we can set the condition codes according to
4237 ;; its value.  Such a move is common after a return from subroutine and the
4238 ;; result is being tested against zero.
4240 (define_insn "*movsi_compare0"
4241   [(set (reg:CC CC_REGNUM)
4242         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4243                     (const_int 0)))
4244    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4245         (match_dup 1))]
4246   "TARGET_ARM"
4247   "@
4248    cmp%?\\t%0, #0
4249    sub%?s\\t%0, %1, #0"
4250   [(set_attr "conds" "set")]
4253 ;; Subroutine to store a half word from a register into memory.
4254 ;; Operand 0 is the source register (HImode)
4255 ;; Operand 1 is the destination address in a register (SImode)
4257 ;; In both this routine and the next, we must be careful not to spill
4258 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4259 ;; can generate unrecognizable rtl.
4261 (define_expand "storehi"
4262   [;; store the low byte
4263    (set (match_operand 1 "" "") (match_dup 3))
4264    ;; extract the high byte
4265    (set (match_dup 2)
4266         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4267    ;; store the high byte
4268    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
4269   "TARGET_ARM"
4270   "
4271   {
4272     rtx op1 = operands[1];
4273     rtx addr = XEXP (op1, 0);
4274     enum rtx_code code = GET_CODE (addr);
4276     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4277         || code == MINUS)
4278       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4280     operands[4] = adjust_address (op1, QImode, 1);
4281     operands[1] = adjust_address (operands[1], QImode, 0);
4282     operands[3] = gen_lowpart (QImode, operands[0]);
4283     operands[0] = gen_lowpart (SImode, operands[0]);
4284     operands[2] = gen_reg_rtx (SImode); 
4285   }"
4288 (define_expand "storehi_bigend"
4289   [(set (match_dup 4) (match_dup 3))
4290    (set (match_dup 2)
4291         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4292    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4293   "TARGET_ARM"
4294   "
4295   {
4296     rtx op1 = operands[1];
4297     rtx addr = XEXP (op1, 0);
4298     enum rtx_code code = GET_CODE (addr);
4300     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4301         || code == MINUS)
4302       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4304     operands[4] = adjust_address (op1, QImode, 1);
4305     operands[1] = adjust_address (operands[1], QImode, 0);
4306     operands[3] = gen_lowpart (QImode, operands[0]);
4307     operands[0] = gen_lowpart (SImode, operands[0]);
4308     operands[2] = gen_reg_rtx (SImode);
4309   }"
4312 ;; Subroutine to store a half word integer constant into memory.
4313 (define_expand "storeinthi"
4314   [(set (match_operand 0 "" "")
4315         (subreg:QI (match_operand 1 "" "") 0))
4316    (set (match_dup 3) (match_dup 2))]
4317   "TARGET_ARM"
4318   "
4319   {
4320     HOST_WIDE_INT value = INTVAL (operands[1]);
4321     rtx addr = XEXP (operands[0], 0);
4322     rtx op0 = operands[0];
4323     enum rtx_code code = GET_CODE (addr);
4325     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4326         || code == MINUS)
4327       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4329     operands[1] = gen_reg_rtx (SImode);
4330     if (BYTES_BIG_ENDIAN)
4331       {
4332         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4333         if ((value & 255) == ((value >> 8) & 255))
4334           operands[2] = operands[1];
4335         else
4336           {
4337             operands[2] = gen_reg_rtx (SImode);
4338             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4339           }
4340       }
4341     else
4342       {
4343         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4344         if ((value & 255) == ((value >> 8) & 255))
4345           operands[2] = operands[1];
4346         else
4347           {
4348             operands[2] = gen_reg_rtx (SImode);
4349             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4350           }
4351       }
4353     operands[3] = adjust_address (op0, QImode, 1);
4354     operands[0] = adjust_address (operands[0], QImode, 0);
4355     operands[2] = gen_lowpart (QImode, operands[2]);
4356   }"
4359 (define_expand "storehi_single_op"
4360   [(set (match_operand:HI 0 "memory_operand" "")
4361         (match_operand:HI 1 "general_operand" ""))]
4362   "TARGET_ARM && arm_arch4"
4363   "
4364   if (!s_register_operand (operands[1], HImode))
4365     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4366   "
4369 (define_expand "movhi"
4370   [(set (match_operand:HI 0 "general_operand" "")
4371         (match_operand:HI 1 "general_operand" ""))]
4372   "TARGET_EITHER"
4373   "
4374   if (TARGET_ARM)
4375     {
4376       if (!no_new_pseudos)
4377         {
4378           if (GET_CODE (operands[0]) == MEM)
4379             {
4380               if (arm_arch4)
4381                 {
4382                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4383                   DONE;
4384                 }
4385               if (GET_CODE (operands[1]) == CONST_INT)
4386                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4387               else
4388                 {
4389                   if (GET_CODE (operands[1]) == MEM)
4390                     operands[1] = force_reg (HImode, operands[1]);
4391                   if (BYTES_BIG_ENDIAN)
4392                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4393                   else
4394                    emit_insn (gen_storehi (operands[1], operands[0]));
4395                 }
4396               DONE;
4397             }
4398           /* Sign extend a constant, and keep it in an SImode reg.  */
4399           else if (GET_CODE (operands[1]) == CONST_INT)
4400             {
4401               rtx reg = gen_reg_rtx (SImode);
4402               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4404               /* If the constant is already valid, leave it alone.  */
4405               if (!const_ok_for_arm (val))
4406                 {
4407                   /* If setting all the top bits will make the constant 
4408                      loadable in a single instruction, then set them.  
4409                      Otherwise, sign extend the number.  */
4411                   if (const_ok_for_arm (~(val | ~0xffff)))
4412                     val |= ~0xffff;
4413                   else if (val & 0x8000)
4414                     val |= ~0xffff;
4415                 }
4417               emit_insn (gen_movsi (reg, GEN_INT (val)));
4418               operands[1] = gen_lowpart (HImode, reg);
4419             }
4420           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4421                    && GET_CODE (operands[1]) == MEM)
4422             {
4423               rtx reg = gen_reg_rtx (SImode);
4425               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4426               operands[1] = gen_lowpart (HImode, reg);
4427             }
4428           else if (!arm_arch4)
4429             {
4430              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4431                 for v4 and up architectures because LDRH instructions will
4432                 be used to access the HI values, and these cannot generate
4433                 unaligned word access faults in the MMU.  */
4434               if (GET_CODE (operands[1]) == MEM)
4435                 {
4436                   if (TARGET_MMU_TRAPS)
4437                     {
4438                       rtx base;
4439                       rtx offset = const0_rtx;
4440                       rtx reg = gen_reg_rtx (SImode);
4442                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4443                            || (GET_CODE (base) == PLUS
4444                                && (GET_CODE (offset = XEXP (base, 1))
4445                                    == CONST_INT)
4446                                && ((INTVAL(offset) & 1) != 1)
4447                                && GET_CODE (base = XEXP (base, 0)) == REG))
4448                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4449                         {
4450                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4451                           rtx new;
4453                           new = gen_rtx_MEM (SImode,
4454                                              plus_constant (base, new_offset));
4455                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4456                           emit_insn (gen_movsi (reg, new));
4457                           if (((INTVAL (offset) & 2) != 0)
4458                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4459                             {
4460                               rtx reg2 = gen_reg_rtx (SImode);
4462                               emit_insn (gen_lshrsi3 (reg2, reg,
4463                                          GEN_INT (16)));
4464                               reg = reg2;
4465                             }
4466                         }
4467                       else
4468                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4470                       operands[1] = gen_lowpart (HImode, reg);
4471                     }
4472                   else if (BYTES_BIG_ENDIAN)
4473                     {
4474                       rtx base;
4475                       rtx offset = const0_rtx;
4477                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4478                            || (GET_CODE (base) == PLUS
4479                               && (GET_CODE (offset = XEXP (base, 1))
4480                                   == CONST_INT)
4481                               && GET_CODE (base = XEXP (base, 0)) == REG))
4482                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4483                         {
4484                           rtx reg = gen_reg_rtx (SImode);
4485                           rtx new;
4487                           if ((INTVAL (offset) & 2) == 2)
4488                             {
4489                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4490                               new = gen_rtx_MEM (SImode,
4491                                                  plus_constant (base,
4492                                                                 new_offset));
4493                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4494                               emit_insn (gen_movsi (reg, new));
4495                             }
4496                           else
4497                             {
4498                               new = gen_rtx_MEM (SImode,
4499                                                  XEXP (operands[1], 0));
4500                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4501                               emit_insn (gen_rotated_loadsi (reg, new));
4502                             }
4504                           operands[1] = gen_lowpart (HImode, reg);
4505                         }
4506                       else
4507                         {
4508                           emit_insn (gen_movhi_bigend (operands[0],
4509                                                        operands[1]));
4510                           DONE;
4511                         }
4512                     }
4513                }
4514            }
4515         }
4516       /* Handle loading a large integer during reload */
4517       else if (GET_CODE (operands[1]) == CONST_INT
4518                && !const_ok_for_arm (INTVAL (operands[1]))
4519                && !const_ok_for_arm (~INTVAL (operands[1])))
4520         {
4521           /* Writing a constant to memory needs a scratch, which should
4522              be handled with SECONDARY_RELOADs.  */
4523           if (GET_CODE (operands[0]) != REG)
4524             abort ();
4526           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4527           emit_insn (gen_movsi (operands[0], operands[1]));
4528           DONE;
4529        }
4530     }
4531   else /* TARGET_THUMB */
4532     {
4533       if (!no_new_pseudos)
4534         {
4535           if (GET_CODE (operands[0]) != REG)
4536             operands[1] = force_reg (HImode, operands[1]);
4538           /* ??? We shouldn't really get invalid addresses here, but this can
4539              happen if we are passed a SP (never OK for HImode/QImode) or 
4540              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4541              HImode/QImode) relative address.  */
4542           /* ??? This should perhaps be fixed elsewhere, for instance, in
4543              fixup_stack_1, by checking for other kinds of invalid addresses,
4544              e.g. a bare reference to a virtual register.  This may confuse the
4545              alpha though, which must handle this case differently.  */
4546           if (GET_CODE (operands[0]) == MEM
4547               && !memory_address_p (GET_MODE (operands[0]),
4548                                     XEXP (operands[0], 0)))
4549             operands[0]
4550               = replace_equiv_address (operands[0],
4551                                        copy_to_reg (XEXP (operands[0], 0)));
4552    
4553           if (GET_CODE (operands[1]) == MEM
4554               && !memory_address_p (GET_MODE (operands[1]),
4555                                     XEXP (operands[1], 0)))
4556             operands[1]
4557               = replace_equiv_address (operands[1],
4558                                        copy_to_reg (XEXP (operands[1], 0)));
4559         }
4560       /* Handle loading a large integer during reload */
4561       else if (GET_CODE (operands[1]) == CONST_INT
4562                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4563         {
4564           /* Writing a constant to memory needs a scratch, which should
4565              be handled with SECONDARY_RELOADs.  */
4566           if (GET_CODE (operands[0]) != REG)
4567             abort ();
4569           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4570           emit_insn (gen_movsi (operands[0], operands[1]));
4571           DONE;
4572         }
4573     }
4574   "
4577 (define_insn "*thumb_movhi_insn"
4578   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4579         (match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4580   "TARGET_THUMB
4581    && (   register_operand (operands[0], HImode)
4582        || register_operand (operands[1], HImode))"
4583   "*
4584   switch (which_alternative)
4585     {
4586     case 0: return \"add        %0, %1, #0\";
4587     case 2: return \"strh       %1, %0\";
4588     case 3: return \"mov        %0, %1\";
4589     case 4: return \"mov        %0, %1\";
4590     case 5: return \"mov        %0, %1\";
4591     default: abort ();
4592     case 1:
4593       /* The stack pointer can end up being taken as an index register.
4594           Catch this case here and deal with it.  */
4595       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4596           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4597           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4598         {
4599           rtx ops[2];
4600           ops[0] = operands[0];
4601           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4602       
4603           output_asm_insn (\"mov        %0, %1\", ops);
4605           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4606     
4607         }
4608       return \"ldrh     %0, %1\";
4609     }"
4610   [(set_attr "length" "2,4,2,2,2,2")
4611    (set_attr "type" "*,load,store1,*,*,*")
4612    (set_attr "pool_range" "*,64,*,*,*,*")]
4616 (define_insn "rotated_loadsi"
4617   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4618         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4619                    (const_int 16)))]
4620   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4621   "*
4622   {
4623     rtx ops[2];
4625     ops[0] = operands[0];
4626     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4627     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4628     return \"\";
4629   }"
4630   [(set_attr "type" "load")
4631    (set_attr "predicable" "yes")]
4634 (define_expand "movhi_bytes"
4635   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4636    (set (match_dup 3)
4637         (zero_extend:SI (match_dup 6)))
4638    (set (match_operand:SI 0 "" "")
4639          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4640   "TARGET_ARM"
4641   "
4642   {
4643     rtx mem1, mem2;
4644     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4646     mem1 = gen_rtx_MEM (QImode, addr);
4647     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4648     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4649     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4650     operands[0] = gen_lowpart (SImode, operands[0]);
4651     operands[1] = mem1;
4652     operands[2] = gen_reg_rtx (SImode);
4653     operands[3] = gen_reg_rtx (SImode);
4654     operands[6] = mem2;
4656     if (BYTES_BIG_ENDIAN)
4657       {
4658         operands[4] = operands[2];
4659         operands[5] = operands[3];
4660       }
4661     else
4662       {
4663         operands[4] = operands[3];
4664         operands[5] = operands[2];
4665       }
4666   }"
4669 (define_expand "movhi_bigend"
4670   [(set (match_dup 2)
4671         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4672                    (const_int 16)))
4673    (set (match_dup 3)
4674         (ashiftrt:SI (match_dup 2) (const_int 16)))
4675    (set (match_operand:HI 0 "s_register_operand" "")
4676         (subreg:HI (match_dup 3) 0))]
4677   "TARGET_ARM"
4678   "
4679   operands[2] = gen_reg_rtx (SImode);
4680   operands[3] = gen_reg_rtx (SImode);
4681   "
4684 ;; Pattern to recognise insn generated default case above
4685 (define_insn "*movhi_insn_arch4"
4686   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4687         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4688   "TARGET_ARM
4689    && arm_arch4
4690    && (GET_CODE (operands[1]) != CONST_INT
4691        || const_ok_for_arm (INTVAL (operands[1]))
4692        || const_ok_for_arm (~INTVAL (operands[1])))"
4693   "@
4694    mov%?\\t%0, %1\\t%@ movhi
4695    mvn%?\\t%0, #%B1\\t%@ movhi
4696    str%?h\\t%1, %0\\t%@ movhi 
4697    ldr%?h\\t%0, %1\\t%@ movhi"
4698   [(set_attr "type" "*,*,store1,load")
4699    (set_attr "predicable" "yes")
4700    (set_attr "pool_range" "*,*,*,256")
4701    (set_attr "neg_pool_range" "*,*,*,244")]
4704 (define_insn "*movhi_insn_littleend"
4705   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4706         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4707   "TARGET_ARM
4708    && !arm_arch4
4709    && !BYTES_BIG_ENDIAN
4710    && !TARGET_MMU_TRAPS
4711    && (GET_CODE (operands[1]) != CONST_INT
4712        || const_ok_for_arm (INTVAL (operands[1]))
4713        || const_ok_for_arm (~INTVAL (operands[1])))"
4714   "@
4715    mov%?\\t%0, %1\\t%@ movhi
4716    mvn%?\\t%0, #%B1\\t%@ movhi
4717    ldr%?\\t%0, %1\\t%@ movhi"
4718   [(set_attr "type" "*,*,load")
4719    (set_attr "predicable" "yes")
4720    (set_attr "pool_range" "4096")
4721    (set_attr "neg_pool_range" "4084")]
4724 (define_insn "*movhi_insn_bigend"
4725   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4726         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4727   "TARGET_ARM
4728    && !arm_arch4
4729    && BYTES_BIG_ENDIAN
4730    && !TARGET_MMU_TRAPS
4731    && (GET_CODE (operands[1]) != CONST_INT
4732        || const_ok_for_arm (INTVAL (operands[1]))
4733        || const_ok_for_arm (~INTVAL (operands[1])))"
4734   "@
4735    mov%?\\t%0, %1\\t%@ movhi
4736    mvn%?\\t%0, #%B1\\t%@ movhi
4737    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4738   [(set_attr "type" "*,*,load")
4739    (set_attr "predicable" "yes")
4740    (set_attr "length" "4,4,8")
4741    (set_attr "pool_range" "*,*,4092")
4742    (set_attr "neg_pool_range" "*,*,4084")]
4745 (define_insn "*loadhi_si_bigend"
4746   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4747         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4748                    (const_int 16)))]
4749   "TARGET_ARM
4750    && BYTES_BIG_ENDIAN
4751    && !TARGET_MMU_TRAPS"
4752   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4753   [(set_attr "type" "load")
4754    (set_attr "predicable" "yes")
4755    (set_attr "pool_range" "4096")
4756    (set_attr "neg_pool_range" "4084")]
4759 (define_insn "*movhi_bytes"
4760   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4761         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4762   "TARGET_ARM && TARGET_MMU_TRAPS"
4763   "@
4764    mov%?\\t%0, %1\\t%@ movhi
4765    mvn%?\\t%0, #%B1\\t%@ movhi"
4766   [(set_attr "predicable" "yes")]
4769 (define_insn "thumb_movhi_clobber"
4770   [(set (match_operand:HI     0 "memory_operand"   "=m")
4771         (match_operand:HI     1 "register_operand" "l"))
4772    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4773   "TARGET_THUMB"
4774   "*
4775   abort ();"
4777         
4778 ;; We use a DImode scratch because we may occasionally need an additional
4779 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4780 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4781 (define_expand "reload_outhi"
4782   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4783               (match_operand:HI 1 "s_register_operand"        "r")
4784               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4785   "TARGET_EITHER"
4786   "if (TARGET_ARM)
4787      arm_reload_out_hi (operands);
4788    else
4789      thumb_reload_out_hi (operands);
4790   DONE;
4791   "
4794 (define_expand "reload_inhi"
4795   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4796               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4797               (match_operand:DI 2 "s_register_operand" "=&r")])]
4798   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4799   "
4800   if (TARGET_ARM)
4801     arm_reload_in_hi (operands);
4802   else
4803     thumb_reload_out_hi (operands);
4804   DONE;
4807 (define_expand "movqi"
4808   [(set (match_operand:QI 0 "general_operand" "")
4809         (match_operand:QI 1 "general_operand" ""))]
4810   "TARGET_EITHER"
4811   "
4812   if (TARGET_ARM)
4813     {
4814       /* Everything except mem = const or mem = mem can be done easily */
4816       if (!no_new_pseudos)
4817         {
4818           if (GET_CODE (operands[1]) == CONST_INT)
4819             {
4820               rtx reg = gen_reg_rtx (SImode);
4822               emit_insn (gen_movsi (reg, operands[1]));
4823               operands[1] = gen_lowpart (QImode, reg);
4824             }
4825           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4826             {
4827               rtx reg = gen_reg_rtx (SImode);
4829               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4830               operands[1] = gen_lowpart (QImode, reg);
4831             }
4832           if (GET_CODE (operands[0]) == MEM)
4833             operands[1] = force_reg (QImode, operands[1]);
4834         }
4835     }
4836   else /* TARGET_THUMB */
4837     {
4838       if (!no_new_pseudos)
4839         {
4840           if (GET_CODE (operands[0]) != REG)
4841             operands[1] = force_reg (QImode, operands[1]);
4843           /* ??? We shouldn't really get invalid addresses here, but this can
4844              happen if we are passed a SP (never OK for HImode/QImode) or
4845              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4846              HImode/QImode) relative address.  */
4847           /* ??? This should perhaps be fixed elsewhere, for instance, in
4848              fixup_stack_1, by checking for other kinds of invalid addresses,
4849              e.g. a bare reference to a virtual register.  This may confuse the
4850              alpha though, which must handle this case differently.  */
4851           if (GET_CODE (operands[0]) == MEM
4852               && !memory_address_p (GET_MODE (operands[0]),
4853                                      XEXP (operands[0], 0)))
4854             operands[0]
4855               = replace_equiv_address (operands[0],
4856                                        copy_to_reg (XEXP (operands[0], 0)));
4857           if (GET_CODE (operands[1]) == MEM
4858               && !memory_address_p (GET_MODE (operands[1]),
4859                                     XEXP (operands[1], 0)))
4860              operands[1]
4861                = replace_equiv_address (operands[1],
4862                                         copy_to_reg (XEXP (operands[1], 0)));
4863         }
4864       /* Handle loading a large integer during reload */
4865       else if (GET_CODE (operands[1]) == CONST_INT
4866                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4867         {
4868           /* Writing a constant to memory needs a scratch, which should
4869              be handled with SECONDARY_RELOADs.  */
4870           if (GET_CODE (operands[0]) != REG)
4871             abort ();
4873           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4874           emit_insn (gen_movsi (operands[0], operands[1]));
4875           DONE;
4876        }
4877     }
4878   "
4882 (define_insn "*arm_movqi_insn"
4883   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4884         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4885   "TARGET_ARM
4886    && (   register_operand (operands[0], QImode)
4887        || register_operand (operands[1], QImode))"
4888   "@
4889    mov%?\\t%0, %1
4890    mvn%?\\t%0, #%B1
4891    ldr%?b\\t%0, %1
4892    str%?b\\t%1, %0"
4893   [(set_attr "type" "*,*,load,store1")
4894    (set_attr "predicable" "yes")]
4897 (define_insn "*thumb_movqi_insn"
4898   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4899         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4900   "TARGET_THUMB
4901    && (   register_operand (operands[0], QImode)
4902        || register_operand (operands[1], QImode))"
4903   "@
4904    add\\t%0, %1, #0
4905    ldrb\\t%0, %1
4906    strb\\t%1, %0
4907    mov\\t%0, %1
4908    mov\\t%0, %1
4909    mov\\t%0, %1"
4910   [(set_attr "length" "2")
4911    (set_attr "type" "*,load,store1,*,*,*")
4912    (set_attr "pool_range" "*,32,*,*,*,*")]
4915 (define_expand "movsf"
4916   [(set (match_operand:SF 0 "general_operand" "")
4917         (match_operand:SF 1 "general_operand" ""))]
4918   "TARGET_EITHER"
4919   "
4920   if (TARGET_ARM)
4921     {
4922       if (GET_CODE (operands[0]) == MEM)
4923         operands[1] = force_reg (SFmode, operands[1]);
4924     }
4925   else /* TARGET_THUMB */
4926     {
4927       if (!no_new_pseudos)
4928         {
4929            if (GET_CODE (operands[0]) != REG)
4930              operands[1] = force_reg (SFmode, operands[1]);
4931         }
4932     }
4933   "
4936 (define_split
4937   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4938         (match_operand:SF 1 "immediate_operand" ""))]
4939   "TARGET_ARM
4940    && !TARGET_HARD_FLOAT
4941    && reload_completed
4942    && GET_CODE (operands[1]) == CONST_DOUBLE"
4943   [(set (match_dup 2) (match_dup 3))]
4944   "
4945   operands[2] = gen_lowpart (SImode, operands[0]);
4946   operands[3] = gen_lowpart (SImode, operands[1]);
4947   if (operands[2] == 0 || operands[3] == 0)
4948     FAIL;
4949   "
4952 (define_insn "*arm_movsf_hard_insn"
4953   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4954         (match_operand:SF 1 "general_operand"      "fG,H,mE,f,r,f,r,mE,r"))]
4955   "TARGET_ARM
4956    && TARGET_HARD_FLOAT
4957    && (GET_CODE (operands[0]) != MEM
4958        || register_operand (operands[1], SFmode))"
4959   "@
4960    mvf%?s\\t%0, %1
4961    mnf%?s\\t%0, #%N1
4962    ldf%?s\\t%0, %1
4963    stf%?s\\t%1, %0
4964    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4965    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4966    mov%?\\t%0, %1
4967    ldr%?\\t%0, %1\\t%@ float
4968    str%?\\t%1, %0\\t%@ float"
4969   [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4970    (set_attr "predicable" "yes")
4971    (set_attr "type"
4972          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4973    (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4974    (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4977 ;; Exactly the same as above, except that all `f' cases are deleted.
4978 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4979 ;; when -msoft-float.
4981 (define_insn "*arm_movsf_soft_insn"
4982   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4983         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4984   "TARGET_ARM
4985    && TARGET_SOFT_FLOAT
4986    && (GET_CODE (operands[0]) != MEM
4987        || register_operand (operands[1], SFmode))"
4988   "@
4989    mov%?\\t%0, %1
4990    ldr%?\\t%0, %1\\t%@ float
4991    str%?\\t%1, %0\\t%@ float"
4992   [(set_attr "length" "4,4,4")
4993    (set_attr "predicable" "yes")
4994    (set_attr "type" "*,load,store1")
4995    (set_attr "pool_range" "*,4096,*")
4996    (set_attr "neg_pool_range" "*,4084,*")]
4999 ;;; ??? This should have alternatives for constants.
5000 (define_insn "*thumb_movsf_insn"
5001   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5002         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5003   "TARGET_THUMB
5004    && (   register_operand (operands[0], SFmode) 
5005        || register_operand (operands[1], SFmode))"
5006   "@
5007    add\\t%0, %1, #0
5008    ldmia\\t%1, {%0}
5009    stmia\\t%0, {%1}
5010    ldr\\t%0, %1
5011    str\\t%1, %0
5012    mov\\t%0, %1
5013    mov\\t%0, %1"
5014   [(set_attr "length" "2")
5015    (set_attr "type" "*,load,store1,load,store1,*,*")
5016    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5019 (define_expand "movdf"
5020   [(set (match_operand:DF 0 "general_operand" "")
5021         (match_operand:DF 1 "general_operand" ""))]
5022   "TARGET_EITHER"
5023   "
5024   if (TARGET_ARM)
5025     {
5026       if (GET_CODE (operands[0]) == MEM)
5027         operands[1] = force_reg (DFmode, operands[1]);
5028     }
5029   else /* TARGET_THUMB */
5030     {
5031       if (!no_new_pseudos)
5032         {
5033           if (GET_CODE (operands[0]) != REG)
5034             operands[1] = force_reg (DFmode, operands[1]);
5035         }
5036     }
5037   "
5040 ;; Reloading a df mode value stored in integer regs to memory can require a
5041 ;; scratch reg.
5042 (define_expand "reload_outdf"
5043   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5044    (match_operand:DF 1 "s_register_operand" "r")
5045    (match_operand:SI 2 "s_register_operand" "=&r")]
5046   "TARGET_ARM"
5047   "
5048   {
5049     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5051     if (code == REG)
5052       operands[2] = XEXP (operands[0], 0);
5053     else if (code == POST_INC || code == PRE_DEC)
5054       {
5055         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5056         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5057         emit_insn (gen_movdi (operands[0], operands[1]));
5058         DONE;
5059       }
5060     else if (code == PRE_INC)
5061       {
5062         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5064         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5065         operands[2] = reg;
5066       }
5067     else if (code == POST_DEC)
5068       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5069     else
5070       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5071                              XEXP (XEXP (operands[0], 0), 1)));
5073     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5074                             operands[1]));
5076     if (code == POST_DEC)
5077       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5079     DONE;
5080   }"
5083 (define_insn "*movdf_hard_insn"
5084   [(set (match_operand:DF 0 "nonimmediate_operand"
5085                                                 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5086         (match_operand:DF 1 "general_operand"
5087                                                 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5088   "TARGET_ARM
5089    && TARGET_HARD_FLOAT
5090    && (GET_CODE (operands[0]) != MEM
5091        || register_operand (operands[1], DFmode))"
5092   "*
5093   {
5094   switch (which_alternative)
5095     {
5096     default:
5097     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5098     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5099     case 2: case 3: case 4: return output_move_double (operands);
5100     case 5: return \"mvf%?d\\t%0, %1\";
5101     case 6: return \"mnf%?d\\t%0, #%N1\";
5102     case 7: return \"ldf%?d\\t%0, %1\";
5103     case 8: return \"stf%?d\\t%1, %0\";
5104     case 9: return output_mov_double_fpu_from_arm (operands);
5105     case 10: return output_mov_double_arm_from_fpu (operands);
5106     }
5107   }
5108   "
5109   [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5110    (set_attr "predicable" "yes")
5111    (set_attr "type"
5112     "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5113    (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
5114    (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
5117 ;; Software floating point version.  This is essentially the same as movdi.
5118 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5119 ;; an `f' reg.
5121 (define_insn "*movdf_soft_insn"
5122   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5123         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5124   "TARGET_ARM && TARGET_SOFT_FLOAT
5125   "
5126   "* return output_move_double (operands);"
5127   [(set_attr "length" "8,8,8")
5128    (set_attr "type" "*,load,store2")
5129    (set_attr "pool_range" "1020")
5130    (set_attr "neg_pool_range" "1008")]
5133 ;;; ??? This should have alternatives for constants.
5134 ;;; ??? This was originally identical to the movdi_insn pattern.
5135 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5136 ;;; thumb_reorg with a memory reference.
5137 (define_insn "*thumb_movdf_insn"
5138   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5139         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5140   "TARGET_THUMB
5141    && (   register_operand (operands[0], DFmode)
5142        || register_operand (operands[1], DFmode))"
5143   "*
5144   switch (which_alternative)
5145     {
5146     default:
5147     case 0:
5148       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5149         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5150       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5151     case 1:
5152       return \"ldmia\\t%1, {%0, %H0}\";
5153     case 2:
5154       return \"stmia\\t%0, {%1, %H1}\";
5155     case 3:
5156       return thumb_load_double_from_address (operands);
5157     case 4:
5158       operands[2] = gen_rtx (MEM, SImode,
5159                              plus_constant (XEXP (operands[0], 0), 4));
5160       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5161       return \"\";
5162     case 5:
5163       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5164         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5165       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5166     }
5167   "
5168   [(set_attr "length" "4,2,2,6,4,4")
5169    (set_attr "type" "*,load,store2,load,store2,*")
5170    (set_attr "pool_range" "*,*,*,1020,*,*")]
5174 (define_expand "movxf"
5175   [(set (match_operand:XF 0 "general_operand" "")
5176         (match_operand:XF 1 "general_operand" ""))]
5177   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5178   "")
5180 ;; Even when the XFmode patterns aren't enabled, we enable this after
5181 ;; reloading so that we can push floating point registers in the prologue.
5183 (define_insn "*movxf_hard_insn"
5184   [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5185         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5186   "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5187   "*
5188   switch (which_alternative)
5189     {
5190     default:
5191     case 0: return \"mvf%?e\\t%0, %1\";
5192     case 1: return \"mnf%?e\\t%0, #%N1\";
5193     case 2: return \"ldf%?e\\t%0, %1\";
5194     case 3: return \"stf%?e\\t%1, %0\";
5195     case 4: return output_mov_long_double_fpu_from_arm (operands);
5196     case 5: return output_mov_long_double_arm_from_fpu (operands);
5197     case 6: return output_mov_long_double_arm_from_arm (operands);
5198     }
5199   "
5200   [(set_attr "length" "4,4,4,4,8,8,12")
5201    (set_attr "predicable" "yes")
5202    (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5203    (set_attr "pool_range" "*,*,1024,*,*,*,*")
5204    (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5208 ;; load- and store-multiple insns
5209 ;; The arm can load/store any set of registers, provided that they are in
5210 ;; ascending order; but that is beyond GCC so stick with what it knows.
5212 (define_expand "load_multiple"
5213   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5214                           (match_operand:SI 1 "" ""))
5215                      (use (match_operand:SI 2 "" ""))])]
5216   "TARGET_ARM"
5217   "
5218   /* Support only fixed point registers.  */
5219   if (GET_CODE (operands[2]) != CONST_INT
5220       || INTVAL (operands[2]) > 14
5221       || INTVAL (operands[2]) < 2
5222       || GET_CODE (operands[1]) != MEM
5223       || GET_CODE (operands[0]) != REG
5224       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5225       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5226     FAIL;
5228   operands[3]
5229     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5230                              force_reg (SImode, XEXP (operands[1], 0)),
5231                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5232                              MEM_IN_STRUCT_P(operands[1]),
5233                              MEM_SCALAR_P (operands[1]));
5234   "
5237 ;; Load multiple with write-back
5239 (define_insn "*ldmsi_postinc4"
5240   [(match_parallel 0 "load_multiple_operation"
5241     [(set (match_operand:SI 1 "s_register_operand" "=r")
5242           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5243                    (const_int 16)))
5244      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5245           (mem:SI (match_dup 2)))
5246      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5247           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5248      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5249           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5250      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5251           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5252   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5253   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5254   [(set_attr "type" "load")
5255    (set_attr "predicable" "yes")]
5258 (define_insn "*ldmsi_postinc3"
5259   [(match_parallel 0 "load_multiple_operation"
5260     [(set (match_operand:SI 1 "s_register_operand" "=r")
5261           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5262                    (const_int 12)))
5263      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5264           (mem:SI (match_dup 2)))
5265      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5266           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5267      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5268           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5269   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5270   "ldm%?ia\\t%1!, {%3, %4, %5}"
5271   [(set_attr "type" "load")
5272    (set_attr "predicable" "yes")]
5275 (define_insn "*ldmsi_postinc2"
5276   [(match_parallel 0 "load_multiple_operation"
5277     [(set (match_operand:SI 1 "s_register_operand" "=r")
5278           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5279                    (const_int 8)))
5280      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5281           (mem:SI (match_dup 2)))
5282      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5283           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5284   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5285   "ldm%?ia\\t%1!, {%3, %4}"
5286   [(set_attr "type" "load")
5287    (set_attr "predicable" "yes")]
5290 ;; Ordinary load multiple
5292 (define_insn "*ldmsi4"
5293   [(match_parallel 0 "load_multiple_operation"
5294     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5295           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5296      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5297           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5298      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5299           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5300      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5301           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5302   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5303   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5304   [(set_attr "type" "load")
5305    (set_attr "predicable" "yes")]
5308 (define_insn "*ldmsi3"
5309   [(match_parallel 0 "load_multiple_operation"
5310     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5311           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5312      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5313           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5314      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5315           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5316   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5317   "ldm%?ia\\t%1, {%2, %3, %4}"
5318   [(set_attr "type" "load")
5319    (set_attr "predicable" "yes")]
5322 (define_insn "*ldmsi2"
5323   [(match_parallel 0 "load_multiple_operation"
5324     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5325           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5326      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5327           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5328   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5329   "ldm%?ia\\t%1, {%2, %3}"
5330   [(set_attr "type" "load")
5331    (set_attr "predicable" "yes")]
5334 (define_expand "store_multiple"
5335   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5336                           (match_operand:SI 1 "" ""))
5337                      (use (match_operand:SI 2 "" ""))])]
5338   "TARGET_ARM"
5339   "
5340   /* Support only fixed point registers */
5341   if (GET_CODE (operands[2]) != CONST_INT
5342       || INTVAL (operands[2]) > 14
5343       || INTVAL (operands[2]) < 2
5344       || GET_CODE (operands[1]) != REG
5345       || GET_CODE (operands[0]) != MEM
5346       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5347       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5348     FAIL;
5350   operands[3]
5351     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5352                               force_reg (SImode, XEXP (operands[0], 0)),
5353                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5354                               MEM_IN_STRUCT_P(operands[0]), 
5355                               MEM_SCALAR_P (operands[0]));
5356   "
5359 ;; Store multiple with write-back
5361 (define_insn "*stmsi_postinc4"
5362   [(match_parallel 0 "store_multiple_operation"
5363     [(set (match_operand:SI 1 "s_register_operand" "=r")
5364           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5365                    (const_int 16)))
5366      (set (mem:SI (match_dup 2))
5367           (match_operand:SI 3 "arm_hard_register_operand" ""))
5368      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5369           (match_operand:SI 4 "arm_hard_register_operand" ""))
5370      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5371           (match_operand:SI 5 "arm_hard_register_operand" ""))
5372      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5373           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5374   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5375   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5376   [(set_attr "predicable" "yes")
5377    (set_attr "type" "store4")]
5380 (define_insn "*stmsi_postinc3"
5381   [(match_parallel 0 "store_multiple_operation"
5382     [(set (match_operand:SI 1 "s_register_operand" "=r")
5383           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5384                    (const_int 12)))
5385      (set (mem:SI (match_dup 2))
5386           (match_operand:SI 3 "arm_hard_register_operand" ""))
5387      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5388           (match_operand:SI 4 "arm_hard_register_operand" ""))
5389      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5390           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5391   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5392   "stm%?ia\\t%1!, {%3, %4, %5}"
5393   [(set_attr "predicable" "yes")
5394    (set_attr "type" "store3")]
5397 (define_insn "*stmsi_postinc2"
5398   [(match_parallel 0 "store_multiple_operation"
5399     [(set (match_operand:SI 1 "s_register_operand" "=r")
5400           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5401                    (const_int 8)))
5402      (set (mem:SI (match_dup 2))
5403           (match_operand:SI 3 "arm_hard_register_operand" ""))
5404      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5405           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5406   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5407   "stm%?ia\\t%1!, {%3, %4}"
5408   [(set_attr "predicable" "yes")
5409    (set_attr "type" "store2")]
5412 ;; Ordinary store multiple
5414 (define_insn "*stmsi4"
5415   [(match_parallel 0 "store_multiple_operation"
5416     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5417           (match_operand:SI 2 "arm_hard_register_operand" ""))
5418      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5419           (match_operand:SI 3 "arm_hard_register_operand" ""))
5420      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5421           (match_operand:SI 4 "arm_hard_register_operand" ""))
5422      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5423           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5424   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5425   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5426   [(set_attr "predicable" "yes")
5427    (set_attr "type" "store4")]
5430 (define_insn "*stmsi3"
5431   [(match_parallel 0 "store_multiple_operation"
5432     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5433           (match_operand:SI 2 "arm_hard_register_operand" ""))
5434      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5435           (match_operand:SI 3 "arm_hard_register_operand" ""))
5436      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5437           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5438   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5439   "stm%?ia\\t%1, {%2, %3, %4}"
5440   [(set_attr "predicable" "yes")
5441    (set_attr "type" "store3")]
5444 (define_insn "*stmsi2"
5445   [(match_parallel 0 "store_multiple_operation"
5446     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5447           (match_operand:SI 2 "arm_hard_register_operand" ""))
5448      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5449           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5450   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5451   "stm%?ia\\t%1, {%2, %3}"
5452   [(set_attr "predicable" "yes")
5453    (set_attr "type" "store2")]
5456 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5457 ;; We could let this apply for blocks of less than this, but it clobbers so
5458 ;; many registers that there is then probably a better way.
5460 (define_expand "movstrqi"
5461   [(match_operand:BLK 0 "general_operand" "")
5462    (match_operand:BLK 1 "general_operand" "")
5463    (match_operand:SI 2 "const_int_operand" "")
5464    (match_operand:SI 3 "const_int_operand" "")]
5465   "TARGET_EITHER"
5466   "
5467   if (TARGET_ARM)
5468     {
5469       if (arm_gen_movstrqi (operands))
5470         DONE;
5471       FAIL;
5472     }
5473   else /* TARGET_THUMB */
5474     {
5475       if (   INTVAL (operands[3]) != 4
5476           || INTVAL (operands[2]) > 48)
5477         FAIL;
5479       thumb_expand_movstrqi (operands);
5480       DONE;
5481     }
5482   "
5485 ;; Thumb block-move insns
5487 (define_insn "movmem12b"
5488   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5489         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5490    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5491         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5492    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5493         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5494    (set (match_operand:SI 0 "register_operand" "=l")
5495         (plus:SI (match_dup 2) (const_int 12)))
5496    (set (match_operand:SI 1 "register_operand" "=l")
5497         (plus:SI (match_dup 3) (const_int 12)))
5498    (clobber (match_scratch:SI 4 "=&l"))
5499    (clobber (match_scratch:SI 5 "=&l"))
5500    (clobber (match_scratch:SI 6 "=&l"))]
5501   "TARGET_THUMB"
5502   "* return thumb_output_move_mem_multiple (3, operands);"
5503   [(set_attr "length" "4")
5504    ; This isn't entirely accurate...  It loads as well, but in terms of
5505    ; scheduling the following insn it is better to consider it as a store
5506    (set_attr "type" "store3")]
5509 (define_insn "movmem8b"
5510   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5511         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5512    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5513         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5514    (set (match_operand:SI 0 "register_operand" "=l")
5515         (plus:SI (match_dup 2) (const_int 8)))
5516    (set (match_operand:SI 1 "register_operand" "=l")
5517         (plus:SI (match_dup 3) (const_int 8)))
5518    (clobber (match_scratch:SI 4 "=&l"))
5519    (clobber (match_scratch:SI 5 "=&l"))]
5520   "TARGET_THUMB"
5521   "* return thumb_output_move_mem_multiple (2, operands);"
5522   [(set_attr "length" "4")
5523    ; This isn't entirely accurate...  It loads as well, but in terms of
5524    ; scheduling the following insn it is better to consider it as a store
5525    (set_attr "type" "store2")]
5530 ;; Compare & branch insns
5531 ;; The range calcualations are based as follows:
5532 ;; For forward branches, the address calculation returns the address of
5533 ;; the next instruction.  This is 2 beyond the branch instruction.
5534 ;; For backward branches, the address calculation returns the address of
5535 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5536 ;; instruction for the shortest sequence, and 4 before the branch instruction
5537 ;; if we have to jump around an unconditional branch.
5538 ;; To the basic branch range the PC offset must be added (this is +4).
5539 ;; So for forward branches we have 
5540 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5541 ;; And for backward branches we have 
5542 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5544 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5545 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5547 (define_insn "cbranchsi4"
5548   [(set (pc)
5549         (if_then_else
5550             (match_operator                    0 "arm_comparison_operator"
5551                             [(match_operand:SI 1 "register_operand"   "l,r")
5552                              (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5553             (label_ref       (match_operand    3 "" ""))
5554             (pc)))]
5555   "TARGET_THUMB"
5556   "*
5557   output_asm_insn (\"cmp\\t%1, %2\", operands);
5558   switch (get_attr_length (insn))
5559     {
5560     case 4:  return \"b%d0\\t%l3\";
5561     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5562     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5563     }
5564   "
5565   [(set (attr "far_jump")
5566         (if_then_else
5567             (eq_attr "length" "8")
5568             (const_string "yes")
5569             (const_string "no")))
5570    (set (attr "length") 
5571         (if_then_else
5572             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5573                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5574             (const_int 4)
5575             (if_then_else
5576                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5577                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5578                 (const_int 6)
5579                 (const_int 8))))]
5582 (define_insn "*negated_cbranchsi4"
5583   [(set (pc)
5584         (if_then_else
5585          (match_operator             0 "arm_comparison_operator"
5586           [(match_operand:SI         1 "register_operand"  "l")
5587            (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5588          (label_ref (match_operand   3 "" ""))
5589          (pc)))]
5590   "TARGET_THUMB"
5591   "*
5592   output_asm_insn (\"cmn\\t%1, %2\", operands);
5593   switch (get_attr_length (insn))
5594     {
5595     case 4:  return \"b%d0\\t%l3\";
5596     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5597     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5598     }
5599   "
5600   [(set (attr "far_jump")
5601         (if_then_else
5602             (eq_attr "length" "8")
5603             (const_string "yes")
5604             (const_string "no")))
5605    (set (attr "length") 
5606         (if_then_else
5607             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5608                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5609             (const_int 4)
5610             (if_then_else
5611                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5612                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5613                 (const_int 6)
5614                 (const_int 8))))]
5618 ;; Comparison and test insns
5620 (define_expand "cmpsi"
5621   [(match_operand:SI 0 "s_register_operand" "")
5622    (match_operand:SI 1 "arm_add_operand" "")]
5623   "TARGET_ARM"
5624   "{
5625     arm_compare_op0 = operands[0];
5626     arm_compare_op1 = operands[1];
5627     DONE;
5628   }"
5631 (define_expand "cmpsf"
5632   [(match_operand:SF 0 "s_register_operand" "")
5633    (match_operand:SF 1 "fpu_rhs_operand" "")]
5634   "TARGET_ARM && TARGET_HARD_FLOAT"
5635   "
5636   arm_compare_op0 = operands[0];
5637   arm_compare_op1 = operands[1];
5638   DONE;
5639   "
5642 (define_expand "cmpdf"
5643   [(match_operand:DF 0 "s_register_operand" "")
5644    (match_operand:DF 1 "fpu_rhs_operand" "")]
5645   "TARGET_ARM && TARGET_HARD_FLOAT"
5646   "
5647   arm_compare_op0 = operands[0];
5648   arm_compare_op1 = operands[1];
5649   DONE;
5650   "
5653 (define_expand "cmpxf"
5654   [(match_operand:XF 0 "s_register_operand" "")
5655    (match_operand:XF 1 "fpu_rhs_operand" "")]
5656   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5657   "
5658   arm_compare_op0 = operands[0];
5659   arm_compare_op1 = operands[1];
5660   DONE;
5661   "
5664 (define_insn "*arm_cmpsi_insn"
5665   [(set (reg:CC CC_REGNUM)
5666         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5667                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5668   "TARGET_ARM"
5669   "@
5670    cmp%?\\t%0, %1
5671    cmn%?\\t%0, #%n1"
5672   [(set_attr "conds" "set")]
5675 (define_insn "*cmpsi_shiftsi"
5676   [(set (reg:CC CC_REGNUM)
5677         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
5678                     (match_operator:SI  3 "shift_operator"
5679                      [(match_operand:SI 1 "s_register_operand" "r")
5680                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5681   "TARGET_ARM"
5682   "cmp%?\\t%0, %1%S3"
5683   [(set_attr "conds" "set")
5684    (set_attr "shift" "1")
5685    ]
5688 (define_insn "*cmpsi_shiftsi_swp"
5689   [(set (reg:CC_SWP CC_REGNUM)
5690         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5691                          [(match_operand:SI 1 "s_register_operand" "r")
5692                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
5693                         (match_operand:SI 0 "s_register_operand" "r")))]
5694   "TARGET_ARM"
5695   "cmp%?\\t%0, %1%S3"
5696   [(set_attr "conds" "set")
5697    (set_attr "shift" "1")
5698    ]
5701 (define_insn "*cmpsi_neg_shiftsi"
5702   [(set (reg:CC CC_REGNUM)
5703         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5704                     (neg:SI (match_operator:SI 3 "shift_operator"
5705                              [(match_operand:SI 1 "s_register_operand" "r")
5706                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5707   "TARGET_ARM"
5708   "cmn%?\\t%0, %1%S3"
5709   [(set_attr "conds" "set")
5710    (set_attr "shift" "1")
5711    ]
5714 (define_insn "*cmpsf_insn"
5715   [(set (reg:CCFP CC_REGNUM)
5716         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5717                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5718   "TARGET_ARM && TARGET_HARD_FLOAT"
5719   "@
5720    cmf%?\\t%0, %1
5721    cnf%?\\t%0, #%N1"
5722   [(set_attr "conds" "set")
5723    (set_attr "type" "f_2_r")]
5726 (define_insn "*cmpdf_insn"
5727   [(set (reg:CCFP CC_REGNUM)
5728         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5729                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5730   "TARGET_ARM && TARGET_HARD_FLOAT"
5731   "@
5732    cmf%?\\t%0, %1
5733    cnf%?\\t%0, #%N1"
5734   [(set_attr "conds" "set")
5735    (set_attr "type" "f_2_r")]
5738 (define_insn "*cmpesfdf_df"
5739   [(set (reg:CCFP CC_REGNUM)
5740         (compare:CCFP (float_extend:DF
5741                        (match_operand:SF 0 "s_register_operand" "f,f"))
5742                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5743   "TARGET_ARM && TARGET_HARD_FLOAT"
5744   "@
5745    cmf%?\\t%0, %1
5746    cnf%?\\t%0, #%N1"
5747   [(set_attr "conds" "set")
5748    (set_attr "type" "f_2_r")]
5751 (define_insn "*cmpdf_esfdf"
5752   [(set (reg:CCFP CC_REGNUM)
5753         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5754                       (float_extend:DF
5755                        (match_operand:SF 1 "s_register_operand" "f"))))]
5756   "TARGET_ARM && TARGET_HARD_FLOAT"
5757   "cmf%?\\t%0, %1"
5758   [(set_attr "conds" "set")
5759    (set_attr "type" "f_2_r")]
5762 (define_insn "*cmpxf_insn"
5763   [(set (reg:CCFP CC_REGNUM)
5764         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5765                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5766   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5767   "@
5768    cmf%?\\t%0, %1
5769    cnf%?\\t%0, #%N1"
5770   [(set_attr "conds" "set")
5771    (set_attr "type" "f_2_r")]
5774 (define_insn "*cmpsf_trap"
5775   [(set (reg:CCFPE CC_REGNUM)
5776         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5777                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5778   "TARGET_ARM && TARGET_HARD_FLOAT"
5779   "@
5780    cmf%?e\\t%0, %1
5781    cnf%?e\\t%0, #%N1"
5782   [(set_attr "conds" "set")
5783    (set_attr "type" "f_2_r")]
5786 (define_insn "*cmpdf_trap"
5787   [(set (reg:CCFPE CC_REGNUM)
5788         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5789                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5790   "TARGET_ARM && TARGET_HARD_FLOAT"
5791   "@
5792    cmf%?e\\t%0, %1
5793    cnf%?e\\t%0, #%N1"
5794   [(set_attr "conds" "set")
5795    (set_attr "type" "f_2_r")]
5798 (define_insn "*cmp_esfdf_df_trap"
5799   [(set (reg:CCFPE CC_REGNUM)
5800         (compare:CCFPE (float_extend:DF
5801                         (match_operand:SF 0 "s_register_operand" "f,f"))
5802                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5803   "TARGET_ARM && TARGET_HARD_FLOAT"
5804   "@
5805    cmf%?e\\t%0, %1
5806    cnf%?e\\t%0, #%N1"
5807   [(set_attr "conds" "set")
5808    (set_attr "type" "f_2_r")]
5811 (define_insn "*cmp_df_esfdf_trap"
5812   [(set (reg:CCFPE CC_REGNUM)
5813         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5814                        (float_extend:DF
5815                         (match_operand:SF 1 "s_register_operand" "f"))))]
5816   "TARGET_ARM && TARGET_HARD_FLOAT"
5817   "cmf%?e\\t%0, %1"
5818   [(set_attr "conds" "set")
5819    (set_attr "type" "f_2_r")]
5822 (define_insn "*cmpxf_trap"
5823   [(set (reg:CCFPE CC_REGNUM)
5824         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5825                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5826   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5827   "@
5828    cmf%?e\\t%0, %1
5829    cnf%?e\\t%0, #%N1"
5830   [(set_attr "conds" "set")
5831    (set_attr "type" "f_2_r")]
5834 ; This insn allows redundant compares to be removed by cse, nothing should
5835 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5836 ; is deleted later on. The match_dup will match the mode here, so that
5837 ; mode changes of the condition codes aren't lost by this even though we don't
5838 ; specify what they are.
5840 (define_insn "*deleted_compare"
5841   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5842   "TARGET_ARM"
5843   "\\t%@ deleted compare"
5844   [(set_attr "conds" "set")
5845    (set_attr "length" "0")]
5849 ;; Conditional branch insns
5851 (define_expand "beq"
5852   [(set (pc)
5853         (if_then_else (eq (match_dup 1) (const_int 0))
5854                       (label_ref (match_operand 0 "" ""))
5855                       (pc)))]
5856   "TARGET_ARM"
5857   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5860 (define_expand "bne"
5861   [(set (pc)
5862         (if_then_else (ne (match_dup 1) (const_int 0))
5863                       (label_ref (match_operand 0 "" ""))
5864                       (pc)))]
5865   "TARGET_ARM"
5866   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5869 (define_expand "bgt"
5870   [(set (pc)
5871         (if_then_else (gt (match_dup 1) (const_int 0))
5872                       (label_ref (match_operand 0 "" ""))
5873                       (pc)))]
5874   "TARGET_ARM"
5875   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5878 (define_expand "ble"
5879   [(set (pc)
5880         (if_then_else (le (match_dup 1) (const_int 0))
5881                       (label_ref (match_operand 0 "" ""))
5882                       (pc)))]
5883   "TARGET_ARM"
5884   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5887 (define_expand "bge"
5888   [(set (pc)
5889         (if_then_else (ge (match_dup 1) (const_int 0))
5890                       (label_ref (match_operand 0 "" ""))
5891                       (pc)))]
5892   "TARGET_ARM"
5893   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5896 (define_expand "blt"
5897   [(set (pc)
5898         (if_then_else (lt (match_dup 1) (const_int 0))
5899                       (label_ref (match_operand 0 "" ""))
5900                       (pc)))]
5901   "TARGET_ARM"
5902   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5905 (define_expand "bgtu"
5906   [(set (pc)
5907         (if_then_else (gtu (match_dup 1) (const_int 0))
5908                       (label_ref (match_operand 0 "" ""))
5909                       (pc)))]
5910   "TARGET_ARM"
5911   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5914 (define_expand "bleu"
5915   [(set (pc)
5916         (if_then_else (leu (match_dup 1) (const_int 0))
5917                       (label_ref (match_operand 0 "" ""))
5918                       (pc)))]
5919   "TARGET_ARM"
5920   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5923 (define_expand "bgeu"
5924   [(set (pc)
5925         (if_then_else (geu (match_dup 1) (const_int 0))
5926                       (label_ref (match_operand 0 "" ""))
5927                       (pc)))]
5928   "TARGET_ARM"
5929   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5932 (define_expand "bltu"
5933   [(set (pc)
5934         (if_then_else (ltu (match_dup 1) (const_int 0))
5935                       (label_ref (match_operand 0 "" ""))
5936                       (pc)))]
5937   "TARGET_ARM"
5938   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5941 (define_expand "bunordered"
5942   [(set (pc)
5943         (if_then_else (unordered (match_dup 1) (const_int 0))
5944                       (label_ref (match_operand 0 "" ""))
5945                       (pc)))]
5946   "TARGET_ARM && TARGET_HARD_FLOAT"
5947   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5948                                       arm_compare_op1);"
5951 (define_expand "bordered"
5952   [(set (pc)
5953         (if_then_else (ordered (match_dup 1) (const_int 0))
5954                       (label_ref (match_operand 0 "" ""))
5955                       (pc)))]
5956   "TARGET_ARM && TARGET_HARD_FLOAT"
5957   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5958                                       arm_compare_op1);"
5961 (define_expand "bungt"
5962   [(set (pc)
5963         (if_then_else (ungt (match_dup 1) (const_int 0))
5964                       (label_ref (match_operand 0 "" ""))
5965                       (pc)))]
5966   "TARGET_ARM && TARGET_HARD_FLOAT"
5967   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5970 (define_expand "bunlt"
5971   [(set (pc)
5972         (if_then_else (unlt (match_dup 1) (const_int 0))
5973                       (label_ref (match_operand 0 "" ""))
5974                       (pc)))]
5975   "TARGET_ARM && TARGET_HARD_FLOAT"
5976   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5979 (define_expand "bunge"
5980   [(set (pc)
5981         (if_then_else (unge (match_dup 1) (const_int 0))
5982                       (label_ref (match_operand 0 "" ""))
5983                       (pc)))]
5984   "TARGET_ARM && TARGET_HARD_FLOAT"
5985   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5988 (define_expand "bunle"
5989   [(set (pc)
5990         (if_then_else (unle (match_dup 1) (const_int 0))
5991                       (label_ref (match_operand 0 "" ""))
5992                       (pc)))]
5993   "TARGET_ARM && TARGET_HARD_FLOAT"
5994   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5997 ;; The following two patterns need two branch instructions, since there is
5998 ;; no single instruction that will handle all cases.
5999 (define_expand "buneq"
6000   [(set (pc)
6001         (if_then_else (uneq (match_dup 1) (const_int 0))
6002                       (label_ref (match_operand 0 "" ""))
6003                       (pc)))]
6004   "TARGET_ARM && TARGET_HARD_FLOAT"
6005   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6008 (define_expand "bltgt"
6009   [(set (pc)
6010         (if_then_else (ltgt (match_dup 1) (const_int 0))
6011                       (label_ref (match_operand 0 "" ""))
6012                       (pc)))]
6013   "TARGET_ARM && TARGET_HARD_FLOAT"
6014   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6018 ;; Patterns to match conditional branch insns.
6021 ; Special pattern to match UNEQ.
6022 (define_insn "*arm_buneq"
6023   [(set (pc)
6024         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6025                       (label_ref (match_operand 0 "" ""))
6026                       (pc)))]
6027   "TARGET_ARM && TARGET_HARD_FLOAT"
6028   "*
6029   if (arm_ccfsm_state != 0)
6030     abort ();
6032   return \"bvs\\t%l0\;beq\\t%l0\";
6033   "
6034   [(set_attr "conds" "jump_clob")
6035    (set_attr "length" "8")]
6038 ; Special pattern to match LTGT.
6039 (define_insn "*arm_bltgt"
6040   [(set (pc)
6041         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6042                       (label_ref (match_operand 0 "" ""))
6043                       (pc)))]
6044   "TARGET_ARM && TARGET_HARD_FLOAT"
6045   "*
6046   if (arm_ccfsm_state != 0)
6047     abort ();
6049   return \"bmi\\t%l0\;bgt\\t%l0\";
6050   "
6051   [(set_attr "conds" "jump_clob")
6052    (set_attr "length" "8")]
6055 (define_insn "*arm_cond_branch"
6056   [(set (pc)
6057         (if_then_else (match_operator 1 "arm_comparison_operator"
6058                        [(match_operand 2 "cc_register" "") (const_int 0)])
6059                       (label_ref (match_operand 0 "" ""))
6060                       (pc)))]
6061   "TARGET_ARM"
6062   "*
6063   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6064     {
6065       arm_ccfsm_state += 2;
6066       return \"\";
6067     }
6068   return \"b%d1\\t%l0\";
6069   "
6070   [(set_attr "conds" "use")]
6073 ; Special pattern to match reversed UNEQ.
6074 (define_insn "*arm_buneq_reversed"
6075   [(set (pc)
6076         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6077                       (pc)
6078                       (label_ref (match_operand 0 "" ""))))]
6079   "TARGET_ARM && TARGET_HARD_FLOAT"
6080   "*
6081   if (arm_ccfsm_state != 0)
6082     abort ();
6084   return \"bmi\\t%l0\;bgt\\t%l0\";
6085   "
6086   [(set_attr "conds" "jump_clob")
6087    (set_attr "length" "8")]
6090 ; Special pattern to match reversed LTGT.
6091 (define_insn "*arm_bltgt_reversed"
6092   [(set (pc)
6093         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6094                       (pc)
6095                       (label_ref (match_operand 0 "" ""))))]
6096   "TARGET_ARM && TARGET_HARD_FLOAT"
6097   "*
6098   if (arm_ccfsm_state != 0)
6099     abort ();
6101   return \"bvs\\t%l0\;beq\\t%l0\";
6102   "
6103   [(set_attr "conds" "jump_clob")
6104    (set_attr "length" "8")]
6107 (define_insn "*arm_cond_branch_reversed"
6108   [(set (pc)
6109         (if_then_else (match_operator 1 "arm_comparison_operator"
6110                        [(match_operand 2 "cc_register" "") (const_int 0)])
6111                       (pc)
6112                       (label_ref (match_operand 0 "" ""))))]
6113   "TARGET_ARM"
6114   "*
6115   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6116     {
6117       arm_ccfsm_state += 2;
6118       return \"\";
6119     }
6120   return \"b%D1\\t%l0\";
6121   "
6122   [(set_attr "conds" "use")]
6127 ; scc insns
6129 (define_expand "seq"
6130   [(set (match_operand:SI 0 "s_register_operand" "=r")
6131         (eq:SI (match_dup 1) (const_int 0)))]
6132   "TARGET_ARM"
6133   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6136 (define_expand "sne"
6137   [(set (match_operand:SI 0 "s_register_operand" "=r")
6138         (ne:SI (match_dup 1) (const_int 0)))]
6139   "TARGET_ARM"
6140   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6143 (define_expand "sgt"
6144   [(set (match_operand:SI 0 "s_register_operand" "=r")
6145         (gt:SI (match_dup 1) (const_int 0)))]
6146   "TARGET_ARM"
6147   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6150 (define_expand "sle"
6151   [(set (match_operand:SI 0 "s_register_operand" "=r")
6152         (le:SI (match_dup 1) (const_int 0)))]
6153   "TARGET_ARM"
6154   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6157 (define_expand "sge"
6158   [(set (match_operand:SI 0 "s_register_operand" "=r")
6159         (ge:SI (match_dup 1) (const_int 0)))]
6160   "TARGET_ARM"
6161   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6164 (define_expand "slt"
6165   [(set (match_operand:SI 0 "s_register_operand" "=r")
6166         (lt:SI (match_dup 1) (const_int 0)))]
6167   "TARGET_ARM"
6168   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6171 (define_expand "sgtu"
6172   [(set (match_operand:SI 0 "s_register_operand" "=r")
6173         (gtu:SI (match_dup 1) (const_int 0)))]
6174   "TARGET_ARM"
6175   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6178 (define_expand "sleu"
6179   [(set (match_operand:SI 0 "s_register_operand" "=r")
6180         (leu:SI (match_dup 1) (const_int 0)))]
6181   "TARGET_ARM"
6182   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6185 (define_expand "sgeu"
6186   [(set (match_operand:SI 0 "s_register_operand" "=r")
6187         (geu:SI (match_dup 1) (const_int 0)))]
6188   "TARGET_ARM"
6189   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6192 (define_expand "sltu"
6193   [(set (match_operand:SI 0 "s_register_operand" "=r")
6194         (ltu:SI (match_dup 1) (const_int 0)))]
6195   "TARGET_ARM"
6196   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6199 (define_expand "sunordered"
6200   [(set (match_operand:SI 0 "s_register_operand" "=r")
6201         (unordered:SI (match_dup 1) (const_int 0)))]
6202   "TARGET_ARM && TARGET_HARD_FLOAT"
6203   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6204                                       arm_compare_op1);"
6207 (define_expand "sordered"
6208   [(set (match_operand:SI 0 "s_register_operand" "=r")
6209         (ordered:SI (match_dup 1) (const_int 0)))]
6210   "TARGET_ARM && TARGET_HARD_FLOAT"
6211   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6212                                       arm_compare_op1);"
6215 (define_expand "sungt"
6216   [(set (match_operand:SI 0 "s_register_operand" "=r")
6217         (ungt:SI (match_dup 1) (const_int 0)))]
6218   "TARGET_ARM && TARGET_HARD_FLOAT"
6219   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6220                                       arm_compare_op1);"
6223 (define_expand "sunge"
6224   [(set (match_operand:SI 0 "s_register_operand" "=r")
6225         (unge:SI (match_dup 1) (const_int 0)))]
6226   "TARGET_ARM && TARGET_HARD_FLOAT"
6227   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6228                                       arm_compare_op1);"
6231 (define_expand "sunlt"
6232   [(set (match_operand:SI 0 "s_register_operand" "=r")
6233         (unlt:SI (match_dup 1) (const_int 0)))]
6234   "TARGET_ARM && TARGET_HARD_FLOAT"
6235   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6236                                       arm_compare_op1);"
6239 (define_expand "sunle"
6240   [(set (match_operand:SI 0 "s_register_operand" "=r")
6241         (unle:SI (match_dup 1) (const_int 0)))]
6242   "TARGET_ARM && TARGET_HARD_FLOAT"
6243   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6244                                       arm_compare_op1);"
6247 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6248 ;;; simple ARM instructions. 
6250 ; (define_expand "suneq"
6251 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6252 ;       (uneq:SI (match_dup 1) (const_int 0)))]
6253 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6254 ;   "abort ();"
6255 ; )
6257 ; (define_expand "sltgt"
6258 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6259 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
6260 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6261 ;   "abort ();"
6262 ; )
6264 (define_insn "*mov_scc"
6265   [(set (match_operand:SI 0 "s_register_operand" "=r")
6266         (match_operator:SI 1 "arm_comparison_operator"
6267          [(match_operand 2 "cc_register" "") (const_int 0)]))]
6268   "TARGET_ARM"
6269   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6270   [(set_attr "conds" "use")
6271    (set_attr "length" "8")]
6274 (define_insn "*mov_negscc"
6275   [(set (match_operand:SI 0 "s_register_operand" "=r")
6276         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6277                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6278   "TARGET_ARM"
6279   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6280   [(set_attr "conds" "use")
6281    (set_attr "length" "8")]
6284 (define_insn "*mov_notscc"
6285   [(set (match_operand:SI 0 "s_register_operand" "=r")
6286         (not:SI (match_operator:SI 1 "arm_comparison_operator"
6287                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6288   "TARGET_ARM"
6289   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6290   [(set_attr "conds" "use")
6291    (set_attr "length" "8")]
6295 ;; Conditional move insns
6297 (define_expand "movsicc"
6298   [(set (match_operand:SI 0 "s_register_operand" "")
6299         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6300                          (match_operand:SI 2 "arm_not_operand" "")
6301                          (match_operand:SI 3 "arm_not_operand" "")))]
6302   "TARGET_ARM"
6303   "
6304   {
6305     enum rtx_code code = GET_CODE (operands[1]);
6306     rtx ccreg;
6308     if (code == UNEQ || code == LTGT)
6309       FAIL;
6311     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6312     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6313   }"
6316 (define_expand "movsfcc"
6317   [(set (match_operand:SF 0 "s_register_operand" "")
6318         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6319                          (match_operand:SF 2 "s_register_operand" "")
6320                          (match_operand:SF 3 "nonmemory_operand" "")))]
6321   "TARGET_ARM"
6322   "
6323   {
6324     enum rtx_code code = GET_CODE (operands[1]);
6325     rtx ccreg;
6327     if (code == UNEQ || code == LTGT)
6328       FAIL;
6330     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
6331        Otherwise, ensure it is a valid FP add operand */
6332     if ((!TARGET_HARD_FLOAT)
6333         || (!fpu_add_operand (operands[3], SFmode)))
6334       operands[3] = force_reg (SFmode, operands[3]);
6336     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6337     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6338   }"
6341 (define_expand "movdfcc"
6342   [(set (match_operand:DF 0 "s_register_operand" "")
6343         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6344                          (match_operand:DF 2 "s_register_operand" "")
6345                          (match_operand:DF 3 "fpu_add_operand" "")))]
6346   "TARGET_ARM && TARGET_HARD_FLOAT"
6347   "
6348   {
6349     enum rtx_code code = GET_CODE (operands[1]);
6350     rtx ccreg;
6352     if (code == UNEQ || code == LTGT)
6353       FAIL;
6355     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6356     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6357   }"
6360 (define_insn "*movsicc_insn"
6361   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6362         (if_then_else:SI
6363          (match_operator 3 "arm_comparison_operator"
6364           [(match_operand 4 "cc_register" "") (const_int 0)])
6365          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6366          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6367   "TARGET_ARM"
6368   "@
6369    mov%D3\\t%0, %2
6370    mvn%D3\\t%0, #%B2
6371    mov%d3\\t%0, %1
6372    mvn%d3\\t%0, #%B1
6373    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6374    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6375    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6376    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6377   [(set_attr "length" "4,4,4,4,8,8,8,8")
6378    (set_attr "conds" "use")]
6381 (define_insn "*movsfcc_hard_insn"
6382   [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6383         (if_then_else:SF
6384          (match_operator 3 "arm_comparison_operator" 
6385           [(match_operand 4 "cc_register" "") (const_int 0)])
6386          (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6387          (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6388   "TARGET_ARM && TARGET_HARD_FLOAT"
6389   "@
6390    mvf%D3s\\t%0, %2
6391    mnf%D3s\\t%0, #%N2
6392    mvf%d3s\\t%0, %1
6393    mnf%d3s\\t%0, #%N1
6394    mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6395    mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6396    mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6397    mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6398   [(set_attr "length" "4,4,4,4,8,8,8,8")
6399    (set_attr "type" "ffarith")
6400    (set_attr "conds" "use")]
6403 (define_insn "*movsfcc_soft_insn"
6404   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6405         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6406                           [(match_operand 4 "cc_register" "") (const_int 0)])
6407                          (match_operand:SF 1 "s_register_operand" "0,r")
6408                          (match_operand:SF 2 "s_register_operand" "r,0")))]
6409   "TARGET_ARM && TARGET_SOFT_FLOAT"
6410   "@
6411    mov%D3\\t%0, %2
6412    mov%d3\\t%0, %1"
6413   [(set_attr "conds" "use")]
6416 (define_insn "*movdfcc_insn"
6417   [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6418         (if_then_else:DF
6419          (match_operator 3 "arm_comparison_operator"
6420           [(match_operand 4 "cc_register" "") (const_int 0)])
6421          (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6422          (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6423   "TARGET_ARM && TARGET_HARD_FLOAT"
6424   "@
6425    mvf%D3d\\t%0, %2
6426    mnf%D3d\\t%0, #%N2
6427    mvf%d3d\\t%0, %1
6428    mnf%d3d\\t%0, #%N1
6429    mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6430    mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6431    mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6432    mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6433   [(set_attr "length" "4,4,4,4,8,8,8,8")
6434    (set_attr "type" "ffarith")
6435    (set_attr "conds" "use")]
6439 ;; Jump and linkage insns
6441 (define_expand "jump"
6442   [(set (pc)
6443         (label_ref (match_operand 0 "" "")))]
6444   "TARGET_EITHER"
6445   ""
6448 (define_insn "*arm_jump"
6449   [(set (pc)
6450         (label_ref (match_operand 0 "" "")))]
6451   "TARGET_ARM"
6452   "*
6453   {
6454     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6455       {
6456         arm_ccfsm_state += 2;
6457         return \"\";
6458       }
6459     return \"b%?\\t%l0\";
6460   }
6461   "
6462   [(set_attr "predicable" "yes")]
6465 (define_insn "*thumb_jump"
6466   [(set (pc)
6467         (label_ref (match_operand 0 "" "")))]
6468   "TARGET_THUMB"
6469   "*
6470   if (get_attr_length (insn) == 2)
6471     return \"b\\t%l0\";
6472   return \"bl\\t%l0\\t%@ far jump\";
6473   "
6474   [(set (attr "far_jump")
6475         (if_then_else
6476             (eq_attr "length" "4")
6477             (const_string "yes")
6478             (const_string "no")))
6479    (set (attr "length") 
6480         (if_then_else
6481             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6482                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
6483             (const_int 2)
6484             (const_int 4)))]
6487 (define_expand "call"
6488   [(parallel [(call (match_operand 0 "memory_operand" "")
6489                     (match_operand 1 "general_operand" ""))
6490               (use (match_operand 2 "" ""))
6491               (clobber (reg:SI LR_REGNUM))])]
6492   "TARGET_EITHER"
6493   "
6494   {
6495     rtx callee;
6496     
6497     /* In an untyped call, we can get NULL for operand 2.  */
6498     if (operands[2] == NULL_RTX)
6499       operands[2] = const0_rtx;
6500       
6501     /* This is to decide if we should generate indirect calls by loading the
6502        32 bit address of the callee into a register before performing the
6503        branch and link.  operand[2] encodes the long_call/short_call
6504        attribute of the function being called.  This attribute is set whenever
6505        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6506        is used, and the short_call attribute can also be set if function is
6507        declared as static or if it has already been defined in the current
6508        compilation unit.  See arm.c and arm.h for info about this.  The third
6509        parameter to arm_is_longcall_p is used to tell it which pattern
6510        invoked it.  */
6511     callee  = XEXP (operands[0], 0);
6512     
6513     if (GET_CODE (callee) != REG
6514        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6515       XEXP (operands[0], 0) = force_reg (Pmode, callee);
6516   }"
6519 (define_insn "*call_reg"
6520   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6521          (match_operand 1 "" ""))
6522    (use (match_operand 2 "" ""))
6523    (clobber (reg:SI LR_REGNUM))]
6524   "TARGET_ARM"
6525   "*
6526   return output_call (operands);
6527   "
6528   ;; length is worst case, normally it is only two
6529   [(set_attr "length" "12")
6530    (set_attr "type" "call")]
6533 (define_insn "*call_mem"
6534   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6535          (match_operand 1 "" ""))
6536    (use (match_operand 2 "" ""))
6537    (clobber (reg:SI LR_REGNUM))]
6538   "TARGET_ARM"
6539   "*
6540   return output_call_mem (operands);
6541   "
6542   [(set_attr "length" "12")
6543    (set_attr "type" "call")]
6546 (define_insn "*call_indirect"
6547   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6548          (match_operand 1 "" ""))
6549    (use (match_operand 2 "" ""))
6550    (clobber (reg:SI LR_REGNUM))]
6551   "TARGET_THUMB"
6552   "*
6553   {
6554     if (TARGET_CALLER_INTERWORKING)
6555       return \"bl\\t%__interwork_call_via_%0\";
6556     else
6557       return \"bl\\t%__call_via_%0\";
6558   }"
6559   [(set_attr "type" "call")]
6562 (define_insn "*call_value_indirect"
6563   [(set (match_operand 0 "" "=l")
6564         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6565               (match_operand 2 "" "")))
6566    (use (match_operand 3 "" ""))
6567    (clobber (reg:SI LR_REGNUM))]
6568   "TARGET_THUMB"
6569   "*
6570   {
6571     if (TARGET_CALLER_INTERWORKING)
6572       return \"bl\\t%__interwork_call_via_%1\";
6573     else
6574       return \"bl\\t%__call_via_%1\";
6575   }"
6576   [(set_attr "type" "call")]
6579 (define_expand "call_value"
6580   [(parallel [(set (match_operand       0 "" "")
6581                    (call (match_operand 1 "memory_operand" "")
6582                          (match_operand 2 "general_operand" "")))
6583               (use (match_operand 3 "" ""))
6584               (clobber (reg:SI LR_REGNUM))])]
6585   "TARGET_EITHER"
6586   "
6587   {
6588     rtx callee = XEXP (operands[1], 0);
6589     
6590     /* In an untyped call, we can get NULL for operand 2.  */
6591     if (operands[3] == 0)
6592       operands[3] = const0_rtx;
6593       
6594     /* See the comment in define_expand \"call\".  */
6595     if (GET_CODE (callee) != REG
6596         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6597       XEXP (operands[1], 0) = force_reg (Pmode, callee);
6598   }"
6601 (define_insn "*call_value_reg"
6602   [(set (match_operand 0 "" "=r,f")
6603         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6604               (match_operand 2 "" "")))
6605    (use (match_operand 3 "" ""))
6606    (clobber (reg:SI LR_REGNUM))]
6607   "TARGET_ARM"
6608   "*
6609   return output_call (&operands[1]);
6610   "
6611   [(set_attr "length" "12")
6612    (set_attr "type" "call")]
6615 (define_insn "*call_value_mem"
6616   [(set (match_operand 0 "" "=r,f")
6617         (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6618               (match_operand 2 "" "")))
6619    (use (match_operand 3 "" ""))
6620    (clobber (reg:SI LR_REGNUM))]
6621   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6622   "*
6623   return output_call_mem (&operands[1]);
6624   "
6625   [(set_attr "length" "12")
6626    (set_attr "type" "call")]
6629 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6630 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6632 (define_insn "*call_symbol"
6633   [(call (mem:SI (match_operand:SI 0 "" "X"))
6634          (match_operand 1 "" ""))
6635    (use (match_operand 2 "" ""))
6636    (clobber (reg:SI LR_REGNUM))]
6637   "TARGET_ARM
6638    && (GET_CODE (operands[0]) == SYMBOL_REF)
6639    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6640   "*
6641   {
6642     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6643   }"
6644   [(set_attr "type" "call")]
6647 (define_insn "*call_value_symbol"
6648   [(set (match_operand 0 "s_register_operand" "=r,f")
6649         (call (mem:SI (match_operand:SI 1 "" "X,X"))
6650         (match_operand:SI 2 "" "")))
6651    (use (match_operand 3 "" ""))
6652    (clobber (reg:SI LR_REGNUM))]
6653   "TARGET_ARM
6654    && (GET_CODE (operands[1]) == SYMBOL_REF)
6655    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6656   "*
6657   {
6658     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6659   }"
6660   [(set_attr "type" "call")]
6663 (define_insn "*call_insn"
6664   [(call (mem:SI (match_operand:SI 0 "" "X"))
6665          (match_operand:SI 1 "" ""))
6666    (use (match_operand 2 "" ""))
6667    (clobber (reg:SI LR_REGNUM))]
6668   "TARGET_THUMB
6669    && GET_CODE (operands[0]) == SYMBOL_REF
6670    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6671   "bl\\t%a0"
6672   [(set_attr "length" "4")
6673    (set_attr "type" "call")]
6676 (define_insn "*call_value_insn"
6677   [(set (match_operand 0 "register_operand" "=l")
6678         (call (mem:SI (match_operand 1 "" "X"))
6679               (match_operand 2 "" "")))
6680    (use (match_operand 3 "" ""))
6681    (clobber (reg:SI LR_REGNUM))]
6682   "TARGET_THUMB
6683    && GET_CODE (operands[1]) == SYMBOL_REF
6684    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6685   "bl\\t%a1"
6686   [(set_attr "length" "4")
6687    (set_attr "type" "call")]
6690 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6691 (define_expand "sibcall"
6692   [(parallel [(call (match_operand 0 "memory_operand" "")
6693                     (match_operand 1 "general_operand" ""))
6694               (use (match_operand 2 "" ""))
6695               (use (reg:SI LR_REGNUM))])]
6696   "TARGET_ARM"
6697   "
6698   {
6699     if (operands[2] == NULL_RTX)
6700       operands[2] = const0_rtx;
6701   }"
6704 (define_expand "sibcall_value"
6705   [(parallel [(set (match_operand 0 "register_operand" "")
6706                    (call (match_operand 1 "memory_operand" "")
6707                          (match_operand 2 "general_operand" "")))
6708               (use (match_operand 3 "" ""))
6709               (use (reg:SI LR_REGNUM))])]
6710   "TARGET_ARM"
6711   "
6712   {
6713     if (operands[3] == NULL_RTX)
6714       operands[3] = const0_rtx;
6715   }"
6718 (define_insn "*sibcall_insn"
6719  [(call (mem:SI (match_operand:SI 0 "" "X"))
6720         (match_operand 1 "" ""))
6721   (use (match_operand 2 "" ""))
6722   (use (reg:SI LR_REGNUM))]
6723   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6724   "*
6725   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6726   "
6727   [(set_attr "type" "call")]
6730 (define_insn "*sibcall_value_insn"
6731  [(set (match_operand 0 "s_register_operand" "=r,f")
6732        (call (mem:SI (match_operand:SI 1 "" "X,X"))
6733              (match_operand 2 "" "")))
6734   (use (match_operand 3 "" ""))
6735   (use (reg:SI LR_REGNUM))]
6736   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6737   "*
6738   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6739   "
6740   [(set_attr "type" "call")]
6743 ;; Often the return insn will be the same as loading from memory, so set attr
6744 (define_insn "return"
6745   [(return)]
6746   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6747   "*
6748   {
6749     if (arm_ccfsm_state == 2)
6750       {
6751         arm_ccfsm_state += 2;
6752         return \"\";
6753       }
6754     return output_return_instruction (const_true_rtx, TRUE, FALSE);
6755   }"
6756   [(set_attr "type" "load")
6757    (set_attr "predicable" "yes")]
6760 (define_insn "*cond_return"
6761   [(set (pc)
6762         (if_then_else (match_operator 0 "arm_comparison_operator"
6763                        [(match_operand 1 "cc_register" "") (const_int 0)])
6764                       (return)
6765                       (pc)))]
6766   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6767   "*
6768   {
6769     if (arm_ccfsm_state == 2)
6770       {
6771         arm_ccfsm_state += 2;
6772         return \"\";
6773       }
6774     return output_return_instruction (operands[0], TRUE, FALSE);
6775   }"
6776   [(set_attr "conds" "use")
6777    (set_attr "type" "load")]
6780 (define_insn "*cond_return_inverted"
6781   [(set (pc)
6782         (if_then_else (match_operator 0 "arm_comparison_operator"
6783                        [(match_operand 1 "cc_register" "") (const_int 0)])
6784                       (pc)
6785                       (return)))]
6786   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6787   "*
6788   {
6789     if (arm_ccfsm_state == 2)
6790       {
6791         arm_ccfsm_state += 2;
6792         return \"\";
6793       }
6794     return output_return_instruction (operands[0], TRUE, TRUE);
6795   }"
6796   [(set_attr "conds" "use")
6797    (set_attr "type" "load")]
6800 ;; Call subroutine returning any type.
6802 (define_expand "untyped_call"
6803   [(parallel [(call (match_operand 0 "" "")
6804                     (const_int 0))
6805               (match_operand 1 "" "")
6806               (match_operand 2 "" "")])]
6807   "TARGET_ARM"
6808   "
6809   {
6810     int i;
6812     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6814     for (i = 0; i < XVECLEN (operands[2], 0); i++)
6815       {
6816         rtx set = XVECEXP (operands[2], 0, i);
6818         emit_move_insn (SET_DEST (set), SET_SRC (set));
6819       }
6821     /* The optimizer does not know that the call sets the function value
6822        registers we stored in the result block.  We avoid problems by
6823        claiming that all hard registers are used and clobbered at this
6824        point.  */
6825     emit_insn (gen_blockage ());
6827     DONE;
6828   }"
6831 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6832 ;; all of memory.  This blocks insns from being moved across this point.
6834 (define_insn "blockage"
6835   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6836   "TARGET_EITHER"
6837   ""
6838   [(set_attr "length" "0")
6839    (set_attr "type" "block")]
6842 (define_expand "casesi"
6843   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6844    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
6845    (match_operand:SI 2 "const_int_operand" "")  ; total range
6846    (match_operand:SI 3 "" "")                   ; table label
6847    (match_operand:SI 4 "" "")]                  ; Out of range label
6848   "TARGET_ARM"
6849   "
6850   {
6851     rtx reg;
6852     if (operands[1] != const0_rtx)
6853       {
6854         reg = gen_reg_rtx (SImode);
6856         emit_insn (gen_addsi3 (reg, operands[0],
6857                                GEN_INT (-INTVAL (operands[1]))));
6858         operands[0] = reg;
6859       }
6861     if (!const_ok_for_arm (INTVAL (operands[2])))
6862       operands[2] = force_reg (SImode, operands[2]);
6864     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6865                                          operands[4]));
6866     DONE;
6867   }"
6870 ;; The USE in this pattern is needed to tell flow analysis that this is
6871 ;; a CASESI insn.  It has no other purpose.
6872 (define_insn "casesi_internal"
6873   [(parallel [(set (pc)
6874                (if_then_else
6875                 (leu (match_operand:SI 0 "s_register_operand" "r")
6876                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
6877                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6878                                  (label_ref (match_operand 2 "" ""))))
6879                 (label_ref (match_operand 3 "" ""))))
6880               (clobber (reg:CC CC_REGNUM))
6881               (use (label_ref (match_dup 2)))])]
6882   "TARGET_ARM"
6883   "*
6884     if (flag_pic)
6885       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6886     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6887   "
6888   [(set_attr "conds" "clob")
6889    (set_attr "length" "12")]
6892 (define_expand "indirect_jump"
6893   [(set (pc)
6894         (match_operand:SI 0 "s_register_operand" ""))]
6895   "TARGET_EITHER"
6896   ""
6899 (define_insn "*arm_indirect_jump"
6900   [(set (pc)
6901         (match_operand:SI 0 "s_register_operand" "r"))]
6902   "TARGET_ARM"
6903   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6904   [(set_attr "predicable" "yes")]
6907 ;; Although not supported by the define_expand above,
6908 ;; cse/combine may generate this form.
6909 (define_insn "*load_indirect_jump"
6910   [(set (pc)
6911         (match_operand:SI 0 "memory_operand" "m"))]
6912   "TARGET_ARM"
6913   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6914   [(set_attr "type" "load")
6915    (set_attr "pool_range" "4096")
6916    (set_attr "neg_pool_range" "4084")
6917    (set_attr "predicable" "yes")]
6920 (define_insn "*thumb_indirect_jump"
6921   [(set (pc)
6922         (match_operand:SI 0 "register_operand" "l*r"))]
6923   "TARGET_THUMB"
6924   "mov\\tpc, %0"
6925   [(set_attr "conds" "clob")
6926    (set_attr "length" "2")]
6930 ;; Misc insns
6932 (define_insn "nop"
6933   [(const_int 0)]
6934   "TARGET_EITHER"
6935   "*
6936   if (TARGET_ARM)
6937     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6938   return  \"mov\\tr8, r8\";
6939   "
6940   [(set (attr "length")
6941         (if_then_else (eq_attr "is_thumb" "yes")
6942                       (const_int 2)
6943                       (const_int 4)))]
6947 ;; Patterns to allow combination of arithmetic, cond code and shifts
6949 (define_insn "*arith_shiftsi"
6950   [(set (match_operand:SI 0 "s_register_operand" "=r")
6951         (match_operator:SI 1 "shiftable_operator"
6952           [(match_operator:SI 3 "shift_operator"
6953              [(match_operand:SI 4 "s_register_operand" "r")
6954               (match_operand:SI 5 "reg_or_int_operand" "rI")])
6955            (match_operand:SI 2 "s_register_operand" "r")]))]
6956   "TARGET_ARM"
6957   "%i1%?\\t%0, %2, %4%S3"
6958   [(set_attr "predicable" "yes")
6959    (set_attr "shift" "4")
6960    ]
6963 (define_insn "*arith_shiftsi_compare0"
6964   [(set (reg:CC_NOOV CC_REGNUM)
6965         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6966                           [(match_operator:SI 3 "shift_operator"
6967                             [(match_operand:SI 4 "s_register_operand" "r")
6968                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6969                            (match_operand:SI 2 "s_register_operand" "r")])
6970                          (const_int 0)))
6971    (set (match_operand:SI 0 "s_register_operand" "=r")
6972         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6973                          (match_dup 2)]))]
6974   "TARGET_ARM"
6975   "%i1%?s\\t%0, %2, %4%S3"
6976   [(set_attr "conds" "set")
6977    (set_attr "shift" "4")
6978    ]
6981 (define_insn "*arith_shiftsi_compare0_scratch"
6982   [(set (reg:CC_NOOV CC_REGNUM)
6983         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6984                           [(match_operator:SI 3 "shift_operator"
6985                             [(match_operand:SI 4 "s_register_operand" "r")
6986                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6987                            (match_operand:SI 2 "s_register_operand" "r")])
6988                          (const_int 0)))
6989    (clobber (match_scratch:SI 0 "=r"))]
6990   "TARGET_ARM"
6991   "%i1%?s\\t%0, %2, %4%S3"
6992   [(set_attr "conds" "set")
6993    (set_attr "shift" "4")
6994    ]
6997 (define_insn "*sub_shiftsi"
6998   [(set (match_operand:SI 0 "s_register_operand" "=r")
6999         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7000                   (match_operator:SI 2 "shift_operator"
7001                    [(match_operand:SI 3 "s_register_operand" "r")
7002                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7003   "TARGET_ARM"
7004   "sub%?\\t%0, %1, %3%S2"
7005   [(set_attr "predicable" "yes")
7006    (set_attr "shift" "3")
7007    ]
7010 (define_insn "*sub_shiftsi_compare0"
7011   [(set (reg:CC_NOOV CC_REGNUM)
7012         (compare:CC_NOOV
7013          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7014                    (match_operator:SI 2 "shift_operator"
7015                     [(match_operand:SI 3 "s_register_operand" "r")
7016                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7017          (const_int 0)))
7018    (set (match_operand:SI 0 "s_register_operand" "=r")
7019         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7020                                                  (match_dup 4)])))]
7021   "TARGET_ARM"
7022   "sub%?s\\t%0, %1, %3%S2"
7023   [(set_attr "conds" "set")
7024    (set_attr "shift" "3") 
7025    ]
7028 (define_insn "*sub_shiftsi_compare0_scratch"
7029   [(set (reg:CC_NOOV CC_REGNUM)
7030         (compare:CC_NOOV
7031          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7032                    (match_operator:SI 2 "shift_operator"
7033                     [(match_operand:SI 3 "s_register_operand" "r")
7034                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7035          (const_int 0)))
7036    (clobber (match_scratch:SI 0 "=r"))]
7037   "TARGET_ARM"
7038   "sub%?s\\t%0, %1, %3%S2"
7039   [(set_attr "conds" "set")
7040    (set_attr "shift" "3") 
7041    ]
7046 (define_insn "*and_scc"
7047   [(set (match_operand:SI 0 "s_register_operand" "=r")
7048         (and:SI (match_operator:SI 1 "arm_comparison_operator"
7049                  [(match_operand 3 "cc_register" "") (const_int 0)])
7050                 (match_operand:SI 2 "s_register_operand" "r")))]
7051   "TARGET_ARM"
7052   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7053   [(set_attr "conds" "use")
7054    (set_attr "length" "8")]
7057 (define_insn "*ior_scc"
7058   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7059         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7060                  [(match_operand 3 "cc_register" "") (const_int 0)])
7061                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7062   "TARGET_ARM"
7063   "@
7064    orr%d2\\t%0, %1, #1
7065    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7066   [(set_attr "conds" "use")
7067    (set_attr "length" "4,8")]
7070 (define_insn "*compare_scc"
7071   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7072         (match_operator:SI 1 "arm_comparison_operator"
7073          [(match_operand:SI 2 "s_register_operand" "r,r")
7074           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7075    (clobber (reg:CC CC_REGNUM))]
7076   "TARGET_ARM"
7077   "*
7078     if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7079       return \"mov\\t%0, %2, lsr #31\";
7081     if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7082       return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7084     if (GET_CODE (operands[1]) == NE)
7085       {
7086         if (which_alternative == 1)
7087           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7088         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7089       }
7090     if (which_alternative == 1)
7091       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7092     else
7093       output_asm_insn (\"cmp\\t%2, %3\", operands);
7094     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7095   "
7096   [(set_attr "conds" "clob")
7097    (set_attr "length" "12")]
7100 (define_insn "*cond_move"
7101   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7102         (if_then_else:SI (match_operator 3 "equality_operator"
7103                           [(match_operator 4 "arm_comparison_operator"
7104                             [(match_operand 5 "cc_register" "") (const_int 0)])
7105                            (const_int 0)])
7106                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7107                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7108   "TARGET_ARM"
7109   "*
7110     if (GET_CODE (operands[3]) == NE)
7111       {
7112         if (which_alternative != 1)
7113           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7114         if (which_alternative != 0)
7115           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7116         return \"\";
7117       }
7118     if (which_alternative != 0)
7119       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7120     if (which_alternative != 1)
7121       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7122     return \"\";
7123   "
7124   [(set_attr "conds" "use")
7125    (set_attr "length" "4,4,8")]
7128 (define_insn "*cond_arith"
7129   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7130         (match_operator:SI 5 "shiftable_operator" 
7131          [(match_operator:SI 4 "arm_comparison_operator"
7132            [(match_operand:SI 2 "s_register_operand" "r,r")
7133             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7134           (match_operand:SI 1 "s_register_operand" "0,?r")]))
7135    (clobber (reg:CC CC_REGNUM))]
7136   "TARGET_ARM"
7137   "*
7138     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7139       return \"%i5\\t%0, %1, %2, lsr #31\";
7141     output_asm_insn (\"cmp\\t%2, %3\", operands);
7142     if (GET_CODE (operands[5]) == AND)
7143       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7144     else if (GET_CODE (operands[5]) == MINUS)
7145       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7146     else if (which_alternative != 0)
7147       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7148     return \"%i5%d4\\t%0, %1, #1\";
7149   "
7150   [(set_attr "conds" "clob")
7151    (set_attr "length" "12")]
7154 (define_insn "*cond_sub"
7155   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7156         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7157                   (match_operator:SI 4 "arm_comparison_operator"
7158                    [(match_operand:SI 2 "s_register_operand" "r,r")
7159                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7160    (clobber (reg:CC CC_REGNUM))]
7161   "TARGET_ARM"
7162   "*
7163     output_asm_insn (\"cmp\\t%2, %3\", operands);
7164     if (which_alternative != 0)
7165       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7166     return \"sub%d4\\t%0, %1, #1\";
7167   "
7168   [(set_attr "conds" "clob")
7169    (set_attr "length" "8,12")]
7172 (define_insn "*cmp_ite0"
7173   [(set (match_operand 6 "dominant_cc_register" "")
7174         (compare
7175          (if_then_else:SI
7176           (match_operator 4 "arm_comparison_operator"
7177            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7178             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7179           (match_operator:SI 5 "arm_comparison_operator"
7180            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7181             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7182           (const_int 0))
7183          (const_int 0)))]
7184   "TARGET_ARM"
7185   "*
7186   {
7187     static const char * const opcodes[4][2] =
7188     {
7189       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7190        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7191       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7192        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7193       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7194        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7195       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7196        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7197     };
7198     int swap =
7199       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7201     return opcodes[which_alternative][swap];
7202   }"
7203   [(set_attr "conds" "set")
7204    (set_attr "length" "8")]
7207 (define_insn "*cmp_ite1"
7208   [(set (match_operand 6 "dominant_cc_register" "")
7209         (compare
7210          (if_then_else:SI
7211           (match_operator 4 "arm_comparison_operator"
7212            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7213             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7214           (match_operator:SI 5 "arm_comparison_operator"
7215            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7216             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7217           (const_int 1))
7218          (const_int 0)))]
7219   "TARGET_ARM"
7220   "*
7221   {
7222     static const char * const opcodes[4][2] =
7223     {
7224       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7225        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7226       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7227        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7228       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7229        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7230       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7231        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7232     };
7233     int swap =
7234       comparison_dominates_p (GET_CODE (operands[5]),
7235                               reverse_condition (GET_CODE (operands[4])));
7237     return opcodes[which_alternative][swap];
7238   }"
7239   [(set_attr "conds" "set")
7240    (set_attr "length" "8")]
7243 (define_insn "*cmp_and"
7244   [(set (match_operand 6 "dominant_cc_register" "")
7245         (compare
7246          (and:SI
7247           (match_operator 4 "arm_comparison_operator"
7248            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7249             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7250           (match_operator:SI 5 "arm_comparison_operator"
7251            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7252             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7253          (const_int 0)))]
7254   "TARGET_ARM"
7255   "*
7256   {
7257     static const char *const opcodes[4][2] =
7258     {
7259       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7260        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7261       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7262        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7263       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7264        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7265       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7266        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7267     };
7268     int swap =
7269       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7271     return opcodes[which_alternative][swap];
7272   }"
7273   [(set_attr "conds" "set")
7274    (set_attr "predicable" "no")
7275    (set_attr "length" "8")]
7278 (define_insn "*cmp_ior"
7279   [(set (match_operand 6 "dominant_cc_register" "")
7280         (compare
7281          (ior:SI
7282           (match_operator 4 "arm_comparison_operator"
7283            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7284             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7285           (match_operator:SI 5 "arm_comparison_operator"
7286            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7287             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7288          (const_int 0)))]
7289   "TARGET_ARM"
7290   "*
7292   static const char *const opcodes[4][2] =
7293   {
7294     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7295      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7296     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7297      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7298     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7299      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7300     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7301      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7302   };
7303   int swap =
7304     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7306   return opcodes[which_alternative][swap];
7309   [(set_attr "conds" "set")
7310    (set_attr "length" "8")]
7313 (define_insn "*negscc"
7314   [(set (match_operand:SI 0 "s_register_operand" "=r")
7315         (neg:SI (match_operator 3 "arm_comparison_operator"
7316                  [(match_operand:SI 1 "s_register_operand" "r")
7317                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7318    (clobber (reg:CC CC_REGNUM))]
7319   "TARGET_ARM"
7320   "*
7321   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7322     return \"mov\\t%0, %1, asr #31\";
7324   if (GET_CODE (operands[3]) == NE)
7325     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7327   if (GET_CODE (operands[3]) == GT)
7328     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7330   output_asm_insn (\"cmp\\t%1, %2\", operands);
7331   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7332   return \"mvn%d3\\t%0, #0\";
7333   "
7334   [(set_attr "conds" "clob")
7335    (set_attr "length" "12")]
7338 (define_insn "movcond"
7339   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7340         (if_then_else:SI
7341          (match_operator 5 "arm_comparison_operator"
7342           [(match_operand:SI 3 "s_register_operand" "r,r,r")
7343            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7344          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7345          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7346    (clobber (reg:CC CC_REGNUM))]
7347   "TARGET_ARM"
7348   "*
7349   if (GET_CODE (operands[5]) == LT
7350       && (operands[4] == const0_rtx))
7351     {
7352       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7353         {
7354           if (operands[2] == const0_rtx)
7355             return \"and\\t%0, %1, %3, asr #31\";
7356           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7357         }
7358       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7359         {
7360           if (operands[1] == const0_rtx)
7361             return \"bic\\t%0, %2, %3, asr #31\";
7362           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7363         }
7364       /* The only case that falls through to here is when both ops 1 & 2
7365          are constants */
7366     }
7368   if (GET_CODE (operands[5]) == GE
7369       && (operands[4] == const0_rtx))
7370     {
7371       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7372         {
7373           if (operands[2] == const0_rtx)
7374             return \"bic\\t%0, %1, %3, asr #31\";
7375           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7376         }
7377       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7378         {
7379           if (operands[1] == const0_rtx)
7380             return \"and\\t%0, %2, %3, asr #31\";
7381           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7382         }
7383       /* The only case that falls through to here is when both ops 1 & 2
7384          are constants */
7385     }
7386   if (GET_CODE (operands[4]) == CONST_INT
7387       && !const_ok_for_arm (INTVAL (operands[4])))
7388     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7389   else
7390     output_asm_insn (\"cmp\\t%3, %4\", operands);
7391   if (which_alternative != 0)
7392     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7393   if (which_alternative != 1)
7394     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7395   return \"\";
7396   "
7397   [(set_attr "conds" "clob")
7398    (set_attr "length" "8,8,12")]
7401 (define_insn "*ifcompare_plus_move"
7402   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7403         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7404                           [(match_operand:SI 4 "s_register_operand" "r,r")
7405                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7406                          (plus:SI
7407                           (match_operand:SI 2 "s_register_operand" "r,r")
7408                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7409                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7410    (clobber (reg:CC CC_REGNUM))]
7411   "TARGET_ARM"
7412   "#"
7413   [(set_attr "conds" "clob")
7414    (set_attr "length" "8,12")]
7417 (define_insn "*if_plus_move"
7418   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7419         (if_then_else:SI
7420          (match_operator 4 "arm_comparison_operator"
7421           [(match_operand 5 "cc_register" "") (const_int 0)])
7422          (plus:SI
7423           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7424           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7425          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7426   "TARGET_ARM"
7427   "@
7428    add%d4\\t%0, %2, %3
7429    sub%d4\\t%0, %2, #%n3
7430    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7431    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7432   [(set_attr "conds" "use")
7433    (set_attr "length" "4,4,8,8")
7434    (set_attr "type" "*,*,*,*")]
7437 (define_insn "*ifcompare_move_plus"
7438   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7439         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7440                           [(match_operand:SI 4 "s_register_operand" "r,r")
7441                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7442                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7443                          (plus:SI
7444                           (match_operand:SI 2 "s_register_operand" "r,r")
7445                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7446    (clobber (reg:CC CC_REGNUM))]
7447   "TARGET_ARM"
7448   "#"
7449   [(set_attr "conds" "clob")
7450    (set_attr "length" "8,12")]
7453 (define_insn "*if_move_plus"
7454   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7455         (if_then_else:SI
7456          (match_operator 4 "arm_comparison_operator"
7457           [(match_operand 5 "cc_register" "") (const_int 0)])
7458          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7459          (plus:SI
7460           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7461           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7462   "TARGET_ARM"
7463   "@
7464    add%D4\\t%0, %2, %3
7465    sub%D4\\t%0, %2, #%n3
7466    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7467    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7468   [(set_attr "conds" "use")
7469    (set_attr "length" "4,4,8,8")
7470    (set_attr "type" "*,*,*,*")]
7473 (define_insn "*ifcompare_arith_arith"
7474   [(set (match_operand:SI 0 "s_register_operand" "=r")
7475         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7476                           [(match_operand:SI 5 "s_register_operand" "r")
7477                            (match_operand:SI 6 "arm_add_operand" "rIL")])
7478                          (match_operator:SI 8 "shiftable_operator"
7479                           [(match_operand:SI 1 "s_register_operand" "r")
7480                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7481                          (match_operator:SI 7 "shiftable_operator"
7482                           [(match_operand:SI 3 "s_register_operand" "r")
7483                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7484    (clobber (reg:CC CC_REGNUM))]
7485   "TARGET_ARM"
7486   "#"
7487   [(set_attr "conds" "clob")
7488    (set_attr "length" "12")]
7491 (define_insn "*if_arith_arith"
7492   [(set (match_operand:SI 0 "s_register_operand" "=r")
7493         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7494                           [(match_operand 8 "cc_register" "") (const_int 0)])
7495                          (match_operator:SI 6 "shiftable_operator"
7496                           [(match_operand:SI 1 "s_register_operand" "r")
7497                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7498                          (match_operator:SI 7 "shiftable_operator"
7499                           [(match_operand:SI 3 "s_register_operand" "r")
7500                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7501   "TARGET_ARM"
7502   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7503   [(set_attr "conds" "use")
7504    (set_attr "length" "8")]
7507 (define_insn "*ifcompare_arith_move"
7508   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7509         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7510                           [(match_operand:SI 2 "s_register_operand" "r,r")
7511                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7512                          (match_operator:SI 7 "shiftable_operator"
7513                           [(match_operand:SI 4 "s_register_operand" "r,r")
7514                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7515                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7516    (clobber (reg:CC CC_REGNUM))]
7517   "TARGET_ARM"
7518   "*
7519   /* If we have an operation where (op x 0) is the identity operation and
7520      the conditional operator is LT or GE and we are comparing against zero and
7521      everything is in registers then we can do this in two instructions */
7522   if (operands[3] == const0_rtx
7523       && GET_CODE (operands[7]) != AND
7524       && GET_CODE (operands[5]) == REG
7525       && GET_CODE (operands[1]) == REG 
7526       && REGNO (operands[1]) == REGNO (operands[4])
7527       && REGNO (operands[4]) != REGNO (operands[0]))
7528     {
7529       if (GET_CODE (operands[6]) == LT)
7530         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7531       else if (GET_CODE (operands[6]) == GE)
7532         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7533     }
7534   if (GET_CODE (operands[3]) == CONST_INT
7535       && !const_ok_for_arm (INTVAL (operands[3])))
7536     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7537   else
7538     output_asm_insn (\"cmp\\t%2, %3\", operands);
7539   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7540   if (which_alternative != 0)
7541     return \"mov%D6\\t%0, %1\";
7542   return \"\";
7543   "
7544   [(set_attr "conds" "clob")
7545    (set_attr "length" "8,12")]
7548 (define_insn "*if_arith_move"
7549   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7550         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7551                           [(match_operand 6 "cc_register" "") (const_int 0)])
7552                          (match_operator:SI 5 "shiftable_operator"
7553                           [(match_operand:SI 2 "s_register_operand" "r,r")
7554                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7555                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7556   "TARGET_ARM"
7557   "@
7558    %I5%d4\\t%0, %2, %3
7559    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7560   [(set_attr "conds" "use")
7561    (set_attr "length" "4,8")
7562    (set_attr "type" "*,*")]
7565 (define_insn "*ifcompare_move_arith"
7566   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7567         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7568                           [(match_operand:SI 4 "s_register_operand" "r,r")
7569                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7570                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7571                          (match_operator:SI 7 "shiftable_operator"
7572                           [(match_operand:SI 2 "s_register_operand" "r,r")
7573                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7574    (clobber (reg:CC CC_REGNUM))]
7575   "TARGET_ARM"
7576   "*
7577   /* If we have an operation where (op x 0) is the identity operation and
7578      the conditional operator is LT or GE and we are comparing against zero and
7579      everything is in registers then we can do this in two instructions */
7580   if (operands[5] == const0_rtx
7581       && GET_CODE (operands[7]) != AND
7582       && GET_CODE (operands[3]) == REG
7583       && GET_CODE (operands[1]) == REG 
7584       && REGNO (operands[1]) == REGNO (operands[2])
7585       && REGNO (operands[2]) != REGNO (operands[0]))
7586     {
7587       if (GET_CODE (operands[6]) == GE)
7588         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7589       else if (GET_CODE (operands[6]) == LT)
7590         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7591     }
7593   if (GET_CODE (operands[5]) == CONST_INT
7594       && !const_ok_for_arm (INTVAL (operands[5])))
7595     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7596   else
7597     output_asm_insn (\"cmp\\t%4, %5\", operands);
7599   if (which_alternative != 0)
7600     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7601   return \"%I7%D6\\t%0, %2, %3\";
7602   "
7603   [(set_attr "conds" "clob")
7604    (set_attr "length" "8,12")]
7607 (define_insn "*if_move_arith"
7608   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7609         (if_then_else:SI
7610          (match_operator 4 "arm_comparison_operator"
7611           [(match_operand 6 "cc_register" "") (const_int 0)])
7612          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7613          (match_operator:SI 5 "shiftable_operator"
7614           [(match_operand:SI 2 "s_register_operand" "r,r")
7615            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7616   "TARGET_ARM"
7617   "@
7618    %I5%D4\\t%0, %2, %3
7619    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7620   [(set_attr "conds" "use")
7621    (set_attr "length" "4,8")
7622    (set_attr "type" "*,*")]
7625 (define_insn "*ifcompare_move_not"
7626   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7627         (if_then_else:SI
7628          (match_operator 5 "arm_comparison_operator"
7629           [(match_operand:SI 3 "s_register_operand" "r,r")
7630            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7631          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7632          (not:SI
7633           (match_operand:SI 2 "s_register_operand" "r,r"))))
7634    (clobber (reg:CC CC_REGNUM))]
7635   "TARGET_ARM"
7636   "#"
7637   [(set_attr "conds" "clob")
7638    (set_attr "length" "8,12")]
7641 (define_insn "*if_move_not"
7642   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7643         (if_then_else:SI
7644          (match_operator 4 "arm_comparison_operator"
7645           [(match_operand 3 "cc_register" "") (const_int 0)])
7646          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7647          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7648   "TARGET_ARM"
7649   "@
7650    mvn%D4\\t%0, %2
7651    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7652    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7653   [(set_attr "conds" "use")
7654    (set_attr "length" "4,8,8")]
7657 (define_insn "*ifcompare_not_move"
7658   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7659         (if_then_else:SI 
7660          (match_operator 5 "arm_comparison_operator"
7661           [(match_operand:SI 3 "s_register_operand" "r,r")
7662            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7663          (not:SI
7664           (match_operand:SI 2 "s_register_operand" "r,r"))
7665          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7666    (clobber (reg:CC CC_REGNUM))]
7667   "TARGET_ARM"
7668   "#"
7669   [(set_attr "conds" "clob")
7670    (set_attr "length" "8,12")]
7673 (define_insn "*if_not_move"
7674   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7675         (if_then_else:SI
7676          (match_operator 4 "arm_comparison_operator"
7677           [(match_operand 3 "cc_register" "") (const_int 0)])
7678          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7679          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7680   "TARGET_ARM"
7681   "@
7682    mvn%d4\\t%0, %2
7683    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7684    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7685   [(set_attr "conds" "use")
7686    (set_attr "length" "4,8,8")]
7689 (define_insn "*ifcompare_shift_move"
7690   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7691         (if_then_else:SI
7692          (match_operator 6 "arm_comparison_operator"
7693           [(match_operand:SI 4 "s_register_operand" "r,r")
7694            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7695          (match_operator:SI 7 "shift_operator"
7696           [(match_operand:SI 2 "s_register_operand" "r,r")
7697            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7698          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7699    (clobber (reg:CC CC_REGNUM))]
7700   "TARGET_ARM"
7701   "#"
7702   [(set_attr "conds" "clob")
7703    (set_attr "length" "8,12")]
7706 (define_insn "*if_shift_move"
7707   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7708         (if_then_else:SI
7709          (match_operator 5 "arm_comparison_operator"
7710           [(match_operand 6 "cc_register" "") (const_int 0)])
7711          (match_operator:SI 4 "shift_operator"
7712           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7713            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7714          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7715   "TARGET_ARM"
7716   "@
7717    mov%d5\\t%0, %2%S4
7718    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7719    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7720   [(set_attr "conds" "use")
7721    (set_attr "shift" "2")
7722    (set_attr "length" "4,8,8")]
7725 (define_insn "*ifcompare_move_shift"
7726   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7727         (if_then_else:SI
7728          (match_operator 6 "arm_comparison_operator"
7729           [(match_operand:SI 4 "s_register_operand" "r,r")
7730            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7731          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7732          (match_operator:SI 7 "shift_operator"
7733           [(match_operand:SI 2 "s_register_operand" "r,r")
7734            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7735    (clobber (reg:CC CC_REGNUM))]
7736   "TARGET_ARM"
7737   "#"
7738   [(set_attr "conds" "clob")
7739    (set_attr "length" "8,12")]
7742 (define_insn "*if_move_shift"
7743   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7744         (if_then_else:SI
7745          (match_operator 5 "arm_comparison_operator"
7746           [(match_operand 6 "cc_register" "") (const_int 0)])
7747          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7748          (match_operator:SI 4 "shift_operator"
7749           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7750            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7751   "TARGET_ARM"
7752   "@
7753    mov%D5\\t%0, %2%S4
7754    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7755    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7756   [(set_attr "conds" "use")
7757    (set_attr "shift" "2")
7758    (set_attr "length" "4,8,8")]
7761 (define_insn "*ifcompare_shift_shift"
7762   [(set (match_operand:SI 0 "s_register_operand" "=r")
7763         (if_then_else:SI
7764          (match_operator 7 "arm_comparison_operator"
7765           [(match_operand:SI 5 "s_register_operand" "r")
7766            (match_operand:SI 6 "arm_add_operand" "rIL")])
7767          (match_operator:SI 8 "shift_operator"
7768           [(match_operand:SI 1 "s_register_operand" "r")
7769            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7770          (match_operator:SI 9 "shift_operator"
7771           [(match_operand:SI 3 "s_register_operand" "r")
7772            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7773    (clobber (reg:CC CC_REGNUM))]
7774   "TARGET_ARM"
7775   "#"
7776   [(set_attr "conds" "clob")
7777    (set_attr "length" "12")]
7780 (define_insn "*if_shift_shift"
7781   [(set (match_operand:SI 0 "s_register_operand" "=r")
7782         (if_then_else:SI
7783          (match_operator 5 "arm_comparison_operator"
7784           [(match_operand 8 "cc_register" "") (const_int 0)])
7785          (match_operator:SI 6 "shift_operator"
7786           [(match_operand:SI 1 "s_register_operand" "r")
7787            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7788          (match_operator:SI 7 "shift_operator"
7789           [(match_operand:SI 3 "s_register_operand" "r")
7790            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7791   "TARGET_ARM"
7792   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7793   [(set_attr "conds" "use")
7794    (set_attr "shift" "1")
7795    (set_attr "length" "8")]
7798 (define_insn "*ifcompare_not_arith"
7799   [(set (match_operand:SI 0 "s_register_operand" "=r")
7800         (if_then_else:SI
7801          (match_operator 6 "arm_comparison_operator"
7802           [(match_operand:SI 4 "s_register_operand" "r")
7803            (match_operand:SI 5 "arm_add_operand" "rIL")])
7804          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7805          (match_operator:SI 7 "shiftable_operator"
7806           [(match_operand:SI 2 "s_register_operand" "r")
7807            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7808    (clobber (reg:CC CC_REGNUM))]
7809   "TARGET_ARM"
7810   "#"
7811   [(set_attr "conds" "clob")
7812    (set_attr "length" "12")]
7815 (define_insn "*if_not_arith"
7816   [(set (match_operand:SI 0 "s_register_operand" "=r")
7817         (if_then_else:SI
7818          (match_operator 5 "arm_comparison_operator"
7819           [(match_operand 4 "cc_register" "") (const_int 0)])
7820          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7821          (match_operator:SI 6 "shiftable_operator"
7822           [(match_operand:SI 2 "s_register_operand" "r")
7823            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7824   "TARGET_ARM"
7825   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7826   [(set_attr "conds" "use")
7827    (set_attr "length" "8")]
7830 (define_insn "*ifcompare_arith_not"
7831   [(set (match_operand:SI 0 "s_register_operand" "=r")
7832         (if_then_else:SI
7833          (match_operator 6 "arm_comparison_operator"
7834           [(match_operand:SI 4 "s_register_operand" "r")
7835            (match_operand:SI 5 "arm_add_operand" "rIL")])
7836          (match_operator:SI 7 "shiftable_operator"
7837           [(match_operand:SI 2 "s_register_operand" "r")
7838            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7839          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7840    (clobber (reg:CC CC_REGNUM))]
7841   "TARGET_ARM"
7842   "#"
7843   [(set_attr "conds" "clob")
7844    (set_attr "length" "12")]
7847 (define_insn "*if_arith_not"
7848   [(set (match_operand:SI 0 "s_register_operand" "=r")
7849         (if_then_else:SI
7850          (match_operator 5 "arm_comparison_operator"
7851           [(match_operand 4 "cc_register" "") (const_int 0)])
7852          (match_operator:SI 6 "shiftable_operator"
7853           [(match_operand:SI 2 "s_register_operand" "r")
7854            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7855          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7856   "TARGET_ARM"
7857   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7858   [(set_attr "conds" "use")
7859    (set_attr "length" "8")]
7862 (define_insn "*ifcompare_neg_move"
7863   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7864         (if_then_else:SI
7865          (match_operator 5 "arm_comparison_operator"
7866           [(match_operand:SI 3 "s_register_operand" "r,r")
7867            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7868          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7869          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7870    (clobber (reg:CC CC_REGNUM))]
7871   "TARGET_ARM"
7872   "#"
7873   [(set_attr "conds" "clob")
7874    (set_attr "length" "8,12")]
7877 (define_insn "*if_neg_move"
7878   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7879         (if_then_else:SI
7880          (match_operator 4 "arm_comparison_operator"
7881           [(match_operand 3 "cc_register" "") (const_int 0)])
7882          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7883          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7884   "TARGET_ARM"
7885   "@
7886    rsb%d4\\t%0, %2, #0
7887    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7888    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7889   [(set_attr "conds" "use")
7890    (set_attr "length" "4,8,8")]
7893 (define_insn "*ifcompare_move_neg"
7894   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7895         (if_then_else:SI
7896          (match_operator 5 "arm_comparison_operator"
7897           [(match_operand:SI 3 "s_register_operand" "r,r")
7898            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7899          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7900          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7901    (clobber (reg:CC CC_REGNUM))]
7902   "TARGET_ARM"
7903   "#"
7904   [(set_attr "conds" "clob")
7905    (set_attr "length" "8,12")]
7908 (define_insn "*if_move_neg"
7909   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7910         (if_then_else:SI
7911          (match_operator 4 "arm_comparison_operator"
7912           [(match_operand 3 "cc_register" "") (const_int 0)])
7913          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7914          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7915   "TARGET_ARM"
7916   "@
7917    rsb%D4\\t%0, %2, #0
7918    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7919    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7920   [(set_attr "conds" "use")
7921    (set_attr "length" "4,8,8")]
7924 (define_insn "*arith_adjacentmem"
7925   [(set (match_operand:SI 0 "s_register_operand" "=r")
7926         (match_operator:SI 1 "shiftable_operator"
7927          [(match_operand:SI 2 "memory_operand" "m")
7928           (match_operand:SI 3 "memory_operand" "m")]))
7929    (clobber (match_scratch:SI 4 "=r"))]
7930   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7931   "*
7932   {
7933     rtx ldm[3];
7934     rtx arith[4];
7935     int val1 = 0, val2 = 0;
7937     if (REGNO (operands[0]) > REGNO (operands[4]))
7938       {
7939         ldm[1] = operands[4];
7940         ldm[2] = operands[0];
7941       }
7942     else
7943       {
7944         ldm[1] = operands[0];
7945         ldm[2] = operands[4];
7946       }
7947     if (GET_CODE (XEXP (operands[2], 0)) != REG)
7948       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7949     if (GET_CODE (XEXP (operands[3], 0)) != REG)
7950       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7951     arith[0] = operands[0];
7952     arith[3] = operands[1];
7953     if (val1 < val2)
7954       {
7955         arith[1] = ldm[1];
7956         arith[2] = ldm[2];
7957       }
7958     else
7959       {
7960         arith[1] = ldm[2];
7961         arith[2] = ldm[1];
7962       }
7963    if (val1 && val2)
7964       {
7965         rtx ops[3];
7966         ldm[0] = ops[0] = operands[4];
7967         ops[1] = XEXP (XEXP (operands[2], 0), 0);
7968         ops[2] = XEXP (XEXP (operands[2], 0), 1);
7969         output_add_immediate (ops);
7970         if (val1 < val2)
7971           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7972         else
7973           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7974       }
7975     else if (val1)
7976       {
7977         ldm[0] = XEXP (operands[3], 0);
7978         if (val1 < val2)
7979           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7980         else
7981           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7982       }
7983     else
7984       {
7985         ldm[0] = XEXP (operands[2], 0);
7986         if (val1 < val2)
7987           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7988         else
7989           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7990       }
7991     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7992     return \"\";
7993   }"
7994   [(set_attr "length" "12")
7995    (set_attr "predicable" "yes")
7996    (set_attr "type" "load")]
7999 ;; the arm can support extended pre-inc instructions
8001 ;; In all these cases, we use operands 0 and 1 for the register being
8002 ;; incremented because those are the operands that local-alloc will
8003 ;; tie and these are the pair most likely to be tieable (and the ones
8004 ;; that will benefit the most).
8006 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8007 ;; elimination will cause too many headaches.
8009 (define_insn "*strqi_preinc"
8010   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8011                          (match_operand:SI 2 "index_operand" "rJ")))
8012         (match_operand:QI 3 "s_register_operand" "r"))
8013    (set (match_operand:SI 0 "s_register_operand" "=r")
8014         (plus:SI (match_dup 1) (match_dup 2)))]
8015   "TARGET_ARM
8016    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8017    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8018    && (GET_CODE (operands[2]) != REG
8019        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8020   "str%?b\\t%3, [%0, %2]!"
8021   [(set_attr "type" "store1")
8022    (set_attr "predicable" "yes")]
8025 (define_insn "*strqi_predec"
8026   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8027                           (match_operand:SI 2 "s_register_operand" "r")))
8028         (match_operand:QI 3 "s_register_operand" "r"))
8029    (set (match_operand:SI 0 "s_register_operand" "=r")
8030         (minus:SI (match_dup 1) (match_dup 2)))]
8031   "TARGET_ARM
8032    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8033    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8034    && (GET_CODE (operands[2]) != REG
8035        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8036   "str%?b\\t%3, [%0, -%2]!"
8037   [(set_attr "type" "store1")
8038    (set_attr "predicable" "yes")]
8041 (define_insn "*loadqi_preinc"
8042   [(set (match_operand:QI 3 "s_register_operand" "=r")
8043         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8044                          (match_operand:SI 2 "index_operand" "rJ"))))
8045    (set (match_operand:SI 0 "s_register_operand" "=r")
8046         (plus:SI (match_dup 1) (match_dup 2)))]
8047   "TARGET_ARM
8048    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8049    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8050    && (GET_CODE (operands[2]) != REG
8051        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8052   "ldr%?b\\t%3, [%0, %2]!"
8053   [(set_attr "type" "load")
8054    (set_attr "predicable" "yes")]
8057 (define_insn "*loadqi_predec"
8058   [(set (match_operand:QI 3 "s_register_operand" "=r")
8059         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8060                           (match_operand:SI 2 "s_register_operand" "r"))))
8061    (set (match_operand:SI 0 "s_register_operand" "=r")
8062         (minus:SI (match_dup 1) (match_dup 2)))]
8063   "TARGET_ARM
8064    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8065    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8066    && (GET_CODE (operands[2]) != REG
8067        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8068   "ldr%?b\\t%3, [%0, -%2]!"
8069   [(set_attr "type" "load")
8070    (set_attr "predicable" "yes")]
8073 (define_insn "*loadqisi_preinc"
8074   [(set (match_operand:SI 3 "s_register_operand" "=r")
8075         (zero_extend:SI
8076          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8077                           (match_operand:SI 2 "index_operand" "rJ")))))
8078    (set (match_operand:SI 0 "s_register_operand" "=r")
8079         (plus:SI (match_dup 1) (match_dup 2)))]
8080   "TARGET_ARM
8081    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8082    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8083    && (GET_CODE (operands[2]) != REG
8084        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8085   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8086   [(set_attr "type" "load")
8087    (set_attr "predicable" "yes")]
8090 (define_insn "*loadqisi_predec"
8091   [(set (match_operand:SI 3 "s_register_operand" "=r")
8092         (zero_extend:SI
8093          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8094                            (match_operand:SI 2 "s_register_operand" "r")))))
8095    (set (match_operand:SI 0 "s_register_operand" "=r")
8096         (minus:SI (match_dup 1) (match_dup 2)))]
8097   "TARGET_ARM
8098    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8099    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8100    && (GET_CODE (operands[2]) != REG
8101        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8102   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8103   [(set_attr "type" "load")
8104    (set_attr "predicable" "yes")]
8107 (define_insn "*strsi_preinc"
8108   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8109                          (match_operand:SI 2 "index_operand" "rJ")))
8110         (match_operand:SI 3 "s_register_operand" "r"))
8111    (set (match_operand:SI 0 "s_register_operand" "=r")
8112         (plus:SI (match_dup 1) (match_dup 2)))]
8113   "TARGET_ARM
8114    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8115    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8116    && (GET_CODE (operands[2]) != REG
8117        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8118   "str%?\\t%3, [%0, %2]!"
8119   [(set_attr "type" "store1")
8120    (set_attr "predicable" "yes")]
8123 (define_insn "*strsi_predec"
8124   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8125                           (match_operand:SI 2 "s_register_operand" "r")))
8126         (match_operand:SI 3 "s_register_operand" "r"))
8127    (set (match_operand:SI 0 "s_register_operand" "=r")
8128         (minus:SI (match_dup 1) (match_dup 2)))]
8129   "TARGET_ARM
8130    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8131    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8132    && (GET_CODE (operands[2]) != REG
8133        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8134   "str%?\\t%3, [%0, -%2]!"
8135   [(set_attr "type" "store1")
8136    (set_attr "predicable" "yes")]
8139 (define_insn "*loadsi_preinc"
8140   [(set (match_operand:SI 3 "s_register_operand" "=r")
8141         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8142                          (match_operand:SI 2 "index_operand" "rJ"))))
8143    (set (match_operand:SI 0 "s_register_operand" "=r")
8144         (plus:SI (match_dup 1) (match_dup 2)))]
8145   "TARGET_ARM
8146    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8147    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8148    && (GET_CODE (operands[2]) != REG
8149        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8150   "ldr%?\\t%3, [%0, %2]!"
8151   [(set_attr "type" "load")
8152    (set_attr "predicable" "yes")]
8155 (define_insn "*loadsi_predec"
8156   [(set (match_operand:SI 3 "s_register_operand" "=r")
8157         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8158                           (match_operand:SI 2 "s_register_operand" "r"))))
8159    (set (match_operand:SI 0 "s_register_operand" "=r")
8160         (minus:SI (match_dup 1) (match_dup 2)))]
8161   "TARGET_ARM
8162    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8163    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8164    && (GET_CODE (operands[2]) != REG
8165        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8166   "ldr%?\\t%3, [%0, -%2]!"
8167   [(set_attr "type" "load")
8168    (set_attr "predicable" "yes")]
8171 (define_insn "*loadhi_preinc"
8172   [(set (match_operand:HI 3 "s_register_operand" "=r")
8173         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8174                          (match_operand:SI 2 "index_operand" "rJ"))))
8175    (set (match_operand:SI 0 "s_register_operand" "=r")
8176         (plus:SI (match_dup 1) (match_dup 2)))]
8177   "TARGET_ARM
8178    && !BYTES_BIG_ENDIAN
8179    && !TARGET_MMU_TRAPS
8180    && !arm_arch4
8181    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8182    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8183    && (GET_CODE (operands[2]) != REG
8184        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8185   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8186   [(set_attr "type" "load")
8187    (set_attr "predicable" "yes")]
8190 (define_insn "*loadhi_predec"
8191   [(set (match_operand:HI 3 "s_register_operand" "=r")
8192         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8193                           (match_operand:SI 2 "s_register_operand" "r"))))
8194    (set (match_operand:SI 0 "s_register_operand" "=r")
8195         (minus:SI (match_dup 1) (match_dup 2)))]
8196   "TARGET_ARM
8197    && !BYTES_BIG_ENDIAN
8198    && !TARGET_MMU_TRAPS
8199    && !arm_arch4
8200    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8201    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8202    && (GET_CODE (operands[2]) != REG
8203        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8204   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8205   [(set_attr "type" "load")
8206    (set_attr "predicable" "yes")]
8209 (define_insn "*strqi_shiftpreinc"
8210   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8211                           [(match_operand:SI 3 "s_register_operand" "r")
8212                            (match_operand:SI 4 "const_shift_operand" "n")])
8213                          (match_operand:SI 1 "s_register_operand" "0")))
8214         (match_operand:QI 5 "s_register_operand" "r"))
8215    (set (match_operand:SI 0 "s_register_operand" "=r")
8216         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8217                  (match_dup 1)))]
8218   "TARGET_ARM
8219    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8220    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8221    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8222   "str%?b\\t%5, [%0, %3%S2]!"
8223   [(set_attr "type" "store1")
8224    (set_attr "predicable" "yes")]
8227 (define_insn "*strqi_shiftpredec"
8228   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8229                           (match_operator:SI 2 "shift_operator"
8230                            [(match_operand:SI 3 "s_register_operand" "r")
8231                             (match_operand:SI 4 "const_shift_operand" "n")])))
8232         (match_operand:QI 5 "s_register_operand" "r"))
8233    (set (match_operand:SI 0 "s_register_operand" "=r")
8234         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8235                                                  (match_dup 4)])))]
8236   "TARGET_ARM
8237    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8238    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8239    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8240   "str%?b\\t%5, [%0, -%3%S2]!"
8241   [(set_attr "type" "store1")
8242    (set_attr "predicable" "yes")]
8245 (define_insn "*loadqi_shiftpreinc"
8246   [(set (match_operand:QI 5 "s_register_operand" "=r")
8247         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8248                           [(match_operand:SI 3 "s_register_operand" "r")
8249                            (match_operand:SI 4 "const_shift_operand" "n")])
8250                          (match_operand:SI 1 "s_register_operand" "0"))))
8251    (set (match_operand:SI 0 "s_register_operand" "=r")
8252         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8253                  (match_dup 1)))]
8254   "TARGET_ARM
8255    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8256    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8257    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8258   "ldr%?b\\t%5, [%0, %3%S2]!"
8259   [(set_attr "type" "load")
8260    (set_attr "predicable" "yes")]
8263 (define_insn "*loadqi_shiftpredec"
8264   [(set (match_operand:QI 5 "s_register_operand" "=r")
8265         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8266                           (match_operator:SI 2 "shift_operator"
8267                            [(match_operand:SI 3 "s_register_operand" "r")
8268                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8269    (set (match_operand:SI 0 "s_register_operand" "=r")
8270         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8271                                                  (match_dup 4)])))]
8272   "TARGET_ARM
8273    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8274    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8275    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8276   "ldr%?b\\t%5, [%0, -%3%S2]!"
8277   [(set_attr "type" "load")
8278    (set_attr "predicable" "yes")]
8281 (define_insn "*strsi_shiftpreinc"
8282   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8283                           [(match_operand:SI 3 "s_register_operand" "r")
8284                            (match_operand:SI 4 "const_shift_operand" "n")])
8285                          (match_operand:SI 1 "s_register_operand" "0")))
8286         (match_operand:SI 5 "s_register_operand" "r"))
8287    (set (match_operand:SI 0 "s_register_operand" "=r")
8288         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8289                  (match_dup 1)))]
8290   "TARGET_ARM
8291    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8292    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8293    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8294   "str%?\\t%5, [%0, %3%S2]!"
8295   [(set_attr "type" "store1")
8296    (set_attr "predicable" "yes")]
8299 (define_insn "*strsi_shiftpredec"
8300   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8301                           (match_operator:SI 2 "shift_operator"
8302                            [(match_operand:SI 3 "s_register_operand" "r")
8303                             (match_operand:SI 4 "const_shift_operand" "n")])))
8304         (match_operand:SI 5 "s_register_operand" "r"))
8305    (set (match_operand:SI 0 "s_register_operand" "=r")
8306         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8307                                                  (match_dup 4)])))]
8308   "TARGET_ARM
8309    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8310    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8311    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8312   "str%?\\t%5, [%0, -%3%S2]!"
8313   [(set_attr "type" "store1")
8314    (set_attr "predicable" "yes")]
8317 (define_insn "*loadsi_shiftpreinc"
8318   [(set (match_operand:SI 5 "s_register_operand" "=r")
8319         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8320                           [(match_operand:SI 3 "s_register_operand" "r")
8321                            (match_operand:SI 4 "const_shift_operand" "n")])
8322                          (match_operand:SI 1 "s_register_operand" "0"))))
8323    (set (match_operand:SI 0 "s_register_operand" "=r")
8324         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8325                  (match_dup 1)))]
8326   "TARGET_ARM
8327    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8328    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8329    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8330   "ldr%?\\t%5, [%0, %3%S2]!"
8331   [(set_attr "type" "load")
8332    (set_attr "predicable" "yes")]
8335 (define_insn "*loadsi_shiftpredec"
8336   [(set (match_operand:SI 5 "s_register_operand" "=r")
8337         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8338                           (match_operator:SI 2 "shift_operator"
8339                            [(match_operand:SI 3 "s_register_operand" "r")
8340                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8341    (set (match_operand:SI 0 "s_register_operand" "=r")
8342         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8343                                                  (match_dup 4)])))]
8344   "TARGET_ARM
8345    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8346    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8347    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8348   "ldr%?\\t%5, [%0, -%3%S2]!"
8349   [(set_attr "type" "load")
8350    (set_attr "predicable" "yes")])
8352 (define_insn "*loadhi_shiftpreinc"
8353   [(set (match_operand:HI 5 "s_register_operand" "=r")
8354         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8355                           [(match_operand:SI 3 "s_register_operand" "r")
8356                            (match_operand:SI 4 "const_shift_operand" "n")])
8357                          (match_operand:SI 1 "s_register_operand" "0"))))
8358    (set (match_operand:SI 0 "s_register_operand" "=r")
8359         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8360                  (match_dup 1)))]
8361   "TARGET_ARM
8362    && !BYTES_BIG_ENDIAN
8363    && !TARGET_MMU_TRAPS
8364    && !arm_arch4
8365    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8366    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8367    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8368   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8369   [(set_attr "type" "load")
8370    (set_attr "predicable" "yes")]
8373 (define_insn "*loadhi_shiftpredec"
8374   [(set (match_operand:HI 5 "s_register_operand" "=r")
8375         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8376                           (match_operator:SI 2 "shift_operator"
8377                            [(match_operand:SI 3 "s_register_operand" "r")
8378                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8379    (set (match_operand:SI 0 "s_register_operand" "=r")
8380         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8381                                                  (match_dup 4)])))]
8382   "TARGET_ARM
8383    && !BYTES_BIG_ENDIAN
8384    && !TARGET_MMU_TRAPS
8385    && !arm_arch4
8386    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8387    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8388    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8389   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8390   [(set_attr "type" "load")
8391    (set_attr "predicable" "yes")]
8394 ; It can also support extended post-inc expressions, but combine doesn't
8395 ; try these....
8396 ; It doesn't seem worth adding peepholes for anything but the most common
8397 ; cases since, unlike combine, the increment must immediately follow the load
8398 ; for this pattern to match.
8399 ; We must watch to see that the source/destination register isn't also the
8400 ; same as the base address register, and that if the index is a register,
8401 ; that it is not the same as the base address register.  In such cases the
8402 ; instruction that we would generate would have UNPREDICTABLE behaviour so 
8403 ; we cannot use it.
8405 (define_peephole
8406   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8407         (match_operand:QI 2 "s_register_operand" "r"))
8408    (set (match_dup 0)
8409         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8410   "TARGET_ARM
8411    && (REGNO (operands[2]) != REGNO (operands[0]))
8412    && (GET_CODE (operands[1]) != REG
8413        || (REGNO (operands[1]) != REGNO (operands[0])))"
8414   "str%?b\\t%2, [%0], %1"
8417 (define_peephole
8418   [(set (match_operand:QI 0 "s_register_operand" "=r")
8419         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8420    (set (match_dup 1)
8421         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8422   "TARGET_ARM
8423    && REGNO (operands[0]) != REGNO(operands[1])
8424    && (GET_CODE (operands[2]) != REG
8425        || REGNO(operands[0]) != REGNO (operands[2]))"
8426   "ldr%?b\\t%0, [%1], %2"
8429 (define_peephole
8430   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8431         (match_operand:SI 2 "s_register_operand" "r"))
8432    (set (match_dup 0)
8433         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8434   "TARGET_ARM
8435    && (REGNO (operands[2]) != REGNO (operands[0]))
8436    && (GET_CODE (operands[1]) != REG
8437        || (REGNO (operands[1]) != REGNO (operands[0])))"
8438   "str%?\\t%2, [%0], %1"
8441 (define_peephole
8442   [(set (match_operand:HI 0 "s_register_operand" "=r")
8443         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8444    (set (match_dup 1)
8445         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8446   "TARGET_ARM
8447    && !BYTES_BIG_ENDIAN
8448    && !TARGET_MMU_TRAPS
8449    && !arm_arch4
8450    && REGNO (operands[0]) != REGNO(operands[1])
8451    && (GET_CODE (operands[2]) != REG
8452        || REGNO(operands[0]) != REGNO (operands[2]))"
8453   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8456 (define_peephole
8457   [(set (match_operand:SI 0 "s_register_operand" "=r")
8458         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8459    (set (match_dup 1)
8460         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8461   "TARGET_ARM
8462    && REGNO (operands[0]) != REGNO(operands[1])
8463    && (GET_CODE (operands[2]) != REG
8464        || REGNO(operands[0]) != REGNO (operands[2]))"
8465   "ldr%?\\t%0, [%1], %2"
8468 (define_peephole
8469   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8470                          (match_operand:SI 1 "index_operand" "rJ")))
8471         (match_operand:QI 2 "s_register_operand" "r"))
8472    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8473   "TARGET_ARM
8474    && (REGNO (operands[2]) != REGNO (operands[0]))
8475    && (GET_CODE (operands[1]) != REG
8476        || (REGNO (operands[1]) != REGNO (operands[0])))"
8477   "str%?b\\t%2, [%0, %1]!"
8480 (define_peephole
8481   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8482                           [(match_operand:SI 0 "s_register_operand" "r")
8483                            (match_operand:SI 1 "const_int_operand" "n")])
8484                          (match_operand:SI 2 "s_register_operand" "+r")))
8485         (match_operand:QI 3 "s_register_operand" "r"))
8486    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8487                                (match_dup 2)))]
8488   "TARGET_ARM
8489    && (REGNO (operands[3]) != REGNO (operands[2]))
8490    && (REGNO (operands[0]) != REGNO (operands[2]))"
8491   "str%?b\\t%3, [%2, %0%S4]!"
8494 ; This pattern is never tried by combine, so do it as a peephole
8496 (define_peephole2
8497   [(set (match_operand:SI 0 "s_register_operand" "")
8498         (match_operand:SI 1 "s_register_operand" ""))
8499    (set (reg:CC CC_REGNUM)
8500         (compare:CC (match_dup 1) (const_int 0)))]
8501   "TARGET_ARM
8502   "
8503   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8504               (set (match_dup 0) (match_dup 1))])]
8505   ""
8508 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8509 ; reversed, check that the memory references aren't volatile.
8511 (define_peephole
8512   [(set (match_operand:SI 0 "s_register_operand" "=r")
8513         (match_operand:SI 4 "memory_operand" "m"))
8514    (set (match_operand:SI 1 "s_register_operand" "=r")
8515         (match_operand:SI 5 "memory_operand" "m"))
8516    (set (match_operand:SI 2 "s_register_operand" "=r")
8517         (match_operand:SI 6 "memory_operand" "m"))
8518    (set (match_operand:SI 3 "s_register_operand" "=r")
8519         (match_operand:SI 7 "memory_operand" "m"))]
8520   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8521   "*
8522   return emit_ldm_seq (operands, 4);
8523   "
8526 (define_peephole
8527   [(set (match_operand:SI 0 "s_register_operand" "=r")
8528         (match_operand:SI 3 "memory_operand" "m"))
8529    (set (match_operand:SI 1 "s_register_operand" "=r")
8530         (match_operand:SI 4 "memory_operand" "m"))
8531    (set (match_operand:SI 2 "s_register_operand" "=r")
8532         (match_operand:SI 5 "memory_operand" "m"))]
8533   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8534   "*
8535   return emit_ldm_seq (operands, 3);
8536   "
8539 (define_peephole
8540   [(set (match_operand:SI 0 "s_register_operand" "=r")
8541         (match_operand:SI 2 "memory_operand" "m"))
8542    (set (match_operand:SI 1 "s_register_operand" "=r")
8543         (match_operand:SI 3 "memory_operand" "m"))]
8544   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8545   "*
8546   return emit_ldm_seq (operands, 2);
8547   "
8550 (define_peephole
8551   [(set (match_operand:SI 4 "memory_operand" "=m")
8552         (match_operand:SI 0 "s_register_operand" "r"))
8553    (set (match_operand:SI 5 "memory_operand" "=m")
8554         (match_operand:SI 1 "s_register_operand" "r"))
8555    (set (match_operand:SI 6 "memory_operand" "=m")
8556         (match_operand:SI 2 "s_register_operand" "r"))
8557    (set (match_operand:SI 7 "memory_operand" "=m")
8558         (match_operand:SI 3 "s_register_operand" "r"))]
8559   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8560   "*
8561   return emit_stm_seq (operands, 4);
8562   "
8565 (define_peephole
8566   [(set (match_operand:SI 3 "memory_operand" "=m")
8567         (match_operand:SI 0 "s_register_operand" "r"))
8568    (set (match_operand:SI 4 "memory_operand" "=m")
8569         (match_operand:SI 1 "s_register_operand" "r"))
8570    (set (match_operand:SI 5 "memory_operand" "=m")
8571         (match_operand:SI 2 "s_register_operand" "r"))]
8572   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8573   "*
8574   return emit_stm_seq (operands, 3);
8575   "
8578 (define_peephole
8579   [(set (match_operand:SI 2 "memory_operand" "=m")
8580         (match_operand:SI 0 "s_register_operand" "r"))
8581    (set (match_operand:SI 3 "memory_operand" "=m")
8582         (match_operand:SI 1 "s_register_operand" "r"))]
8583   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8584   "*
8585   return emit_stm_seq (operands, 2);
8586   "
8589 (define_split
8590   [(set (match_operand:SI 0 "s_register_operand" "")
8591         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8592                        (const_int 0))
8593                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8594                          [(match_operand:SI 3 "s_register_operand" "")
8595                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
8596    (clobber (match_operand:SI 5 "s_register_operand" ""))]
8597   "TARGET_ARM"
8598   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8599    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8600                               (match_dup 5)))]
8601   ""
8604 ;; This split can be used because CC_Z mode implies that the following
8605 ;; branch will be an equality, or an unsigned inequality, so the sign
8606 ;; extension is not needed.
8608 (define_split
8609   [(set (reg:CC_Z CC_REGNUM)
8610         (compare:CC_Z
8611          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8612                     (const_int 24))
8613          (match_operand 1 "const_int_operand" "")))
8614    (clobber (match_scratch:SI 2 ""))]
8615   "TARGET_ARM
8616    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8617        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8618   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8619    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8620   "
8621   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8622   "
8625 (define_expand "prologue"
8626   [(clobber (const_int 0))]
8627   "TARGET_EITHER"
8628   "if (TARGET_ARM)
8629      arm_expand_prologue ();
8630    else
8631      thumb_expand_prologue ();
8632   DONE;
8633   "
8636 (define_expand "epilogue"
8637   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8638   "TARGET_EITHER"
8639   "
8640   if (TARGET_THUMB)
8641     thumb_expand_epilogue ();
8642   else if (USE_RETURN_INSN (FALSE))
8643     {
8644       emit_jump_insn (gen_return ());
8645       DONE;
8646     }
8647   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8648         gen_rtvec (1,
8649                 gen_rtx_RETURN (VOIDmode)),
8650         VUNSPEC_EPILOGUE));
8651   DONE;
8652   "
8655 (define_insn "sibcall_epilogue"
8656   [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8657   "TARGET_ARM"
8658   "*
8659   output_asm_insn (\"%@ Sibcall epilogue\", operands);
8660   if (USE_RETURN_INSN (FALSE))
8661     return output_return_instruction (const_true_rtx, FALSE, FALSE);
8662   return arm_output_epilogue (FALSE);
8663   "
8664 ;; Length is absolute worst case
8665   [(set_attr "length" "44")
8666    (set_attr "type" "block")]
8669 (define_insn "*epilogue_insns"
8670   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8671   "TARGET_EITHER"
8672   "*
8673   if (TARGET_ARM)
8674     return arm_output_epilogue (TRUE);
8675   else /* TARGET_THUMB */
8676     return thumb_unexpanded_epilogue ();
8677   "
8678   ; Length is absolute worst case
8679   [(set_attr "length" "44")
8680    (set_attr "type" "block")]
8683 (define_expand "eh_epilogue"
8684   [(use (match_operand:SI 0 "register_operand" "r"))
8685    (use (match_operand:SI 1 "register_operand" "r"))
8686    (use (match_operand:SI 2 "register_operand" "r"))]
8687   "TARGET_EITHER"
8688   "
8689   {
8690     cfun->machine->eh_epilogue_sp_ofs = operands[1];
8691     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8692       {
8693         rtx ra = gen_rtx_REG (Pmode, 2);
8695         emit_move_insn (ra, operands[2]);
8696         operands[2] = ra;
8697       }
8698     /* This is a hack -- we may have crystalized the function type too
8699        early.  */
8700     cfun->machine->func_type = 0;
8701   }"
8704 ;; This split is only used during output to reduce the number of patterns
8705 ;; that need assembler instructions adding to them.  We allowed the setting
8706 ;; of the conditions to be implicit during rtl generation so that
8707 ;; the conditional compare patterns would work.  However this conflicts to
8708 ;; some extent with the conditional data operations, so we have to split them
8709 ;; up again here.
8711 (define_split
8712   [(set (match_operand:SI 0 "s_register_operand" "")
8713         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8714                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8715                          (match_dup 0)
8716                          (match_operand 4 "" "")))
8717    (clobber (reg:CC CC_REGNUM))]
8718   "TARGET_ARM && reload_completed"
8719   [(set (match_dup 5) (match_dup 6))
8720    (cond_exec (match_dup 7)
8721               (set (match_dup 0) (match_dup 4)))]
8722   "
8723   {
8724     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8725                                              operands[2], operands[3]);
8726     enum rtx_code rc = GET_CODE (operands[1]);
8728     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8729     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8730     if (mode == CCFPmode || mode == CCFPEmode)
8731       rc = reverse_condition_maybe_unordered (rc);
8732     else
8733       rc = reverse_condition (rc);
8735     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8736   }"
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_operand 4 "" "")
8744                          (match_dup 0)))
8745    (clobber (reg:CC CC_REGNUM))]
8746   "TARGET_ARM && reload_completed"
8747   [(set (match_dup 5) (match_dup 6))
8748    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
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]);
8755     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8756     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8757   }"
8760 (define_split
8761   [(set (match_operand:SI 0 "s_register_operand" "")
8762         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8763                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8764                          (match_operand 4 "" "")
8765                          (match_operand 5 "" "")))
8766    (clobber (reg:CC CC_REGNUM))]
8767   "TARGET_ARM && reload_completed"
8768   [(set (match_dup 6) (match_dup 7))
8769    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8770               (set (match_dup 0) (match_dup 4)))
8771    (cond_exec (match_dup 8)
8772               (set (match_dup 0) (match_dup 5)))]
8773   "
8774   {
8775     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8776                                              operands[2], operands[3]);
8777     enum rtx_code rc = GET_CODE (operands[1]);
8779     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8780     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8781     if (mode == CCFPmode || mode == CCFPEmode)
8782       rc = reverse_condition_maybe_unordered (rc);
8783     else
8784       rc = reverse_condition (rc);
8786     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8787   }"
8790 (define_split
8791   [(set (match_operand:SI 0 "s_register_operand" "")
8792         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8793                           [(match_operand:SI 2 "s_register_operand" "")
8794                            (match_operand:SI 3 "arm_add_operand" "")])
8795                          (match_operand:SI 4 "arm_rhs_operand" "")
8796                          (not:SI
8797                           (match_operand:SI 5 "s_register_operand" ""))))
8798    (clobber (reg:CC CC_REGNUM))]
8799   "TARGET_ARM && reload_completed"
8800   [(set (match_dup 6) (match_dup 7))
8801    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8802               (set (match_dup 0) (match_dup 4)))
8803    (cond_exec (match_dup 8)
8804               (set (match_dup 0) (not:SI (match_dup 5))))]
8805   "
8806   {
8807     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8808                                              operands[2], operands[3]);
8809     enum rtx_code rc = GET_CODE (operands[1]);
8811     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8812     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8813     if (mode == CCFPmode || mode == CCFPEmode)
8814       rc = reverse_condition_maybe_unordered (rc);
8815     else
8816       rc = reverse_condition (rc);
8818     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8819   }"
8822 (define_insn "*cond_move_not"
8823   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8824         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8825                           [(match_operand 3 "cc_register" "") (const_int 0)])
8826                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8827                          (not:SI
8828                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
8829   "TARGET_ARM"
8830   "@
8831    mvn%D4\\t%0, %2
8832    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8833   [(set_attr "conds" "use")
8834    (set_attr "length" "4,8")]
8837 ;; The next two patterns occur when an AND operation is followed by a
8838 ;; scc insn sequence 
8840 (define_insn "*sign_extract_onebit"
8841   [(set (match_operand:SI 0 "s_register_operand" "=r")
8842         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8843                          (const_int 1)
8844                          (match_operand:SI 2 "const_int_operand" "n")))]
8845   "TARGET_ARM"
8846   "*
8847     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8848     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8849     return \"mvnne\\t%0, #0\";
8850   "
8851   [(set_attr "conds" "clob")
8852    (set_attr "length" "8")]
8855 (define_insn "*not_signextract_onebit"
8856   [(set (match_operand:SI 0 "s_register_operand" "=r")
8857         (not:SI
8858          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8859                           (const_int 1)
8860                           (match_operand:SI 2 "const_int_operand" "n"))))]
8861   "TARGET_ARM"
8862   "*
8863     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8864     output_asm_insn (\"tst\\t%1, %2\", operands);
8865     output_asm_insn (\"mvneq\\t%0, #0\", operands);
8866     return \"movne\\t%0, #0\";
8867   "
8868   [(set_attr "conds" "clob")
8869    (set_attr "length" "12")]
8872 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8873 ;; expressions.  For simplicity, the first register is also in the unspec
8874 ;; part.
8875 (define_insn "*push_multi"
8876   [(match_parallel 2 "multi_register_push"
8877     [(set (match_operand:BLK 0 "memory_operand" "=m")
8878           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8879                       UNSPEC_PUSH_MULT))])]
8880   "TARGET_ARM"
8881   "*
8882   {
8883     int num_saves = XVECLEN (operands[2], 0);
8884      
8885     /* For the StrongARM at least it is faster to
8886        use STR to store only a single register.  */
8887     if (num_saves == 1)
8888       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8889     else
8890       {
8891         int i;
8892         char pattern[100];
8894         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8896         for (i = 1; i < num_saves; i++)
8897           {
8898             strcat (pattern, \", %|\");
8899             strcat (pattern,
8900                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8901           }
8903         strcat (pattern, \"}\");
8904         output_asm_insn (pattern, operands);
8905       }
8907     return \"\";
8908   }"
8909   [(set_attr "type" "store4")]
8912 (define_insn "stack_tie"
8913   [(set (mem:BLK (scratch))
8914         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8915                      (match_operand:SI 1 "s_register_operand" "r")]
8916                     UNSPEC_PRLG_STK))]
8917   ""
8918   ""
8919   [(set_attr "length" "0")]
8922 ;; Similarly for the floating point registers
8923 (define_insn "*push_fp_multi"
8924   [(match_parallel 2 "multi_register_push"
8925     [(set (match_operand:BLK 0 "memory_operand" "=m")
8926           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8927                       UNSPEC_PUSH_MULT))])]
8928   "TARGET_ARM"
8929   "*
8930   {
8931     char pattern[100];
8933     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8934     output_asm_insn (pattern, operands);
8935     return \"\";
8936   }"
8937   [(set_attr "type" "f_store")]
8940 ;; Special patterns for dealing with the constant pool
8942 (define_insn "align_4"
8943   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8944   "TARGET_EITHER"
8945   "*
8946   assemble_align (32);
8947   return \"\";
8948   "
8951 (define_insn "consttable_end"
8952   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8953   "TARGET_EITHER"
8954   "*
8955   making_const_table = FALSE;
8956   return \"\";
8957   "
8960 (define_insn "consttable_1"
8961   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8962   "TARGET_THUMB"
8963   "*
8964   making_const_table = TRUE;
8965   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8966   assemble_zeros (3);
8967   return \"\";
8968   "
8969   [(set_attr "length" "4")]
8972 (define_insn "consttable_2"
8973   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8974   "TARGET_THUMB"
8975   "*
8976   making_const_table = TRUE;
8977   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8978   assemble_zeros (2);
8979   return \"\";
8980   "
8981   [(set_attr "length" "4")]
8984 (define_insn "consttable_4"
8985   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8986   "TARGET_EITHER"
8987   "*
8988   {
8989     making_const_table = TRUE;
8990     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8991       {
8992       case MODE_FLOAT:
8993       {
8994         REAL_VALUE_TYPE r;
8995         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8996         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8997         break;
8998       }
8999       default:
9000         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9001         break;
9002       }
9003     return \"\";
9004   }"
9005   [(set_attr "length" "4")]
9008 (define_insn "consttable_8"
9009   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9010   "TARGET_EITHER"
9011   "*
9012   {
9013     making_const_table = TRUE;
9014     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9015       {
9016        case MODE_FLOAT:
9017         {
9018           REAL_VALUE_TYPE r;
9019           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9020           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9021           break;
9022         }
9023       default:
9024         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9025         break;
9026       }
9027     return \"\";
9028   }"
9029   [(set_attr "length" "8")]
9032 ;; Miscellaneous Thumb patterns
9034 (define_expand "tablejump"
9035   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9036               (use (label_ref (match_operand 1 "" "")))])]
9037   "TARGET_THUMB"
9038   "
9039   if (flag_pic)
9040     {
9041       /* Hopefully, CSE will eliminate this copy.  */
9042       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9043       rtx reg2 = gen_reg_rtx (SImode);
9045       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9046       operands[0] = reg2;
9047     }
9048   "
9051 (define_insn "*thumb_tablejump"
9052   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9053    (use (label_ref (match_operand 1 "" "")))]
9054   "TARGET_THUMB"
9055   "mov\\t%|pc, %0"
9056   [(set_attr "length" "2")]
9059 ;; V5 Instructions,
9061 (define_insn "clz"
9062   [(set (match_operand:SI             0 "s_register_operand" "=r")
9063         (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9064                    UNSPEC_CLZ))]
9065   "TARGET_ARM && arm_arch5"
9066   "clz\\t%0, %1")
9068 (define_expand "ffssi2"
9069   [(set (match_operand:SI 0 "s_register_operand" "")
9070         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9071   "TARGET_ARM && arm_arch5"
9072   "
9073   {
9074     rtx t1, t2, t3;
9076     t1 = gen_reg_rtx (SImode);
9077     t2 = gen_reg_rtx (SImode);
9078     t3 = gen_reg_rtx (SImode);
9080     emit_insn (gen_negsi2 (t1, operands[1]));
9081     emit_insn (gen_andsi3 (t2, operands[1], t1));
9082     emit_insn (gen_clz (t3, t2));
9083     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9084     DONE;
9085   }"
9088 ;; V5E instructions.
9090 (define_insn "prefetch"
9091   [(prefetch (match_operand:SI 0 "address_operand" "p")
9092              (match_operand:SI 1 "" "")
9093              (match_operand:SI 2 "" ""))]
9094   "TARGET_ARM && arm_arch5e"
9095   "pld\\t%a0")
9097 ;; General predication pattern
9099 (define_cond_exec
9100   [(match_operator 0 "arm_comparison_operator"
9101     [(match_operand 1 "cc_register" "")
9102      (const_int 0)])]
9103   "TARGET_ARM"
9104   ""
9107 (define_insn "prologue_use"
9108   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9109   ""
9110   "%@ %0 needed for prologue"