* arm.c (use_return_insn): Don't try to determine the function type
[official-gcc.git] / gcc / config / arm / arm.md
blob205dc3794c09a1054e899cd1ce15e9408b291d1b
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000, 2001
3 ;;  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   ]
70 ;; UNSPEC_VOLATILE Usage:
72 (define_constants
73   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
74                         ;   insn in the code.
75    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
76                         ;   instruction epilogue sequence that isn't expanded
77                         ;   into normal RTL.  Used for both normal and sibcall
78                         ;   epilogues.
79    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
80                         ;   for inlined constants.
81    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
82                         ;   table.
83    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
84                         ;   an 8-bit object.
85    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
86                         ;   a 16-bit object.
87    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
88                         ;   a 32-bit object.
89    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
90                         ;   a 64-bit object.
91    (VUNSPEC_PREFETCH 8) ; `pld' insn to prefetch a cache line:
92                         ;   operand 0 is the address to fetch.
93   ]
96 ;;---------------------------------------------------------------------------
97 ;; Attributes
99 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
100 ; generating ARM code.  This is used to control the length of some insn
101 ; patterns that share the same RTL in both ARM and Thumb code.
102 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
104 ; PROG_MODE attribute is used to determine whether condition codes are
105 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
106 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
107 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
109 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
110 ; scheduling decisions for the load unit and the multiplier.
111 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
113 ;; Operand number of an input operand that is shifted.  Zero if the
114 ;; given instruction does not shift one of its input operands.
115 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
116 (define_attr "shift" "" (const_int 0))
118 ; Floating Point Unit.  If we only have floating point emulation, then there
119 ; is no point in scheduling the floating point insns.  (Well, for best
120 ; performance we should try and group them together).
121 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
123 ; LENGTH of an instruction (in bytes)
124 (define_attr "length" "" (const_int 4))
126 ; POOL_RANGE is how far away from a constant pool entry that this insn
127 ; can be placed.  If the distance is zero, then this insn will never
128 ; reference the pool.
129 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
130 ; before its address.
131 (define_attr "pool_range" "" (const_int 0))
132 (define_attr "neg_pool_range" "" (const_int 0))
134 ; An assembler sequence may clobber the condition codes without us knowing.
135 (define_asm_attributes
136  [(set_attr "conds" "clob")])
138 ; TYPE attribute is used to detect floating point instructions which, if
139 ; running on a co-processor can run in parallel with other, basic instructions
140 ; If write-buffer scheduling is enabled then it can also be used in the
141 ; scheduling of writes.
143 ; Classification of each insn
144 ; normal        any data instruction that doesn't hit memory or fp regs
145 ; mult          a multiply instruction
146 ; block         blockage insn, this blocks all functional units
147 ; float         a floating point arithmetic operation (subject to expansion)
148 ; fdivx         XFmode floating point division
149 ; fdivd         DFmode floating point division
150 ; fdivs         SFmode floating point division
151 ; fmul          Floating point multiply
152 ; ffmul         Fast floating point multiply
153 ; farith        Floating point arithmetic (4 cycle)
154 ; ffarith       Fast floating point arithmetic (2 cycle)
155 ; float_em      a floating point arithmetic operation that is normally emulated
156 ;               even on a machine with an fpa.
157 ; f_load        a floating point load from memory
158 ; f_store       a floating point store to memory
159 ; f_mem_r       a transfer of a floating point register to a real reg via mem
160 ; r_mem_f       the reverse of f_mem_r
161 ; f_2_r         fast transfer float to arm (no memory needed)
162 ; r_2_f         fast transfer arm to float
163 ; call          a subroutine call
164 ; load          any load from memory
165 ; store1        store 1 word to memory from arm registers
166 ; store2        store 2 words
167 ; store3        store 3 words
168 ; store4        store 4 words
170 (define_attr "type"
171         "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" 
172         (const_string "normal"))
174 ; Load scheduling, set from the arm_ld_sched variable
175 ; initialised by arm_override_options() 
176 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
178 ; condition codes: this one is used by final_prescan_insn to speed up
179 ; conditionalizing instructions.  It saves having to scan the rtl to see if
180 ; it uses or alters the condition codes.
182 ; USE means that the condition codes are used by the insn in the process of
183 ;   outputting code, this means (at present) that we can't use the insn in
184 ;   inlined branches
186 ; SET means that the purpose of the insn is to set the condition codes in a
187 ;   well defined manner.
189 ; CLOB means that the condition codes are altered in an undefined manner, if
190 ;   they are altered at all
192 ; JUMP_CLOB is used when the condition cannot be represented by a single
193 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
195 ; NOCOND means that the condition codes are neither altered nor affect the
196 ;   output of this insn
198 (define_attr "conds" "use,set,clob,jump_clob,nocond"
199         (if_then_else (eq_attr "type" "call")
200          (if_then_else (eq_attr "prog_mode" "prog32")
201           (const_string "clob") (const_string "nocond"))
202          (const_string "nocond")))
204 ; Predicable means that the insn can be conditionally executed based on
205 ; an automatically added predicate (additional patterns are generated by 
206 ; gen...).  We default to 'no' because no Thumb patterns match this rule
207 ; and not all ARM patterns do.
208 (define_attr "predicable" "no,yes" (const_string "no"))
210 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
211 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
212 ; suffer blockages enough to warrent modelling this (and it can adversely
213 ; affect the schedule).
214 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
216 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
217 ; to stall the processor.  Used with model_wbuf above.
218 (define_attr "write_conflict" "no,yes"
219   (if_then_else (eq_attr "type"
220                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
221                 (const_string "yes")
222                 (const_string "no")))
224 ; Classify the insns into those that take one cycle and those that take more
225 ; than one on the main cpu execution unit.
226 (define_attr "core_cycles" "single,multi"
227   (if_then_else (eq_attr "type"
228                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
229                 (const_string "single")
230                 (const_string "multi")))
232 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
233 ;; distant label.  Only applicable to Thumb code.
234 (define_attr "far_jump" "yes,no" (const_string "no"))
236 ;; (define_function_unit {name} {num-units} {n-users} {test}
237 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
239 ;;--------------------------------------------------------------------
240 ;; Floating point unit (FPA)
241 ;;--------------------------------------------------------------------
242 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
243                                      (eq_attr "type" "fdivx")) 71 69)
245 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
246                                      (eq_attr "type" "fdivd")) 59 57)
248 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
249                                      (eq_attr "type" "fdivs")) 31 29)
251 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
252                                      (eq_attr "type" "fmul")) 9 7)
254 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
255                                      (eq_attr "type" "ffmul")) 6 4)
257 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
258                                      (eq_attr "type" "farith")) 4 2)
260 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
261                                      (eq_attr "type" "ffarith")) 2 2)
263 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
264                                      (eq_attr "type" "r_2_f")) 5 3)
266 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
267                                      (eq_attr "type" "f_2_r")) 1 2)
269 ; The fpa10 doesn't really have a memory read unit, but it can start to
270 ; speculatively execute the instruction in the pipeline, provided the data
271 ; is already loaded, so pretend reads have a delay of 2 (and that the
272 ; pipeline is infinite).
274 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
275                                          (eq_attr "type" "f_load")) 3 1)
277 ;;--------------------------------------------------------------------
278 ;; Write buffer
279 ;;--------------------------------------------------------------------
280 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
282 ; The write buffer on some of the arm6 processors is hard to model exactly.
283 ; There is room in the buffer for up to two addresses and up to eight words
284 ; of memory, but the two needn't be split evenly.  When writing the two
285 ; addresses are fully pipelined.  However, a read from memory that is not
286 ; currently in the cache will block until the writes have completed.
287 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
288 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
289 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
290 ; cycle to add as well.
292 (define_function_unit "write_buf" 1 2
293   (and (eq_attr "model_wbuf" "yes")
294        (eq_attr "type" "store1,r_mem_f")) 5 3)
295 (define_function_unit "write_buf" 1 2 
296   (and (eq_attr "model_wbuf" "yes")
297        (eq_attr "type" "store2")) 7 4)
298 (define_function_unit "write_buf" 1 2
299   (and (eq_attr "model_wbuf" "yes")
300        (eq_attr "type" "store3")) 9 5)
301 (define_function_unit "write_buf" 1 2
302   (and (eq_attr "model_wbuf" "yes")
303        (eq_attr "type" "store4")) 11 6)
305 ;;--------------------------------------------------------------------
306 ;; Write blockage unit
307 ;;--------------------------------------------------------------------
308 ; The write_blockage unit models (partially), the fact that reads will stall
309 ; until the write buffer empties.
310 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
311 ; so we don't model them here
312 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
313                                                 (eq_attr "type" "store1")) 5 5
314         [(eq_attr "write_conflict" "yes")])
315 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
316                                                 (eq_attr "type" "store2")) 7 7
317         [(eq_attr "write_conflict" "yes")])
318 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
319                                                 (eq_attr "type" "store3")) 9 9
320         [(eq_attr "write_conflict" "yes")])
321 (define_function_unit "write_blockage" 1 0
322         (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
323         [(eq_attr "write_conflict" "yes")])
324 (define_function_unit "write_blockage" 1 0
325         (and (eq_attr "model_wbuf" "yes")
326              (eq_attr "write_conflict" "yes")) 1 1)
328 ;;--------------------------------------------------------------------
329 ;; Core unit
330 ;;--------------------------------------------------------------------
331 ; Everything must spend at least one cycle in the core unit
332 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
334 (define_function_unit "core" 1 0
335   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
337 (define_function_unit "core" 1 0
338   (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
340 ;; We do not need to conditionalize the define_function_unit immediately
341 ;; above.  This one will be ignored for anything other than xscale
342 ;; compiles and for xscale compiles it provides a larger delay
343 ;; and the scheduler will DTRT.
344 ;; FIXME: this test needs to be revamped to not depend on this feature 
345 ;; of the scheduler.
347 (define_function_unit "core" 1 0
348   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
349        (eq_attr "is_xscale" "yes"))
350    3 1)
352 (define_function_unit "core" 1 0
353   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
355 (define_function_unit "core" 1 0
356   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
358 (define_function_unit "core" 1 0
359   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
361 (define_function_unit "core" 1 0
362   (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
364 (define_function_unit "core" 1 0
365   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
367 (define_function_unit "core" 1 0
368   (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
370 (define_function_unit "core" 1 0
371   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
372        (eq_attr "type" "mult")) 4 4)
374 (define_function_unit "core" 1 0
375   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
376        (eq_attr "type" "mult")) 3 2)
378 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
380 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
382 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
384 (define_function_unit "core" 1 0
385   (and (eq_attr "core_cycles" "multi")
386        (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
388 ;;---------------------------------------------------------------------------
389 ;; Insn patterns
391 ;; Addition insns.
393 ;; Note: For DImode insns, there is normally no reason why operands should
394 ;; not be in the same register, what we don't want is for something being
395 ;; written to partially overlap something that is an input.
397 (define_expand "adddi3"
398  [(parallel
399    [(set (match_operand:DI           0 "s_register_operand" "")
400           (plus:DI (match_operand:DI 1 "s_register_operand" "")
401                    (match_operand:DI 2 "s_register_operand" "")))
402     (clobber (reg:CC CC_REGNUM))])]
403   "TARGET_EITHER"
404   "
405   if (TARGET_THUMB)
406     {
407       if (GET_CODE (operands[1]) != REG)
408         operands[1] = force_reg (SImode, operands[1]);
409       if (GET_CODE (operands[2]) != REG)
410         operands[2] = force_reg (SImode, operands[2]);
411      }
412   "
415 (define_insn "*thumb_adddi3"
416   [(set (match_operand:DI          0 "register_operand" "=l")
417         (plus:DI (match_operand:DI 1 "register_operand" "%0")
418                  (match_operand:DI 2 "register_operand" "l")))
419    (clobber (reg:CC CC_REGNUM))
420   ]
421   "TARGET_THUMB"
422   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
423   [(set_attr "length" "4")]
426 (define_insn_and_split "*arm_adddi3"
427   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
428         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
429                  (match_operand:DI 2 "s_register_operand" "r,  0")))
430    (clobber (reg:CC CC_REGNUM))]
431   "TARGET_ARM"
432   "#"
433   "TARGET_ARM && reload_completed"
434   [(parallel [(set (reg:CC_C CC_REGNUM)
435                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
436                                  (match_dup 1)))
437               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
438    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
439                                (plus:SI (match_dup 4) (match_dup 5))))]
440   "
441   {
442     operands[3] = gen_highpart (SImode, operands[0]);
443     operands[0] = gen_lowpart (SImode, operands[0]);
444     operands[4] = gen_highpart (SImode, operands[1]);
445     operands[1] = gen_lowpart (SImode, operands[1]);
446     operands[5] = gen_highpart (SImode, operands[2]);
447     operands[2] = gen_lowpart (SImode, operands[2]);
448   }"
449   [(set_attr "conds" "clob")
450    (set_attr "length" "8")]
453 (define_insn_and_split "*adddi_sesidi_di"
454   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
455         (plus:DI (sign_extend:DI
456                   (match_operand:SI 2 "s_register_operand" "r,r"))
457                  (match_operand:DI 1 "s_register_operand" "r,0")))
458    (clobber (reg:CC CC_REGNUM))]
459   "TARGET_ARM"
460   "#"
461   "TARGET_ARM && reload_completed"
462   [(parallel [(set (reg:CC_C CC_REGNUM)
463                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
464                                  (match_dup 1)))
465               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
466    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
467                                (plus:SI (ashiftrt:SI (match_dup 2)
468                                                      (const_int 31))
469                                         (match_dup 4))))]
470   "
471   {
472     operands[3] = gen_highpart (SImode, operands[0]);
473     operands[0] = gen_lowpart (SImode, operands[0]);
474     operands[4] = gen_highpart (SImode, operands[1]);
475     operands[1] = gen_lowpart (SImode, operands[1]);
476     operands[2] = gen_lowpart (SImode, operands[2]);
477   }"
478   [(set_attr "conds" "clob")
479    (set_attr "length" "8")]
482 (define_insn_and_split "*adddi_zesidi_di"
483   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
484         (plus:DI (zero_extend:DI
485                   (match_operand:SI 2 "s_register_operand" "r,r"))
486                  (match_operand:DI 1 "s_register_operand" "r,0")))
487    (clobber (reg:CC CC_REGNUM))]
488   "TARGET_ARM"
489   "#"
490   "TARGET_ARM && reload_completed"
491   [(parallel [(set (reg:CC_C CC_REGNUM)
492                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
493                                  (match_dup 1)))
494               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
495    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
496                                (plus:SI (match_dup 4) (const_int 0))))]
497   "
498   {
499     operands[3] = gen_highpart (SImode, operands[0]);
500     operands[0] = gen_lowpart (SImode, operands[0]);
501     operands[4] = gen_highpart (SImode, operands[1]);
502     operands[1] = gen_lowpart (SImode, operands[1]);
503     operands[2] = gen_lowpart (SImode, operands[2]);
504   }"
505   [(set_attr "conds" "clob")
506    (set_attr "length" "8")]
509 (define_expand "addsi3"
510   [(set (match_operand:SI          0 "s_register_operand" "")
511         (plus:SI (match_operand:SI 1 "s_register_operand" "")
512                  (match_operand:SI 2 "reg_or_int_operand" "")))]
513   "TARGET_EITHER"
514   "
515   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
516     {
517       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
518                           operands[1],
519                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
520       DONE;
521     }
522   "
525 ; If there is a scratch available, this will be faster than synthesising the
526 ; addition.
527 (define_peephole2
528   [(match_scratch:SI 3 "r")
529    (set (match_operand:SI          0 "s_register_operand" "")
530         (plus:SI (match_operand:SI 1 "s_register_operand" "")
531                  (match_operand:SI 2 "const_int_operand"  "")))]
532   "TARGET_ARM &&
533    !(const_ok_for_arm (INTVAL (operands[2]))
534      || const_ok_for_arm (-INTVAL (operands[2])))
535     && const_ok_for_arm (~INTVAL (operands[2]))"
536   [(set (match_dup 3) (match_dup 2))
537    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
538   ""
541 (define_insn_and_split "*arm_addsi3"
542   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
543         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
544                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
545   "TARGET_ARM"
546   "@
547    add%?\\t%0, %1, %2
548    sub%?\\t%0, %1, #%n2
549    #"
550   "TARGET_ARM &&
551    GET_CODE (operands[2]) == CONST_INT
552    && !(const_ok_for_arm (INTVAL (operands[2]))
553         || const_ok_for_arm (-INTVAL (operands[2])))"
554   [(clobber (const_int 0))]
555   "
556   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
557                       operands[1], 0);
558   DONE;
559   "
560   [(set_attr "length" "4,4,16")
561    (set_attr "predicable" "yes")]
564 ;; Register group 'k' is a single register group containing only the stack
565 ;; register.  Trying to reload it will always fail catastrophically,
566 ;; so never allow those alternatives to match if reloading is needed.
568 (define_insn "*thumb_addsi3"
569   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
570         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
571                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
572   "TARGET_THUMB"
573   "*
574    static const char * const asms[] = 
575    {
576      \"add\\t%0, %0, %2\",
577      \"sub\\t%0, %0, #%n2\",
578      \"add\\t%0, %1, %2\",
579      \"add\\t%0, %0, %2\",
580      \"add\\t%0, %0, %2\",
581      \"add\\t%0, %1, %2\",
582      \"add\\t%0, %1, %2\"
583    };
584    if ((which_alternative == 2 || which_alternative == 6)
585        && GET_CODE (operands[2]) == CONST_INT
586        && INTVAL (operands[2]) < 0)
587      return \"sub\\t%0, %1, #%n2\";
588    return asms[which_alternative];
589   "
590   [(set_attr "length" "2")]
593 ;; Reloading and elimination of the frame pointer can
594 ;; sometimes cause this optimization to be missed.
595 (define_peephole2
596   [(set (match_operand:SI 0 "register_operand" "=l")
597         (match_operand:SI 1 "const_int_operand" "M"))
598    (set (match_dup 0)
599         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
600   "TARGET_THUMB
601    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
602    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
603    && (INTVAL (operands[1]) & 3) == 0"
604   [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
605   ""
608 (define_insn "*addsi3_compare0"
609   [(set (reg:CC_NOOV CC_REGNUM)
610         (compare:CC_NOOV
611          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
612                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
613          (const_int 0)))
614    (set (match_operand:SI 0 "s_register_operand" "=r,r")
615         (plus:SI (match_dup 1) (match_dup 2)))]
616   "TARGET_ARM"
617   "@
618    add%?s\\t%0, %1, %2
619    sub%?s\\t%0, %1, #%n2"
620   [(set_attr "conds" "set")]
623 (define_insn "*addsi3_compare0_scratch"
624   [(set (reg:CC_NOOV CC_REGNUM)
625         (compare:CC_NOOV
626          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
627                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
628          (const_int 0)))]
629   "TARGET_ARM"
630   "@
631    cmn%?\\t%0, %1
632    cmp%?\\t%0, #%n1"
633   [(set_attr "conds" "set")]
636 ;; These patterns are the same ones as the two regular addsi3_compare0
637 ;; patterns, except we write them slightly different - the combiner
638 ;; tends to generate them this way.
639 (define_insn "*addsi3_compare0_for_combiner"
640   [(set (reg:CC CC_REGNUM)
641         (compare:CC
642          (match_operand:SI 1 "s_register_operand" "r,r")
643          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
644    (set (match_operand:SI 0 "s_register_operand" "=r,r")
645         (plus:SI (match_dup 1) (match_dup 2)))]
646   "TARGET_ARM"
647   "@
648    add%?s\\t%0, %1, %2
649    sub%?s\\t%0, %1, #%n2"
650   [(set_attr "conds" "set")]
653 (define_insn "*addsi3_compare0_scratch_for_combiner"
654   [(set (reg:CC CC_REGNUM)
655         (compare:CC
656          (match_operand:SI 0 "s_register_operand" "r,r")
657          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
658   "TARGET_ARM"
659   "@
660    cmn%?\\t%0, %1
661    cmp%?\\t%0, #%n1"
662   [(set_attr "conds" "set")]
665 ;; The next four insns work because they compare the result with one of
666 ;; the operands, and we know that the use of the condition code is
667 ;; either GEU or LTU, so we can use the carry flag from the addition
668 ;; instead of doing the compare a second time.
669 (define_insn "*addsi3_compare_op1"
670   [(set (reg:CC_C CC_REGNUM)
671         (compare:CC_C
672          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
674          (match_dup 1)))
675    (set (match_operand:SI 0 "s_register_operand" "=r,r")
676         (plus:SI (match_dup 1) (match_dup 2)))]
677   "TARGET_ARM"
678   "@
679    add%?s\\t%0, %1, %2
680    sub%?s\\t%0, %1, #%n2"
681   [(set_attr "conds" "set")]
684 (define_insn "*addsi3_compare_op2"
685   [(set (reg:CC_C CC_REGNUM)
686         (compare:CC_C
687          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
688                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
689          (match_dup 2)))
690    (set (match_operand:SI 0 "s_register_operand" "=r,r")
691         (plus:SI (match_dup 1) (match_dup 2)))]
692   "TARGET_ARM"
693   "@
694    add%?s\\t%0, %1, %2
695    sub%?s\\t%0, %1, #%n2"
696   [(set_attr "conds" "set")]
699 (define_insn "*compare_addsi2_op0"
700   [(set (reg:CC_C CC_REGNUM)
701         (compare:CC_C
702          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
704          (match_dup 0)))]
705   "TARGET_ARM"
706   "@
707    cmn%?\\t%0, %1
708    cmp%?\\t%0, #%n1"
709   [(set_attr "conds" "set")]
712 (define_insn "*compare_addsi2_op1"
713   [(set (reg:CC_C CC_REGNUM)
714         (compare:CC_C
715          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
716                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
717          (match_dup 1)))]
718   "TARGET_ARM"
719   "@
720    cmn%?\\t%0, %1
721    cmp%?\\t%0, #%n1"
722   [(set_attr "conds" "set")]
725 (define_insn "*addsi3_carryin"
726   [(set (match_operand:SI 0 "s_register_operand" "=r")
727         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
728                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
729                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
730   "TARGET_ARM"
731   "adc%?\\t%0, %1, %2"
732   [(set_attr "conds" "use")]
735 (define_insn "*addsi3_carryin_shift"
736   [(set (match_operand:SI 0 "s_register_operand" "")
737         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
738                  (plus:SI
739                    (match_operator:SI 2 "shift_operator"
740                       [(match_operand:SI 3 "s_register_operand" "")
741                        (match_operand:SI 4 "reg_or_int_operand" "")])
742                     (match_operand:SI 1 "s_register_operand" ""))))]
743   "TARGET_ARM"
744   "adc%?\\t%0, %1, %3%S2"
745   [(set_attr "conds" "use")]
748 (define_insn "*addsi3_carryin_alt1"
749   [(set (match_operand:SI 0 "s_register_operand" "=r")
750         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
751                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
752                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
753   "TARGET_ARM"
754   "adc%?\\t%0, %1, %2"
755   [(set_attr "conds" "use")]
758 (define_insn "*addsi3_carryin_alt2"
759   [(set (match_operand:SI 0 "s_register_operand" "=r")
760         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
761                           (match_operand:SI 1 "s_register_operand" "r"))
762                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
763   "TARGET_ARM"
764   "adc%?\\t%0, %1, %2"
765   [(set_attr "conds" "use")]
768 (define_insn "*addsi3_carryin_alt3"
769   [(set (match_operand:SI 0 "s_register_operand" "=r")
770         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
771                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
772                  (match_operand:SI 1 "s_register_operand" "r")))]
773   "TARGET_ARM"
774   "adc%?\\t%0, %1, %2"
775   [(set_attr "conds" "use")]
778 (define_insn "incscc"
779   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
780         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
781                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
782                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
783   "TARGET_ARM"
784   "@
785   add%d2\\t%0, %1, #1
786   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
787   [(set_attr "conds" "use")
788    (set_attr "length" "4,8")]
791 (define_insn "addsf3"
792   [(set (match_operand:SF          0 "s_register_operand" "=f,f")
793         (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
794                  (match_operand:SF 2 "fpu_add_operand"    "fG,H")))]
795   "TARGET_ARM && TARGET_HARD_FLOAT"
796   "@
797    adf%?s\\t%0, %1, %2
798    suf%?s\\t%0, %1, #%N2"
799   [(set_attr "type" "farith")
800    (set_attr "predicable" "yes")]
803 (define_insn "adddf3"
804   [(set (match_operand:DF          0 "s_register_operand" "=f,f")
805         (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
806                  (match_operand:DF 2 "fpu_add_operand"    "fG,H")))]
807   "TARGET_ARM && TARGET_HARD_FLOAT"
808   "@
809    adf%?d\\t%0, %1, %2
810    suf%?d\\t%0, %1, #%N2"
811   [(set_attr "type" "farith")
812    (set_attr "predicable" "yes")]
815 (define_insn "*adddf_esfdf_df"
816   [(set (match_operand:DF           0 "s_register_operand" "=f,f")
817         (plus:DF (float_extend:DF
818                   (match_operand:SF 1 "s_register_operand"  "f,f"))
819                  (match_operand:DF  2 "fpu_add_operand"    "fG,H")))]
820   "TARGET_ARM && TARGET_HARD_FLOAT"
821   "@
822    adf%?d\\t%0, %1, %2
823    suf%?d\\t%0, %1, #%N2"
824   [(set_attr "type" "farith")
825    (set_attr "predicable" "yes")]
828 (define_insn "*adddf_df_esfdf"
829   [(set (match_operand:DF           0 "s_register_operand" "=f")
830         (plus:DF (match_operand:DF  1 "s_register_operand"  "f")
831                  (float_extend:DF
832                   (match_operand:SF 2 "s_register_operand"  "f"))))]
833   "TARGET_ARM && TARGET_HARD_FLOAT"
834   "adf%?d\\t%0, %1, %2"
835   [(set_attr "type" "farith")
836    (set_attr "predicable" "yes")]
839 (define_insn "*adddf_esfdf_esfdf"
840   [(set (match_operand:DF           0 "s_register_operand" "=f")
841         (plus:DF (float_extend:DF 
842                   (match_operand:SF 1 "s_register_operand" "f"))
843                  (float_extend:DF
844                   (match_operand:SF 2 "s_register_operand" "f"))))]
845   "TARGET_ARM && TARGET_HARD_FLOAT"
846   "adf%?d\\t%0, %1, %2"
847   [(set_attr "type" "farith")
848    (set_attr "predicable" "yes")]
851 (define_insn "addxf3"
852   [(set (match_operand:XF          0 "s_register_operand" "=f,f")
853         (plus:XF (match_operand:XF 1 "s_register_operand"  "f,f")
854                  (match_operand:XF 2 "fpu_add_operand"    "fG,H")))]
855   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
856   "@
857    adf%?e\\t%0, %1, %2
858    suf%?e\\t%0, %1, #%N2"
859   [(set_attr "type" "farith")
860    (set_attr "predicable" "yes")]
863 (define_expand "subdi3"
864  [(parallel
865    [(set (match_operand:DI            0 "s_register_operand" "")
866           (minus:DI (match_operand:DI 1 "s_register_operand" "")
867                     (match_operand:DI 2 "s_register_operand" "")))
868     (clobber (reg:CC CC_REGNUM))])]
869   "TARGET_EITHER"
870   "
871   if (TARGET_THUMB)
872     {
873       if (GET_CODE (operands[1]) != REG)
874         operands[1] = force_reg (SImode, operands[1]);
875       if (GET_CODE (operands[2]) != REG)
876         operands[2] = force_reg (SImode, operands[2]);
877      }  
878   "
881 (define_insn "*arm_subdi3"
882   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
883         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
884                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
885    (clobber (reg:CC CC_REGNUM))]
886   "TARGET_ARM"
887   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
888   [(set_attr "conds" "clob")
889    (set_attr "length" "8")]
892 (define_insn "*thumb_subdi3"
893   [(set (match_operand:DI           0 "register_operand" "=l")
894         (minus:DI (match_operand:DI 1 "register_operand"  "0")
895                   (match_operand:DI 2 "register_operand"  "l")))
896    (clobber (reg:CC CC_REGNUM))]
897   "TARGET_THUMB"
898   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
899   [(set_attr "length" "4")]
902 (define_insn "*subdi_di_zesidi"
903   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
904         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
905                   (zero_extend:DI
906                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
907    (clobber (reg:CC CC_REGNUM))]
908   "TARGET_ARM"
909   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
910   [(set_attr "conds" "clob")
911    (set_attr "length" "8")]
914 (define_insn "*subdi_di_sesidi"
915   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
916         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
917                   (sign_extend:DI
918                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
919    (clobber (reg:CC CC_REGNUM))]
920   "TARGET_ARM"
921   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
922   [(set_attr "conds" "clob")
923    (set_attr "length" "8")]
926 (define_insn "*subdi_zesidi_di"
927   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
928         (minus:DI (zero_extend:DI
929                    (match_operand:SI 2 "s_register_operand"  "r,r"))
930                   (match_operand:DI  1 "s_register_operand" "?r,0")))
931    (clobber (reg:CC CC_REGNUM))]
932   "TARGET_ARM"
933   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
934   [(set_attr "conds" "clob")
935    (set_attr "length" "8")]
938 (define_insn "*subdi_sesidi_di"
939   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
940         (minus:DI (sign_extend:DI
941                    (match_operand:SI 2 "s_register_operand"   "r,r"))
942                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
943    (clobber (reg:CC CC_REGNUM))]
944   "TARGET_ARM"
945   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
946   [(set_attr "conds" "clob")
947    (set_attr "length" "8")]
950 (define_insn "*subdi_zesidi_zesidi"
951   [(set (match_operand:DI            0 "s_register_operand" "=r")
952         (minus:DI (zero_extend:DI
953                    (match_operand:SI 1 "s_register_operand"  "r"))
954                   (zero_extend:DI
955                    (match_operand:SI 2 "s_register_operand"  "r"))))
956    (clobber (reg:CC CC_REGNUM))]
957   "TARGET_ARM"
958   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
959   [(set_attr "conds" "clob")
960    (set_attr "length" "8")]
963 (define_expand "subsi3"
964   [(set (match_operand:SI           0 "s_register_operand" "")
965         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
966                   (match_operand:SI 2 "s_register_operand" "")))]
967   "TARGET_EITHER"
968   "
969   if (GET_CODE (operands[1]) == CONST_INT)
970     {
971       if (TARGET_ARM)
972         {
973           arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
974                               operands[2],
975                               (no_new_pseudos ? 0
976                                :  preserve_subexpressions_p ()));
977           DONE;
978         }
979       else /* TARGET_THUMB */
980         operands[1] = force_reg (SImode, operands[1]);
981     }
982   "
985 (define_insn "*thumb_subsi3_insn"
986   [(set (match_operand:SI           0 "register_operand" "=l")
987         (minus:SI (match_operand:SI 1 "register_operand" "l")
988                   (match_operand:SI 2 "register_operand" "l")))]
989   "TARGET_THUMB"
990   "sub\\t%0, %1, %2"
991   [(set_attr "length" "2")]
994 (define_insn_and_split "*arm_subsi3_insn"
995   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
996         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
997                   (match_operand:SI 2 "s_register_operand" "r,r")))]
998   "TARGET_ARM"
999   "@
1000    rsb%?\\t%0, %2, %1
1001    #"
1002   "TARGET_ARM
1003    && GET_CODE (operands[1]) == CONST_INT
1004    && !const_ok_for_arm (INTVAL (operands[1]))"
1005   [(clobber (const_int 0))]
1006   "
1007   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1008                       operands[2], 0);
1009   DONE;
1010   "
1011   [(set_attr "length" "4,16")
1012    (set_attr "predicable" "yes")]
1015 (define_peephole2
1016   [(match_scratch:SI 3 "r")
1017    (set (match_operand:SI           0 "s_register_operand" "")
1018         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1019                   (match_operand:SI 2 "s_register_operand" "")))]
1020   "TARGET_ARM
1021    && !const_ok_for_arm (INTVAL (operands[1]))
1022    && const_ok_for_arm (~INTVAL (operands[1]))"
1023   [(set (match_dup 3) (match_dup 1))
1024    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1025   ""
1028 (define_insn "*subsi3_compare0"
1029   [(set (reg:CC_NOOV CC_REGNUM)
1030         (compare:CC_NOOV
1031          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1032                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1033          (const_int 0)))
1034    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1035         (minus:SI (match_dup 1) (match_dup 2)))]
1036   "TARGET_ARM"
1037   "@
1038    sub%?s\\t%0, %1, %2
1039    rsb%?s\\t%0, %2, %1"
1040   [(set_attr "conds" "set")]
1043 (define_insn "decscc"
1044   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1045         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1046                   (match_operator:SI 2 "arm_comparison_operator"
1047                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1048   "TARGET_ARM"
1049   "@
1050    sub%d2\\t%0, %1, #1
1051    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1052   [(set_attr "conds" "use")
1053    (set_attr "length" "*,8")]
1056 (define_insn "subsf3"
1057   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1058         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1059                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1060   "TARGET_ARM && TARGET_HARD_FLOAT"
1061   "@
1062    suf%?s\\t%0, %1, %2
1063    rsf%?s\\t%0, %2, %1"
1064   [(set_attr "type" "farith")]
1067 (define_insn "subdf3"
1068   [(set (match_operand:DF           0 "s_register_operand" "=f,f")
1069         (minus:DF (match_operand:DF 1 "fpu_rhs_operand"     "f,G")
1070                   (match_operand:DF 2 "fpu_rhs_operand"    "fG,f")))]
1071   "TARGET_ARM && TARGET_HARD_FLOAT"
1072   "@
1073    suf%?d\\t%0, %1, %2
1074    rsf%?d\\t%0, %2, %1"
1075   [(set_attr "type" "farith")
1076    (set_attr "predicable" "yes")]
1079 (define_insn "*subdf_esfdf_df"
1080   [(set (match_operand:DF            0 "s_register_operand" "=f")
1081         (minus:DF (float_extend:DF
1082                    (match_operand:SF 1 "s_register_operand"  "f"))
1083                   (match_operand:DF  2 "fpu_rhs_operand"    "fG")))]
1084   "TARGET_ARM && TARGET_HARD_FLOAT"
1085   "suf%?d\\t%0, %1, %2"
1086   [(set_attr "type" "farith")
1087    (set_attr "predicable" "yes")]
1090 (define_insn "*subdf_df_esfdf"
1091   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1092         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1093                   (float_extend:DF
1094                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
1095   "TARGET_ARM && TARGET_HARD_FLOAT"
1096   "@
1097    suf%?d\\t%0, %1, %2
1098    rsf%?d\\t%0, %2, %1"
1099   [(set_attr "type" "farith")
1100    (set_attr "predicable" "yes")]
1103 (define_insn "*subdf_esfdf_esfdf"
1104   [(set (match_operand:DF 0 "s_register_operand" "=f")
1105         (minus:DF (float_extend:DF
1106                    (match_operand:SF 1 "s_register_operand" "f"))
1107                   (float_extend:DF
1108                    (match_operand:SF 2 "s_register_operand" "f"))))]
1109   "TARGET_ARM && TARGET_HARD_FLOAT"
1110   "suf%?d\\t%0, %1, %2"
1111   [(set_attr "type" "farith")
1112    (set_attr "predicable" "yes")]
1115 (define_insn "subxf3"
1116   [(set (match_operand:XF           0 "s_register_operand" "=f,f")
1117         (minus:XF (match_operand:XF 1 "fpu_rhs_operand"     "f,G")
1118                   (match_operand:XF 2 "fpu_rhs_operand"    "fG,f")))]
1119   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1120   "@
1121    suf%?e\\t%0, %1, %2
1122    rsf%?e\\t%0, %2, %1"
1123   [(set_attr "type" "farith")
1124    (set_attr "predicable" "yes")]
1127 ;; Multiplication insns
1129 (define_expand "mulsi3"
1130   [(set (match_operand:SI          0 "s_register_operand" "")
1131         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1132                  (match_operand:SI 1 "s_register_operand" "")))]
1133   "TARGET_EITHER"
1134   ""
1137 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1138 (define_insn "*arm_mulsi3"
1139   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1140         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1141                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1142   "TARGET_ARM"
1143   "mul%?\\t%0, %2, %1"
1144   [(set_attr "type" "mult")
1145    (set_attr "predicable" "yes")]
1148 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1149 ; 1 and 2; are the same, because reload will make operand 0 match 
1150 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1151 ; this by adding another alternative to match this case, and then `reload' 
1152 ; it ourselves.  This alternative must come first.
1153 (define_insn "*thumb_mulsi3"
1154   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1155         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1156                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1157   "TARGET_THUMB"
1158   "*
1159   if (which_alternative < 2)
1160     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1161   else
1162     return \"mul\\t%0, %0, %2\";
1163   "
1164   [(set_attr "length" "4,4,2")
1165    (set_attr "type" "mult")]
1168 (define_insn "*mulsi3_compare0"
1169   [(set (reg:CC_NOOV CC_REGNUM)
1170         (compare:CC_NOOV (mult:SI
1171                           (match_operand:SI 2 "s_register_operand" "r,r")
1172                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1173                          (const_int 0)))
1174    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1175         (mult:SI (match_dup 2) (match_dup 1)))]
1176   "TARGET_ARM && !arm_is_xscale"
1177   "mul%?s\\t%0, %2, %1"
1178   [(set_attr "conds" "set")
1179    (set_attr "type" "mult")]
1182 (define_insn "*mulsi_compare0_scratch"
1183   [(set (reg:CC_NOOV CC_REGNUM)
1184         (compare:CC_NOOV (mult:SI
1185                           (match_operand:SI 2 "s_register_operand" "r,r")
1186                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1187                          (const_int 0)))
1188    (clobber (match_scratch:SI 0 "=&r,&r"))]
1189   "TARGET_ARM && !arm_is_xscale"
1190   "mul%?s\\t%0, %2, %1"
1191   [(set_attr "conds" "set")
1192    (set_attr "type" "mult")]
1195 ;; Unnamed templates to match MLA instruction.
1197 (define_insn "*mulsi3addsi"
1198   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1199         (plus:SI
1200           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1201                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1202           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1203   "TARGET_ARM"
1204   "mla%?\\t%0, %2, %1, %3"
1205   [(set_attr "type" "mult")
1206    (set_attr "predicable" "yes")]
1209 (define_insn "*mulsi3addsi_compare0"
1210   [(set (reg:CC_NOOV CC_REGNUM)
1211         (compare:CC_NOOV
1212          (plus:SI (mult:SI
1213                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1214                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1215                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1216          (const_int 0)))
1217    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1218         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1219                  (match_dup 3)))]
1220   "TARGET_ARM && !arm_is_xscale"
1221   "mla%?s\\t%0, %2, %1, %3"
1222   [(set_attr "conds" "set")
1223    (set_attr "type" "mult")]
1226 (define_insn "*mulsi3addsi_compare0_scratch"
1227   [(set (reg:CC_NOOV CC_REGNUM)
1228         (compare:CC_NOOV
1229          (plus:SI (mult:SI
1230                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1231                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1232                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1233          (const_int 0)))
1234    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1235   "TARGET_ARM && !arm_is_xscale"
1236   "mla%?s\\t%0, %2, %1, %3"
1237   [(set_attr "conds" "set")
1238    (set_attr "type" "mult")]
1241 ;; Unnamed template to match long long multiply-accumlate (smlal)
1243 (define_insn "*mulsidi3adddi"
1244   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1245         (plus:DI
1246          (mult:DI
1247           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1248           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1249          (match_operand:DI 1 "s_register_operand" "0")))]
1250   "TARGET_ARM && arm_fast_multiply"
1251   "smlal%?\\t%Q0, %R0, %3, %2"
1252   [(set_attr "type" "mult")
1253    (set_attr "predicable" "yes")]
1256 (define_insn "mulsidi3"
1257   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1258         (mult:DI
1259          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1260          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1261   "TARGET_ARM && arm_fast_multiply"
1262   "smull%?\\t%Q0, %R0, %1, %2"
1263   [(set_attr "type" "mult")
1264    (set_attr "predicable" "yes")]
1267 (define_insn "umulsidi3"
1268   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1269         (mult:DI
1270          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1271          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1272   "TARGET_ARM && arm_fast_multiply"
1273   "umull%?\\t%Q0, %R0, %1, %2"
1274   [(set_attr "type" "mult")
1275    (set_attr "predicable" "yes")]
1278 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1280 (define_insn "*umulsidi3adddi"
1281   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1282         (plus:DI
1283          (mult:DI
1284           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1285           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1286          (match_operand:DI 1 "s_register_operand" "0")))]
1287   "TARGET_ARM && arm_fast_multiply"
1288   "umlal%?\\t%Q0, %R0, %3, %2"
1289   [(set_attr "type" "mult")
1290    (set_attr "predicable" "yes")]
1293 (define_insn "smulsi3_highpart"
1294   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1295         (truncate:SI
1296          (lshiftrt:DI
1297           (mult:DI
1298            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1299            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1300           (const_int 32))))
1301    (clobber (match_scratch:SI 3 "=&r,&r"))]
1302   "TARGET_ARM && arm_fast_multiply"
1303   "smull%?\\t%3, %0, %2, %1"
1304   [(set_attr "type" "mult")
1305    (set_attr "predicable" "yes")]
1308 (define_insn "umulsi3_highpart"
1309   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1310         (truncate:SI
1311          (lshiftrt:DI
1312           (mult:DI
1313            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1314            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1315           (const_int 32))))
1316    (clobber (match_scratch:SI 3 "=&r,&r"))]
1317   "TARGET_ARM && arm_fast_multiply"
1318   "umull%?\\t%3, %0, %2, %1"
1319   [(set_attr "type" "mult")
1320    (set_attr "predicable" "yes")]
1323 (define_insn "mulhisi3"
1324   [(set (match_operand:SI 0 "s_register_operand" "=r")
1325         (mult:SI (sign_extend:SI
1326                   (match_operand:HI 1 "s_register_operand" "%r"))
1327                  (sign_extend:SI
1328                   (match_operand:HI 2 "s_register_operand" "r"))))]
1329   "TARGET_ARM && arm_is_xscale"
1330   "smulbb%?\\t%0, %1, %2"
1331   [(set_attr "type" "mult")]
1334 (define_insn "*mulhisi3addsi"
1335   [(set (match_operand:SI 0 "s_register_operand" "=r")
1336         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1337                  (mult:SI (sign_extend:SI
1338                            (match_operand:HI 2 "s_register_operand" "%r"))
1339                           (sign_extend:SI
1340                            (match_operand:HI 3 "s_register_operand" "r")))))]
1341   "TARGET_ARM && arm_is_xscale"
1342   "smlabb%?\\t%0, %2, %3, %1"
1343   [(set_attr "type" "mult")]
1346 (define_insn "*mulhidi3adddi"
1347   [(set (match_operand:DI 0 "s_register_operand" "=r")
1348         (plus:DI
1349           (match_operand:DI 1 "s_register_operand" "0")
1350           (mult:DI (sign_extend:DI
1351                     (match_operand:HI 2 "s_register_operand" "%r"))
1352                    (sign_extend:DI
1353                     (match_operand:HI 3 "s_register_operand" "r")))))]
1354   "TARGET_ARM && arm_is_xscale"
1355   "smlalbb%?\\t%Q0, %R0, %2, %3"
1356 [(set_attr "type" "mult")])
1358 (define_insn "mulsf3"
1359   [(set (match_operand:SF 0 "s_register_operand" "=f")
1360         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1361                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1362   "TARGET_ARM && TARGET_HARD_FLOAT"
1363   "fml%?s\\t%0, %1, %2"
1364   [(set_attr "type" "ffmul")
1365    (set_attr "predicable" "yes")]
1368 (define_insn "muldf3"
1369   [(set (match_operand:DF 0 "s_register_operand" "=f")
1370         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1371                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1372   "TARGET_ARM && TARGET_HARD_FLOAT"
1373   "muf%?d\\t%0, %1, %2"
1374   [(set_attr "type" "fmul")
1375    (set_attr "predicable" "yes")]
1378 (define_insn "*muldf_esfdf_df"
1379   [(set (match_operand:DF 0 "s_register_operand" "=f")
1380         (mult:DF (float_extend:DF
1381                   (match_operand:SF 1 "s_register_operand" "f"))
1382                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1383   "TARGET_ARM && TARGET_HARD_FLOAT"
1384   "muf%?d\\t%0, %1, %2"
1385   [(set_attr "type" "fmul")
1386    (set_attr "predicable" "yes")]
1389 (define_insn "*muldf_df_esfdf"
1390   [(set (match_operand:DF 0 "s_register_operand" "=f")
1391         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1392                  (float_extend:DF
1393                   (match_operand:SF 2 "s_register_operand" "f"))))]
1394   "TARGET_ARM && TARGET_HARD_FLOAT"
1395   "muf%?d\\t%0, %1, %2"
1396   [(set_attr "type" "fmul")
1397    (set_attr "predicable" "yes")]
1400 (define_insn "*muldf_esfdf_esfdf"
1401   [(set (match_operand:DF 0 "s_register_operand" "=f")
1402         (mult:DF
1403          (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1404          (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1405   "TARGET_ARM && TARGET_HARD_FLOAT"
1406   "muf%?d\\t%0, %1, %2"
1407   [(set_attr "type" "fmul")
1408    (set_attr "predicable" "yes")]
1411 (define_insn "mulxf3"
1412   [(set (match_operand:XF 0 "s_register_operand" "=f")
1413         (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1414                  (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1415   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1416   "muf%?e\\t%0, %1, %2"
1417   [(set_attr "type" "fmul")
1418    (set_attr "predicable" "yes")]
1421 ;; Division insns
1423 (define_insn "divsf3"
1424   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1425         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1426                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1427   "TARGET_ARM && TARGET_HARD_FLOAT"
1428   "@
1429    fdv%?s\\t%0, %1, %2
1430    frd%?s\\t%0, %2, %1"
1431   [(set_attr "type" "fdivs")
1432    (set_attr "predicable" "yes")]
1435 (define_insn "divdf3"
1436   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1437         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1438                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1439   "TARGET_ARM && TARGET_HARD_FLOAT"
1440   "@
1441    dvf%?d\\t%0, %1, %2
1442    rdf%?d\\t%0, %2, %1"
1443   [(set_attr "type" "fdivd")
1444    (set_attr "predicable" "yes")]
1447 (define_insn "*divdf_esfdf_df"
1448   [(set (match_operand:DF 0 "s_register_operand" "=f")
1449         (div:DF (float_extend:DF
1450                  (match_operand:SF 1 "s_register_operand" "f"))
1451                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1452   "TARGET_ARM && TARGET_HARD_FLOAT"
1453   "dvf%?d\\t%0, %1, %2"
1454   [(set_attr "type" "fdivd")
1455    (set_attr "predicable" "yes")]
1458 (define_insn "*divdf_df_esfdf"
1459   [(set (match_operand:DF 0 "s_register_operand" "=f")
1460         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1461                 (float_extend:DF
1462                  (match_operand:SF 2 "s_register_operand" "f"))))]
1463   "TARGET_ARM && TARGET_HARD_FLOAT"
1464   "rdf%?d\\t%0, %2, %1"
1465   [(set_attr "type" "fdivd")
1466    (set_attr "predicable" "yes")]
1469 (define_insn "*divdf_esfdf_esfdf"
1470   [(set (match_operand:DF 0 "s_register_operand" "=f")
1471         (div:DF (float_extend:DF
1472                  (match_operand:SF 1 "s_register_operand" "f"))
1473                 (float_extend:DF
1474                  (match_operand:SF 2 "s_register_operand" "f"))))]
1475   "TARGET_ARM && TARGET_HARD_FLOAT"
1476   "dvf%?d\\t%0, %1, %2"
1477   [(set_attr "type" "fdivd")
1478    (set_attr "predicable" "yes")]
1481 (define_insn "divxf3"
1482   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1483         (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1484                 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1485   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1486   "@
1487    dvf%?e\\t%0, %1, %2
1488    rdf%?e\\t%0, %2, %1"
1489   [(set_attr "type" "fdivx")
1490    (set_attr "predicable" "yes")]
1493 ;; Modulo insns
1495 (define_insn "modsf3"
1496   [(set (match_operand:SF 0 "s_register_operand" "=f")
1497         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1498                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1499   "TARGET_ARM && TARGET_HARD_FLOAT"
1500   "rmf%?s\\t%0, %1, %2"
1501   [(set_attr "type" "fdivs")
1502    (set_attr "predicable" "yes")]
1505 (define_insn "moddf3"
1506   [(set (match_operand:DF 0 "s_register_operand" "=f")
1507         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1508                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1509   "TARGET_ARM && TARGET_HARD_FLOAT"
1510   "rmf%?d\\t%0, %1, %2"
1511   [(set_attr "type" "fdivd")
1512    (set_attr "predicable" "yes")]
1515 (define_insn "*moddf_esfdf_df"
1516   [(set (match_operand:DF 0 "s_register_operand" "=f")
1517         (mod:DF (float_extend:DF
1518                  (match_operand:SF 1 "s_register_operand" "f"))
1519                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1520   "TARGET_ARM && TARGET_HARD_FLOAT"
1521   "rmf%?d\\t%0, %1, %2"
1522   [(set_attr "type" "fdivd")
1523    (set_attr "predicable" "yes")]
1526 (define_insn "*moddf_df_esfdf"
1527   [(set (match_operand:DF 0 "s_register_operand" "=f")
1528         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1529                 (float_extend:DF
1530                  (match_operand:SF 2 "s_register_operand" "f"))))]
1531   "TARGET_ARM && TARGET_HARD_FLOAT"
1532   "rmf%?d\\t%0, %1, %2"
1533   [(set_attr "type" "fdivd")
1534    (set_attr "predicable" "yes")]
1537 (define_insn "*moddf_esfdf_esfdf"
1538   [(set (match_operand:DF 0 "s_register_operand" "=f")
1539         (mod:DF (float_extend:DF
1540                  (match_operand:SF 1 "s_register_operand" "f"))
1541                 (float_extend:DF
1542                  (match_operand:SF 2 "s_register_operand" "f"))))]
1543   "TARGET_ARM && TARGET_HARD_FLOAT"
1544   "rmf%?d\\t%0, %1, %2"
1545   [(set_attr "type" "fdivd")
1546    (set_attr "predicable" "yes")]
1549 (define_insn "modxf3"
1550   [(set (match_operand:XF 0 "s_register_operand" "=f")
1551         (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1552                 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1553   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1554   "rmf%?e\\t%0, %1, %2"
1555   [(set_attr "type" "fdivx")
1556    (set_attr "predicable" "yes")]
1559 ;; Boolean and,ior,xor insns
1561 ;; Split up double word logical operations
1563 ;; Split up simple DImode logical operations.  Simply perform the logical
1564 ;; operation on the upper and lower halves of the registers.
1565 (define_split
1566   [(set (match_operand:DI 0 "s_register_operand" "")
1567         (match_operator:DI 6 "logical_binary_operator"
1568           [(match_operand:DI 1 "s_register_operand" "")
1569            (match_operand:DI 2 "s_register_operand" "")]))]
1570   "TARGET_ARM && reload_completed"
1571   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1572    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1573   "
1574   {
1575     operands[3] = gen_highpart (SImode, operands[0]);
1576     operands[0] = gen_lowpart (SImode, operands[0]);
1577     operands[4] = gen_highpart (SImode, operands[1]);
1578     operands[1] = gen_lowpart (SImode, operands[1]);
1579     operands[5] = gen_highpart (SImode, operands[2]);
1580     operands[2] = gen_lowpart (SImode, operands[2]);
1581   }"
1584 (define_split
1585   [(set (match_operand:DI 0 "s_register_operand" "")
1586         (match_operator:DI 6 "logical_binary_operator"
1587           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1588            (match_operand:DI 1 "s_register_operand" "")]))]
1589   "TARGET_ARM && reload_completed"
1590   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1591    (set (match_dup 3) (match_op_dup:SI 6
1592                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1593                          (match_dup 4)]))]
1594   "
1595   {
1596     operands[3] = gen_highpart (SImode, operands[0]);
1597     operands[0] = gen_lowpart (SImode, operands[0]);
1598     operands[4] = gen_highpart (SImode, operands[1]);
1599     operands[1] = gen_lowpart (SImode, operands[1]);
1600     operands[5] = gen_highpart (SImode, operands[2]);
1601     operands[2] = gen_lowpart (SImode, operands[2]);
1602   }"
1605 ;; The zero extend of operand 2 means we can just copy the high part of
1606 ;; operand1 into operand0.
1607 (define_split
1608   [(set (match_operand:DI 0 "s_register_operand" "")
1609         (ior:DI
1610           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1611           (match_operand:DI 1 "s_register_operand" "")))]
1612   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1613   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1614    (set (match_dup 3) (match_dup 4))]
1615   "
1616   {
1617     operands[4] = gen_highpart (SImode, operands[1]);
1618     operands[3] = gen_highpart (SImode, operands[0]);
1619     operands[0] = gen_lowpart (SImode, operands[0]);
1620     operands[1] = gen_lowpart (SImode, operands[1]);
1621   }"
1624 ;; The zero extend of operand 2 means we can just copy the high part of
1625 ;; operand1 into operand0.
1626 (define_split
1627   [(set (match_operand:DI 0 "s_register_operand" "")
1628         (xor:DI
1629           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1630           (match_operand:DI 1 "s_register_operand" "")))]
1631   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1632   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1633    (set (match_dup 3) (match_dup 4))]
1634   "
1635   {
1636     operands[4] = gen_highpart (SImode, operands[1]);
1637     operands[3] = gen_highpart (SImode, operands[0]);
1638     operands[0] = gen_lowpart (SImode, operands[0]);
1639     operands[1] = gen_lowpart (SImode, operands[1]);
1640   }"
1643 (define_insn "anddi3"
1644   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1645         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1646                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1647   "TARGET_ARM"
1648   "#"
1649   [(set_attr "length" "8")]
1652 (define_insn_and_split "*anddi_zesidi_di"
1653   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1654         (and:DI (zero_extend:DI
1655                  (match_operand:SI 2 "s_register_operand" "r,r"))
1656                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1657   "TARGET_ARM"
1658   "#"
1659   "TARGET_ARM && reload_completed"
1660   ; The zero extend of operand 2 clears the high word of the output
1661   ; operand.
1662   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1663    (set (match_dup 3) (const_int 0))]
1664   "
1665   {
1666     operands[3] = gen_highpart (SImode, operands[0]);
1667     operands[0] = gen_lowpart (SImode, operands[0]);
1668     operands[1] = gen_lowpart (SImode, operands[1]);
1669   }"
1670   [(set_attr "length" "8")]
1673 (define_insn "*anddi_sesdi_di"
1674   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1675         (and:DI (sign_extend:DI
1676                  (match_operand:SI 2 "s_register_operand" "r,r"))
1677                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1678   "TARGET_ARM"
1679   "#"
1680   [(set_attr "length" "8")]
1683 (define_expand "andsi3"
1684   [(set (match_operand:SI         0 "s_register_operand" "")
1685         (and:SI (match_operand:SI 1 "s_register_operand" "")
1686                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1687   "TARGET_EITHER"
1688   "
1689   if (TARGET_ARM)
1690     {
1691       if (GET_CODE (operands[2]) == CONST_INT)
1692         {
1693           arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1694                               operands[1],
1695                               (no_new_pseudos
1696                                ? 0 : preserve_subexpressions_p ()));
1697           DONE;
1698         }
1699     }
1700   else /* TARGET_THUMB */
1701     {
1702       if (GET_CODE (operands[2]) != CONST_INT)
1703         operands[2] = force_reg (SImode, operands[2]);
1704       else
1705         {
1706           int i;
1707           
1708           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1709             {
1710               operands[2] = force_reg (SImode,
1711                                        GEN_INT (~INTVAL (operands[2])));
1712               
1713               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1714               
1715               DONE;
1716             }
1718           for (i = 9; i <= 31; i++)
1719             {
1720               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1721                 {
1722                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1723                                         const0_rtx));
1724                   DONE;
1725                 }
1726               else if ((((HOST_WIDE_INT) 1) << i) - 1
1727                        == ~INTVAL (operands[2]))
1728                 {
1729                   rtx shift = GEN_INT (i);
1730                   rtx reg = gen_reg_rtx (SImode);
1731                 
1732                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1733                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1734                   
1735                   DONE;
1736                 }
1737             }
1739           operands[2] = force_reg (SImode, operands[2]);
1740         }
1741     }
1742   "
1745 (define_insn_and_split "*arm_andsi3_insn"
1746   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1747         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1748                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1749   "TARGET_ARM"
1750   "@
1751    and%?\\t%0, %1, %2
1752    bic%?\\t%0, %1, #%B2
1753    #"
1754   "TARGET_ARM
1755    && GET_CODE (operands[2]) == CONST_INT
1756    && !(const_ok_for_arm (INTVAL (operands[2]))
1757         || const_ok_for_arm (~INTVAL (operands[2])))"
1758   [(clobber (const_int 0))]
1759   "
1760   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1761                        operands[1], 0);
1762   DONE;
1763   "
1764   [(set_attr "length" "4,4,16")
1765    (set_attr "predicable" "yes")]
1768 (define_insn "*thumb_andsi3_insn"
1769   [(set (match_operand:SI         0 "register_operand" "=l")
1770         (and:SI (match_operand:SI 1 "register_operand" "%0")
1771                 (match_operand:SI 2 "register_operand" "l")))]
1772   "TARGET_THUMB"
1773   "and\\t%0, %0, %2"
1774   [(set_attr "length" "2")]
1777 (define_insn "*andsi3_compare0"
1778   [(set (reg:CC_NOOV CC_REGNUM)
1779         (compare:CC_NOOV
1780          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1781                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1782          (const_int 0)))
1783    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1784         (and:SI (match_dup 1) (match_dup 2)))]
1785   "TARGET_ARM"
1786   "@
1787    and%?s\\t%0, %1, %2
1788    bic%?s\\t%0, %1, #%B2"
1789   [(set_attr "conds" "set")]
1792 (define_insn "*andsi3_compare0_scratch"
1793   [(set (reg:CC_NOOV CC_REGNUM)
1794         (compare:CC_NOOV
1795          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1796                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1797          (const_int 0)))
1798    (clobber (match_scratch:SI 2 "=X,r"))]
1799   "TARGET_ARM"
1800   "@
1801    tst%?\\t%0, %1
1802    bic%?s\\t%2, %0, #%B1"
1803   [(set_attr "conds" "set")]
1806 (define_insn "*zeroextractsi_compare0_scratch"
1807   [(set (reg:CC_NOOV CC_REGNUM)
1808         (compare:CC_NOOV (zero_extract:SI
1809                           (match_operand:SI 0 "s_register_operand" "r")
1810                           (match_operand 1 "const_int_operand" "n")
1811                           (match_operand 2 "const_int_operand" "n"))
1812                          (const_int 0)))]
1813   "TARGET_ARM
1814   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1815       && INTVAL (operands[1]) > 0 
1816       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1817       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1818   "*
1819   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1820                          << INTVAL (operands[2]));
1821   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1822   return \"\";
1823   "
1824   [(set_attr "conds" "set")]
1827 (define_insn "*ne_zeroextractsi"
1828   [(set (match_operand:SI 0 "s_register_operand" "=r")
1829         (ne:SI (zero_extract:SI
1830                 (match_operand:SI 1 "s_register_operand" "r")
1831                 (match_operand:SI 2 "const_int_operand" "n")
1832                 (match_operand:SI 3 "const_int_operand" "n"))
1833                (const_int 0)))]
1834   "TARGET_ARM
1835    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1836        && INTVAL (operands[2]) > 0 
1837        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1838        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1839   "*
1840   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1841                          << INTVAL (operands[3]));
1842   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1843   return \"movne\\t%0, #1\";
1844   "
1845   [(set_attr "conds" "clob")
1846    (set_attr "length" "8")]
1849 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1850 ;;; represented by the bitfield, then this will produce incorrect results.
1851 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1852 ;;; which have a real bitfield insert instruction, the truncation happens
1853 ;;; in the bitfield insert instruction itself.  Since arm does not have a
1854 ;;; bitfield insert instruction, we would have to emit code here to truncate
1855 ;;; the value before we insert.  This loses some of the advantage of having
1856 ;;; this insv pattern, so this pattern needs to be reevalutated.
1858 (define_expand "insv"
1859   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1860                          (match_operand:SI 1 "general_operand" "")
1861                          (match_operand:SI 2 "general_operand" ""))
1862         (match_operand:SI 3 "nonmemory_operand" ""))]
1863   "TARGET_ARM"
1864   "
1865   {
1866     int start_bit = INTVAL (operands[2]);
1867     int width = INTVAL (operands[1]);
1868     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1869     rtx target, subtarget;
1871     target = operands[0];
1872     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1873        subreg as the final target.  */
1874     if (GET_CODE (target) == SUBREG)
1875       {
1876         subtarget = gen_reg_rtx (SImode);
1877         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1878             < GET_MODE_SIZE (SImode))
1879           target = SUBREG_REG (target);
1880       }
1881     else
1882       subtarget = target;    
1884     if (GET_CODE (operands[3]) == CONST_INT)
1885       {
1886         /* Since we are inserting a known constant, we may be able to
1887            reduce the number of bits that we have to clear so that
1888            the mask becomes simple.  */
1889         /* ??? This code does not check to see if the new mask is actually
1890            simpler.  It may not be.  */
1891         rtx op1 = gen_reg_rtx (SImode);
1892         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1893            start of this pattern.  */
1894         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1895         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1897         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1898         emit_insn (gen_iorsi3 (subtarget, op1,
1899                                GEN_INT (op3_value << start_bit)));
1900       }
1901     else if (start_bit == 0
1902              && !(const_ok_for_arm (mask)
1903                   || const_ok_for_arm (~mask)))
1904       {
1905         /* A Trick, since we are setting the bottom bits in the word,
1906            we can shift operand[3] up, operand[0] down, OR them together
1907            and rotate the result back again.  This takes 3 insns, and
1908            the third might be mergable into another op.  */
1909         /* The shift up copes with the possibility that operand[3] is
1910            wider than the bitfield.  */
1911         rtx op0 = gen_reg_rtx (SImode);
1912         rtx op1 = gen_reg_rtx (SImode);
1914         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1915         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1916         emit_insn (gen_iorsi3  (op1, op1, op0));
1917         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1918       }
1919     else if ((width + start_bit == 32)
1920              && !(const_ok_for_arm (mask)
1921                   || const_ok_for_arm (~mask)))
1922       {
1923         /* Similar trick, but slightly less efficient.  */
1925         rtx op0 = gen_reg_rtx (SImode);
1926         rtx op1 = gen_reg_rtx (SImode);
1928         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1929         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1930         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1931         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1932       }
1933     else
1934       {
1935         rtx op0 = GEN_INT (mask);
1936         rtx op1 = gen_reg_rtx (SImode);
1937         rtx op2 = gen_reg_rtx (SImode);
1939         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1940           {
1941             rtx tmp = gen_reg_rtx (SImode);
1943             emit_insn (gen_movsi (tmp, op0));
1944             op0 = tmp;
1945           }
1947         /* Mask out any bits in operand[3] that are not needed.  */
1948            emit_insn (gen_andsi3 (op1, operands[3], op0));
1950         if (GET_CODE (op0) == CONST_INT
1951             && (const_ok_for_arm (mask << start_bit)
1952                 || const_ok_for_arm (~(mask << start_bit))))
1953           {
1954             op0 = GEN_INT (~(mask << start_bit));
1955             emit_insn (gen_andsi3 (op2, operands[0], op0));
1956           }
1957         else
1958           {
1959             if (GET_CODE (op0) == CONST_INT)
1960               {
1961                 rtx tmp = gen_reg_rtx (SImode);
1963                 emit_insn (gen_movsi (tmp, op0));
1964                 op0 = tmp;
1965               }
1967             if (start_bit != 0)
1968               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1969             
1970             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1971           }
1973         if (start_bit != 0)
1974           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1976         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1977       }
1979     if (subtarget != target)
1980       {
1981         /* If TARGET is still a SUBREG, then it must be wider than a word,
1982            so we must be careful only to set the subword we were asked to.  */
1983         if (GET_CODE (target) == SUBREG)
1984           emit_move_insn (target, subtarget);
1985         else
1986           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1987       }
1989     DONE;
1990   }"
1993 ; constants for op 2 will never be given to these patterns.
1994 (define_insn_and_split "*anddi_notdi_di"
1995   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1996         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1997                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1998   "TARGET_ARM"
1999   "#"
2000   "TARGET_ARM && reload_completed"
2001   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2002    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2003   "
2004   {
2005     operands[3] = gen_highpart (SImode, operands[0]);
2006     operands[0] = gen_lowpart (SImode, operands[0]);
2007     operands[4] = gen_highpart (SImode, operands[1]);
2008     operands[1] = gen_lowpart (SImode, operands[1]);
2009     operands[5] = gen_highpart (SImode, operands[2]);
2010     operands[2] = gen_lowpart (SImode, operands[2]);
2011   }"
2012   [(set_attr "length" "8")
2013    (set_attr "predicable" "yes")]
2015   
2016 (define_insn_and_split "*anddi_notzesidi_di"
2017   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2018         (and:DI (not:DI (zero_extend:DI
2019                          (match_operand:SI 2 "s_register_operand" "r,r")))
2020                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2021   "TARGET_ARM"
2022   "@
2023    bic%?\\t%Q0, %Q1, %2
2024    #"
2025   ; (not (zero_extend ...)) allows us to just copy the high word from
2026   ; operand1 to operand0.
2027   "TARGET_ARM
2028    && reload_completed
2029    && operands[0] != operands[1]"
2030   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2031    (set (match_dup 3) (match_dup 4))]
2032   "
2033   {
2034     operands[3] = gen_highpart (SImode, operands[0]);
2035     operands[0] = gen_lowpart (SImode, operands[0]);
2036     operands[4] = gen_highpart (SImode, operands[1]);
2037     operands[1] = gen_lowpart (SImode, operands[1]);
2038   }"
2039   [(set_attr "length" "4,8")
2040    (set_attr "predicable" "yes")]
2042   
2043 (define_insn_and_split "*anddi_notsesidi_di"
2044   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2045         (and:DI (not:DI (sign_extend:DI
2046                          (match_operand:SI 2 "s_register_operand" "r,r")))
2047                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2048   "TARGET_ARM"
2049   "#"
2050   "TARGET_ARM && reload_completed"
2051   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2052    (set (match_dup 3) (and:SI (not:SI
2053                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2054                                (match_dup 4)))]
2055   "
2056   {
2057     operands[3] = gen_highpart (SImode, operands[0]);
2058     operands[0] = gen_lowpart (SImode, operands[0]);
2059     operands[4] = gen_highpart (SImode, operands[1]);
2060     operands[1] = gen_lowpart (SImode, operands[1]);
2061   }"
2062   [(set_attr "length" "8")
2063    (set_attr "predicable" "yes")]
2065   
2066 (define_insn "andsi_notsi_si"
2067   [(set (match_operand:SI 0 "s_register_operand" "=r")
2068         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2069                 (match_operand:SI 1 "s_register_operand" "r")))]
2070   "TARGET_ARM"
2071   "bic%?\\t%0, %1, %2"
2072   [(set_attr "predicable" "yes")]
2075 (define_insn "bicsi3"
2076   [(set (match_operand:SI                 0 "register_operand" "=l")
2077         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2078                 (match_operand:SI         2 "register_operand" "0")))]
2079   "TARGET_THUMB"
2080   "bic\\t%0, %0, %1"
2081   [(set_attr "length" "2")]
2084 (define_insn "andsi_not_shiftsi_si"
2085   [(set (match_operand:SI                   0 "s_register_operand" "=r")
2086         (and:SI (not:SI (match_operator:SI  4 "shift_operator"
2087                          [(match_operand:SI 2 "s_register_operand"  "r")
2088                           (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
2089                 (match_operand:SI           1 "s_register_operand"  "r")))]
2090   "TARGET_ARM"
2091   "bic%?\\t%0, %1, %2%S4"
2092   [(set_attr "predicable" "yes")
2093    (set_attr "shift" "2")
2094    ]
2097 (define_insn "*andsi_notsi_si_compare0"
2098   [(set (reg:CC_NOOV CC_REGNUM)
2099         (compare:CC_NOOV
2100          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2101                  (match_operand:SI 1 "s_register_operand" "r"))
2102          (const_int 0)))
2103    (set (match_operand:SI 0 "s_register_operand" "=r")
2104         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2105   "TARGET_ARM"
2106   "bic%?s\\t%0, %1, %2"
2107   [(set_attr "conds" "set")]
2110 (define_insn "*andsi_notsi_si_compare0_scratch"
2111   [(set (reg:CC_NOOV CC_REGNUM)
2112         (compare:CC_NOOV
2113          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114                  (match_operand:SI 1 "s_register_operand" "r"))
2115          (const_int 0)))
2116    (clobber (match_scratch:SI 0 "=r"))]
2117   "TARGET_ARM"
2118   "bic%?s\\t%0, %1, %2"
2119   [(set_attr "conds" "set")]
2122 (define_insn "iordi3"
2123   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2124         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2125                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2126   "TARGET_ARM"
2127   "#"
2128   [(set_attr "length" "8")
2129    (set_attr "predicable" "yes")]
2132 (define_insn "*iordi_zesidi_di"
2133   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2134         (ior:DI (zero_extend:DI
2135                  (match_operand:SI 2 "s_register_operand" "r,r"))
2136                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2137   "TARGET_ARM"
2138   "@
2139    orr%?\\t%Q0, %Q1, %2
2140    #"
2141   [(set_attr "length" "4,8")
2142    (set_attr "predicable" "yes")]
2145 (define_insn "*iordi_sesidi_di"
2146   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2147         (ior:DI (sign_extend:DI
2148                  (match_operand:SI 2 "s_register_operand" "r,r"))
2149                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2150   "TARGET_ARM"
2151   "#"
2152   [(set_attr "length" "8")
2153    (set_attr "predicable" "yes")]
2156 (define_expand "iorsi3"
2157   [(set (match_operand:SI         0 "s_register_operand" "")
2158         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2159                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2160   "TARGET_EITHER"
2161   "
2162   if (GET_CODE (operands[2]) == CONST_INT)
2163     {
2164       if (TARGET_ARM)
2165         {
2166           arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2167                               operands[1],
2168                               (no_new_pseudos
2169                               ? 0 : preserve_subexpressions_p ()));
2170           DONE;
2171         }
2172       else /* TARGET_THUMB */
2173         operands [2] = force_reg (SImode, operands [2]);
2174     }
2175   "
2178 (define_insn_and_split "*arm_iorsi3"
2179   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2180         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2181                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2182   "TARGET_ARM"
2183   "@
2184    orr%?\\t%0, %1, %2
2185    #"
2186   "TARGET_ARM
2187    && GET_CODE (operands[2]) == CONST_INT
2188    && !const_ok_for_arm (INTVAL (operands[2]))"
2189   [(clobber (const_int 0))]
2190   "
2191   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2192                       operands[1], 0);
2193   DONE;
2194   "
2195   [(set_attr "length" "4,16")
2196    (set_attr "predicable" "yes")]
2199 (define_insn "*thumb_iorsi3"
2200   [(set (match_operand:SI         0 "register_operand" "=l")
2201         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2202                 (match_operand:SI 2 "register_operand" "l")))]
2203   "TARGET_THUMB"
2204   "orr\\t%0, %0, %2"
2205   [(set_attr "length" "2")]
2208 (define_peephole2
2209   [(match_scratch:SI 3 "r")
2210    (set (match_operand:SI         0 "s_register_operand" "")
2211         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2212                 (match_operand:SI 2 "const_int_operand" "")))]
2213   "TARGET_ARM
2214    && !const_ok_for_arm (INTVAL (operands[2]))
2215    && const_ok_for_arm (~INTVAL (operands[2]))"
2216   [(set (match_dup 3) (match_dup 2))
2217    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2218   ""
2221 (define_insn "*iorsi3_compare0"
2222   [(set (reg:CC_NOOV CC_REGNUM)
2223         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2224                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2225                          (const_int 0)))
2226    (set (match_operand:SI 0 "s_register_operand" "=r")
2227         (ior:SI (match_dup 1) (match_dup 2)))]
2228   "TARGET_ARM"
2229   "orr%?s\\t%0, %1, %2"
2230   [(set_attr "conds" "set")]
2233 (define_insn "*iorsi3_compare0_scratch"
2234   [(set (reg:CC_NOOV CC_REGNUM)
2235         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2237                          (const_int 0)))
2238    (clobber (match_scratch:SI 0 "=r"))]
2239   "TARGET_ARM"
2240   "orr%?s\\t%0, %1, %2"
2241   [(set_attr "conds" "set")]
2244 (define_insn "xordi3"
2245   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2246         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2247                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2248   "TARGET_ARM"
2249   "#"
2250   [(set_attr "length" "8")
2251    (set_attr "predicable" "yes")]
2254 (define_insn "*xordi_zesidi_di"
2255   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2256         (xor:DI (zero_extend:DI
2257                  (match_operand:SI 2 "s_register_operand" "r,r"))
2258                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2259   "TARGET_ARM"
2260   "@
2261    eor%?\\t%Q0, %Q1, %2
2262    #"
2263   [(set_attr "length" "4,8")
2264    (set_attr "predicable" "yes")]
2267 (define_insn "*xordi_sesidi_di"
2268   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2269         (xor:DI (sign_extend:DI
2270                  (match_operand:SI 2 "s_register_operand" "r,r"))
2271                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2272   "TARGET_ARM"
2273   "#"
2274   [(set_attr "length" "8")
2275    (set_attr "predicable" "yes")]
2278 (define_expand "xorsi3"
2279   [(set (match_operand:SI         0 "s_register_operand" "")
2280         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2281                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2282   "TARGET_EITHER"
2283   "if (TARGET_THUMB)
2284      if (GET_CODE (operands[2]) == CONST_INT)
2285        operands[2] = force_reg (SImode, operands[2]);
2286   "
2289 (define_insn "*arm_xorsi3"
2290   [(set (match_operand:SI         0 "s_register_operand" "=r")
2291         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2292                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2293   "TARGET_ARM"
2294   "eor%?\\t%0, %1, %2"
2295   [(set_attr "predicable" "yes")]
2298 (define_insn "*thumb_xorsi3"
2299   [(set (match_operand:SI         0 "register_operand" "=l")
2300         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2301                 (match_operand:SI 2 "register_operand" "l")))]
2302   "TARGET_THUMB"
2303   "eor\\t%0, %0, %2"
2304   [(set_attr "length" "2")]
2307 (define_insn "*xorsi3_compare0"
2308   [(set (reg:CC_NOOV CC_REGNUM)
2309         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2310                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2311                          (const_int 0)))
2312    (set (match_operand:SI 0 "s_register_operand" "=r")
2313         (xor:SI (match_dup 1) (match_dup 2)))]
2314   "TARGET_ARM"
2315   "eor%?s\\t%0, %1, %2"
2316   [(set_attr "conds" "set")]
2319 (define_insn "*xorsi3_compare0_scratch"
2320   [(set (reg:CC_NOOV CC_REGNUM)
2321         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2322                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2323                          (const_int 0)))]
2324   "TARGET_ARM"
2325   "teq%?\\t%0, %1"
2326   [(set_attr "conds" "set")]
2329 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2330 ; (NOT D) we can sometimes merge the final NOT into one of the following
2331 ; insns.
2333 (define_split
2334   [(set (match_operand:SI 0 "s_register_operand" "=r")
2335         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2336                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
2337                 (match_operand:SI 3 "arm_rhs_operand" "rI")))
2338    (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
2339   "TARGET_ARM"
2340   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2341                               (not:SI (match_dup 3))))
2342    (set (match_dup 0) (not:SI (match_dup 4)))]
2343   ""
2346 (define_insn "*andsi_iorsi3_notsi"
2347   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2348         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2349                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2350                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2351   "TARGET_ARM"
2352   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2353   [(set_attr "length" "8")
2354    (set_attr "predicable" "yes")]
2359 ;; Minimum and maximum insns
2361 (define_insn "smaxsi3"
2362   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2363         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2364                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2365    (clobber (reg:CC CC_REGNUM))]
2366   "TARGET_ARM"
2367   "@
2368    cmp\\t%1, %2\;movlt\\t%0, %2
2369    cmp\\t%1, %2\;movge\\t%0, %1
2370    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2371   [(set_attr "conds" "clob")
2372    (set_attr "length" "8,8,12")]
2375 (define_insn "sminsi3"
2376   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2377         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2378                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2379    (clobber (reg:CC CC_REGNUM))]
2380   "TARGET_ARM"
2381   "@
2382    cmp\\t%1, %2\;movge\\t%0, %2
2383    cmp\\t%1, %2\;movlt\\t%0, %1
2384    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2385   [(set_attr "conds" "clob")
2386    (set_attr "length" "8,8,12")]
2389 (define_insn "umaxsi3"
2390   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2391         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2392                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2393    (clobber (reg:CC CC_REGNUM))]
2394   "TARGET_ARM"
2395   "@
2396    cmp\\t%1, %2\;movcc\\t%0, %2
2397    cmp\\t%1, %2\;movcs\\t%0, %1
2398    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2399   [(set_attr "conds" "clob")
2400    (set_attr "length" "8,8,12")]
2403 (define_insn "uminsi3"
2404   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2405         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2406                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2407    (clobber (reg:CC CC_REGNUM))]
2408   "TARGET_ARM"
2409   "@
2410    cmp\\t%1, %2\;movcs\\t%0, %2
2411    cmp\\t%1, %2\;movcc\\t%0, %1
2412    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2413   [(set_attr "conds" "clob")
2414    (set_attr "length" "8,8,12")]
2417 (define_insn "*store_minmaxsi"
2418   [(set (match_operand:SI 0 "memory_operand" "=m")
2419         (match_operator:SI 3 "minmax_operator"
2420          [(match_operand:SI 1 "s_register_operand" "r")
2421           (match_operand:SI 2 "s_register_operand" "r")]))
2422    (clobber (reg:CC CC_REGNUM))]
2423   "TARGET_ARM"
2424   "*
2425   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2426                          operands[2]);
2427   output_asm_insn (\"cmp\\t%1, %2\", operands);
2428   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2429   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2430   return \"\";
2431   "
2432   [(set_attr "conds" "clob")
2433    (set_attr "length" "12")
2434    (set_attr "type" "store1")]
2437 ; Reject the frame pointer in operand[1], since reloading this after
2438 ; it has been eliminated can cause carnage.
2439 (define_insn "*minmax_arithsi"
2440   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2441         (match_operator:SI 4 "shiftable_operator"
2442          [(match_operator:SI 5 "minmax_operator"
2443            [(match_operand:SI 2 "s_register_operand" "r,r")
2444             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2445           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2446    (clobber (reg:CC CC_REGNUM))]
2447   "TARGET_ARM
2448    && (GET_CODE (operands[1]) != REG
2449        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2450            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2451   "*
2452   {
2453     enum rtx_code code = GET_CODE (operands[4]);
2455     operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2456                            operands[3]);
2457     output_asm_insn (\"cmp\\t%2, %3\", operands);
2458     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2459     if (which_alternative != 0 || operands[3] != const0_rtx
2460         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2461       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2462     return \"\";
2463   }"
2464   [(set_attr "conds" "clob")
2465    (set_attr "length" "12")]
2469 ;; Shift and rotation insns
2471 (define_expand "ashlsi3"
2472   [(set (match_operand:SI            0 "s_register_operand" "")
2473         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2474                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2475   "TARGET_EITHER"
2476   "
2477   if (GET_CODE (operands[2]) == CONST_INT
2478       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2479     {
2480       emit_insn (gen_movsi (operands[0], const0_rtx));
2481       DONE;
2482     }
2483   "
2486 (define_insn "*thumb_ashlsi3"
2487   [(set (match_operand:SI            0 "register_operand" "=l,l")
2488         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2489                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2490   "TARGET_THUMB"
2491   "lsl\\t%0, %1, %2"
2492   [(set_attr "length" "2")]
2495 (define_expand "ashrsi3"
2496   [(set (match_operand:SI              0 "s_register_operand" "")
2497         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2498                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2499   "TARGET_EITHER"
2500   "
2501   if (GET_CODE (operands[2]) == CONST_INT
2502       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2503     operands[2] = GEN_INT (31);
2504   "
2507 (define_insn "*thumb_ashrsi3"
2508   [(set (match_operand:SI              0 "register_operand" "=l,l")
2509         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2510                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2511   "TARGET_THUMB"
2512   "asr\\t%0, %1, %2"
2513   [(set_attr "length" "2")]
2516 (define_expand "lshrsi3"
2517   [(set (match_operand:SI              0 "s_register_operand" "")
2518         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2519                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2520   "TARGET_EITHER"
2521   "
2522   if (GET_CODE (operands[2]) == CONST_INT
2523       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2524     {
2525       emit_insn (gen_movsi (operands[0], const0_rtx));
2526       DONE;
2527     }
2528   "
2531 (define_insn "*thumb_lshrsi3"
2532   [(set (match_operand:SI              0 "register_operand" "=l,l")
2533         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2534                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2535   "TARGET_THUMB"
2536   "lsr\\t%0, %1, %2"
2537   [(set_attr "length" "2")]
2540 (define_expand "rotlsi3"
2541   [(set (match_operand:SI              0 "s_register_operand" "")
2542         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2543                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2544   "TARGET_ARM"
2545   "
2546   if (GET_CODE (operands[2]) == CONST_INT)
2547     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2548   else
2549     {
2550       rtx reg = gen_reg_rtx (SImode);
2551       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2552       operands[2] = reg;
2553     }
2554   "
2557 (define_expand "rotrsi3"
2558   [(set (match_operand:SI              0 "s_register_operand" "")
2559         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2560                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2561   "TARGET_EITHER"
2562   "
2563   if (TARGET_ARM)
2564     {
2565       if (GET_CODE (operands[2]) == CONST_INT
2566           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2567         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2568     }
2569   else /* TARGET_THUMB */
2570     {
2571       if (GET_CODE (operands [2]) == CONST_INT)
2572         operands [2] = force_reg (SImode, operands[2]);
2573     }
2574   "
2577 (define_insn "*thumb_rotrsi3"
2578   [(set (match_operand:SI              0 "register_operand" "=l")
2579         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2580                      (match_operand:SI 2 "register_operand" "l")))]
2581   "TARGET_THUMB"
2582   "ror\\t%0, %0, %2"
2583   [(set_attr "length" "2")]
2586 (define_insn "*arm_shiftsi3"
2587   [(set (match_operand:SI   0 "s_register_operand" "=r")
2588         (match_operator:SI  3 "shift_operator"
2589          [(match_operand:SI 1 "s_register_operand"  "r")
2590           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2591   "TARGET_ARM"
2592   "mov%?\\t%0, %1%S3"
2593   [(set_attr "predicable" "yes")
2594    (set_attr "shift" "1")
2595    ]
2598 (define_insn "*shiftsi3_compare0"
2599   [(set (reg:CC_NOOV CC_REGNUM)
2600         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2601                           [(match_operand:SI 1 "s_register_operand" "r")
2602                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2603                          (const_int 0)))
2604    (set (match_operand:SI 0 "s_register_operand" "=r")
2605         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2606   "TARGET_ARM"
2607   "mov%?s\\t%0, %1%S3"
2608   [(set_attr "conds" "set")
2609    (set_attr "shift" "1")
2610    ]
2613 (define_insn "*shiftsi3_compare0_scratch"
2614   [(set (reg:CC_NOOV CC_REGNUM)
2615         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2616                           [(match_operand:SI 1 "s_register_operand" "r")
2617                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2618                          (const_int 0)))
2619    (clobber (match_scratch:SI 0 "=r"))]
2620   "TARGET_ARM"
2621   "mov%?s\\t%0, %1%S3"
2622   [(set_attr "conds" "set")
2623    (set_attr "shift" "1")
2624    ]
2627 (define_insn "*notsi_shiftsi"
2628   [(set (match_operand:SI 0 "s_register_operand" "=r")
2629         (not:SI (match_operator:SI 3 "shift_operator"
2630                  [(match_operand:SI 1 "s_register_operand" "r")
2631                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2632   "TARGET_ARM"
2633   "mvn%?\\t%0, %1%S3"
2634   [(set_attr "predicable" "yes")
2635    (set_attr "shift" "1")
2636    ]
2639 (define_insn "*notsi_shiftsi_compare0"
2640   [(set (reg:CC_NOOV CC_REGNUM)
2641         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2642                           [(match_operand:SI 1 "s_register_operand" "r")
2643                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2644                          (const_int 0)))
2645    (set (match_operand:SI 0 "s_register_operand" "=r")
2646         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2647   "TARGET_ARM"
2648   "mvn%?s\\t%0, %1%S3"
2649   [(set_attr "conds" "set")
2650    (set_attr "shift" "1")
2651    ]
2654 (define_insn "*not_shiftsi_compare0_scratch"
2655   [(set (reg:CC_NOOV CC_REGNUM)
2656         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2657                           [(match_operand:SI 1 "s_register_operand" "r")
2658                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2659                          (const_int 0)))
2660    (clobber (match_scratch:SI 0 "=r"))]
2661   "TARGET_ARM"
2662   "mvn%?s\\t%0, %1%S3"
2663   [(set_attr "conds" "set")
2664    (set_attr "shift" "1")
2665   ]
2668 ;; We don't really have extzv, but defining this using shifts helps
2669 ;; to reduce register pressure later on.
2671 (define_expand "extzv"
2672   [(set (match_dup 4)
2673         (ashift:SI (match_operand:SI   1 "register_operand" "")
2674                    (match_operand:SI   2 "const_int_operand" "")))
2675    (set (match_operand:SI              0 "register_operand" "")
2676         (lshiftrt:SI (match_dup 4)
2677                      (match_operand:SI 3 "const_int_operand" "")))]
2678   "TARGET_THUMB"
2679   "
2680   {
2681     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2682     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2683     
2684     operands[3] = GEN_INT (rshift);
2685     
2686     if (lshift == 0)
2687       {
2688         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2689         DONE;
2690       }
2691       
2692     operands[2] = GEN_INT (lshift);
2693     operands[4] = gen_reg_rtx (SImode);
2694   }"
2698 ;; Unary arithmetic insns
2700 (define_expand "negdi2"
2701  [(parallel
2702    [(set (match_operand:DI          0 "s_register_operand" "")
2703           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2704     (clobber (reg:CC CC_REGNUM))])]
2705   "TARGET_EITHER"
2706   "
2707   if (TARGET_THUMB)
2708     {
2709       if (GET_CODE (operands[1]) != REG)
2710         operands[1] = force_reg (SImode, operands[1]);
2711      }
2712   "
2715 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2716 ;; The second alternative is to allow the common case of a *full* overlap.
2717 (define_insn "*arm_negdi2"
2718   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2719         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2720    (clobber (reg:CC CC_REGNUM))]
2721   "TARGET_ARM"
2722   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2723   [(set_attr "conds" "clob")
2724    (set_attr "length" "8")]
2727 (define_insn "*thumb_negdi2"
2728   [(set (match_operand:DI         0 "register_operand" "=&l")
2729         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2730    (clobber (reg:CC CC_REGNUM))]
2731   "TARGET_THUMB"
2732   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2733   [(set_attr "length" "6")]
2736 (define_expand "negsi2"
2737   [(set (match_operand:SI         0 "s_register_operand" "")
2738         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2739   "TARGET_EITHER"
2740   ""
2743 (define_insn "*arm_negsi2"
2744   [(set (match_operand:SI         0 "s_register_operand" "=r")
2745         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2746   "TARGET_ARM"
2747   "rsb%?\\t%0, %1, #0"
2748   [(set_attr "predicable" "yes")]
2751 (define_insn "*thumb_negsi2"
2752   [(set (match_operand:SI         0 "register_operand" "=l")
2753         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2754   "TARGET_THUMB"
2755   "neg\\t%0, %1"
2756   [(set_attr "length" "2")]
2759 (define_insn "negsf2"
2760   [(set (match_operand:SF 0 "s_register_operand" "=f")
2761         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2762   "TARGET_ARM && TARGET_HARD_FLOAT"
2763   "mnf%?s\\t%0, %1"
2764   [(set_attr "type" "ffarith")
2765    (set_attr "predicable" "yes")]
2768 (define_insn "negdf2"
2769   [(set (match_operand:DF 0 "s_register_operand" "=f")
2770         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2771   "TARGET_ARM && TARGET_HARD_FLOAT"
2772   "mnf%?d\\t%0, %1"
2773   [(set_attr "type" "ffarith")
2774    (set_attr "predicable" "yes")]
2777 (define_insn "*negdf_esfdf"
2778   [(set (match_operand:DF 0 "s_register_operand" "=f")
2779         (neg:DF (float_extend:DF
2780                  (match_operand:SF 1 "s_register_operand" "f"))))]
2781   "TARGET_ARM && TARGET_HARD_FLOAT"
2782   "mnf%?d\\t%0, %1"
2783   [(set_attr "type" "ffarith")
2784    (set_attr "predicable" "yes")]
2787 (define_insn "negxf2"
2788   [(set (match_operand:XF 0 "s_register_operand" "=f")
2789         (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2790   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2791   "mnf%?e\\t%0, %1"
2792   [(set_attr "type" "ffarith")
2793    (set_attr "predicable" "yes")]
2796 ;; abssi2 doesn't really clobber the condition codes if a different register
2797 ;; is being set.  To keep things simple, assume during rtl manipulations that
2798 ;; it does, but tell the final scan operator the truth.  Similarly for
2799 ;; (neg (abs...))
2801 (define_insn "abssi2"
2802   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2803         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2804    (clobber (reg:CC CC_REGNUM))]
2805   "TARGET_ARM"
2806   "@
2807    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2808    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2809   [(set_attr "conds" "clob,*")
2810    (set_attr "shift" "1")
2811    ;; predicable can't be set based on the variant, so left as no
2812    (set_attr "length" "8")]
2815 (define_insn "*neg_abssi2"
2816   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2817         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2818    (clobber (reg:CC CC_REGNUM))]
2819   "TARGET_ARM"
2820   "@
2821    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2822    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2823   [(set_attr "conds" "clob,*")
2824    (set_attr "shift" "1")
2825    ;; predicable can't be set based on the variant, so left as no
2826    (set_attr "length" "8")]
2829 (define_insn "abssf2"
2830   [(set (match_operand:SF 0 "s_register_operand" "=f")
2831          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2832   "TARGET_ARM && TARGET_HARD_FLOAT"
2833   "abs%?s\\t%0, %1"
2834   [(set_attr "type" "ffarith")
2835    (set_attr "predicable" "yes")]
2838 (define_insn "absdf2"
2839   [(set (match_operand:DF 0 "s_register_operand" "=f")
2840         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2841   "TARGET_ARM && TARGET_HARD_FLOAT"
2842   "abs%?d\\t%0, %1"
2843   [(set_attr "type" "ffarith")
2844    (set_attr "predicable" "yes")]
2847 (define_insn "*absdf_esfdf"
2848   [(set (match_operand:DF 0 "s_register_operand" "=f")
2849         (abs:DF (float_extend:DF
2850                  (match_operand:SF 1 "s_register_operand" "f"))))]
2851   "TARGET_ARM && TARGET_HARD_FLOAT"
2852   "abs%?d\\t%0, %1"
2853   [(set_attr "type" "ffarith")
2854    (set_attr "predicable" "yes")]
2857 (define_insn "absxf2"
2858   [(set (match_operand:XF 0 "s_register_operand" "=f")
2859         (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2860   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2861   "abs%?e\\t%0, %1"
2862   [(set_attr "type" "ffarith")
2863    (set_attr "predicable" "yes")]
2866 (define_insn "sqrtsf2"
2867   [(set (match_operand:SF 0 "s_register_operand" "=f")
2868         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2869   "TARGET_ARM && TARGET_HARD_FLOAT"
2870   "sqt%?s\\t%0, %1"
2871   [(set_attr "type" "float_em")
2872    (set_attr "predicable" "yes")]
2875 (define_insn "sqrtdf2"
2876   [(set (match_operand:DF 0 "s_register_operand" "=f")
2877         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2878   "TARGET_ARM && TARGET_HARD_FLOAT"
2879   "sqt%?d\\t%0, %1"
2880   [(set_attr "type" "float_em")
2881    (set_attr "predicable" "yes")]
2884 (define_insn "*sqrtdf_esfdf"
2885   [(set (match_operand:DF 0 "s_register_operand" "=f")
2886         (sqrt:DF (float_extend:DF
2887                   (match_operand:SF 1 "s_register_operand" "f"))))]
2888   "TARGET_ARM && TARGET_HARD_FLOAT"
2889   "sqt%?d\\t%0, %1"
2890   [(set_attr "type" "float_em")
2891    (set_attr "predicable" "yes")]
2894 (define_insn "sqrtxf2"
2895   [(set (match_operand:XF 0 "s_register_operand" "=f")
2896         (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2897   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2898   "sqt%?e\\t%0, %1"
2899   [(set_attr "type" "float_em")
2900    (set_attr "predicable" "yes")]
2903 ;; SIN COS TAN and family are always emulated, so it's probably better
2904 ;; to always call a library function.
2905 ;(define_insn "sinsf2"
2906 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2907 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2908 ;                   UNSPEC_SIN))]
2909 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2910 ;  "sin%?s\\t%0, %1"
2911 ;[(set_attr "type" "float_em")])
2913 ;(define_insn "sindf2"
2914 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2915 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2916 ;                   UNSPEC_SIN))]
2917 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2918 ;  "sin%?d\\t%0, %1"
2919 ;[(set_attr "type" "float_em")])
2921 ;(define_insn "*sindf_esfdf"
2922 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2923 ;       (unspec:DF [(float_extend:DF
2924 ;                    (match_operand:SF 1 "s_register_operand" "f"))]
2925 ;                   UNSPEC_SIN))]
2926 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2927 ;  "sin%?d\\t%0, %1"
2928 ;[(set_attr "type" "float_em")])
2930 ;(define_insn "sinxf2"
2931 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2932 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2933 ;                  UNSPEC_SIN))]
2934 ;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2935 ;  "sin%?e\\t%0, %1"
2936 ;[(set_attr "type" "float_em")])
2938 ;(define_insn "cossf2"
2939 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2940 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2941 ;                  UNSPEC_COS))]
2942 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2943 ;  "cos%?s\\t%0, %1"
2944 ;[(set_attr "type" "float_em")])
2946 ;(define_insn "cosdf2"
2947 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2948 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2949 ;                  UNSPEC_COS))]
2950 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2951 ;  "cos%?d\\t%0, %1"
2952 ;[(set_attr "type" "float_em")])
2954 ;(define_insn "*cosdf_esfdf"
2955 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2956 ;       (unspec:DF [(float_extend:DF
2957 ;                    (match_operand:SF 1 "s_register_operand" "f"))]
2958 ;                  UNSPEC_COS))]
2959 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2960 ;  "cos%?d\\t%0, %1"
2961 ;[(set_attr "type" "float_em")])
2963 ;(define_insn "cosxf2"
2964 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2965 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2966 ;                  UNSEPC_COS))]
2967 ;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2968 ;  "cos%?e\\t%0, %1"
2969 ;[(set_attr "type" "float_em")])
2971 (define_insn_and_split "one_cmpldi2"
2972   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2973         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2974   "TARGET_ARM"
2975   "#"
2976   "TARGET_ARM && reload_completed"
2977   [(set (match_dup 0) (not:SI (match_dup 1)))
2978    (set (match_dup 2) (not:SI (match_dup 3)))]
2979   "
2980   {
2981     operands[2] = gen_highpart (SImode, operands[0]);
2982     operands[0] = gen_lowpart (SImode, operands[0]);
2983     operands[3] = gen_highpart (SImode, operands[1]);
2984     operands[1] = gen_lowpart (SImode, operands[1]);
2985   }"
2986   [(set_attr "length" "8")
2987    (set_attr "predicable" "yes")]
2990 (define_expand "one_cmplsi2"
2991   [(set (match_operand:SI         0 "s_register_operand" "")
2992         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2993   "TARGET_EITHER"
2994   ""
2997 (define_insn "*arm_one_cmplsi2"
2998   [(set (match_operand:SI         0 "s_register_operand" "=r")
2999         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3000   "TARGET_ARM"
3001   "mvn%?\\t%0, %1"
3002   [(set_attr "predicable" "yes")]
3005 (define_insn "*thumb_one_cmplsi2"
3006   [(set (match_operand:SI         0 "register_operand" "=l")
3007         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3008   "TARGET_THUMB"
3009   "mvn\\t%0, %1"
3010   [(set_attr "length" "2")]
3013 (define_insn "*notsi_compare0"
3014   [(set (reg:CC_NOOV CC_REGNUM)
3015         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3016                          (const_int 0)))
3017    (set (match_operand:SI 0 "s_register_operand" "=r")
3018         (not:SI (match_dup 1)))]
3019   "TARGET_ARM"
3020   "mvn%?s\\t%0, %1"
3021   [(set_attr "conds" "set")]
3024 (define_insn "*notsi_compare0_scratch"
3025   [(set (reg:CC_NOOV CC_REGNUM)
3026         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3027                          (const_int 0)))
3028    (clobber (match_scratch:SI 0 "=r"))]
3029   "TARGET_ARM"
3030   "mvn%?s\\t%0, %1"
3031   [(set_attr "conds" "set")]
3034 ;; Fixed <--> Floating conversion insns
3036 (define_insn "floatsisf2"
3037   [(set (match_operand:SF 0 "s_register_operand" "=f")
3038         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3039   "TARGET_ARM && TARGET_HARD_FLOAT"
3040   "flt%?s\\t%0, %1"
3041   [(set_attr "type" "r_2_f")
3042    (set_attr "predicable" "yes")]
3045 (define_insn "floatsidf2"
3046   [(set (match_operand:DF 0 "s_register_operand" "=f")
3047         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3048   "TARGET_ARM && TARGET_HARD_FLOAT"
3049   "flt%?d\\t%0, %1"
3050   [(set_attr "type" "r_2_f")
3051    (set_attr "predicable" "yes")]
3054 (define_insn "floatsixf2"
3055   [(set (match_operand:XF 0 "s_register_operand" "=f")
3056         (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3057   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3058   "flt%?e\\t%0, %1"
3059   [(set_attr "type" "r_2_f")
3060    (set_attr "predicable" "yes")]
3063 (define_insn "fix_truncsfsi2"
3064   [(set (match_operand:SI 0 "s_register_operand" "=r")
3065         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3066   "TARGET_ARM && TARGET_HARD_FLOAT"
3067   "fix%?z\\t%0, %1"
3068   [(set_attr "type" "f_2_r")
3069    (set_attr "predicable" "yes")]
3072 (define_insn "fix_truncdfsi2"
3073   [(set (match_operand:SI 0 "s_register_operand" "=r")
3074         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3075   "TARGET_ARM && TARGET_HARD_FLOAT"
3076   "fix%?z\\t%0, %1"
3077   [(set_attr "type" "f_2_r")
3078    (set_attr "predicable" "yes")]
3081 (define_insn "fix_truncxfsi2"
3082   [(set (match_operand:SI 0 "s_register_operand" "=r")
3083         (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3084   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3085   "fix%?z\\t%0, %1"
3086   [(set_attr "type" "f_2_r")
3087    (set_attr "predicable" "yes")]
3090 ;; Truncation insns
3092 (define_insn "truncdfsf2"
3093   [(set (match_operand:SF 0 "s_register_operand" "=f")
3094         (float_truncate:SF
3095          (match_operand:DF 1 "s_register_operand" "f")))]
3096   "TARGET_ARM && TARGET_HARD_FLOAT"
3097   "mvf%?s\\t%0, %1"
3098   [(set_attr "type" "ffarith")
3099    (set_attr "predicable" "yes")]
3102 (define_insn "truncxfsf2"
3103   [(set (match_operand:SF 0 "s_register_operand" "=f")
3104         (float_truncate:SF
3105          (match_operand:XF 1 "s_register_operand" "f")))]
3106   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3107   "mvf%?s\\t%0, %1"
3108   [(set_attr "type" "ffarith")
3109    (set_attr "predicable" "yes")]
3112 (define_insn "truncxfdf2"
3113   [(set (match_operand:DF 0 "s_register_operand" "=f")
3114         (float_truncate:DF
3115          (match_operand:XF 1 "s_register_operand" "f")))]
3116   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3117   "mvf%?d\\t%0, %1"
3118   [(set_attr "type" "ffarith")
3119    (set_attr "predicable" "yes")]
3122 ;; Zero and sign extension instructions.
3124 (define_insn "zero_extendsidi2"
3125   [(set (match_operand:DI 0 "s_register_operand" "=r")
3126         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3127   "TARGET_ARM"
3128   "*
3129     if (REGNO (operands[1])
3130         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3131       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3132     return \"mov%?\\t%R0, #0\";
3133   "
3134   [(set_attr "length" "8")
3135    (set_attr "predicable" "yes")]
3138 (define_insn "zero_extendqidi2"
3139   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3140         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3141   "TARGET_ARM"
3142   "@
3143    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3144    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3145   [(set_attr "length" "8")
3146    (set_attr "predicable" "yes")
3147    (set_attr "type" "*,load")
3148    (set_attr "pool_range" "*,4092")
3149    (set_attr "neg_pool_range" "*,4084")]
3152 (define_insn "extendsidi2"
3153   [(set (match_operand:DI 0 "s_register_operand" "=r")
3154         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3155   "TARGET_ARM"
3156   "*
3157     if (REGNO (operands[1])
3158         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3159       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3160     return \"mov%?\\t%R0, %Q0, asr #31\";
3161   "
3162   [(set_attr "length" "8")
3163    (set_attr "shift" "1")
3164    (set_attr "predicable" "yes")]
3167 (define_expand "zero_extendhisi2"
3168   [(set (match_dup 2)
3169         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3170                    (const_int 16)))
3171    (set (match_operand:SI 0 "s_register_operand" "")
3172         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3173   "TARGET_EITHER"
3174   "
3175   {
3176     if (TARGET_ARM)
3177       {
3178         if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3179           {
3180            /* Note: We do not have to worry about TARGET_MMU_TRAPS
3181               here because the insn below will generate an LDRH instruction
3182               rather than an LDR instruction, so we cannot get an unaligned
3183               word access.  */
3184             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3185                                     gen_rtx_ZERO_EXTEND (SImode,
3186                                                          operands[1])));
3187             DONE;
3188           }
3189         if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3190           {
3191             emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3192             DONE;
3193           }
3194         if (!s_register_operand (operands[1], HImode))
3195           operands[1] = copy_to_mode_reg (HImode, operands[1]);
3196         operands[1] = gen_lowpart (SImode, operands[1]);
3197         operands[2] = gen_reg_rtx (SImode);
3198       }
3199     else /* TARGET_THUMB */
3200       {
3201         if (GET_CODE (operands[1]) == MEM)
3202           {
3203             rtx tmp;
3205             tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3206             tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3207             emit_insn (tmp);
3208           }
3209         else
3210           {
3211             rtx ops[3];
3212             
3213             if (!s_register_operand (operands[1], HImode))
3214               operands[1] = copy_to_mode_reg (HImode, operands[1]);
3215             operands[1] = gen_lowpart (SImode, operands[1]);
3216             operands[2] = gen_reg_rtx (SImode);
3217             
3218             ops[0] = operands[2];
3219             ops[1] = operands[1];
3220             ops[2] = GEN_INT (16);
3221             
3222             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3223                                     gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3225             ops[0] = operands[0];
3226             ops[1] = operands[2];
3227             ops[2] = GEN_INT (16);
3229             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3230                                     gen_rtx_LSHIFTRT (SImode, ops[1],
3231                                                       ops[2])));
3232           }
3233         DONE; 
3234       }
3235   }"
3238 (define_insn "*thumb_zero_extendhisi2"
3239   [(set (match_operand:SI                 0 "register_operand" "=l")
3240         (zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3241   "TARGET_THUMB"
3242   "*
3243   rtx mem = XEXP (operands[1], 0);
3245   if (GET_CODE (mem) == CONST)
3246     mem = XEXP (mem, 0);
3247     
3248   if (GET_CODE (mem) == LABEL_REF)
3249     return \"ldr\\t%0, %1\";
3250     
3251   if (GET_CODE (mem) == PLUS)
3252     {
3253       rtx a = XEXP (mem, 0);
3254       rtx b = XEXP (mem, 1);
3256       /* This can happen due to bugs in reload.  */
3257       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3258         {
3259           rtx ops[2];
3260           ops[0] = operands[0];
3261           ops[1] = a;
3262       
3263           output_asm_insn (\"mov        %0, %1\", ops);
3265           XEXP (mem, 0) = operands[0];
3266        }
3268       else if (   GET_CODE (a) == LABEL_REF
3269                && GET_CODE (b) == CONST_INT)
3270         return \"ldr\\t%0, %1\";
3271     }
3272     
3273   return \"ldrh\\t%0, %1\";
3274   "
3275   [(set_attr "length" "4")
3276    (set_attr "type" "load")
3277    (set_attr "pool_range" "60")]
3280 (define_insn "*arm_zero_extendhisi2"
3281   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3282         (zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3283   "TARGET_ARM && arm_arch4"
3284   "ldr%?h\\t%0, %1"
3285   [(set_attr "type" "load")
3286    (set_attr "predicable" "yes")
3287    (set_attr "pool_range" "256")
3288    (set_attr "neg_pool_range" "244")]
3291 (define_split
3292   [(set (match_operand:SI 0 "s_register_operand" "")
3293         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3294    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3295   "TARGET_ARM && (!arm_arch4)"
3296   [(set (match_dup 2) (match_dup 1))
3297    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3298   "
3299   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3300     FAIL;
3301   "
3304 (define_split
3305   [(set (match_operand:SI 0 "s_register_operand" "")
3306         (match_operator:SI 3 "shiftable_operator"
3307          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3308           (match_operand:SI 4 "s_register_operand" "")]))
3309    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3310   "TARGET_ARM && (!arm_arch4)"
3311   [(set (match_dup 2) (match_dup 1))
3312    (set (match_dup 0)
3313         (match_op_dup 3
3314          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3315   "
3316   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3317     FAIL;
3318   "
3321 (define_expand "zero_extendqisi2"
3322   [(set (match_operand:SI 0 "s_register_operand" "")
3323         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3324   "TARGET_EITHER"
3325   "
3326   if (GET_CODE (operands[1]) != MEM)
3327     {
3328       if (TARGET_ARM)
3329         {
3330           emit_insn (gen_andsi3 (operands[0],
3331                                  gen_lowpart (SImode, operands[1]),
3332                                  GEN_INT (255)));
3333         }
3334       else /* TARGET_THUMB */
3335         {
3336           rtx temp = gen_reg_rtx (SImode);
3337           rtx ops[3];
3338           
3339           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3340           operands[1] = gen_lowpart (SImode, operands[1]);
3342           ops[0] = temp;
3343           ops[1] = operands[1];
3344           ops[2] = GEN_INT (24);
3346           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3347                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3348           
3349           ops[0] = operands[0];
3350           ops[1] = temp;
3351           ops[2] = GEN_INT (24);
3353           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3354                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3355         }
3356       DONE;
3357     }
3358   "
3361 (define_insn "*thumb_zero_extendqisi2"
3362   [(set (match_operand:SI                 0 "register_operand" "=l")
3363         (zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3364   "TARGET_THUMB"
3365   "ldrb\\t%0, %1"
3366   [(set_attr "length" "2")
3367    (set_attr "type" "load")
3368    (set_attr "pool_range" "32")]
3371 (define_insn "*arm_zero_extendqisi2"
3372   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3373         (zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3374   "TARGET_ARM"
3375   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3376   [(set_attr "type" "load")
3377    (set_attr "predicable" "yes")
3378    (set_attr "pool_range" "4096")
3379    (set_attr "neg_pool_range" "4084")]
3382 (define_split
3383   [(set (match_operand:SI 0 "s_register_operand" "")
3384         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3385    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3386   "TARGET_ARM && (GET_CODE (operands[1]) != MEM)"
3387   [(set (match_dup 2) (match_dup 1))
3388    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3389   ""
3392 (define_insn "*compareqi_eq0"
3393   [(set (reg:CC_Z CC_REGNUM)
3394         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3395                          (const_int 0)))]
3396   "TARGET_ARM"
3397   "tst\\t%0, #255"
3398   [(set_attr "conds" "set")]
3401 (define_expand "extendhisi2"
3402   [(set (match_dup 2)
3403         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3404                    (const_int 16)))
3405    (set (match_operand:SI 0 "s_register_operand" "")
3406         (ashiftrt:SI (match_dup 2)
3407                      (const_int 16)))]
3408   "TARGET_EITHER"
3409   "
3410   {
3411     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3412       {
3413        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3414           here because the insn below will generate an LDRH instruction
3415           rather than an LDR instruction, so we cannot get an unaligned
3416           word access.  */
3417         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3418                    gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3419         DONE;
3420       }
3422     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3423       {
3424         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3425         DONE;
3426       }
3427     if (!s_register_operand (operands[1], HImode))
3428       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3429     operands[1] = gen_lowpart (SImode, operands[1]);
3430     operands[2] = gen_reg_rtx (SImode);
3432     if (TARGET_THUMB)
3433       {
3434         rtx ops[3];
3435         
3436         ops[0] = operands[2];
3437         ops[1] = operands[1];
3438         ops[2] = GEN_INT (16);
3439         
3440         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3441                                 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3442             
3443         ops[0] = operands[0];
3444         ops[1] = operands[2];
3445         ops[2] = GEN_INT (16);
3446         
3447         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3448                                 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3449         
3450         DONE;
3451       }
3452   }"
3455 (define_insn "*thumb_extendhisi2_insn"
3456   [(set (match_operand:SI                 0 "register_operand" "=l")
3457         (sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3458    (clobber (match_scratch:SI             2                   "=&l"))]
3459   "TARGET_THUMB"
3460   "*
3461   {
3462     rtx ops[4];
3463     rtx mem = XEXP (operands[1], 0);
3465     /* This code used to try to use 'V', and fix the address only if it was
3466        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3467        range of QImode offsets, and offsettable_address_p does a QImode
3468        address check.  */
3469        
3470     if (GET_CODE (mem) == CONST)
3471       mem = XEXP (mem, 0);
3472     
3473     if (GET_CODE (mem) == LABEL_REF)
3474       return \"ldr\\t%0, %1\";
3475     
3476     if (GET_CODE (mem) == PLUS)
3477       {
3478         rtx a = XEXP (mem, 0);
3479         rtx b = XEXP (mem, 1);
3481         if (GET_CODE (a) == LABEL_REF
3482             && GET_CODE (b) == CONST_INT)
3483           return \"ldr\\t%0, %1\";
3485         if (GET_CODE (b) == REG)
3486           return \"ldrsh\\t%0, %1\";
3487           
3488         ops[1] = a;
3489         ops[2] = b;
3490       }
3491     else
3492       {
3493         ops[1] = mem;
3494         ops[2] = const0_rtx;
3495       }
3496       
3497     if (GET_CODE (ops[1]) != REG)
3498       {
3499         debug_rtx (ops[1]);
3500         abort ();
3501       }
3503     ops[0] = operands[0];
3504     ops[3] = operands[2];
3505     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3506     return \"\";
3507   }"
3508   [(set_attr "length" "4")
3509    (set_attr "type" "load")
3510    (set_attr "pool_range" "1020")]
3513 (define_expand "extendhisi2_mem"
3514   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3515    (set (match_dup 3)
3516         (zero_extend:SI (match_dup 7)))
3517    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3518    (set (match_operand:SI 0 "" "")
3519         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3520   "TARGET_ARM"
3521   "
3522   {
3523     rtx mem1, mem2;
3524     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3526     mem1 = gen_rtx_MEM (QImode, addr);
3527     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3528     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3529     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3530     operands[0] = gen_lowpart (SImode, operands[0]);
3531     operands[1] = mem1;
3532     operands[2] = gen_reg_rtx (SImode);
3533     operands[3] = gen_reg_rtx (SImode);
3534     operands[6] = gen_reg_rtx (SImode);
3535     operands[7] = mem2;
3537     if (BYTES_BIG_ENDIAN)
3538       {
3539         operands[4] = operands[2];
3540         operands[5] = operands[3];
3541       }
3542     else
3543       {
3544         operands[4] = operands[3];
3545         operands[5] = operands[2];
3546       }
3547   }"
3550 (define_insn "*arm_extendhisi_insn"
3551   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3552         (sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3553   "TARGET_ARM && arm_arch4"
3554   "ldr%?sh\\t%0, %1"
3555   [(set_attr "type" "load")
3556    (set_attr "predicable" "yes")
3557    (set_attr "pool_range" "256")
3558    (set_attr "neg_pool_range" "244")]
3561 (define_split
3562   [(set (match_operand:SI                 0 "s_register_operand" "")
3563         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3564    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3565   "TARGET_ARM && (!arm_arch4)"
3566   [(set (match_dup 2) (match_dup 1))
3567    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3568   "
3569   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3570     FAIL;
3571   "
3574 (define_split
3575   [(set (match_operand:SI                   0 "s_register_operand" "")
3576         (match_operator:SI                  3 "shiftable_operator"
3577          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3578           (match_operand:SI                 4 "s_register_operand" "")]))
3579    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3580   "TARGET_ARM && (!arm_arch4)"
3581   [(set (match_dup 2) (match_dup 1))
3582    (set (match_dup 0)
3583         (match_op_dup 3
3584          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3585   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3586      FAIL;
3587   "
3590 (define_expand "extendqihi2"
3591   [(set (match_dup 2)
3592         (ashift:SI (match_operand:QI 1 "general_operand" "")
3593                    (const_int 24)))
3594    (set (match_operand:HI 0 "s_register_operand" "")
3595         (ashiftrt:SI (match_dup 2)
3596                      (const_int 24)))]
3597   "TARGET_ARM"
3598   "
3599   {
3600     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3601       {
3602         emit_insn (gen_rtx_SET (VOIDmode,
3603                                 operands[0],
3604                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3605         DONE;
3606       }
3607     if (!s_register_operand (operands[1], QImode))
3608       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3609     operands[0] = gen_lowpart (SImode, operands[0]);
3610     operands[1] = gen_lowpart (SImode, operands[1]);
3611     operands[2] = gen_reg_rtx (SImode);
3612   }"
3615 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3616 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3617 (define_insn "*extendqihi_insn"
3618   [(set (match_operand:HI                 0 "s_register_operand" "=r")
3619         (sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3620   "TARGET_ARM && arm_arch4"
3621   "*
3622   /* If the address is invalid, this will split the instruction into two. */
3623   if (bad_signed_byte_operand (operands[1], VOIDmode))
3624     return \"#\";
3625   return \"ldr%?sb\\t%0, %1\";
3626   "
3627   [(set_attr "type" "load")
3628    (set_attr "predicable" "yes")
3629    (set_attr "length" "8")
3630    (set_attr "pool_range" "256")
3631    (set_attr "neg_pool_range" "244")]
3634 (define_split
3635   [(set (match_operand:HI 0 "s_register_operand" "")
3636         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3637   "TARGET_ARM && arm_arch4 && reload_completed"
3638   [(set (match_dup 3) (match_dup 1))
3639    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3640   "
3641   {
3642     HOST_WIDE_INT offset;
3644     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3645     operands[2] = gen_rtx_MEM (QImode, operands[3]);
3646     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3647     operands[1] = XEXP (operands[1], 0);
3648     if (GET_CODE (operands[1]) == PLUS
3649         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3650         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3651              || const_ok_for_arm (-offset)))
3652       {
3653         HOST_WIDE_INT low = (offset > 0
3654                              ? (offset & 0xff) : -((-offset) & 0xff));
3655         XEXP (operands[2], 0) = plus_constant (operands[3], low);
3656         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3657       }
3658     /* Ensure the sum is in correct canonical form */
3659     else if (GET_CODE (operands[1]) == PLUS
3660              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3661              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3662       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3663                                            XEXP (operands[1], 1),
3664                                            XEXP (operands[1], 0));
3665   }"
3668 (define_expand "extendqisi2"
3669   [(set (match_dup 2)
3670         (ashift:SI (match_operand:QI 1 "general_operand" "")
3671                    (const_int 24)))
3672    (set (match_operand:SI 0 "s_register_operand" "")
3673         (ashiftrt:SI (match_dup 2)
3674                      (const_int 24)))]
3675   "TARGET_EITHER"
3676   "
3677   {
3678     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3679       {
3680         emit_insn (gen_rtx_SET (VOIDmode,
3681                                 operands[0],
3682                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3683         DONE;
3684       }
3685     if (!s_register_operand (operands[1], QImode))
3686       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3687     operands[1] = gen_lowpart (SImode, operands[1]);
3688     operands[2] = gen_reg_rtx (SImode);
3689     
3690     if (TARGET_THUMB)
3691       {
3692         rtx ops[3];
3693         
3694         ops[0] = operands[2];
3695         ops[1] = operands[1];
3696         ops[2] = GEN_INT (24);
3697         
3698         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3699                    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3701         ops[0] = operands[0];
3702         ops[1] = operands[2];
3703         ops[2] = GEN_INT (24);
3704         
3705         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3706                    gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3707         
3708         DONE;
3709       }
3710   }"
3713 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3714 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3715 (define_insn "*arm_extendqisi_insn"
3716   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3717         (sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3718   "TARGET_ARM && arm_arch4"
3719   "*
3720   /* If the address is invalid, this will split the instruction into two. */
3721   if (bad_signed_byte_operand (operands[1], VOIDmode))
3722     return \"#\";
3723   return \"ldr%?sb\\t%0, %1\";
3724   "
3725   [(set_attr "type" "load")
3726    (set_attr "predicable" "yes")
3727    (set_attr "length" "8")
3728    (set_attr "pool_range" "256")
3729    (set_attr "neg_pool_range" "244")]
3732 (define_split
3733   [(set (match_operand:SI 0 "s_register_operand" "")
3734         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3735   "TARGET_ARM && arm_arch4 && reload_completed"
3736   [(set (match_dup 0) (match_dup 1))
3737    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3738   "
3739   {
3740     HOST_WIDE_INT offset;
3742     operands[2] = gen_rtx_MEM (QImode, operands[0]);
3743     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3744     operands[1] = XEXP (operands[1], 0);
3745     if (GET_CODE (operands[1]) == PLUS
3746         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3747         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3748              || const_ok_for_arm (-offset)))
3749       {
3750         HOST_WIDE_INT low = (offset > 0
3751                              ? (offset & 0xff) : -((-offset) & 0xff));
3752         XEXP (operands[2], 0) = plus_constant (operands[0], low);
3753         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3754       }
3755     /* Ensure the sum is in correct canonical form */
3756     else if (GET_CODE (operands[1]) == PLUS
3757              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3758              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3759       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3760                                            XEXP (operands[1], 1),
3761                                            XEXP (operands[1], 0));
3762   }"
3765 (define_insn "*thumb_extendqisi2_insn"
3766   [(set (match_operand:SI                 0 "register_operand" "=l,l")
3767         (sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3768   "TARGET_THUMB"
3769   "*
3770   {
3771     rtx ops[3];
3772     rtx mem = XEXP (operands[1], 0);
3773     
3774     if (GET_CODE (mem) == CONST)
3775       mem = XEXP (mem, 0);
3776     
3777     if (GET_CODE (mem) == LABEL_REF)
3778       return \"ldr\\t%0, %1\";
3780     if (GET_CODE (mem) == PLUS
3781         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3782       return \"ldr\\t%0, %1\";
3783       
3784     if (which_alternative == 0)
3785       return \"ldrsb\\t%0, %1\";
3786       
3787     ops[0] = operands[0];
3788     
3789     if (GET_CODE (mem) == PLUS)
3790       {
3791         rtx a = XEXP (mem, 0);
3792         rtx b = XEXP (mem, 1);
3793         
3794         ops[1] = a;
3795         ops[2] = b;
3797         if (GET_CODE (a) == REG)
3798           {
3799             if (GET_CODE (b) == REG)
3800               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3801             else if (REGNO (a) == REGNO (ops[0]))
3802               {
3803                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3804                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3805                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3806               }
3807             else
3808               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3809           }
3810         else if (GET_CODE (b) != REG)
3811           abort ();
3812         else
3813           {
3814             if (REGNO (b) == REGNO (ops[0]))
3815               {
3816                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3817                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3818                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3819               }
3820             else
3821               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3822           }
3823       }
3824     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3825       {
3826         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3827         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3828         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3829       }
3830     else
3831       {
3832         ops[1] = mem;
3833         ops[2] = const0_rtx;
3834         
3835         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3836       }
3837     return \"\";
3838   }"
3839   [(set_attr "length" "2,6")
3840    (set_attr "type" "load,load")
3841    (set_attr "pool_range" "32,32")]
3844 (define_insn "extendsfdf2"
3845   [(set (match_operand:DF                  0 "s_register_operand" "=f")
3846         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "f")))]
3847   "TARGET_ARM && TARGET_HARD_FLOAT"
3848   "mvf%?d\\t%0, %1"
3849   [(set_attr "type" "ffarith")
3850    (set_attr "predicable" "yes")]
3853 (define_insn "extendsfxf2"
3854   [(set (match_operand:XF 0 "s_register_operand" "=f")
3855         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3856   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3857   "mvf%?e\\t%0, %1"
3858   [(set_attr "type" "ffarith")
3859    (set_attr "predicable" "yes")]
3862 (define_insn "extenddfxf2"
3863   [(set (match_operand:XF 0 "s_register_operand" "=f")
3864         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3865   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3866   "mvf%?e\\t%0, %1"
3867   [(set_attr "type" "ffarith")
3868    (set_attr "predicable" "yes")]
3872 ;; Move insns (including loads and stores)
3874 ;; XXX Just some ideas about movti.
3875 ;; I don't think these are a good idea on the arm, there just aren't enough
3876 ;; registers
3877 ;;(define_expand "loadti"
3878 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3879 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3880 ;;  "" "")
3882 ;;(define_expand "storeti"
3883 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3884 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3885 ;;  "" "")
3887 ;;(define_expand "movti"
3888 ;;  [(set (match_operand:TI 0 "general_operand" "")
3889 ;;      (match_operand:TI 1 "general_operand" ""))]
3890 ;;  ""
3891 ;;  "
3893 ;;  rtx insn;
3895 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3896 ;;    operands[1] = copy_to_reg (operands[1]);
3897 ;;  if (GET_CODE (operands[0]) == MEM)
3898 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3899 ;;  else if (GET_CODE (operands[1]) == MEM)
3900 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3901 ;;  else
3902 ;;    FAIL;
3904 ;;  emit_insn (insn);
3905 ;;  DONE;
3906 ;;}")
3908 ;; Recognise garbage generated above.
3910 ;;(define_insn ""
3911 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3912 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3913 ;;  ""
3914 ;;  "*
3915 ;;  {
3916 ;;    register mem = (which_alternative < 3);
3917 ;;    register const char *template;
3919 ;;    operands[mem] = XEXP (operands[mem], 0);
3920 ;;    switch (which_alternative)
3921 ;;      {
3922 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3923 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3924 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3925 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3926 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3927 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3928 ;;      }
3929 ;;    output_asm_insn (template, operands);
3930 ;;    return \"\";
3931 ;;  }")
3933 (define_expand "movdi"
3934   [(set (match_operand:DI 0 "general_operand" "")
3935         (match_operand:DI 1 "general_operand" ""))]
3936   "TARGET_EITHER"
3937   "
3938   if (TARGET_THUMB)
3939     {
3940       if (!no_new_pseudos)
3941         {
3942           if (GET_CODE (operands[0]) != REG)
3943             operands[1] = force_reg (DImode, operands[1]);
3944         }
3945     }
3946   "
3949 (define_insn "*arm_movdi"
3950   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3951         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3952   "TARGET_ARM
3953   "
3954   "*
3955   return (output_move_double (operands));
3956   "
3957   [(set_attr "length" "8")
3958    (set_attr "type" "*,load,store2")
3959    (set_attr "pool_range" "*,1020,*")
3960    (set_attr "neg_pool_range" "*,1012,*")]
3963 ;;; ??? This should have alternatives for constants.
3964 ;;; ??? This was originally identical to the movdf_insn pattern.
3965 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3966 ;;; thumb_reorg with a memory reference.
3967 (define_insn "*thumb_movdi_insn"
3968   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3969         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3970   "TARGET_THUMB
3971    && (   register_operand (operands[0], DImode)
3972        || register_operand (operands[1], DImode))"
3973   "*
3974   {
3975   switch (which_alternative)
3976     {
3977     default:
3978     case 0:
3979       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3980         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3981       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3982     case 1:
3983       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3984     case 2:
3985       operands[1] = GEN_INT (- INTVAL (operands[1]));
3986       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3987     case 3:
3988       return \"ldmia\\t%1, {%0, %H0}\";
3989     case 4:
3990       return \"stmia\\t%0, {%1, %H1}\";
3991     case 5:
3992       return thumb_load_double_from_address (operands);
3993     case 6:
3994       operands[2] = gen_rtx (MEM, SImode,
3995                              plus_constant (XEXP (operands[0], 0), 4));
3996       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3997       return \"\";
3998     case 7:
3999       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4000         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4001       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4002     }
4003   }"
4004   [(set_attr "length" "4,4,6,2,2,6,4,4")
4005    (set_attr "type" "*,*,*,load,store2,load,store2,*")
4006    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4009 (define_expand "movsi"
4010   [(set (match_operand:SI 0 "general_operand" "")
4011         (match_operand:SI 1 "general_operand" ""))]
4012   "TARGET_EITHER"
4013   "
4014   if (TARGET_ARM)
4015     {
4016       /* Everything except mem = const or mem = mem can be done easily */
4017       if (GET_CODE (operands[0]) == MEM)
4018         operands[1] = force_reg (SImode, operands[1]);
4019       if (GET_CODE (operands[1]) == CONST_INT
4020           && !(const_ok_for_arm (INTVAL (operands[1]))
4021                || const_ok_for_arm (~INTVAL (operands[1]))))
4022         {
4023            arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4024                               NULL_RTX,
4025                               (no_new_pseudos ? 0
4026                                : preserve_subexpressions_p ()));
4027           DONE;
4028         }
4029     }
4030   else /* TARGET_THUMB.... */
4031     {
4032       if (!no_new_pseudos)
4033         {
4034           if (GET_CODE (operands[0]) != REG)
4035             operands[1] = force_reg (SImode, operands[1]);
4036         }
4037     }
4038     
4039   if (flag_pic
4040       && (CONSTANT_P (operands[1])
4041          || symbol_mentioned_p (operands[1])
4042          || label_mentioned_p (operands[1])))
4043     operands[1] = legitimize_pic_address (operands[1], SImode,
4044                                           (no_new_pseudos ? operands[0] : 0));
4045   "
4048 (define_insn "*arm_movsi_insn"
4049   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4050         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4051   "TARGET_ARM
4052    && (   register_operand (operands[0], SImode)
4053        || register_operand (operands[1], SImode))"
4054   "@
4055    mov%?\\t%0, %1
4056    mvn%?\\t%0, #%B1
4057    ldr%?\\t%0, %1
4058    str%?\\t%1, %0"
4059   [(set_attr "type" "*,*,load,store1")
4060    (set_attr "predicable" "yes")
4061    (set_attr "pool_range" "*,*,4096,*")
4062    (set_attr "neg_pool_range" "*,*,4084,*")]
4065 (define_split
4066   [(set (match_operand:SI 0 "s_register_operand" "")
4067         (match_operand:SI 1 "const_int_operand" ""))]
4068   "TARGET_ARM
4069   && (!(const_ok_for_arm (INTVAL (operands[1]))
4070         || const_ok_for_arm (~INTVAL (operands[1]))))"
4071   [(clobber (const_int 0))]
4072   "
4073   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4074                       NULL_RTX, 0);
4075   DONE;
4076   "
4079 (define_insn "*thumb_movsi_insn"
4080   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4081         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4082   "TARGET_THUMB
4083    && (   register_operand (operands[0], SImode) 
4084        || register_operand (operands[1], SImode))"
4085   "@
4086    mov  %0, %1
4087    mov  %0, %1
4088    #
4089    #
4090    ldmia\\t%1, {%0}
4091    stmia\\t%0, {%1}
4092    ldr\\t%0, %1
4093    str\\t%1, %0
4094    mov\\t%0, %1"
4095   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4096    (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4097    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4100 (define_split 
4101   [(set (match_operand:SI 0 "register_operand" "")
4102         (match_operand:SI 1 "const_int_operand" ""))]
4103   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4104   [(set (match_dup 0) (match_dup 1))
4105    (set (match_dup 0) (neg:SI (match_dup 0)))]
4106   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4109 (define_split 
4110   [(set (match_operand:SI 0 "register_operand" "")
4111         (match_operand:SI 1 "const_int_operand" ""))]
4112   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4113   [(set (match_dup 0) (match_dup 1))
4114    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4115   "
4116   {
4117     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4118     unsigned HOST_WIDE_INT mask = 0xff;
4119     int i;
4120     
4121     for (i = 0; i < 25; i++)
4122       if ((val & (mask << i)) == val)
4123         break;
4125     if (i == 0)
4126       FAIL;
4128     operands[1] = GEN_INT (val >> i);
4129     operands[2] = GEN_INT (i);
4130   }"
4133 (define_expand "movaddr"
4134   [(set (match_operand:SI 0 "s_register_operand" "")
4135         (match_operand:DI 1 "address_operand" ""))]
4136   "TARGET_ARM"
4137   ""
4140 (define_insn "*movaddr_insn"
4141   [(set (match_operand:SI 0 "s_register_operand" "=r")
4142         (match_operand:DI 1 "address_operand" "p"))]
4143   "TARGET_ARM
4144    && reload_completed
4145    && (GET_CODE (operands[1]) == LABEL_REF
4146        || (GET_CODE (operands[1]) == CONST
4147            && GET_CODE (XEXP (operands[1], 0)) == PLUS
4148            && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
4149            && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
4150   "adr%?\\t%0, %a1"
4151   [(set_attr "predicable" "yes")]
4154 ;; When generating pic, we need to load the symbol offset into a register.
4155 ;; So that the optimizer does not confuse this with a normal symbol load
4156 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4157 ;; since that is the only type of relocation we can use.
4159 ;; The rather odd constraints on the following are to force reload to leave
4160 ;; the insn alone, and to force the minipool generation pass to then move
4161 ;; the GOT symbol to memory.
4163 (define_insn "pic_load_addr_arm"
4164   [(set (match_operand:SI 0 "s_register_operand" "=r")
4165         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4166   "TARGET_ARM && flag_pic"
4167   "ldr%?\\t%0, %1"
4168   [(set_attr "type" "load")
4169    (set (attr "pool_range")     (const_int 4096))
4170    (set (attr "neg_pool_range") (const_int 4084))]
4173 (define_insn "pic_load_addr_thumb"
4174   [(set (match_operand:SI 0 "s_register_operand" "=l")
4175         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4176   "TARGET_THUMB && flag_pic"
4177   "ldr\\t%0, %1"
4178   [(set_attr "type" "load")
4179    (set (attr "pool_range") (const_int 1024))]
4182 ;; This variant is used for AOF assembly, since it needs to mention the
4183 ;; pic register in the rtl.
4184 (define_expand "pic_load_addr_based"
4185   [(set (match_operand:SI 0 "s_register_operand" "=r")
4186         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4187   "TARGET_ARM && flag_pic"
4188   "operands[2] = pic_offset_table_rtx;"
4191 (define_insn "*pic_load_addr_based_insn"
4192   [(set (match_operand:SI 0 "s_register_operand" "=r")
4193         (unspec:SI [(match_operand 1 "" "")
4194                     (match_operand 2 "s_register_operand" "r")]
4195                    UNSPEC_PIC_SYM))]
4196   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4197   "*
4198 #ifdef AOF_ASSEMBLER
4199   operands[1] = aof_pic_entry (operands[1]);
4200 #endif
4201   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4202   return \"\";
4203   "
4204   [(set_attr "type" "load")
4205    (set (attr "pool_range")
4206         (if_then_else (eq_attr "is_thumb" "yes")
4207                       (const_int 1024)
4208                       (const_int 4096)))
4209    (set (attr "neg_pool_range")
4210         (if_then_else (eq_attr "is_thumb" "yes")
4211                       (const_int 0)
4212                       (const_int 4084)))]
4215 (define_insn "pic_add_dot_plus_four"
4216   [(set (match_operand:SI 0 "register_operand" "+r")
4217         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4218    (use (label_ref (match_operand 1 "" "")))]
4219   "TARGET_THUMB && flag_pic"
4220   "*
4221   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4222                              CODE_LABEL_NUMBER (operands[1]));
4223   return \"add\\t%0, %|pc\";
4224   "
4225   [(set_attr "length" "2")]
4228 (define_insn "pic_add_dot_plus_eight"
4229   [(set (match_operand:SI 0 "register_operand" "+r")
4230         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4231    (use (label_ref (match_operand 1 "" "")))]
4232   "TARGET_ARM && flag_pic"
4233   "*
4234     ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4235                                CODE_LABEL_NUMBER (operands[1]));
4236     return \"add%?\\t%0, %|pc, %0\";
4237   "
4238   [(set_attr "predicable" "yes")]
4241 ;; If copying one reg to another we can set the condition codes according to
4242 ;; its value.  Such a move is common after a return from subroutine and the
4243 ;; result is being tested against zero.
4245 (define_insn "*movsi_compare0"
4246   [(set (reg:CC CC_REGNUM)
4247         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4248                     (const_int 0)))
4249    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4250         (match_dup 1))]
4251   "TARGET_ARM"
4252   "@
4253    cmp%?\\t%0, #0
4254    sub%?s\\t%0, %1, #0"
4255   [(set_attr "conds" "set")]
4258 ;; Subroutine to store a half word from a register into memory.
4259 ;; Operand 0 is the source register (HImode)
4260 ;; Operand 1 is the destination address in a register (SImode)
4262 ;; In both this routine and the next, we must be careful not to spill
4263 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4264 ;; can generate unrecognizable rtl.
4266 (define_expand "storehi"
4267   [;; store the low byte
4268    (set (match_operand 1 "" "") (match_dup 3))
4269    ;; extract the high byte
4270    (set (match_dup 2)
4271         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4272    ;; store the high byte
4273    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
4274   "TARGET_ARM"
4275   "
4276   {
4277     rtx addr = XEXP (operands[1], 0);
4278     enum rtx_code code = GET_CODE (addr);
4280     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4281         || code == MINUS)
4282       addr = force_reg (SImode, addr);
4284     operands[4] = change_address (operands[1], QImode,
4285                                   plus_constant (addr, 1));
4286     operands[1] = change_address (operands[1], QImode, NULL_RTX);
4287     operands[3] = gen_lowpart (QImode, operands[0]);
4288     operands[0] = gen_lowpart (SImode, operands[0]);
4289     operands[2] = gen_reg_rtx (SImode); 
4290   }"
4293 (define_expand "storehi_bigend"
4294   [(set (match_dup 4) (match_dup 3))
4295    (set (match_dup 2)
4296         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4297    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
4298   "TARGET_ARM"
4299   "
4300   {
4301     rtx addr = XEXP (operands[1], 0);
4302     enum rtx_code code = GET_CODE (addr);
4304     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4305         || code == MINUS)
4306       addr = force_reg (SImode, addr);
4308     operands[4] = change_address (operands[1], QImode,
4309                                   plus_constant (addr, 1));
4310     operands[1] = change_address (operands[1], QImode, NULL_RTX);
4311     operands[3] = gen_lowpart (QImode, operands[0]);
4312     operands[0] = gen_lowpart (SImode, operands[0]);
4313     operands[2] = gen_reg_rtx (SImode);
4314   }"
4317 ;; Subroutine to store a half word integer constant into memory.
4318 (define_expand "storeinthi"
4319   [(set (match_operand 0 "" "")
4320         (subreg:QI (match_operand 1 "" "") 0))
4321    (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
4322   "TARGET_ARM"
4323   "
4324   {
4325     HOST_WIDE_INT value = INTVAL (operands[1]);
4326     rtx addr = XEXP (operands[0], 0);
4327     enum rtx_code code = GET_CODE (addr);
4329     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4330         || code == MINUS)
4331       addr = force_reg (SImode, addr);
4333     operands[1] = gen_reg_rtx (SImode);
4334     if (BYTES_BIG_ENDIAN)
4335       {
4336         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4337         if ((value & 255) == ((value >> 8) & 255))
4338           operands[2] = operands[1];
4339         else
4340           {
4341             operands[2] = gen_reg_rtx (SImode);
4342             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4343           }
4344       }
4345     else
4346       {
4347         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4348         if ((value & 255) == ((value >> 8) & 255))
4349           operands[2] = operands[1];
4350         else
4351           {
4352             operands[2] = gen_reg_rtx (SImode);
4353             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4354           }
4355       }
4357     operands[3] = change_address (operands[0], QImode,
4358                                   plus_constant (addr, 1));
4359     operands[0] = change_address (operands[0], QImode, NULL_RTX);
4360   }"
4363 (define_expand "storehi_single_op"
4364   [(set (match_operand:HI 0 "memory_operand" "")
4365         (match_operand:HI 1 "general_operand" ""))]
4366   "TARGET_ARM && arm_arch4"
4367   "
4368   if (!s_register_operand (operands[1], HImode))
4369     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4370   "
4373 (define_expand "movhi"
4374   [(set (match_operand:HI 0 "general_operand" "")
4375         (match_operand:HI 1 "general_operand" ""))]
4376   "TARGET_EITHER"
4377   "
4378   if (TARGET_ARM)
4379     {
4380       if (!no_new_pseudos)
4381         {
4382           if (GET_CODE (operands[0]) == MEM)
4383             {
4384               if (arm_arch4)
4385                 {
4386                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4387                   DONE;
4388                 }
4389               if (GET_CODE (operands[1]) == CONST_INT)
4390                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4391               else
4392                 {
4393                   if (GET_CODE (operands[1]) == MEM)
4394                     operands[1] = force_reg (HImode, operands[1]);
4395                   if (BYTES_BIG_ENDIAN)
4396                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4397                   else
4398                    emit_insn (gen_storehi (operands[1], operands[0]));
4399                 }
4400               DONE;
4401             }
4402           /* Sign extend a constant, and keep it in an SImode reg.  */
4403           else if (GET_CODE (operands[1]) == CONST_INT)
4404             {
4405               rtx reg = gen_reg_rtx (SImode);
4406               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4408               /* If the constant is already valid, leave it alone.  */
4409               if (!const_ok_for_arm (val))
4410                 {
4411                   /* If setting all the top bits will make the constant 
4412                      loadable in a single instruction, then set them.  
4413                      Otherwise, sign extend the number.  */
4415                   if (const_ok_for_arm (~(val | ~0xffff)))
4416                     val |= ~0xffff;
4417                   else if (val & 0x8000)
4418                     val |= ~0xffff;
4419                 }
4421               emit_insn (gen_movsi (reg, GEN_INT (val)));
4422               operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
4423             }
4424           else if (!arm_arch4)
4425             {
4426              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4427                 for v4 and up architectures because LDRH instructions will
4428                 be used to access the HI values, and these cannot generate
4429                 unaligned word access faults in the MMU.  */
4430               if (GET_CODE (operands[1]) == MEM)
4431                 {
4432                   if (TARGET_MMU_TRAPS)
4433                     {
4434                       rtx base;
4435                       rtx offset = const0_rtx;
4436                       rtx reg = gen_reg_rtx (SImode);
4438                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4439                            || (GET_CODE (base) == PLUS
4440                                && (GET_CODE (offset = XEXP (base, 1))
4441                                    == CONST_INT)
4442                                && ((INTVAL(offset) & 1) != 1)
4443                                && GET_CODE (base = XEXP (base, 0)) == REG))
4444                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4445                         {
4446                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4447                           rtx new;
4449                           new = gen_rtx_MEM (SImode,
4450                                              plus_constant (base, new_offset));
4451                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4452                           emit_insn (gen_movsi (reg, new));
4453                           if (((INTVAL (offset) & 2) != 0)
4454                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4455                             {
4456                               rtx reg2 = gen_reg_rtx (SImode);
4458                               emit_insn (gen_lshrsi3 (reg2, reg,
4459                                          GEN_INT (16)));
4460                               reg = reg2;
4461                             }
4462                         }
4463                       else
4464                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4466                       operands[1] = gen_lowpart (HImode, reg);
4467                     }
4468                   else if (BYTES_BIG_ENDIAN)
4469                     {
4470                       rtx base;
4471                       rtx offset = const0_rtx;
4473                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4474                            || (GET_CODE (base) == PLUS
4475                               && (GET_CODE (offset = XEXP (base, 1))
4476                                   == CONST_INT)
4477                               && GET_CODE (base = XEXP (base, 0)) == REG))
4478                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4479                         {
4480                           rtx reg = gen_reg_rtx (SImode);
4481                           rtx new;
4483                           if ((INTVAL (offset) & 2) == 2)
4484                             {
4485                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4486                               new = gen_rtx_MEM (SImode,
4487                                                  plus_constant (base,
4488                                                                 new_offset));
4489                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4490                               emit_insn (gen_movsi (reg, new));
4491                             }
4492                           else
4493                             {
4494                               new = gen_rtx_MEM (SImode,
4495                                                  XEXP (operands[1], 0));
4496                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4497                               emit_insn (gen_rotated_loadsi (reg, new));
4498                             }
4500                           operands[1] = gen_lowpart (HImode, reg);
4501                         }
4502                       else
4503                         {
4504                           emit_insn (gen_movhi_bigend (operands[0],
4505                                                        operands[1]));
4506                           DONE;
4507                         }
4508                     }
4509                }
4510            }
4511         }
4512       /* Handle loading a large integer during reload */
4513       else if (GET_CODE (operands[1]) == CONST_INT
4514                && !const_ok_for_arm (INTVAL (operands[1]))
4515                && !const_ok_for_arm (~INTVAL (operands[1])))
4516         {
4517           /* Writing a constant to memory needs a scratch, which should
4518              be handled with SECONDARY_RELOADs.  */
4519           if (GET_CODE (operands[0]) != REG)
4520             abort ();
4522           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4523           emit_insn (gen_movsi (operands[0], operands[1]));
4524           DONE;
4525        }
4526     }
4527   else /* TARGET_THUMB */
4528     {
4529       if (!no_new_pseudos)
4530         {
4531           if (GET_CODE (operands[0]) != REG)
4532             operands[1] = force_reg (HImode, operands[1]);
4534           /* ??? We shouldn't really get invalid addresses here, but this can
4535              happen if we are passed a SP (never OK for HImode/QImode) or 
4536              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4537              HImode/QImode) relative address.  */
4538           /* ??? This should perhaps be fixed elsewhere, for instance, in
4539              fixup_stack_1, by checking for other kinds of invalid addresses,
4540              e.g. a bare reference to a virtual register.  This may confuse the
4541              alpha though, which must handle this case differently.  */
4542           if (GET_CODE (operands[0]) == MEM
4543               && !memory_address_p (GET_MODE (operands[0]),
4544                                     XEXP (operands[0], 0)))
4545             {
4546               rtx temp = copy_to_reg (XEXP (operands[0], 0));
4547               operands[0] = change_address (operands[0], VOIDmode, temp);
4548             }
4549    
4550           if (GET_CODE (operands[1]) == MEM
4551               && !memory_address_p (GET_MODE (operands[1]),
4552                                     XEXP (operands[1], 0)))
4553             {
4554               rtx temp = copy_to_reg (XEXP (operands[1], 0));
4555               operands[1] = change_address (operands[1], VOIDmode, temp);
4556             }
4557         }
4558       /* Handle loading a large integer during reload */
4559       else if (GET_CODE (operands[1]) == CONST_INT
4560                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4561         {
4562           /* Writing a constant to memory needs a scratch, which should
4563              be handled with SECONDARY_RELOADs.  */
4564           if (GET_CODE (operands[0]) != REG)
4565             abort ();
4567           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4568           emit_insn (gen_movsi (operands[0], operands[1]));
4569           DONE;
4570         }
4571     }
4572   "
4575 (define_insn "*thumb_movhi_insn"
4576   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4577         (match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4578   "TARGET_THUMB
4579    && (   register_operand (operands[0], HImode)
4580        || register_operand (operands[1], HImode))"
4581   "*
4582   switch (which_alternative)
4583     {
4584     case 0: return \"add        %0, %1, #0\";
4585     case 2: return \"strh       %1, %0\";
4586     case 3: return \"mov        %0, %1\";
4587     case 4: return \"mov        %0, %1\";
4588     case 5: return \"mov        %0, %1\";
4589     default: abort ();
4590     case 1:
4591       /* The stack pointer can end up being taken as an index register.
4592           Catch this case here and deal with it.  */
4593       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4594           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4595           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4596         {
4597           rtx ops[2];
4598           ops[0] = operands[0];
4599           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4600       
4601           output_asm_insn (\"mov        %0, %1\", ops);
4603           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4604     
4605         }
4606       return \"ldrh     %0, %1\";
4607     }"
4608   [(set_attr "length" "2,4,2,2,2,2")
4609    (set_attr "type" "*,load,store1,*,*,*")
4610    (set_attr "pool_range" "*,64,*,*,*,*")]
4614 (define_insn "rotated_loadsi"
4615   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4616         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4617                    (const_int 16)))]
4618   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4619   "*
4620   {
4621     rtx ops[2];
4623     ops[0] = operands[0];
4624     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4625     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4626     return \"\";
4627   }"
4628   [(set_attr "type" "load")
4629    (set_attr "predicable" "yes")]
4632 (define_expand "movhi_bytes"
4633   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4634    (set (match_dup 3)
4635         (zero_extend:SI (match_dup 6)))
4636    (set (match_operand:SI 0 "" "")
4637          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4638   "TARGET_ARM"
4639   "
4640   {
4641     rtx mem1, mem2;
4642     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4644     mem1 = gen_rtx_MEM (QImode, addr);
4645     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4646     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4647     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4648     operands[0] = gen_lowpart (SImode, operands[0]);
4649     operands[1] = mem1;
4650     operands[2] = gen_reg_rtx (SImode);
4651     operands[3] = gen_reg_rtx (SImode);
4652     operands[6] = mem2;
4654     if (BYTES_BIG_ENDIAN)
4655       {
4656         operands[4] = operands[2];
4657         operands[5] = operands[3];
4658       }
4659     else
4660       {
4661         operands[4] = operands[3];
4662         operands[5] = operands[2];
4663       }
4664   }"
4667 (define_expand "movhi_bigend"
4668   [(set (match_dup 2)
4669         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4670                    (const_int 16)))
4671    (set (match_dup 3)
4672         (ashiftrt:SI (match_dup 2) (const_int 16)))
4673    (set (match_operand:HI 0 "s_register_operand" "")
4674         (subreg:HI (match_dup 3) 0))]
4675   "TARGET_ARM"
4676   "
4677   operands[2] = gen_reg_rtx (SImode);
4678   operands[3] = gen_reg_rtx (SImode);
4679   "
4682 ;; Pattern to recognise insn generated default case above
4683 (define_insn "*movhi_insn_arch4"
4684   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4685         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4686   "TARGET_ARM
4687    && arm_arch4
4688    && (GET_CODE (operands[1]) != CONST_INT
4689        || const_ok_for_arm (INTVAL (operands[1]))
4690        || const_ok_for_arm (~INTVAL (operands[1])))"
4691   "@
4692    mov%?\\t%0, %1\\t%@ movhi
4693    mvn%?\\t%0, #%B1\\t%@ movhi
4694    str%?h\\t%1, %0\\t%@ movhi 
4695    ldr%?h\\t%0, %1\\t%@ movhi"
4696   [(set_attr "type" "*,*,store1,load")
4697    (set_attr "predicable" "yes")
4698    (set_attr "pool_range" "*,*,*,256")
4699    (set_attr "neg_pool_range" "*,*,*,244")]
4702 (define_insn "*movhi_insn_littleend"
4703   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4704         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4705   "TARGET_ARM
4706    && !arm_arch4
4707    && !BYTES_BIG_ENDIAN
4708    && !TARGET_MMU_TRAPS
4709    && (GET_CODE (operands[1]) != CONST_INT
4710        || const_ok_for_arm (INTVAL (operands[1]))
4711        || const_ok_for_arm (~INTVAL (operands[1])))"
4712   "@
4713    mov%?\\t%0, %1\\t%@ movhi
4714    mvn%?\\t%0, #%B1\\t%@ movhi
4715    ldr%?\\t%0, %1\\t%@ movhi"
4716   [(set_attr "type" "*,*,load")
4717    (set_attr "predicable" "yes")
4718    (set_attr "pool_range" "4096")
4719    (set_attr "neg_pool_range" "4084")]
4722 (define_insn "*movhi_insn_bigend"
4723   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4724         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4725   "TARGET_ARM
4726    && !arm_arch4
4727    && BYTES_BIG_ENDIAN
4728    && !TARGET_MMU_TRAPS
4729    && (GET_CODE (operands[1]) != CONST_INT
4730        || const_ok_for_arm (INTVAL (operands[1]))
4731        || const_ok_for_arm (~INTVAL (operands[1])))"
4732   "@
4733    mov%?\\t%0, %1\\t%@ movhi
4734    mvn%?\\t%0, #%B1\\t%@ movhi
4735    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4736   [(set_attr "type" "*,*,load")
4737    (set_attr "predicable" "yes")
4738    (set_attr "length" "4,4,8")
4739    (set_attr "pool_range" "*,*,4092")
4740    (set_attr "neg_pool_range" "*,*,4084")]
4743 (define_insn "*loadhi_si_bigend"
4744   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4745         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4746                    (const_int 16)))]
4747   "TARGET_ARM
4748    && BYTES_BIG_ENDIAN
4749    && !TARGET_MMU_TRAPS"
4750   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4751   [(set_attr "type" "load")
4752    (set_attr "predicable" "yes")
4753    (set_attr "pool_range" "4096")
4754    (set_attr "neg_pool_range" "4084")]
4757 (define_insn "*movhi_bytes"
4758   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4759         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4760   "TARGET_ARM && TARGET_MMU_TRAPS"
4761   "@
4762    mov%?\\t%0, %1\\t%@ movhi
4763    mvn%?\\t%0, #%B1\\t%@ movhi"
4764   [(set_attr "predicable" "yes")]
4767 (define_insn "thumb_movhi_clobber"
4768   [(set (match_operand:HI     0 "memory_operand"   "=m")
4769         (match_operand:HI     1 "register_operand" "l"))
4770    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4771   "TARGET_THUMB"
4772   "*
4773   abort ();"
4775         
4776 ;; We use a DImode scratch because we may occasionally need an additional
4777 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4778 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4779 (define_expand "reload_outhi"
4780   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4781               (match_operand:HI 1 "s_register_operand"        "r")
4782               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4783   "TARGET_EITHER"
4784   "if (TARGET_ARM)
4785      arm_reload_out_hi (operands);
4786    else
4787      thumb_reload_out_hi (operands);
4788   DONE;
4789   "
4792 (define_expand "reload_inhi"
4793   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4794               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4795               (match_operand:DI 2 "s_register_operand" "=&r")])]
4796   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4797   "
4798   if (TARGET_ARM)
4799     arm_reload_in_hi (operands);
4800   else
4801     thumb_reload_out_hi (operands);
4802   DONE;
4805 (define_expand "movqi"
4806   [(set (match_operand:QI 0 "general_operand" "")
4807         (match_operand:QI 1 "general_operand" ""))]
4808   "TARGET_EITHER"
4809   "
4810   if (TARGET_ARM)
4811     {
4812       /* Everything except mem = const or mem = mem can be done easily */
4814       if (!no_new_pseudos)
4815         {
4816           if (GET_CODE (operands[1]) == CONST_INT)
4817             {
4818               rtx reg = gen_reg_rtx (SImode);
4820               emit_insn (gen_movsi (reg, operands[1]));
4821               operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
4822             }
4823          if (GET_CODE (operands[0]) == MEM)
4824            operands[1] = force_reg (QImode, operands[1]);
4825        }
4826     }
4827   else /* TARGET_THUMB */
4828     {
4829       if (!no_new_pseudos)
4830         {
4831           if (GET_CODE (operands[0]) != REG)
4832             operands[1] = force_reg (QImode, operands[1]);
4834           /* ??? We shouldn't really get invalid addresses here, but this can
4835              happen if we are passed a SP (never OK for HImode/QImode) or
4836              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4837              HImode/QImode) relative address.  */
4838           /* ??? This should perhaps be fixed elsewhere, for instance, in
4839              fixup_stack_1, by checking for other kinds of invalid addresses,
4840              e.g. a bare reference to a virtual register.  This may confuse the
4841              alpha though, which must handle this case differently.  */
4842           if (GET_CODE (operands[0]) == MEM
4843               && !memory_address_p (GET_MODE (operands[0]),
4844                                      XEXP (operands[0], 0)))
4845             {
4846               rtx temp = copy_to_reg (XEXP (operands[0], 0));
4847               operands[0] = change_address (operands[0], VOIDmode, temp);
4848             }
4849           if (GET_CODE (operands[1]) == MEM
4850               && !memory_address_p (GET_MODE (operands[1]),
4851                                     XEXP (operands[1], 0)))
4852             {
4853                rtx temp = copy_to_reg (XEXP (operands[1], 0));
4854                operands[1] = change_address (operands[1], VOIDmode, temp);
4855             }
4856         }
4857       /* Handle loading a large integer during reload */
4858       else if (GET_CODE (operands[1]) == CONST_INT
4859                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4860         {
4861           /* Writing a constant to memory needs a scratch, which should
4862              be handled with SECONDARY_RELOADs.  */
4863           if (GET_CODE (operands[0]) != REG)
4864             abort ();
4866           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4867           emit_insn (gen_movsi (operands[0], operands[1]));
4868           DONE;
4869        }
4870     }
4871   "
4875 (define_insn "*arm_movqi_insn"
4876   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4877         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4878   "TARGET_ARM
4879    && (   register_operand (operands[0], QImode)
4880        || register_operand (operands[1], QImode))"
4881   "@
4882    mov%?\\t%0, %1
4883    mvn%?\\t%0, #%B1
4884    ldr%?b\\t%0, %1
4885    str%?b\\t%1, %0"
4886   [(set_attr "type" "*,*,load,store1")
4887    (set_attr "predicable" "yes")]
4890 (define_insn "*thumb_movqi_insn"
4891   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4892         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4893   "TARGET_THUMB
4894    && (   register_operand (operands[0], QImode)
4895        || register_operand (operands[1], QImode))"
4896   "@
4897    add\\t%0, %1, #0
4898    ldrb\\t%0, %1
4899    strb\\t%1, %0
4900    mov\\t%0, %1
4901    mov\\t%0, %1
4902    mov\\t%0, %1"
4903   [(set_attr "length" "2")
4904    (set_attr "type" "*,load,store1,*,*,*")
4905    (set_attr "pool_range" "*,32,*,*,*,*")]
4908 (define_expand "movsf"
4909   [(set (match_operand:SF 0 "general_operand" "")
4910         (match_operand:SF 1 "general_operand" ""))]
4911   "TARGET_EITHER"
4912   "
4913   if (TARGET_ARM)
4914     {
4915       if (GET_CODE (operands[0]) == MEM)
4916         operands[1] = force_reg (SFmode, operands[1]);
4917     }
4918   else /* TARGET_THUMB */
4919     {
4920       if (!no_new_pseudos)
4921         {
4922            if (GET_CODE (operands[0]) != REG)
4923              operands[1] = force_reg (SFmode, operands[1]);
4924         }
4925     }
4926   "
4929 (define_split
4930   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4931         (match_operand:SF 1 "immediate_operand" ""))]
4932   "TARGET_ARM
4933    && !TARGET_HARD_FLOAT
4934    && reload_completed
4935    && GET_CODE (operands[1]) == CONST_DOUBLE"
4936   [(set (match_dup 2) (match_dup 3))]
4937   "
4938   operands[2] = gen_lowpart (SImode, operands[0]);
4939   operands[3] = gen_lowpart (SImode, operands[1]);
4940   if (operands[2] == 0 || operands[3] == 0)
4941     FAIL;
4942   "
4945 (define_insn "*arm_movsf_hard_insn"
4946   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4947         (match_operand:SF 1 "general_operand"      "fG,H,mE,f,r,f,r,mE,r"))]
4948   "TARGET_ARM
4949    && TARGET_HARD_FLOAT
4950    && (GET_CODE (operands[0]) != MEM
4951        || register_operand (operands[1], SFmode))"
4952   "@
4953    mvf%?s\\t%0, %1
4954    mnf%?s\\t%0, #%N1
4955    ldf%?s\\t%0, %1
4956    stf%?s\\t%1, %0
4957    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4958    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4959    mov%?\\t%0, %1
4960    ldr%?\\t%0, %1\\t%@ float
4961    str%?\\t%1, %0\\t%@ float"
4962   [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4963    (set_attr "predicable" "yes")
4964    (set_attr "type"
4965          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4966    (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4967    (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4970 ;; Exactly the same as above, except that all `f' cases are deleted.
4971 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4972 ;; when -msoft-float.
4974 (define_insn "*arm_movsf_soft_insn"
4975   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4976         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4977   "TARGET_ARM
4978    && TARGET_SOFT_FLOAT
4979    && (GET_CODE (operands[0]) != MEM
4980        || register_operand (operands[1], SFmode))"
4981   "@
4982    mov%?\\t%0, %1
4983    ldr%?\\t%0, %1\\t%@ float
4984    str%?\\t%1, %0\\t%@ float"
4985   [(set_attr "length" "4,4,4")
4986    (set_attr "predicable" "yes")
4987    (set_attr "type" "*,load,store1")
4988    (set_attr "pool_range" "*,4096,*")
4989    (set_attr "neg_pool_range" "*,4084,*")]
4992 ;;; ??? This should have alternatives for constants.
4993 (define_insn "*thumb_movsf_insn"
4994   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4995         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4996   "TARGET_THUMB
4997    && (   register_operand (operands[0], SFmode) 
4998        || register_operand (operands[1], SFmode))"
4999   "@
5000    add\\t%0, %1, #0
5001    ldmia\\t%1, {%0}
5002    stmia\\t%0, {%1}
5003    ldr\\t%0, %1
5004    str\\t%1, %0
5005    mov\\t%0, %1
5006    mov\\t%0, %1"
5007   [(set_attr "length" "2")
5008    (set_attr "type" "*,load,store1,load,store1,*,*")
5009    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5012 (define_expand "movdf"
5013   [(set (match_operand:DF 0 "general_operand" "")
5014         (match_operand:DF 1 "general_operand" ""))]
5015   "TARGET_EITHER"
5016   "
5017   if (TARGET_ARM)
5018     {
5019       if (GET_CODE (operands[0]) == MEM)
5020         operands[1] = force_reg (DFmode, operands[1]);
5021     }
5022   else /* TARGET_THUMB */
5023     {
5024       if (!no_new_pseudos)
5025         {
5026           if (GET_CODE (operands[0]) != REG)
5027             operands[1] = force_reg (DFmode, operands[1]);
5028         }
5029     }
5030   "
5033 ;; Reloading a df mode value stored in integer regs to memory can require a
5034 ;; scratch reg.
5035 (define_expand "reload_outdf"
5036   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5037    (match_operand:DF 1 "s_register_operand" "r")
5038    (match_operand:SI 2 "s_register_operand" "=&r")]
5039   "TARGET_ARM"
5040   "
5041   {
5042     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5044     if (code == REG)
5045       operands[2] = XEXP (operands[0], 0);
5046     else if (code == POST_INC || code == PRE_DEC)
5047       {
5048         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5049         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5050         emit_insn (gen_movdi (operands[0], operands[1]));
5051         DONE;
5052       }
5053     else if (code == PRE_INC)
5054       {
5055         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5057         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5058         operands[2] = reg;
5059       }
5060     else if (code == POST_DEC)
5061       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5062     else
5063       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5064                              XEXP (XEXP (operands[0], 0), 1)));
5066     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5067                             operands[1]));
5069     if (code == POST_DEC)
5070       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5072     DONE;
5073   }"
5076 (define_insn "*movdf_hard_insn"
5077   [(set (match_operand:DF 0 "nonimmediate_operand"
5078                                                 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5079         (match_operand:DF 1 "general_operand"
5080                                                 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5081   "TARGET_ARM
5082    && TARGET_HARD_FLOAT
5083    && (GET_CODE (operands[0]) != MEM
5084        || register_operand (operands[1], DFmode))"
5085   "*
5086   {
5087   switch (which_alternative)
5088     {
5089     default:
5090     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5091     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5092     case 2: case 3: case 4: return output_move_double (operands);
5093     case 5: return \"mvf%?d\\t%0, %1\";
5094     case 6: return \"mnf%?d\\t%0, #%N1\";
5095     case 7: return \"ldf%?d\\t%0, %1\";
5096     case 8: return \"stf%?d\\t%1, %0\";
5097     case 9: return output_mov_double_fpu_from_arm (operands);
5098     case 10: return output_mov_double_arm_from_fpu (operands);
5099     }
5100   }
5101   "
5102   [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5103    (set_attr "predicable" "yes")
5104    (set_attr "type"
5105     "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5106    (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")
5107    (set_attr "neg_pool_range" "*,*,*,*,244,*,*,1012,*,*,*")]
5110 ;; Software floating point version.  This is essentially the same as movdi.
5111 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5112 ;; an `f' reg.
5114 (define_insn "*movdf_soft_insn"
5115   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5116         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5117   "TARGET_ARM && TARGET_SOFT_FLOAT
5118   "
5119   "* return output_move_double (operands);"
5120   [(set_attr "length" "8,8,8")
5121    (set_attr "type" "*,load,store2")
5122    (set_attr "pool_range" "252")
5123    (set_attr "neg_pool_range" "244")]
5126 ;;; ??? This should have alternatives for constants.
5127 ;;; ??? This was originally identical to the movdi_insn pattern.
5128 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5129 ;;; thumb_reorg with a memory reference.
5130 (define_insn "*thumb_movdf_insn"
5131   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5132         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5133   "TARGET_THUMB
5134    && (   register_operand (operands[0], DFmode)
5135        || register_operand (operands[1], DFmode))"
5136   "*
5137   switch (which_alternative)
5138     {
5139     default:
5140     case 0:
5141       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5142         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5143       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5144     case 1:
5145       return \"ldmia\\t%1, {%0, %H0}\";
5146     case 2:
5147       return \"stmia\\t%0, {%1, %H1}\";
5148     case 3:
5149       return thumb_load_double_from_address (operands);
5150     case 4:
5151       operands[2] = gen_rtx (MEM, SImode,
5152                              plus_constant (XEXP (operands[0], 0), 4));
5153       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5154       return \"\";
5155     case 5:
5156       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5157         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5158       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5159     }
5160   "
5161   [(set_attr "length" "4,2,2,6,4,4")
5162    (set_attr "type" "*,load,store2,load,store2,*")
5163    (set_attr "pool_range" "*,*,*,1020,*,*")]
5167 (define_expand "movxf"
5168   [(set (match_operand:XF 0 "general_operand" "")
5169         (match_operand:XF 1 "general_operand" ""))]
5170   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5171   "")
5173 ;; Even when the XFmode patterns aren't enabled, we enable this after
5174 ;; reloading so that we can push floating point registers in the prologue.
5176 (define_insn "*movxf_hard_insn"
5177   [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5178         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5179   "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5180   "*
5181   switch (which_alternative)
5182     {
5183     default:
5184     case 0: return \"mvf%?e\\t%0, %1\";
5185     case 1: return \"mnf%?e\\t%0, #%N1\";
5186     case 2: return \"ldf%?e\\t%0, %1\";
5187     case 3: return \"stf%?e\\t%1, %0\";
5188     case 4: return output_mov_long_double_fpu_from_arm (operands);
5189     case 5: return output_mov_long_double_arm_from_fpu (operands);
5190     case 6: return output_mov_long_double_arm_from_arm (operands);
5191     }
5192   "
5193   [(set_attr "length" "4,4,4,4,8,8,12")
5194    (set_attr "predicable" "yes")
5195    (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5196    (set_attr "pool_range" "*,*,1024,*,*,*,*")
5197    (set_attr "neg_pool_range" "*,*,1012,*,*,*,*")]
5201 ;; load- and store-multiple insns
5202 ;; The arm can load/store any set of registers, provided that they are in
5203 ;; ascending order; but that is beyond GCC so stick with what it knows.
5205 (define_expand "load_multiple"
5206   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5207                           (match_operand:SI 1 "" ""))
5208                      (use (match_operand:SI 2 "" ""))])]
5209   "TARGET_ARM"
5210   "
5211   /* Support only fixed point registers.  */
5212   if (GET_CODE (operands[2]) != CONST_INT
5213       || INTVAL (operands[2]) > 14
5214       || INTVAL (operands[2]) < 2
5215       || GET_CODE (operands[1]) != MEM
5216       || GET_CODE (operands[0]) != REG
5217       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5218       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5219     FAIL;
5221   operands[3]
5222     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5223                              force_reg (SImode, XEXP (operands[1], 0)),
5224                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5225                              MEM_IN_STRUCT_P(operands[1]),
5226                              MEM_SCALAR_P (operands[1]));
5227   "
5230 ;; Load multiple with write-back
5232 (define_insn "*ldmsi_postinc4"
5233   [(match_parallel 0 "load_multiple_operation"
5234     [(set (match_operand:SI 1 "s_register_operand" "=r")
5235           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5236                    (const_int 16)))
5237      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5238           (mem:SI (match_dup 2)))
5239      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5240           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5241      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5242           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5243      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5244           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5245   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5246   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5247   [(set_attr "type" "load")
5248    (set_attr "predicable" "yes")]
5251 (define_insn "*ldmsi_postinc3"
5252   [(match_parallel 0 "load_multiple_operation"
5253     [(set (match_operand:SI 1 "s_register_operand" "=r")
5254           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5255                    (const_int 12)))
5256      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5257           (mem:SI (match_dup 2)))
5258      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5259           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5260      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5261           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5262   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5263   "ldm%?ia\\t%1!, {%3, %4, %5}"
5264   [(set_attr "type" "load")
5265    (set_attr "predicable" "yes")]
5268 (define_insn "*ldmsi_postinc2"
5269   [(match_parallel 0 "load_multiple_operation"
5270     [(set (match_operand:SI 1 "s_register_operand" "=r")
5271           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5272                    (const_int 8)))
5273      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5274           (mem:SI (match_dup 2)))
5275      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5276           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5277   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5278   "ldm%?ia\\t%1!, {%3, %4}"
5279   [(set_attr "type" "load")
5280    (set_attr "predicable" "yes")]
5283 ;; Ordinary load multiple
5285 (define_insn "*ldmsi4"
5286   [(match_parallel 0 "load_multiple_operation"
5287     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5288           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5289      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5290           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5291      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5292           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5293      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5294           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5295   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5296   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5297   [(set_attr "type" "load")
5298    (set_attr "predicable" "yes")]
5301 (define_insn "*ldmsi3"
5302   [(match_parallel 0 "load_multiple_operation"
5303     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5304           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5305      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5306           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5307      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5308           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5309   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5310   "ldm%?ia\\t%1, {%2, %3, %4}"
5311   [(set_attr "type" "load")
5312    (set_attr "predicable" "yes")]
5315 (define_insn "*ldmsi2"
5316   [(match_parallel 0 "load_multiple_operation"
5317     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5318           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5319      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5320           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5321   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5322   "ldm%?ia\\t%1, {%2, %3}"
5323   [(set_attr "type" "load")
5324    (set_attr "predicable" "yes")]
5327 (define_expand "store_multiple"
5328   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5329                           (match_operand:SI 1 "" ""))
5330                      (use (match_operand:SI 2 "" ""))])]
5331   "TARGET_ARM"
5332   "
5333   /* Support only fixed point registers */
5334   if (GET_CODE (operands[2]) != CONST_INT
5335       || INTVAL (operands[2]) > 14
5336       || INTVAL (operands[2]) < 2
5337       || GET_CODE (operands[1]) != REG
5338       || GET_CODE (operands[0]) != MEM
5339       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5340       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5341     FAIL;
5343   operands[3]
5344     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5345                               force_reg (SImode, XEXP (operands[0], 0)),
5346                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5347                               MEM_IN_STRUCT_P(operands[0]), 
5348                               MEM_SCALAR_P (operands[0]));
5349   "
5352 ;; Store multiple with write-back
5354 (define_insn "*stmsi_postinc4"
5355   [(match_parallel 0 "store_multiple_operation"
5356     [(set (match_operand:SI 1 "s_register_operand" "=r")
5357           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5358                    (const_int 16)))
5359      (set (mem:SI (match_dup 2))
5360           (match_operand:SI 3 "arm_hard_register_operand" ""))
5361      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5362           (match_operand:SI 4 "arm_hard_register_operand" ""))
5363      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5364           (match_operand:SI 5 "arm_hard_register_operand" ""))
5365      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5366           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5367   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5368   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5369   [(set_attr "predicable" "yes")
5370    (set_attr "type" "store4")]
5373 (define_insn "*stmsi_postinc3"
5374   [(match_parallel 0 "store_multiple_operation"
5375     [(set (match_operand:SI 1 "s_register_operand" "=r")
5376           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5377                    (const_int 12)))
5378      (set (mem:SI (match_dup 2))
5379           (match_operand:SI 3 "arm_hard_register_operand" ""))
5380      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5381           (match_operand:SI 4 "arm_hard_register_operand" ""))
5382      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5383           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5384   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5385   "stm%?ia\\t%1!, {%3, %4, %5}"
5386   [(set_attr "predicable" "yes")
5387    (set_attr "type" "store3")]
5390 (define_insn "*stmsi_postinc2"
5391   [(match_parallel 0 "store_multiple_operation"
5392     [(set (match_operand:SI 1 "s_register_operand" "=r")
5393           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5394                    (const_int 8)))
5395      (set (mem:SI (match_dup 2))
5396           (match_operand:SI 3 "arm_hard_register_operand" ""))
5397      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5398           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5399   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5400   "stm%?ia\\t%1!, {%3, %4}"
5401   [(set_attr "predicable" "yes")
5402    (set_attr "type" "store2")]
5405 ;; Ordinary store multiple
5407 (define_insn "*stmsi4"
5408   [(match_parallel 0 "store_multiple_operation"
5409     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5410           (match_operand:SI 2 "arm_hard_register_operand" ""))
5411      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5412           (match_operand:SI 3 "arm_hard_register_operand" ""))
5413      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5414           (match_operand:SI 4 "arm_hard_register_operand" ""))
5415      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5416           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5417   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5418   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5419   [(set_attr "predicable" "yes")
5420    (set_attr "type" "store4")]
5423 (define_insn "*stmsi3"
5424   [(match_parallel 0 "store_multiple_operation"
5425     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5426           (match_operand:SI 2 "arm_hard_register_operand" ""))
5427      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5428           (match_operand:SI 3 "arm_hard_register_operand" ""))
5429      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5430           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5431   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5432   "stm%?ia\\t%1, {%2, %3, %4}"
5433   [(set_attr "predicable" "yes")
5434    (set_attr "type" "store3")]
5437 (define_insn "*stmsi2"
5438   [(match_parallel 0 "store_multiple_operation"
5439     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5440           (match_operand:SI 2 "arm_hard_register_operand" ""))
5441      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5442           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5443   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5444   "stm%?ia\\t%1, {%2, %3}"
5445   [(set_attr "predicable" "yes")
5446    (set_attr "type" "store2")]
5449 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5450 ;; We could let this apply for blocks of less than this, but it clobbers so
5451 ;; many registers that there is then probably a better way.
5453 (define_expand "movstrqi"
5454   [(match_operand:BLK 0 "general_operand" "")
5455    (match_operand:BLK 1 "general_operand" "")
5456    (match_operand:SI 2 "const_int_operand" "")
5457    (match_operand:SI 3 "const_int_operand" "")]
5458   "TARGET_EITHER"
5459   "
5460   if (TARGET_ARM)
5461     {
5462       if (arm_gen_movstrqi (operands))
5463         DONE;
5464       FAIL;
5465     }
5466   else /* TARGET_THUMB */
5467     {
5468       if (   INTVAL (operands[3]) != 4
5469           || INTVAL (operands[2]) > 48)
5470         FAIL;
5472       thumb_expand_movstrqi (operands);
5473       DONE;
5474     }
5475   "
5478 ;; Thumb block-move insns
5480 (define_insn "movmem12b"
5481   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5482         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5483    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5484         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5485    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5486         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5487    (set (match_operand:SI 0 "register_operand" "=l")
5488         (plus:SI (match_dup 2) (const_int 12)))
5489    (set (match_operand:SI 1 "register_operand" "=l")
5490         (plus:SI (match_dup 3) (const_int 12)))
5491    (clobber (match_scratch:SI 4 "=&l"))
5492    (clobber (match_scratch:SI 5 "=&l"))
5493    (clobber (match_scratch:SI 6 "=&l"))]
5494   "TARGET_THUMB"
5495   "* return thumb_output_move_mem_multiple (3, operands);"
5496   [(set_attr "length" "4")
5497    ; This isn't entirely accurate...  It loads as well, but in terms of
5498    ; scheduling the following insn it is better to consider it as a store
5499    (set_attr "type" "store3")]
5502 (define_insn "movmem8b"
5503   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5504         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5505    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5506         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5507    (set (match_operand:SI 0 "register_operand" "=l")
5508         (plus:SI (match_dup 2) (const_int 8)))
5509    (set (match_operand:SI 1 "register_operand" "=l")
5510         (plus:SI (match_dup 3) (const_int 8)))
5511    (clobber (match_scratch:SI 4 "=&l"))
5512    (clobber (match_scratch:SI 5 "=&l"))]
5513   "TARGET_THUMB"
5514   "* return thumb_output_move_mem_multiple (2, operands);"
5515   [(set_attr "length" "4")
5516    ; This isn't entirely accurate...  It loads as well, but in terms of
5517    ; scheduling the following insn it is better to consider it as a store
5518    (set_attr "type" "store2")]
5523 ;; Compare & branch insns
5524 ;; The range calcualations are based as follows:
5525 ;; For forward branches, the address calculation returns the address of
5526 ;; the next instruction.  This is 2 beyond the branch instruction.
5527 ;; For backward branches, the address calculation returns the address of
5528 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5529 ;; instruction for the shortest sequence, and 4 before the branch instruction
5530 ;; if we have to jump around an unconditional branch.
5531 ;; To the basic branch range the PC offset must be added (this is +4).
5532 ;; So for forward branches we have 
5533 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5534 ;; And for backward branches we have 
5535 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5537 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5538 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5540 (define_insn "cbranchsi4"
5541   [(set (pc)
5542         (if_then_else
5543             (match_operator                    0 "arm_comparison_operator"
5544                             [(match_operand:SI 1 "register_operand"   "l,r")
5545                              (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5546             (label_ref       (match_operand    3 "" ""))
5547             (pc)))]
5548   "TARGET_THUMB"
5549   "*
5550   output_asm_insn (\"cmp\\t%1, %2\", operands);
5551   switch (get_attr_length (insn))
5552     {
5553     case 4:  return \"b%d0\\t%l3\";
5554     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5555     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5556     }
5557   "
5558   [(set (attr "far_jump")
5559         (if_then_else
5560             (eq_attr "length" "8")
5561             (const_string "yes")
5562             (const_string "no")))
5563    (set (attr "length") 
5564         (if_then_else
5565             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5566                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5567             (const_int 4)
5568             (if_then_else
5569                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5570                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5571                 (const_int 6)
5572                 (const_int 8))))]
5575 (define_insn "*negated_cbranchsi4"
5576   [(set (pc)
5577         (if_then_else
5578          (match_operator             0 "arm_comparison_operator"
5579           [(match_operand:SI         1 "register_operand"  "l")
5580            (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5581          (label_ref (match_operand   3 "" ""))
5582          (pc)))]
5583   "TARGET_THUMB"
5584   "*
5585   output_asm_insn (\"cmn\\t%1, %2\", operands);
5586   switch (get_attr_length (insn))
5587     {
5588     case 4:  return \"b%d0\\t%l3\";
5589     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5590     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5591     }
5592   "
5593   [(set (attr "far_jump")
5594         (if_then_else
5595             (eq_attr "length" "8")
5596             (const_string "yes")
5597             (const_string "no")))
5598    (set (attr "length") 
5599         (if_then_else
5600             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5601                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5602             (const_int 4)
5603             (if_then_else
5604                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5605                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5606                 (const_int 6)
5607                 (const_int 8))))]
5611 ;; Comparison and test insns
5613 (define_expand "cmpsi"
5614   [(match_operand:SI 0 "s_register_operand" "")
5615    (match_operand:SI 1 "arm_add_operand" "")]
5616   "TARGET_ARM"
5617   "{
5618     arm_compare_op0 = operands[0];
5619     arm_compare_op1 = operands[1];
5620     DONE;
5621   }"
5624 (define_expand "cmpsf"
5625   [(match_operand:SF 0 "s_register_operand" "")
5626    (match_operand:SF 1 "fpu_rhs_operand" "")]
5627   "TARGET_ARM && TARGET_HARD_FLOAT"
5628   "
5629   arm_compare_op0 = operands[0];
5630   arm_compare_op1 = operands[1];
5631   DONE;
5632   "
5635 (define_expand "cmpdf"
5636   [(match_operand:DF 0 "s_register_operand" "")
5637    (match_operand:DF 1 "fpu_rhs_operand" "")]
5638   "TARGET_ARM && TARGET_HARD_FLOAT"
5639   "
5640   arm_compare_op0 = operands[0];
5641   arm_compare_op1 = operands[1];
5642   DONE;
5643   "
5646 (define_expand "cmpxf"
5647   [(match_operand:XF 0 "s_register_operand" "")
5648    (match_operand:XF 1 "fpu_rhs_operand" "")]
5649   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5650   "
5651   arm_compare_op0 = operands[0];
5652   arm_compare_op1 = operands[1];
5653   DONE;
5654   "
5657 (define_insn "*arm_cmpsi_insn"
5658   [(set (reg:CC CC_REGNUM)
5659         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5660                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5661   "TARGET_ARM"
5662   "@
5663    cmp%?\\t%0, %1
5664    cmn%?\\t%0, #%n1"
5665   [(set_attr "conds" "set")]
5668 (define_insn "*cmpsi_shiftsi"
5669   [(set (reg:CC CC_REGNUM)
5670         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
5671                     (match_operator:SI  3 "shift_operator"
5672                      [(match_operand:SI 1 "s_register_operand" "r")
5673                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5674   "TARGET_ARM"
5675   "cmp%?\\t%0, %1%S3"
5676   [(set_attr "conds" "set")
5677    (set_attr "shift" "1")
5678    ]
5681 (define_insn "*cmpsi_shiftsi_swp"
5682   [(set (reg:CC_SWP CC_REGNUM)
5683         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5684                          [(match_operand:SI 1 "s_register_operand" "r")
5685                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
5686                         (match_operand:SI 0 "s_register_operand" "r")))]
5687   "TARGET_ARM"
5688   "cmp%?\\t%0, %1%S3"
5689   [(set_attr "conds" "set")
5690    (set_attr "shift" "1")
5691    ]
5694 (define_insn "*cmpsi_neg_shiftsi"
5695   [(set (reg:CC CC_REGNUM)
5696         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5697                     (neg:SI (match_operator:SI 3 "shift_operator"
5698                              [(match_operand:SI 1 "s_register_operand" "r")
5699                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5700   "TARGET_ARM"
5701   "cmn%?\\t%0, %1%S3"
5702   [(set_attr "conds" "set")
5703    (set_attr "shift" "1")
5704    ]
5707 (define_insn "*cmpsf_insn"
5708   [(set (reg:CCFP CC_REGNUM)
5709         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5710                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5711   "TARGET_ARM && TARGET_HARD_FLOAT"
5712   "@
5713    cmf%?\\t%0, %1
5714    cnf%?\\t%0, #%N1"
5715   [(set_attr "conds" "set")
5716    (set_attr "type" "f_2_r")]
5719 (define_insn "*cmpdf_insn"
5720   [(set (reg:CCFP CC_REGNUM)
5721         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5722                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5723   "TARGET_ARM && TARGET_HARD_FLOAT"
5724   "@
5725    cmf%?\\t%0, %1
5726    cnf%?\\t%0, #%N1"
5727   [(set_attr "conds" "set")
5728    (set_attr "type" "f_2_r")]
5731 (define_insn "*cmpesfdf_df"
5732   [(set (reg:CCFP CC_REGNUM)
5733         (compare:CCFP (float_extend:DF
5734                        (match_operand:SF 0 "s_register_operand" "f,f"))
5735                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5736   "TARGET_ARM && TARGET_HARD_FLOAT"
5737   "@
5738    cmf%?\\t%0, %1
5739    cnf%?\\t%0, #%N1"
5740   [(set_attr "conds" "set")
5741    (set_attr "type" "f_2_r")]
5744 (define_insn "*cmpdf_esfdf"
5745   [(set (reg:CCFP CC_REGNUM)
5746         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5747                       (float_extend:DF
5748                        (match_operand:SF 1 "s_register_operand" "f"))))]
5749   "TARGET_ARM && TARGET_HARD_FLOAT"
5750   "cmf%?\\t%0, %1"
5751   [(set_attr "conds" "set")
5752    (set_attr "type" "f_2_r")]
5755 (define_insn "*cmpxf_insn"
5756   [(set (reg:CCFP CC_REGNUM)
5757         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5758                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5759   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5760   "@
5761    cmf%?\\t%0, %1
5762    cnf%?\\t%0, #%N1"
5763   [(set_attr "conds" "set")
5764    (set_attr "type" "f_2_r")]
5767 (define_insn "*cmpsf_trap"
5768   [(set (reg:CCFPE CC_REGNUM)
5769         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5770                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5771   "TARGET_ARM && TARGET_HARD_FLOAT"
5772   "@
5773    cmf%?e\\t%0, %1
5774    cnf%?e\\t%0, #%N1"
5775   [(set_attr "conds" "set")
5776    (set_attr "type" "f_2_r")]
5779 (define_insn "*cmpdf_trap"
5780   [(set (reg:CCFPE CC_REGNUM)
5781         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5782                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5783   "TARGET_ARM && TARGET_HARD_FLOAT"
5784   "@
5785    cmf%?e\\t%0, %1
5786    cnf%?e\\t%0, #%N1"
5787   [(set_attr "conds" "set")
5788    (set_attr "type" "f_2_r")]
5791 (define_insn "*cmp_esfdf_df_trap"
5792   [(set (reg:CCFPE CC_REGNUM)
5793         (compare:CCFPE (float_extend:DF
5794                         (match_operand:SF 0 "s_register_operand" "f,f"))
5795                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5796   "TARGET_ARM && TARGET_HARD_FLOAT"
5797   "@
5798    cmf%?e\\t%0, %1
5799    cnf%?e\\t%0, #%N1"
5800   [(set_attr "conds" "set")
5801    (set_attr "type" "f_2_r")]
5804 (define_insn "*cmp_df_esfdf_trap"
5805   [(set (reg:CCFPE CC_REGNUM)
5806         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5807                        (float_extend:DF
5808                         (match_operand:SF 1 "s_register_operand" "f"))))]
5809   "TARGET_ARM && TARGET_HARD_FLOAT"
5810   "cmf%?e\\t%0, %1"
5811   [(set_attr "conds" "set")
5812    (set_attr "type" "f_2_r")]
5815 (define_insn "*cmpxf_trap"
5816   [(set (reg:CCFPE CC_REGNUM)
5817         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5818                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5819   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5820   "@
5821    cmf%?e\\t%0, %1
5822    cnf%?e\\t%0, #%N1"
5823   [(set_attr "conds" "set")
5824    (set_attr "type" "f_2_r")]
5827 ; This insn allows redundant compares to be removed by cse, nothing should
5828 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5829 ; is deleted later on. The match_dup will match the mode here, so that
5830 ; mode changes of the condition codes aren't lost by this even though we don't
5831 ; specify what they are.
5833 (define_insn "*deleted_compare"
5834   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5835   "TARGET_ARM"
5836   "\\t%@ deleted compare"
5837   [(set_attr "conds" "set")
5838    (set_attr "length" "0")]
5842 ;; Conditional branch insns
5844 (define_expand "beq"
5845   [(set (pc)
5846         (if_then_else (eq (match_dup 1) (const_int 0))
5847                       (label_ref (match_operand 0 "" ""))
5848                       (pc)))]
5849   "TARGET_ARM"
5850   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5853 (define_expand "bne"
5854   [(set (pc)
5855         (if_then_else (ne (match_dup 1) (const_int 0))
5856                       (label_ref (match_operand 0 "" ""))
5857                       (pc)))]
5858   "TARGET_ARM"
5859   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5862 (define_expand "bgt"
5863   [(set (pc)
5864         (if_then_else (gt (match_dup 1) (const_int 0))
5865                       (label_ref (match_operand 0 "" ""))
5866                       (pc)))]
5867   "TARGET_ARM"
5868   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5871 (define_expand "ble"
5872   [(set (pc)
5873         (if_then_else (le (match_dup 1) (const_int 0))
5874                       (label_ref (match_operand 0 "" ""))
5875                       (pc)))]
5876   "TARGET_ARM"
5877   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5880 (define_expand "bge"
5881   [(set (pc)
5882         (if_then_else (ge (match_dup 1) (const_int 0))
5883                       (label_ref (match_operand 0 "" ""))
5884                       (pc)))]
5885   "TARGET_ARM"
5886   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5889 (define_expand "blt"
5890   [(set (pc)
5891         (if_then_else (lt (match_dup 1) (const_int 0))
5892                       (label_ref (match_operand 0 "" ""))
5893                       (pc)))]
5894   "TARGET_ARM"
5895   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5898 (define_expand "bgtu"
5899   [(set (pc)
5900         (if_then_else (gtu (match_dup 1) (const_int 0))
5901                       (label_ref (match_operand 0 "" ""))
5902                       (pc)))]
5903   "TARGET_ARM"
5904   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5907 (define_expand "bleu"
5908   [(set (pc)
5909         (if_then_else (leu (match_dup 1) (const_int 0))
5910                       (label_ref (match_operand 0 "" ""))
5911                       (pc)))]
5912   "TARGET_ARM"
5913   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5916 (define_expand "bgeu"
5917   [(set (pc)
5918         (if_then_else (geu (match_dup 1) (const_int 0))
5919                       (label_ref (match_operand 0 "" ""))
5920                       (pc)))]
5921   "TARGET_ARM"
5922   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5925 (define_expand "bltu"
5926   [(set (pc)
5927         (if_then_else (ltu (match_dup 1) (const_int 0))
5928                       (label_ref (match_operand 0 "" ""))
5929                       (pc)))]
5930   "TARGET_ARM"
5931   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5934 (define_expand "bunordered"
5935   [(set (pc)
5936         (if_then_else (unordered (match_dup 1) (const_int 0))
5937                       (label_ref (match_operand 0 "" ""))
5938                       (pc)))]
5939   "TARGET_ARM && TARGET_HARD_FLOAT"
5940   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5941                                       arm_compare_op1);"
5944 (define_expand "bordered"
5945   [(set (pc)
5946         (if_then_else (ordered (match_dup 1) (const_int 0))
5947                       (label_ref (match_operand 0 "" ""))
5948                       (pc)))]
5949   "TARGET_ARM && TARGET_HARD_FLOAT"
5950   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5951                                       arm_compare_op1);"
5954 (define_expand "bungt"
5955   [(set (pc)
5956         (if_then_else (ungt (match_dup 1) (const_int 0))
5957                       (label_ref (match_operand 0 "" ""))
5958                       (pc)))]
5959   "TARGET_ARM && TARGET_HARD_FLOAT"
5960   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5963 (define_expand "bunlt"
5964   [(set (pc)
5965         (if_then_else (unlt (match_dup 1) (const_int 0))
5966                       (label_ref (match_operand 0 "" ""))
5967                       (pc)))]
5968   "TARGET_ARM && TARGET_HARD_FLOAT"
5969   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5972 (define_expand "bunge"
5973   [(set (pc)
5974         (if_then_else (unge (match_dup 1) (const_int 0))
5975                       (label_ref (match_operand 0 "" ""))
5976                       (pc)))]
5977   "TARGET_ARM && TARGET_HARD_FLOAT"
5978   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5981 (define_expand "bunle"
5982   [(set (pc)
5983         (if_then_else (unle (match_dup 1) (const_int 0))
5984                       (label_ref (match_operand 0 "" ""))
5985                       (pc)))]
5986   "TARGET_ARM && TARGET_HARD_FLOAT"
5987   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5990 ;; The following two patterns need two branch instructions, since there is
5991 ;; no single instruction that will handle all cases.
5992 (define_expand "buneq"
5993   [(set (pc)
5994         (if_then_else (uneq (match_dup 1) (const_int 0))
5995                       (label_ref (match_operand 0 "" ""))
5996                       (pc)))]
5997   "TARGET_ARM && TARGET_HARD_FLOAT"
5998   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6001 (define_expand "bltgt"
6002   [(set (pc)
6003         (if_then_else (ltgt (match_dup 1) (const_int 0))
6004                       (label_ref (match_operand 0 "" ""))
6005                       (pc)))]
6006   "TARGET_ARM && TARGET_HARD_FLOAT"
6007   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6011 ;; Patterns to match conditional branch insns.
6014 ; Special pattern to match UNEQ.
6015 (define_insn "*arm_buneq"
6016   [(set (pc)
6017         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6018                       (label_ref (match_operand 0 "" ""))
6019                       (pc)))]
6020   "TARGET_ARM && TARGET_HARD_FLOAT"
6021   "*
6022   if (arm_ccfsm_state != 0)
6023     abort ();
6025   return \"bvs\\t%l0;beq\\t%l0\";
6026   "
6027   [(set_attr "conds" "jump_clob")
6028    (set_attr "length" "8")]
6031 ; Special pattern to match LTGT.
6032 (define_insn "*arm_bltgt"
6033   [(set (pc)
6034         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6035                       (label_ref (match_operand 0 "" ""))
6036                       (pc)))]
6037   "TARGET_ARM && TARGET_HARD_FLOAT"
6038   "*
6039   if (arm_ccfsm_state != 0)
6040     abort ();
6042   return \"bmi\\t%l0;bgt\\t%l0\";
6043   "
6044   [(set_attr "conds" "jump_clob")
6045    (set_attr "length" "8")]
6048 (define_insn "*arm_cond_branch"
6049   [(set (pc)
6050         (if_then_else (match_operator 1 "arm_comparison_operator"
6051                        [(match_operand 2 "cc_register" "") (const_int 0)])
6052                       (label_ref (match_operand 0 "" ""))
6053                       (pc)))]
6054   "TARGET_ARM"
6055   "*
6056   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6057     {
6058       arm_ccfsm_state += 2;
6059       return \"\";
6060     }
6061   return \"b%d1\\t%l0\";
6062   "
6063   [(set_attr "conds" "use")]
6066 ; Special pattern to match reversed UNEQ.
6067 (define_insn "*arm_buneq_reversed"
6068   [(set (pc)
6069         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6070                       (pc)
6071                       (label_ref (match_operand 0 "" ""))))]
6072   "TARGET_ARM && TARGET_HARD_FLOAT"
6073   "*
6074   if (arm_ccfsm_state != 0)
6075     abort ();
6077   return \"bmi\\t%l0;bgt\\t%l0\";
6078   "
6079   [(set_attr "conds" "jump_clob")
6080    (set_attr "length" "8")]
6083 ; Special pattern to match reversed LTGT.
6084 (define_insn "*arm_bltgt_reversed"
6085   [(set (pc)
6086         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6087                       (pc)
6088                       (label_ref (match_operand 0 "" ""))))]
6089   "TARGET_ARM && TARGET_HARD_FLOAT"
6090   "*
6091   if (arm_ccfsm_state != 0)
6092     abort ();
6094   return \"bvs\\t%l0;beq\\t%l0\";
6095   "
6096   [(set_attr "conds" "jump_clob")
6097    (set_attr "length" "8")]
6100 (define_insn "*arm_cond_branch_reversed"
6101   [(set (pc)
6102         (if_then_else (match_operator 1 "arm_comparison_operator"
6103                        [(match_operand 2 "cc_register" "") (const_int 0)])
6104                       (pc)
6105                       (label_ref (match_operand 0 "" ""))))]
6106   "TARGET_ARM"
6107   "*
6108   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6109     {
6110       arm_ccfsm_state += 2;
6111       return \"\";
6112     }
6113   return \"b%D1\\t%l0\";
6114   "
6115   [(set_attr "conds" "use")]
6120 ; scc insns
6122 (define_expand "seq"
6123   [(set (match_operand:SI 0 "s_register_operand" "=r")
6124         (eq:SI (match_dup 1) (const_int 0)))]
6125   "TARGET_ARM"
6126   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6129 (define_expand "sne"
6130   [(set (match_operand:SI 0 "s_register_operand" "=r")
6131         (ne:SI (match_dup 1) (const_int 0)))]
6132   "TARGET_ARM"
6133   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6136 (define_expand "sgt"
6137   [(set (match_operand:SI 0 "s_register_operand" "=r")
6138         (gt:SI (match_dup 1) (const_int 0)))]
6139   "TARGET_ARM"
6140   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6143 (define_expand "sle"
6144   [(set (match_operand:SI 0 "s_register_operand" "=r")
6145         (le:SI (match_dup 1) (const_int 0)))]
6146   "TARGET_ARM"
6147   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6150 (define_expand "sge"
6151   [(set (match_operand:SI 0 "s_register_operand" "=r")
6152         (ge:SI (match_dup 1) (const_int 0)))]
6153   "TARGET_ARM"
6154   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6157 (define_expand "slt"
6158   [(set (match_operand:SI 0 "s_register_operand" "=r")
6159         (lt:SI (match_dup 1) (const_int 0)))]
6160   "TARGET_ARM"
6161   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6164 (define_expand "sgtu"
6165   [(set (match_operand:SI 0 "s_register_operand" "=r")
6166         (gtu:SI (match_dup 1) (const_int 0)))]
6167   "TARGET_ARM"
6168   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6171 (define_expand "sleu"
6172   [(set (match_operand:SI 0 "s_register_operand" "=r")
6173         (leu:SI (match_dup 1) (const_int 0)))]
6174   "TARGET_ARM"
6175   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6178 (define_expand "sgeu"
6179   [(set (match_operand:SI 0 "s_register_operand" "=r")
6180         (geu:SI (match_dup 1) (const_int 0)))]
6181   "TARGET_ARM"
6182   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6185 (define_expand "sltu"
6186   [(set (match_operand:SI 0 "s_register_operand" "=r")
6187         (ltu:SI (match_dup 1) (const_int 0)))]
6188   "TARGET_ARM"
6189   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6192 (define_expand "sunordered"
6193   [(set (match_operand:SI 0 "s_register_operand" "=r")
6194         (unordered:SI (match_dup 1) (const_int 0)))]
6195   "TARGET_ARM && TARGET_HARD_FLOAT"
6196   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6197                                       arm_compare_op1);"
6200 (define_expand "sordered"
6201   [(set (match_operand:SI 0 "s_register_operand" "=r")
6202         (ordered:SI (match_dup 1) (const_int 0)))]
6203   "TARGET_ARM && TARGET_HARD_FLOAT"
6204   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6205                                       arm_compare_op1);"
6208 (define_expand "sungt"
6209   [(set (match_operand:SI 0 "s_register_operand" "=r")
6210         (ungt:SI (match_dup 1) (const_int 0)))]
6211   "TARGET_ARM && TARGET_HARD_FLOAT"
6212   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6213                                       arm_compare_op1);"
6216 (define_expand "sunge"
6217   [(set (match_operand:SI 0 "s_register_operand" "=r")
6218         (unge:SI (match_dup 1) (const_int 0)))]
6219   "TARGET_ARM && TARGET_HARD_FLOAT"
6220   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6221                                       arm_compare_op1);"
6224 (define_expand "sunlt"
6225   [(set (match_operand:SI 0 "s_register_operand" "=r")
6226         (unlt:SI (match_dup 1) (const_int 0)))]
6227   "TARGET_ARM && TARGET_HARD_FLOAT"
6228   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6229                                       arm_compare_op1);"
6232 (define_expand "sunle"
6233   [(set (match_operand:SI 0 "s_register_operand" "=r")
6234         (unle:SI (match_dup 1) (const_int 0)))]
6235   "TARGET_ARM && TARGET_HARD_FLOAT"
6236   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6237                                       arm_compare_op1);"
6240 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6241 ;;; simple ARM instructions. 
6243 ; (define_expand "suneq"
6244 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6245 ;       (uneq:SI (match_dup 1) (const_int 0)))]
6246 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6247 ;   "abort ();"
6248 ; )
6250 ; (define_expand "sltgt"
6251 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6252 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
6253 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6254 ;   "abort ();"
6255 ; )
6257 (define_insn "*mov_scc"
6258   [(set (match_operand:SI 0 "s_register_operand" "=r")
6259         (match_operator:SI 1 "arm_comparison_operator"
6260          [(match_operand 2 "cc_register" "") (const_int 0)]))]
6261   "TARGET_ARM"
6262   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6263   [(set_attr "conds" "use")
6264    (set_attr "length" "8")]
6267 (define_insn "*mov_negscc"
6268   [(set (match_operand:SI 0 "s_register_operand" "=r")
6269         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6270                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6271   "TARGET_ARM"
6272   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6273   [(set_attr "conds" "use")
6274    (set_attr "length" "8")]
6277 (define_insn "*mov_notscc"
6278   [(set (match_operand:SI 0 "s_register_operand" "=r")
6279         (not:SI (match_operator:SI 1 "arm_comparison_operator"
6280                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6281   "TARGET_ARM"
6282   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6283   [(set_attr "conds" "use")
6284    (set_attr "length" "8")]
6288 ;; Conditional move insns
6290 (define_expand "movsicc"
6291   [(set (match_operand:SI 0 "s_register_operand" "")
6292         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6293                          (match_operand:SI 2 "arm_not_operand" "")
6294                          (match_operand:SI 3 "arm_not_operand" "")))]
6295   "TARGET_ARM"
6296   "
6297   {
6298     enum rtx_code code = GET_CODE (operands[1]);
6299     rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6301     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6302   }"
6305 (define_expand "movsfcc"
6306   [(set (match_operand:SF 0 "s_register_operand" "")
6307         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6308                          (match_operand:SF 2 "s_register_operand" "")
6309                          (match_operand:SF 3 "nonmemory_operand" "")))]
6310   "TARGET_ARM"
6311   "
6312   {
6313     enum rtx_code code = GET_CODE (operands[1]);
6314     rtx ccreg;
6316     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
6317        Otherwise, ensure it is a valid FP add operand */
6318     if ((!TARGET_HARD_FLOAT)
6319         || (!fpu_add_operand (operands[3], SFmode)))
6320       operands[3] = force_reg (SFmode, operands[3]);
6322     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6323     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6324   }"
6327 (define_expand "movdfcc"
6328   [(set (match_operand:DF 0 "s_register_operand" "")
6329         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6330                          (match_operand:DF 2 "s_register_operand" "")
6331                          (match_operand:DF 3 "fpu_add_operand" "")))]
6332   "TARGET_ARM && TARGET_HARD_FLOAT"
6333   "
6334   {
6335     enum rtx_code code = GET_CODE (operands[1]);
6336     rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6338     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6339   }"
6342 (define_insn "*movsicc_insn"
6343   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6344         (if_then_else:SI
6345          (match_operator 3 "arm_comparison_operator"
6346           [(match_operand 4 "cc_register" "") (const_int 0)])
6347          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6348          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6349   "TARGET_ARM"
6350   "@
6351    mov%D3\\t%0, %2
6352    mvn%D3\\t%0, #%B2
6353    mov%d3\\t%0, %1
6354    mvn%d3\\t%0, #%B1
6355    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6356    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6357    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6358    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6359   [(set_attr "length" "4,4,4,4,8,8,8,8")
6360    (set_attr "conds" "use")]
6363 (define_insn "*movsfcc_hard_insn"
6364   [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6365         (if_then_else:SF
6366          (match_operator 3 "arm_comparison_operator" 
6367           [(match_operand 4 "cc_register" "") (const_int 0)])
6368          (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6369          (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6370   "TARGET_ARM && TARGET_HARD_FLOAT"
6371   "@
6372    mvf%D3s\\t%0, %2
6373    mnf%D3s\\t%0, #%N2
6374    mvf%d3s\\t%0, %1
6375    mnf%d3s\\t%0, #%N1
6376    mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6377    mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6378    mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6379    mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6380   [(set_attr "length" "4,4,4,4,8,8,8,8")
6381    (set_attr "type" "ffarith")
6382    (set_attr "conds" "use")]
6385 (define_insn "*movsfcc_soft_insn"
6386   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6387         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6388                           [(match_operand 4 "cc_register" "") (const_int 0)])
6389                          (match_operand:SF 1 "s_register_operand" "0,r")
6390                          (match_operand:SF 2 "s_register_operand" "r,0")))]
6391   "TARGET_ARM && TARGET_SOFT_FLOAT"
6392   "@
6393    mov%D3\\t%0, %2
6394    mov%d3\\t%0, %1"
6395   [(set_attr "conds" "use")]
6398 (define_insn "*movdfcc_insn"
6399   [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6400         (if_then_else:DF
6401          (match_operator 3 "arm_comparison_operator"
6402           [(match_operand 4 "cc_register" "") (const_int 0)])
6403          (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6404          (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6405   "TARGET_ARM && TARGET_HARD_FLOAT"
6406   "@
6407    mvf%D3d\\t%0, %2
6408    mnf%D3d\\t%0, #%N2
6409    mvf%d3d\\t%0, %1
6410    mnf%d3d\\t%0, #%N1
6411    mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6412    mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6413    mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6414    mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6415   [(set_attr "length" "4,4,4,4,8,8,8,8")
6416    (set_attr "type" "ffarith")
6417    (set_attr "conds" "use")]
6421 ;; Jump and linkage insns
6423 (define_expand "jump"
6424   [(set (pc)
6425         (label_ref (match_operand 0 "" "")))]
6426   "TARGET_EITHER"
6427   ""
6430 (define_insn "*arm_jump"
6431   [(set (pc)
6432         (label_ref (match_operand 0 "" "")))]
6433   "TARGET_ARM"
6434   "*
6435   {
6436     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6437       {
6438         arm_ccfsm_state += 2;
6439         return \"\";
6440       }
6441     return \"b%?\\t%l0\";
6442   }
6443   "
6444   [(set_attr "predicable" "yes")]
6447 (define_insn "*thumb_jump"
6448   [(set (pc)
6449         (label_ref (match_operand 0 "" "")))]
6450   "TARGET_THUMB"
6451   "*
6452   if (get_attr_length (insn) == 2)
6453     return \"b\\t%l0\";
6454   return \"bl\\t%l0\\t%@ far jump\";
6455   "
6456   [(set (attr "far_jump")
6457         (if_then_else
6458             (eq_attr "length" "4")
6459             (const_string "yes")
6460             (const_string "no")))
6461    (set (attr "length") 
6462         (if_then_else
6463             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6464                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
6465             (const_int 2)
6466             (const_int 4)))]
6469 (define_expand "call"
6470   [(parallel [(call (match_operand 0 "memory_operand" "")
6471                     (match_operand 1 "general_operand" ""))
6472               (use (match_operand 2 "" ""))
6473               (clobber (reg:SI LR_REGNUM))])]
6474   "TARGET_EITHER"
6475   "
6476   {
6477     rtx callee;
6478     
6479     /* In an untyped call, we can get NULL for operand 2.  */
6480     if (operands[2] == NULL_RTX)
6481       operands[2] = const0_rtx;
6482       
6483     /* This is to decide if we should generate indirect calls by loading the
6484        32 bit address of the callee into a register before performing the
6485        branch and link.  operand[2] encodes the long_call/short_call
6486        attribute of the function being called.  This attribute is set whenever
6487        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6488        is used, and the short_call attribute can also be set if function is
6489        declared as static or if it has already been defined in the current
6490        compilation unit.  See arm.c and arm.h for info about this.  The third
6491        parameter to arm_is_longcall_p is used to tell it which pattern
6492        invoked it.  */
6493     callee  = XEXP (operands[0], 0);
6494     
6495     if (GET_CODE (callee) != REG
6496        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6497       XEXP (operands[0], 0) = force_reg (Pmode, callee);
6498   }"
6501 (define_insn "*call_reg"
6502   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6503          (match_operand 1 "" ""))
6504    (use (match_operand 2 "" ""))
6505    (clobber (reg:SI LR_REGNUM))]
6506   "TARGET_ARM"
6507   "*
6508   return output_call (operands);
6509   "
6510   ;; length is worst case, normally it is only two
6511   [(set_attr "length" "12")
6512    (set_attr "type" "call")]
6515 (define_insn "*call_mem"
6516   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6517          (match_operand 1 "" ""))
6518    (use (match_operand 2 "" ""))
6519    (clobber (reg:SI LR_REGNUM))]
6520   "TARGET_ARM"
6521   "*
6522   return output_call_mem (operands);
6523   "
6524   [(set_attr "length" "12")
6525    (set_attr "type" "call")]
6528 (define_insn "*call_indirect"
6529   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6530          (match_operand 1 "" ""))
6531    (use (match_operand 2 "" ""))
6532    (clobber (reg:SI LR_REGNUM))]
6533   "TARGET_THUMB"
6534   "*
6535   {
6536     if (TARGET_CALLER_INTERWORKING)
6537       return \"bl\\t%__interwork_call_via_%0\";
6538     else
6539       return \"bl\\t%__call_via_%0\";
6540   }"
6541   [(set_attr "type" "call")]
6544 (define_insn "*call_value_indirect"
6545   [(set (match_operand 0 "" "=l")
6546         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6547               (match_operand 2 "" "")))
6548    (use (match_operand 3 "" ""))
6549    (clobber (reg:SI LR_REGNUM))]
6550   "TARGET_THUMB"
6551   "*
6552   {
6553     if (TARGET_CALLER_INTERWORKING)
6554       return \"bl\\t%__interwork_call_via_%1\";
6555     else
6556       return \"bl\\t%__call_via_%1\";
6557   }"
6558   [(set_attr "type" "call")]
6561 (define_expand "call_value"
6562   [(parallel [(set (match_operand       0 "" "")
6563                    (call (match_operand 1 "memory_operand" "")
6564                          (match_operand 2 "general_operand" "")))
6565               (use (match_operand 3 "" ""))
6566               (clobber (reg:SI LR_REGNUM))])]
6567   "TARGET_EITHER"
6568   "
6569   {
6570     rtx callee = XEXP (operands[1], 0);
6571     
6572     /* In an untyped call, we can get NULL for operand 2.  */
6573     if (operands[3] == 0)
6574       operands[3] = const0_rtx;
6575       
6576     /* See the comment in define_expand \"call\".  */
6577     if (GET_CODE (callee) != REG
6578         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6579       XEXP (operands[1], 0) = force_reg (Pmode, callee);
6580   }"
6583 (define_insn "*call_value_reg"
6584   [(set (match_operand 0 "" "=r,f")
6585         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6586               (match_operand 2 "" "")))
6587    (use (match_operand 3 "" ""))
6588    (clobber (reg:SI LR_REGNUM))]
6589   "TARGET_ARM"
6590   "*
6591   return output_call (&operands[1]);
6592   "
6593   [(set_attr "length" "12")
6594    (set_attr "type" "call")]
6597 (define_insn "*call_value_mem"
6598   [(set (match_operand 0 "" "=r,f")
6599         (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6600               (match_operand 2 "" "")))
6601    (use (match_operand 3 "" ""))
6602    (clobber (reg:SI LR_REGNUM))]
6603   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6604   "*
6605   return output_call_mem (&operands[1]);
6606   "
6607   [(set_attr "length" "12")
6608    (set_attr "type" "call")]
6611 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6612 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6614 (define_insn "*call_symbol"
6615   [(call (mem:SI (match_operand:SI 0 "" "X"))
6616          (match_operand 1 "" ""))
6617    (use (match_operand 2 "" ""))
6618    (clobber (reg:SI LR_REGNUM))]
6619   "TARGET_ARM
6620    && (GET_CODE (operands[0]) == SYMBOL_REF)
6621    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6622   "*
6623   {
6624     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6625   }"
6626   [(set_attr "type" "call")]
6629 (define_insn "*call_value_symbol"
6630   [(set (match_operand 0 "s_register_operand" "=r,f")
6631         (call (mem:SI (match_operand:SI 1 "" "X,X"))
6632         (match_operand:SI 2 "" "")))
6633    (use (match_operand 3 "" ""))
6634    (clobber (reg:SI LR_REGNUM))]
6635   "TARGET_ARM
6636    && (GET_CODE (operands[1]) == SYMBOL_REF)
6637    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6638   "*
6639   {
6640     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6641   }"
6642   [(set_attr "type" "call")]
6645 (define_insn "*call_insn"
6646   [(call (mem:SI (match_operand:SI 0 "" "X"))
6647          (match_operand:SI 1 "" ""))
6648    (use (match_operand 2 "" ""))
6649    (clobber (reg:SI LR_REGNUM))]
6650   "TARGET_THUMB
6651    && operands[2] == const0_rtx && (GET_CODE (operands[0]) == SYMBOL_REF)"
6652   "bl\\t%a0"
6653   [(set_attr "length" "4")
6654    (set_attr "type" "call")]
6657 (define_insn "*call_value_insn"
6658   [(set (match_operand 0 "register_operand" "=l")
6659         (call (mem:SI (match_operand 1 "" "X"))
6660               (match_operand 2 "" "")))
6661    (use (match_operand 3 "" ""))
6662    (clobber (reg:SI LR_REGNUM))]
6663   "TARGET_THUMB
6664    && operands[3] == const0_rtx && (GET_CODE (operands[1]) == SYMBOL_REF)"
6665   "bl\\t%a1"
6666   [(set_attr "length" "4")
6667    (set_attr "type" "call")]
6670 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6671 (define_expand "sibcall"
6672   [(parallel [(call (match_operand 0 "memory_operand" "")
6673                     (match_operand 1 "general_operand" ""))
6674               (use (match_operand 2 "" ""))
6675               (use (reg:SI LR_REGNUM))])]
6676   "TARGET_ARM"
6677   "
6678   {
6679     if (operands[2] == NULL_RTX)
6680       operands[2] = const0_rtx;
6681   }"
6684 (define_expand "sibcall_value"
6685   [(parallel [(set (match_operand 0 "register_operand" "")
6686                    (call (match_operand 1 "memory_operand" "")
6687                          (match_operand 2 "general_operand" "")))
6688               (use (match_operand 3 "" ""))
6689               (use (reg:SI LR_REGNUM))])]
6690   "TARGET_ARM"
6691   "
6692   {
6693     if (operands[3] == NULL_RTX)
6694       operands[3] = const0_rtx;
6695   }"
6698 (define_insn "*sibcall_insn"
6699  [(call (mem:SI (match_operand:SI 0 "" "X"))
6700         (match_operand 1 "" ""))
6701   (use (match_operand 2 "" ""))
6702   (use (reg:SI LR_REGNUM))]
6703   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6704   "*
6705   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6706   "
6707   [(set_attr "type" "call")]
6710 (define_insn "*sibcall_value_insn"
6711  [(set (match_operand 0 "s_register_operand" "=r,f")
6712        (call (mem:SI (match_operand:SI 1 "" "X,X"))
6713              (match_operand 2 "" "")))
6714   (use (match_operand 3 "" ""))
6715   (use (reg:SI LR_REGNUM))]
6716   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6717   "*
6718   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6719   "
6720   [(set_attr "type" "call")]
6723 ;; Often the return insn will be the same as loading from memory, so set attr
6724 (define_insn "return"
6725   [(return)]
6726   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6727   "*
6728   {
6729     if (arm_ccfsm_state == 2)
6730       {
6731         arm_ccfsm_state += 2;
6732         return \"\";
6733       }
6734     return output_return_instruction (NULL, TRUE, FALSE);
6735   }"
6736   [(set_attr "type" "load")
6737    (set_attr "predicable" "yes")]
6740 (define_insn "*cond_return"
6741   [(set (pc)
6742         (if_then_else (match_operator 0 "arm_comparison_operator"
6743                        [(match_operand 1 "cc_register" "") (const_int 0)])
6744                       (return)
6745                       (pc)))]
6746   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6747   "*
6748   {
6749     if (arm_ccfsm_state == 2)
6750       {
6751         arm_ccfsm_state += 2;
6752         return \"\";
6753       }
6754     return output_return_instruction (operands[0], TRUE, FALSE);
6755   }"
6756   [(set_attr "conds" "use")
6757    (set_attr "type" "load")]
6760 (define_insn "*cond_return_inverted"
6761   [(set (pc)
6762         (if_then_else (match_operator 0 "arm_comparison_operator"
6763                        [(match_operand 1 "cc_register" "") (const_int 0)])
6764                       (pc)
6765                       (return)))]
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, TRUE);
6775   }"
6776   [(set_attr "conds" "use")
6777    (set_attr "type" "load")]
6780 ;; Call subroutine returning any type.
6782 (define_expand "untyped_call"
6783   [(parallel [(call (match_operand 0 "" "")
6784                     (const_int 0))
6785               (match_operand 1 "" "")
6786               (match_operand 2 "" "")])]
6787   "TARGET_ARM"
6788   "
6789   {
6790     int i;
6792     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6794     for (i = 0; i < XVECLEN (operands[2], 0); i++)
6795       {
6796         rtx set = XVECEXP (operands[2], 0, i);
6798         emit_move_insn (SET_DEST (set), SET_SRC (set));
6799       }
6801     /* The optimizer does not know that the call sets the function value
6802        registers we stored in the result block.  We avoid problems by
6803        claiming that all hard registers are used and clobbered at this
6804        point.  */
6805     emit_insn (gen_blockage ());
6807     DONE;
6808   }"
6811 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6812 ;; all of memory.  This blocks insns from being moved across this point.
6814 (define_insn "blockage"
6815   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6816   "TARGET_EITHER"
6817   ""
6818   [(set_attr "length" "0")
6819    (set_attr "type" "block")]
6822 (define_expand "casesi"
6823   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6824    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
6825    (match_operand:SI 2 "const_int_operand" "")  ; total range
6826    (match_operand:SI 3 "" "")                   ; table label
6827    (match_operand:SI 4 "" "")]                  ; Out of range label
6828   "TARGET_ARM"
6829   "
6830   {
6831     rtx reg;
6832     if (operands[1] != const0_rtx)
6833       {
6834         reg = gen_reg_rtx (SImode);
6836         emit_insn (gen_addsi3 (reg, operands[0],
6837                                GEN_INT (-INTVAL (operands[1]))));
6838         operands[0] = reg;
6839       }
6841     if (!const_ok_for_arm (INTVAL (operands[2])))
6842       operands[2] = force_reg (SImode, operands[2]);
6844     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6845                                          operands[4]));
6846     DONE;
6847   }"
6850 ;; The USE in this pattern is needed to tell flow analysis that this is
6851 ;; a CASESI insn.  It has no other purpose.
6852 (define_insn "casesi_internal"
6853   [(parallel [(set (pc)
6854                (if_then_else
6855                 (leu (match_operand:SI 0 "s_register_operand" "r")
6856                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
6857                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6858                                  (label_ref (match_operand 2 "" ""))))
6859                 (label_ref (match_operand 3 "" ""))))
6860               (clobber (reg:CC CC_REGNUM))
6861               (use (label_ref (match_dup 2)))])]
6862   "TARGET_ARM"
6863   "*
6864     if (flag_pic)
6865       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6866     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6867   "
6868   [(set_attr "conds" "clob")
6869    (set_attr "length" "12")]
6872 (define_expand "indirect_jump"
6873   [(set (pc)
6874         (match_operand:SI 0 "s_register_operand" ""))]
6875   "TARGET_EITHER"
6876   ""
6879 (define_insn "*arm_indirect_jump"
6880   [(set (pc)
6881         (match_operand:SI 0 "s_register_operand" "r"))]
6882   "TARGET_ARM"
6883   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6884   [(set_attr "predicable" "yes")]
6887 ;; Although not supported by the define_expand above,
6888 ;; cse/combine may generate this form.
6889 (define_insn "*load_indirect_jump"
6890   [(set (pc)
6891         (match_operand:SI 0 "memory_operand" "m"))]
6892   "TARGET_ARM"
6893   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6894   [(set_attr "type" "load")
6895    (set_attr "pool_range" "4096")
6896    (set_attr "neg_pool_range" "4084")
6897    (set_attr "predicable" "yes")]
6900 (define_insn "*thumb_indirect_jump"
6901   [(set (pc)
6902         (match_operand:SI 0 "register_operand" "l*r"))]
6903   "TARGET_THUMB"
6904   "mov\\tpc, %0"
6905   [(set_attr "conds" "clob")
6906    (set_attr "length" "2")]
6910 ;; Misc insns
6912 (define_insn "nop"
6913   [(const_int 0)]
6914   "TARGET_EITHER"
6915   "*
6916   if (TARGET_ARM)
6917     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6918   return  \"mov\\tr8, r8\";
6919   "
6920   [(set (attr "length")
6921         (if_then_else (eq_attr "is_thumb" "yes")
6922                       (const_int 2)
6923                       (const_int 4)))]
6927 ;; Patterns to allow combination of arithmetic, cond code and shifts
6929 (define_insn "*arith_shiftsi"
6930   [(set (match_operand:SI 0 "s_register_operand" "=r")
6931         (match_operator:SI 1 "shiftable_operator"
6932           [(match_operator:SI 3 "shift_operator"
6933              [(match_operand:SI 4 "s_register_operand" "r")
6934               (match_operand:SI 5 "reg_or_int_operand" "rI")])
6935            (match_operand:SI 2 "s_register_operand" "r")]))]
6936   "TARGET_ARM"
6937   "%i1%?\\t%0, %2, %4%S3"
6938   [(set_attr "predicable" "yes")
6939    (set_attr "shift" "4")
6940    ]
6943 (define_insn "*arith_shiftsi_compare0"
6944   [(set (reg:CC_NOOV CC_REGNUM)
6945         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6946                           [(match_operator:SI 3 "shift_operator"
6947                             [(match_operand:SI 4 "s_register_operand" "r")
6948                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6949                            (match_operand:SI 2 "s_register_operand" "r")])
6950                          (const_int 0)))
6951    (set (match_operand:SI 0 "s_register_operand" "=r")
6952         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6953                          (match_dup 2)]))]
6954   "TARGET_ARM"
6955   "%i1%?s\\t%0, %2, %4%S3"
6956   [(set_attr "conds" "set")
6957    (set_attr "shift" "4")
6958    ]
6961 (define_insn "*arith_shiftsi_compare0_scratch"
6962   [(set (reg:CC_NOOV CC_REGNUM)
6963         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6964                           [(match_operator:SI 3 "shift_operator"
6965                             [(match_operand:SI 4 "s_register_operand" "r")
6966                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6967                            (match_operand:SI 2 "s_register_operand" "r")])
6968                          (const_int 0)))
6969    (clobber (match_scratch:SI 0 "=r"))]
6970   "TARGET_ARM"
6971   "%i1%?s\\t%0, %2, %4%S3"
6972   [(set_attr "conds" "set")
6973    (set_attr "shift" "4")
6974    ]
6977 (define_insn "*sub_shiftsi"
6978   [(set (match_operand:SI 0 "s_register_operand" "=r")
6979         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6980                   (match_operator:SI 2 "shift_operator"
6981                    [(match_operand:SI 3 "s_register_operand" "r")
6982                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6983   "TARGET_ARM"
6984   "sub%?\\t%0, %1, %3%S2"
6985   [(set_attr "predicable" "yes")
6986    (set_attr "shift" "3")
6987    ]
6990 (define_insn "*sub_shiftsi_compare0"
6991   [(set (reg:CC_NOOV CC_REGNUM)
6992         (compare:CC_NOOV
6993          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6994                    (match_operator:SI 2 "shift_operator"
6995                     [(match_operand:SI 3 "s_register_operand" "r")
6996                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6997          (const_int 0)))
6998    (set (match_operand:SI 0 "s_register_operand" "=r")
6999         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7000                                                  (match_dup 4)])))]
7001   "TARGET_ARM"
7002   "sub%?s\\t%0, %1, %3%S2"
7003   [(set_attr "conds" "set")
7004    (set_attr "shift" "3") 
7005    ]
7008 (define_insn "*sub_shiftsi_compare0_scratch"
7009   [(set (reg:CC_NOOV CC_REGNUM)
7010         (compare:CC_NOOV
7011          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7012                    (match_operator:SI 2 "shift_operator"
7013                     [(match_operand:SI 3 "s_register_operand" "r")
7014                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7015          (const_int 0)))
7016    (clobber (match_scratch:SI 0 "=r"))]
7017   "TARGET_ARM"
7018   "sub%?s\\t%0, %1, %3%S2"
7019   [(set_attr "conds" "set")
7020    (set_attr "shift" "3") 
7021    ]
7024 ;; These variants of the above insns can occur if the first operand is the
7025 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
7026 ;; seem to be a way around it.  Most of the predicates have to be null
7027 ;; because the format can be generated part way through reload, so
7028 ;; if we don't match it as soon as it becomes available, reload doesn't know
7029 ;; how to reload pseudos that haven't got hard registers; the constraints will
7030 ;; sort everything out.
7032 (define_insn "*reload_mulsi3"
7033   [(set (match_operand:SI 0 "" "=&r")
7034         (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
7035                            [(match_operand:SI 3 "" "r")
7036                             (match_operand:SI 4 "" "rM")])
7037                           (match_operand:SI 2 "" "r"))
7038                  (match_operand:SI 1 "const_int_operand" "n")))]
7039   "TARGET_ARM && reload_in_progress"
7040   "*
7041   output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
7042   operands[2] = operands[1];
7043   operands[1] = operands[0];
7044   return output_add_immediate (operands);
7045   "
7046   [
7047    ; we have no idea how long the add_immediate is, it could be up to 4.
7048    (set_attr "length" "20")]
7051 (define_insn "*reload_mulsi_compare0"
7052   [(set (reg:CC_NOOV CC_REGNUM)
7053         (compare:CC_NOOV (plus:SI
7054                           (plus:SI 
7055                            (match_operator:SI 5 "shift_operator"
7056                             [(match_operand:SI 3 "" "r")
7057                              (match_operand:SI 4 "" "rM")])
7058                            (match_operand:SI 1 "" "r"))
7059                           (match_operand:SI 2 "const_int_operand" "n"))
7060                          (const_int 0)))
7061    (set (match_operand:SI 0 "" "=&r")
7062         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
7063                           (match_dup 1))
7064                  (match_dup 2)))]
7065   "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7066   "*
7067     output_add_immediate (operands);
7068     return \"add%?s\\t%0, %0, %3%S5\";
7069   "
7070   [(set_attr "conds" "set")
7071    (set_attr "shift" "3")
7072    (set_attr "length" "20")]
7075 (define_insn "*reload_mulsi_compare0_scratch"
7076   [(set (reg:CC_NOOV CC_REGNUM)
7077         (compare:CC_NOOV (plus:SI
7078                           (plus:SI 
7079                            (match_operator:SI 5 "shift_operator"
7080                             [(match_operand:SI 3 "" "r")
7081                              (match_operand:SI 4 "" "rM")])
7082                            (match_operand:SI 1 "" "r"))
7083                           (match_operand:SI 2 "const_int_operand" "n"))
7084                          (const_int 0)))
7085    (clobber (match_scratch:SI 0 "=&r"))]
7086   "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7087   "*
7088     output_add_immediate (operands);
7089     return \"add%?s\\t%0, %0, %3%S5\";
7090   "
7091   [(set_attr "conds" "set")
7092    (set_attr "shift" "3")
7093    (set_attr "length" "20")]
7096 ;; These are similar, but are needed when the mla pattern contains the
7097 ;; eliminated register as operand 3.
7099 (define_insn "*reload_muladdsi"
7100   [(set (match_operand:SI 0 "" "=&r,&r")
7101         (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
7102                                    (match_operand:SI 2 "" "r,r"))
7103                           (match_operand:SI 3 "" "r,r"))
7104                  (match_operand:SI 4 "const_int_operand" "n,n")))]
7105   "TARGET_ARM && reload_in_progress"
7106   "*
7107   output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
7108   operands[2] = operands[4];
7109   operands[1] = operands[0];
7110   return output_add_immediate (operands);
7111   "
7112   [(set_attr "length" "20")
7113    (set_attr "type" "mult")]
7116 (define_insn "*reload_muladdsi_compare0"
7117   [(set (reg:CC_NOOV CC_REGNUM)
7118         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7119                                             (match_operand:SI 3 "" "r")
7120                                             (match_operand:SI 4 "" "r"))
7121                                            (match_operand:SI 1 "" "r"))
7122                                   (match_operand:SI 2 "const_int_operand" "n"))
7123                          (const_int 0)))
7124    (set (match_operand:SI 0 "" "=&r")
7125         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
7126                  (match_dup 2)))]
7127   "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7128   "*
7129     output_add_immediate (operands);
7130     output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
7131     return \"\";
7132   "
7133   [(set_attr "length" "20")
7134    (set_attr "conds" "set")
7135    (set_attr "type" "mult")]
7138 (define_insn "*reload_muladdsi_compare0_scratch"
7139   [(set (reg:CC_NOOV CC_REGNUM)
7140         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7141                                             (match_operand:SI 3 "" "r")
7142                                             (match_operand:SI 4 "" "r"))
7143                                            (match_operand:SI 1 "" "r"))
7144                                   (match_operand:SI 2 "const_int_operand" "n"))
7145                          (const_int 0)))
7146    (clobber (match_scratch:SI 0 "=&r"))]
7147   "TARGET_ARM && reload_in_progress"
7148   "*
7149     output_add_immediate (operands);
7150     return \"mla%?s\\t%0, %3, %4, %0\";
7151   "
7152   [(set_attr "length" "20")
7153    (set_attr "conds" "set")
7154    (set_attr "type" "mult")]
7159 (define_insn "*and_scc"
7160   [(set (match_operand:SI 0 "s_register_operand" "=r")
7161         (and:SI (match_operator:SI 1 "arm_comparison_operator"
7162                  [(match_operand 3 "cc_register" "") (const_int 0)])
7163                 (match_operand:SI 2 "s_register_operand" "r")))]
7164   "TARGET_ARM"
7165   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7166   [(set_attr "conds" "use")
7167    (set_attr "length" "8")]
7170 (define_insn "*ior_scc"
7171   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7172         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7173                  [(match_operand 3 "cc_register" "") (const_int 0)])
7174                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7175   "TARGET_ARM"
7176   "@
7177    orr%d2\\t%0, %1, #1
7178    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7179   [(set_attr "conds" "use")
7180    (set_attr "length" "4,8")]
7183 (define_insn "*compare_scc"
7184   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7185         (match_operator:SI 1 "arm_comparison_operator"
7186          [(match_operand:SI 2 "s_register_operand" "r,r")
7187           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7188    (clobber (reg:CC CC_REGNUM))]
7189   "TARGET_ARM"
7190   "*
7191     if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7192       return \"mov\\t%0, %2, lsr #31\";
7194     if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7195       return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7197     if (GET_CODE (operands[1]) == NE)
7198       {
7199         if (which_alternative == 1)
7200           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7201         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7202       }
7203     if (which_alternative == 1)
7204       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7205     else
7206       output_asm_insn (\"cmp\\t%2, %3\", operands);
7207     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7208   "
7209   [(set_attr "conds" "clob")
7210    (set_attr "length" "12")]
7213 (define_insn "*cond_move"
7214   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7215         (if_then_else:SI (match_operator 3 "equality_operator"
7216                           [(match_operator 4 "arm_comparison_operator"
7217                             [(match_operand 5 "cc_register" "") (const_int 0)])
7218                            (const_int 0)])
7219                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7220                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7221   "TARGET_ARM"
7222   "*
7223     if (GET_CODE (operands[3]) == NE)
7224       {
7225         if (which_alternative != 1)
7226           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7227         if (which_alternative != 0)
7228           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7229         return \"\";
7230       }
7231     if (which_alternative != 0)
7232       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7233     if (which_alternative != 1)
7234       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7235     return \"\";
7236   "
7237   [(set_attr "conds" "use")
7238    (set_attr "length" "4,4,8")]
7241 (define_insn "*cond_arith"
7242   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7243         (match_operator:SI 5 "shiftable_operator" 
7244          [(match_operator:SI 4 "arm_comparison_operator"
7245            [(match_operand:SI 2 "s_register_operand" "r,r")
7246             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7247           (match_operand:SI 1 "s_register_operand" "0,?r")]))
7248    (clobber (reg:CC CC_REGNUM))]
7249   "TARGET_ARM"
7250   "*
7251     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7252       return \"%i5\\t%0, %1, %2, lsr #31\";
7254     output_asm_insn (\"cmp\\t%2, %3\", operands);
7255     if (GET_CODE (operands[5]) == AND)
7256       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7257     else if (GET_CODE (operands[5]) == MINUS)
7258       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7259     else if (which_alternative != 0)
7260       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7261     return \"%i5%d4\\t%0, %1, #1\";
7262   "
7263   [(set_attr "conds" "clob")
7264    (set_attr "length" "12")]
7267 (define_insn "*cond_sub"
7268   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7269         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7270                   (match_operator:SI 4 "arm_comparison_operator"
7271                    [(match_operand:SI 2 "s_register_operand" "r,r")
7272                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7273    (clobber (reg:CC CC_REGNUM))]
7274   "TARGET_ARM"
7275   "*
7276     output_asm_insn (\"cmp\\t%2, %3\", operands);
7277     if (which_alternative != 0)
7278       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7279     return \"sub%d4\\t%0, %1, #1\";
7280   "
7281   [(set_attr "conds" "clob")
7282    (set_attr "length" "8,12")]
7285 (define_insn "*cmp_ite0"
7286   [(set (match_operand 6 "dominant_cc_register" "")
7287         (compare
7288          (if_then_else:SI
7289           (match_operator 4 "arm_comparison_operator"
7290            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7291             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7292           (match_operator:SI 5 "arm_comparison_operator"
7293            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7294             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7295           (const_int 0))
7296          (const_int 0)))]
7297   "TARGET_ARM"
7298   "*
7299   {
7300     static const char * const opcodes[4][2] =
7301     {
7302       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7303        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7304       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7305        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7306       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7307        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7308       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7309        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7310     };
7311     int swap =
7312       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7314     return opcodes[which_alternative][swap];
7315   }"
7316   [(set_attr "conds" "set")
7317    (set_attr "length" "8")]
7320 (define_insn "*cmp_ite1"
7321   [(set (match_operand 6 "dominant_cc_register" "")
7322         (compare
7323          (if_then_else:SI
7324           (match_operator 4 "arm_comparison_operator"
7325            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7326             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7327           (match_operator:SI 5 "arm_comparison_operator"
7328            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7329             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7330           (const_int 1))
7331          (const_int 0)))]
7332   "TARGET_ARM"
7333   "*
7334   {
7335     static const char * const opcodes[4][2] =
7336     {
7337       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7338        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7339       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7340        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7341       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7342        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7343       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7344        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7345     };
7346     int swap =
7347       comparison_dominates_p (GET_CODE (operands[5]),
7348                               reverse_condition (GET_CODE (operands[4])));
7350     return opcodes[which_alternative][swap];
7351   }"
7352   [(set_attr "conds" "set")
7353    (set_attr "length" "8")]
7356 (define_insn "*cmp_and"
7357   [(set (match_operand 6 "dominant_cc_register" "")
7358         (compare
7359          (and:SI
7360           (match_operator 4 "arm_comparison_operator"
7361            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7362             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7363           (match_operator:SI 5 "arm_comparison_operator"
7364            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7365             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7366          (const_int 0)))]
7367   "TARGET_ARM"
7368   "*
7369   {
7370     const char * opcodes[4][2] =
7371     {
7372       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7373        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7374       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7375        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7376       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7377        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7378       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7379        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7380     };
7381     int swap =
7382       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7384     return opcodes[which_alternative][swap];
7385   }"
7386   [(set_attr "conds" "set")
7387    (set_attr "predicable" "no")
7388    (set_attr "length" "8")]
7391 (define_insn "*cmp_ior"
7392   [(set (match_operand 6 "dominant_cc_register" "")
7393         (compare
7394          (ior:SI
7395           (match_operator 4 "arm_comparison_operator"
7396            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7397             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7398           (match_operator:SI 5 "arm_comparison_operator"
7399            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7400             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7401          (const_int 0)))]
7402   "TARGET_ARM"
7403   "*
7405   const char * opcodes[4][2] =
7406   {
7407     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7408      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7409     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7410      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7411     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7412      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7413     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7414      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7415   };
7416   int swap =
7417     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7419   return opcodes[which_alternative][swap];
7422   [(set_attr "conds" "set")
7423    (set_attr "length" "8")]
7426 (define_insn "*negscc"
7427   [(set (match_operand:SI 0 "s_register_operand" "=r")
7428         (neg:SI (match_operator 3 "arm_comparison_operator"
7429                  [(match_operand:SI 1 "s_register_operand" "r")
7430                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7431    (clobber (reg:CC CC_REGNUM))]
7432   "TARGET_ARM"
7433   "*
7434   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7435     return \"mov\\t%0, %1, asr #31\";
7437   if (GET_CODE (operands[3]) == NE)
7438     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7440   if (GET_CODE (operands[3]) == GT)
7441     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7443   output_asm_insn (\"cmp\\t%1, %2\", operands);
7444   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7445   return \"mvn%d3\\t%0, #0\";
7446   "
7447   [(set_attr "conds" "clob")
7448    (set_attr "length" "12")]
7451 (define_insn "movcond"
7452   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7453         (if_then_else:SI
7454          (match_operator 5 "arm_comparison_operator"
7455           [(match_operand:SI 3 "s_register_operand" "r,r,r")
7456            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7457          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7458          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7459    (clobber (reg:CC CC_REGNUM))]
7460   "TARGET_ARM"
7461   "*
7462   if (GET_CODE (operands[5]) == LT
7463       && (operands[4] == const0_rtx))
7464     {
7465       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7466         {
7467           if (operands[2] == const0_rtx)
7468             return \"and\\t%0, %1, %3, asr #31\";
7469           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7470         }
7471       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7472         {
7473           if (operands[1] == const0_rtx)
7474             return \"bic\\t%0, %2, %3, asr #31\";
7475           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7476         }
7477       /* The only case that falls through to here is when both ops 1 & 2
7478          are constants */
7479     }
7481   if (GET_CODE (operands[5]) == GE
7482       && (operands[4] == const0_rtx))
7483     {
7484       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7485         {
7486           if (operands[2] == const0_rtx)
7487             return \"bic\\t%0, %1, %3, asr #31\";
7488           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7489         }
7490       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7491         {
7492           if (operands[1] == const0_rtx)
7493             return \"and\\t%0, %2, %3, asr #31\";
7494           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7495         }
7496       /* The only case that falls through to here is when both ops 1 & 2
7497          are constants */
7498     }
7499   if (GET_CODE (operands[4]) == CONST_INT
7500       && !const_ok_for_arm (INTVAL (operands[4])))
7501     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7502   else
7503     output_asm_insn (\"cmp\\t%3, %4\", operands);
7504   if (which_alternative != 0)
7505     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7506   if (which_alternative != 1)
7507     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7508   return \"\";
7509   "
7510   [(set_attr "conds" "clob")
7511    (set_attr "length" "8,8,12")]
7514 (define_insn "*ifcompare_plus_move"
7515   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7516         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7517                           [(match_operand:SI 4 "s_register_operand" "r,r")
7518                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7519                          (plus:SI
7520                           (match_operand:SI 2 "s_register_operand" "r,r")
7521                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7522                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7523    (clobber (reg:CC CC_REGNUM))]
7524   "TARGET_ARM"
7525   "#"
7526   [(set_attr "conds" "clob")
7527    (set_attr "length" "8,12")]
7530 (define_insn "*if_plus_move"
7531   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7532         (if_then_else:SI
7533          (match_operator 4 "arm_comparison_operator"
7534           [(match_operand 5 "cc_register" "") (const_int 0)])
7535          (plus:SI
7536           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7537           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7538          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7539   "TARGET_ARM"
7540   "@
7541    add%d4\\t%0, %2, %3
7542    sub%d4\\t%0, %2, #%n3
7543    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7544    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7545   [(set_attr "conds" "use")
7546    (set_attr "length" "4,4,8,8")
7547    (set_attr "type" "*,*,*,*")]
7550 (define_insn "*ifcompare_move_plus"
7551   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7552         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7553                           [(match_operand:SI 4 "s_register_operand" "r,r")
7554                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7555                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7556                          (plus:SI
7557                           (match_operand:SI 2 "s_register_operand" "r,r")
7558                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7559    (clobber (reg:CC CC_REGNUM))]
7560   "TARGET_ARM"
7561   "#"
7562   [(set_attr "conds" "clob")
7563    (set_attr "length" "8,12")]
7566 (define_insn "*if_move_plus"
7567   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7568         (if_then_else:SI
7569          (match_operator 4 "arm_comparison_operator"
7570           [(match_operand 5 "cc_register" "") (const_int 0)])
7571          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7572          (plus:SI
7573           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7574           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7575   "TARGET_ARM"
7576   "@
7577    add%D4\\t%0, %2, %3
7578    sub%D4\\t%0, %2, #%n3
7579    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7580    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7581   [(set_attr "conds" "use")
7582    (set_attr "length" "4,4,8,8")
7583    (set_attr "type" "*,*,*,*")]
7586 (define_insn "*ifcompare_arith_arith"
7587   [(set (match_operand:SI 0 "s_register_operand" "=r")
7588         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7589                           [(match_operand:SI 5 "s_register_operand" "r")
7590                            (match_operand:SI 6 "arm_add_operand" "rIL")])
7591                          (match_operator:SI 8 "shiftable_operator"
7592                           [(match_operand:SI 1 "s_register_operand" "r")
7593                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7594                          (match_operator:SI 7 "shiftable_operator"
7595                           [(match_operand:SI 3 "s_register_operand" "r")
7596                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7597    (clobber (reg:CC CC_REGNUM))]
7598   "TARGET_ARM"
7599   "#"
7600   [(set_attr "conds" "clob")
7601    (set_attr "length" "12")]
7604 (define_insn "*if_arith_arith"
7605   [(set (match_operand:SI 0 "s_register_operand" "=r")
7606         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7607                           [(match_operand 8 "cc_register" "") (const_int 0)])
7608                          (match_operator:SI 6 "shiftable_operator"
7609                           [(match_operand:SI 1 "s_register_operand" "r")
7610                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7611                          (match_operator:SI 7 "shiftable_operator"
7612                           [(match_operand:SI 3 "s_register_operand" "r")
7613                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7614   "TARGET_ARM"
7615   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7616   [(set_attr "conds" "use")
7617    (set_attr "length" "8")]
7620 (define_insn "*ifcompare_arith_move"
7621   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7622         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7623                           [(match_operand:SI 2 "s_register_operand" "r,r")
7624                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7625                          (match_operator:SI 7 "shiftable_operator"
7626                           [(match_operand:SI 4 "s_register_operand" "r,r")
7627                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7628                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7629    (clobber (reg:CC CC_REGNUM))]
7630   "TARGET_ARM"
7631   "*
7632   /* If we have an operation where (op x 0) is the identity operation and
7633      the conditional operator is LT or GE and we are comparing against zero and
7634      everything is in registers then we can do this in two instructions */
7635   if (operands[3] == const0_rtx
7636       && GET_CODE (operands[7]) != AND
7637       && GET_CODE (operands[5]) == REG
7638       && GET_CODE (operands[1]) == REG 
7639       && REGNO (operands[1]) == REGNO (operands[4])
7640       && REGNO (operands[4]) != REGNO (operands[0]))
7641     {
7642       if (GET_CODE (operands[6]) == LT)
7643         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7644       else if (GET_CODE (operands[6]) == GE)
7645         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7646     }
7647   if (GET_CODE (operands[3]) == CONST_INT
7648       && !const_ok_for_arm (INTVAL (operands[3])))
7649     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7650   else
7651     output_asm_insn (\"cmp\\t%2, %3\", operands);
7652   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7653   if (which_alternative != 0)
7654     return \"mov%D6\\t%0, %1\";
7655   return \"\";
7656   "
7657   [(set_attr "conds" "clob")
7658    (set_attr "length" "8,12")]
7661 (define_insn "*if_arith_move"
7662   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7663         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7664                           [(match_operand 6 "cc_register" "") (const_int 0)])
7665                          (match_operator:SI 5 "shiftable_operator"
7666                           [(match_operand:SI 2 "s_register_operand" "r,r")
7667                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7668                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7669   "TARGET_ARM"
7670   "@
7671    %I5%d4\\t%0, %2, %3
7672    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7673   [(set_attr "conds" "use")
7674    (set_attr "length" "4,8")
7675    (set_attr "type" "*,*")]
7678 (define_insn "*ifcompare_move_arith"
7679   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7680         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7681                           [(match_operand:SI 4 "s_register_operand" "r,r")
7682                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7683                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7684                          (match_operator:SI 7 "shiftable_operator"
7685                           [(match_operand:SI 2 "s_register_operand" "r,r")
7686                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7687    (clobber (reg:CC CC_REGNUM))]
7688   "TARGET_ARM"
7689   "*
7690   /* If we have an operation where (op x 0) is the identity operation and
7691      the conditional operator is LT or GE and we are comparing against zero and
7692      everything is in registers then we can do this in two instructions */
7693   if (operands[5] == const0_rtx
7694       && GET_CODE (operands[7]) != AND
7695       && GET_CODE (operands[3]) == REG
7696       && GET_CODE (operands[1]) == REG 
7697       && REGNO (operands[1]) == REGNO (operands[2])
7698       && REGNO (operands[2]) != REGNO (operands[0]))
7699     {
7700       if (GET_CODE (operands[6]) == GE)
7701         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7702       else if (GET_CODE (operands[6]) == LT)
7703         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7704     }
7706   if (GET_CODE (operands[5]) == CONST_INT
7707       && !const_ok_for_arm (INTVAL (operands[5])))
7708     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7709   else
7710     output_asm_insn (\"cmp\\t%4, %5\", operands);
7712   if (which_alternative != 0)
7713     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7714   return \"%I7%D6\\t%0, %2, %3\";
7715   "
7716   [(set_attr "conds" "clob")
7717    (set_attr "length" "8,12")]
7720 (define_insn "*if_move_arith"
7721   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7722         (if_then_else:SI
7723          (match_operator 4 "arm_comparison_operator"
7724           [(match_operand 6 "cc_register" "") (const_int 0)])
7725          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7726          (match_operator:SI 5 "shiftable_operator"
7727           [(match_operand:SI 2 "s_register_operand" "r,r")
7728            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7729   "TARGET_ARM"
7730   "@
7731    %I5%D4\\t%0, %2, %3
7732    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7733   [(set_attr "conds" "use")
7734    (set_attr "length" "4,8")
7735    (set_attr "type" "*,*")]
7738 (define_insn "*ifcompare_move_not"
7739   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7740         (if_then_else:SI
7741          (match_operator 5 "arm_comparison_operator"
7742           [(match_operand:SI 3 "s_register_operand" "r,r")
7743            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7744          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7745          (not:SI
7746           (match_operand:SI 2 "s_register_operand" "r,r"))))
7747    (clobber (reg:CC CC_REGNUM))]
7748   "TARGET_ARM"
7749   "#"
7750   [(set_attr "conds" "clob")
7751    (set_attr "length" "8,12")]
7754 (define_insn "*if_move_not"
7755   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7756         (if_then_else:SI
7757          (match_operator 4 "arm_comparison_operator"
7758           [(match_operand 3 "cc_register" "") (const_int 0)])
7759          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7760          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7761   "TARGET_ARM"
7762   "@
7763    mvn%D4\\t%0, %2
7764    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7765    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7766   [(set_attr "conds" "use")
7767    (set_attr "length" "4,8,8")]
7770 (define_insn "*ifcompare_not_move"
7771   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7772         (if_then_else:SI 
7773          (match_operator 5 "arm_comparison_operator"
7774           [(match_operand:SI 3 "s_register_operand" "r,r")
7775            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7776          (not:SI
7777           (match_operand:SI 2 "s_register_operand" "r,r"))
7778          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7779    (clobber (reg:CC CC_REGNUM))]
7780   "TARGET_ARM"
7781   "#"
7782   [(set_attr "conds" "clob")
7783    (set_attr "length" "8,12")]
7786 (define_insn "*if_not_move"
7787   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7788         (if_then_else:SI
7789          (match_operator 4 "arm_comparison_operator"
7790           [(match_operand 3 "cc_register" "") (const_int 0)])
7791          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7792          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7793   "TARGET_ARM"
7794   "@
7795    mvn%d4\\t%0, %2
7796    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7797    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7798   [(set_attr "conds" "use")
7799    (set_attr "length" "4,8,8")]
7802 (define_insn "*ifcompare_shift_move"
7803   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7804         (if_then_else:SI
7805          (match_operator 6 "arm_comparison_operator"
7806           [(match_operand:SI 4 "s_register_operand" "r,r")
7807            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7808          (match_operator:SI 7 "shift_operator"
7809           [(match_operand:SI 2 "s_register_operand" "r,r")
7810            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7811          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7812    (clobber (reg:CC CC_REGNUM))]
7813   "TARGET_ARM"
7814   "#"
7815   [(set_attr "conds" "clob")
7816    (set_attr "length" "8,12")]
7819 (define_insn "*if_shift_move"
7820   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7821         (if_then_else:SI
7822          (match_operator 5 "arm_comparison_operator"
7823           [(match_operand 6 "cc_register" "") (const_int 0)])
7824          (match_operator:SI 4 "shift_operator"
7825           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7826            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7827          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7828   "TARGET_ARM"
7829   "@
7830    mov%d5\\t%0, %2%S4
7831    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7832    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7833   [(set_attr "conds" "use")
7834    (set_attr "shift" "2")
7835    (set_attr "length" "4,8,8")]
7838 (define_insn "*ifcompare_move_shift"
7839   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7840         (if_then_else:SI
7841          (match_operator 6 "arm_comparison_operator"
7842           [(match_operand:SI 4 "s_register_operand" "r,r")
7843            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7844          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7845          (match_operator:SI 7 "shift_operator"
7846           [(match_operand:SI 2 "s_register_operand" "r,r")
7847            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7848    (clobber (reg:CC CC_REGNUM))]
7849   "TARGET_ARM"
7850   "#"
7851   [(set_attr "conds" "clob")
7852    (set_attr "length" "8,12")]
7855 (define_insn "*if_move_shift"
7856   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7857         (if_then_else:SI
7858          (match_operator 5 "arm_comparison_operator"
7859           [(match_operand 6 "cc_register" "") (const_int 0)])
7860          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7861          (match_operator:SI 4 "shift_operator"
7862           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7863            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7864   "TARGET_ARM"
7865   "@
7866    mov%D5\\t%0, %2%S4
7867    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7868    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7869   [(set_attr "conds" "use")
7870    (set_attr "shift" "2")
7871    (set_attr "length" "4,8,8")]
7874 (define_insn "*ifcompare_shift_shift"
7875   [(set (match_operand:SI 0 "s_register_operand" "=r")
7876         (if_then_else:SI
7877          (match_operator 7 "arm_comparison_operator"
7878           [(match_operand:SI 5 "s_register_operand" "r")
7879            (match_operand:SI 6 "arm_add_operand" "rIL")])
7880          (match_operator:SI 8 "shift_operator"
7881           [(match_operand:SI 1 "s_register_operand" "r")
7882            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7883          (match_operator:SI 9 "shift_operator"
7884           [(match_operand:SI 3 "s_register_operand" "r")
7885            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7886    (clobber (reg:CC CC_REGNUM))]
7887   "TARGET_ARM"
7888   "#"
7889   [(set_attr "conds" "clob")
7890    (set_attr "length" "12")]
7893 (define_insn "*if_shift_shift"
7894   [(set (match_operand:SI 0 "s_register_operand" "=r")
7895         (if_then_else:SI
7896          (match_operator 5 "arm_comparison_operator"
7897           [(match_operand 8 "cc_register" "") (const_int 0)])
7898          (match_operator:SI 6 "shift_operator"
7899           [(match_operand:SI 1 "s_register_operand" "r")
7900            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7901          (match_operator:SI 7 "shift_operator"
7902           [(match_operand:SI 3 "s_register_operand" "r")
7903            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7904   "TARGET_ARM"
7905   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7906   [(set_attr "conds" "use")
7907    (set_attr "shift" "1")
7908    (set_attr "length" "8")]
7911 (define_insn "*ifcompare_not_arith"
7912   [(set (match_operand:SI 0 "s_register_operand" "=r")
7913         (if_then_else:SI
7914          (match_operator 6 "arm_comparison_operator"
7915           [(match_operand:SI 4 "s_register_operand" "r")
7916            (match_operand:SI 5 "arm_add_operand" "rIL")])
7917          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7918          (match_operator:SI 7 "shiftable_operator"
7919           [(match_operand:SI 2 "s_register_operand" "r")
7920            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7921    (clobber (reg:CC CC_REGNUM))]
7922   "TARGET_ARM"
7923   "#"
7924   [(set_attr "conds" "clob")
7925    (set_attr "length" "12")]
7928 (define_insn "*if_not_arith"
7929   [(set (match_operand:SI 0 "s_register_operand" "=r")
7930         (if_then_else:SI
7931          (match_operator 5 "arm_comparison_operator"
7932           [(match_operand 4 "cc_register" "") (const_int 0)])
7933          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7934          (match_operator:SI 6 "shiftable_operator"
7935           [(match_operand:SI 2 "s_register_operand" "r")
7936            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7937   "TARGET_ARM"
7938   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7939   [(set_attr "conds" "use")
7940    (set_attr "length" "8")]
7943 (define_insn "*ifcompare_arith_not"
7944   [(set (match_operand:SI 0 "s_register_operand" "=r")
7945         (if_then_else:SI
7946          (match_operator 6 "arm_comparison_operator"
7947           [(match_operand:SI 4 "s_register_operand" "r")
7948            (match_operand:SI 5 "arm_add_operand" "rIL")])
7949          (match_operator:SI 7 "shiftable_operator"
7950           [(match_operand:SI 2 "s_register_operand" "r")
7951            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7952          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7953    (clobber (reg:CC CC_REGNUM))]
7954   "TARGET_ARM"
7955   "#"
7956   [(set_attr "conds" "clob")
7957    (set_attr "length" "12")]
7960 (define_insn "*if_arith_not"
7961   [(set (match_operand:SI 0 "s_register_operand" "=r")
7962         (if_then_else:SI
7963          (match_operator 5 "arm_comparison_operator"
7964           [(match_operand 4 "cc_register" "") (const_int 0)])
7965          (match_operator:SI 6 "shiftable_operator"
7966           [(match_operand:SI 2 "s_register_operand" "r")
7967            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7968          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7969   "TARGET_ARM"
7970   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7971   [(set_attr "conds" "use")
7972    (set_attr "length" "8")]
7975 (define_insn "*ifcompare_neg_move"
7976   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7977         (if_then_else:SI
7978          (match_operator 5 "arm_comparison_operator"
7979           [(match_operand:SI 3 "s_register_operand" "r,r")
7980            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7981          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7982          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7983    (clobber (reg:CC CC_REGNUM))]
7984   "TARGET_ARM"
7985   "#"
7986   [(set_attr "conds" "clob")
7987    (set_attr "length" "8,12")]
7990 (define_insn "*if_neg_move"
7991   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7992         (if_then_else:SI
7993          (match_operator 4 "arm_comparison_operator"
7994           [(match_operand 3 "cc_register" "") (const_int 0)])
7995          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7996          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7997   "TARGET_ARM"
7998   "@
7999    rsb%d4\\t%0, %2, #0
8000    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8001    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8002   [(set_attr "conds" "use")
8003    (set_attr "length" "4,8,8")]
8006 (define_insn "*ifcompare_move_neg"
8007   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8008         (if_then_else:SI
8009          (match_operator 5 "arm_comparison_operator"
8010           [(match_operand:SI 3 "s_register_operand" "r,r")
8011            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8012          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8013          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8014    (clobber (reg:CC CC_REGNUM))]
8015   "TARGET_ARM"
8016   "#"
8017   [(set_attr "conds" "clob")
8018    (set_attr "length" "8,12")]
8021 (define_insn "*if_move_neg"
8022   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8023         (if_then_else:SI
8024          (match_operator 4 "arm_comparison_operator"
8025           [(match_operand 3 "cc_register" "") (const_int 0)])
8026          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8027          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8028   "TARGET_ARM"
8029   "@
8030    rsb%D4\\t%0, %2, #0
8031    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8032    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8033   [(set_attr "conds" "use")
8034    (set_attr "length" "4,8,8")]
8037 (define_insn "*arith_adjacentmem"
8038   [(set (match_operand:SI 0 "s_register_operand" "=r")
8039         (match_operator:SI 1 "shiftable_operator"
8040          [(match_operand:SI 2 "memory_operand" "m")
8041           (match_operand:SI 3 "memory_operand" "m")]))
8042    (clobber (match_scratch:SI 4 "=r"))]
8043   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8044   "*
8045   {
8046     rtx ldm[3];
8047     rtx arith[4];
8048     int val1 = 0, val2 = 0;
8050     if (REGNO (operands[0]) > REGNO (operands[4]))
8051       {
8052         ldm[1] = operands[4];
8053         ldm[2] = operands[0];
8054       }
8055     else
8056       {
8057         ldm[1] = operands[0];
8058         ldm[2] = operands[4];
8059       }
8060     if (GET_CODE (XEXP (operands[2], 0)) != REG)
8061       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8062     if (GET_CODE (XEXP (operands[3], 0)) != REG)
8063       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8064     arith[0] = operands[0];
8065     arith[3] = operands[1];
8066     if (val1 < val2)
8067       {
8068         arith[1] = ldm[1];
8069         arith[2] = ldm[2];
8070       }
8071     else
8072       {
8073         arith[1] = ldm[2];
8074         arith[2] = ldm[1];
8075       }
8076    if (val1 && val2)
8077       {
8078         rtx ops[3];
8079         ldm[0] = ops[0] = operands[4];
8080         ops[1] = XEXP (XEXP (operands[2], 0), 0);
8081         ops[2] = XEXP (XEXP (operands[2], 0), 1);
8082         output_add_immediate (ops);
8083         if (val1 < val2)
8084           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8085         else
8086           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8087       }
8088     else if (val1)
8089       {
8090         ldm[0] = XEXP (operands[3], 0);
8091         if (val1 < val2)
8092           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8093         else
8094           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8095       }
8096     else
8097       {
8098         ldm[0] = XEXP (operands[2], 0);
8099         if (val1 < val2)
8100           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8101         else
8102           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8103       }
8104     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8105     return \"\";
8106   }"
8107   [(set_attr "length" "12")
8108    (set_attr "predicable" "yes")
8109    (set_attr "type" "load")]
8112 ;; the arm can support extended pre-inc instructions
8114 ;; In all these cases, we use operands 0 and 1 for the register being
8115 ;; incremented because those are the operands that local-alloc will
8116 ;; tie and these are the pair most likely to be tieable (and the ones
8117 ;; that will benefit the most).
8119 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8120 ;; elimination will cause too many headaches.
8122 (define_insn "*strqi_preinc"
8123   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8124                          (match_operand:SI 2 "index_operand" "rJ")))
8125         (match_operand:QI 3 "s_register_operand" "r"))
8126    (set (match_operand:SI 0 "s_register_operand" "=r")
8127         (plus:SI (match_dup 1) (match_dup 2)))]
8128   "TARGET_ARM
8129    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8130    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8131    && (GET_CODE (operands[2]) != REG
8132        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8133   "str%?b\\t%3, [%0, %2]!"
8134   [(set_attr "type" "store1")
8135    (set_attr "predicable" "yes")]
8138 (define_insn "*strqi_predec"
8139   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8140                           (match_operand:SI 2 "s_register_operand" "r")))
8141         (match_operand:QI 3 "s_register_operand" "r"))
8142    (set (match_operand:SI 0 "s_register_operand" "=r")
8143         (minus:SI (match_dup 1) (match_dup 2)))]
8144   "TARGET_ARM
8145    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8146    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8147    && (GET_CODE (operands[2]) != REG
8148        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8149   "str%?b\\t%3, [%0, -%2]!"
8150   [(set_attr "type" "store1")
8151    (set_attr "predicable" "yes")]
8154 (define_insn "*loadqi_preinc"
8155   [(set (match_operand:QI 3 "s_register_operand" "=r")
8156         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8157                          (match_operand:SI 2 "index_operand" "rJ"))))
8158    (set (match_operand:SI 0 "s_register_operand" "=r")
8159         (plus:SI (match_dup 1) (match_dup 2)))]
8160   "TARGET_ARM
8161    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8162    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8163    && (GET_CODE (operands[2]) != REG
8164        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8165   "ldr%?b\\t%3, [%0, %2]!"
8166   [(set_attr "type" "load")
8167    (set_attr "predicable" "yes")]
8170 (define_insn "*loadqi_predec"
8171   [(set (match_operand:QI 3 "s_register_operand" "=r")
8172         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8173                           (match_operand:SI 2 "s_register_operand" "r"))))
8174    (set (match_operand:SI 0 "s_register_operand" "=r")
8175         (minus:SI (match_dup 1) (match_dup 2)))]
8176   "TARGET_ARM
8177    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8178    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8179    && (GET_CODE (operands[2]) != REG
8180        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8181   "ldr%?b\\t%3, [%0, -%2]!"
8182   [(set_attr "type" "load")
8183    (set_attr "predicable" "yes")]
8186 (define_insn "*loadqisi_preinc"
8187   [(set (match_operand:SI 3 "s_register_operand" "=r")
8188         (zero_extend:SI
8189          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8190                           (match_operand:SI 2 "index_operand" "rJ")))))
8191    (set (match_operand:SI 0 "s_register_operand" "=r")
8192         (plus:SI (match_dup 1) (match_dup 2)))]
8193   "TARGET_ARM
8194    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8195    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8196    && (GET_CODE (operands[2]) != REG
8197        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8198   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8199   [(set_attr "type" "load")
8200    (set_attr "predicable" "yes")]
8203 (define_insn "*loadqisi_predec"
8204   [(set (match_operand:SI 3 "s_register_operand" "=r")
8205         (zero_extend:SI
8206          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8207                            (match_operand:SI 2 "s_register_operand" "r")))))
8208    (set (match_operand:SI 0 "s_register_operand" "=r")
8209         (minus:SI (match_dup 1) (match_dup 2)))]
8210   "TARGET_ARM
8211    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8212    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8213    && (GET_CODE (operands[2]) != REG
8214        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8215   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8216   [(set_attr "type" "load")
8217    (set_attr "predicable" "yes")]
8220 (define_insn "*strsi_preinc"
8221   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8222                          (match_operand:SI 2 "index_operand" "rJ")))
8223         (match_operand:SI 3 "s_register_operand" "r"))
8224    (set (match_operand:SI 0 "s_register_operand" "=r")
8225         (plus:SI (match_dup 1) (match_dup 2)))]
8226   "TARGET_ARM
8227    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8228    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8229    && (GET_CODE (operands[2]) != REG
8230        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8231   "str%?\\t%3, [%0, %2]!"
8232   [(set_attr "type" "store1")
8233    (set_attr "predicable" "yes")]
8236 (define_insn "*strsi_predec"
8237   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8238                           (match_operand:SI 2 "s_register_operand" "r")))
8239         (match_operand:SI 3 "s_register_operand" "r"))
8240    (set (match_operand:SI 0 "s_register_operand" "=r")
8241         (minus:SI (match_dup 1) (match_dup 2)))]
8242   "TARGET_ARM
8243    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8244    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8245    && (GET_CODE (operands[2]) != REG
8246        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8247   "str%?\\t%3, [%0, -%2]!"
8248   [(set_attr "type" "store1")
8249    (set_attr "predicable" "yes")]
8252 (define_insn "*loadsi_preinc"
8253   [(set (match_operand:SI 3 "s_register_operand" "=r")
8254         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8255                          (match_operand:SI 2 "index_operand" "rJ"))))
8256    (set (match_operand:SI 0 "s_register_operand" "=r")
8257         (plus:SI (match_dup 1) (match_dup 2)))]
8258   "TARGET_ARM
8259    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8260    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8261    && (GET_CODE (operands[2]) != REG
8262        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8263   "ldr%?\\t%3, [%0, %2]!"
8264   [(set_attr "type" "load")
8265    (set_attr "predicable" "yes")]
8268 (define_insn "*loadsi_predec"
8269   [(set (match_operand:SI 3 "s_register_operand" "=r")
8270         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8271                           (match_operand:SI 2 "s_register_operand" "r"))))
8272    (set (match_operand:SI 0 "s_register_operand" "=r")
8273         (minus:SI (match_dup 1) (match_dup 2)))]
8274   "TARGET_ARM
8275    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8276    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8277    && (GET_CODE (operands[2]) != REG
8278        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8279   "ldr%?\\t%3, [%0, -%2]!"
8280   [(set_attr "type" "load")
8281    (set_attr "predicable" "yes")]
8284 (define_insn "*loadhi_preinc"
8285   [(set (match_operand:HI 3 "s_register_operand" "=r")
8286         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8287                          (match_operand:SI 2 "index_operand" "rJ"))))
8288    (set (match_operand:SI 0 "s_register_operand" "=r")
8289         (plus:SI (match_dup 1) (match_dup 2)))]
8290   "TARGET_ARM
8291    && !BYTES_BIG_ENDIAN
8292    && !TARGET_MMU_TRAPS
8293    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8294    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8295    && (GET_CODE (operands[2]) != REG
8296        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8297   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8298   [(set_attr "type" "load")
8299    (set_attr "predicable" "yes")]
8302 (define_insn "*loadhi_predec"
8303   [(set (match_operand:HI 3 "s_register_operand" "=r")
8304         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8305                           (match_operand:SI 2 "s_register_operand" "r"))))
8306    (set (match_operand:SI 0 "s_register_operand" "=r")
8307         (minus:SI (match_dup 1) (match_dup 2)))]
8308   "TARGET_ARM
8309    && !BYTES_BIG_ENDIAN
8310    && !TARGET_MMU_TRAPS
8311    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8312    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8313    && (GET_CODE (operands[2]) != REG
8314        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8315   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8316   [(set_attr "type" "load")
8317    (set_attr "predicable" "yes")]
8320 (define_insn "*strqi_shiftpreinc"
8321   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8322                           [(match_operand:SI 3 "s_register_operand" "r")
8323                            (match_operand:SI 4 "const_shift_operand" "n")])
8324                          (match_operand:SI 1 "s_register_operand" "0")))
8325         (match_operand:QI 5 "s_register_operand" "r"))
8326    (set (match_operand:SI 0 "s_register_operand" "=r")
8327         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8328                  (match_dup 1)))]
8329   "TARGET_ARM
8330    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8331    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8332    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8333   "str%?b\\t%5, [%0, %3%S2]!"
8334   [(set_attr "type" "store1")
8335    (set_attr "predicable" "yes")]
8338 (define_insn "*strqi_shiftpredec"
8339   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8340                           (match_operator:SI 2 "shift_operator"
8341                            [(match_operand:SI 3 "s_register_operand" "r")
8342                             (match_operand:SI 4 "const_shift_operand" "n")])))
8343         (match_operand:QI 5 "s_register_operand" "r"))
8344    (set (match_operand:SI 0 "s_register_operand" "=r")
8345         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8346                                                  (match_dup 4)])))]
8347   "TARGET_ARM
8348    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8349    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8350    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8351   "str%?b\\t%5, [%0, -%3%S2]!"
8352   [(set_attr "type" "store1")
8353    (set_attr "predicable" "yes")]
8356 (define_insn "*loadqi_shiftpreinc"
8357   [(set (match_operand:QI 5 "s_register_operand" "=r")
8358         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8359                           [(match_operand:SI 3 "s_register_operand" "r")
8360                            (match_operand:SI 4 "const_shift_operand" "n")])
8361                          (match_operand:SI 1 "s_register_operand" "0"))))
8362    (set (match_operand:SI 0 "s_register_operand" "=r")
8363         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8364                  (match_dup 1)))]
8365   "TARGET_ARM
8366    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8367    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8368    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8369   "ldr%?b\\t%5, [%0, %3%S2]!"
8370   [(set_attr "type" "load")
8371    (set_attr "predicable" "yes")]
8374 (define_insn "*loadqi_shiftpredec"
8375   [(set (match_operand:QI 5 "s_register_operand" "=r")
8376         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8377                           (match_operator:SI 2 "shift_operator"
8378                            [(match_operand:SI 3 "s_register_operand" "r")
8379                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8380    (set (match_operand:SI 0 "s_register_operand" "=r")
8381         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8382                                                  (match_dup 4)])))]
8383   "TARGET_ARM
8384    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8385    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8386    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8387   "ldr%?b\\t%5, [%0, -%3%S2]!"
8388   [(set_attr "type" "load")
8389    (set_attr "predicable" "yes")]
8392 (define_insn "*strsi_shiftpreinc"
8393   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8394                           [(match_operand:SI 3 "s_register_operand" "r")
8395                            (match_operand:SI 4 "const_shift_operand" "n")])
8396                          (match_operand:SI 1 "s_register_operand" "0")))
8397         (match_operand:SI 5 "s_register_operand" "r"))
8398    (set (match_operand:SI 0 "s_register_operand" "=r")
8399         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8400                  (match_dup 1)))]
8401   "TARGET_ARM
8402    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8403    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8404    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8405   "str%?\\t%5, [%0, %3%S2]!"
8406   [(set_attr "type" "store1")
8407    (set_attr "predicable" "yes")]
8410 (define_insn "*strsi_shiftpredec"
8411   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8412                           (match_operator:SI 2 "shift_operator"
8413                            [(match_operand:SI 3 "s_register_operand" "r")
8414                             (match_operand:SI 4 "const_shift_operand" "n")])))
8415         (match_operand:SI 5 "s_register_operand" "r"))
8416    (set (match_operand:SI 0 "s_register_operand" "=r")
8417         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8418                                                  (match_dup 4)])))]
8419   "TARGET_ARM
8420    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8421    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8422    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8423   "str%?\\t%5, [%0, -%3%S2]!"
8424   [(set_attr "type" "store1")
8425    (set_attr "predicable" "yes")]
8428 (define_insn "*loadsi_shiftpreinc"
8429   [(set (match_operand:SI 5 "s_register_operand" "=r")
8430         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8431                           [(match_operand:SI 3 "s_register_operand" "r")
8432                            (match_operand:SI 4 "const_shift_operand" "n")])
8433                          (match_operand:SI 1 "s_register_operand" "0"))))
8434    (set (match_operand:SI 0 "s_register_operand" "=r")
8435         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8436                  (match_dup 1)))]
8437   "TARGET_ARM
8438    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8439    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8440    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8441   "ldr%?\\t%5, [%0, %3%S2]!"
8442   [(set_attr "type" "load")
8443    (set_attr "predicable" "yes")]
8446 (define_insn "*loadsi_shiftpredec"
8447   [(set (match_operand:SI 5 "s_register_operand" "=r")
8448         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8449                           (match_operator:SI 2 "shift_operator"
8450                            [(match_operand:SI 3 "s_register_operand" "r")
8451                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8452    (set (match_operand:SI 0 "s_register_operand" "=r")
8453         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8454                                                  (match_dup 4)])))]
8455   "TARGET_ARM
8456    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8457    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8458    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8459   "ldr%?\\t%5, [%0, -%3%S2]!"
8460   [(set_attr "type" "load")
8461    (set_attr "predicable" "yes")])
8463 (define_insn "*loadhi_shiftpreinc"
8464   [(set (match_operand:HI 5 "s_register_operand" "=r")
8465         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8466                           [(match_operand:SI 3 "s_register_operand" "r")
8467                            (match_operand:SI 4 "const_shift_operand" "n")])
8468                          (match_operand:SI 1 "s_register_operand" "0"))))
8469    (set (match_operand:SI 0 "s_register_operand" "=r")
8470         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8471                  (match_dup 1)))]
8472   "TARGET_ARM
8473    && !BYTES_BIG_ENDIAN
8474    && !TARGET_MMU_TRAPS
8475    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8476    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8477    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8478   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8479   [(set_attr "type" "load")
8480    (set_attr "predicable" "yes")]
8483 (define_insn "*loadhi_shiftpredec"
8484   [(set (match_operand:HI 5 "s_register_operand" "=r")
8485         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8486                           (match_operator:SI 2 "shift_operator"
8487                            [(match_operand:SI 3 "s_register_operand" "r")
8488                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8489    (set (match_operand:SI 0 "s_register_operand" "=r")
8490         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8491                                                  (match_dup 4)])))]
8492   "TARGET_ARM
8493    && !BYTES_BIG_ENDIAN
8494    && !TARGET_MMU_TRAPS
8495    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8496    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8497    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8498   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8499   [(set_attr "type" "load")
8500    (set_attr "predicable" "yes")]
8503 ; It can also support extended post-inc expressions, but combine doesn't
8504 ; try these....
8505 ; It doesn't seem worth adding peepholes for anything but the most common
8506 ; cases since, unlike combine, the increment must immediately follow the load
8507 ; for this pattern to match.
8508 ; We must watch to see that the source/destination register isn't also the
8509 ; same as the base address register, and that if the index is a register,
8510 ; that it is not the same as the base address register.  In such cases the
8511 ; instruction that we would generate would have UNPREDICTABLE behaviour so 
8512 ; we cannot use it.
8514 (define_peephole
8515   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8516         (match_operand:QI 2 "s_register_operand" "r"))
8517    (set (match_dup 0)
8518         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8519   "TARGET_ARM
8520    && (REGNO (operands[2]) != REGNO (operands[0]))
8521    && (GET_CODE (operands[1]) != REG
8522        || (REGNO (operands[1]) != REGNO (operands[0])))"
8523   "str%?b\\t%2, [%0], %1"
8526 (define_peephole
8527   [(set (match_operand:QI 0 "s_register_operand" "=r")
8528         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8529    (set (match_dup 1)
8530         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8531   "TARGET_ARM
8532    && REGNO (operands[0]) != REGNO(operands[1])
8533    && (GET_CODE (operands[2]) != REG
8534        || REGNO(operands[0]) != REGNO (operands[2]))"
8535   "ldr%?b\\t%0, [%1], %2"
8538 (define_peephole
8539   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8540         (match_operand:SI 2 "s_register_operand" "r"))
8541    (set (match_dup 0)
8542         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8543   "TARGET_ARM
8544    && (REGNO (operands[2]) != REGNO (operands[0]))
8545    && (GET_CODE (operands[1]) != REG
8546        || (REGNO (operands[1]) != REGNO (operands[0])))"
8547   "str%?\\t%2, [%0], %1"
8550 (define_peephole
8551   [(set (match_operand:HI 0 "s_register_operand" "=r")
8552         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8553    (set (match_dup 1)
8554         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8555   "TARGET_ARM
8556    && !BYTES_BIG_ENDIAN
8557    && !TARGET_MMU_TRAPS
8558    && REGNO (operands[0]) != REGNO(operands[1])
8559    && (GET_CODE (operands[2]) != REG
8560        || REGNO(operands[0]) != REGNO (operands[2]))"
8561   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8564 (define_peephole
8565   [(set (match_operand:SI 0 "s_register_operand" "=r")
8566         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8567    (set (match_dup 1)
8568         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8569   "TARGET_ARM
8570    && REGNO (operands[0]) != REGNO(operands[1])
8571    && (GET_CODE (operands[2]) != REG
8572        || REGNO(operands[0]) != REGNO (operands[2]))"
8573   "ldr%?\\t%0, [%1], %2"
8576 (define_peephole
8577   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8578                          (match_operand:SI 1 "index_operand" "rJ")))
8579         (match_operand:QI 2 "s_register_operand" "r"))
8580    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8581   "TARGET_ARM
8582    && (REGNO (operands[2]) != REGNO (operands[0]))
8583    && (GET_CODE (operands[1]) != REG
8584        || (REGNO (operands[1]) != REGNO (operands[0])))"
8585   "str%?b\\t%2, [%0, %1]!"
8588 (define_peephole
8589   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8590                           [(match_operand:SI 0 "s_register_operand" "r")
8591                            (match_operand:SI 1 "const_int_operand" "n")])
8592                          (match_operand:SI 2 "s_register_operand" "+r")))
8593         (match_operand:QI 3 "s_register_operand" "r"))
8594    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8595                                (match_dup 2)))]
8596   "TARGET_ARM
8597    && (REGNO (operands[3]) != REGNO (operands[2]))
8598    && (REGNO (operands[0]) != REGNO (operands[2]))"
8599   "str%?b\\t%3, [%2, %0%S4]!"
8602 ; This pattern is never tried by combine, so do it as a peephole
8604 (define_peephole2
8605   [(set (match_operand:SI 0 "s_register_operand" "")
8606         (match_operand:SI 1 "s_register_operand" ""))
8607    (set (reg:CC CC_REGNUM)
8608         (compare:CC (match_dup 1) (const_int 0)))]
8609   "TARGET_ARM"
8610   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8611               (set (match_dup 0) (match_dup 1))])]
8612   ""
8615 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8616 ; reversed, check that the memory references aren't volatile.
8618 (define_peephole
8619   [(set (match_operand:SI 0 "s_register_operand" "=r")
8620         (match_operand:SI 4 "memory_operand" "m"))
8621    (set (match_operand:SI 1 "s_register_operand" "=r")
8622         (match_operand:SI 5 "memory_operand" "m"))
8623    (set (match_operand:SI 2 "s_register_operand" "=r")
8624         (match_operand:SI 6 "memory_operand" "m"))
8625    (set (match_operand:SI 3 "s_register_operand" "=r")
8626         (match_operand:SI 7 "memory_operand" "m"))]
8627   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8628   "*
8629   return emit_ldm_seq (operands, 4);
8630   "
8633 (define_peephole
8634   [(set (match_operand:SI 0 "s_register_operand" "=r")
8635         (match_operand:SI 3 "memory_operand" "m"))
8636    (set (match_operand:SI 1 "s_register_operand" "=r")
8637         (match_operand:SI 4 "memory_operand" "m"))
8638    (set (match_operand:SI 2 "s_register_operand" "=r")
8639         (match_operand:SI 5 "memory_operand" "m"))]
8640   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8641   "*
8642   return emit_ldm_seq (operands, 3);
8643   "
8646 (define_peephole
8647   [(set (match_operand:SI 0 "s_register_operand" "=r")
8648         (match_operand:SI 2 "memory_operand" "m"))
8649    (set (match_operand:SI 1 "s_register_operand" "=r")
8650         (match_operand:SI 3 "memory_operand" "m"))]
8651   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8652   "*
8653   return emit_ldm_seq (operands, 2);
8654   "
8657 (define_peephole
8658   [(set (match_operand:SI 4 "memory_operand" "=m")
8659         (match_operand:SI 0 "s_register_operand" "r"))
8660    (set (match_operand:SI 5 "memory_operand" "=m")
8661         (match_operand:SI 1 "s_register_operand" "r"))
8662    (set (match_operand:SI 6 "memory_operand" "=m")
8663         (match_operand:SI 2 "s_register_operand" "r"))
8664    (set (match_operand:SI 7 "memory_operand" "=m")
8665         (match_operand:SI 3 "s_register_operand" "r"))]
8666   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8667   "*
8668   return emit_stm_seq (operands, 4);
8669   "
8672 (define_peephole
8673   [(set (match_operand:SI 3 "memory_operand" "=m")
8674         (match_operand:SI 0 "s_register_operand" "r"))
8675    (set (match_operand:SI 4 "memory_operand" "=m")
8676         (match_operand:SI 1 "s_register_operand" "r"))
8677    (set (match_operand:SI 5 "memory_operand" "=m")
8678         (match_operand:SI 2 "s_register_operand" "r"))]
8679   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8680   "*
8681   return emit_stm_seq (operands, 3);
8682   "
8685 (define_peephole
8686   [(set (match_operand:SI 2 "memory_operand" "=m")
8687         (match_operand:SI 0 "s_register_operand" "r"))
8688    (set (match_operand:SI 3 "memory_operand" "=m")
8689         (match_operand:SI 1 "s_register_operand" "r"))]
8690   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8691   "*
8692   return emit_stm_seq (operands, 2);
8693   "
8696 (define_split
8697   [(set (match_operand:SI 0 "s_register_operand" "")
8698         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8699                        (const_int 0))
8700                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8701                          [(match_operand:SI 3 "s_register_operand" "")
8702                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
8703    (clobber (match_operand:SI 5 "s_register_operand" ""))]
8704   "TARGET_ARM"
8705   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8706    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8707                               (match_dup 5)))]
8708   ""
8711 ;; This split can be used because CC_Z mode implies that the following
8712 ;; branch will be an equality, or an unsigned inequality, so the sign
8713 ;; extension is not needed.
8715 (define_split
8716   [(set (reg:CC_Z CC_REGNUM)
8717         (compare:CC_Z
8718          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8719                     (const_int 24))
8720          (match_operand 1 "const_int_operand" "")))
8721    (clobber (match_scratch:SI 2 ""))]
8722   "TARGET_ARM
8723    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8724        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8725   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8726    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8727   "
8728   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8729   "
8732 (define_expand "prologue"
8733   [(clobber (const_int 0))]
8734   "TARGET_EITHER"
8735   "if (TARGET_ARM)
8736      arm_expand_prologue ();
8737    else
8738      thumb_expand_prologue ();
8739   DONE;
8740   "
8743 (define_expand "epilogue"
8744   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8745   "TARGET_EITHER"
8746   "
8747   if (TARGET_THUMB)
8748     thumb_expand_epilogue ();
8749   else if (USE_RETURN_INSN (FALSE))
8750     {
8751       emit_jump_insn (gen_return ());
8752       DONE;
8753     }
8754   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8755         gen_rtvec (1,
8756                 gen_rtx_RETURN (VOIDmode)),
8757         VUNSPEC_EPILOGUE));
8758   DONE;
8759   "
8762 (define_insn "sibcall_epilogue"
8763   [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8764   "TARGET_ARM"
8765   "*
8766   output_asm_insn (\"%@ Sibcall epilogue\", operands);
8767   if (USE_RETURN_INSN (FALSE))
8768     return output_return_instruction (NULL, FALSE, FALSE);
8769   return arm_output_epilogue (FALSE);
8770   "
8771 ;; Length is absolute worst case
8772   [(set_attr "length" "44")
8773    (set_attr "type" "block")]
8776 (define_insn "*epilogue_insns"
8777   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8778   "TARGET_EITHER"
8779   "*
8780   if (TARGET_ARM)
8781     return arm_output_epilogue (TRUE);
8782   else /* TARGET_THUMB */
8783     return thumb_unexpanded_epilogue ();
8784   "
8785   ; Length is absolute worst case
8786   [(set_attr "length" "44")
8787    (set_attr "type" "block")]
8790 (define_expand "eh_epilogue"
8791   [(use (match_operand:SI 0 "register_operand" "r"))
8792    (use (match_operand:SI 1 "register_operand" "r"))
8793    (use (match_operand:SI 2 "register_operand" "r"))]
8794   "TARGET_EITHER"
8795   "
8796   {
8797     cfun->machine->eh_epilogue_sp_ofs = operands[1];
8798     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8799       {
8800         rtx ra = gen_rtx_REG (Pmode, 2);
8802         emit_move_insn (ra, operands[2]);
8803         operands[2] = ra;
8804       }
8805     /* This is a hack -- we may have crystalized the function type too
8806        early.  */
8807     cfun->machine->func_type = 0;
8808   }"
8811 ;; This split is only used during output to reduce the number of patterns
8812 ;; that need assembler instructions adding to them.  We allowed the setting
8813 ;; of the conditions to be implicit during rtl generation so that
8814 ;; the conditional compare patterns would work.  However this conflicts to
8815 ;; some extent with the conditional data operations, so we have to split them
8816 ;; up again here.
8818 (define_split
8819   [(set (match_operand:SI 0 "s_register_operand" "")
8820         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8821                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8822                          (match_dup 0)
8823                          (match_operand 4 "" "")))
8824    (clobber (reg:CC CC_REGNUM))]
8825   "TARGET_ARM && reload_completed"
8826   [(set (match_dup 5) (match_dup 6))
8827    (cond_exec (match_dup 7)
8828               (set (match_dup 0) (match_dup 4)))]
8829   "
8830   {
8831     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8832                                              operands[2], operands[3]);
8833     enum rtx_code rc = GET_CODE (operands[1]);
8835     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8836     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8837     if (mode == CCFPmode || mode == CCFPEmode)
8838       rc = reverse_condition_maybe_unordered (rc);
8839     else
8840       rc = reverse_condition (rc);
8842     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8843   }"
8846 (define_split
8847   [(set (match_operand:SI 0 "s_register_operand" "")
8848         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8849                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8850                          (match_operand 4 "" "")
8851                          (match_dup 0)))
8852    (clobber (reg:CC CC_REGNUM))]
8853   "TARGET_ARM && reload_completed"
8854   [(set (match_dup 5) (match_dup 6))
8855    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8856               (set (match_dup 0) (match_dup 4)))]
8857   "
8858   {
8859     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8860                                              operands[2], operands[3]);
8862     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8863     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8864   }"
8867 (define_split
8868   [(set (match_operand:SI 0 "s_register_operand" "")
8869         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8870                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8871                          (match_operand 4 "" "")
8872                          (match_operand 5 "" "")))
8873    (clobber (reg:CC CC_REGNUM))]
8874   "TARGET_ARM && reload_completed"
8875   [(set (match_dup 6) (match_dup 7))
8876    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8877               (set (match_dup 0) (match_dup 4)))
8878    (cond_exec (match_dup 8)
8879               (set (match_dup 0) (match_dup 5)))]
8880   "
8881   {
8882     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8883                                              operands[2], operands[3]);
8884     enum rtx_code rc = GET_CODE (operands[1]);
8886     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8887     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8888     if (mode == CCFPmode || mode == CCFPEmode)
8889       rc = reverse_condition_maybe_unordered (rc);
8890     else
8891       rc = reverse_condition (rc);
8893     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8894   }"
8897 (define_split
8898   [(set (match_operand:SI 0 "s_register_operand" "")
8899         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8900                           [(match_operand:SI 2 "s_register_operand" "")
8901                            (match_operand:SI 3 "arm_add_operand" "")])
8902                          (match_operand:SI 4 "arm_rhs_operand" "")
8903                          (not:SI
8904                           (match_operand:SI 5 "s_register_operand" ""))))
8905    (clobber (reg:CC CC_REGNUM))]
8906   "TARGET_ARM && reload_completed"
8907   [(set (match_dup 6) (match_dup 7))
8908    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8909               (set (match_dup 0) (match_dup 4)))
8910    (cond_exec (match_dup 8)
8911               (set (match_dup 0) (not:SI (match_dup 5))))]
8912   "
8913   {
8914     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8915                                              operands[2], operands[3]);
8916     enum rtx_code rc = GET_CODE (operands[1]);
8918     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8919     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8920     if (mode == CCFPmode || mode == CCFPEmode)
8921       rc = reverse_condition_maybe_unordered (rc);
8922     else
8923       rc = reverse_condition (rc);
8925     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8926   }"
8929 (define_insn "*cond_move_not"
8930   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8931         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8932                           [(match_operand 3 "cc_register" "") (const_int 0)])
8933                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8934                          (not:SI
8935                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
8936   "TARGET_ARM"
8937   "@
8938    mvn%D4\\t%0, %2
8939    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8940   [(set_attr "conds" "use")
8941    (set_attr "length" "4,8")]
8944 ;; The next two patterns occur when an AND operation is followed by a
8945 ;; scc insn sequence 
8947 (define_insn "*sign_extract_onebit"
8948   [(set (match_operand:SI 0 "s_register_operand" "=r")
8949         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8950                          (const_int 1)
8951                          (match_operand:SI 2 "const_int_operand" "n")))]
8952   "TARGET_ARM"
8953   "*
8954     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8955     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8956     return \"mvnne\\t%0, #0\";
8957   "
8958   [(set_attr "conds" "clob")
8959    (set_attr "length" "8")]
8962 (define_insn "*not_signextract_onebit"
8963   [(set (match_operand:SI 0 "s_register_operand" "=r")
8964         (not:SI
8965          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8966                           (const_int 1)
8967                           (match_operand:SI 2 "const_int_operand" "n"))))]
8968   "TARGET_ARM"
8969   "*
8970     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8971     output_asm_insn (\"tst\\t%1, %2\", operands);
8972     output_asm_insn (\"mvneq\\t%0, #0\", operands);
8973     return \"movne\\t%0, #0\";
8974   "
8975   [(set_attr "conds" "clob")
8976    (set_attr "length" "12")]
8979 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8980 ;; expressions.  For simplicity, the first register is also in the unspec
8981 ;; part.
8982 (define_insn "*push_multi"
8983   [(match_parallel 2 "multi_register_push"
8984     [(set (match_operand:BLK 0 "memory_operand" "=m")
8985           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8986                       UNSPEC_PUSH_MULT))])]
8987   "TARGET_ARM"
8988   "*
8989   {
8990     int num_saves = XVECLEN (operands[2], 0);
8991      
8992     /* For the StrongARM at least it is faster to
8993        use STR to store only a single register.  */
8994     if (num_saves == 1)
8995       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8996     else
8997       {
8998         int i;
8999         char pattern[100];
9001         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9003         for (i = 1; i < num_saves; i++)
9004           {
9005             strcat (pattern, \", %|\");
9006             strcat (pattern,
9007                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9008           }
9010         strcat (pattern, \"}\");
9011         output_asm_insn (pattern, operands);
9012       }
9014     return \"\";
9015   }"
9016   [(set_attr "type" "store4")]
9019 ;; Similarly for the floating point registers
9020 (define_insn "*push_fp_multi"
9021   [(match_parallel 2 "multi_register_push"
9022     [(set (match_operand:BLK 0 "memory_operand" "=m")
9023           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9024                       UNSPEC_PUSH_MULT))])]
9025   "TARGET_ARM"
9026   "*
9027   {
9028     char pattern[100];
9030     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9031     output_asm_insn (pattern, operands);
9032     return \"\";
9033   }"
9034   [(set_attr "type" "f_store")]
9037 ;; Special patterns for dealing with the constant pool
9039 (define_insn "align_4"
9040   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9041   "TARGET_EITHER"
9042   "*
9043   assemble_align (32);
9044   return \"\";
9045   "
9048 (define_insn "consttable_end"
9049   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9050   "TARGET_EITHER"
9051   "*
9052   making_const_table = FALSE;
9053   return \"\";
9054   "
9057 (define_insn "consttable_1"
9058   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9059   "TARGET_THUMB"
9060   "*
9061   making_const_table = TRUE;
9062   assemble_integer (operands[0], 1, 1);
9063   assemble_zeros (3);
9064   return \"\";
9065   "
9066   [(set_attr "length" "4")]
9069 (define_insn "consttable_2"
9070   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9071   "TARGET_THUMB"
9072   "*
9073   making_const_table = TRUE;
9074   assemble_integer (operands[0], 2, 1);
9075   assemble_zeros (2);
9076   return \"\";
9077   "
9078   [(set_attr "length" "4")]
9081 (define_insn "consttable_4"
9082   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9083   "TARGET_EITHER"
9084   "*
9085   {
9086     making_const_table = TRUE;
9087     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9088       {
9089       case MODE_FLOAT:
9090       {
9091         union real_extract u;
9092         memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9093         assemble_real (u.d, GET_MODE (operands[0]));
9094         break;
9095       }
9096       default:
9097         assemble_integer (operands[0], 4, 1);
9098         break;
9099       }
9100     return \"\";
9101   }"
9102   [(set_attr "length" "4")]
9105 (define_insn "consttable_8"
9106   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9107   "TARGET_EITHER"
9108   "*
9109   {
9110     making_const_table = TRUE;
9111     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9112       {
9113        case MODE_FLOAT:
9114         {
9115           union real_extract u;
9116           memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9117           assemble_real (u.d, GET_MODE (operands[0]));
9118           break;
9119         }
9120       default:
9121         assemble_integer (operands[0], 8, 1);
9122         break;
9123       }
9124     return \"\";
9125   }"
9126   [(set_attr "length" "8")]
9129 ;; Miscellaneous Thumb patterns
9131 (define_insn "tablejump"
9132   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9133    (use (label_ref (match_operand 1 "" "")))]
9134   "TARGET_THUMB"
9135   "mov  pc, %0"
9136   [(set_attr "length" "2")]
9139 ;; V5 Instructions,
9141 (define_insn "clz"
9142   [(set (match_operand:SI             0 "s_register_operand" "=r")
9143         (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9144                    UNSPEC_CLZ))]
9145   "TARGET_ARM && arm_arch5"
9146   "clz\\t%0, %1")
9148 (define_expand "ffssi2"
9149   [(set (match_operand:SI 0 "s_register_operand" "")
9150         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9151   "TARGET_ARM && arm_arch5"
9152   "
9153   {
9154     rtx t1, t2, t3;
9156     t1 = gen_reg_rtx (SImode);
9157     t2 = gen_reg_rtx (SImode);
9158     t3 = gen_reg_rtx (SImode);
9160     emit_insn (gen_negsi2 (t1, operands[1]));
9161     emit_insn (gen_andsi3 (t2, operands[1], t1));
9162     emit_insn (gen_clz (t3, t2));
9163     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9164     DONE;
9165   }"
9168 ;; V5E instructions.
9170 (define_insn "prefetch"
9171   [(unspec_volatile
9172     [(match_operand:SI 0 "offsettable_memory_operand" "o")] VUNSPEC_PREFETCH)]
9173   "TARGET_ARM && arm_arch5e"
9174   "pld\\t%0")
9176 ;; General predication pattern
9178 (define_cond_exec
9179   [(match_operator 0 "arm_comparison_operator"
9180     [(match_operand 1 "cc_register" "")
9181      (const_int 0)])]
9182   "TARGET_ARM"
9183   ""