(extendsfdf2): Add pattern accidentally deleted when cirrus instructions were
[official-gcc.git] / gcc / config / arm / arm.md
blob946064ba69680f1fbe20a1418fd74f217e5652b4
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002, 2003  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 GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; 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.
28 ;;---------------------------------------------------------------------------
29 ;; Constants
31 ;; Register numbers
32 (define_constants
33   [(IP_REGNUM       12)         ; Scratch register
34    (SP_REGNUM       13)         ; Stack pointer
35    (LR_REGNUM       14)         ; Return address register
36    (PC_REGNUM       15)         ; Program counter
37    (CC_REGNUM       24)         ; Condition code pseudo register
38    (LAST_ARM_REGNUM 15)
39   ]
42 ;; UNSPEC Usage:
43 ;; Note: sin and cos are no-longer used.
45 (define_constants
46   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
47                         ;   operand 0 is the result,
48                         ;   operand 1 the parameter.
49    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
50                         ;   operand 0 is the result,
51                         ;   operand 1 the parameter.
52    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
53                         ;   operand 0 is the first register,
54                         ;   subsequent registers are in parallel (use ...)
55                         ;   expressions.
56    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
57                         ;   usage, that is, we will add the pic_register
58                         ;   value to it before trying to dereference it.
59    (UNSPEC_PRLG_STK  4) ; A special barrier that prevents frame accesses 
60                         ;   being scheduled before the stack adjustment insn.
61    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
62                         ; this unspec is used to prevent the deletion of
63                         ; instructions setting registers for EH handling
64                         ; and stack frame generation.  Operand 0 is the
65                         ; register to "use".
66    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
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   ]
94 ;;---------------------------------------------------------------------------
95 ;; Attributes
97 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
98 ; generating ARM code.  This is used to control the length of some insn
99 ; patterns that share the same RTL in both ARM and Thumb code.
100 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
102 ; PROG_MODE attribute is used to determine whether condition codes are
103 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
104 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
105 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
107 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
108 ; scheduling decisions for the load unit and the multiplier.
109 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
111 ;; Operand number of an input operand that is shifted.  Zero if the
112 ;; given instruction does not shift one of its input operands.
113 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
114 (define_attr "shift" "" (const_int 0))
116 ; Floating Point Unit.  If we only have floating point emulation, then there
117 ; is no point in scheduling the floating point insns.  (Well, for best
118 ; performance we should try and group them together).
119 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
121 ; LENGTH of an instruction (in bytes)
122 (define_attr "length" "" (const_int 4))
124 ; POOL_RANGE is how far away from a constant pool entry that this insn
125 ; can be placed.  If the distance is zero, then this insn will never
126 ; reference the pool.
127 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
128 ; before its address.
129 (define_attr "pool_range" "" (const_int 0))
130 (define_attr "neg_pool_range" "" (const_int 0))
132 ; An assembler sequence may clobber the condition codes without us knowing.
133 ; If such an insn references the pool, then we have no way of knowing how,
134 ; so use the most conservative value for pool_range.
135 (define_asm_attributes
136  [(set_attr "conds" "clob")
137   (set_attr "length" "4")
138   (set_attr "pool_range" "250")])
140 ; TYPE attribute is used to detect floating point instructions which, if
141 ; running on a co-processor can run in parallel with other, basic instructions
142 ; If write-buffer scheduling is enabled then it can also be used in the
143 ; scheduling of writes.
145 ; Classification of each insn
146 ; normal        any data instruction that doesn't hit memory or fp regs
147 ; mult          a multiply instruction
148 ; block         blockage insn, this blocks all functional units
149 ; float         a floating point arithmetic operation (subject to expansion)
150 ; fdivd         DFmode floating point division
151 ; fdivs         SFmode floating point division
152 ; fmul          Floating point multiply
153 ; ffmul         Fast floating point multiply
154 ; farith        Floating point arithmetic (4 cycle)
155 ; ffarith       Fast floating point arithmetic (2 cycle)
156 ; float_em      a floating point arithmetic operation that is normally emulated
157 ;               even on a machine with an fpa.
158 ; f_load        a floating point load from memory
159 ; f_store       a floating point store to memory
160 ; f_mem_r       a transfer of a floating point register to a real reg via mem
161 ; r_mem_f       the reverse of f_mem_r
162 ; f_2_r         fast transfer float to arm (no memory needed)
163 ; r_2_f         fast transfer arm to float
164 ; call          a subroutine call
165 ; load          any load from memory
166 ; store1        store 1 word to memory from arm registers
167 ; store2        store 2 words
168 ; store3        store 3 words
169 ; store4        store 4 words
170 ;  Additions for Cirrus Maverick co-processor:
171 ; mav_farith    Floating point arithmetic (4 cycle)
172 ; mav_dmult     Double multiplies (7 cycle)
174 (define_attr "type"
175         "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,mav_farith,mav_dmult" 
176         (const_string "normal"))
178 ; Load scheduling, set from the arm_ld_sched variable
179 ; initialized by arm_override_options() 
180 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
182 ; condition codes: this one is used by final_prescan_insn to speed up
183 ; conditionalizing instructions.  It saves having to scan the rtl to see if
184 ; it uses or alters the condition codes.
186 ; USE means that the condition codes are used by the insn in the process of
187 ;   outputting code, this means (at present) that we can't use the insn in
188 ;   inlined branches
190 ; SET means that the purpose of the insn is to set the condition codes in a
191 ;   well defined manner.
193 ; CLOB means that the condition codes are altered in an undefined manner, if
194 ;   they are altered at all
196 ; JUMP_CLOB is used when the condition cannot be represented by a single
197 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
199 ; NOCOND means that the condition codes are neither altered nor affect the
200 ;   output of this insn
202 (define_attr "conds" "use,set,clob,jump_clob,nocond"
203         (if_then_else (eq_attr "type" "call")
204          (if_then_else (eq_attr "prog_mode" "prog32")
205           (const_string "clob") (const_string "nocond"))
206          (const_string "nocond")))
208 ; Predicable means that the insn can be conditionally executed based on
209 ; an automatically added predicate (additional patterns are generated by 
210 ; gen...).  We default to 'no' because no Thumb patterns match this rule
211 ; and not all ARM patterns do.
212 (define_attr "predicable" "no,yes" (const_string "no"))
214 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
215 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
216 ; suffer blockages enough to warrent modelling this (and it can adversely
217 ; affect the schedule).
218 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
220 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
221 ; to stall the processor.  Used with model_wbuf above.
222 (define_attr "write_conflict" "no,yes"
223   (if_then_else (eq_attr "type"
224                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
225                 (const_string "yes")
226                 (const_string "no")))
228 ; Classify the insns into those that take one cycle and those that take more
229 ; than one on the main cpu execution unit.
230 (define_attr "core_cycles" "single,multi"
231   (if_then_else (eq_attr "type"
232                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
233                 (const_string "single")
234                 (const_string "multi")))
236 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
237 ;; distant label.  Only applicable to Thumb code.
238 (define_attr "far_jump" "yes,no" (const_string "no"))
240 ;; (define_function_unit {name} {num-units} {n-users} {test}
241 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
243 ;;--------------------------------------------------------------------
244 ;; Floating point unit (FPA)
245 ;;--------------------------------------------------------------------
246 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
247                                      (eq_attr "type" "fdivx")) 71 69)
249 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
250                                      (eq_attr "type" "fdivd")) 59 57)
252 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
253                                      (eq_attr "type" "fdivs")) 31 29)
255 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
256                                      (eq_attr "type" "fmul")) 9 7)
258 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
259                                      (eq_attr "type" "ffmul")) 6 4)
261 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
262                                      (eq_attr "type" "farith")) 4 2)
264 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
265                                      (eq_attr "type" "ffarith")) 2 2)
267 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
268                                      (eq_attr "type" "r_2_f")) 5 3)
270 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
271                                      (eq_attr "type" "f_2_r")) 1 2)
273 ; The fpa10 doesn't really have a memory read unit, but it can start to
274 ; speculatively execute the instruction in the pipeline, provided the data
275 ; is already loaded, so pretend reads have a delay of 2 (and that the
276 ; pipeline is infinite).
278 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
279                                          (eq_attr "type" "f_load")) 3 1)
281 ;;--------------------------------------------------------------------
282 ;; Write buffer
283 ;;--------------------------------------------------------------------
284 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
286 ; The write buffer on some of the arm6 processors is hard to model exactly.
287 ; There is room in the buffer for up to two addresses and up to eight words
288 ; of memory, but the two needn't be split evenly.  When writing the two
289 ; addresses are fully pipelined.  However, a read from memory that is not
290 ; currently in the cache will block until the writes have completed.
291 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
292 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
293 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
294 ; cycle to add as well.
296 (define_function_unit "write_buf" 1 2
297   (and (eq_attr "model_wbuf" "yes")
298        (eq_attr "type" "store1,r_mem_f")) 5 3)
299 (define_function_unit "write_buf" 1 2 
300   (and (eq_attr "model_wbuf" "yes")
301        (eq_attr "type" "store2")) 7 4)
302 (define_function_unit "write_buf" 1 2
303   (and (eq_attr "model_wbuf" "yes")
304        (eq_attr "type" "store3")) 9 5)
305 (define_function_unit "write_buf" 1 2
306   (and (eq_attr "model_wbuf" "yes")
307        (eq_attr "type" "store4")) 11 6)
309 ;;--------------------------------------------------------------------
310 ;; Write blockage unit
311 ;;--------------------------------------------------------------------
312 ; The write_blockage unit models (partially), the fact that reads will stall
313 ; until the write buffer empties.
314 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
315 ; so we don't model them here
316 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
317                                                 (eq_attr "type" "store1")) 5 5
318         [(eq_attr "write_conflict" "yes")])
319 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
320                                                 (eq_attr "type" "store2")) 7 7
321         [(eq_attr "write_conflict" "yes")])
322 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
323                                                 (eq_attr "type" "store3")) 9 9
324         [(eq_attr "write_conflict" "yes")])
325 (define_function_unit "write_blockage" 1 0
326         (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
327         [(eq_attr "write_conflict" "yes")])
328 (define_function_unit "write_blockage" 1 0
329         (and (eq_attr "model_wbuf" "yes")
330              (eq_attr "write_conflict" "yes")) 1 1)
332 ;;--------------------------------------------------------------------
333 ;; Core unit
334 ;;--------------------------------------------------------------------
335 ; Everything must spend at least one cycle in the core unit
336 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
338 (define_function_unit "core" 1 0
339   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
341 (define_function_unit "core" 1 0
342   (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
344 ;; We do not need to conditionalize the define_function_unit immediately
345 ;; above.  This one will be ignored for anything other than xscale
346 ;; compiles and for xscale compiles it provides a larger delay
347 ;; and the scheduler will DTRT.
348 ;; FIXME: this test needs to be revamped to not depend on this feature 
349 ;; of the scheduler.
351 (define_function_unit "core" 1 0
352   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
353        (eq_attr "is_xscale" "yes"))
354    3 1)
356 (define_function_unit "core" 1 0
357   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
359 (define_function_unit "core" 1 0
360   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
362 (define_function_unit "core" 1 0
363   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
365 (define_function_unit "core" 1 0
366   (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
368 (define_function_unit "core" 1 0
369   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
371 (define_function_unit "core" 1 0
372   (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
374 (define_function_unit "core" 1 0
375   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
376        (eq_attr "type" "mult")) 4 4)
378 (define_function_unit "core" 1 0
379   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
380        (eq_attr "type" "mult")) 3 2)
382 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
384 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
386 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
388 (define_function_unit "core" 1 0
389   (and (eq_attr "core_cycles" "multi")
390        (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
392 (include "cirrus.md")
394 ;;---------------------------------------------------------------------------
395 ;; Insn patterns
397 ;; Addition insns.
399 ;; Note: For DImode insns, there is normally no reason why operands should
400 ;; not be in the same register, what we don't want is for something being
401 ;; written to partially overlap something that is an input.
402 ;; Cirrus 64bit additions should not be split because we have a native
403 ;; 64bit addition instructions.
405 (define_expand "adddi3"
406  [(parallel
407    [(set (match_operand:DI           0 "s_register_operand" "")
408           (plus:DI (match_operand:DI 1 "s_register_operand" "")
409                    (match_operand:DI 2 "s_register_operand" "")))
410     (clobber (reg:CC CC_REGNUM))])]
411   "TARGET_EITHER"
412   "
413   if (TARGET_CIRRUS)
414     {
415       if (!cirrus_fp_register (operands[0], DImode))
416         operands[0] = force_reg (DImode, operands[0]);
417       if (!cirrus_fp_register (operands[1], DImode))
418         operands[1] = force_reg (DImode, operands[1]);
419       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
420       DONE;
421     }
423   if (TARGET_THUMB)
424     {
425       if (GET_CODE (operands[1]) != REG)
426         operands[1] = force_reg (SImode, operands[1]);
427       if (GET_CODE (operands[2]) != REG)
428         operands[2] = force_reg (SImode, operands[2]);
429      }
430   "
433 (define_insn "*thumb_adddi3"
434   [(set (match_operand:DI          0 "register_operand" "=l")
435         (plus:DI (match_operand:DI 1 "register_operand" "%0")
436                  (match_operand:DI 2 "register_operand" "l")))
437    (clobber (reg:CC CC_REGNUM))
438   ]
439   "TARGET_THUMB"
440   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
441   [(set_attr "length" "4")]
444 (define_insn_and_split "*arm_adddi3"
445   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
446         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
447                  (match_operand:DI 2 "s_register_operand" "r,  0")))
448    (clobber (reg:CC CC_REGNUM))]
449   "TARGET_ARM && !TARGET_CIRRUS"
450   "#"
451   "TARGET_ARM && reload_completed"
452   [(parallel [(set (reg:CC_C CC_REGNUM)
453                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
454                                  (match_dup 1)))
455               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
456    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
457                                (plus:SI (match_dup 4) (match_dup 5))))]
458   "
459   {
460     operands[3] = gen_highpart (SImode, operands[0]);
461     operands[0] = gen_lowpart (SImode, operands[0]);
462     operands[4] = gen_highpart (SImode, operands[1]);
463     operands[1] = gen_lowpart (SImode, operands[1]);
464     operands[5] = gen_highpart (SImode, operands[2]);
465     operands[2] = gen_lowpart (SImode, operands[2]);
466   }"
467   [(set_attr "conds" "clob")
468    (set_attr "length" "8")]
471 (define_insn_and_split "*adddi_sesidi_di"
472   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
473         (plus:DI (sign_extend:DI
474                   (match_operand:SI 2 "s_register_operand" "r,r"))
475                  (match_operand:DI 1 "s_register_operand" "r,0")))
476    (clobber (reg:CC CC_REGNUM))]
477   "TARGET_ARM && !TARGET_CIRRUS"
478   "#"
479   "TARGET_ARM && reload_completed"
480   [(parallel [(set (reg:CC_C CC_REGNUM)
481                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
482                                  (match_dup 1)))
483               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
484    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
485                                (plus:SI (ashiftrt:SI (match_dup 2)
486                                                      (const_int 31))
487                                         (match_dup 4))))]
488   "
489   {
490     operands[3] = gen_highpart (SImode, operands[0]);
491     operands[0] = gen_lowpart (SImode, operands[0]);
492     operands[4] = gen_highpart (SImode, operands[1]);
493     operands[1] = gen_lowpart (SImode, operands[1]);
494     operands[2] = gen_lowpart (SImode, operands[2]);
495   }"
496   [(set_attr "conds" "clob")
497    (set_attr "length" "8")]
500 (define_insn_and_split "*adddi_zesidi_di"
501   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
502         (plus:DI (zero_extend:DI
503                   (match_operand:SI 2 "s_register_operand" "r,r"))
504                  (match_operand:DI 1 "s_register_operand" "r,0")))
505    (clobber (reg:CC CC_REGNUM))]
506   "TARGET_ARM && !TARGET_CIRRUS"
507   "#"
508   "TARGET_ARM && reload_completed"
509   [(parallel [(set (reg:CC_C CC_REGNUM)
510                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
511                                  (match_dup 1)))
512               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
513    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
514                                (plus:SI (match_dup 4) (const_int 0))))]
515   "
516   {
517     operands[3] = gen_highpart (SImode, operands[0]);
518     operands[0] = gen_lowpart (SImode, operands[0]);
519     operands[4] = gen_highpart (SImode, operands[1]);
520     operands[1] = gen_lowpart (SImode, operands[1]);
521     operands[2] = gen_lowpart (SImode, operands[2]);
522   }"
523   [(set_attr "conds" "clob")
524    (set_attr "length" "8")]
527 (define_expand "addsi3"
528   [(set (match_operand:SI          0 "s_register_operand" "")
529         (plus:SI (match_operand:SI 1 "s_register_operand" "")
530                  (match_operand:SI 2 "reg_or_int_operand" "")))]
531   "TARGET_EITHER"
532   "
533   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
534     {
535       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
536                           operands[1],
537                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
538       DONE;
539     }
540   "
543 ; If there is a scratch available, this will be faster than synthesising the
544 ; addition.
545 (define_peephole2
546   [(match_scratch:SI 3 "r")
547    (set (match_operand:SI          0 "s_register_operand" "")
548         (plus:SI (match_operand:SI 1 "s_register_operand" "")
549                  (match_operand:SI 2 "const_int_operand"  "")))]
550   "TARGET_ARM &&
551    !(const_ok_for_arm (INTVAL (operands[2]))
552      || const_ok_for_arm (-INTVAL (operands[2])))
553     && const_ok_for_arm (~INTVAL (operands[2]))"
554   [(set (match_dup 3) (match_dup 2))
555    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
556   ""
559 (define_insn_and_split "*arm_addsi3"
560   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
561         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
562                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
563   "TARGET_ARM"
564   "@
565    add%?\\t%0, %1, %2
566    sub%?\\t%0, %1, #%n2
567    #"
568   "TARGET_ARM &&
569    GET_CODE (operands[2]) == CONST_INT
570    && !(const_ok_for_arm (INTVAL (operands[2]))
571         || const_ok_for_arm (-INTVAL (operands[2])))"
572   [(clobber (const_int 0))]
573   "
574   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
575                       operands[1], 0);
576   DONE;
577   "
578   [(set_attr "length" "4,4,16")
579    (set_attr "predicable" "yes")]
582 ;; Register group 'k' is a single register group containing only the stack
583 ;; register.  Trying to reload it will always fail catastrophically,
584 ;; so never allow those alternatives to match if reloading is needed.
586 (define_insn "*thumb_addsi3"
587   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
588         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
589                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
590   "TARGET_THUMB"
591   "*
592    static const char * const asms[] = 
593    {
594      \"add\\t%0, %0, %2\",
595      \"sub\\t%0, %0, #%n2\",
596      \"add\\t%0, %1, %2\",
597      \"add\\t%0, %0, %2\",
598      \"add\\t%0, %0, %2\",
599      \"add\\t%0, %1, %2\",
600      \"add\\t%0, %1, %2\"
601    };
602    if ((which_alternative == 2 || which_alternative == 6)
603        && GET_CODE (operands[2]) == CONST_INT
604        && INTVAL (operands[2]) < 0)
605      return \"sub\\t%0, %1, #%n2\";
606    return asms[which_alternative];
607   "
608   [(set_attr "length" "2")]
611 ;; Reloading and elimination of the frame pointer can
612 ;; sometimes cause this optimization to be missed.
613 (define_peephole2
614   [(set (match_operand:SI 0 "register_operand" "")
615         (match_operand:SI 1 "const_int_operand" ""))
616    (set (match_dup 0)
617         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
618   "TARGET_THUMB
619    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
620    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
621    && (INTVAL (operands[1]) & 3) == 0"
622   [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
623   ""
626 (define_insn "*addsi3_compare0"
627   [(set (reg:CC_NOOV CC_REGNUM)
628         (compare:CC_NOOV
629          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
630                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
631          (const_int 0)))
632    (set (match_operand:SI 0 "s_register_operand" "=r,r")
633         (plus:SI (match_dup 1) (match_dup 2)))]
634   "TARGET_ARM"
635   "@
636    add%?s\\t%0, %1, %2
637    sub%?s\\t%0, %1, #%n2"
638   [(set_attr "conds" "set")]
641 (define_insn "*addsi3_compare0_scratch"
642   [(set (reg:CC_NOOV CC_REGNUM)
643         (compare:CC_NOOV
644          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
645                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
646          (const_int 0)))]
647   "TARGET_ARM"
648   "@
649    cmn%?\\t%0, %1
650    cmp%?\\t%0, #%n1"
651   [(set_attr "conds" "set")]
654 ;; These patterns are the same ones as the two regular addsi3_compare0
655 ;; patterns, except we write them slightly different - the combiner
656 ;; tends to generate them this way.
657 (define_insn "*addsi3_compare0_for_combiner"
658   [(set (reg:CC CC_REGNUM)
659         (compare:CC
660          (match_operand:SI 1 "s_register_operand" "r,r")
661          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
662    (set (match_operand:SI 0 "s_register_operand" "=r,r")
663         (plus:SI (match_dup 1) (match_dup 2)))]
664   "TARGET_ARM"
665   "@
666    add%?s\\t%0, %1, %2
667    sub%?s\\t%0, %1, #%n2"
668   [(set_attr "conds" "set")]
671 (define_insn "*addsi3_compare0_scratch_for_combiner"
672   [(set (reg:CC CC_REGNUM)
673         (compare:CC
674          (match_operand:SI 0 "s_register_operand" "r,r")
675          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
676   "TARGET_ARM"
677   "@
678    cmn%?\\t%0, %1
679    cmp%?\\t%0, #%n1"
680   [(set_attr "conds" "set")]
683 ;; The next four insns work because they compare the result with one of
684 ;; the operands, and we know that the use of the condition code is
685 ;; either GEU or LTU, so we can use the carry flag from the addition
686 ;; instead of doing the compare a second time.
687 (define_insn "*addsi3_compare_op1"
688   [(set (reg:CC_C CC_REGNUM)
689         (compare:CC_C
690          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
691                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
692          (match_dup 1)))
693    (set (match_operand:SI 0 "s_register_operand" "=r,r")
694         (plus:SI (match_dup 1) (match_dup 2)))]
695   "TARGET_ARM"
696   "@
697    add%?s\\t%0, %1, %2
698    sub%?s\\t%0, %1, #%n2"
699   [(set_attr "conds" "set")]
702 (define_insn "*addsi3_compare_op2"
703   [(set (reg:CC_C CC_REGNUM)
704         (compare:CC_C
705          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
706                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
707          (match_dup 2)))
708    (set (match_operand:SI 0 "s_register_operand" "=r,r")
709         (plus:SI (match_dup 1) (match_dup 2)))]
710   "TARGET_ARM"
711   "@
712    add%?s\\t%0, %1, %2
713    sub%?s\\t%0, %1, #%n2"
714   [(set_attr "conds" "set")]
717 (define_insn "*compare_addsi2_op0"
718   [(set (reg:CC_C CC_REGNUM)
719         (compare:CC_C
720          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
721                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
722          (match_dup 0)))]
723   "TARGET_ARM"
724   "@
725    cmn%?\\t%0, %1
726    cmp%?\\t%0, #%n1"
727   [(set_attr "conds" "set")]
730 (define_insn "*compare_addsi2_op1"
731   [(set (reg:CC_C CC_REGNUM)
732         (compare:CC_C
733          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
734                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
735          (match_dup 1)))]
736   "TARGET_ARM"
737   "@
738    cmn%?\\t%0, %1
739    cmp%?\\t%0, #%n1"
740   [(set_attr "conds" "set")]
743 (define_insn "*addsi3_carryin"
744   [(set (match_operand:SI 0 "s_register_operand" "=r")
745         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
746                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
747                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
748   "TARGET_ARM"
749   "adc%?\\t%0, %1, %2"
750   [(set_attr "conds" "use")]
753 (define_insn "*addsi3_carryin_shift"
754   [(set (match_operand:SI 0 "s_register_operand" "")
755         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
756                  (plus:SI
757                    (match_operator:SI 2 "shift_operator"
758                       [(match_operand:SI 3 "s_register_operand" "")
759                        (match_operand:SI 4 "reg_or_int_operand" "")])
760                     (match_operand:SI 1 "s_register_operand" ""))))]
761   "TARGET_ARM"
762   "adc%?\\t%0, %1, %3%S2"
763   [(set_attr "conds" "use")]
766 (define_insn "*addsi3_carryin_alt1"
767   [(set (match_operand:SI 0 "s_register_operand" "=r")
768         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
769                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
770                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
771   "TARGET_ARM"
772   "adc%?\\t%0, %1, %2"
773   [(set_attr "conds" "use")]
776 (define_insn "*addsi3_carryin_alt2"
777   [(set (match_operand:SI 0 "s_register_operand" "=r")
778         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
779                           (match_operand:SI 1 "s_register_operand" "r"))
780                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
781   "TARGET_ARM"
782   "adc%?\\t%0, %1, %2"
783   [(set_attr "conds" "use")]
786 (define_insn "*addsi3_carryin_alt3"
787   [(set (match_operand:SI 0 "s_register_operand" "=r")
788         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
789                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
790                  (match_operand:SI 1 "s_register_operand" "r")))]
791   "TARGET_ARM"
792   "adc%?\\t%0, %1, %2"
793   [(set_attr "conds" "use")]
796 (define_insn "incscc"
797   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
798         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
799                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
800                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
801   "TARGET_ARM"
802   "@
803   add%d2\\t%0, %1, #1
804   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
805   [(set_attr "conds" "use")
806    (set_attr "length" "4,8")]
809 (define_insn "*arm_addsf3"
810   [(set (match_operand:SF          0 "s_register_operand" "=f,f")
811         (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
812                  (match_operand:SF 2 "fpu_add_operand"    "fG,H")))]
813   "TARGET_ARM && TARGET_HARD_FLOAT"
814   "@
815    adf%?s\\t%0, %1, %2
816    suf%?s\\t%0, %1, #%N2"
817   [(set_attr "type" "farith")
818    (set_attr "predicable" "yes")]
821 (define_insn "*arm_adddf3"
822   [(set (match_operand:DF          0 "s_register_operand" "=f,f")
823         (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
824                  (match_operand:DF 2 "fpu_add_operand"    "fG,H")))]
825   "TARGET_ARM && TARGET_HARD_FLOAT"
826   "@
827    adf%?d\\t%0, %1, %2
828    suf%?d\\t%0, %1, #%N2"
829   [(set_attr "type" "farith")
830    (set_attr "predicable" "yes")]
833 (define_insn "*adddf_esfdf_df"
834   [(set (match_operand:DF           0 "s_register_operand" "=f,f")
835         (plus:DF (float_extend:DF
836                   (match_operand:SF 1 "s_register_operand"  "f,f"))
837                  (match_operand:DF  2 "fpu_add_operand"    "fG,H")))]
838   "TARGET_ARM && TARGET_HARD_FLOAT"
839   "@
840    adf%?d\\t%0, %1, %2
841    suf%?d\\t%0, %1, #%N2"
842   [(set_attr "type" "farith")
843    (set_attr "predicable" "yes")]
846 (define_insn "*adddf_df_esfdf"
847   [(set (match_operand:DF           0 "s_register_operand" "=f")
848         (plus:DF (match_operand:DF  1 "s_register_operand"  "f")
849                  (float_extend:DF
850                   (match_operand:SF 2 "s_register_operand"  "f"))))]
851   "TARGET_ARM && TARGET_HARD_FLOAT"
852   "adf%?d\\t%0, %1, %2"
853   [(set_attr "type" "farith")
854    (set_attr "predicable" "yes")]
857 (define_insn "*adddf_esfdf_esfdf"
858   [(set (match_operand:DF           0 "s_register_operand" "=f")
859         (plus:DF (float_extend:DF 
860                   (match_operand:SF 1 "s_register_operand" "f"))
861                  (float_extend:DF
862                   (match_operand:SF 2 "s_register_operand" "f"))))]
863   "TARGET_ARM && TARGET_HARD_FLOAT"
864   "adf%?d\\t%0, %1, %2"
865   [(set_attr "type" "farith")
866    (set_attr "predicable" "yes")]
869 (define_expand "subdi3"
870  [(parallel
871    [(set (match_operand:DI            0 "s_register_operand" "")
872           (minus:DI (match_operand:DI 1 "s_register_operand" "")
873                     (match_operand:DI 2 "s_register_operand" "")))
874     (clobber (reg:CC CC_REGNUM))])]
875   "TARGET_EITHER"
876   "
877   if (TARGET_CIRRUS
878       && TARGET_ARM
879       && cirrus_fp_register (operands[0], DImode)
880       && cirrus_fp_register (operands[1], DImode))
881     {
882       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
883       DONE;
884     }
886   if (TARGET_THUMB)
887     {
888       if (GET_CODE (operands[1]) != REG)
889         operands[1] = force_reg (SImode, operands[1]);
890       if (GET_CODE (operands[2]) != REG)
891         operands[2] = force_reg (SImode, operands[2]);
892      }  
893   "
896 (define_insn "*arm_subdi3"
897   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
898         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
899                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
900    (clobber (reg:CC CC_REGNUM))]
901   "TARGET_ARM"
902   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
903   [(set_attr "conds" "clob")
904    (set_attr "length" "8")]
907 (define_insn "*thumb_subdi3"
908   [(set (match_operand:DI           0 "register_operand" "=l")
909         (minus:DI (match_operand:DI 1 "register_operand"  "0")
910                   (match_operand:DI 2 "register_operand"  "l")))
911    (clobber (reg:CC CC_REGNUM))]
912   "TARGET_THUMB"
913   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
914   [(set_attr "length" "4")]
917 (define_insn "*subdi_di_zesidi"
918   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
919         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
920                   (zero_extend:DI
921                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
922    (clobber (reg:CC CC_REGNUM))]
923   "TARGET_ARM"
924   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
925   [(set_attr "conds" "clob")
926    (set_attr "length" "8")]
929 (define_insn "*subdi_di_sesidi"
930   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
931         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
932                   (sign_extend:DI
933                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
934    (clobber (reg:CC CC_REGNUM))]
935   "TARGET_ARM"
936   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
937   [(set_attr "conds" "clob")
938    (set_attr "length" "8")]
941 (define_insn "*subdi_zesidi_di"
942   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
943         (minus:DI (zero_extend:DI
944                    (match_operand:SI 2 "s_register_operand"  "r,r"))
945                   (match_operand:DI  1 "s_register_operand" "?r,0")))
946    (clobber (reg:CC CC_REGNUM))]
947   "TARGET_ARM"
948   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
949   [(set_attr "conds" "clob")
950    (set_attr "length" "8")]
953 (define_insn "*subdi_sesidi_di"
954   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
955         (minus:DI (sign_extend:DI
956                    (match_operand:SI 2 "s_register_operand"   "r,r"))
957                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
958    (clobber (reg:CC CC_REGNUM))]
959   "TARGET_ARM"
960   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
961   [(set_attr "conds" "clob")
962    (set_attr "length" "8")]
965 (define_insn "*subdi_zesidi_zesidi"
966   [(set (match_operand:DI            0 "s_register_operand" "=r")
967         (minus:DI (zero_extend:DI
968                    (match_operand:SI 1 "s_register_operand"  "r"))
969                   (zero_extend:DI
970                    (match_operand:SI 2 "s_register_operand"  "r"))))
971    (clobber (reg:CC CC_REGNUM))]
972   "TARGET_ARM"
973   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
974   [(set_attr "conds" "clob")
975    (set_attr "length" "8")]
978 (define_expand "subsi3"
979   [(set (match_operand:SI           0 "s_register_operand" "")
980         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
981                   (match_operand:SI 2 "s_register_operand" "")))]
982   "TARGET_EITHER"
983   "
984   if (GET_CODE (operands[1]) == CONST_INT)
985     {
986       if (TARGET_ARM)
987         {
988           arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
989                               operands[2],
990                               (no_new_pseudos ? 0
991                                :  preserve_subexpressions_p ()));
992           DONE;
993         }
994       else /* TARGET_THUMB */
995         operands[1] = force_reg (SImode, operands[1]);
996     }
997   "
1000 (define_insn "*thumb_subsi3_insn"
1001   [(set (match_operand:SI           0 "register_operand" "=l")
1002         (minus:SI (match_operand:SI 1 "register_operand" "l")
1003                   (match_operand:SI 2 "register_operand" "l")))]
1004   "TARGET_THUMB"
1005   "sub\\t%0, %1, %2"
1006   [(set_attr "length" "2")]
1009 (define_insn_and_split "*arm_subsi3_insn"
1010   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
1011         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1012                   (match_operand:SI 2 "s_register_operand" "r,r")))]
1013   "TARGET_ARM"
1014   "@
1015    rsb%?\\t%0, %2, %1
1016    #"
1017   "TARGET_ARM
1018    && GET_CODE (operands[1]) == CONST_INT
1019    && !const_ok_for_arm (INTVAL (operands[1]))"
1020   [(clobber (const_int 0))]
1021   "
1022   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1023                       operands[2], 0);
1024   DONE;
1025   "
1026   [(set_attr "length" "4,16")
1027    (set_attr "predicable" "yes")]
1030 (define_peephole2
1031   [(match_scratch:SI 3 "r")
1032    (set (match_operand:SI           0 "s_register_operand" "")
1033         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1034                   (match_operand:SI 2 "s_register_operand" "")))]
1035   "TARGET_ARM
1036    && !const_ok_for_arm (INTVAL (operands[1]))
1037    && const_ok_for_arm (~INTVAL (operands[1]))"
1038   [(set (match_dup 3) (match_dup 1))
1039    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1040   ""
1043 (define_insn "*subsi3_compare0"
1044   [(set (reg:CC_NOOV CC_REGNUM)
1045         (compare:CC_NOOV
1046          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1047                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1048          (const_int 0)))
1049    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1050         (minus:SI (match_dup 1) (match_dup 2)))]
1051   "TARGET_ARM"
1052   "@
1053    sub%?s\\t%0, %1, %2
1054    rsb%?s\\t%0, %2, %1"
1055   [(set_attr "conds" "set")]
1058 (define_insn "decscc"
1059   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1060         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1061                   (match_operator:SI 2 "arm_comparison_operator"
1062                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1063   "TARGET_ARM"
1064   "@
1065    sub%d2\\t%0, %1, #1
1066    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1067   [(set_attr "conds" "use")
1068    (set_attr "length" "*,8")]
1071 (define_insn "*arm_subsf3"
1072   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1073         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1074                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1075   "TARGET_ARM && TARGET_HARD_FLOAT"
1076   "@
1077    suf%?s\\t%0, %1, %2
1078    rsf%?s\\t%0, %2, %1"
1079   [(set_attr "type" "farith")]
1082 (define_insn "*arm_subdf3"
1083   [(set (match_operand:DF           0 "s_register_operand" "=f,f")
1084         (minus:DF (match_operand:DF 1 "fpu_rhs_operand"     "f,G")
1085                   (match_operand:DF 2 "fpu_rhs_operand"    "fG,f")))]
1086   "TARGET_ARM && TARGET_HARD_FLOAT"
1087   "@
1088    suf%?d\\t%0, %1, %2
1089    rsf%?d\\t%0, %2, %1"
1090   [(set_attr "type" "farith")
1091    (set_attr "predicable" "yes")]
1094 (define_insn "*subdf_esfdf_df"
1095   [(set (match_operand:DF            0 "s_register_operand" "=f")
1096         (minus:DF (float_extend:DF
1097                    (match_operand:SF 1 "s_register_operand"  "f"))
1098                   (match_operand:DF  2 "fpu_rhs_operand"    "fG")))]
1099   "TARGET_ARM && TARGET_HARD_FLOAT"
1100   "suf%?d\\t%0, %1, %2"
1101   [(set_attr "type" "farith")
1102    (set_attr "predicable" "yes")]
1105 (define_insn "*subdf_df_esfdf"
1106   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1107         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1108                   (float_extend:DF
1109                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
1110   "TARGET_ARM && TARGET_HARD_FLOAT"
1111   "@
1112    suf%?d\\t%0, %1, %2
1113    rsf%?d\\t%0, %2, %1"
1114   [(set_attr "type" "farith")
1115    (set_attr "predicable" "yes")]
1118 (define_insn "*subdf_esfdf_esfdf"
1119   [(set (match_operand:DF 0 "s_register_operand" "=f")
1120         (minus:DF (float_extend:DF
1121                    (match_operand:SF 1 "s_register_operand" "f"))
1122                   (float_extend:DF
1123                    (match_operand:SF 2 "s_register_operand" "f"))))]
1124   "TARGET_ARM && TARGET_HARD_FLOAT"
1125   "suf%?d\\t%0, %1, %2"
1126   [(set_attr "type" "farith")
1127    (set_attr "predicable" "yes")]
1130 ;; Multiplication insns
1132 (define_expand "mulsi3"
1133   [(set (match_operand:SI          0 "s_register_operand" "")
1134         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1135                  (match_operand:SI 1 "s_register_operand" "")))]
1136   "TARGET_EITHER"
1137   ""
1140 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1141 (define_insn "*arm_mulsi3"
1142   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1143         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1144                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1145   "TARGET_ARM"
1146   "mul%?\\t%0, %2, %1"
1147   [(set_attr "type" "mult")
1148    (set_attr "predicable" "yes")]
1151 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1152 ; 1 and 2; are the same, because reload will make operand 0 match 
1153 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1154 ; this by adding another alternative to match this case, and then `reload' 
1155 ; it ourselves.  This alternative must come first.
1156 (define_insn "*thumb_mulsi3"
1157   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1158         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1159                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1160   "TARGET_THUMB"
1161   "*
1162   if (which_alternative < 2)
1163     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1164   else
1165     return \"mul\\t%0, %0, %2\";
1166   "
1167   [(set_attr "length" "4,4,2")
1168    (set_attr "type" "mult")]
1171 (define_insn "*mulsi3_compare0"
1172   [(set (reg:CC_NOOV CC_REGNUM)
1173         (compare:CC_NOOV (mult:SI
1174                           (match_operand:SI 2 "s_register_operand" "r,r")
1175                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1176                          (const_int 0)))
1177    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1178         (mult:SI (match_dup 2) (match_dup 1)))]
1179   "TARGET_ARM && !arm_is_xscale"
1180   "mul%?s\\t%0, %2, %1"
1181   [(set_attr "conds" "set")
1182    (set_attr "type" "mult")]
1185 (define_insn "*mulsi_compare0_scratch"
1186   [(set (reg:CC_NOOV CC_REGNUM)
1187         (compare:CC_NOOV (mult:SI
1188                           (match_operand:SI 2 "s_register_operand" "r,r")
1189                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1190                          (const_int 0)))
1191    (clobber (match_scratch:SI 0 "=&r,&r"))]
1192   "TARGET_ARM && !arm_is_xscale"
1193   "mul%?s\\t%0, %2, %1"
1194   [(set_attr "conds" "set")
1195    (set_attr "type" "mult")]
1198 ;; Unnamed templates to match MLA instruction.
1200 (define_insn "*mulsi3addsi"
1201   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1202         (plus:SI
1203           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1204                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1205           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1206   "TARGET_ARM"
1207   "mla%?\\t%0, %2, %1, %3"
1208   [(set_attr "type" "mult")
1209    (set_attr "predicable" "yes")]
1212 (define_insn "*mulsi3addsi_compare0"
1213   [(set (reg:CC_NOOV CC_REGNUM)
1214         (compare:CC_NOOV
1215          (plus:SI (mult:SI
1216                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1217                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1218                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1219          (const_int 0)))
1220    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1221         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1222                  (match_dup 3)))]
1223   "TARGET_ARM && !arm_is_xscale"
1224   "mla%?s\\t%0, %2, %1, %3"
1225   [(set_attr "conds" "set")
1226    (set_attr "type" "mult")]
1229 (define_insn "*mulsi3addsi_compare0_scratch"
1230   [(set (reg:CC_NOOV CC_REGNUM)
1231         (compare:CC_NOOV
1232          (plus:SI (mult:SI
1233                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1234                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1235                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1236          (const_int 0)))
1237    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1238   "TARGET_ARM && !arm_is_xscale"
1239   "mla%?s\\t%0, %2, %1, %3"
1240   [(set_attr "conds" "set")
1241    (set_attr "type" "mult")]
1244 ;; Unnamed template to match long long multiply-accumlate (smlal)
1246 (define_insn "*mulsidi3adddi"
1247   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1248         (plus:DI
1249          (mult:DI
1250           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1251           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1252          (match_operand:DI 1 "s_register_operand" "0")))]
1253   "TARGET_ARM && arm_fast_multiply"
1254   "smlal%?\\t%Q0, %R0, %3, %2"
1255   [(set_attr "type" "mult")
1256    (set_attr "predicable" "yes")]
1259 (define_insn "mulsidi3"
1260   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1261         (mult:DI
1262          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1263          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1264   "TARGET_ARM && arm_fast_multiply"
1265   "smull%?\\t%Q0, %R0, %1, %2"
1266   [(set_attr "type" "mult")
1267    (set_attr "predicable" "yes")]
1270 (define_insn "umulsidi3"
1271   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1272         (mult:DI
1273          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1274          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1275   "TARGET_ARM && arm_fast_multiply"
1276   "umull%?\\t%Q0, %R0, %1, %2"
1277   [(set_attr "type" "mult")
1278    (set_attr "predicable" "yes")]
1281 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1283 (define_insn "*umulsidi3adddi"
1284   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1285         (plus:DI
1286          (mult:DI
1287           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1288           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1289          (match_operand:DI 1 "s_register_operand" "0")))]
1290   "TARGET_ARM && arm_fast_multiply"
1291   "umlal%?\\t%Q0, %R0, %3, %2"
1292   [(set_attr "type" "mult")
1293    (set_attr "predicable" "yes")]
1296 (define_insn "smulsi3_highpart"
1297   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1298         (truncate:SI
1299          (lshiftrt:DI
1300           (mult:DI
1301            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1302            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1303           (const_int 32))))
1304    (clobber (match_scratch:SI 3 "=&r,&r"))]
1305   "TARGET_ARM && arm_fast_multiply"
1306   "smull%?\\t%3, %0, %2, %1"
1307   [(set_attr "type" "mult")
1308    (set_attr "predicable" "yes")]
1311 (define_insn "umulsi3_highpart"
1312   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1313         (truncate:SI
1314          (lshiftrt:DI
1315           (mult:DI
1316            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1317            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1318           (const_int 32))))
1319    (clobber (match_scratch:SI 3 "=&r,&r"))]
1320   "TARGET_ARM && arm_fast_multiply"
1321   "umull%?\\t%3, %0, %2, %1"
1322   [(set_attr "type" "mult")
1323    (set_attr "predicable" "yes")]
1326 (define_insn "mulhisi3"
1327   [(set (match_operand:SI 0 "s_register_operand" "=r")
1328         (mult:SI (sign_extend:SI
1329                   (match_operand:HI 1 "s_register_operand" "%r"))
1330                  (sign_extend:SI
1331                   (match_operand:HI 2 "s_register_operand" "r"))))]
1332   "TARGET_ARM && arm_is_xscale"
1333   "smulbb%?\\t%0, %1, %2"
1334   [(set_attr "type" "mult")]
1337 (define_insn "*mulhisi3addsi"
1338   [(set (match_operand:SI 0 "s_register_operand" "=r")
1339         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1340                  (mult:SI (sign_extend:SI
1341                            (match_operand:HI 2 "s_register_operand" "%r"))
1342                           (sign_extend:SI
1343                            (match_operand:HI 3 "s_register_operand" "r")))))]
1344   "TARGET_ARM && arm_is_xscale"
1345   "smlabb%?\\t%0, %2, %3, %1"
1346   [(set_attr "type" "mult")]
1349 (define_insn "*mulhidi3adddi"
1350   [(set (match_operand:DI 0 "s_register_operand" "=r")
1351         (plus:DI
1352           (match_operand:DI 1 "s_register_operand" "0")
1353           (mult:DI (sign_extend:DI
1354                     (match_operand:HI 2 "s_register_operand" "%r"))
1355                    (sign_extend:DI
1356                     (match_operand:HI 3 "s_register_operand" "r")))))]
1357   "TARGET_ARM && arm_is_xscale"
1358   "smlalbb%?\\t%Q0, %R0, %2, %3"
1359 [(set_attr "type" "mult")])
1361 (define_insn "*arm_mulsf3"
1362   [(set (match_operand:SF 0 "s_register_operand" "=f")
1363         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1364                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1365   "TARGET_ARM && TARGET_HARD_FLOAT"
1366   "fml%?s\\t%0, %1, %2"
1367   [(set_attr "type" "ffmul")
1368    (set_attr "predicable" "yes")]
1371 (define_insn "*arm_muldf3"
1372   [(set (match_operand:DF 0 "s_register_operand" "=f")
1373         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1374                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1375   "TARGET_ARM && TARGET_HARD_FLOAT"
1376   "muf%?d\\t%0, %1, %2"
1377   [(set_attr "type" "fmul")
1378    (set_attr "predicable" "yes")]
1381 (define_insn "*muldf_esfdf_df"
1382   [(set (match_operand:DF 0 "s_register_operand" "=f")
1383         (mult:DF (float_extend:DF
1384                   (match_operand:SF 1 "s_register_operand" "f"))
1385                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1386   "TARGET_ARM && TARGET_HARD_FLOAT"
1387   "muf%?d\\t%0, %1, %2"
1388   [(set_attr "type" "fmul")
1389    (set_attr "predicable" "yes")]
1392 (define_insn "*muldf_df_esfdf"
1393   [(set (match_operand:DF 0 "s_register_operand" "=f")
1394         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1395                  (float_extend:DF
1396                   (match_operand:SF 2 "s_register_operand" "f"))))]
1397   "TARGET_ARM && TARGET_HARD_FLOAT"
1398   "muf%?d\\t%0, %1, %2"
1399   [(set_attr "type" "fmul")
1400    (set_attr "predicable" "yes")]
1403 (define_insn "*muldf_esfdf_esfdf"
1404   [(set (match_operand:DF 0 "s_register_operand" "=f")
1405         (mult:DF
1406          (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1407          (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1408   "TARGET_ARM && TARGET_HARD_FLOAT"
1409   "muf%?d\\t%0, %1, %2"
1410   [(set_attr "type" "fmul")
1411    (set_attr "predicable" "yes")]
1414 ;; Division insns
1416 (define_insn "divsf3"
1417   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1418         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1419                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1420   "TARGET_ARM && TARGET_HARD_FLOAT"
1421   "@
1422    fdv%?s\\t%0, %1, %2
1423    frd%?s\\t%0, %2, %1"
1424   [(set_attr "type" "fdivs")
1425    (set_attr "predicable" "yes")]
1428 (define_insn "divdf3"
1429   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1430         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1431                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1432   "TARGET_ARM && TARGET_HARD_FLOAT"
1433   "@
1434    dvf%?d\\t%0, %1, %2
1435    rdf%?d\\t%0, %2, %1"
1436   [(set_attr "type" "fdivd")
1437    (set_attr "predicable" "yes")]
1440 (define_insn "*divdf_esfdf_df"
1441   [(set (match_operand:DF 0 "s_register_operand" "=f")
1442         (div:DF (float_extend:DF
1443                  (match_operand:SF 1 "s_register_operand" "f"))
1444                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1445   "TARGET_ARM && TARGET_HARD_FLOAT"
1446   "dvf%?d\\t%0, %1, %2"
1447   [(set_attr "type" "fdivd")
1448    (set_attr "predicable" "yes")]
1451 (define_insn "*divdf_df_esfdf"
1452   [(set (match_operand:DF 0 "s_register_operand" "=f")
1453         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1454                 (float_extend:DF
1455                  (match_operand:SF 2 "s_register_operand" "f"))))]
1456   "TARGET_ARM && TARGET_HARD_FLOAT"
1457   "rdf%?d\\t%0, %2, %1"
1458   [(set_attr "type" "fdivd")
1459    (set_attr "predicable" "yes")]
1462 (define_insn "*divdf_esfdf_esfdf"
1463   [(set (match_operand:DF 0 "s_register_operand" "=f")
1464         (div:DF (float_extend:DF
1465                  (match_operand:SF 1 "s_register_operand" "f"))
1466                 (float_extend:DF
1467                  (match_operand:SF 2 "s_register_operand" "f"))))]
1468   "TARGET_ARM && TARGET_HARD_FLOAT"
1469   "dvf%?d\\t%0, %1, %2"
1470   [(set_attr "type" "fdivd")
1471    (set_attr "predicable" "yes")]
1474 ;; Modulo insns
1476 (define_insn "modsf3"
1477   [(set (match_operand:SF 0 "s_register_operand" "=f")
1478         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1479                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1480   "TARGET_ARM && TARGET_HARD_FLOAT"
1481   "rmf%?s\\t%0, %1, %2"
1482   [(set_attr "type" "fdivs")
1483    (set_attr "predicable" "yes")]
1486 (define_insn "moddf3"
1487   [(set (match_operand:DF 0 "s_register_operand" "=f")
1488         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1489                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1490   "TARGET_ARM && TARGET_HARD_FLOAT"
1491   "rmf%?d\\t%0, %1, %2"
1492   [(set_attr "type" "fdivd")
1493    (set_attr "predicable" "yes")]
1496 (define_insn "*moddf_esfdf_df"
1497   [(set (match_operand:DF 0 "s_register_operand" "=f")
1498         (mod:DF (float_extend:DF
1499                  (match_operand:SF 1 "s_register_operand" "f"))
1500                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1501   "TARGET_ARM && TARGET_HARD_FLOAT"
1502   "rmf%?d\\t%0, %1, %2"
1503   [(set_attr "type" "fdivd")
1504    (set_attr "predicable" "yes")]
1507 (define_insn "*moddf_df_esfdf"
1508   [(set (match_operand:DF 0 "s_register_operand" "=f")
1509         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1510                 (float_extend:DF
1511                  (match_operand:SF 2 "s_register_operand" "f"))))]
1512   "TARGET_ARM && TARGET_HARD_FLOAT"
1513   "rmf%?d\\t%0, %1, %2"
1514   [(set_attr "type" "fdivd")
1515    (set_attr "predicable" "yes")]
1518 (define_insn "*moddf_esfdf_esfdf"
1519   [(set (match_operand:DF 0 "s_register_operand" "=f")
1520         (mod:DF (float_extend:DF
1521                  (match_operand:SF 1 "s_register_operand" "f"))
1522                 (float_extend:DF
1523                  (match_operand:SF 2 "s_register_operand" "f"))))]
1524   "TARGET_ARM && TARGET_HARD_FLOAT"
1525   "rmf%?d\\t%0, %1, %2"
1526   [(set_attr "type" "fdivd")
1527    (set_attr "predicable" "yes")]
1530 ;; Boolean and,ior,xor insns
1532 ;; Split up double word logical operations
1534 ;; Split up simple DImode logical operations.  Simply perform the logical
1535 ;; operation on the upper and lower halves of the registers.
1536 (define_split
1537   [(set (match_operand:DI 0 "s_register_operand" "")
1538         (match_operator:DI 6 "logical_binary_operator"
1539           [(match_operand:DI 1 "s_register_operand" "")
1540            (match_operand:DI 2 "s_register_operand" "")]))]
1541   "TARGET_ARM && reload_completed"
1542   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1543    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1544   "
1545   {
1546     operands[3] = gen_highpart (SImode, operands[0]);
1547     operands[0] = gen_lowpart (SImode, operands[0]);
1548     operands[4] = gen_highpart (SImode, operands[1]);
1549     operands[1] = gen_lowpart (SImode, operands[1]);
1550     operands[5] = gen_highpart (SImode, operands[2]);
1551     operands[2] = gen_lowpart (SImode, operands[2]);
1552   }"
1555 (define_split
1556   [(set (match_operand:DI 0 "s_register_operand" "")
1557         (match_operator:DI 6 "logical_binary_operator"
1558           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1559            (match_operand:DI 1 "s_register_operand" "")]))]
1560   "TARGET_ARM && reload_completed"
1561   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1562    (set (match_dup 3) (match_op_dup:SI 6
1563                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1564                          (match_dup 4)]))]
1565   "
1566   {
1567     operands[3] = gen_highpart (SImode, operands[0]);
1568     operands[0] = gen_lowpart (SImode, operands[0]);
1569     operands[4] = gen_highpart (SImode, operands[1]);
1570     operands[1] = gen_lowpart (SImode, operands[1]);
1571     operands[5] = gen_highpart (SImode, operands[2]);
1572     operands[2] = gen_lowpart (SImode, operands[2]);
1573   }"
1576 ;; The zero extend of operand 2 means we can just copy the high part of
1577 ;; operand1 into operand0.
1578 (define_split
1579   [(set (match_operand:DI 0 "s_register_operand" "")
1580         (ior:DI
1581           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1582           (match_operand:DI 1 "s_register_operand" "")))]
1583   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1584   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1585    (set (match_dup 3) (match_dup 4))]
1586   "
1587   {
1588     operands[4] = gen_highpart (SImode, operands[1]);
1589     operands[3] = gen_highpart (SImode, operands[0]);
1590     operands[0] = gen_lowpart (SImode, operands[0]);
1591     operands[1] = gen_lowpart (SImode, operands[1]);
1592   }"
1595 ;; The zero extend of operand 2 means we can just copy the high part of
1596 ;; operand1 into operand0.
1597 (define_split
1598   [(set (match_operand:DI 0 "s_register_operand" "")
1599         (xor:DI
1600           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1601           (match_operand:DI 1 "s_register_operand" "")))]
1602   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1603   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1604    (set (match_dup 3) (match_dup 4))]
1605   "
1606   {
1607     operands[4] = gen_highpart (SImode, operands[1]);
1608     operands[3] = gen_highpart (SImode, operands[0]);
1609     operands[0] = gen_lowpart (SImode, operands[0]);
1610     operands[1] = gen_lowpart (SImode, operands[1]);
1611   }"
1614 (define_insn "anddi3"
1615   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1616         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1617                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1618   "TARGET_ARM"
1619   "#"
1620   [(set_attr "length" "8")]
1623 (define_insn_and_split "*anddi_zesidi_di"
1624   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1625         (and:DI (zero_extend:DI
1626                  (match_operand:SI 2 "s_register_operand" "r,r"))
1627                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1628   "TARGET_ARM"
1629   "#"
1630   "TARGET_ARM && reload_completed"
1631   ; The zero extend of operand 2 clears the high word of the output
1632   ; operand.
1633   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1634    (set (match_dup 3) (const_int 0))]
1635   "
1636   {
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   }"
1641   [(set_attr "length" "8")]
1644 (define_insn "*anddi_sesdi_di"
1645   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1646         (and:DI (sign_extend:DI
1647                  (match_operand:SI 2 "s_register_operand" "r,r"))
1648                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1649   "TARGET_ARM"
1650   "#"
1651   [(set_attr "length" "8")]
1654 (define_expand "andsi3"
1655   [(set (match_operand:SI         0 "s_register_operand" "")
1656         (and:SI (match_operand:SI 1 "s_register_operand" "")
1657                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1658   "TARGET_EITHER"
1659   "
1660   if (TARGET_ARM)
1661     {
1662       if (GET_CODE (operands[2]) == CONST_INT)
1663         {
1664           arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1665                               operands[1],
1666                               (no_new_pseudos
1667                                ? 0 : preserve_subexpressions_p ()));
1668           DONE;
1669         }
1670     }
1671   else /* TARGET_THUMB */
1672     {
1673       if (GET_CODE (operands[2]) != CONST_INT)
1674         operands[2] = force_reg (SImode, operands[2]);
1675       else
1676         {
1677           int i;
1678           
1679           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1680             {
1681               operands[2] = force_reg (SImode,
1682                                        GEN_INT (~INTVAL (operands[2])));
1683               
1684               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1685               
1686               DONE;
1687             }
1689           for (i = 9; i <= 31; i++)
1690             {
1691               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1692                 {
1693                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1694                                         const0_rtx));
1695                   DONE;
1696                 }
1697               else if ((((HOST_WIDE_INT) 1) << i) - 1
1698                        == ~INTVAL (operands[2]))
1699                 {
1700                   rtx shift = GEN_INT (i);
1701                   rtx reg = gen_reg_rtx (SImode);
1702                 
1703                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1704                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1705                   
1706                   DONE;
1707                 }
1708             }
1710           operands[2] = force_reg (SImode, operands[2]);
1711         }
1712     }
1713   "
1716 (define_insn_and_split "*arm_andsi3_insn"
1717   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1718         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1719                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1720   "TARGET_ARM"
1721   "@
1722    and%?\\t%0, %1, %2
1723    bic%?\\t%0, %1, #%B2
1724    #"
1725   "TARGET_ARM
1726    && GET_CODE (operands[2]) == CONST_INT
1727    && !(const_ok_for_arm (INTVAL (operands[2]))
1728         || const_ok_for_arm (~INTVAL (operands[2])))"
1729   [(clobber (const_int 0))]
1730   "
1731   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1732                        operands[1], 0);
1733   DONE;
1734   "
1735   [(set_attr "length" "4,4,16")
1736    (set_attr "predicable" "yes")]
1739 (define_insn "*thumb_andsi3_insn"
1740   [(set (match_operand:SI         0 "register_operand" "=l")
1741         (and:SI (match_operand:SI 1 "register_operand" "%0")
1742                 (match_operand:SI 2 "register_operand" "l")))]
1743   "TARGET_THUMB"
1744   "and\\t%0, %0, %2"
1745   [(set_attr "length" "2")]
1748 (define_insn "*andsi3_compare0"
1749   [(set (reg:CC_NOOV CC_REGNUM)
1750         (compare:CC_NOOV
1751          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1752                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1753          (const_int 0)))
1754    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1755         (and:SI (match_dup 1) (match_dup 2)))]
1756   "TARGET_ARM"
1757   "@
1758    and%?s\\t%0, %1, %2
1759    bic%?s\\t%0, %1, #%B2"
1760   [(set_attr "conds" "set")]
1763 (define_insn "*andsi3_compare0_scratch"
1764   [(set (reg:CC_NOOV CC_REGNUM)
1765         (compare:CC_NOOV
1766          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1767                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1768          (const_int 0)))
1769    (clobber (match_scratch:SI 2 "=X,r"))]
1770   "TARGET_ARM"
1771   "@
1772    tst%?\\t%0, %1
1773    bic%?s\\t%2, %0, #%B1"
1774   [(set_attr "conds" "set")]
1777 (define_insn "*zeroextractsi_compare0_scratch"
1778   [(set (reg:CC_NOOV CC_REGNUM)
1779         (compare:CC_NOOV (zero_extract:SI
1780                           (match_operand:SI 0 "s_register_operand" "r")
1781                           (match_operand 1 "const_int_operand" "n")
1782                           (match_operand 2 "const_int_operand" "n"))
1783                          (const_int 0)))]
1784   "TARGET_ARM
1785   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1786       && INTVAL (operands[1]) > 0 
1787       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1788       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1789   "*
1790   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1791                          << INTVAL (operands[2]));
1792   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1793   return \"\";
1794   "
1795   [(set_attr "conds" "set")]
1798 (define_insn "*ne_zeroextractsi"
1799   [(set (match_operand:SI 0 "s_register_operand" "=r")
1800         (ne:SI (zero_extract:SI
1801                 (match_operand:SI 1 "s_register_operand" "r")
1802                 (match_operand:SI 2 "const_int_operand" "n")
1803                 (match_operand:SI 3 "const_int_operand" "n"))
1804                (const_int 0)))
1805    (clobber (reg:CC CC_REGNUM))]
1806   "TARGET_ARM
1807    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1808        && INTVAL (operands[2]) > 0 
1809        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1810        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1811   "*
1812   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1813                          << INTVAL (operands[3]));
1814   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1815   return \"movne\\t%0, #1\";
1816   "
1817   [(set_attr "conds" "clob")
1818    (set_attr "length" "8")]
1821 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1822 ;;; represented by the bitfield, then this will produce incorrect results.
1823 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1824 ;;; which have a real bit-field insert instruction, the truncation happens
1825 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1826 ;;; bit-field insert instruction, we would have to emit code here to truncate
1827 ;;; the value before we insert.  This loses some of the advantage of having
1828 ;;; this insv pattern, so this pattern needs to be reevalutated.
1830 (define_expand "insv"
1831   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1832                          (match_operand:SI 1 "general_operand" "")
1833                          (match_operand:SI 2 "general_operand" ""))
1834         (match_operand:SI 3 "reg_or_int_operand" ""))]
1835   "TARGET_ARM"
1836   "
1837   {
1838     int start_bit = INTVAL (operands[2]);
1839     int width = INTVAL (operands[1]);
1840     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1841     rtx target, subtarget;
1843     target = operands[0];
1844     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1845        subreg as the final target.  */
1846     if (GET_CODE (target) == SUBREG)
1847       {
1848         subtarget = gen_reg_rtx (SImode);
1849         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1850             < GET_MODE_SIZE (SImode))
1851           target = SUBREG_REG (target);
1852       }
1853     else
1854       subtarget = target;    
1856     if (GET_CODE (operands[3]) == CONST_INT)
1857       {
1858         /* Since we are inserting a known constant, we may be able to
1859            reduce the number of bits that we have to clear so that
1860            the mask becomes simple.  */
1861         /* ??? This code does not check to see if the new mask is actually
1862            simpler.  It may not be.  */
1863         rtx op1 = gen_reg_rtx (SImode);
1864         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1865            start of this pattern.  */
1866         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1867         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1869         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1870         emit_insn (gen_iorsi3 (subtarget, op1,
1871                                GEN_INT (op3_value << start_bit)));
1872       }
1873     else if (start_bit == 0
1874              && !(const_ok_for_arm (mask)
1875                   || const_ok_for_arm (~mask)))
1876       {
1877         /* A Trick, since we are setting the bottom bits in the word,
1878            we can shift operand[3] up, operand[0] down, OR them together
1879            and rotate the result back again.  This takes 3 insns, and
1880            the third might be mergable into another op.  */
1881         /* The shift up copes with the possibility that operand[3] is
1882            wider than the bitfield.  */
1883         rtx op0 = gen_reg_rtx (SImode);
1884         rtx op1 = gen_reg_rtx (SImode);
1886         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1887         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1888         emit_insn (gen_iorsi3  (op1, op1, op0));
1889         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1890       }
1891     else if ((width + start_bit == 32)
1892              && !(const_ok_for_arm (mask)
1893                   || const_ok_for_arm (~mask)))
1894       {
1895         /* Similar trick, but slightly less efficient.  */
1897         rtx op0 = gen_reg_rtx (SImode);
1898         rtx op1 = gen_reg_rtx (SImode);
1900         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1901         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1902         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1903         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1904       }
1905     else
1906       {
1907         rtx op0 = GEN_INT (mask);
1908         rtx op1 = gen_reg_rtx (SImode);
1909         rtx op2 = gen_reg_rtx (SImode);
1911         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1912           {
1913             rtx tmp = gen_reg_rtx (SImode);
1915             emit_insn (gen_movsi (tmp, op0));
1916             op0 = tmp;
1917           }
1919         /* Mask out any bits in operand[3] that are not needed.  */
1920            emit_insn (gen_andsi3 (op1, operands[3], op0));
1922         if (GET_CODE (op0) == CONST_INT
1923             && (const_ok_for_arm (mask << start_bit)
1924                 || const_ok_for_arm (~(mask << start_bit))))
1925           {
1926             op0 = GEN_INT (~(mask << start_bit));
1927             emit_insn (gen_andsi3 (op2, operands[0], op0));
1928           }
1929         else
1930           {
1931             if (GET_CODE (op0) == CONST_INT)
1932               {
1933                 rtx tmp = gen_reg_rtx (SImode);
1935                 emit_insn (gen_movsi (tmp, op0));
1936                 op0 = tmp;
1937               }
1939             if (start_bit != 0)
1940               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1941             
1942             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1943           }
1945         if (start_bit != 0)
1946           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1948         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1949       }
1951     if (subtarget != target)
1952       {
1953         /* If TARGET is still a SUBREG, then it must be wider than a word,
1954            so we must be careful only to set the subword we were asked to.  */
1955         if (GET_CODE (target) == SUBREG)
1956           emit_move_insn (target, subtarget);
1957         else
1958           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1959       }
1961     DONE;
1962   }"
1965 ; constants for op 2 will never be given to these patterns.
1966 (define_insn_and_split "*anddi_notdi_di"
1967   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1968         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1969                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1970   "TARGET_ARM"
1971   "#"
1972   "TARGET_ARM && reload_completed"
1973   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1974    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1975   "
1976   {
1977     operands[3] = gen_highpart (SImode, operands[0]);
1978     operands[0] = gen_lowpart (SImode, operands[0]);
1979     operands[4] = gen_highpart (SImode, operands[1]);
1980     operands[1] = gen_lowpart (SImode, operands[1]);
1981     operands[5] = gen_highpart (SImode, operands[2]);
1982     operands[2] = gen_lowpart (SImode, operands[2]);
1983   }"
1984   [(set_attr "length" "8")
1985    (set_attr "predicable" "yes")]
1987   
1988 (define_insn_and_split "*anddi_notzesidi_di"
1989   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1990         (and:DI (not:DI (zero_extend:DI
1991                          (match_operand:SI 2 "s_register_operand" "r,r")))
1992                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1993   "TARGET_ARM"
1994   "@
1995    bic%?\\t%Q0, %Q1, %2
1996    #"
1997   ; (not (zero_extend ...)) allows us to just copy the high word from
1998   ; operand1 to operand0.
1999   "TARGET_ARM
2000    && reload_completed
2001    && operands[0] != operands[1]"
2002   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2003    (set (match_dup 3) (match_dup 4))]
2004   "
2005   {
2006     operands[3] = gen_highpart (SImode, operands[0]);
2007     operands[0] = gen_lowpart (SImode, operands[0]);
2008     operands[4] = gen_highpart (SImode, operands[1]);
2009     operands[1] = gen_lowpart (SImode, operands[1]);
2010   }"
2011   [(set_attr "length" "4,8")
2012    (set_attr "predicable" "yes")]
2014   
2015 (define_insn_and_split "*anddi_notsesidi_di"
2016   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2017         (and:DI (not:DI (sign_extend:DI
2018                          (match_operand:SI 2 "s_register_operand" "r,r")))
2019                 (match_operand:DI 1 "s_register_operand" "0,r")))]
2020   "TARGET_ARM"
2021   "#"
2022   "TARGET_ARM && reload_completed"
2023   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2024    (set (match_dup 3) (and:SI (not:SI
2025                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2026                                (match_dup 4)))]
2027   "
2028   {
2029     operands[3] = gen_highpart (SImode, operands[0]);
2030     operands[0] = gen_lowpart (SImode, operands[0]);
2031     operands[4] = gen_highpart (SImode, operands[1]);
2032     operands[1] = gen_lowpart (SImode, operands[1]);
2033   }"
2034   [(set_attr "length" "8")
2035    (set_attr "predicable" "yes")]
2037   
2038 (define_insn "andsi_notsi_si"
2039   [(set (match_operand:SI 0 "s_register_operand" "=r")
2040         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2041                 (match_operand:SI 1 "s_register_operand" "r")))]
2042   "TARGET_ARM"
2043   "bic%?\\t%0, %1, %2"
2044   [(set_attr "predicable" "yes")]
2047 (define_insn "bicsi3"
2048   [(set (match_operand:SI                 0 "register_operand" "=l")
2049         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2050                 (match_operand:SI         2 "register_operand" "0")))]
2051   "TARGET_THUMB"
2052   "bic\\t%0, %0, %1"
2053   [(set_attr "length" "2")]
2056 (define_insn "andsi_not_shiftsi_si"
2057   [(set (match_operand:SI                   0 "s_register_operand" "=r")
2058         (and:SI (not:SI (match_operator:SI  4 "shift_operator"
2059                          [(match_operand:SI 2 "s_register_operand"  "r")
2060                           (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
2061                 (match_operand:SI           1 "s_register_operand"  "r")))]
2062   "TARGET_ARM"
2063   "bic%?\\t%0, %1, %2%S4"
2064   [(set_attr "predicable" "yes")
2065    (set_attr "shift" "2")
2066    ]
2069 (define_insn "*andsi_notsi_si_compare0"
2070   [(set (reg:CC_NOOV CC_REGNUM)
2071         (compare:CC_NOOV
2072          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2073                  (match_operand:SI 1 "s_register_operand" "r"))
2074          (const_int 0)))
2075    (set (match_operand:SI 0 "s_register_operand" "=r")
2076         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2077   "TARGET_ARM"
2078   "bic%?s\\t%0, %1, %2"
2079   [(set_attr "conds" "set")]
2082 (define_insn "*andsi_notsi_si_compare0_scratch"
2083   [(set (reg:CC_NOOV CC_REGNUM)
2084         (compare:CC_NOOV
2085          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2086                  (match_operand:SI 1 "s_register_operand" "r"))
2087          (const_int 0)))
2088    (clobber (match_scratch:SI 0 "=r"))]
2089   "TARGET_ARM"
2090   "bic%?s\\t%0, %1, %2"
2091   [(set_attr "conds" "set")]
2094 (define_insn "iordi3"
2095   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2096         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2097                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2098   "TARGET_ARM"
2099   "#"
2100   [(set_attr "length" "8")
2101    (set_attr "predicable" "yes")]
2104 (define_insn "*iordi_zesidi_di"
2105   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2106         (ior:DI (zero_extend:DI
2107                  (match_operand:SI 2 "s_register_operand" "r,r"))
2108                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2109   "TARGET_ARM"
2110   "@
2111    orr%?\\t%Q0, %Q1, %2
2112    #"
2113   [(set_attr "length" "4,8")
2114    (set_attr "predicable" "yes")]
2117 (define_insn "*iordi_sesidi_di"
2118   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2119         (ior:DI (sign_extend:DI
2120                  (match_operand:SI 2 "s_register_operand" "r,r"))
2121                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2122   "TARGET_ARM"
2123   "#"
2124   [(set_attr "length" "8")
2125    (set_attr "predicable" "yes")]
2128 (define_expand "iorsi3"
2129   [(set (match_operand:SI         0 "s_register_operand" "")
2130         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2131                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2132   "TARGET_EITHER"
2133   "
2134   if (GET_CODE (operands[2]) == CONST_INT)
2135     {
2136       if (TARGET_ARM)
2137         {
2138           arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2139                               operands[1],
2140                               (no_new_pseudos
2141                               ? 0 : preserve_subexpressions_p ()));
2142           DONE;
2143         }
2144       else /* TARGET_THUMB */
2145         operands [2] = force_reg (SImode, operands [2]);
2146     }
2147   "
2150 (define_insn_and_split "*arm_iorsi3"
2151   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2152         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2153                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2154   "TARGET_ARM"
2155   "@
2156    orr%?\\t%0, %1, %2
2157    #"
2158   "TARGET_ARM
2159    && GET_CODE (operands[2]) == CONST_INT
2160    && !const_ok_for_arm (INTVAL (operands[2]))"
2161   [(clobber (const_int 0))]
2162   "
2163   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2164                       operands[1], 0);
2165   DONE;
2166   "
2167   [(set_attr "length" "4,16")
2168    (set_attr "predicable" "yes")]
2171 (define_insn "*thumb_iorsi3"
2172   [(set (match_operand:SI         0 "register_operand" "=l")
2173         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2174                 (match_operand:SI 2 "register_operand" "l")))]
2175   "TARGET_THUMB"
2176   "orr\\t%0, %0, %2"
2177   [(set_attr "length" "2")]
2180 (define_peephole2
2181   [(match_scratch:SI 3 "r")
2182    (set (match_operand:SI         0 "s_register_operand" "")
2183         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2184                 (match_operand:SI 2 "const_int_operand" "")))]
2185   "TARGET_ARM
2186    && !const_ok_for_arm (INTVAL (operands[2]))
2187    && const_ok_for_arm (~INTVAL (operands[2]))"
2188   [(set (match_dup 3) (match_dup 2))
2189    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2190   ""
2193 (define_insn "*iorsi3_compare0"
2194   [(set (reg:CC_NOOV CC_REGNUM)
2195         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2196                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2197                          (const_int 0)))
2198    (set (match_operand:SI 0 "s_register_operand" "=r")
2199         (ior:SI (match_dup 1) (match_dup 2)))]
2200   "TARGET_ARM"
2201   "orr%?s\\t%0, %1, %2"
2202   [(set_attr "conds" "set")]
2205 (define_insn "*iorsi3_compare0_scratch"
2206   [(set (reg:CC_NOOV CC_REGNUM)
2207         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2208                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2209                          (const_int 0)))
2210    (clobber (match_scratch:SI 0 "=r"))]
2211   "TARGET_ARM"
2212   "orr%?s\\t%0, %1, %2"
2213   [(set_attr "conds" "set")]
2216 (define_insn "xordi3"
2217   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2218         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2219                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2220   "TARGET_ARM"
2221   "#"
2222   [(set_attr "length" "8")
2223    (set_attr "predicable" "yes")]
2226 (define_insn "*xordi_zesidi_di"
2227   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2228         (xor:DI (zero_extend:DI
2229                  (match_operand:SI 2 "s_register_operand" "r,r"))
2230                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2231   "TARGET_ARM"
2232   "@
2233    eor%?\\t%Q0, %Q1, %2
2234    #"
2235   [(set_attr "length" "4,8")
2236    (set_attr "predicable" "yes")]
2239 (define_insn "*xordi_sesidi_di"
2240   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2241         (xor:DI (sign_extend:DI
2242                  (match_operand:SI 2 "s_register_operand" "r,r"))
2243                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2244   "TARGET_ARM"
2245   "#"
2246   [(set_attr "length" "8")
2247    (set_attr "predicable" "yes")]
2250 (define_expand "xorsi3"
2251   [(set (match_operand:SI         0 "s_register_operand" "")
2252         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2253                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2254   "TARGET_EITHER"
2255   "if (TARGET_THUMB)
2256      if (GET_CODE (operands[2]) == CONST_INT)
2257        operands[2] = force_reg (SImode, operands[2]);
2258   "
2261 (define_insn "*arm_xorsi3"
2262   [(set (match_operand:SI         0 "s_register_operand" "=r")
2263         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2264                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2265   "TARGET_ARM"
2266   "eor%?\\t%0, %1, %2"
2267   [(set_attr "predicable" "yes")]
2270 (define_insn "*thumb_xorsi3"
2271   [(set (match_operand:SI         0 "register_operand" "=l")
2272         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2273                 (match_operand:SI 2 "register_operand" "l")))]
2274   "TARGET_THUMB"
2275   "eor\\t%0, %0, %2"
2276   [(set_attr "length" "2")]
2279 (define_insn "*xorsi3_compare0"
2280   [(set (reg:CC_NOOV CC_REGNUM)
2281         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2282                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2283                          (const_int 0)))
2284    (set (match_operand:SI 0 "s_register_operand" "=r")
2285         (xor:SI (match_dup 1) (match_dup 2)))]
2286   "TARGET_ARM"
2287   "eor%?s\\t%0, %1, %2"
2288   [(set_attr "conds" "set")]
2291 (define_insn "*xorsi3_compare0_scratch"
2292   [(set (reg:CC_NOOV CC_REGNUM)
2293         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2294                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2295                          (const_int 0)))]
2296   "TARGET_ARM"
2297   "teq%?\\t%0, %1"
2298   [(set_attr "conds" "set")]
2301 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2302 ; (NOT D) we can sometimes merge the final NOT into one of the following
2303 ; insns.
2305 (define_split
2306   [(set (match_operand:SI 0 "s_register_operand" "")
2307         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2308                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2309                 (match_operand:SI 3 "arm_rhs_operand" "")))
2310    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2311   "TARGET_ARM"
2312   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2313                               (not:SI (match_dup 3))))
2314    (set (match_dup 0) (not:SI (match_dup 4)))]
2315   ""
2318 (define_insn "*andsi_iorsi3_notsi"
2319   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2320         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2321                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2322                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2323   "TARGET_ARM"
2324   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2325   [(set_attr "length" "8")
2326    (set_attr "predicable" "yes")]
2331 ;; Minimum and maximum insns
2333 (define_insn "smaxsi3"
2334   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2335         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2336                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2337    (clobber (reg:CC CC_REGNUM))]
2338   "TARGET_ARM"
2339   "@
2340    cmp\\t%1, %2\;movlt\\t%0, %2
2341    cmp\\t%1, %2\;movge\\t%0, %1
2342    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2343   [(set_attr "conds" "clob")
2344    (set_attr "length" "8,8,12")]
2347 (define_insn "sminsi3"
2348   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2349         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2350                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2351    (clobber (reg:CC CC_REGNUM))]
2352   "TARGET_ARM"
2353   "@
2354    cmp\\t%1, %2\;movge\\t%0, %2
2355    cmp\\t%1, %2\;movlt\\t%0, %1
2356    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2357   [(set_attr "conds" "clob")
2358    (set_attr "length" "8,8,12")]
2361 (define_insn "umaxsi3"
2362   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2363         (umax: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\;movcc\\t%0, %2
2369    cmp\\t%1, %2\;movcs\\t%0, %1
2370    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2371   [(set_attr "conds" "clob")
2372    (set_attr "length" "8,8,12")]
2375 (define_insn "uminsi3"
2376   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2377         (umin: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\;movcs\\t%0, %2
2383    cmp\\t%1, %2\;movcc\\t%0, %1
2384    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2385   [(set_attr "conds" "clob")
2386    (set_attr "length" "8,8,12")]
2389 (define_insn "*store_minmaxsi"
2390   [(set (match_operand:SI 0 "memory_operand" "=m")
2391         (match_operator:SI 3 "minmax_operator"
2392          [(match_operand:SI 1 "s_register_operand" "r")
2393           (match_operand:SI 2 "s_register_operand" "r")]))
2394    (clobber (reg:CC CC_REGNUM))]
2395   "TARGET_ARM"
2396   "*
2397   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2398                          operands[2]);
2399   output_asm_insn (\"cmp\\t%1, %2\", operands);
2400   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2401   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2402   return \"\";
2403   "
2404   [(set_attr "conds" "clob")
2405    (set_attr "length" "12")
2406    (set_attr "type" "store1")]
2409 ; Reject the frame pointer in operand[1], since reloading this after
2410 ; it has been eliminated can cause carnage.
2411 (define_insn "*minmax_arithsi"
2412   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2413         (match_operator:SI 4 "shiftable_operator"
2414          [(match_operator:SI 5 "minmax_operator"
2415            [(match_operand:SI 2 "s_register_operand" "r,r")
2416             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2417           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2418    (clobber (reg:CC CC_REGNUM))]
2419   "TARGET_ARM
2420    && (GET_CODE (operands[1]) != REG
2421        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2422            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2423   "*
2424   {
2425     enum rtx_code code = GET_CODE (operands[4]);
2427     operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2428                            operands[3]);
2429     output_asm_insn (\"cmp\\t%2, %3\", operands);
2430     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2431     if (which_alternative != 0 || operands[3] != const0_rtx
2432         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2433       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2434     return \"\";
2435   }"
2436   [(set_attr "conds" "clob")
2437    (set_attr "length" "12")]
2441 ;; Shift and rotation insns
2443 (define_expand "ashlsi3"
2444   [(set (match_operand:SI            0 "s_register_operand" "")
2445         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2446                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2447   "TARGET_EITHER"
2448   "
2449   if (GET_CODE (operands[2]) == CONST_INT
2450       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2451     {
2452       emit_insn (gen_movsi (operands[0], const0_rtx));
2453       DONE;
2454     }
2455   "
2458 (define_insn "*thumb_ashlsi3"
2459   [(set (match_operand:SI            0 "register_operand" "=l,l")
2460         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2461                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2462   "TARGET_THUMB"
2463   "lsl\\t%0, %1, %2"
2464   [(set_attr "length" "2")]
2467 (define_expand "ashrsi3"
2468   [(set (match_operand:SI              0 "s_register_operand" "")
2469         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2470                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2471   "TARGET_EITHER"
2472   "
2473   if (GET_CODE (operands[2]) == CONST_INT
2474       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2475     operands[2] = GEN_INT (31);
2476   "
2479 (define_insn "*thumb_ashrsi3"
2480   [(set (match_operand:SI              0 "register_operand" "=l,l")
2481         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2482                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2483   "TARGET_THUMB"
2484   "asr\\t%0, %1, %2"
2485   [(set_attr "length" "2")]
2488 (define_expand "lshrsi3"
2489   [(set (match_operand:SI              0 "s_register_operand" "")
2490         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2491                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2492   "TARGET_EITHER"
2493   "
2494   if (GET_CODE (operands[2]) == CONST_INT
2495       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2496     {
2497       emit_insn (gen_movsi (operands[0], const0_rtx));
2498       DONE;
2499     }
2500   "
2503 (define_insn "*thumb_lshrsi3"
2504   [(set (match_operand:SI              0 "register_operand" "=l,l")
2505         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2506                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2507   "TARGET_THUMB"
2508   "lsr\\t%0, %1, %2"
2509   [(set_attr "length" "2")]
2512 (define_expand "rotlsi3"
2513   [(set (match_operand:SI              0 "s_register_operand" "")
2514         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2515                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2516   "TARGET_ARM"
2517   "
2518   if (GET_CODE (operands[2]) == CONST_INT)
2519     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2520   else
2521     {
2522       rtx reg = gen_reg_rtx (SImode);
2523       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2524       operands[2] = reg;
2525     }
2526   "
2529 (define_expand "rotrsi3"
2530   [(set (match_operand:SI              0 "s_register_operand" "")
2531         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2532                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2533   "TARGET_EITHER"
2534   "
2535   if (TARGET_ARM)
2536     {
2537       if (GET_CODE (operands[2]) == CONST_INT
2538           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2539         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2540     }
2541   else /* TARGET_THUMB */
2542     {
2543       if (GET_CODE (operands [2]) == CONST_INT)
2544         operands [2] = force_reg (SImode, operands[2]);
2545     }
2546   "
2549 (define_insn "*thumb_rotrsi3"
2550   [(set (match_operand:SI              0 "register_operand" "=l")
2551         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2552                      (match_operand:SI 2 "register_operand" "l")))]
2553   "TARGET_THUMB"
2554   "ror\\t%0, %0, %2"
2555   [(set_attr "length" "2")]
2558 (define_expand "ashldi3"
2559   [(set (match_operand:DI            0 "s_register_operand" "")
2560         (ashift:DI (match_operand:DI 1 "general_operand"    "")
2561                    (match_operand:SI 2 "general_operand"    "")))]
2562   "TARGET_ARM && (TARGET_CIRRUS)"
2563   "
2564   if (! s_register_operand (operands[1], DImode))
2565     operands[1] = copy_to_mode_reg (DImode, operands[1]);
2566   if (! s_register_operand (operands[2], SImode))
2567     operands[2] = copy_to_mode_reg (SImode, operands[2]);
2568   "
2571 (define_insn "*arm_shiftsi3"
2572   [(set (match_operand:SI   0 "s_register_operand" "=r")
2573         (match_operator:SI  3 "shift_operator"
2574          [(match_operand:SI 1 "s_register_operand"  "r")
2575           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2576   "TARGET_ARM"
2577   "mov%?\\t%0, %1%S3"
2578   [(set_attr "predicable" "yes")
2579    (set_attr "shift" "1")
2580    ]
2583 (define_insn "*shiftsi3_compare0"
2584   [(set (reg:CC_NOOV CC_REGNUM)
2585         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2586                           [(match_operand:SI 1 "s_register_operand" "r")
2587                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2588                          (const_int 0)))
2589    (set (match_operand:SI 0 "s_register_operand" "=r")
2590         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2591   "TARGET_ARM"
2592   "mov%?s\\t%0, %1%S3"
2593   [(set_attr "conds" "set")
2594    (set_attr "shift" "1")
2595    ]
2598 (define_insn "*shiftsi3_compare0_scratch"
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    (clobber (match_scratch:SI 0 "=r"))]
2605   "TARGET_ARM"
2606   "mov%?s\\t%0, %1%S3"
2607   [(set_attr "conds" "set")
2608    (set_attr "shift" "1")
2609    ]
2612 (define_insn "*notsi_shiftsi"
2613   [(set (match_operand:SI 0 "s_register_operand" "=r")
2614         (not:SI (match_operator:SI 3 "shift_operator"
2615                  [(match_operand:SI 1 "s_register_operand" "r")
2616                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2617   "TARGET_ARM"
2618   "mvn%?\\t%0, %1%S3"
2619   [(set_attr "predicable" "yes")
2620    (set_attr "shift" "1")
2621    ]
2624 (define_insn "*notsi_shiftsi_compare0"
2625   [(set (reg:CC_NOOV CC_REGNUM)
2626         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2627                           [(match_operand:SI 1 "s_register_operand" "r")
2628                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2629                          (const_int 0)))
2630    (set (match_operand:SI 0 "s_register_operand" "=r")
2631         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2632   "TARGET_ARM"
2633   "mvn%?s\\t%0, %1%S3"
2634   [(set_attr "conds" "set")
2635    (set_attr "shift" "1")
2636    ]
2639 (define_insn "*not_shiftsi_compare0_scratch"
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    (clobber (match_scratch:SI 0 "=r"))]
2646   "TARGET_ARM"
2647   "mvn%?s\\t%0, %1%S3"
2648   [(set_attr "conds" "set")
2649    (set_attr "shift" "1")
2650   ]
2653 ;; We don't really have extzv, but defining this using shifts helps
2654 ;; to reduce register pressure later on.
2656 (define_expand "extzv"
2657   [(set (match_dup 4)
2658         (ashift:SI (match_operand:SI   1 "register_operand" "")
2659                    (match_operand:SI   2 "const_int_operand" "")))
2660    (set (match_operand:SI              0 "register_operand" "")
2661         (lshiftrt:SI (match_dup 4)
2662                      (match_operand:SI 3 "const_int_operand" "")))]
2663   "TARGET_THUMB"
2664   "
2665   {
2666     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2667     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2668     
2669     operands[3] = GEN_INT (rshift);
2670     
2671     if (lshift == 0)
2672       {
2673         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2674         DONE;
2675       }
2676       
2677     operands[2] = GEN_INT (lshift);
2678     operands[4] = gen_reg_rtx (SImode);
2679   }"
2683 ;; Unary arithmetic insns
2685 (define_expand "negdi2"
2686  [(parallel
2687    [(set (match_operand:DI          0 "s_register_operand" "")
2688           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2689     (clobber (reg:CC CC_REGNUM))])]
2690   "TARGET_EITHER"
2691   "
2692   if (TARGET_THUMB)
2693     {
2694       if (GET_CODE (operands[1]) != REG)
2695         operands[1] = force_reg (SImode, operands[1]);
2696      }
2697   "
2700 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2701 ;; The second alternative is to allow the common case of a *full* overlap.
2702 (define_insn "*arm_negdi2"
2703   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2704         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2705    (clobber (reg:CC CC_REGNUM))]
2706   "TARGET_ARM"
2707   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2708   [(set_attr "conds" "clob")
2709    (set_attr "length" "8")]
2712 (define_insn "*thumb_negdi2"
2713   [(set (match_operand:DI         0 "register_operand" "=&l")
2714         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2715    (clobber (reg:CC CC_REGNUM))]
2716   "TARGET_THUMB"
2717   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2718   [(set_attr "length" "6")]
2721 (define_expand "negsi2"
2722   [(set (match_operand:SI         0 "s_register_operand" "")
2723         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2724   "TARGET_EITHER"
2725   ""
2728 (define_insn "*arm_negsi2"
2729   [(set (match_operand:SI         0 "s_register_operand" "=r")
2730         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2731   "TARGET_ARM"
2732   "rsb%?\\t%0, %1, #0"
2733   [(set_attr "predicable" "yes")]
2736 (define_insn "*thumb_negsi2"
2737   [(set (match_operand:SI         0 "register_operand" "=l")
2738         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2739   "TARGET_THUMB"
2740   "neg\\t%0, %1"
2741   [(set_attr "length" "2")]
2744 (define_insn "*arm_negsf2"
2745   [(set (match_operand:SF         0 "s_register_operand" "=f")
2746         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2747   "TARGET_ARM && TARGET_HARD_FLOAT"
2748   "mnf%?s\\t%0, %1"
2749   [(set_attr "type" "ffarith")
2750    (set_attr "predicable" "yes")]
2753 (define_insn "*arm_negdf2"
2754   [(set (match_operand:DF         0 "s_register_operand" "=f")
2755         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2756   "TARGET_ARM && TARGET_HARD_FLOAT"
2757   "mnf%?d\\t%0, %1"
2758   [(set_attr "type" "ffarith")
2759    (set_attr "predicable" "yes")]
2762 (define_insn "*negdf_esfdf"
2763   [(set (match_operand:DF 0 "s_register_operand" "=f")
2764         (neg:DF (float_extend:DF
2765                  (match_operand:SF 1 "s_register_operand" "f"))))]
2766   "TARGET_ARM && TARGET_HARD_FLOAT"
2767   "mnf%?d\\t%0, %1"
2768   [(set_attr "type" "ffarith")
2769    (set_attr "predicable" "yes")]
2772 ;; abssi2 doesn't really clobber the condition codes if a different register
2773 ;; is being set.  To keep things simple, assume during rtl manipulations that
2774 ;; it does, but tell the final scan operator the truth.  Similarly for
2775 ;; (neg (abs...))
2777 (define_insn "*arm_abssi2"
2778   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2779         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2780    (clobber (reg:CC CC_REGNUM))]
2781   "TARGET_ARM"
2782   "@
2783    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2784    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2785   [(set_attr "conds" "clob,*")
2786    (set_attr "shift" "1")
2787    ;; predicable can't be set based on the variant, so left as no
2788    (set_attr "length" "8")]
2791 (define_insn "*neg_abssi2"
2792   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2793         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2794    (clobber (reg:CC CC_REGNUM))]
2795   "TARGET_ARM"
2796   "@
2797    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2798    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2799   [(set_attr "conds" "clob,*")
2800    (set_attr "shift" "1")
2801    ;; predicable can't be set based on the variant, so left as no
2802    (set_attr "length" "8")]
2805 (define_insn "*arm_abssf2"
2806   [(set (match_operand:SF          0 "s_register_operand" "=f")
2807          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2808   "TARGET_ARM && TARGET_HARD_FLOAT"
2809   "abs%?s\\t%0, %1"
2810   [(set_attr "type" "ffarith")
2811    (set_attr "predicable" "yes")]
2814 (define_insn "*arm_absdf2"
2815   [(set (match_operand:DF         0 "s_register_operand" "=f")
2816         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2817   "TARGET_ARM && TARGET_HARD_FLOAT"
2818   "abs%?d\\t%0, %1"
2819   [(set_attr "type" "ffarith")
2820    (set_attr "predicable" "yes")]
2823 (define_insn "*absdf_esfdf"
2824   [(set (match_operand:DF 0 "s_register_operand" "=f")
2825         (abs:DF (float_extend:DF
2826                  (match_operand:SF 1 "s_register_operand" "f"))))]
2827   "TARGET_ARM && TARGET_HARD_FLOAT"
2828   "abs%?d\\t%0, %1"
2829   [(set_attr "type" "ffarith")
2830    (set_attr "predicable" "yes")]
2833 (define_insn "sqrtsf2"
2834   [(set (match_operand:SF 0 "s_register_operand" "=f")
2835         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2836   "TARGET_ARM && TARGET_HARD_FLOAT"
2837   "sqt%?s\\t%0, %1"
2838   [(set_attr "type" "float_em")
2839    (set_attr "predicable" "yes")]
2842 (define_insn "sqrtdf2"
2843   [(set (match_operand:DF 0 "s_register_operand" "=f")
2844         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2845   "TARGET_ARM && TARGET_HARD_FLOAT"
2846   "sqt%?d\\t%0, %1"
2847   [(set_attr "type" "float_em")
2848    (set_attr "predicable" "yes")]
2851 (define_insn "*sqrtdf_esfdf"
2852   [(set (match_operand:DF 0 "s_register_operand" "=f")
2853         (sqrt:DF (float_extend:DF
2854                   (match_operand:SF 1 "s_register_operand" "f"))))]
2855   "TARGET_ARM && TARGET_HARD_FLOAT"
2856   "sqt%?d\\t%0, %1"
2857   [(set_attr "type" "float_em")
2858    (set_attr "predicable" "yes")]
2861 (define_insn_and_split "one_cmpldi2"
2862   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2863         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2864   "TARGET_ARM"
2865   "#"
2866   "TARGET_ARM && reload_completed"
2867   [(set (match_dup 0) (not:SI (match_dup 1)))
2868    (set (match_dup 2) (not:SI (match_dup 3)))]
2869   "
2870   {
2871     operands[2] = gen_highpart (SImode, operands[0]);
2872     operands[0] = gen_lowpart (SImode, operands[0]);
2873     operands[3] = gen_highpart (SImode, operands[1]);
2874     operands[1] = gen_lowpart (SImode, operands[1]);
2875   }"
2876   [(set_attr "length" "8")
2877    (set_attr "predicable" "yes")]
2880 (define_expand "one_cmplsi2"
2881   [(set (match_operand:SI         0 "s_register_operand" "")
2882         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2883   "TARGET_EITHER"
2884   ""
2887 (define_insn "*arm_one_cmplsi2"
2888   [(set (match_operand:SI         0 "s_register_operand" "=r")
2889         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2890   "TARGET_ARM"
2891   "mvn%?\\t%0, %1"
2892   [(set_attr "predicable" "yes")]
2895 (define_insn "*thumb_one_cmplsi2"
2896   [(set (match_operand:SI         0 "register_operand" "=l")
2897         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
2898   "TARGET_THUMB"
2899   "mvn\\t%0, %1"
2900   [(set_attr "length" "2")]
2903 (define_insn "*notsi_compare0"
2904   [(set (reg:CC_NOOV CC_REGNUM)
2905         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2906                          (const_int 0)))
2907    (set (match_operand:SI 0 "s_register_operand" "=r")
2908         (not:SI (match_dup 1)))]
2909   "TARGET_ARM"
2910   "mvn%?s\\t%0, %1"
2911   [(set_attr "conds" "set")]
2914 (define_insn "*notsi_compare0_scratch"
2915   [(set (reg:CC_NOOV CC_REGNUM)
2916         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2917                          (const_int 0)))
2918    (clobber (match_scratch:SI 0 "=r"))]
2919   "TARGET_ARM"
2920   "mvn%?s\\t%0, %1"
2921   [(set_attr "conds" "set")]
2924 ;; Fixed <--> Floating conversion insns
2926 (define_insn "*arm_floatsisf2"
2927   [(set (match_operand:SF           0 "s_register_operand" "=f")
2928         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2929   "TARGET_ARM && TARGET_HARD_FLOAT"
2930   "flt%?s\\t%0, %1"
2931   [(set_attr "type" "r_2_f")
2932    (set_attr "predicable" "yes")]
2935 (define_insn "*arm_floatsidf2"
2936   [(set (match_operand:DF           0 "s_register_operand" "=f")
2937         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2938   "TARGET_ARM && TARGET_HARD_FLOAT"
2939   "flt%?d\\t%0, %1"
2940   [(set_attr "type" "r_2_f")
2941    (set_attr "predicable" "yes")]
2944 (define_insn "*arm_fix_truncsfsi2"
2945   [(set (match_operand:SI         0 "s_register_operand" "=r")
2946         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2947   "TARGET_ARM && TARGET_HARD_FLOAT"
2948   "fix%?z\\t%0, %1"
2949   [(set_attr "type" "f_2_r")
2950    (set_attr "predicable" "yes")]
2953 (define_insn "*arm_fix_truncdfsi2"
2954   [(set (match_operand:SI         0 "s_register_operand" "=r")
2955         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2956   "TARGET_ARM && TARGET_HARD_FLOAT"
2957   "fix%?z\\t%0, %1"
2958   [(set_attr "type" "f_2_r")
2959    (set_attr "predicable" "yes")]
2962 ;; Truncation insns
2964 (define_insn "*arm_truncdfsf2"
2965   [(set (match_operand:SF 0 "s_register_operand" "=f")
2966         (float_truncate:SF
2967          (match_operand:DF 1 "s_register_operand" "f")))]
2968   "TARGET_ARM && TARGET_HARD_FLOAT"
2969   "mvf%?s\\t%0, %1"
2970   [(set_attr "type" "ffarith")
2971    (set_attr "predicable" "yes")]
2974 ;; Zero and sign extension instructions.
2976 (define_insn "zero_extendsidi2"
2977   [(set (match_operand:DI 0 "s_register_operand" "=r")
2978         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2979   "TARGET_ARM"
2980   "*
2981     if (REGNO (operands[1])
2982         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2983       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2984     return \"mov%?\\t%R0, #0\";
2985   "
2986   [(set_attr "length" "8")
2987    (set_attr "predicable" "yes")]
2990 (define_insn "zero_extendqidi2"
2991   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
2992         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2993   "TARGET_ARM"
2994   "@
2995    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2996    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2997   [(set_attr "length" "8")
2998    (set_attr "predicable" "yes")
2999    (set_attr "type" "*,load")
3000    (set_attr "pool_range" "*,4092")
3001    (set_attr "neg_pool_range" "*,4084")]
3004 (define_insn "extendsidi2"
3005   [(set (match_operand:DI 0 "s_register_operand" "=r")
3006         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3007   "TARGET_ARM"
3008   "*
3009     if (REGNO (operands[1])
3010         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3011       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3012     return \"mov%?\\t%R0, %Q0, asr #31\";
3013   "
3014   [(set_attr "length" "8")
3015    (set_attr "shift" "1")
3016    (set_attr "predicable" "yes")]
3019 (define_expand "zero_extendhisi2"
3020   [(set (match_dup 2)
3021         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3022                    (const_int 16)))
3023    (set (match_operand:SI 0 "s_register_operand" "")
3024         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3025   "TARGET_EITHER"
3026   "
3027   {
3028     if (TARGET_ARM)
3029       {
3030         if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3031           {
3032            /* Note: We do not have to worry about TARGET_MMU_TRAPS
3033               here because the insn below will generate an LDRH instruction
3034               rather than an LDR instruction, so we cannot get an unaligned
3035               word access.  */
3036             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3037                                     gen_rtx_ZERO_EXTEND (SImode,
3038                                                          operands[1])));
3039             DONE;
3040           }
3041         if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3042           {
3043             emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3044             DONE;
3045           }
3046         if (!s_register_operand (operands[1], HImode))
3047           operands[1] = copy_to_mode_reg (HImode, operands[1]);
3048         operands[1] = gen_lowpart (SImode, operands[1]);
3049         operands[2] = gen_reg_rtx (SImode);
3050       }
3051     else /* TARGET_THUMB */
3052       {
3053         if (GET_CODE (operands[1]) == MEM)
3054           {
3055             rtx tmp;
3057             tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3058             tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3059             emit_insn (tmp);
3060           }
3061         else
3062           {
3063             rtx ops[3];
3064             
3065             if (!s_register_operand (operands[1], HImode))
3066               operands[1] = copy_to_mode_reg (HImode, operands[1]);
3067             operands[1] = gen_lowpart (SImode, operands[1]);
3068             operands[2] = gen_reg_rtx (SImode);
3069             
3070             ops[0] = operands[2];
3071             ops[1] = operands[1];
3072             ops[2] = GEN_INT (16);
3073             
3074             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3075                                     gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3077             ops[0] = operands[0];
3078             ops[1] = operands[2];
3079             ops[2] = GEN_INT (16);
3081             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3082                                     gen_rtx_LSHIFTRT (SImode, ops[1],
3083                                                       ops[2])));
3084           }
3085         DONE; 
3086       }
3087   }"
3090 (define_insn "*thumb_zero_extendhisi2"
3091   [(set (match_operand:SI                 0 "register_operand" "=l")
3092         (zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3093   "TARGET_THUMB"
3094   "*
3095   rtx mem = XEXP (operands[1], 0);
3097   if (GET_CODE (mem) == CONST)
3098     mem = XEXP (mem, 0);
3099     
3100   if (GET_CODE (mem) == LABEL_REF)
3101     return \"ldr\\t%0, %1\";
3102     
3103   if (GET_CODE (mem) == PLUS)
3104     {
3105       rtx a = XEXP (mem, 0);
3106       rtx b = XEXP (mem, 1);
3108       /* This can happen due to bugs in reload.  */
3109       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3110         {
3111           rtx ops[2];
3112           ops[0] = operands[0];
3113           ops[1] = a;
3114       
3115           output_asm_insn (\"mov        %0, %1\", ops);
3117           XEXP (mem, 0) = operands[0];
3118        }
3120       else if (   GET_CODE (a) == LABEL_REF
3121                && GET_CODE (b) == CONST_INT)
3122         return \"ldr\\t%0, %1\";
3123     }
3124     
3125   return \"ldrh\\t%0, %1\";
3126   "
3127   [(set_attr "length" "4")
3128    (set_attr "type" "load")
3129    (set_attr "pool_range" "60")]
3132 (define_insn "*arm_zero_extendhisi2"
3133   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3134         (zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3135   "TARGET_ARM && arm_arch4"
3136   "ldr%?h\\t%0, %1"
3137   [(set_attr "type" "load")
3138    (set_attr "predicable" "yes")
3139    (set_attr "pool_range" "256")
3140    (set_attr "neg_pool_range" "244")]
3143 (define_split
3144   [(set (match_operand:SI 0 "s_register_operand" "")
3145         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3146    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3147   "TARGET_ARM && (!arm_arch4)"
3148   [(set (match_dup 2) (match_dup 1))
3149    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3150   "
3151   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3152     FAIL;
3153   "
3156 (define_split
3157   [(set (match_operand:SI 0 "s_register_operand" "")
3158         (match_operator:SI 3 "shiftable_operator"
3159          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3160           (match_operand:SI 4 "s_register_operand" "")]))
3161    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3162   "TARGET_ARM && (!arm_arch4)"
3163   [(set (match_dup 2) (match_dup 1))
3164    (set (match_dup 0)
3165         (match_op_dup 3
3166          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3167   "
3168   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3169     FAIL;
3170   "
3173 (define_expand "zero_extendqisi2"
3174   [(set (match_operand:SI 0 "s_register_operand" "")
3175         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3176   "TARGET_EITHER"
3177   "
3178   if (GET_CODE (operands[1]) != MEM)
3179     {
3180       if (TARGET_ARM)
3181         {
3182           emit_insn (gen_andsi3 (operands[0],
3183                                  gen_lowpart (SImode, operands[1]),
3184                                  GEN_INT (255)));
3185         }
3186       else /* TARGET_THUMB */
3187         {
3188           rtx temp = gen_reg_rtx (SImode);
3189           rtx ops[3];
3190           
3191           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3192           operands[1] = gen_lowpart (SImode, operands[1]);
3194           ops[0] = temp;
3195           ops[1] = operands[1];
3196           ops[2] = GEN_INT (24);
3198           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3199                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3200           
3201           ops[0] = operands[0];
3202           ops[1] = temp;
3203           ops[2] = GEN_INT (24);
3205           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3206                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3207         }
3208       DONE;
3209     }
3210   "
3213 (define_insn "*thumb_zero_extendqisi2"
3214   [(set (match_operand:SI                 0 "register_operand" "=l")
3215         (zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3216   "TARGET_THUMB"
3217   "ldrb\\t%0, %1"
3218   [(set_attr "length" "2")
3219    (set_attr "type" "load")
3220    (set_attr "pool_range" "32")]
3223 (define_insn "*arm_zero_extendqisi2"
3224   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3225         (zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3226   "TARGET_ARM"
3227   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3228   [(set_attr "type" "load")
3229    (set_attr "predicable" "yes")
3230    (set_attr "pool_range" "4096")
3231    (set_attr "neg_pool_range" "4084")]
3234 (define_split
3235   [(set (match_operand:SI 0 "s_register_operand" "")
3236         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3237    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3238   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3239   [(set (match_dup 2) (match_dup 1))
3240    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3241   ""
3244 (define_insn "*compareqi_eq0"
3245   [(set (reg:CC_Z CC_REGNUM)
3246         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3247                          (const_int 0)))]
3248   "TARGET_ARM"
3249   "tst\\t%0, #255"
3250   [(set_attr "conds" "set")]
3253 (define_expand "extendhisi2"
3254   [(set (match_dup 2)
3255         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3256                    (const_int 16)))
3257    (set (match_operand:SI 0 "s_register_operand" "")
3258         (ashiftrt:SI (match_dup 2)
3259                      (const_int 16)))]
3260   "TARGET_EITHER"
3261   "
3262   {
3263     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3264       {
3265        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3266           here because the insn below will generate an LDRH instruction
3267           rather than an LDR instruction, so we cannot get an unaligned
3268           word access.  */
3269         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3270                    gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3271         DONE;
3272       }
3274     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3275       {
3276         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3277         DONE;
3278       }
3279     if (!s_register_operand (operands[1], HImode))
3280       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3281     operands[1] = gen_lowpart (SImode, operands[1]);
3282     operands[2] = gen_reg_rtx (SImode);
3284     if (TARGET_THUMB)
3285       {
3286         rtx ops[3];
3287         
3288         ops[0] = operands[2];
3289         ops[1] = operands[1];
3290         ops[2] = GEN_INT (16);
3291         
3292         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3293                                 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3294             
3295         ops[0] = operands[0];
3296         ops[1] = operands[2];
3297         ops[2] = GEN_INT (16);
3298         
3299         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3300                                 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3301         
3302         DONE;
3303       }
3304   }"
3307 (define_insn "*thumb_extendhisi2_insn"
3308   [(set (match_operand:SI                 0 "register_operand" "=l")
3309         (sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3310    (clobber (match_scratch:SI             2                   "=&l"))]
3311   "TARGET_THUMB"
3312   "*
3313   {
3314     rtx ops[4];
3315     rtx mem = XEXP (operands[1], 0);
3317     /* This code used to try to use 'V', and fix the address only if it was
3318        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3319        range of QImode offsets, and offsettable_address_p does a QImode
3320        address check.  */
3321        
3322     if (GET_CODE (mem) == CONST)
3323       mem = XEXP (mem, 0);
3324     
3325     if (GET_CODE (mem) == LABEL_REF)
3326       return \"ldr\\t%0, %1\";
3327     
3328     if (GET_CODE (mem) == PLUS)
3329       {
3330         rtx a = XEXP (mem, 0);
3331         rtx b = XEXP (mem, 1);
3333         if (GET_CODE (a) == LABEL_REF
3334             && GET_CODE (b) == CONST_INT)
3335           return \"ldr\\t%0, %1\";
3337         if (GET_CODE (b) == REG)
3338           return \"ldrsh\\t%0, %1\";
3339           
3340         ops[1] = a;
3341         ops[2] = b;
3342       }
3343     else
3344       {
3345         ops[1] = mem;
3346         ops[2] = const0_rtx;
3347       }
3348       
3349     if (GET_CODE (ops[1]) != REG)
3350       {
3351         debug_rtx (ops[1]);
3352         abort ();
3353       }
3355     ops[0] = operands[0];
3356     ops[3] = operands[2];
3357     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3358     return \"\";
3359   }"
3360   [(set_attr "length" "4")
3361    (set_attr "type" "load")
3362    (set_attr "pool_range" "1020")]
3365 (define_expand "extendhisi2_mem"
3366   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3367    (set (match_dup 3)
3368         (zero_extend:SI (match_dup 7)))
3369    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3370    (set (match_operand:SI 0 "" "")
3371         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3372   "TARGET_ARM"
3373   "
3374   {
3375     rtx mem1, mem2;
3376     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3378     mem1 = gen_rtx_MEM (QImode, addr);
3379     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3380     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3381     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3382     operands[0] = gen_lowpart (SImode, operands[0]);
3383     operands[1] = mem1;
3384     operands[2] = gen_reg_rtx (SImode);
3385     operands[3] = gen_reg_rtx (SImode);
3386     operands[6] = gen_reg_rtx (SImode);
3387     operands[7] = mem2;
3389     if (BYTES_BIG_ENDIAN)
3390       {
3391         operands[4] = operands[2];
3392         operands[5] = operands[3];
3393       }
3394     else
3395       {
3396         operands[4] = operands[3];
3397         operands[5] = operands[2];
3398       }
3399   }"
3402 (define_insn "*arm_extendhisi_insn"
3403   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3404         (sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3405   "TARGET_ARM && arm_arch4"
3406   "ldr%?sh\\t%0, %1"
3407   [(set_attr "type" "load")
3408    (set_attr "predicable" "yes")
3409    (set_attr "pool_range" "256")
3410    (set_attr "neg_pool_range" "244")]
3413 (define_split
3414   [(set (match_operand:SI                 0 "s_register_operand" "")
3415         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3416    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3417   "TARGET_ARM && (!arm_arch4)"
3418   [(set (match_dup 2) (match_dup 1))
3419    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3420   "
3421   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3422     FAIL;
3423   "
3426 (define_split
3427   [(set (match_operand:SI                   0 "s_register_operand" "")
3428         (match_operator:SI                  3 "shiftable_operator"
3429          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3430           (match_operand:SI                 4 "s_register_operand" "")]))
3431    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3432   "TARGET_ARM && (!arm_arch4)"
3433   [(set (match_dup 2) (match_dup 1))
3434    (set (match_dup 0)
3435         (match_op_dup 3
3436          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3437   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3438      FAIL;
3439   "
3442 (define_expand "extendqihi2"
3443   [(set (match_dup 2)
3444         (ashift:SI (match_operand:QI 1 "general_operand" "")
3445                    (const_int 24)))
3446    (set (match_operand:HI 0 "s_register_operand" "")
3447         (ashiftrt:SI (match_dup 2)
3448                      (const_int 24)))]
3449   "TARGET_ARM"
3450   "
3451   {
3452     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3453       {
3454         emit_insn (gen_rtx_SET (VOIDmode,
3455                                 operands[0],
3456                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3457         DONE;
3458       }
3459     if (!s_register_operand (operands[1], QImode))
3460       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3461     operands[0] = gen_lowpart (SImode, operands[0]);
3462     operands[1] = gen_lowpart (SImode, operands[1]);
3463     operands[2] = gen_reg_rtx (SImode);
3464   }"
3467 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3468 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3469 (define_insn "*extendqihi_insn"
3470   [(set (match_operand:HI                 0 "s_register_operand" "=r")
3471         (sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3472   "TARGET_ARM && arm_arch4"
3473   "*
3474   /* If the address is invalid, this will split the instruction into two. */
3475   if (bad_signed_byte_operand (operands[1], VOIDmode))
3476     return \"#\";
3477   return \"ldr%?sb\\t%0, %1\";
3478   "
3479   [(set_attr "type" "load")
3480    (set_attr "predicable" "yes")
3481    (set_attr "length" "8")
3482    (set_attr "pool_range" "256")
3483    (set_attr "neg_pool_range" "244")]
3486 (define_split
3487   [(set (match_operand:HI 0 "s_register_operand" "")
3488         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3489   "TARGET_ARM && arm_arch4 && reload_completed"
3490   [(set (match_dup 3) (match_dup 1))
3491    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3492   "
3493   {
3494     HOST_WIDE_INT offset;
3496     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3497     operands[2] = gen_rtx_MEM (QImode, operands[3]);
3498     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3499     operands[1] = XEXP (operands[1], 0);
3500     if (GET_CODE (operands[1]) == PLUS
3501         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3502         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3503              || const_ok_for_arm (-offset)))
3504       {
3505         HOST_WIDE_INT low = (offset > 0
3506                              ? (offset & 0xff) : -((-offset) & 0xff));
3507         XEXP (operands[2], 0) = plus_constant (operands[3], low);
3508         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3509       }
3510     /* Ensure the sum is in correct canonical form */
3511     else if (GET_CODE (operands[1]) == PLUS
3512              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3513              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3514       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3515                                            XEXP (operands[1], 1),
3516                                            XEXP (operands[1], 0));
3517   }"
3520 (define_expand "extendqisi2"
3521   [(set (match_dup 2)
3522         (ashift:SI (match_operand:QI 1 "general_operand" "")
3523                    (const_int 24)))
3524    (set (match_operand:SI 0 "s_register_operand" "")
3525         (ashiftrt:SI (match_dup 2)
3526                      (const_int 24)))]
3527   "TARGET_EITHER"
3528   "
3529   {
3530     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3531       {
3532         emit_insn (gen_rtx_SET (VOIDmode,
3533                                 operands[0],
3534                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3535         DONE;
3536       }
3537     if (!s_register_operand (operands[1], QImode))
3538       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3539     operands[1] = gen_lowpart (SImode, operands[1]);
3540     operands[2] = gen_reg_rtx (SImode);
3541     
3542     if (TARGET_THUMB)
3543       {
3544         rtx ops[3];
3545         
3546         ops[0] = operands[2];
3547         ops[1] = operands[1];
3548         ops[2] = GEN_INT (24);
3549         
3550         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3551                    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3553         ops[0] = operands[0];
3554         ops[1] = operands[2];
3555         ops[2] = GEN_INT (24);
3556         
3557         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3558                    gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3559         
3560         DONE;
3561       }
3562   }"
3565 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3566 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3567 (define_insn "*arm_extendqisi_insn"
3568   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3569         (sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3570   "TARGET_ARM && arm_arch4"
3571   "*
3572   /* If the address is invalid, this will split the instruction into two. */
3573   if (bad_signed_byte_operand (operands[1], VOIDmode))
3574     return \"#\";
3575   return \"ldr%?sb\\t%0, %1\";
3576   "
3577   [(set_attr "type" "load")
3578    (set_attr "predicable" "yes")
3579    (set_attr "length" "8")
3580    (set_attr "pool_range" "256")
3581    (set_attr "neg_pool_range" "244")]
3584 (define_split
3585   [(set (match_operand:SI 0 "s_register_operand" "")
3586         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3587   "TARGET_ARM && arm_arch4 && reload_completed"
3588   [(set (match_dup 0) (match_dup 1))
3589    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3590   "
3591   {
3592     HOST_WIDE_INT offset;
3594     operands[2] = gen_rtx_MEM (QImode, operands[0]);
3595     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3596     operands[1] = XEXP (operands[1], 0);
3597     if (GET_CODE (operands[1]) == PLUS
3598         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3599         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3600              || const_ok_for_arm (-offset)))
3601       {
3602         HOST_WIDE_INT low = (offset > 0
3603                              ? (offset & 0xff) : -((-offset) & 0xff));
3604         XEXP (operands[2], 0) = plus_constant (operands[0], low);
3605         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3606       }
3607     /* Ensure the sum is in correct canonical form */
3608     else if (GET_CODE (operands[1]) == PLUS
3609              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3610              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3611       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3612                                            XEXP (operands[1], 1),
3613                                            XEXP (operands[1], 0));
3614   }"
3617 (define_insn "*thumb_extendqisi2_insn"
3618   [(set (match_operand:SI                 0 "register_operand" "=l,l")
3619         (sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3620   "TARGET_THUMB"
3621   "*
3622   {
3623     rtx ops[3];
3624     rtx mem = XEXP (operands[1], 0);
3625     
3626     if (GET_CODE (mem) == CONST)
3627       mem = XEXP (mem, 0);
3628     
3629     if (GET_CODE (mem) == LABEL_REF)
3630       return \"ldr\\t%0, %1\";
3632     if (GET_CODE (mem) == PLUS
3633         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3634       return \"ldr\\t%0, %1\";
3635       
3636     if (which_alternative == 0)
3637       return \"ldrsb\\t%0, %1\";
3638       
3639     ops[0] = operands[0];
3640     
3641     if (GET_CODE (mem) == PLUS)
3642       {
3643         rtx a = XEXP (mem, 0);
3644         rtx b = XEXP (mem, 1);
3645         
3646         ops[1] = a;
3647         ops[2] = b;
3649         if (GET_CODE (a) == REG)
3650           {
3651             if (GET_CODE (b) == REG)
3652               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3653             else if (REGNO (a) == REGNO (ops[0]))
3654               {
3655                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3656                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3657                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3658               }
3659             else
3660               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3661           }
3662         else if (GET_CODE (b) != REG)
3663           abort ();
3664         else
3665           {
3666             if (REGNO (b) == REGNO (ops[0]))
3667               {
3668                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3669                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3670                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3671               }
3672             else
3673               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3674           }
3675       }
3676     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3677       {
3678         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3679         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3680         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3681       }
3682     else
3683       {
3684         ops[1] = mem;
3685         ops[2] = const0_rtx;
3686         
3687         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3688       }
3689     return \"\";
3690   }"
3691   [(set_attr "length" "2,6")
3692    (set_attr "type" "load,load")
3693    (set_attr "pool_range" "32,32")]
3696 (define_expand "extendsfdf2"
3697   [(set (match_operand:DF                  0 "s_register_operand" "")
3698         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
3699   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3700   ""
3703 (define_insn "*arm_extendsfdf2"
3704   [(set (match_operand:DF                  0 "s_register_operand" "=f")
3705         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "f")))]
3706   "TARGET_ARM && TARGET_HARD_FLOAT"
3707   "mvf%?d\\t%0, %1"
3708   [(set_attr "type" "ffarith")
3709    (set_attr "predicable" "yes")]
3712 ;; Move insns (including loads and stores)
3714 ;; XXX Just some ideas about movti.
3715 ;; I don't think these are a good idea on the arm, there just aren't enough
3716 ;; registers
3717 ;;(define_expand "loadti"
3718 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3719 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3720 ;;  "" "")
3722 ;;(define_expand "storeti"
3723 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3724 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3725 ;;  "" "")
3727 ;;(define_expand "movti"
3728 ;;  [(set (match_operand:TI 0 "general_operand" "")
3729 ;;      (match_operand:TI 1 "general_operand" ""))]
3730 ;;  ""
3731 ;;  "
3733 ;;  rtx insn;
3735 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3736 ;;    operands[1] = copy_to_reg (operands[1]);
3737 ;;  if (GET_CODE (operands[0]) == MEM)
3738 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3739 ;;  else if (GET_CODE (operands[1]) == MEM)
3740 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3741 ;;  else
3742 ;;    FAIL;
3744 ;;  emit_insn (insn);
3745 ;;  DONE;
3746 ;;}")
3748 ;; Recognize garbage generated above.
3750 ;;(define_insn ""
3751 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3752 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3753 ;;  ""
3754 ;;  "*
3755 ;;  {
3756 ;;    register mem = (which_alternative < 3);
3757 ;;    register const char *template;
3759 ;;    operands[mem] = XEXP (operands[mem], 0);
3760 ;;    switch (which_alternative)
3761 ;;      {
3762 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3763 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3764 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3765 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3766 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3767 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3768 ;;      }
3769 ;;    output_asm_insn (template, operands);
3770 ;;    return \"\";
3771 ;;  }")
3773 (define_expand "movdi"
3774   [(set (match_operand:DI 0 "general_operand" "")
3775         (match_operand:DI 1 "general_operand" ""))]
3776   "TARGET_EITHER"
3777   "
3778   if (TARGET_THUMB)
3779     {
3780       if (!no_new_pseudos)
3781         {
3782           if (GET_CODE (operands[0]) != REG)
3783             operands[1] = force_reg (DImode, operands[1]);
3784         }
3785     }
3786   "
3789 (define_insn "*arm_movdi"
3790   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3791         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3792   "TARGET_ARM && !TARGET_CIRRUS"
3793   "*
3794   return (output_move_double (operands));
3795   "
3796   [(set_attr "length" "8")
3797    (set_attr "type" "*,load,store2")
3798    (set_attr "pool_range" "*,1020,*")
3799    (set_attr "neg_pool_range" "*,1008,*")]
3802 ;;; ??? This should have alternatives for constants.
3803 ;;; ??? This was originally identical to the movdf_insn pattern.
3804 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3805 ;;; thumb_reorg with a memory reference.
3806 (define_insn "*thumb_movdi_insn"
3807   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3808         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3809   "TARGET_THUMB
3810    && !TARGET_CIRRUS
3811    && (   register_operand (operands[0], DImode)
3812        || register_operand (operands[1], DImode))"
3813   "*
3814   {
3815   switch (which_alternative)
3816     {
3817     default:
3818     case 0:
3819       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3820         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3821       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3822     case 1:
3823       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3824     case 2:
3825       operands[1] = GEN_INT (- INTVAL (operands[1]));
3826       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3827     case 3:
3828       return \"ldmia\\t%1, {%0, %H0}\";
3829     case 4:
3830       return \"stmia\\t%0, {%1, %H1}\";
3831     case 5:
3832       return thumb_load_double_from_address (operands);
3833     case 6:
3834       operands[2] = gen_rtx (MEM, SImode,
3835                              plus_constant (XEXP (operands[0], 0), 4));
3836       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3837       return \"\";
3838     case 7:
3839       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3840         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3841       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3842     }
3843   }"
3844   [(set_attr "length" "4,4,6,2,2,6,4,4")
3845    (set_attr "type" "*,*,*,load,store2,load,store2,*")
3846    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3849 (define_expand "movsi"
3850   [(set (match_operand:SI 0 "general_operand" "")
3851         (match_operand:SI 1 "general_operand" ""))]
3852   "TARGET_EITHER"
3853   "
3854   if (TARGET_ARM)
3855     {
3856       /* Everything except mem = const or mem = mem can be done easily */
3857       if (GET_CODE (operands[0]) == MEM)
3858         operands[1] = force_reg (SImode, operands[1]);
3859       if (GET_CODE (operands[1]) == CONST_INT
3860           && !(const_ok_for_arm (INTVAL (operands[1]))
3861                || const_ok_for_arm (~INTVAL (operands[1]))))
3862         {
3863            arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3864                               NULL_RTX,
3865                               (no_new_pseudos ? 0
3866                                : preserve_subexpressions_p ()));
3867           DONE;
3868         }
3869     }
3870   else /* TARGET_THUMB.... */
3871     {
3872       if (!no_new_pseudos)
3873         {
3874           if (GET_CODE (operands[0]) != REG)
3875             operands[1] = force_reg (SImode, operands[1]);
3876         }
3877     }
3878     
3879   if (flag_pic
3880       && (CONSTANT_P (operands[1])
3881          || symbol_mentioned_p (operands[1])
3882          || label_mentioned_p (operands[1])))
3883     operands[1] = legitimize_pic_address (operands[1], SImode,
3884                                           (no_new_pseudos ? operands[0] : 0));
3885   "
3888 (define_insn "*arm_movsi_insn"
3889   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3890         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
3891   "TARGET_ARM
3892    && (   register_operand (operands[0], SImode)
3893        || register_operand (operands[1], SImode))"
3894   "@
3895    mov%?\\t%0, %1
3896    mvn%?\\t%0, #%B1
3897    ldr%?\\t%0, %1
3898    str%?\\t%1, %0"
3899   [(set_attr "type" "*,*,load,store1")
3900    (set_attr "predicable" "yes")
3901    (set_attr "pool_range" "*,*,4096,*")
3902    (set_attr "neg_pool_range" "*,*,4084,*")]
3905 (define_split
3906   [(set (match_operand:SI 0 "s_register_operand" "")
3907         (match_operand:SI 1 "const_int_operand" ""))]
3908   "TARGET_ARM
3909   && (!(const_ok_for_arm (INTVAL (operands[1]))
3910         || const_ok_for_arm (~INTVAL (operands[1]))))"
3911   [(clobber (const_int 0))]
3912   "
3913   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3914                       NULL_RTX, 0);
3915   DONE;
3916   "
3919 (define_insn "*thumb_movsi_insn"
3920   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3921         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
3922   "TARGET_THUMB
3923    && (   register_operand (operands[0], SImode) 
3924        || register_operand (operands[1], SImode))"
3925   "@
3926    mov  %0, %1
3927    mov  %0, %1
3928    #
3929    #
3930    ldmia\\t%1, {%0}
3931    stmia\\t%0, {%1}
3932    ldr\\t%0, %1
3933    str\\t%1, %0
3934    mov\\t%0, %1"
3935   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3936    (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3937    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3940 (define_split 
3941   [(set (match_operand:SI 0 "register_operand" "")
3942         (match_operand:SI 1 "const_int_operand" ""))]
3943   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3944   [(set (match_dup 0) (match_dup 1))
3945    (set (match_dup 0) (neg:SI (match_dup 0)))]
3946   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3949 (define_split 
3950   [(set (match_operand:SI 0 "register_operand" "")
3951         (match_operand:SI 1 "const_int_operand" ""))]
3952   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3953   [(set (match_dup 0) (match_dup 1))
3954    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3955   "
3956   {
3957     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3958     unsigned HOST_WIDE_INT mask = 0xff;
3959     int i;
3960     
3961     for (i = 0; i < 25; i++)
3962       if ((val & (mask << i)) == val)
3963         break;
3965     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
3966     if (i == 0)
3967       FAIL;
3969     operands[1] = GEN_INT (val >> i);
3970     operands[2] = GEN_INT (i);
3971   }"
3974 ;; When generating pic, we need to load the symbol offset into a register.
3975 ;; So that the optimizer does not confuse this with a normal symbol load
3976 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
3977 ;; since that is the only type of relocation we can use.
3979 ;; The rather odd constraints on the following are to force reload to leave
3980 ;; the insn alone, and to force the minipool generation pass to then move
3981 ;; the GOT symbol to memory.
3983 (define_insn "pic_load_addr_arm"
3984   [(set (match_operand:SI 0 "s_register_operand" "=r")
3985         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3986   "TARGET_ARM && flag_pic"
3987   "ldr%?\\t%0, %1"
3988   [(set_attr "type" "load")
3989    (set (attr "pool_range")     (const_int 4096))
3990    (set (attr "neg_pool_range") (const_int 4084))]
3993 (define_insn "pic_load_addr_thumb"
3994   [(set (match_operand:SI 0 "s_register_operand" "=l")
3995         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3996   "TARGET_THUMB && flag_pic"
3997   "ldr\\t%0, %1"
3998   [(set_attr "type" "load")
3999    (set (attr "pool_range") (const_int 1024))]
4002 ;; This variant is used for AOF assembly, since it needs to mention the
4003 ;; pic register in the rtl.
4004 (define_expand "pic_load_addr_based"
4005   [(set (match_operand:SI 0 "s_register_operand" "=r")
4006         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4007   "TARGET_ARM && flag_pic"
4008   "operands[2] = pic_offset_table_rtx;"
4011 (define_insn "*pic_load_addr_based_insn"
4012   [(set (match_operand:SI 0 "s_register_operand" "=r")
4013         (unspec:SI [(match_operand 1 "" "")
4014                     (match_operand 2 "s_register_operand" "r")]
4015                    UNSPEC_PIC_SYM))]
4016   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4017   "*
4018 #ifdef AOF_ASSEMBLER
4019   operands[1] = aof_pic_entry (operands[1]);
4020 #endif
4021   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4022   return \"\";
4023   "
4024   [(set_attr "type" "load")
4025    (set (attr "pool_range")
4026         (if_then_else (eq_attr "is_thumb" "yes")
4027                       (const_int 1024)
4028                       (const_int 4096)))
4029    (set (attr "neg_pool_range")
4030         (if_then_else (eq_attr "is_thumb" "yes")
4031                       (const_int 0)
4032                       (const_int 4084)))]
4035 (define_insn "pic_add_dot_plus_four"
4036   [(set (match_operand:SI 0 "register_operand" "+r")
4037         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4038    (use (label_ref (match_operand 1 "" "")))]
4039   "TARGET_THUMB && flag_pic"
4040   "*
4041   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4042                              CODE_LABEL_NUMBER (operands[1]));
4043   return \"add\\t%0, %|pc\";
4044   "
4045   [(set_attr "length" "2")]
4048 (define_insn "pic_add_dot_plus_eight"
4049   [(set (match_operand:SI 0 "register_operand" "+r")
4050         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4051    (use (label_ref (match_operand 1 "" "")))]
4052   "TARGET_ARM && flag_pic"
4053   "*
4054     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4055                                CODE_LABEL_NUMBER (operands[1]));
4056     return \"add%?\\t%0, %|pc, %0\";
4057   "
4058   [(set_attr "predicable" "yes")]
4061 (define_expand "builtin_setjmp_receiver"
4062   [(label_ref (match_operand 0 "" ""))]
4063   "flag_pic"
4064   "
4066   arm_finalize_pic (0);
4067   DONE;
4070 ;; If copying one reg to another we can set the condition codes according to
4071 ;; its value.  Such a move is common after a return from subroutine and the
4072 ;; result is being tested against zero.
4074 (define_insn "*movsi_compare0"
4075   [(set (reg:CC CC_REGNUM)
4076         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4077                     (const_int 0)))
4078    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4079         (match_dup 1))]
4080   "TARGET_ARM"
4081   "@
4082    cmp%?\\t%0, #0
4083    sub%?s\\t%0, %1, #0"
4084   [(set_attr "conds" "set")]
4087 ;; Subroutine to store a half word from a register into memory.
4088 ;; Operand 0 is the source register (HImode)
4089 ;; Operand 1 is the destination address in a register (SImode)
4091 ;; In both this routine and the next, we must be careful not to spill
4092 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4093 ;; can generate unrecognizable rtl.
4095 (define_expand "storehi"
4096   [;; store the low byte
4097    (set (match_operand 1 "" "") (match_dup 3))
4098    ;; extract the high byte
4099    (set (match_dup 2)
4100         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4101    ;; store the high byte
4102    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
4103   "TARGET_ARM"
4104   "
4105   {
4106     rtx op1 = operands[1];
4107     rtx addr = XEXP (op1, 0);
4108     enum rtx_code code = GET_CODE (addr);
4110     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4111         || code == MINUS)
4112       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4114     operands[4] = adjust_address (op1, QImode, 1);
4115     operands[1] = adjust_address (operands[1], QImode, 0);
4116     operands[3] = gen_lowpart (QImode, operands[0]);
4117     operands[0] = gen_lowpart (SImode, operands[0]);
4118     operands[2] = gen_reg_rtx (SImode); 
4119   }"
4122 (define_expand "storehi_bigend"
4123   [(set (match_dup 4) (match_dup 3))
4124    (set (match_dup 2)
4125         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4126    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4127   "TARGET_ARM"
4128   "
4129   {
4130     rtx op1 = operands[1];
4131     rtx addr = XEXP (op1, 0);
4132     enum rtx_code code = GET_CODE (addr);
4134     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4135         || code == MINUS)
4136       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4138     operands[4] = adjust_address (op1, QImode, 1);
4139     operands[1] = adjust_address (operands[1], QImode, 0);
4140     operands[3] = gen_lowpart (QImode, operands[0]);
4141     operands[0] = gen_lowpart (SImode, operands[0]);
4142     operands[2] = gen_reg_rtx (SImode);
4143   }"
4146 ;; Subroutine to store a half word integer constant into memory.
4147 (define_expand "storeinthi"
4148   [(set (match_operand 0 "" "")
4149         (subreg:QI (match_operand 1 "" "") 0))
4150    (set (match_dup 3) (match_dup 2))]
4151   "TARGET_ARM"
4152   "
4153   {
4154     HOST_WIDE_INT value = INTVAL (operands[1]);
4155     rtx addr = XEXP (operands[0], 0);
4156     rtx op0 = operands[0];
4157     enum rtx_code code = GET_CODE (addr);
4159     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4160         || code == MINUS)
4161       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4163     operands[1] = gen_reg_rtx (SImode);
4164     if (BYTES_BIG_ENDIAN)
4165       {
4166         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4167         if ((value & 255) == ((value >> 8) & 255))
4168           operands[2] = operands[1];
4169         else
4170           {
4171             operands[2] = gen_reg_rtx (SImode);
4172             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4173           }
4174       }
4175     else
4176       {
4177         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4178         if ((value & 255) == ((value >> 8) & 255))
4179           operands[2] = operands[1];
4180         else
4181           {
4182             operands[2] = gen_reg_rtx (SImode);
4183             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4184           }
4185       }
4187     operands[3] = adjust_address (op0, QImode, 1);
4188     operands[0] = adjust_address (operands[0], QImode, 0);
4189     operands[2] = gen_lowpart (QImode, operands[2]);
4190   }"
4193 (define_expand "storehi_single_op"
4194   [(set (match_operand:HI 0 "memory_operand" "")
4195         (match_operand:HI 1 "general_operand" ""))]
4196   "TARGET_ARM && arm_arch4"
4197   "
4198   if (!s_register_operand (operands[1], HImode))
4199     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4200   "
4203 (define_expand "movhi"
4204   [(set (match_operand:HI 0 "general_operand" "")
4205         (match_operand:HI 1 "general_operand" ""))]
4206   "TARGET_EITHER"
4207   "
4208   if (TARGET_ARM)
4209     {
4210       if (!no_new_pseudos)
4211         {
4212           if (GET_CODE (operands[0]) == MEM)
4213             {
4214               if (arm_arch4)
4215                 {
4216                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4217                   DONE;
4218                 }
4219               if (GET_CODE (operands[1]) == CONST_INT)
4220                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4221               else
4222                 {
4223                   if (GET_CODE (operands[1]) == MEM)
4224                     operands[1] = force_reg (HImode, operands[1]);
4225                   if (BYTES_BIG_ENDIAN)
4226                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4227                   else
4228                    emit_insn (gen_storehi (operands[1], operands[0]));
4229                 }
4230               DONE;
4231             }
4232           /* Sign extend a constant, and keep it in an SImode reg.  */
4233           else if (GET_CODE (operands[1]) == CONST_INT)
4234             {
4235               rtx reg = gen_reg_rtx (SImode);
4236               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4238               /* If the constant is already valid, leave it alone.  */
4239               if (!const_ok_for_arm (val))
4240                 {
4241                   /* If setting all the top bits will make the constant 
4242                      loadable in a single instruction, then set them.  
4243                      Otherwise, sign extend the number.  */
4245                   if (const_ok_for_arm (~(val | ~0xffff)))
4246                     val |= ~0xffff;
4247                   else if (val & 0x8000)
4248                     val |= ~0xffff;
4249                 }
4251               emit_insn (gen_movsi (reg, GEN_INT (val)));
4252               operands[1] = gen_lowpart (HImode, reg);
4253             }
4254           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4255                    && GET_CODE (operands[1]) == MEM)
4256             {
4257               rtx reg = gen_reg_rtx (SImode);
4259               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4260               operands[1] = gen_lowpart (HImode, reg);
4261             }
4262           else if (!arm_arch4)
4263             {
4264              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4265                 for v4 and up architectures because LDRH instructions will
4266                 be used to access the HI values, and these cannot generate
4267                 unaligned word access faults in the MMU.  */
4268               if (GET_CODE (operands[1]) == MEM)
4269                 {
4270                   if (TARGET_MMU_TRAPS)
4271                     {
4272                       rtx base;
4273                       rtx offset = const0_rtx;
4274                       rtx reg = gen_reg_rtx (SImode);
4276                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4277                            || (GET_CODE (base) == PLUS
4278                                && (GET_CODE (offset = XEXP (base, 1))
4279                                    == CONST_INT)
4280                                && ((INTVAL(offset) & 1) != 1)
4281                                && GET_CODE (base = XEXP (base, 0)) == REG))
4282                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4283                         {
4284                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4285                           rtx new;
4287                           new = gen_rtx_MEM (SImode,
4288                                              plus_constant (base, new_offset));
4289                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4290                           emit_insn (gen_movsi (reg, new));
4291                           if (((INTVAL (offset) & 2) != 0)
4292                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4293                             {
4294                               rtx reg2 = gen_reg_rtx (SImode);
4296                               emit_insn (gen_lshrsi3 (reg2, reg,
4297                                          GEN_INT (16)));
4298                               reg = reg2;
4299                             }
4300                         }
4301                       else
4302                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4304                       operands[1] = gen_lowpart (HImode, reg);
4305                     }
4306                   else if (BYTES_BIG_ENDIAN)
4307                     {
4308                       rtx base;
4309                       rtx offset = const0_rtx;
4311                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4312                            || (GET_CODE (base) == PLUS
4313                               && (GET_CODE (offset = XEXP (base, 1))
4314                                   == CONST_INT)
4315                               && GET_CODE (base = XEXP (base, 0)) == REG))
4316                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4317                         {
4318                           rtx reg = gen_reg_rtx (SImode);
4319                           rtx new;
4321                           if ((INTVAL (offset) & 2) == 2)
4322                             {
4323                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4324                               new = gen_rtx_MEM (SImode,
4325                                                  plus_constant (base,
4326                                                                 new_offset));
4327                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4328                               emit_insn (gen_movsi (reg, new));
4329                             }
4330                           else
4331                             {
4332                               new = gen_rtx_MEM (SImode,
4333                                                  XEXP (operands[1], 0));
4334                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4335                               emit_insn (gen_rotated_loadsi (reg, new));
4336                             }
4338                           operands[1] = gen_lowpart (HImode, reg);
4339                         }
4340                       else
4341                         {
4342                           emit_insn (gen_movhi_bigend (operands[0],
4343                                                        operands[1]));
4344                           DONE;
4345                         }
4346                     }
4347                }
4348            }
4349         }
4350       /* Handle loading a large integer during reload */
4351       else if (GET_CODE (operands[1]) == CONST_INT
4352                && !const_ok_for_arm (INTVAL (operands[1]))
4353                && !const_ok_for_arm (~INTVAL (operands[1])))
4354         {
4355           /* Writing a constant to memory needs a scratch, which should
4356              be handled with SECONDARY_RELOADs.  */
4357           if (GET_CODE (operands[0]) != REG)
4358             abort ();
4360           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4361           emit_insn (gen_movsi (operands[0], operands[1]));
4362           DONE;
4363        }
4364     }
4365   else /* TARGET_THUMB */
4366     {
4367       if (!no_new_pseudos)
4368         {
4369           if (GET_CODE (operands[0]) != REG)
4370             operands[1] = force_reg (HImode, operands[1]);
4372           /* ??? We shouldn't really get invalid addresses here, but this can
4373              happen if we are passed a SP (never OK for HImode/QImode) or 
4374              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4375              HImode/QImode) relative address.  */
4376           /* ??? This should perhaps be fixed elsewhere, for instance, in
4377              fixup_stack_1, by checking for other kinds of invalid addresses,
4378              e.g. a bare reference to a virtual register.  This may confuse the
4379              alpha though, which must handle this case differently.  */
4380           if (GET_CODE (operands[0]) == MEM
4381               && !memory_address_p (GET_MODE (operands[0]),
4382                                     XEXP (operands[0], 0)))
4383             operands[0]
4384               = replace_equiv_address (operands[0],
4385                                        copy_to_reg (XEXP (operands[0], 0)));
4386    
4387           if (GET_CODE (operands[1]) == MEM
4388               && !memory_address_p (GET_MODE (operands[1]),
4389                                     XEXP (operands[1], 0)))
4390             operands[1]
4391               = replace_equiv_address (operands[1],
4392                                        copy_to_reg (XEXP (operands[1], 0)));
4393         }
4394       /* Handle loading a large integer during reload */
4395       else if (GET_CODE (operands[1]) == CONST_INT
4396                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4397         {
4398           /* Writing a constant to memory needs a scratch, which should
4399              be handled with SECONDARY_RELOADs.  */
4400           if (GET_CODE (operands[0]) != REG)
4401             abort ();
4403           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4404           emit_insn (gen_movsi (operands[0], operands[1]));
4405           DONE;
4406         }
4407     }
4408   "
4411 (define_insn "*thumb_movhi_insn"
4412   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4413         (match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4414   "TARGET_THUMB
4415    && (   register_operand (operands[0], HImode)
4416        || register_operand (operands[1], HImode))"
4417   "*
4418   switch (which_alternative)
4419     {
4420     case 0: return \"add        %0, %1, #0\";
4421     case 2: return \"strh       %1, %0\";
4422     case 3: return \"mov        %0, %1\";
4423     case 4: return \"mov        %0, %1\";
4424     case 5: return \"mov        %0, %1\";
4425     default: abort ();
4426     case 1:
4427       /* The stack pointer can end up being taken as an index register.
4428           Catch this case here and deal with it.  */
4429       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4430           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4431           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4432         {
4433           rtx ops[2];
4434           ops[0] = operands[0];
4435           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4436       
4437           output_asm_insn (\"mov        %0, %1\", ops);
4439           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4440     
4441         }
4442       return \"ldrh     %0, %1\";
4443     }"
4444   [(set_attr "length" "2,4,2,2,2,2")
4445    (set_attr "type" "*,load,store1,*,*,*")
4446    (set_attr "pool_range" "*,64,*,*,*,*")]
4450 (define_insn "rotated_loadsi"
4451   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4452         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4453                    (const_int 16)))]
4454   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4455   "*
4456   {
4457     rtx ops[2];
4459     ops[0] = operands[0];
4460     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4461     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4462     return \"\";
4463   }"
4464   [(set_attr "type" "load")
4465    (set_attr "predicable" "yes")]
4468 (define_expand "movhi_bytes"
4469   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4470    (set (match_dup 3)
4471         (zero_extend:SI (match_dup 6)))
4472    (set (match_operand:SI 0 "" "")
4473          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4474   "TARGET_ARM"
4475   "
4476   {
4477     rtx mem1, mem2;
4478     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4480     mem1 = gen_rtx_MEM (QImode, addr);
4481     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4482     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4483     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4484     operands[0] = gen_lowpart (SImode, operands[0]);
4485     operands[1] = mem1;
4486     operands[2] = gen_reg_rtx (SImode);
4487     operands[3] = gen_reg_rtx (SImode);
4488     operands[6] = mem2;
4490     if (BYTES_BIG_ENDIAN)
4491       {
4492         operands[4] = operands[2];
4493         operands[5] = operands[3];
4494       }
4495     else
4496       {
4497         operands[4] = operands[3];
4498         operands[5] = operands[2];
4499       }
4500   }"
4503 (define_expand "movhi_bigend"
4504   [(set (match_dup 2)
4505         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4506                    (const_int 16)))
4507    (set (match_dup 3)
4508         (ashiftrt:SI (match_dup 2) (const_int 16)))
4509    (set (match_operand:HI 0 "s_register_operand" "")
4510         (subreg:HI (match_dup 3) 0))]
4511   "TARGET_ARM"
4512   "
4513   operands[2] = gen_reg_rtx (SImode);
4514   operands[3] = gen_reg_rtx (SImode);
4515   "
4518 ;; Pattern to recognize insn generated default case above
4519 (define_insn "*movhi_insn_arch4"
4520   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4521         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4522   "TARGET_ARM
4523    && arm_arch4
4524    && (GET_CODE (operands[1]) != CONST_INT
4525        || const_ok_for_arm (INTVAL (operands[1]))
4526        || const_ok_for_arm (~INTVAL (operands[1])))"
4527   "@
4528    mov%?\\t%0, %1\\t%@ movhi
4529    mvn%?\\t%0, #%B1\\t%@ movhi
4530    str%?h\\t%1, %0\\t%@ movhi 
4531    ldr%?h\\t%0, %1\\t%@ movhi"
4532   [(set_attr "type" "*,*,store1,load")
4533    (set_attr "predicable" "yes")
4534    (set_attr "pool_range" "*,*,*,256")
4535    (set_attr "neg_pool_range" "*,*,*,244")]
4538 (define_insn "*movhi_insn_littleend"
4539   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4540         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4541   "TARGET_ARM
4542    && !arm_arch4
4543    && !BYTES_BIG_ENDIAN
4544    && !TARGET_MMU_TRAPS
4545    && (GET_CODE (operands[1]) != CONST_INT
4546        || const_ok_for_arm (INTVAL (operands[1]))
4547        || const_ok_for_arm (~INTVAL (operands[1])))"
4548   "@
4549    mov%?\\t%0, %1\\t%@ movhi
4550    mvn%?\\t%0, #%B1\\t%@ movhi
4551    ldr%?\\t%0, %1\\t%@ movhi"
4552   [(set_attr "type" "*,*,load")
4553    (set_attr "predicable" "yes")
4554    (set_attr "pool_range" "4096")
4555    (set_attr "neg_pool_range" "4084")]
4558 (define_insn "*movhi_insn_bigend"
4559   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4560         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4561   "TARGET_ARM
4562    && !arm_arch4
4563    && BYTES_BIG_ENDIAN
4564    && !TARGET_MMU_TRAPS
4565    && (GET_CODE (operands[1]) != CONST_INT
4566        || const_ok_for_arm (INTVAL (operands[1]))
4567        || const_ok_for_arm (~INTVAL (operands[1])))"
4568   "@
4569    mov%?\\t%0, %1\\t%@ movhi
4570    mvn%?\\t%0, #%B1\\t%@ movhi
4571    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4572   [(set_attr "type" "*,*,load")
4573    (set_attr "predicable" "yes")
4574    (set_attr "length" "4,4,8")
4575    (set_attr "pool_range" "*,*,4092")
4576    (set_attr "neg_pool_range" "*,*,4084")]
4579 (define_insn "*loadhi_si_bigend"
4580   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4581         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4582                    (const_int 16)))]
4583   "TARGET_ARM
4584    && BYTES_BIG_ENDIAN
4585    && !TARGET_MMU_TRAPS"
4586   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4587   [(set_attr "type" "load")
4588    (set_attr "predicable" "yes")
4589    (set_attr "pool_range" "4096")
4590    (set_attr "neg_pool_range" "4084")]
4593 (define_insn "*movhi_bytes"
4594   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4595         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4596   "TARGET_ARM && TARGET_MMU_TRAPS"
4597   "@
4598    mov%?\\t%0, %1\\t%@ movhi
4599    mvn%?\\t%0, #%B1\\t%@ movhi"
4600   [(set_attr "predicable" "yes")]
4603 (define_insn "thumb_movhi_clobber"
4604   [(set (match_operand:HI     0 "memory_operand"   "=m")
4605         (match_operand:HI     1 "register_operand" "l"))
4606    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4607   "TARGET_THUMB"
4608   "*
4609   abort ();"
4611         
4612 ;; We use a DImode scratch because we may occasionally need an additional
4613 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4614 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4615 (define_expand "reload_outhi"
4616   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4617               (match_operand:HI 1 "s_register_operand"        "r")
4618               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4619   "TARGET_EITHER"
4620   "if (TARGET_ARM)
4621      arm_reload_out_hi (operands);
4622    else
4623      thumb_reload_out_hi (operands);
4624   DONE;
4625   "
4628 (define_expand "reload_inhi"
4629   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4630               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4631               (match_operand:DI 2 "s_register_operand" "=&r")])]
4632   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4633   "
4634   if (TARGET_ARM)
4635     arm_reload_in_hi (operands);
4636   else
4637     thumb_reload_out_hi (operands);
4638   DONE;
4641 (define_expand "movqi"
4642   [(set (match_operand:QI 0 "general_operand" "")
4643         (match_operand:QI 1 "general_operand" ""))]
4644   "TARGET_EITHER"
4645   "
4646   if (TARGET_ARM)
4647     {
4648       /* Everything except mem = const or mem = mem can be done easily */
4650       if (!no_new_pseudos)
4651         {
4652           if (GET_CODE (operands[1]) == CONST_INT)
4653             {
4654               rtx reg = gen_reg_rtx (SImode);
4656               emit_insn (gen_movsi (reg, operands[1]));
4657               operands[1] = gen_lowpart (QImode, reg);
4658             }
4659           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4660             {
4661               rtx reg = gen_reg_rtx (SImode);
4663               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4664               operands[1] = gen_lowpart (QImode, reg);
4665             }
4666           if (GET_CODE (operands[0]) == MEM)
4667             operands[1] = force_reg (QImode, operands[1]);
4668         }
4669     }
4670   else /* TARGET_THUMB */
4671     {
4672       if (!no_new_pseudos)
4673         {
4674           if (GET_CODE (operands[0]) != REG)
4675             operands[1] = force_reg (QImode, operands[1]);
4677           /* ??? We shouldn't really get invalid addresses here, but this can
4678              happen if we are passed a SP (never OK for HImode/QImode) or
4679              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4680              HImode/QImode) relative address.  */
4681           /* ??? This should perhaps be fixed elsewhere, for instance, in
4682              fixup_stack_1, by checking for other kinds of invalid addresses,
4683              e.g. a bare reference to a virtual register.  This may confuse the
4684              alpha though, which must handle this case differently.  */
4685           if (GET_CODE (operands[0]) == MEM
4686               && !memory_address_p (GET_MODE (operands[0]),
4687                                      XEXP (operands[0], 0)))
4688             operands[0]
4689               = replace_equiv_address (operands[0],
4690                                        copy_to_reg (XEXP (operands[0], 0)));
4691           if (GET_CODE (operands[1]) == MEM
4692               && !memory_address_p (GET_MODE (operands[1]),
4693                                     XEXP (operands[1], 0)))
4694              operands[1]
4695                = replace_equiv_address (operands[1],
4696                                         copy_to_reg (XEXP (operands[1], 0)));
4697         }
4698       /* Handle loading a large integer during reload */
4699       else if (GET_CODE (operands[1]) == CONST_INT
4700                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4701         {
4702           /* Writing a constant to memory needs a scratch, which should
4703              be handled with SECONDARY_RELOADs.  */
4704           if (GET_CODE (operands[0]) != REG)
4705             abort ();
4707           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4708           emit_insn (gen_movsi (operands[0], operands[1]));
4709           DONE;
4710        }
4711     }
4712   "
4716 (define_insn "*arm_movqi_insn"
4717   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4718         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4719   "TARGET_ARM
4720    && (   register_operand (operands[0], QImode)
4721        || register_operand (operands[1], QImode))"
4722   "@
4723    mov%?\\t%0, %1
4724    mvn%?\\t%0, #%B1
4725    ldr%?b\\t%0, %1
4726    str%?b\\t%1, %0"
4727   [(set_attr "type" "*,*,load,store1")
4728    (set_attr "predicable" "yes")]
4731 (define_insn "*thumb_movqi_insn"
4732   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4733         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4734   "TARGET_THUMB
4735    && (   register_operand (operands[0], QImode)
4736        || register_operand (operands[1], QImode))"
4737   "@
4738    add\\t%0, %1, #0
4739    ldrb\\t%0, %1
4740    strb\\t%1, %0
4741    mov\\t%0, %1
4742    mov\\t%0, %1
4743    mov\\t%0, %1"
4744   [(set_attr "length" "2")
4745    (set_attr "type" "*,load,store1,*,*,*")
4746    (set_attr "pool_range" "*,32,*,*,*,*")]
4749 (define_expand "movsf"
4750   [(set (match_operand:SF 0 "general_operand" "")
4751         (match_operand:SF 1 "general_operand" ""))]
4752   "TARGET_EITHER"
4753   "
4754   if (TARGET_ARM)
4755     {
4756       if (GET_CODE (operands[0]) == MEM)
4757         operands[1] = force_reg (SFmode, operands[1]);
4758     }
4759   else /* TARGET_THUMB */
4760     {
4761       if (!no_new_pseudos)
4762         {
4763            if (GET_CODE (operands[0]) != REG)
4764              operands[1] = force_reg (SFmode, operands[1]);
4765         }
4766     }
4767   "
4770 (define_split
4771   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4772         (match_operand:SF 1 "immediate_operand" ""))]
4773   "TARGET_ARM
4774    && !TARGET_HARD_FLOAT
4775    && reload_completed
4776    && GET_CODE (operands[1]) == CONST_DOUBLE"
4777   [(set (match_dup 2) (match_dup 3))]
4778   "
4779   operands[2] = gen_lowpart (SImode, operands[0]);
4780   operands[3] = gen_lowpart (SImode, operands[1]);
4781   if (operands[2] == 0 || operands[3] == 0)
4782     FAIL;
4783   "
4786 (define_insn "*arm_movsf_hard_insn"
4787   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4788         (match_operand:SF 1 "general_operand"      "fG,H,mE,f,r,f,r,mE,r"))]
4789   "TARGET_ARM
4790    && TARGET_HARD_FLOAT
4791    && (GET_CODE (operands[0]) != MEM
4792        || register_operand (operands[1], SFmode))"
4793   "@
4794    mvf%?s\\t%0, %1
4795    mnf%?s\\t%0, #%N1
4796    ldf%?s\\t%0, %1
4797    stf%?s\\t%1, %0
4798    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4799    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4800    mov%?\\t%0, %1
4801    ldr%?\\t%0, %1\\t%@ float
4802    str%?\\t%1, %0\\t%@ float"
4803   [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4804    (set_attr "predicable" "yes")
4805    (set_attr "type"
4806          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4807    (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4808    (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4811 ;; Exactly the same as above, except that all `f' cases are deleted.
4812 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4813 ;; when -msoft-float.
4815 (define_insn "*arm_movsf_soft_insn"
4816   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4817         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4818   "TARGET_ARM
4819    && !TARGET_CIRRUS
4820    && TARGET_SOFT_FLOAT
4821    && (GET_CODE (operands[0]) != MEM
4822        || register_operand (operands[1], SFmode))"
4823   "@
4824    mov%?\\t%0, %1
4825    ldr%?\\t%0, %1\\t%@ float
4826    str%?\\t%1, %0\\t%@ float"
4827   [(set_attr "length" "4,4,4")
4828    (set_attr "predicable" "yes")
4829    (set_attr "type" "*,load,store1")
4830    (set_attr "pool_range" "*,4096,*")
4831    (set_attr "neg_pool_range" "*,4084,*")]
4834 ;;; ??? This should have alternatives for constants.
4835 (define_insn "*thumb_movsf_insn"
4836   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4837         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4838   "TARGET_THUMB
4839    && (   register_operand (operands[0], SFmode) 
4840        || register_operand (operands[1], SFmode))"
4841   "@
4842    add\\t%0, %1, #0
4843    ldmia\\t%1, {%0}
4844    stmia\\t%0, {%1}
4845    ldr\\t%0, %1
4846    str\\t%1, %0
4847    mov\\t%0, %1
4848    mov\\t%0, %1"
4849   [(set_attr "length" "2")
4850    (set_attr "type" "*,load,store1,load,store1,*,*")
4851    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4854 (define_expand "movdf"
4855   [(set (match_operand:DF 0 "general_operand" "")
4856         (match_operand:DF 1 "general_operand" ""))]
4857   "TARGET_EITHER"
4858   "
4859   if (TARGET_ARM)
4860     {
4861       if (GET_CODE (operands[0]) == MEM)
4862         operands[1] = force_reg (DFmode, operands[1]);
4863     }
4864   else /* TARGET_THUMB */
4865     {
4866       if (!no_new_pseudos)
4867         {
4868           if (GET_CODE (operands[0]) != REG)
4869             operands[1] = force_reg (DFmode, operands[1]);
4870         }
4871     }
4872   "
4875 ;; Reloading a df mode value stored in integer regs to memory can require a
4876 ;; scratch reg.
4877 (define_expand "reload_outdf"
4878   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4879    (match_operand:DF 1 "s_register_operand" "r")
4880    (match_operand:SI 2 "s_register_operand" "=&r")]
4881   "TARGET_ARM"
4882   "
4883   {
4884     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4886     if (code == REG)
4887       operands[2] = XEXP (operands[0], 0);
4888     else if (code == POST_INC || code == PRE_DEC)
4889       {
4890         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4891         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4892         emit_insn (gen_movdi (operands[0], operands[1]));
4893         DONE;
4894       }
4895     else if (code == PRE_INC)
4896       {
4897         rtx reg = XEXP (XEXP (operands[0], 0), 0);
4899         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4900         operands[2] = reg;
4901       }
4902     else if (code == POST_DEC)
4903       operands[2] = XEXP (XEXP (operands[0], 0), 0);
4904     else
4905       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4906                              XEXP (XEXP (operands[0], 0), 1)));
4908     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4909                             operands[1]));
4911     if (code == POST_DEC)
4912       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4914     DONE;
4915   }"
4918 (define_insn "*movdf_hard_insn"
4919   [(set (match_operand:DF 0 "nonimmediate_operand"
4920                                                 "=r,Q,r,m,r, f, f,f, m,!f,!r")
4921         (match_operand:DF 1 "general_operand"
4922                                                 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
4923   "TARGET_ARM
4924    && TARGET_HARD_FLOAT
4925    && (GET_CODE (operands[0]) != MEM
4926        || register_operand (operands[1], DFmode))"
4927   "*
4928   {
4929   switch (which_alternative)
4930     {
4931     default:
4932     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
4933     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
4934     case 2: case 3: case 4: return output_move_double (operands);
4935     case 5: return \"mvf%?d\\t%0, %1\";
4936     case 6: return \"mnf%?d\\t%0, #%N1\";
4937     case 7: return \"ldf%?d\\t%0, %1\";
4938     case 8: return \"stf%?d\\t%1, %0\";
4939     case 9: return output_mov_double_fpu_from_arm (operands);
4940     case 10: return output_mov_double_arm_from_fpu (operands);
4941     }
4942   }
4943   "
4944   [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
4945    (set_attr "predicable" "yes")
4946    (set_attr "type"
4947     "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
4948    (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
4949    (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
4952 ;; Software floating point version.  This is essentially the same as movdi.
4953 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
4954 ;; an `f' reg.
4956 (define_insn "*movdf_soft_insn"
4957   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4958         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4959   "TARGET_ARM && TARGET_SOFT_FLOAT
4960    && !TARGET_CIRRUS
4961   "
4962   "* return output_move_double (operands);"
4963   [(set_attr "length" "8,8,8")
4964    (set_attr "type" "*,load,store2")
4965    (set_attr "pool_range" "1020")
4966    (set_attr "neg_pool_range" "1008")]
4969 ;;; ??? This should have alternatives for constants.
4970 ;;; ??? This was originally identical to the movdi_insn pattern.
4971 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4972 ;;; thumb_reorg with a memory reference.
4973 (define_insn "*thumb_movdf_insn"
4974   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4975         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
4976   "TARGET_THUMB
4977    && (   register_operand (operands[0], DFmode)
4978        || register_operand (operands[1], DFmode))"
4979   "*
4980   switch (which_alternative)
4981     {
4982     default:
4983     case 0:
4984       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4985         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4986       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4987     case 1:
4988       return \"ldmia\\t%1, {%0, %H0}\";
4989     case 2:
4990       return \"stmia\\t%0, {%1, %H1}\";
4991     case 3:
4992       return thumb_load_double_from_address (operands);
4993     case 4:
4994       operands[2] = gen_rtx (MEM, SImode,
4995                              plus_constant (XEXP (operands[0], 0), 4));
4996       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4997       return \"\";
4998     case 5:
4999       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5000         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5001       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5002     }
5003   "
5004   [(set_attr "length" "4,2,2,6,4,4")
5005    (set_attr "type" "*,load,store2,load,store2,*")
5006    (set_attr "pool_range" "*,*,*,1020,*,*")]
5010 ;; Saving and restoring the floating point registers in the prologue should
5011 ;; be done in XFmode, even though we don't support that for anything else
5012 ;; (Well, strictly it's 'internal representation', but that's effectively
5013 ;; XFmode).
5015 (define_insn "*movxf_hard_insn"
5016   [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5017         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5018   "TARGET_ARM && TARGET_HARD_FLOAT && reload_completed"
5019   "*
5020   switch (which_alternative)
5021     {
5022     default:
5023     case 0: return \"mvf%?e\\t%0, %1\";
5024     case 1: return \"mnf%?e\\t%0, #%N1\";
5025     case 2: return \"ldf%?e\\t%0, %1\";
5026     case 3: return \"stf%?e\\t%1, %0\";
5027     case 4: return output_mov_long_double_fpu_from_arm (operands);
5028     case 5: return output_mov_long_double_arm_from_fpu (operands);
5029     case 6: return output_mov_long_double_arm_from_arm (operands);
5030     }
5031   "
5032   [(set_attr "length" "4,4,4,4,8,8,12")
5033    (set_attr "predicable" "yes")
5034    (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5035    (set_attr "pool_range" "*,*,1024,*,*,*,*")
5036    (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5040 ;; load- and store-multiple insns
5041 ;; The arm can load/store any set of registers, provided that they are in
5042 ;; ascending order; but that is beyond GCC so stick with what it knows.
5044 (define_expand "load_multiple"
5045   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5046                           (match_operand:SI 1 "" ""))
5047                      (use (match_operand:SI 2 "" ""))])]
5048   "TARGET_ARM"
5049   "
5050   /* Support only fixed point registers.  */
5051   if (GET_CODE (operands[2]) != CONST_INT
5052       || INTVAL (operands[2]) > 14
5053       || INTVAL (operands[2]) < 2
5054       || GET_CODE (operands[1]) != MEM
5055       || GET_CODE (operands[0]) != REG
5056       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5057       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5058     FAIL;
5060   operands[3]
5061     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5062                              force_reg (SImode, XEXP (operands[1], 0)),
5063                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5064                              MEM_IN_STRUCT_P(operands[1]),
5065                              MEM_SCALAR_P (operands[1]));
5066   "
5069 ;; Load multiple with write-back
5071 (define_insn "*ldmsi_postinc4"
5072   [(match_parallel 0 "load_multiple_operation"
5073     [(set (match_operand:SI 1 "s_register_operand" "=r")
5074           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5075                    (const_int 16)))
5076      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5077           (mem:SI (match_dup 2)))
5078      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5079           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5080      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5081           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5082      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5083           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5084   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5085   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5086   [(set_attr "type" "load")
5087    (set_attr "predicable" "yes")]
5090 (define_insn "*ldmsi_postinc3"
5091   [(match_parallel 0 "load_multiple_operation"
5092     [(set (match_operand:SI 1 "s_register_operand" "=r")
5093           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5094                    (const_int 12)))
5095      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5096           (mem:SI (match_dup 2)))
5097      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5098           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5099      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5100           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5101   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5102   "ldm%?ia\\t%1!, {%3, %4, %5}"
5103   [(set_attr "type" "load")
5104    (set_attr "predicable" "yes")]
5107 (define_insn "*ldmsi_postinc2"
5108   [(match_parallel 0 "load_multiple_operation"
5109     [(set (match_operand:SI 1 "s_register_operand" "=r")
5110           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5111                    (const_int 8)))
5112      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5113           (mem:SI (match_dup 2)))
5114      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5115           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5116   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5117   "ldm%?ia\\t%1!, {%3, %4}"
5118   [(set_attr "type" "load")
5119    (set_attr "predicable" "yes")]
5122 ;; Ordinary load multiple
5124 (define_insn "*ldmsi4"
5125   [(match_parallel 0 "load_multiple_operation"
5126     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5127           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5128      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5129           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5130      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5131           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5132      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5133           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5134   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5135   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5136   [(set_attr "type" "load")
5137    (set_attr "predicable" "yes")]
5140 (define_insn "*ldmsi3"
5141   [(match_parallel 0 "load_multiple_operation"
5142     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5143           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5144      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5145           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5146      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5147           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5148   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5149   "ldm%?ia\\t%1, {%2, %3, %4}"
5150   [(set_attr "type" "load")
5151    (set_attr "predicable" "yes")]
5154 (define_insn "*ldmsi2"
5155   [(match_parallel 0 "load_multiple_operation"
5156     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5157           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5158      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5159           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5160   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5161   "ldm%?ia\\t%1, {%2, %3}"
5162   [(set_attr "type" "load")
5163    (set_attr "predicable" "yes")]
5166 (define_expand "store_multiple"
5167   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5168                           (match_operand:SI 1 "" ""))
5169                      (use (match_operand:SI 2 "" ""))])]
5170   "TARGET_ARM"
5171   "
5172   /* Support only fixed point registers */
5173   if (GET_CODE (operands[2]) != CONST_INT
5174       || INTVAL (operands[2]) > 14
5175       || INTVAL (operands[2]) < 2
5176       || GET_CODE (operands[1]) != REG
5177       || GET_CODE (operands[0]) != MEM
5178       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5179       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5180     FAIL;
5182   operands[3]
5183     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5184                               force_reg (SImode, XEXP (operands[0], 0)),
5185                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5186                               MEM_IN_STRUCT_P(operands[0]), 
5187                               MEM_SCALAR_P (operands[0]));
5188   "
5191 ;; Store multiple with write-back
5193 (define_insn "*stmsi_postinc4"
5194   [(match_parallel 0 "store_multiple_operation"
5195     [(set (match_operand:SI 1 "s_register_operand" "=r")
5196           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5197                    (const_int 16)))
5198      (set (mem:SI (match_dup 2))
5199           (match_operand:SI 3 "arm_hard_register_operand" ""))
5200      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5201           (match_operand:SI 4 "arm_hard_register_operand" ""))
5202      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5203           (match_operand:SI 5 "arm_hard_register_operand" ""))
5204      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5205           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5206   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5207   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5208   [(set_attr "predicable" "yes")
5209    (set_attr "type" "store4")]
5212 (define_insn "*stmsi_postinc3"
5213   [(match_parallel 0 "store_multiple_operation"
5214     [(set (match_operand:SI 1 "s_register_operand" "=r")
5215           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5216                    (const_int 12)))
5217      (set (mem:SI (match_dup 2))
5218           (match_operand:SI 3 "arm_hard_register_operand" ""))
5219      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5220           (match_operand:SI 4 "arm_hard_register_operand" ""))
5221      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5222           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5223   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5224   "stm%?ia\\t%1!, {%3, %4, %5}"
5225   [(set_attr "predicable" "yes")
5226    (set_attr "type" "store3")]
5229 (define_insn "*stmsi_postinc2"
5230   [(match_parallel 0 "store_multiple_operation"
5231     [(set (match_operand:SI 1 "s_register_operand" "=r")
5232           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5233                    (const_int 8)))
5234      (set (mem:SI (match_dup 2))
5235           (match_operand:SI 3 "arm_hard_register_operand" ""))
5236      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5237           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5238   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5239   "stm%?ia\\t%1!, {%3, %4}"
5240   [(set_attr "predicable" "yes")
5241    (set_attr "type" "store2")]
5244 ;; Ordinary store multiple
5246 (define_insn "*stmsi4"
5247   [(match_parallel 0 "store_multiple_operation"
5248     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5249           (match_operand:SI 2 "arm_hard_register_operand" ""))
5250      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5251           (match_operand:SI 3 "arm_hard_register_operand" ""))
5252      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5253           (match_operand:SI 4 "arm_hard_register_operand" ""))
5254      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5255           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5256   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5257   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5258   [(set_attr "predicable" "yes")
5259    (set_attr "type" "store4")]
5262 (define_insn "*stmsi3"
5263   [(match_parallel 0 "store_multiple_operation"
5264     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5265           (match_operand:SI 2 "arm_hard_register_operand" ""))
5266      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5267           (match_operand:SI 3 "arm_hard_register_operand" ""))
5268      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5269           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5270   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5271   "stm%?ia\\t%1, {%2, %3, %4}"
5272   [(set_attr "predicable" "yes")
5273    (set_attr "type" "store3")]
5276 (define_insn "*stmsi2"
5277   [(match_parallel 0 "store_multiple_operation"
5278     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5279           (match_operand:SI 2 "arm_hard_register_operand" ""))
5280      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5281           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5282   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5283   "stm%?ia\\t%1, {%2, %3}"
5284   [(set_attr "predicable" "yes")
5285    (set_attr "type" "store2")]
5288 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5289 ;; We could let this apply for blocks of less than this, but it clobbers so
5290 ;; many registers that there is then probably a better way.
5292 (define_expand "movstrqi"
5293   [(match_operand:BLK 0 "general_operand" "")
5294    (match_operand:BLK 1 "general_operand" "")
5295    (match_operand:SI 2 "const_int_operand" "")
5296    (match_operand:SI 3 "const_int_operand" "")]
5297   "TARGET_EITHER"
5298   "
5299   if (TARGET_ARM)
5300     {
5301       if (arm_gen_movstrqi (operands))
5302         DONE;
5303       FAIL;
5304     }
5305   else /* TARGET_THUMB */
5306     {
5307       if (   INTVAL (operands[3]) != 4
5308           || INTVAL (operands[2]) > 48)
5309         FAIL;
5311       thumb_expand_movstrqi (operands);
5312       DONE;
5313     }
5314   "
5317 ;; Thumb block-move insns
5319 (define_insn "movmem12b"
5320   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5321         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5322    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5323         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5324    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5325         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5326    (set (match_operand:SI 0 "register_operand" "=l")
5327         (plus:SI (match_dup 2) (const_int 12)))
5328    (set (match_operand:SI 1 "register_operand" "=l")
5329         (plus:SI (match_dup 3) (const_int 12)))
5330    (clobber (match_scratch:SI 4 "=&l"))
5331    (clobber (match_scratch:SI 5 "=&l"))
5332    (clobber (match_scratch:SI 6 "=&l"))]
5333   "TARGET_THUMB"
5334   "* return thumb_output_move_mem_multiple (3, operands);"
5335   [(set_attr "length" "4")
5336    ; This isn't entirely accurate...  It loads as well, but in terms of
5337    ; scheduling the following insn it is better to consider it as a store
5338    (set_attr "type" "store3")]
5341 (define_insn "movmem8b"
5342   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5343         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5344    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5345         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5346    (set (match_operand:SI 0 "register_operand" "=l")
5347         (plus:SI (match_dup 2) (const_int 8)))
5348    (set (match_operand:SI 1 "register_operand" "=l")
5349         (plus:SI (match_dup 3) (const_int 8)))
5350    (clobber (match_scratch:SI 4 "=&l"))
5351    (clobber (match_scratch:SI 5 "=&l"))]
5352   "TARGET_THUMB"
5353   "* return thumb_output_move_mem_multiple (2, operands);"
5354   [(set_attr "length" "4")
5355    ; This isn't entirely accurate...  It loads as well, but in terms of
5356    ; scheduling the following insn it is better to consider it as a store
5357    (set_attr "type" "store2")]
5362 ;; Compare & branch insns
5363 ;; The range calcualations are based as follows:
5364 ;; For forward branches, the address calculation returns the address of
5365 ;; the next instruction.  This is 2 beyond the branch instruction.
5366 ;; For backward branches, the address calculation returns the address of
5367 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5368 ;; instruction for the shortest sequence, and 4 before the branch instruction
5369 ;; if we have to jump around an unconditional branch.
5370 ;; To the basic branch range the PC offset must be added (this is +4).
5371 ;; So for forward branches we have 
5372 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5373 ;; And for backward branches we have 
5374 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5376 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5377 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5379 (define_insn "cbranchsi4"
5380   [(set (pc)
5381         (if_then_else
5382             (match_operator                    0 "arm_comparison_operator"
5383                             [(match_operand:SI 1 "register_operand"   "l,r")
5384                              (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5385             (label_ref       (match_operand    3 "" ""))
5386             (pc)))]
5387   "TARGET_THUMB"
5388   "*
5389   output_asm_insn (\"cmp\\t%1, %2\", operands);
5390   switch (get_attr_length (insn))
5391     {
5392     case 4:  return \"b%d0\\t%l3\";
5393     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5394     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5395     }
5396   "
5397   [(set (attr "far_jump")
5398         (if_then_else
5399             (eq_attr "length" "8")
5400             (const_string "yes")
5401             (const_string "no")))
5402    (set (attr "length") 
5403         (if_then_else
5404             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5405                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5406             (const_int 4)
5407             (if_then_else
5408                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5409                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5410                 (const_int 6)
5411                 (const_int 8))))]
5414 (define_insn "*negated_cbranchsi4"
5415   [(set (pc)
5416         (if_then_else
5417          (match_operator             0 "arm_comparison_operator"
5418           [(match_operand:SI         1 "register_operand"  "l")
5419            (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5420          (label_ref (match_operand   3 "" ""))
5421          (pc)))]
5422   "TARGET_THUMB"
5423   "*
5424   output_asm_insn (\"cmn\\t%1, %2\", operands);
5425   switch (get_attr_length (insn))
5426     {
5427     case 4:  return \"b%d0\\t%l3\";
5428     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5429     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5430     }
5431   "
5432   [(set (attr "far_jump")
5433         (if_then_else
5434             (eq_attr "length" "8")
5435             (const_string "yes")
5436             (const_string "no")))
5437    (set (attr "length") 
5438         (if_then_else
5439             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5440                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5441             (const_int 4)
5442             (if_then_else
5443                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5444                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5445                 (const_int 6)
5446                 (const_int 8))))]
5450 ;; Comparison and test insns
5452 (define_expand "cmpsi"
5453   [(match_operand:SI 0 "s_register_operand" "")
5454    (match_operand:SI 1 "arm_add_operand" "")]
5455   "TARGET_ARM"
5456   "{
5457     arm_compare_op0 = operands[0];
5458     arm_compare_op1 = operands[1];
5459     DONE;
5460   }"
5463 (define_expand "cmpsf"
5464   [(match_operand:SF 0 "s_register_operand" "")
5465    (match_operand:SF 1 "fpu_rhs_operand" "")]
5466   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5467   "
5468   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5469     operands[1] = force_reg (SFmode, operands[1]);
5471   arm_compare_op0 = operands[0];
5472   arm_compare_op1 = operands[1];
5473   DONE;
5474   "
5477 (define_expand "cmpdf"
5478   [(match_operand:DF 0 "s_register_operand" "")
5479    (match_operand:DF 1 "fpu_rhs_operand" "")]
5480   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5481   "
5482   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5483     operands[1] = force_reg (DFmode, operands[1]);
5485   arm_compare_op0 = operands[0];
5486   arm_compare_op1 = operands[1];
5487   DONE;
5488   "
5491 (define_insn "*arm_cmpsi_insn"
5492   [(set (reg:CC CC_REGNUM)
5493         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5494                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5495   "TARGET_ARM"
5496   "@
5497    cmp%?\\t%0, %1
5498    cmn%?\\t%0, #%n1"
5499   [(set_attr "conds" "set")]
5502 (define_insn "*cmpsi_shiftsi"
5503   [(set (reg:CC CC_REGNUM)
5504         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
5505                     (match_operator:SI  3 "shift_operator"
5506                      [(match_operand:SI 1 "s_register_operand" "r")
5507                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5508   "TARGET_ARM"
5509   "cmp%?\\t%0, %1%S3"
5510   [(set_attr "conds" "set")
5511    (set_attr "shift" "1")
5512    ]
5515 (define_insn "*cmpsi_shiftsi_swp"
5516   [(set (reg:CC_SWP CC_REGNUM)
5517         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5518                          [(match_operand:SI 1 "s_register_operand" "r")
5519                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
5520                         (match_operand:SI 0 "s_register_operand" "r")))]
5521   "TARGET_ARM"
5522   "cmp%?\\t%0, %1%S3"
5523   [(set_attr "conds" "set")
5524    (set_attr "shift" "1")
5525    ]
5528 (define_insn "*cmpsi_neg_shiftsi"
5529   [(set (reg:CC CC_REGNUM)
5530         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5531                     (neg:SI (match_operator:SI 3 "shift_operator"
5532                              [(match_operand:SI 1 "s_register_operand" "r")
5533                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5534   "TARGET_ARM"
5535   "cmn%?\\t%0, %1%S3"
5536   [(set_attr "conds" "set")
5537    (set_attr "shift" "1")
5538    ]
5541 (define_insn "*cmpsf_insn"
5542   [(set (reg:CCFP CC_REGNUM)
5543         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5544                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5545   "TARGET_ARM && TARGET_HARD_FLOAT"
5546   "@
5547    cmf%?\\t%0, %1
5548    cnf%?\\t%0, #%N1"
5549   [(set_attr "conds" "set")
5550    (set_attr "type" "f_2_r")]
5553 (define_insn "*cmpdf_insn"
5554   [(set (reg:CCFP CC_REGNUM)
5555         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5556                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5557   "TARGET_ARM && TARGET_HARD_FLOAT"
5558   "@
5559    cmf%?\\t%0, %1
5560    cnf%?\\t%0, #%N1"
5561   [(set_attr "conds" "set")
5562    (set_attr "type" "f_2_r")]
5565 (define_insn "*cmpesfdf_df"
5566   [(set (reg:CCFP CC_REGNUM)
5567         (compare:CCFP (float_extend:DF
5568                        (match_operand:SF 0 "s_register_operand" "f,f"))
5569                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5570   "TARGET_ARM && TARGET_HARD_FLOAT"
5571   "@
5572    cmf%?\\t%0, %1
5573    cnf%?\\t%0, #%N1"
5574   [(set_attr "conds" "set")
5575    (set_attr "type" "f_2_r")]
5578 (define_insn "*cmpdf_esfdf"
5579   [(set (reg:CCFP CC_REGNUM)
5580         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5581                       (float_extend:DF
5582                        (match_operand:SF 1 "s_register_operand" "f"))))]
5583   "TARGET_ARM && TARGET_HARD_FLOAT"
5584   "cmf%?\\t%0, %1"
5585   [(set_attr "conds" "set")
5586    (set_attr "type" "f_2_r")]
5589 ;; Cirrus SF compare instruction
5590 (define_insn "*cirrus_cmpsf"
5591   [(set (reg:CCFP CC_REGNUM)
5592         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5593                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
5594   "TARGET_ARM && TARGET_CIRRUS"
5595   "cfcmps%?\\tr15, %V0, %V1"
5596   [(set_attr "type"   "mav_farith")
5597    (set_attr "cirrus" "compare")]
5600 ;; Cirrus DF compare instruction
5601 (define_insn "*cirrus_cmpdf"
5602   [(set (reg:CCFP CC_REGNUM)
5603         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5604                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
5605   "TARGET_ARM && TARGET_CIRRUS"
5606   "cfcmpd%?\\tr15, %V0, %V1"
5607   [(set_attr "type"   "mav_farith")
5608    (set_attr "cirrus" "compare")]
5611 ;; Cirrus DI compare instruction
5612 (define_expand "cmpdi"
5613   [(match_operand:DI 0 "cirrus_fp_register" "")
5614    (match_operand:DI 1 "cirrus_fp_register" "")]
5615   "TARGET_ARM && TARGET_CIRRUS"
5616   "{
5617      arm_compare_op0 = operands[0];
5618      arm_compare_op1 = operands[1];
5619      DONE;
5620    }")
5622 (define_insn "*cirrus_cmpdi"
5623   [(set (reg:CC CC_REGNUM)
5624         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5625                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
5626   "TARGET_ARM && TARGET_CIRRUS"
5627   "cfcmp64%?\\tr15, %V0, %V1"
5628   [(set_attr "type"   "mav_farith")
5629    (set_attr "cirrus" "compare")]
5632 (define_insn "*cmpsf_trap"
5633   [(set (reg:CCFPE CC_REGNUM)
5634         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5635                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5636   "TARGET_ARM && TARGET_HARD_FLOAT"
5637   "@
5638    cmf%?e\\t%0, %1
5639    cnf%?e\\t%0, #%N1"
5640   [(set_attr "conds" "set")
5641    (set_attr "type" "f_2_r")]
5644 (define_insn "*cmpdf_trap"
5645   [(set (reg:CCFPE CC_REGNUM)
5646         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5647                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5648   "TARGET_ARM && TARGET_HARD_FLOAT"
5649   "@
5650    cmf%?e\\t%0, %1
5651    cnf%?e\\t%0, #%N1"
5652   [(set_attr "conds" "set")
5653    (set_attr "type" "f_2_r")]
5656 (define_insn "*cmp_esfdf_df_trap"
5657   [(set (reg:CCFPE CC_REGNUM)
5658         (compare:CCFPE (float_extend:DF
5659                         (match_operand:SF 0 "s_register_operand" "f,f"))
5660                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5661   "TARGET_ARM && TARGET_HARD_FLOAT"
5662   "@
5663    cmf%?e\\t%0, %1
5664    cnf%?e\\t%0, #%N1"
5665   [(set_attr "conds" "set")
5666    (set_attr "type" "f_2_r")]
5669 (define_insn "*cmp_df_esfdf_trap"
5670   [(set (reg:CCFPE CC_REGNUM)
5671         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5672                        (float_extend:DF
5673                         (match_operand:SF 1 "s_register_operand" "f"))))]
5674   "TARGET_ARM && TARGET_HARD_FLOAT"
5675   "cmf%?e\\t%0, %1"
5676   [(set_attr "conds" "set")
5677    (set_attr "type" "f_2_r")]
5680 ; This insn allows redundant compares to be removed by cse, nothing should
5681 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5682 ; is deleted later on. The match_dup will match the mode here, so that
5683 ; mode changes of the condition codes aren't lost by this even though we don't
5684 ; specify what they are.
5686 (define_insn "*deleted_compare"
5687   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5688   "TARGET_ARM"
5689   "\\t%@ deleted compare"
5690   [(set_attr "conds" "set")
5691    (set_attr "length" "0")]
5695 ;; Conditional branch insns
5697 (define_expand "beq"
5698   [(set (pc)
5699         (if_then_else (eq (match_dup 1) (const_int 0))
5700                       (label_ref (match_operand 0 "" ""))
5701                       (pc)))]
5702   "TARGET_ARM"
5703   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5706 (define_expand "bne"
5707   [(set (pc)
5708         (if_then_else (ne (match_dup 1) (const_int 0))
5709                       (label_ref (match_operand 0 "" ""))
5710                       (pc)))]
5711   "TARGET_ARM"
5712   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5715 (define_expand "bgt"
5716   [(set (pc)
5717         (if_then_else (gt (match_dup 1) (const_int 0))
5718                       (label_ref (match_operand 0 "" ""))
5719                       (pc)))]
5720   "TARGET_ARM"
5721   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5724 (define_expand "ble"
5725   [(set (pc)
5726         (if_then_else (le (match_dup 1) (const_int 0))
5727                       (label_ref (match_operand 0 "" ""))
5728                       (pc)))]
5729   "TARGET_ARM"
5730   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5733 (define_expand "bge"
5734   [(set (pc)
5735         (if_then_else (ge (match_dup 1) (const_int 0))
5736                       (label_ref (match_operand 0 "" ""))
5737                       (pc)))]
5738   "TARGET_ARM"
5739   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5742 (define_expand "blt"
5743   [(set (pc)
5744         (if_then_else (lt (match_dup 1) (const_int 0))
5745                       (label_ref (match_operand 0 "" ""))
5746                       (pc)))]
5747   "TARGET_ARM"
5748   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5751 (define_expand "bgtu"
5752   [(set (pc)
5753         (if_then_else (gtu (match_dup 1) (const_int 0))
5754                       (label_ref (match_operand 0 "" ""))
5755                       (pc)))]
5756   "TARGET_ARM"
5757   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5760 (define_expand "bleu"
5761   [(set (pc)
5762         (if_then_else (leu (match_dup 1) (const_int 0))
5763                       (label_ref (match_operand 0 "" ""))
5764                       (pc)))]
5765   "TARGET_ARM"
5766   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5769 (define_expand "bgeu"
5770   [(set (pc)
5771         (if_then_else (geu (match_dup 1) (const_int 0))
5772                       (label_ref (match_operand 0 "" ""))
5773                       (pc)))]
5774   "TARGET_ARM"
5775   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5778 (define_expand "bltu"
5779   [(set (pc)
5780         (if_then_else (ltu (match_dup 1) (const_int 0))
5781                       (label_ref (match_operand 0 "" ""))
5782                       (pc)))]
5783   "TARGET_ARM"
5784   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5787 (define_expand "bunordered"
5788   [(set (pc)
5789         (if_then_else (unordered (match_dup 1) (const_int 0))
5790                       (label_ref (match_operand 0 "" ""))
5791                       (pc)))]
5792   "TARGET_ARM && TARGET_HARD_FLOAT"
5793   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5794                                       arm_compare_op1);"
5797 (define_expand "bordered"
5798   [(set (pc)
5799         (if_then_else (ordered (match_dup 1) (const_int 0))
5800                       (label_ref (match_operand 0 "" ""))
5801                       (pc)))]
5802   "TARGET_ARM && TARGET_HARD_FLOAT"
5803   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5804                                       arm_compare_op1);"
5807 (define_expand "bungt"
5808   [(set (pc)
5809         (if_then_else (ungt (match_dup 1) (const_int 0))
5810                       (label_ref (match_operand 0 "" ""))
5811                       (pc)))]
5812   "TARGET_ARM && TARGET_HARD_FLOAT"
5813   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5816 (define_expand "bunlt"
5817   [(set (pc)
5818         (if_then_else (unlt (match_dup 1) (const_int 0))
5819                       (label_ref (match_operand 0 "" ""))
5820                       (pc)))]
5821   "TARGET_ARM && TARGET_HARD_FLOAT"
5822   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5825 (define_expand "bunge"
5826   [(set (pc)
5827         (if_then_else (unge (match_dup 1) (const_int 0))
5828                       (label_ref (match_operand 0 "" ""))
5829                       (pc)))]
5830   "TARGET_ARM && TARGET_HARD_FLOAT"
5831   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5834 (define_expand "bunle"
5835   [(set (pc)
5836         (if_then_else (unle (match_dup 1) (const_int 0))
5837                       (label_ref (match_operand 0 "" ""))
5838                       (pc)))]
5839   "TARGET_ARM && TARGET_HARD_FLOAT"
5840   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5843 ;; The following two patterns need two branch instructions, since there is
5844 ;; no single instruction that will handle all cases.
5845 (define_expand "buneq"
5846   [(set (pc)
5847         (if_then_else (uneq (match_dup 1) (const_int 0))
5848                       (label_ref (match_operand 0 "" ""))
5849                       (pc)))]
5850   "TARGET_ARM && TARGET_HARD_FLOAT"
5851   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5854 (define_expand "bltgt"
5855   [(set (pc)
5856         (if_then_else (ltgt (match_dup 1) (const_int 0))
5857                       (label_ref (match_operand 0 "" ""))
5858                       (pc)))]
5859   "TARGET_ARM && TARGET_HARD_FLOAT"
5860   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5864 ;; Patterns to match conditional branch insns.
5867 ; Special pattern to match UNEQ.
5868 (define_insn "*arm_buneq"
5869   [(set (pc)
5870         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5871                       (label_ref (match_operand 0 "" ""))
5872                       (pc)))]
5873   "TARGET_ARM && TARGET_HARD_FLOAT"
5874   "*
5875   if (arm_ccfsm_state != 0)
5876     abort ();
5878   return \"bvs\\t%l0\;beq\\t%l0\";
5879   "
5880   [(set_attr "conds" "jump_clob")
5881    (set_attr "length" "8")]
5884 ; Special pattern to match LTGT.
5885 (define_insn "*arm_bltgt"
5886   [(set (pc)
5887         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5888                       (label_ref (match_operand 0 "" ""))
5889                       (pc)))]
5890   "TARGET_ARM && TARGET_HARD_FLOAT"
5891   "*
5892   if (arm_ccfsm_state != 0)
5893     abort ();
5895   return \"bmi\\t%l0\;bgt\\t%l0\";
5896   "
5897   [(set_attr "conds" "jump_clob")
5898    (set_attr "length" "8")]
5901 (define_insn "*arm_cond_branch"
5902   [(set (pc)
5903         (if_then_else (match_operator 1 "arm_comparison_operator"
5904                        [(match_operand 2 "cc_register" "") (const_int 0)])
5905                       (label_ref (match_operand 0 "" ""))
5906                       (pc)))]
5907   "TARGET_ARM"
5908   "*
5909   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5910     {
5911       arm_ccfsm_state += 2;
5912       return \"\";
5913     }
5914   return \"b%d1\\t%l0\";
5915   "
5916   [(set_attr "conds" "use")]
5919 ; Special pattern to match reversed UNEQ.
5920 (define_insn "*arm_buneq_reversed"
5921   [(set (pc)
5922         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5923                       (pc)
5924                       (label_ref (match_operand 0 "" ""))))]
5925   "TARGET_ARM && TARGET_HARD_FLOAT"
5926   "*
5927   if (arm_ccfsm_state != 0)
5928     abort ();
5930   return \"bmi\\t%l0\;bgt\\t%l0\";
5931   "
5932   [(set_attr "conds" "jump_clob")
5933    (set_attr "length" "8")]
5936 ; Special pattern to match reversed LTGT.
5937 (define_insn "*arm_bltgt_reversed"
5938   [(set (pc)
5939         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5940                       (pc)
5941                       (label_ref (match_operand 0 "" ""))))]
5942   "TARGET_ARM && TARGET_HARD_FLOAT"
5943   "*
5944   if (arm_ccfsm_state != 0)
5945     abort ();
5947   return \"bvs\\t%l0\;beq\\t%l0\";
5948   "
5949   [(set_attr "conds" "jump_clob")
5950    (set_attr "length" "8")]
5953 (define_insn "*arm_cond_branch_reversed"
5954   [(set (pc)
5955         (if_then_else (match_operator 1 "arm_comparison_operator"
5956                        [(match_operand 2 "cc_register" "") (const_int 0)])
5957                       (pc)
5958                       (label_ref (match_operand 0 "" ""))))]
5959   "TARGET_ARM"
5960   "*
5961   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5962     {
5963       arm_ccfsm_state += 2;
5964       return \"\";
5965     }
5966   return \"b%D1\\t%l0\";
5967   "
5968   [(set_attr "conds" "use")]
5973 ; scc insns
5975 (define_expand "seq"
5976   [(set (match_operand:SI 0 "s_register_operand" "=r")
5977         (eq:SI (match_dup 1) (const_int 0)))]
5978   "TARGET_ARM"
5979   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5982 (define_expand "sne"
5983   [(set (match_operand:SI 0 "s_register_operand" "=r")
5984         (ne:SI (match_dup 1) (const_int 0)))]
5985   "TARGET_ARM"
5986   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5989 (define_expand "sgt"
5990   [(set (match_operand:SI 0 "s_register_operand" "=r")
5991         (gt:SI (match_dup 1) (const_int 0)))]
5992   "TARGET_ARM"
5993   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5996 (define_expand "sle"
5997   [(set (match_operand:SI 0 "s_register_operand" "=r")
5998         (le:SI (match_dup 1) (const_int 0)))]
5999   "TARGET_ARM"
6000   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6003 (define_expand "sge"
6004   [(set (match_operand:SI 0 "s_register_operand" "=r")
6005         (ge:SI (match_dup 1) (const_int 0)))]
6006   "TARGET_ARM"
6007   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6010 (define_expand "slt"
6011   [(set (match_operand:SI 0 "s_register_operand" "=r")
6012         (lt:SI (match_dup 1) (const_int 0)))]
6013   "TARGET_ARM"
6014   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6017 (define_expand "sgtu"
6018   [(set (match_operand:SI 0 "s_register_operand" "=r")
6019         (gtu:SI (match_dup 1) (const_int 0)))]
6020   "TARGET_ARM"
6021   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6024 (define_expand "sleu"
6025   [(set (match_operand:SI 0 "s_register_operand" "=r")
6026         (leu:SI (match_dup 1) (const_int 0)))]
6027   "TARGET_ARM"
6028   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6031 (define_expand "sgeu"
6032   [(set (match_operand:SI 0 "s_register_operand" "=r")
6033         (geu:SI (match_dup 1) (const_int 0)))]
6034   "TARGET_ARM"
6035   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6038 (define_expand "sltu"
6039   [(set (match_operand:SI 0 "s_register_operand" "=r")
6040         (ltu:SI (match_dup 1) (const_int 0)))]
6041   "TARGET_ARM"
6042   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6045 (define_expand "sunordered"
6046   [(set (match_operand:SI 0 "s_register_operand" "=r")
6047         (unordered:SI (match_dup 1) (const_int 0)))]
6048   "TARGET_ARM && TARGET_HARD_FLOAT"
6049   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6050                                       arm_compare_op1);"
6053 (define_expand "sordered"
6054   [(set (match_operand:SI 0 "s_register_operand" "=r")
6055         (ordered:SI (match_dup 1) (const_int 0)))]
6056   "TARGET_ARM && TARGET_HARD_FLOAT"
6057   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6058                                       arm_compare_op1);"
6061 (define_expand "sungt"
6062   [(set (match_operand:SI 0 "s_register_operand" "=r")
6063         (ungt:SI (match_dup 1) (const_int 0)))]
6064   "TARGET_ARM && TARGET_HARD_FLOAT"
6065   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6066                                       arm_compare_op1);"
6069 (define_expand "sunge"
6070   [(set (match_operand:SI 0 "s_register_operand" "=r")
6071         (unge:SI (match_dup 1) (const_int 0)))]
6072   "TARGET_ARM && TARGET_HARD_FLOAT"
6073   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6074                                       arm_compare_op1);"
6077 (define_expand "sunlt"
6078   [(set (match_operand:SI 0 "s_register_operand" "=r")
6079         (unlt:SI (match_dup 1) (const_int 0)))]
6080   "TARGET_ARM && TARGET_HARD_FLOAT"
6081   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6082                                       arm_compare_op1);"
6085 (define_expand "sunle"
6086   [(set (match_operand:SI 0 "s_register_operand" "=r")
6087         (unle:SI (match_dup 1) (const_int 0)))]
6088   "TARGET_ARM && TARGET_HARD_FLOAT"
6089   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6090                                       arm_compare_op1);"
6093 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6094 ;;; simple ARM instructions. 
6096 ; (define_expand "suneq"
6097 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6098 ;       (uneq:SI (match_dup 1) (const_int 0)))]
6099 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6100 ;   "abort ();"
6101 ; )
6103 ; (define_expand "sltgt"
6104 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6105 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
6106 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6107 ;   "abort ();"
6108 ; )
6110 (define_insn "*mov_scc"
6111   [(set (match_operand:SI 0 "s_register_operand" "=r")
6112         (match_operator:SI 1 "arm_comparison_operator"
6113          [(match_operand 2 "cc_register" "") (const_int 0)]))]
6114   "TARGET_ARM"
6115   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6116   [(set_attr "conds" "use")
6117    (set_attr "length" "8")]
6120 (define_insn "*mov_negscc"
6121   [(set (match_operand:SI 0 "s_register_operand" "=r")
6122         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6123                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6124   "TARGET_ARM"
6125   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6126   [(set_attr "conds" "use")
6127    (set_attr "length" "8")]
6130 (define_insn "*mov_notscc"
6131   [(set (match_operand:SI 0 "s_register_operand" "=r")
6132         (not:SI (match_operator:SI 1 "arm_comparison_operator"
6133                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6134   "TARGET_ARM"
6135   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6136   [(set_attr "conds" "use")
6137    (set_attr "length" "8")]
6141 ;; Conditional move insns
6143 (define_expand "movsicc"
6144   [(set (match_operand:SI 0 "s_register_operand" "")
6145         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6146                          (match_operand:SI 2 "arm_not_operand" "")
6147                          (match_operand:SI 3 "arm_not_operand" "")))]
6148   "TARGET_ARM"
6149   "
6150   {
6151     enum rtx_code code = GET_CODE (operands[1]);
6152     rtx ccreg;
6154     if (code == UNEQ || code == LTGT)
6155       FAIL;
6157     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6158     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6159   }"
6162 (define_expand "movsfcc"
6163   [(set (match_operand:SF 0 "s_register_operand" "")
6164         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6165                          (match_operand:SF 2 "s_register_operand" "")
6166                          (match_operand:SF 3 "nonmemory_operand" "")))]
6167   "TARGET_ARM"
6168   "
6169   {
6170     enum rtx_code code = GET_CODE (operands[1]);
6171     rtx ccreg;
6173     if (code == UNEQ || code == LTGT)
6174       FAIL;
6176     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
6177        Otherwise, ensure it is a valid FP add operand */
6178     if ((!TARGET_HARD_FLOAT)
6179         || (!fpu_add_operand (operands[3], SFmode)))
6180       operands[3] = force_reg (SFmode, operands[3]);
6182     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6183     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6184   }"
6187 (define_expand "movdfcc"
6188   [(set (match_operand:DF 0 "s_register_operand" "")
6189         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6190                          (match_operand:DF 2 "s_register_operand" "")
6191                          (match_operand:DF 3 "fpu_add_operand" "")))]
6192   "TARGET_ARM && TARGET_HARD_FLOAT"
6193   "
6194   {
6195     enum rtx_code code = GET_CODE (operands[1]);
6196     rtx ccreg;
6198     if (code == UNEQ || code == LTGT)
6199       FAIL;
6201     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6202     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6203   }"
6206 (define_insn "*movsicc_insn"
6207   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6208         (if_then_else:SI
6209          (match_operator 3 "arm_comparison_operator"
6210           [(match_operand 4 "cc_register" "") (const_int 0)])
6211          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6212          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6213   "TARGET_ARM"
6214   "@
6215    mov%D3\\t%0, %2
6216    mvn%D3\\t%0, #%B2
6217    mov%d3\\t%0, %1
6218    mvn%d3\\t%0, #%B1
6219    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6220    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6221    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6222    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6223   [(set_attr "length" "4,4,4,4,8,8,8,8")
6224    (set_attr "conds" "use")]
6227 (define_insn "*movsfcc_hard_insn"
6228   [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6229         (if_then_else:SF
6230          (match_operator 3 "arm_comparison_operator" 
6231           [(match_operand 4 "cc_register" "") (const_int 0)])
6232          (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6233          (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6234   "TARGET_ARM && TARGET_HARD_FLOAT"
6235   "@
6236    mvf%D3s\\t%0, %2
6237    mnf%D3s\\t%0, #%N2
6238    mvf%d3s\\t%0, %1
6239    mnf%d3s\\t%0, #%N1
6240    mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6241    mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6242    mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6243    mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6244   [(set_attr "length" "4,4,4,4,8,8,8,8")
6245    (set_attr "type" "ffarith")
6246    (set_attr "conds" "use")]
6249 (define_insn "*movsfcc_soft_insn"
6250   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6251         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6252                           [(match_operand 4 "cc_register" "") (const_int 0)])
6253                          (match_operand:SF 1 "s_register_operand" "0,r")
6254                          (match_operand:SF 2 "s_register_operand" "r,0")))]
6255   "TARGET_ARM && TARGET_SOFT_FLOAT"
6256   "@
6257    mov%D3\\t%0, %2
6258    mov%d3\\t%0, %1"
6259   [(set_attr "conds" "use")]
6262 (define_insn "*movdfcc_insn"
6263   [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6264         (if_then_else:DF
6265          (match_operator 3 "arm_comparison_operator"
6266           [(match_operand 4 "cc_register" "") (const_int 0)])
6267          (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6268          (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6269   "TARGET_ARM && TARGET_HARD_FLOAT"
6270   "@
6271    mvf%D3d\\t%0, %2
6272    mnf%D3d\\t%0, #%N2
6273    mvf%d3d\\t%0, %1
6274    mnf%d3d\\t%0, #%N1
6275    mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6276    mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6277    mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6278    mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6279   [(set_attr "length" "4,4,4,4,8,8,8,8")
6280    (set_attr "type" "ffarith")
6281    (set_attr "conds" "use")]
6285 ;; Jump and linkage insns
6287 (define_expand "jump"
6288   [(set (pc)
6289         (label_ref (match_operand 0 "" "")))]
6290   "TARGET_EITHER"
6291   ""
6294 (define_insn "*arm_jump"
6295   [(set (pc)
6296         (label_ref (match_operand 0 "" "")))]
6297   "TARGET_ARM"
6298   "*
6299   {
6300     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6301       {
6302         arm_ccfsm_state += 2;
6303         return \"\";
6304       }
6305     return \"b%?\\t%l0\";
6306   }
6307   "
6308   [(set_attr "predicable" "yes")]
6311 (define_insn "*thumb_jump"
6312   [(set (pc)
6313         (label_ref (match_operand 0 "" "")))]
6314   "TARGET_THUMB"
6315   "*
6316   if (get_attr_length (insn) == 2)
6317     return \"b\\t%l0\";
6318   return \"bl\\t%l0\\t%@ far jump\";
6319   "
6320   [(set (attr "far_jump")
6321         (if_then_else
6322             (eq_attr "length" "4")
6323             (const_string "yes")
6324             (const_string "no")))
6325    (set (attr "length") 
6326         (if_then_else
6327             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6328                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
6329             (const_int 2)
6330             (const_int 4)))]
6333 (define_expand "call"
6334   [(parallel [(call (match_operand 0 "memory_operand" "")
6335                     (match_operand 1 "general_operand" ""))
6336               (use (match_operand 2 "" ""))
6337               (clobber (reg:SI LR_REGNUM))])]
6338   "TARGET_EITHER"
6339   "
6340   {
6341     rtx callee;
6342     
6343     /* In an untyped call, we can get NULL for operand 2.  */
6344     if (operands[2] == NULL_RTX)
6345       operands[2] = const0_rtx;
6346       
6347     /* This is to decide if we should generate indirect calls by loading the
6348        32 bit address of the callee into a register before performing the
6349        branch and link.  operand[2] encodes the long_call/short_call
6350        attribute of the function being called.  This attribute is set whenever
6351        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6352        is used, and the short_call attribute can also be set if function is
6353        declared as static or if it has already been defined in the current
6354        compilation unit.  See arm.c and arm.h for info about this.  The third
6355        parameter to arm_is_longcall_p is used to tell it which pattern
6356        invoked it.  */
6357     callee  = XEXP (operands[0], 0);
6358     
6359     if (GET_CODE (callee) != REG
6360        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6361       XEXP (operands[0], 0) = force_reg (Pmode, callee);
6362   }"
6365 (define_insn "*call_reg"
6366   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6367          (match_operand 1 "" ""))
6368    (use (match_operand 2 "" ""))
6369    (clobber (reg:SI LR_REGNUM))]
6370   "TARGET_ARM"
6371   "*
6372   return output_call (operands);
6373   "
6374   ;; length is worst case, normally it is only two
6375   [(set_attr "length" "12")
6376    (set_attr "type" "call")]
6379 (define_insn "*call_mem"
6380   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6381          (match_operand 1 "" ""))
6382    (use (match_operand 2 "" ""))
6383    (clobber (reg:SI LR_REGNUM))]
6384   "TARGET_ARM"
6385   "*
6386   return output_call_mem (operands);
6387   "
6388   [(set_attr "length" "12")
6389    (set_attr "type" "call")]
6392 (define_insn "*call_indirect"
6393   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6394          (match_operand 1 "" ""))
6395    (use (match_operand 2 "" ""))
6396    (clobber (reg:SI LR_REGNUM))]
6397   "TARGET_THUMB"
6398   "*
6399   {
6400     if (TARGET_CALLER_INTERWORKING)
6401       return \"bl\\t%__interwork_call_via_%0\";
6402     else
6403       return \"bl\\t%__call_via_%0\";
6404   }"
6405   [(set_attr "type" "call")]
6408 (define_insn "*call_value_indirect"
6409   [(set (match_operand 0 "" "=l")
6410         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6411               (match_operand 2 "" "")))
6412    (use (match_operand 3 "" ""))
6413    (clobber (reg:SI LR_REGNUM))]
6414   "TARGET_THUMB"
6415   "*
6416   {
6417     if (TARGET_CALLER_INTERWORKING)
6418       return \"bl\\t%__interwork_call_via_%1\";
6419     else
6420       return \"bl\\t%__call_via_%1\";
6421   }"
6422   [(set_attr "type" "call")]
6425 (define_expand "call_value"
6426   [(parallel [(set (match_operand       0 "" "")
6427                    (call (match_operand 1 "memory_operand" "")
6428                          (match_operand 2 "general_operand" "")))
6429               (use (match_operand 3 "" ""))
6430               (clobber (reg:SI LR_REGNUM))])]
6431   "TARGET_EITHER"
6432   "
6433   {
6434     rtx callee = XEXP (operands[1], 0);
6435     
6436     /* In an untyped call, we can get NULL for operand 2.  */
6437     if (operands[3] == 0)
6438       operands[3] = const0_rtx;
6439       
6440     /* See the comment in define_expand \"call\".  */
6441     if (GET_CODE (callee) != REG
6442         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6443       XEXP (operands[1], 0) = force_reg (Pmode, callee);
6444   }"
6447 (define_insn "*call_value_reg"
6448   [(set (match_operand 0 "" "=r,f,v")
6449         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
6450               (match_operand 2 "" "")))
6451    (use (match_operand 3 "" ""))
6452    (clobber (reg:SI LR_REGNUM))]
6453   "TARGET_ARM"
6454   "*
6455   return output_call (&operands[1]);
6456   "
6457   [(set_attr "length" "12")
6458    (set_attr "type" "call")]
6461 (define_insn "*call_value_mem"
6462   [(set (match_operand 0 "" "=r,f,v")
6463         (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
6464               (match_operand 2 "" "")))
6465    (use (match_operand 3 "" ""))
6466    (clobber (reg:SI LR_REGNUM))]
6467   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6468   "*
6469   return output_call_mem (&operands[1]);
6470   "
6471   [(set_attr "length" "12")
6472    (set_attr "type" "call")]
6475 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6476 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6478 (define_insn "*call_symbol"
6479   [(call (mem:SI (match_operand:SI 0 "" "X"))
6480          (match_operand 1 "" ""))
6481    (use (match_operand 2 "" ""))
6482    (clobber (reg:SI LR_REGNUM))]
6483   "TARGET_ARM
6484    && (GET_CODE (operands[0]) == SYMBOL_REF)
6485    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6486   "*
6487   {
6488     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6489   }"
6490   [(set_attr "type" "call")]
6493 (define_insn "*call_value_symbol"
6494   [(set (match_operand 0 "s_register_operand" "=r,f,v")
6495         (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6496         (match_operand:SI 2 "" "")))
6497    (use (match_operand 3 "" ""))
6498    (clobber (reg:SI LR_REGNUM))]
6499   "TARGET_ARM
6500    && (GET_CODE (operands[1]) == SYMBOL_REF)
6501    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6502   "*
6503   {
6504     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6505   }"
6506   [(set_attr "type" "call")]
6509 (define_insn "*call_insn"
6510   [(call (mem:SI (match_operand:SI 0 "" "X"))
6511          (match_operand:SI 1 "" ""))
6512    (use (match_operand 2 "" ""))
6513    (clobber (reg:SI LR_REGNUM))]
6514   "TARGET_THUMB
6515    && GET_CODE (operands[0]) == SYMBOL_REF
6516    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6517   "bl\\t%a0"
6518   [(set_attr "length" "4")
6519    (set_attr "type" "call")]
6522 (define_insn "*call_value_insn"
6523   [(set (match_operand 0 "register_operand" "=l")
6524         (call (mem:SI (match_operand 1 "" "X"))
6525               (match_operand 2 "" "")))
6526    (use (match_operand 3 "" ""))
6527    (clobber (reg:SI LR_REGNUM))]
6528   "TARGET_THUMB
6529    && GET_CODE (operands[1]) == SYMBOL_REF
6530    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6531   "bl\\t%a1"
6532   [(set_attr "length" "4")
6533    (set_attr "type" "call")]
6536 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6537 (define_expand "sibcall"
6538   [(parallel [(call (match_operand 0 "memory_operand" "")
6539                     (match_operand 1 "general_operand" ""))
6540               (return)
6541               (use (match_operand 2 "" ""))])]
6542   "TARGET_ARM"
6543   "
6544   {
6545     if (operands[2] == NULL_RTX)
6546       operands[2] = const0_rtx;
6547   }"
6550 (define_expand "sibcall_value"
6551   [(parallel [(set (match_operand 0 "register_operand" "")
6552                    (call (match_operand 1 "memory_operand" "")
6553                          (match_operand 2 "general_operand" "")))
6554               (return)
6555               (use (match_operand 3 "" ""))])]
6556   "TARGET_ARM"
6557   "
6558   {
6559     if (operands[3] == NULL_RTX)
6560       operands[3] = const0_rtx;
6561   }"
6564 (define_insn "*sibcall_insn"
6565  [(call (mem:SI (match_operand:SI 0 "" "X"))
6566         (match_operand 1 "" ""))
6567   (return)
6568   (use (match_operand 2 "" ""))]
6569   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6570   "*
6571   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6572   "
6573   [(set_attr "type" "call")]
6576 (define_insn "*sibcall_value_insn"
6577  [(set (match_operand 0 "s_register_operand" "=r,f,v")
6578        (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6579              (match_operand 2 "" "")))
6580   (return)
6581   (use (match_operand 3 "" ""))]
6582   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6583   "*
6584   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6585   "
6586   [(set_attr "type" "call")]
6589 ;; Often the return insn will be the same as loading from memory, so set attr
6590 (define_insn "return"
6591   [(return)]
6592   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6593   "*
6594   {
6595     if (arm_ccfsm_state == 2)
6596       {
6597         arm_ccfsm_state += 2;
6598         return \"\";
6599       }
6600     return output_return_instruction (const_true_rtx, TRUE, FALSE);
6601   }"
6602   [(set_attr "type" "load")
6603    (set_attr "predicable" "yes")]
6606 (define_insn "*cond_return"
6607   [(set (pc)
6608         (if_then_else (match_operator 0 "arm_comparison_operator"
6609                        [(match_operand 1 "cc_register" "") (const_int 0)])
6610                       (return)
6611                       (pc)))]
6612   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6613   "*
6614   {
6615     if (arm_ccfsm_state == 2)
6616       {
6617         arm_ccfsm_state += 2;
6618         return \"\";
6619       }
6620     return output_return_instruction (operands[0], TRUE, FALSE);
6621   }"
6622   [(set_attr "conds" "use")
6623    (set_attr "type" "load")]
6626 (define_insn "*cond_return_inverted"
6627   [(set (pc)
6628         (if_then_else (match_operator 0 "arm_comparison_operator"
6629                        [(match_operand 1 "cc_register" "") (const_int 0)])
6630                       (pc)
6631                       (return)))]
6632   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6633   "*
6634   {
6635     if (arm_ccfsm_state == 2)
6636       {
6637         arm_ccfsm_state += 2;
6638         return \"\";
6639       }
6640     return output_return_instruction (operands[0], TRUE, TRUE);
6641   }"
6642   [(set_attr "conds" "use")
6643    (set_attr "type" "load")]
6646 ;; Generate a sequence of instructions to determine if the processor is
6647 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6648 ;; mask.
6650 (define_expand "return_addr_mask"
6651   [(set (match_dup 1)
6652       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6653                        (const_int 0)))
6654    (set (match_operand:SI 0 "s_register_operand" "")
6655       (if_then_else:SI (eq (match_dup 1) (const_int 0))
6656                        (const_int -1)
6657                        (const_int 67108860)))] ; 0x03fffffc
6658   "TARGET_ARM"
6659   "
6660   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6661   ")
6663 (define_insn "*check_arch2"
6664   [(set (match_operand:CC_NOOV 0 "cc_register" "")
6665       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6666                        (const_int 0)))]
6667   "TARGET_ARM"
6668   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6669   [(set_attr "length" "8")
6670    (set_attr "conds" "set")]
6673 ;; Call subroutine returning any type.
6675 (define_expand "untyped_call"
6676   [(parallel [(call (match_operand 0 "" "")
6677                     (const_int 0))
6678               (match_operand 1 "" "")
6679               (match_operand 2 "" "")])]
6680   "TARGET_ARM"
6681   "
6682   {
6683     int i;
6685     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6687     for (i = 0; i < XVECLEN (operands[2], 0); i++)
6688       {
6689         rtx set = XVECEXP (operands[2], 0, i);
6691         emit_move_insn (SET_DEST (set), SET_SRC (set));
6692       }
6694     /* The optimizer does not know that the call sets the function value
6695        registers we stored in the result block.  We avoid problems by
6696        claiming that all hard registers are used and clobbered at this
6697        point.  */
6698     emit_insn (gen_blockage ());
6700     DONE;
6701   }"
6704 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6705 ;; all of memory.  This blocks insns from being moved across this point.
6707 (define_insn "blockage"
6708   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6709   "TARGET_EITHER"
6710   ""
6711   [(set_attr "length" "0")
6712    (set_attr "type" "block")]
6715 (define_expand "casesi"
6716   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6717    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
6718    (match_operand:SI 2 "const_int_operand" "")  ; total range
6719    (match_operand:SI 3 "" "")                   ; table label
6720    (match_operand:SI 4 "" "")]                  ; Out of range label
6721   "TARGET_ARM"
6722   "
6723   {
6724     rtx reg;
6725     if (operands[1] != const0_rtx)
6726       {
6727         reg = gen_reg_rtx (SImode);
6729         emit_insn (gen_addsi3 (reg, operands[0],
6730                                GEN_INT (-INTVAL (operands[1]))));
6731         operands[0] = reg;
6732       }
6734     if (!const_ok_for_arm (INTVAL (operands[2])))
6735       operands[2] = force_reg (SImode, operands[2]);
6737     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6738                                          operands[4]));
6739     DONE;
6740   }"
6743 ;; The USE in this pattern is needed to tell flow analysis that this is
6744 ;; a CASESI insn.  It has no other purpose.
6745 (define_insn "casesi_internal"
6746   [(parallel [(set (pc)
6747                (if_then_else
6748                 (leu (match_operand:SI 0 "s_register_operand" "r")
6749                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
6750                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6751                                  (label_ref (match_operand 2 "" ""))))
6752                 (label_ref (match_operand 3 "" ""))))
6753               (clobber (reg:CC CC_REGNUM))
6754               (use (label_ref (match_dup 2)))])]
6755   "TARGET_ARM"
6756   "*
6757     if (flag_pic)
6758       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6759     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6760   "
6761   [(set_attr "conds" "clob")
6762    (set_attr "length" "12")]
6765 (define_expand "indirect_jump"
6766   [(set (pc)
6767         (match_operand:SI 0 "s_register_operand" ""))]
6768   "TARGET_EITHER"
6769   ""
6772 (define_insn "*arm_indirect_jump"
6773   [(set (pc)
6774         (match_operand:SI 0 "s_register_operand" "r"))]
6775   "TARGET_ARM"
6776   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6777   [(set_attr "predicable" "yes")]
6780 ;; Although not supported by the define_expand above,
6781 ;; cse/combine may generate this form.
6782 (define_insn "*load_indirect_jump"
6783   [(set (pc)
6784         (match_operand:SI 0 "memory_operand" "m"))]
6785   "TARGET_ARM"
6786   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6787   [(set_attr "type" "load")
6788    (set_attr "pool_range" "4096")
6789    (set_attr "neg_pool_range" "4084")
6790    (set_attr "predicable" "yes")]
6793 (define_insn "*thumb_indirect_jump"
6794   [(set (pc)
6795         (match_operand:SI 0 "register_operand" "l*r"))]
6796   "TARGET_THUMB"
6797   "mov\\tpc, %0"
6798   [(set_attr "conds" "clob")
6799    (set_attr "length" "2")]
6803 ;; Misc insns
6805 (define_insn "nop"
6806   [(const_int 0)]
6807   "TARGET_EITHER"
6808   "*
6809   if (TARGET_ARM)
6810     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6811   return  \"mov\\tr8, r8\";
6812   "
6813   [(set (attr "length")
6814         (if_then_else (eq_attr "is_thumb" "yes")
6815                       (const_int 2)
6816                       (const_int 4)))]
6820 ;; Patterns to allow combination of arithmetic, cond code and shifts
6822 (define_insn "*arith_shiftsi"
6823   [(set (match_operand:SI 0 "s_register_operand" "=r")
6824         (match_operator:SI 1 "shiftable_operator"
6825           [(match_operator:SI 3 "shift_operator"
6826              [(match_operand:SI 4 "s_register_operand" "r")
6827               (match_operand:SI 5 "reg_or_int_operand" "rI")])
6828            (match_operand:SI 2 "s_register_operand" "r")]))]
6829   "TARGET_ARM"
6830   "%i1%?\\t%0, %2, %4%S3"
6831   [(set_attr "predicable" "yes")
6832    (set_attr "shift" "4")
6833    ]
6836 (define_insn "*arith_shiftsi_compare0"
6837   [(set (reg:CC_NOOV CC_REGNUM)
6838         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6839                           [(match_operator:SI 3 "shift_operator"
6840                             [(match_operand:SI 4 "s_register_operand" "r")
6841                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6842                            (match_operand:SI 2 "s_register_operand" "r")])
6843                          (const_int 0)))
6844    (set (match_operand:SI 0 "s_register_operand" "=r")
6845         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6846                          (match_dup 2)]))]
6847   "TARGET_ARM"
6848   "%i1%?s\\t%0, %2, %4%S3"
6849   [(set_attr "conds" "set")
6850    (set_attr "shift" "4")
6851    ]
6854 (define_insn "*arith_shiftsi_compare0_scratch"
6855   [(set (reg:CC_NOOV CC_REGNUM)
6856         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6857                           [(match_operator:SI 3 "shift_operator"
6858                             [(match_operand:SI 4 "s_register_operand" "r")
6859                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6860                            (match_operand:SI 2 "s_register_operand" "r")])
6861                          (const_int 0)))
6862    (clobber (match_scratch:SI 0 "=r"))]
6863   "TARGET_ARM"
6864   "%i1%?s\\t%0, %2, %4%S3"
6865   [(set_attr "conds" "set")
6866    (set_attr "shift" "4")
6867    ]
6870 (define_insn "*sub_shiftsi"
6871   [(set (match_operand:SI 0 "s_register_operand" "=r")
6872         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6873                   (match_operator:SI 2 "shift_operator"
6874                    [(match_operand:SI 3 "s_register_operand" "r")
6875                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6876   "TARGET_ARM"
6877   "sub%?\\t%0, %1, %3%S2"
6878   [(set_attr "predicable" "yes")
6879    (set_attr "shift" "3")
6880    ]
6883 (define_insn "*sub_shiftsi_compare0"
6884   [(set (reg:CC_NOOV CC_REGNUM)
6885         (compare:CC_NOOV
6886          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6887                    (match_operator:SI 2 "shift_operator"
6888                     [(match_operand:SI 3 "s_register_operand" "r")
6889                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6890          (const_int 0)))
6891    (set (match_operand:SI 0 "s_register_operand" "=r")
6892         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6893                                                  (match_dup 4)])))]
6894   "TARGET_ARM"
6895   "sub%?s\\t%0, %1, %3%S2"
6896   [(set_attr "conds" "set")
6897    (set_attr "shift" "3") 
6898    ]
6901 (define_insn "*sub_shiftsi_compare0_scratch"
6902   [(set (reg:CC_NOOV CC_REGNUM)
6903         (compare:CC_NOOV
6904          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6905                    (match_operator:SI 2 "shift_operator"
6906                     [(match_operand:SI 3 "s_register_operand" "r")
6907                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6908          (const_int 0)))
6909    (clobber (match_scratch:SI 0 "=r"))]
6910   "TARGET_ARM"
6911   "sub%?s\\t%0, %1, %3%S2"
6912   [(set_attr "conds" "set")
6913    (set_attr "shift" "3") 
6914    ]
6919 (define_insn "*and_scc"
6920   [(set (match_operand:SI 0 "s_register_operand" "=r")
6921         (and:SI (match_operator:SI 1 "arm_comparison_operator"
6922                  [(match_operand 3 "cc_register" "") (const_int 0)])
6923                 (match_operand:SI 2 "s_register_operand" "r")))]
6924   "TARGET_ARM"
6925   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6926   [(set_attr "conds" "use")
6927    (set_attr "length" "8")]
6930 (define_insn "*ior_scc"
6931   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6932         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6933                  [(match_operand 3 "cc_register" "") (const_int 0)])
6934                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6935   "TARGET_ARM"
6936   "@
6937    orr%d2\\t%0, %1, #1
6938    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6939   [(set_attr "conds" "use")
6940    (set_attr "length" "4,8")]
6943 (define_insn "*compare_scc"
6944   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6945         (match_operator:SI 1 "arm_comparison_operator"
6946          [(match_operand:SI 2 "s_register_operand" "r,r")
6947           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6948    (clobber (reg:CC CC_REGNUM))]
6949   "TARGET_ARM"
6950   "*
6951     if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
6952       return \"mov\\t%0, %2, lsr #31\";
6954     if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
6955       return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6957     if (GET_CODE (operands[1]) == NE)
6958       {
6959         if (which_alternative == 1)
6960           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
6961         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
6962       }
6963     if (which_alternative == 1)
6964       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6965     else
6966       output_asm_insn (\"cmp\\t%2, %3\", operands);
6967     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
6968   "
6969   [(set_attr "conds" "clob")
6970    (set_attr "length" "12")]
6973 (define_insn "*cond_move"
6974   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6975         (if_then_else:SI (match_operator 3 "equality_operator"
6976                           [(match_operator 4 "arm_comparison_operator"
6977                             [(match_operand 5 "cc_register" "") (const_int 0)])
6978                            (const_int 0)])
6979                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6980                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
6981   "TARGET_ARM"
6982   "*
6983     if (GET_CODE (operands[3]) == NE)
6984       {
6985         if (which_alternative != 1)
6986           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
6987         if (which_alternative != 0)
6988           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6989         return \"\";
6990       }
6991     if (which_alternative != 0)
6992       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6993     if (which_alternative != 1)
6994       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
6995     return \"\";
6996   "
6997   [(set_attr "conds" "use")
6998    (set_attr "length" "4,4,8")]
7001 (define_insn "*cond_arith"
7002   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7003         (match_operator:SI 5 "shiftable_operator" 
7004          [(match_operator:SI 4 "arm_comparison_operator"
7005            [(match_operand:SI 2 "s_register_operand" "r,r")
7006             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7007           (match_operand:SI 1 "s_register_operand" "0,?r")]))
7008    (clobber (reg:CC CC_REGNUM))]
7009   "TARGET_ARM"
7010   "*
7011     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7012       return \"%i5\\t%0, %1, %2, lsr #31\";
7014     output_asm_insn (\"cmp\\t%2, %3\", operands);
7015     if (GET_CODE (operands[5]) == AND)
7016       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7017     else if (GET_CODE (operands[5]) == MINUS)
7018       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7019     else if (which_alternative != 0)
7020       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7021     return \"%i5%d4\\t%0, %1, #1\";
7022   "
7023   [(set_attr "conds" "clob")
7024    (set_attr "length" "12")]
7027 (define_insn "*cond_sub"
7028   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7029         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7030                   (match_operator:SI 4 "arm_comparison_operator"
7031                    [(match_operand:SI 2 "s_register_operand" "r,r")
7032                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7033    (clobber (reg:CC CC_REGNUM))]
7034   "TARGET_ARM"
7035   "*
7036     output_asm_insn (\"cmp\\t%2, %3\", operands);
7037     if (which_alternative != 0)
7038       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7039     return \"sub%d4\\t%0, %1, #1\";
7040   "
7041   [(set_attr "conds" "clob")
7042    (set_attr "length" "8,12")]
7045 (define_insn "*cmp_ite0"
7046   [(set (match_operand 6 "dominant_cc_register" "")
7047         (compare
7048          (if_then_else:SI
7049           (match_operator 4 "arm_comparison_operator"
7050            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7051             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7052           (match_operator:SI 5 "arm_comparison_operator"
7053            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7054             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7055           (const_int 0))
7056          (const_int 0)))]
7057   "TARGET_ARM"
7058   "*
7059   {
7060     static const char * const opcodes[4][2] =
7061     {
7062       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7063        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7064       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7065        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7066       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7067        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7068       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7069        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7070     };
7071     int swap =
7072       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7074     return opcodes[which_alternative][swap];
7075   }"
7076   [(set_attr "conds" "set")
7077    (set_attr "length" "8")]
7080 (define_insn "*cmp_ite1"
7081   [(set (match_operand 6 "dominant_cc_register" "")
7082         (compare
7083          (if_then_else:SI
7084           (match_operator 4 "arm_comparison_operator"
7085            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7086             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7087           (match_operator:SI 5 "arm_comparison_operator"
7088            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7089             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7090           (const_int 1))
7091          (const_int 0)))]
7092   "TARGET_ARM"
7093   "*
7094   {
7095     static const char * const opcodes[4][2] =
7096     {
7097       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7098        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7099       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7100        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7101       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7102        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7103       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7104        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7105     };
7106     int swap =
7107       comparison_dominates_p (GET_CODE (operands[5]),
7108                               reverse_condition (GET_CODE (operands[4])));
7110     return opcodes[which_alternative][swap];
7111   }"
7112   [(set_attr "conds" "set")
7113    (set_attr "length" "8")]
7116 (define_insn "*cmp_and"
7117   [(set (match_operand 6 "dominant_cc_register" "")
7118         (compare
7119          (and:SI
7120           (match_operator 4 "arm_comparison_operator"
7121            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7122             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7123           (match_operator:SI 5 "arm_comparison_operator"
7124            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7125             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7126          (const_int 0)))]
7127   "TARGET_ARM"
7128   "*
7129   {
7130     static const char *const opcodes[4][2] =
7131     {
7132       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7133        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7134       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7135        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7136       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7137        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7138       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7139        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7140     };
7141     int swap =
7142       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7144     return opcodes[which_alternative][swap];
7145   }"
7146   [(set_attr "conds" "set")
7147    (set_attr "predicable" "no")
7148    (set_attr "length" "8")]
7151 (define_insn "*cmp_ior"
7152   [(set (match_operand 6 "dominant_cc_register" "")
7153         (compare
7154          (ior:SI
7155           (match_operator 4 "arm_comparison_operator"
7156            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7157             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7158           (match_operator:SI 5 "arm_comparison_operator"
7159            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7160             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7161          (const_int 0)))]
7162   "TARGET_ARM"
7163   "*
7165   static const char *const opcodes[4][2] =
7166   {
7167     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7168      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7169     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7170      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7171     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7172      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7173     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7174      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7175   };
7176   int swap =
7177     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7179   return opcodes[which_alternative][swap];
7182   [(set_attr "conds" "set")
7183    (set_attr "length" "8")]
7186 (define_insn "*negscc"
7187   [(set (match_operand:SI 0 "s_register_operand" "=r")
7188         (neg:SI (match_operator 3 "arm_comparison_operator"
7189                  [(match_operand:SI 1 "s_register_operand" "r")
7190                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7191    (clobber (reg:CC CC_REGNUM))]
7192   "TARGET_ARM"
7193   "*
7194   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7195     return \"mov\\t%0, %1, asr #31\";
7197   if (GET_CODE (operands[3]) == NE)
7198     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7200   if (GET_CODE (operands[3]) == GT)
7201     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7203   output_asm_insn (\"cmp\\t%1, %2\", operands);
7204   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7205   return \"mvn%d3\\t%0, #0\";
7206   "
7207   [(set_attr "conds" "clob")
7208    (set_attr "length" "12")]
7211 (define_insn "movcond"
7212   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7213         (if_then_else:SI
7214          (match_operator 5 "arm_comparison_operator"
7215           [(match_operand:SI 3 "s_register_operand" "r,r,r")
7216            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7217          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7218          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7219    (clobber (reg:CC CC_REGNUM))]
7220   "TARGET_ARM"
7221   "*
7222   if (GET_CODE (operands[5]) == LT
7223       && (operands[4] == const0_rtx))
7224     {
7225       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7226         {
7227           if (operands[2] == const0_rtx)
7228             return \"and\\t%0, %1, %3, asr #31\";
7229           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7230         }
7231       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7232         {
7233           if (operands[1] == const0_rtx)
7234             return \"bic\\t%0, %2, %3, asr #31\";
7235           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7236         }
7237       /* The only case that falls through to here is when both ops 1 & 2
7238          are constants */
7239     }
7241   if (GET_CODE (operands[5]) == GE
7242       && (operands[4] == const0_rtx))
7243     {
7244       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7245         {
7246           if (operands[2] == const0_rtx)
7247             return \"bic\\t%0, %1, %3, asr #31\";
7248           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7249         }
7250       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7251         {
7252           if (operands[1] == const0_rtx)
7253             return \"and\\t%0, %2, %3, asr #31\";
7254           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7255         }
7256       /* The only case that falls through to here is when both ops 1 & 2
7257          are constants */
7258     }
7259   if (GET_CODE (operands[4]) == CONST_INT
7260       && !const_ok_for_arm (INTVAL (operands[4])))
7261     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7262   else
7263     output_asm_insn (\"cmp\\t%3, %4\", operands);
7264   if (which_alternative != 0)
7265     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7266   if (which_alternative != 1)
7267     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7268   return \"\";
7269   "
7270   [(set_attr "conds" "clob")
7271    (set_attr "length" "8,8,12")]
7274 (define_insn "*ifcompare_plus_move"
7275   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7276         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7277                           [(match_operand:SI 4 "s_register_operand" "r,r")
7278                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7279                          (plus:SI
7280                           (match_operand:SI 2 "s_register_operand" "r,r")
7281                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7282                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7283    (clobber (reg:CC CC_REGNUM))]
7284   "TARGET_ARM"
7285   "#"
7286   [(set_attr "conds" "clob")
7287    (set_attr "length" "8,12")]
7290 (define_insn "*if_plus_move"
7291   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7292         (if_then_else:SI
7293          (match_operator 4 "arm_comparison_operator"
7294           [(match_operand 5 "cc_register" "") (const_int 0)])
7295          (plus:SI
7296           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7297           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7298          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7299   "TARGET_ARM"
7300   "@
7301    add%d4\\t%0, %2, %3
7302    sub%d4\\t%0, %2, #%n3
7303    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7304    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7305   [(set_attr "conds" "use")
7306    (set_attr "length" "4,4,8,8")
7307    (set_attr "type" "*,*,*,*")]
7310 (define_insn "*ifcompare_move_plus"
7311   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7312         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7313                           [(match_operand:SI 4 "s_register_operand" "r,r")
7314                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7315                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7316                          (plus:SI
7317                           (match_operand:SI 2 "s_register_operand" "r,r")
7318                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7319    (clobber (reg:CC CC_REGNUM))]
7320   "TARGET_ARM"
7321   "#"
7322   [(set_attr "conds" "clob")
7323    (set_attr "length" "8,12")]
7326 (define_insn "*if_move_plus"
7327   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7328         (if_then_else:SI
7329          (match_operator 4 "arm_comparison_operator"
7330           [(match_operand 5 "cc_register" "") (const_int 0)])
7331          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7332          (plus:SI
7333           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7334           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7335   "TARGET_ARM"
7336   "@
7337    add%D4\\t%0, %2, %3
7338    sub%D4\\t%0, %2, #%n3
7339    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7340    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7341   [(set_attr "conds" "use")
7342    (set_attr "length" "4,4,8,8")
7343    (set_attr "type" "*,*,*,*")]
7346 (define_insn "*ifcompare_arith_arith"
7347   [(set (match_operand:SI 0 "s_register_operand" "=r")
7348         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7349                           [(match_operand:SI 5 "s_register_operand" "r")
7350                            (match_operand:SI 6 "arm_add_operand" "rIL")])
7351                          (match_operator:SI 8 "shiftable_operator"
7352                           [(match_operand:SI 1 "s_register_operand" "r")
7353                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7354                          (match_operator:SI 7 "shiftable_operator"
7355                           [(match_operand:SI 3 "s_register_operand" "r")
7356                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7357    (clobber (reg:CC CC_REGNUM))]
7358   "TARGET_ARM"
7359   "#"
7360   [(set_attr "conds" "clob")
7361    (set_attr "length" "12")]
7364 (define_insn "*if_arith_arith"
7365   [(set (match_operand:SI 0 "s_register_operand" "=r")
7366         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7367                           [(match_operand 8 "cc_register" "") (const_int 0)])
7368                          (match_operator:SI 6 "shiftable_operator"
7369                           [(match_operand:SI 1 "s_register_operand" "r")
7370                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7371                          (match_operator:SI 7 "shiftable_operator"
7372                           [(match_operand:SI 3 "s_register_operand" "r")
7373                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7374   "TARGET_ARM"
7375   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7376   [(set_attr "conds" "use")
7377    (set_attr "length" "8")]
7380 (define_insn "*ifcompare_arith_move"
7381   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7382         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7383                           [(match_operand:SI 2 "s_register_operand" "r,r")
7384                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7385                          (match_operator:SI 7 "shiftable_operator"
7386                           [(match_operand:SI 4 "s_register_operand" "r,r")
7387                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7388                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7389    (clobber (reg:CC CC_REGNUM))]
7390   "TARGET_ARM"
7391   "*
7392   /* If we have an operation where (op x 0) is the identity operation and
7393      the conditional operator is LT or GE and we are comparing against zero and
7394      everything is in registers then we can do this in two instructions */
7395   if (operands[3] == const0_rtx
7396       && GET_CODE (operands[7]) != AND
7397       && GET_CODE (operands[5]) == REG
7398       && GET_CODE (operands[1]) == REG 
7399       && REGNO (operands[1]) == REGNO (operands[4])
7400       && REGNO (operands[4]) != REGNO (operands[0]))
7401     {
7402       if (GET_CODE (operands[6]) == LT)
7403         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7404       else if (GET_CODE (operands[6]) == GE)
7405         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7406     }
7407   if (GET_CODE (operands[3]) == CONST_INT
7408       && !const_ok_for_arm (INTVAL (operands[3])))
7409     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7410   else
7411     output_asm_insn (\"cmp\\t%2, %3\", operands);
7412   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7413   if (which_alternative != 0)
7414     return \"mov%D6\\t%0, %1\";
7415   return \"\";
7416   "
7417   [(set_attr "conds" "clob")
7418    (set_attr "length" "8,12")]
7421 (define_insn "*if_arith_move"
7422   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7423         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7424                           [(match_operand 6 "cc_register" "") (const_int 0)])
7425                          (match_operator:SI 5 "shiftable_operator"
7426                           [(match_operand:SI 2 "s_register_operand" "r,r")
7427                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7428                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7429   "TARGET_ARM"
7430   "@
7431    %I5%d4\\t%0, %2, %3
7432    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7433   [(set_attr "conds" "use")
7434    (set_attr "length" "4,8")
7435    (set_attr "type" "*,*")]
7438 (define_insn "*ifcompare_move_arith"
7439   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7440         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7441                           [(match_operand:SI 4 "s_register_operand" "r,r")
7442                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7443                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7444                          (match_operator:SI 7 "shiftable_operator"
7445                           [(match_operand:SI 2 "s_register_operand" "r,r")
7446                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7447    (clobber (reg:CC CC_REGNUM))]
7448   "TARGET_ARM"
7449   "*
7450   /* If we have an operation where (op x 0) is the identity operation and
7451      the conditional operator is LT or GE and we are comparing against zero and
7452      everything is in registers then we can do this in two instructions */
7453   if (operands[5] == const0_rtx
7454       && GET_CODE (operands[7]) != AND
7455       && GET_CODE (operands[3]) == REG
7456       && GET_CODE (operands[1]) == REG 
7457       && REGNO (operands[1]) == REGNO (operands[2])
7458       && REGNO (operands[2]) != REGNO (operands[0]))
7459     {
7460       if (GET_CODE (operands[6]) == GE)
7461         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7462       else if (GET_CODE (operands[6]) == LT)
7463         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7464     }
7466   if (GET_CODE (operands[5]) == CONST_INT
7467       && !const_ok_for_arm (INTVAL (operands[5])))
7468     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7469   else
7470     output_asm_insn (\"cmp\\t%4, %5\", operands);
7472   if (which_alternative != 0)
7473     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7474   return \"%I7%D6\\t%0, %2, %3\";
7475   "
7476   [(set_attr "conds" "clob")
7477    (set_attr "length" "8,12")]
7480 (define_insn "*if_move_arith"
7481   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7482         (if_then_else:SI
7483          (match_operator 4 "arm_comparison_operator"
7484           [(match_operand 6 "cc_register" "") (const_int 0)])
7485          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7486          (match_operator:SI 5 "shiftable_operator"
7487           [(match_operand:SI 2 "s_register_operand" "r,r")
7488            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7489   "TARGET_ARM"
7490   "@
7491    %I5%D4\\t%0, %2, %3
7492    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7493   [(set_attr "conds" "use")
7494    (set_attr "length" "4,8")
7495    (set_attr "type" "*,*")]
7498 (define_insn "*ifcompare_move_not"
7499   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7500         (if_then_else:SI
7501          (match_operator 5 "arm_comparison_operator"
7502           [(match_operand:SI 3 "s_register_operand" "r,r")
7503            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7504          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7505          (not:SI
7506           (match_operand:SI 2 "s_register_operand" "r,r"))))
7507    (clobber (reg:CC CC_REGNUM))]
7508   "TARGET_ARM"
7509   "#"
7510   [(set_attr "conds" "clob")
7511    (set_attr "length" "8,12")]
7514 (define_insn "*if_move_not"
7515   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7516         (if_then_else:SI
7517          (match_operator 4 "arm_comparison_operator"
7518           [(match_operand 3 "cc_register" "") (const_int 0)])
7519          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7520          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7521   "TARGET_ARM"
7522   "@
7523    mvn%D4\\t%0, %2
7524    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7525    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7526   [(set_attr "conds" "use")
7527    (set_attr "length" "4,8,8")]
7530 (define_insn "*ifcompare_not_move"
7531   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7532         (if_then_else:SI 
7533          (match_operator 5 "arm_comparison_operator"
7534           [(match_operand:SI 3 "s_register_operand" "r,r")
7535            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7536          (not:SI
7537           (match_operand:SI 2 "s_register_operand" "r,r"))
7538          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7539    (clobber (reg:CC CC_REGNUM))]
7540   "TARGET_ARM"
7541   "#"
7542   [(set_attr "conds" "clob")
7543    (set_attr "length" "8,12")]
7546 (define_insn "*if_not_move"
7547   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7548         (if_then_else:SI
7549          (match_operator 4 "arm_comparison_operator"
7550           [(match_operand 3 "cc_register" "") (const_int 0)])
7551          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7552          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7553   "TARGET_ARM"
7554   "@
7555    mvn%d4\\t%0, %2
7556    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7557    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7558   [(set_attr "conds" "use")
7559    (set_attr "length" "4,8,8")]
7562 (define_insn "*ifcompare_shift_move"
7563   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7564         (if_then_else:SI
7565          (match_operator 6 "arm_comparison_operator"
7566           [(match_operand:SI 4 "s_register_operand" "r,r")
7567            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7568          (match_operator:SI 7 "shift_operator"
7569           [(match_operand:SI 2 "s_register_operand" "r,r")
7570            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7571          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7572    (clobber (reg:CC CC_REGNUM))]
7573   "TARGET_ARM"
7574   "#"
7575   [(set_attr "conds" "clob")
7576    (set_attr "length" "8,12")]
7579 (define_insn "*if_shift_move"
7580   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7581         (if_then_else:SI
7582          (match_operator 5 "arm_comparison_operator"
7583           [(match_operand 6 "cc_register" "") (const_int 0)])
7584          (match_operator:SI 4 "shift_operator"
7585           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7586            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7587          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7588   "TARGET_ARM"
7589   "@
7590    mov%d5\\t%0, %2%S4
7591    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7592    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7593   [(set_attr "conds" "use")
7594    (set_attr "shift" "2")
7595    (set_attr "length" "4,8,8")]
7598 (define_insn "*ifcompare_move_shift"
7599   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7600         (if_then_else:SI
7601          (match_operator 6 "arm_comparison_operator"
7602           [(match_operand:SI 4 "s_register_operand" "r,r")
7603            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7604          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7605          (match_operator:SI 7 "shift_operator"
7606           [(match_operand:SI 2 "s_register_operand" "r,r")
7607            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7608    (clobber (reg:CC CC_REGNUM))]
7609   "TARGET_ARM"
7610   "#"
7611   [(set_attr "conds" "clob")
7612    (set_attr "length" "8,12")]
7615 (define_insn "*if_move_shift"
7616   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7617         (if_then_else:SI
7618          (match_operator 5 "arm_comparison_operator"
7619           [(match_operand 6 "cc_register" "") (const_int 0)])
7620          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7621          (match_operator:SI 4 "shift_operator"
7622           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7623            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7624   "TARGET_ARM"
7625   "@
7626    mov%D5\\t%0, %2%S4
7627    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7628    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7629   [(set_attr "conds" "use")
7630    (set_attr "shift" "2")
7631    (set_attr "length" "4,8,8")]
7634 (define_insn "*ifcompare_shift_shift"
7635   [(set (match_operand:SI 0 "s_register_operand" "=r")
7636         (if_then_else:SI
7637          (match_operator 7 "arm_comparison_operator"
7638           [(match_operand:SI 5 "s_register_operand" "r")
7639            (match_operand:SI 6 "arm_add_operand" "rIL")])
7640          (match_operator:SI 8 "shift_operator"
7641           [(match_operand:SI 1 "s_register_operand" "r")
7642            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7643          (match_operator:SI 9 "shift_operator"
7644           [(match_operand:SI 3 "s_register_operand" "r")
7645            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7646    (clobber (reg:CC CC_REGNUM))]
7647   "TARGET_ARM"
7648   "#"
7649   [(set_attr "conds" "clob")
7650    (set_attr "length" "12")]
7653 (define_insn "*if_shift_shift"
7654   [(set (match_operand:SI 0 "s_register_operand" "=r")
7655         (if_then_else:SI
7656          (match_operator 5 "arm_comparison_operator"
7657           [(match_operand 8 "cc_register" "") (const_int 0)])
7658          (match_operator:SI 6 "shift_operator"
7659           [(match_operand:SI 1 "s_register_operand" "r")
7660            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7661          (match_operator:SI 7 "shift_operator"
7662           [(match_operand:SI 3 "s_register_operand" "r")
7663            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7664   "TARGET_ARM"
7665   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7666   [(set_attr "conds" "use")
7667    (set_attr "shift" "1")
7668    (set_attr "length" "8")]
7671 (define_insn "*ifcompare_not_arith"
7672   [(set (match_operand:SI 0 "s_register_operand" "=r")
7673         (if_then_else:SI
7674          (match_operator 6 "arm_comparison_operator"
7675           [(match_operand:SI 4 "s_register_operand" "r")
7676            (match_operand:SI 5 "arm_add_operand" "rIL")])
7677          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7678          (match_operator:SI 7 "shiftable_operator"
7679           [(match_operand:SI 2 "s_register_operand" "r")
7680            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7681    (clobber (reg:CC CC_REGNUM))]
7682   "TARGET_ARM"
7683   "#"
7684   [(set_attr "conds" "clob")
7685    (set_attr "length" "12")]
7688 (define_insn "*if_not_arith"
7689   [(set (match_operand:SI 0 "s_register_operand" "=r")
7690         (if_then_else:SI
7691          (match_operator 5 "arm_comparison_operator"
7692           [(match_operand 4 "cc_register" "") (const_int 0)])
7693          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7694          (match_operator:SI 6 "shiftable_operator"
7695           [(match_operand:SI 2 "s_register_operand" "r")
7696            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7697   "TARGET_ARM"
7698   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7699   [(set_attr "conds" "use")
7700    (set_attr "length" "8")]
7703 (define_insn "*ifcompare_arith_not"
7704   [(set (match_operand:SI 0 "s_register_operand" "=r")
7705         (if_then_else:SI
7706          (match_operator 6 "arm_comparison_operator"
7707           [(match_operand:SI 4 "s_register_operand" "r")
7708            (match_operand:SI 5 "arm_add_operand" "rIL")])
7709          (match_operator:SI 7 "shiftable_operator"
7710           [(match_operand:SI 2 "s_register_operand" "r")
7711            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7712          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7713    (clobber (reg:CC CC_REGNUM))]
7714   "TARGET_ARM"
7715   "#"
7716   [(set_attr "conds" "clob")
7717    (set_attr "length" "12")]
7720 (define_insn "*if_arith_not"
7721   [(set (match_operand:SI 0 "s_register_operand" "=r")
7722         (if_then_else:SI
7723          (match_operator 5 "arm_comparison_operator"
7724           [(match_operand 4 "cc_register" "") (const_int 0)])
7725          (match_operator:SI 6 "shiftable_operator"
7726           [(match_operand:SI 2 "s_register_operand" "r")
7727            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7728          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7729   "TARGET_ARM"
7730   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7731   [(set_attr "conds" "use")
7732    (set_attr "length" "8")]
7735 (define_insn "*ifcompare_neg_move"
7736   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7737         (if_then_else:SI
7738          (match_operator 5 "arm_comparison_operator"
7739           [(match_operand:SI 3 "s_register_operand" "r,r")
7740            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7741          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7742          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7743    (clobber (reg:CC CC_REGNUM))]
7744   "TARGET_ARM"
7745   "#"
7746   [(set_attr "conds" "clob")
7747    (set_attr "length" "8,12")]
7750 (define_insn "*if_neg_move"
7751   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7752         (if_then_else:SI
7753          (match_operator 4 "arm_comparison_operator"
7754           [(match_operand 3 "cc_register" "") (const_int 0)])
7755          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7756          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7757   "TARGET_ARM"
7758   "@
7759    rsb%d4\\t%0, %2, #0
7760    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7761    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7762   [(set_attr "conds" "use")
7763    (set_attr "length" "4,8,8")]
7766 (define_insn "*ifcompare_move_neg"
7767   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7768         (if_then_else:SI
7769          (match_operator 5 "arm_comparison_operator"
7770           [(match_operand:SI 3 "s_register_operand" "r,r")
7771            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7772          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7773          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7774    (clobber (reg:CC CC_REGNUM))]
7775   "TARGET_ARM"
7776   "#"
7777   [(set_attr "conds" "clob")
7778    (set_attr "length" "8,12")]
7781 (define_insn "*if_move_neg"
7782   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7783         (if_then_else:SI
7784          (match_operator 4 "arm_comparison_operator"
7785           [(match_operand 3 "cc_register" "") (const_int 0)])
7786          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7787          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7788   "TARGET_ARM"
7789   "@
7790    rsb%D4\\t%0, %2, #0
7791    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7792    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7793   [(set_attr "conds" "use")
7794    (set_attr "length" "4,8,8")]
7797 (define_insn "*arith_adjacentmem"
7798   [(set (match_operand:SI 0 "s_register_operand" "=r")
7799         (match_operator:SI 1 "shiftable_operator"
7800          [(match_operand:SI 2 "memory_operand" "m")
7801           (match_operand:SI 3 "memory_operand" "m")]))
7802    (clobber (match_scratch:SI 4 "=r"))]
7803   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7804   "*
7805   {
7806     rtx ldm[3];
7807     rtx arith[4];
7808     int val1 = 0, val2 = 0;
7810     if (REGNO (operands[0]) > REGNO (operands[4]))
7811       {
7812         ldm[1] = operands[4];
7813         ldm[2] = operands[0];
7814       }
7815     else
7816       {
7817         ldm[1] = operands[0];
7818         ldm[2] = operands[4];
7819       }
7820     if (GET_CODE (XEXP (operands[2], 0)) != REG)
7821       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7822     if (GET_CODE (XEXP (operands[3], 0)) != REG)
7823       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7824     arith[0] = operands[0];
7825     arith[3] = operands[1];
7826     if (val1 < val2)
7827       {
7828         arith[1] = ldm[1];
7829         arith[2] = ldm[2];
7830       }
7831     else
7832       {
7833         arith[1] = ldm[2];
7834         arith[2] = ldm[1];
7835       }
7836    if (val1 && val2)
7837       {
7838         rtx ops[3];
7839         ldm[0] = ops[0] = operands[4];
7840         ops[1] = XEXP (XEXP (operands[2], 0), 0);
7841         ops[2] = XEXP (XEXP (operands[2], 0), 1);
7842         output_add_immediate (ops);
7843         if (val1 < val2)
7844           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7845         else
7846           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7847       }
7848     else if (val1)
7849       {
7850         ldm[0] = XEXP (operands[3], 0);
7851         if (val1 < val2)
7852           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7853         else
7854           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7855       }
7856     else
7857       {
7858         ldm[0] = XEXP (operands[2], 0);
7859         if (val1 < val2)
7860           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7861         else
7862           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7863       }
7864     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7865     return \"\";
7866   }"
7867   [(set_attr "length" "12")
7868    (set_attr "predicable" "yes")
7869    (set_attr "type" "load")]
7872 ;; the arm can support extended pre-inc instructions
7874 ;; In all these cases, we use operands 0 and 1 for the register being
7875 ;; incremented because those are the operands that local-alloc will
7876 ;; tie and these are the pair most likely to be tieable (and the ones
7877 ;; that will benefit the most).
7879 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7880 ;; elimination will cause too many headaches.
7882 (define_insn "*strqi_preinc"
7883   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7884                          (match_operand:SI 2 "index_operand" "rJ")))
7885         (match_operand:QI 3 "s_register_operand" "r"))
7886    (set (match_operand:SI 0 "s_register_operand" "=r")
7887         (plus:SI (match_dup 1) (match_dup 2)))]
7888   "TARGET_ARM
7889    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7890    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7891    && (GET_CODE (operands[2]) != REG
7892        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7893   "str%?b\\t%3, [%0, %2]!"
7894   [(set_attr "type" "store1")
7895    (set_attr "predicable" "yes")]
7898 (define_insn "*strqi_predec"
7899   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7900                           (match_operand:SI 2 "s_register_operand" "r")))
7901         (match_operand:QI 3 "s_register_operand" "r"))
7902    (set (match_operand:SI 0 "s_register_operand" "=r")
7903         (minus:SI (match_dup 1) (match_dup 2)))]
7904   "TARGET_ARM
7905    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7906    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7907    && (GET_CODE (operands[2]) != REG
7908        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7909   "str%?b\\t%3, [%0, -%2]!"
7910   [(set_attr "type" "store1")
7911    (set_attr "predicable" "yes")]
7914 (define_insn "*loadqi_preinc"
7915   [(set (match_operand:QI 3 "s_register_operand" "=r")
7916         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7917                          (match_operand:SI 2 "index_operand" "rJ"))))
7918    (set (match_operand:SI 0 "s_register_operand" "=r")
7919         (plus:SI (match_dup 1) (match_dup 2)))]
7920   "TARGET_ARM
7921    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7922    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7923    && (GET_CODE (operands[2]) != REG
7924        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7925   "ldr%?b\\t%3, [%0, %2]!"
7926   [(set_attr "type" "load")
7927    (set_attr "predicable" "yes")]
7930 (define_insn "*loadqi_predec"
7931   [(set (match_operand:QI 3 "s_register_operand" "=r")
7932         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7933                           (match_operand:SI 2 "s_register_operand" "r"))))
7934    (set (match_operand:SI 0 "s_register_operand" "=r")
7935         (minus:SI (match_dup 1) (match_dup 2)))]
7936   "TARGET_ARM
7937    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7938    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7939    && (GET_CODE (operands[2]) != REG
7940        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7941   "ldr%?b\\t%3, [%0, -%2]!"
7942   [(set_attr "type" "load")
7943    (set_attr "predicable" "yes")]
7946 (define_insn "*loadqisi_preinc"
7947   [(set (match_operand:SI 3 "s_register_operand" "=r")
7948         (zero_extend:SI
7949          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7950                           (match_operand:SI 2 "index_operand" "rJ")))))
7951    (set (match_operand:SI 0 "s_register_operand" "=r")
7952         (plus:SI (match_dup 1) (match_dup 2)))]
7953   "TARGET_ARM
7954    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7955    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7956    && (GET_CODE (operands[2]) != REG
7957        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7958   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
7959   [(set_attr "type" "load")
7960    (set_attr "predicable" "yes")]
7963 (define_insn "*loadqisi_predec"
7964   [(set (match_operand:SI 3 "s_register_operand" "=r")
7965         (zero_extend:SI
7966          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7967                            (match_operand:SI 2 "s_register_operand" "r")))))
7968    (set (match_operand:SI 0 "s_register_operand" "=r")
7969         (minus:SI (match_dup 1) (match_dup 2)))]
7970   "TARGET_ARM
7971    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7972    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7973    && (GET_CODE (operands[2]) != REG
7974        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7975   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
7976   [(set_attr "type" "load")
7977    (set_attr "predicable" "yes")]
7980 (define_insn "*strsi_preinc"
7981   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7982                          (match_operand:SI 2 "index_operand" "rJ")))
7983         (match_operand:SI 3 "s_register_operand" "r"))
7984    (set (match_operand:SI 0 "s_register_operand" "=r")
7985         (plus:SI (match_dup 1) (match_dup 2)))]
7986   "TARGET_ARM
7987    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7988    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7989    && (GET_CODE (operands[2]) != REG
7990        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7991   "str%?\\t%3, [%0, %2]!"
7992   [(set_attr "type" "store1")
7993    (set_attr "predicable" "yes")]
7996 (define_insn "*strsi_predec"
7997   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7998                           (match_operand:SI 2 "s_register_operand" "r")))
7999         (match_operand:SI 3 "s_register_operand" "r"))
8000    (set (match_operand:SI 0 "s_register_operand" "=r")
8001         (minus:SI (match_dup 1) (match_dup 2)))]
8002   "TARGET_ARM
8003    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8004    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8005    && (GET_CODE (operands[2]) != REG
8006        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8007   "str%?\\t%3, [%0, -%2]!"
8008   [(set_attr "type" "store1")
8009    (set_attr "predicable" "yes")]
8012 (define_insn "*loadsi_preinc"
8013   [(set (match_operand:SI 3 "s_register_operand" "=r")
8014         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8015                          (match_operand:SI 2 "index_operand" "rJ"))))
8016    (set (match_operand:SI 0 "s_register_operand" "=r")
8017         (plus:SI (match_dup 1) (match_dup 2)))]
8018   "TARGET_ARM
8019    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8020    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8021    && (GET_CODE (operands[2]) != REG
8022        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8023   "ldr%?\\t%3, [%0, %2]!"
8024   [(set_attr "type" "load")
8025    (set_attr "predicable" "yes")]
8028 (define_insn "*loadsi_predec"
8029   [(set (match_operand:SI 3 "s_register_operand" "=r")
8030         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8031                           (match_operand:SI 2 "s_register_operand" "r"))))
8032    (set (match_operand:SI 0 "s_register_operand" "=r")
8033         (minus:SI (match_dup 1) (match_dup 2)))]
8034   "TARGET_ARM
8035    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8036    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8037    && (GET_CODE (operands[2]) != REG
8038        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8039   "ldr%?\\t%3, [%0, -%2]!"
8040   [(set_attr "type" "load")
8041    (set_attr "predicable" "yes")]
8044 (define_insn "*loadhi_preinc"
8045   [(set (match_operand:HI 3 "s_register_operand" "=r")
8046         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8047                          (match_operand:SI 2 "index_operand" "rJ"))))
8048    (set (match_operand:SI 0 "s_register_operand" "=r")
8049         (plus:SI (match_dup 1) (match_dup 2)))]
8050   "TARGET_ARM
8051    && !BYTES_BIG_ENDIAN
8052    && !TARGET_MMU_TRAPS
8053    && !arm_arch4
8054    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8055    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8056    && (GET_CODE (operands[2]) != REG
8057        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8058   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8059   [(set_attr "type" "load")
8060    (set_attr "predicable" "yes")]
8063 (define_insn "*loadhi_predec"
8064   [(set (match_operand:HI 3 "s_register_operand" "=r")
8065         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8066                           (match_operand:SI 2 "s_register_operand" "r"))))
8067    (set (match_operand:SI 0 "s_register_operand" "=r")
8068         (minus:SI (match_dup 1) (match_dup 2)))]
8069   "TARGET_ARM
8070    && !BYTES_BIG_ENDIAN
8071    && !TARGET_MMU_TRAPS
8072    && !arm_arch4
8073    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8074    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8075    && (GET_CODE (operands[2]) != REG
8076        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8077   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8078   [(set_attr "type" "load")
8079    (set_attr "predicable" "yes")]
8082 (define_insn "*strqi_shiftpreinc"
8083   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8084                           [(match_operand:SI 3 "s_register_operand" "r")
8085                            (match_operand:SI 4 "const_shift_operand" "n")])
8086                          (match_operand:SI 1 "s_register_operand" "0")))
8087         (match_operand:QI 5 "s_register_operand" "r"))
8088    (set (match_operand:SI 0 "s_register_operand" "=r")
8089         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8090                  (match_dup 1)))]
8091   "TARGET_ARM
8092    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8093    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8094    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8095   "str%?b\\t%5, [%0, %3%S2]!"
8096   [(set_attr "type" "store1")
8097    (set_attr "predicable" "yes")]
8100 (define_insn "*strqi_shiftpredec"
8101   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8102                           (match_operator:SI 2 "shift_operator"
8103                            [(match_operand:SI 3 "s_register_operand" "r")
8104                             (match_operand:SI 4 "const_shift_operand" "n")])))
8105         (match_operand:QI 5 "s_register_operand" "r"))
8106    (set (match_operand:SI 0 "s_register_operand" "=r")
8107         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8108                                                  (match_dup 4)])))]
8109   "TARGET_ARM
8110    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8111    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8112    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8113   "str%?b\\t%5, [%0, -%3%S2]!"
8114   [(set_attr "type" "store1")
8115    (set_attr "predicable" "yes")]
8118 (define_insn "*loadqi_shiftpreinc"
8119   [(set (match_operand:QI 5 "s_register_operand" "=r")
8120         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8121                           [(match_operand:SI 3 "s_register_operand" "r")
8122                            (match_operand:SI 4 "const_shift_operand" "n")])
8123                          (match_operand:SI 1 "s_register_operand" "0"))))
8124    (set (match_operand:SI 0 "s_register_operand" "=r")
8125         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8126                  (match_dup 1)))]
8127   "TARGET_ARM
8128    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8129    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8130    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8131   "ldr%?b\\t%5, [%0, %3%S2]!"
8132   [(set_attr "type" "load")
8133    (set_attr "predicable" "yes")]
8136 (define_insn "*loadqi_shiftpredec"
8137   [(set (match_operand:QI 5 "s_register_operand" "=r")
8138         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8139                           (match_operator:SI 2 "shift_operator"
8140                            [(match_operand:SI 3 "s_register_operand" "r")
8141                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8142    (set (match_operand:SI 0 "s_register_operand" "=r")
8143         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8144                                                  (match_dup 4)])))]
8145   "TARGET_ARM
8146    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8147    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8148    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8149   "ldr%?b\\t%5, [%0, -%3%S2]!"
8150   [(set_attr "type" "load")
8151    (set_attr "predicable" "yes")]
8154 (define_insn "*strsi_shiftpreinc"
8155   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8156                           [(match_operand:SI 3 "s_register_operand" "r")
8157                            (match_operand:SI 4 "const_shift_operand" "n")])
8158                          (match_operand:SI 1 "s_register_operand" "0")))
8159         (match_operand:SI 5 "s_register_operand" "r"))
8160    (set (match_operand:SI 0 "s_register_operand" "=r")
8161         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8162                  (match_dup 1)))]
8163   "TARGET_ARM
8164    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8165    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8166    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8167   "str%?\\t%5, [%0, %3%S2]!"
8168   [(set_attr "type" "store1")
8169    (set_attr "predicable" "yes")]
8172 (define_insn "*strsi_shiftpredec"
8173   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8174                           (match_operator:SI 2 "shift_operator"
8175                            [(match_operand:SI 3 "s_register_operand" "r")
8176                             (match_operand:SI 4 "const_shift_operand" "n")])))
8177         (match_operand:SI 5 "s_register_operand" "r"))
8178    (set (match_operand:SI 0 "s_register_operand" "=r")
8179         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8180                                                  (match_dup 4)])))]
8181   "TARGET_ARM
8182    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8183    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8184    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8185   "str%?\\t%5, [%0, -%3%S2]!"
8186   [(set_attr "type" "store1")
8187    (set_attr "predicable" "yes")]
8190 (define_insn "*loadsi_shiftpreinc"
8191   [(set (match_operand:SI 5 "s_register_operand" "=r")
8192         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8193                           [(match_operand:SI 3 "s_register_operand" "r")
8194                            (match_operand:SI 4 "const_shift_operand" "n")])
8195                          (match_operand:SI 1 "s_register_operand" "0"))))
8196    (set (match_operand:SI 0 "s_register_operand" "=r")
8197         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8198                  (match_dup 1)))]
8199   "TARGET_ARM
8200    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8201    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8202    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8203   "ldr%?\\t%5, [%0, %3%S2]!"
8204   [(set_attr "type" "load")
8205    (set_attr "predicable" "yes")]
8208 (define_insn "*loadsi_shiftpredec"
8209   [(set (match_operand:SI 5 "s_register_operand" "=r")
8210         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8211                           (match_operator:SI 2 "shift_operator"
8212                            [(match_operand:SI 3 "s_register_operand" "r")
8213                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8214    (set (match_operand:SI 0 "s_register_operand" "=r")
8215         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8216                                                  (match_dup 4)])))]
8217   "TARGET_ARM
8218    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8219    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8220    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8221   "ldr%?\\t%5, [%0, -%3%S2]!"
8222   [(set_attr "type" "load")
8223    (set_attr "predicable" "yes")])
8225 (define_insn "*loadhi_shiftpreinc"
8226   [(set (match_operand:HI 5 "s_register_operand" "=r")
8227         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8228                           [(match_operand:SI 3 "s_register_operand" "r")
8229                            (match_operand:SI 4 "const_shift_operand" "n")])
8230                          (match_operand:SI 1 "s_register_operand" "0"))))
8231    (set (match_operand:SI 0 "s_register_operand" "=r")
8232         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8233                  (match_dup 1)))]
8234   "TARGET_ARM
8235    && !BYTES_BIG_ENDIAN
8236    && !TARGET_MMU_TRAPS
8237    && !arm_arch4
8238    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8239    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8240    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8241   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8242   [(set_attr "type" "load")
8243    (set_attr "predicable" "yes")]
8246 (define_insn "*loadhi_shiftpredec"
8247   [(set (match_operand:HI 5 "s_register_operand" "=r")
8248         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8249                           (match_operator:SI 2 "shift_operator"
8250                            [(match_operand:SI 3 "s_register_operand" "r")
8251                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8252    (set (match_operand:SI 0 "s_register_operand" "=r")
8253         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8254                                                  (match_dup 4)])))]
8255   "TARGET_ARM
8256    && !BYTES_BIG_ENDIAN
8257    && !TARGET_MMU_TRAPS
8258    && !arm_arch4
8259    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8260    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8261    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8262   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8263   [(set_attr "type" "load")
8264    (set_attr "predicable" "yes")]
8267 ; It can also support extended post-inc expressions, but combine doesn't
8268 ; try these....
8269 ; It doesn't seem worth adding peepholes for anything but the most common
8270 ; cases since, unlike combine, the increment must immediately follow the load
8271 ; for this pattern to match.
8272 ; We must watch to see that the source/destination register isn't also the
8273 ; same as the base address register, and that if the index is a register,
8274 ; that it is not the same as the base address register.  In such cases the
8275 ; instruction that we would generate would have UNPREDICTABLE behavior so 
8276 ; we cannot use it.
8278 (define_peephole
8279   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8280         (match_operand:QI 2 "s_register_operand" "r"))
8281    (set (match_dup 0)
8282         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8283   "TARGET_ARM
8284    && (REGNO (operands[2]) != REGNO (operands[0]))
8285    && (GET_CODE (operands[1]) != REG
8286        || (REGNO (operands[1]) != REGNO (operands[0])))"
8287   "str%?b\\t%2, [%0], %1"
8290 (define_peephole
8291   [(set (match_operand:QI 0 "s_register_operand" "=r")
8292         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8293    (set (match_dup 1)
8294         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8295   "TARGET_ARM
8296    && REGNO (operands[0]) != REGNO(operands[1])
8297    && (GET_CODE (operands[2]) != REG
8298        || REGNO(operands[0]) != REGNO (operands[2]))"
8299   "ldr%?b\\t%0, [%1], %2"
8302 (define_peephole
8303   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8304         (match_operand:SI 2 "s_register_operand" "r"))
8305    (set (match_dup 0)
8306         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8307   "TARGET_ARM
8308    && (REGNO (operands[2]) != REGNO (operands[0]))
8309    && (GET_CODE (operands[1]) != REG
8310        || (REGNO (operands[1]) != REGNO (operands[0])))"
8311   "str%?\\t%2, [%0], %1"
8314 (define_peephole
8315   [(set (match_operand:HI 0 "s_register_operand" "=r")
8316         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8317    (set (match_dup 1)
8318         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8319   "TARGET_ARM
8320    && !BYTES_BIG_ENDIAN
8321    && !TARGET_MMU_TRAPS
8322    && !arm_arch4
8323    && REGNO (operands[0]) != REGNO(operands[1])
8324    && (GET_CODE (operands[2]) != REG
8325        || REGNO(operands[0]) != REGNO (operands[2]))"
8326   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8329 (define_peephole
8330   [(set (match_operand:SI 0 "s_register_operand" "=r")
8331         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8332    (set (match_dup 1)
8333         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8334   "TARGET_ARM
8335    && REGNO (operands[0]) != REGNO(operands[1])
8336    && (GET_CODE (operands[2]) != REG
8337        || REGNO(operands[0]) != REGNO (operands[2]))"
8338   "ldr%?\\t%0, [%1], %2"
8341 (define_peephole
8342   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8343                          (match_operand:SI 1 "index_operand" "rJ")))
8344         (match_operand:QI 2 "s_register_operand" "r"))
8345    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8346   "TARGET_ARM
8347    && (REGNO (operands[2]) != REGNO (operands[0]))
8348    && (GET_CODE (operands[1]) != REG
8349        || (REGNO (operands[1]) != REGNO (operands[0])))"
8350   "str%?b\\t%2, [%0, %1]!"
8353 (define_peephole
8354   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8355                           [(match_operand:SI 0 "s_register_operand" "r")
8356                            (match_operand:SI 1 "const_int_operand" "n")])
8357                          (match_operand:SI 2 "s_register_operand" "+r")))
8358         (match_operand:QI 3 "s_register_operand" "r"))
8359    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8360                                (match_dup 2)))]
8361   "TARGET_ARM
8362    && (REGNO (operands[3]) != REGNO (operands[2]))
8363    && (REGNO (operands[0]) != REGNO (operands[2]))"
8364   "str%?b\\t%3, [%2, %0%S4]!"
8367 ; This pattern is never tried by combine, so do it as a peephole
8369 (define_peephole2
8370   [(set (match_operand:SI 0 "s_register_operand" "")
8371         (match_operand:SI 1 "s_register_operand" ""))
8372    (set (reg:CC CC_REGNUM)
8373         (compare:CC (match_dup 1) (const_int 0)))]
8374   "TARGET_ARM
8375    && (!TARGET_CIRRUS
8376        || (!cirrus_fp_register (operands[0], SImode)
8377            && !cirrus_fp_register (operands[1], SImode)))
8378   "
8379   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8380               (set (match_dup 0) (match_dup 1))])]
8381   ""
8384 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8385 ; reversed, check that the memory references aren't volatile.
8387 (define_peephole
8388   [(set (match_operand:SI 0 "s_register_operand" "=r")
8389         (match_operand:SI 4 "memory_operand" "m"))
8390    (set (match_operand:SI 1 "s_register_operand" "=r")
8391         (match_operand:SI 5 "memory_operand" "m"))
8392    (set (match_operand:SI 2 "s_register_operand" "=r")
8393         (match_operand:SI 6 "memory_operand" "m"))
8394    (set (match_operand:SI 3 "s_register_operand" "=r")
8395         (match_operand:SI 7 "memory_operand" "m"))]
8396   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8397   "*
8398   return emit_ldm_seq (operands, 4);
8399   "
8402 (define_peephole
8403   [(set (match_operand:SI 0 "s_register_operand" "=r")
8404         (match_operand:SI 3 "memory_operand" "m"))
8405    (set (match_operand:SI 1 "s_register_operand" "=r")
8406         (match_operand:SI 4 "memory_operand" "m"))
8407    (set (match_operand:SI 2 "s_register_operand" "=r")
8408         (match_operand:SI 5 "memory_operand" "m"))]
8409   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8410   "*
8411   return emit_ldm_seq (operands, 3);
8412   "
8415 (define_peephole
8416   [(set (match_operand:SI 0 "s_register_operand" "=r")
8417         (match_operand:SI 2 "memory_operand" "m"))
8418    (set (match_operand:SI 1 "s_register_operand" "=r")
8419         (match_operand:SI 3 "memory_operand" "m"))]
8420   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8421   "*
8422   return emit_ldm_seq (operands, 2);
8423   "
8426 (define_peephole
8427   [(set (match_operand:SI 4 "memory_operand" "=m")
8428         (match_operand:SI 0 "s_register_operand" "r"))
8429    (set (match_operand:SI 5 "memory_operand" "=m")
8430         (match_operand:SI 1 "s_register_operand" "r"))
8431    (set (match_operand:SI 6 "memory_operand" "=m")
8432         (match_operand:SI 2 "s_register_operand" "r"))
8433    (set (match_operand:SI 7 "memory_operand" "=m")
8434         (match_operand:SI 3 "s_register_operand" "r"))]
8435   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8436   "*
8437   return emit_stm_seq (operands, 4);
8438   "
8441 (define_peephole
8442   [(set (match_operand:SI 3 "memory_operand" "=m")
8443         (match_operand:SI 0 "s_register_operand" "r"))
8444    (set (match_operand:SI 4 "memory_operand" "=m")
8445         (match_operand:SI 1 "s_register_operand" "r"))
8446    (set (match_operand:SI 5 "memory_operand" "=m")
8447         (match_operand:SI 2 "s_register_operand" "r"))]
8448   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8449   "*
8450   return emit_stm_seq (operands, 3);
8451   "
8454 (define_peephole
8455   [(set (match_operand:SI 2 "memory_operand" "=m")
8456         (match_operand:SI 0 "s_register_operand" "r"))
8457    (set (match_operand:SI 3 "memory_operand" "=m")
8458         (match_operand:SI 1 "s_register_operand" "r"))]
8459   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8460   "*
8461   return emit_stm_seq (operands, 2);
8462   "
8465 (define_split
8466   [(set (match_operand:SI 0 "s_register_operand" "")
8467         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8468                        (const_int 0))
8469                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8470                          [(match_operand:SI 3 "s_register_operand" "")
8471                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
8472    (clobber (match_operand:SI 5 "s_register_operand" ""))]
8473   "TARGET_ARM"
8474   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8475    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8476                               (match_dup 5)))]
8477   ""
8480 ;; This split can be used because CC_Z mode implies that the following
8481 ;; branch will be an equality, or an unsigned inequality, so the sign
8482 ;; extension is not needed.
8484 (define_split
8485   [(set (reg:CC_Z CC_REGNUM)
8486         (compare:CC_Z
8487          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8488                     (const_int 24))
8489          (match_operand 1 "const_int_operand" "")))
8490    (clobber (match_scratch:SI 2 ""))]
8491   "TARGET_ARM
8492    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8493        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8494   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8495    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8496   "
8497   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8498   "
8501 (define_expand "prologue"
8502   [(clobber (const_int 0))]
8503   "TARGET_EITHER"
8504   "if (TARGET_ARM)
8505      arm_expand_prologue ();
8506    else
8507      thumb_expand_prologue ();
8508   DONE;
8509   "
8512 (define_expand "epilogue"
8513   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8514   "TARGET_EITHER"
8515   "
8516   if (TARGET_THUMB)
8517     thumb_expand_epilogue ();
8518   else if (USE_RETURN_INSN (FALSE))
8519     {
8520       emit_jump_insn (gen_return ());
8521       DONE;
8522     }
8523   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8524         gen_rtvec (1,
8525                 gen_rtx_RETURN (VOIDmode)),
8526         VUNSPEC_EPILOGUE));
8527   DONE;
8528   "
8531 ;; Note - although unspec_volatile's USE all hard registers,
8532 ;; USEs are ignored after relaod has completed.  Thus we need
8533 ;; to add an unspec of the link register to ensure that flow
8534 ;; does not think that it is unused by the sibcall branch that
8535 ;; will replace the standard function epilogue.
8536 (define_insn "sibcall_epilogue"
8537   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8538               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8539   "TARGET_ARM"
8540   "*
8541   if (USE_RETURN_INSN (FALSE))
8542     return output_return_instruction (const_true_rtx, FALSE, FALSE);
8543   return arm_output_epilogue (FALSE);
8544   "
8545 ;; Length is absolute worst case
8546   [(set_attr "length" "44")
8547    (set_attr "type" "block")
8548    ;; We don't clobber the conditions, but the potential length of this
8549    ;; operation is sufficient to make conditionalizing the sequence 
8550    ;; unlikely to be profitable.
8551    (set_attr "conds" "clob")]
8554 (define_insn "*epilogue_insns"
8555   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8556   "TARGET_EITHER"
8557   "*
8558   if (TARGET_ARM)
8559     return arm_output_epilogue (TRUE);
8560   else /* TARGET_THUMB */
8561     return thumb_unexpanded_epilogue ();
8562   "
8563   ; Length is absolute worst case
8564   [(set_attr "length" "44")
8565    (set_attr "type" "block")
8566    ;; We don't clobber the conditions, but the potential length of this
8567    ;; operation is sufficient to make conditionalizing the sequence 
8568    ;; unlikely to be profitable.
8569    (set_attr "conds" "clob")]
8572 (define_expand "eh_epilogue"
8573   [(use (match_operand:SI 0 "register_operand" "r"))
8574    (use (match_operand:SI 1 "register_operand" "r"))
8575    (use (match_operand:SI 2 "register_operand" "r"))]
8576   "TARGET_EITHER"
8577   "
8578   {
8579     cfun->machine->eh_epilogue_sp_ofs = operands[1];
8580     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8581       {
8582         rtx ra = gen_rtx_REG (Pmode, 2);
8584         emit_move_insn (ra, operands[2]);
8585         operands[2] = ra;
8586       }
8587     /* This is a hack -- we may have crystalized the function type too
8588        early.  */
8589     cfun->machine->func_type = 0;
8590   }"
8593 ;; This split is only used during output to reduce the number of patterns
8594 ;; that need assembler instructions adding to them.  We allowed the setting
8595 ;; of the conditions to be implicit during rtl generation so that
8596 ;; the conditional compare patterns would work.  However this conflicts to
8597 ;; some extent with the conditional data operations, so we have to split them
8598 ;; up again here.
8600 (define_split
8601   [(set (match_operand:SI 0 "s_register_operand" "")
8602         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8603                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8604                          (match_dup 0)
8605                          (match_operand 4 "" "")))
8606    (clobber (reg:CC CC_REGNUM))]
8607   "TARGET_ARM && reload_completed"
8608   [(set (match_dup 5) (match_dup 6))
8609    (cond_exec (match_dup 7)
8610               (set (match_dup 0) (match_dup 4)))]
8611   "
8612   {
8613     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8614                                              operands[2], operands[3]);
8615     enum rtx_code rc = GET_CODE (operands[1]);
8617     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8618     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8619     if (mode == CCFPmode || mode == CCFPEmode)
8620       rc = reverse_condition_maybe_unordered (rc);
8621     else
8622       rc = reverse_condition (rc);
8624     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8625   }"
8628 (define_split
8629   [(set (match_operand:SI 0 "s_register_operand" "")
8630         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8631                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8632                          (match_operand 4 "" "")
8633                          (match_dup 0)))
8634    (clobber (reg:CC CC_REGNUM))]
8635   "TARGET_ARM && reload_completed"
8636   [(set (match_dup 5) (match_dup 6))
8637    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8638               (set (match_dup 0) (match_dup 4)))]
8639   "
8640   {
8641     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8642                                              operands[2], operands[3]);
8644     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8645     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8646   }"
8649 (define_split
8650   [(set (match_operand:SI 0 "s_register_operand" "")
8651         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8652                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8653                          (match_operand 4 "" "")
8654                          (match_operand 5 "" "")))
8655    (clobber (reg:CC CC_REGNUM))]
8656   "TARGET_ARM && reload_completed"
8657   [(set (match_dup 6) (match_dup 7))
8658    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8659               (set (match_dup 0) (match_dup 4)))
8660    (cond_exec (match_dup 8)
8661               (set (match_dup 0) (match_dup 5)))]
8662   "
8663   {
8664     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8665                                              operands[2], operands[3]);
8666     enum rtx_code rc = GET_CODE (operands[1]);
8668     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8669     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8670     if (mode == CCFPmode || mode == CCFPEmode)
8671       rc = reverse_condition_maybe_unordered (rc);
8672     else
8673       rc = reverse_condition (rc);
8675     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8676   }"
8679 (define_split
8680   [(set (match_operand:SI 0 "s_register_operand" "")
8681         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8682                           [(match_operand:SI 2 "s_register_operand" "")
8683                            (match_operand:SI 3 "arm_add_operand" "")])
8684                          (match_operand:SI 4 "arm_rhs_operand" "")
8685                          (not:SI
8686                           (match_operand:SI 5 "s_register_operand" ""))))
8687    (clobber (reg:CC CC_REGNUM))]
8688   "TARGET_ARM && reload_completed"
8689   [(set (match_dup 6) (match_dup 7))
8690    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8691               (set (match_dup 0) (match_dup 4)))
8692    (cond_exec (match_dup 8)
8693               (set (match_dup 0) (not:SI (match_dup 5))))]
8694   "
8695   {
8696     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8697                                              operands[2], operands[3]);
8698     enum rtx_code rc = GET_CODE (operands[1]);
8700     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8701     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8702     if (mode == CCFPmode || mode == CCFPEmode)
8703       rc = reverse_condition_maybe_unordered (rc);
8704     else
8705       rc = reverse_condition (rc);
8707     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8708   }"
8711 (define_insn "*cond_move_not"
8712   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8713         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8714                           [(match_operand 3 "cc_register" "") (const_int 0)])
8715                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8716                          (not:SI
8717                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
8718   "TARGET_ARM"
8719   "@
8720    mvn%D4\\t%0, %2
8721    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8722   [(set_attr "conds" "use")
8723    (set_attr "length" "4,8")]
8726 ;; The next two patterns occur when an AND operation is followed by a
8727 ;; scc insn sequence 
8729 (define_insn "*sign_extract_onebit"
8730   [(set (match_operand:SI 0 "s_register_operand" "=r")
8731         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8732                          (const_int 1)
8733                          (match_operand:SI 2 "const_int_operand" "n")))
8734     (clobber (reg:CC CC_REGNUM))]
8735   "TARGET_ARM"
8736   "*
8737     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8738     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8739     return \"mvnne\\t%0, #0\";
8740   "
8741   [(set_attr "conds" "clob")
8742    (set_attr "length" "8")]
8745 (define_insn "*not_signextract_onebit"
8746   [(set (match_operand:SI 0 "s_register_operand" "=r")
8747         (not:SI
8748          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8749                           (const_int 1)
8750                           (match_operand:SI 2 "const_int_operand" "n"))))
8751    (clobber (reg:CC CC_REGNUM))]
8752   "TARGET_ARM"
8753   "*
8754     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8755     output_asm_insn (\"tst\\t%1, %2\", operands);
8756     output_asm_insn (\"mvneq\\t%0, #0\", operands);
8757     return \"movne\\t%0, #0\";
8758   "
8759   [(set_attr "conds" "clob")
8760    (set_attr "length" "12")]
8763 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8764 ;; expressions.  For simplicity, the first register is also in the unspec
8765 ;; part.
8766 (define_insn "*push_multi"
8767   [(match_parallel 2 "multi_register_push"
8768     [(set (match_operand:BLK 0 "memory_operand" "=m")
8769           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8770                       UNSPEC_PUSH_MULT))])]
8771   "TARGET_ARM"
8772   "*
8773   {
8774     int num_saves = XVECLEN (operands[2], 0);
8775      
8776     /* For the StrongARM at least it is faster to
8777        use STR to store only a single register.  */
8778     if (num_saves == 1)
8779       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8780     else
8781       {
8782         int i;
8783         char pattern[100];
8785         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8787         for (i = 1; i < num_saves; i++)
8788           {
8789             strcat (pattern, \", %|\");
8790             strcat (pattern,
8791                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8792           }
8794         strcat (pattern, \"}\");
8795         output_asm_insn (pattern, operands);
8796       }
8798     return \"\";
8799   }"
8800   [(set_attr "type" "store4")]
8803 (define_insn "stack_tie"
8804   [(set (mem:BLK (scratch))
8805         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8806                      (match_operand:SI 1 "s_register_operand" "r")]
8807                     UNSPEC_PRLG_STK))]
8808   ""
8809   ""
8810   [(set_attr "length" "0")]
8813 ;; Similarly for the floating point registers
8814 (define_insn "*push_fp_multi"
8815   [(match_parallel 2 "multi_register_push"
8816     [(set (match_operand:BLK 0 "memory_operand" "=m")
8817           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8818                       UNSPEC_PUSH_MULT))])]
8819   "TARGET_ARM"
8820   "*
8821   {
8822     char pattern[100];
8824     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8825     output_asm_insn (pattern, operands);
8826     return \"\";
8827   }"
8828   [(set_attr "type" "f_store")]
8831 ;; Special patterns for dealing with the constant pool
8833 (define_insn "align_4"
8834   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8835   "TARGET_EITHER"
8836   "*
8837   assemble_align (32);
8838   return \"\";
8839   "
8842 (define_insn "consttable_end"
8843   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8844   "TARGET_EITHER"
8845   "*
8846   making_const_table = FALSE;
8847   return \"\";
8848   "
8851 (define_insn "consttable_1"
8852   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8853   "TARGET_THUMB"
8854   "*
8855   making_const_table = TRUE;
8856   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8857   assemble_zeros (3);
8858   return \"\";
8859   "
8860   [(set_attr "length" "4")]
8863 (define_insn "consttable_2"
8864   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8865   "TARGET_THUMB"
8866   "*
8867   making_const_table = TRUE;
8868   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8869   assemble_zeros (2);
8870   return \"\";
8871   "
8872   [(set_attr "length" "4")]
8875 (define_insn "consttable_4"
8876   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8877   "TARGET_EITHER"
8878   "*
8879   {
8880     making_const_table = TRUE;
8881     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8882       {
8883       case MODE_FLOAT:
8884       {
8885         REAL_VALUE_TYPE r;
8886         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8887         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8888         break;
8889       }
8890       default:
8891         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8892         break;
8893       }
8894     return \"\";
8895   }"
8896   [(set_attr "length" "4")]
8899 (define_insn "consttable_8"
8900   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8901   "TARGET_EITHER"
8902   "*
8903   {
8904     making_const_table = TRUE;
8905     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8906       {
8907        case MODE_FLOAT:
8908         {
8909           REAL_VALUE_TYPE r;
8910           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8911           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8912           break;
8913         }
8914       default:
8915         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8916         break;
8917       }
8918     return \"\";
8919   }"
8920   [(set_attr "length" "8")]
8923 ;; Miscellaneous Thumb patterns
8925 (define_expand "tablejump"
8926   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8927               (use (label_ref (match_operand 1 "" "")))])]
8928   "TARGET_THUMB"
8929   "
8930   if (flag_pic)
8931     {
8932       /* Hopefully, CSE will eliminate this copy.  */
8933       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8934       rtx reg2 = gen_reg_rtx (SImode);
8936       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8937       operands[0] = reg2;
8938     }
8939   "
8942 (define_insn "*thumb_tablejump"
8943   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8944    (use (label_ref (match_operand 1 "" "")))]
8945   "TARGET_THUMB"
8946   "mov\\t%|pc, %0"
8947   [(set_attr "length" "2")]
8950 ;; V5 Instructions,
8952 (define_insn "clzsi2"
8953   [(set (match_operand:SI 0 "s_register_operand" "=r")
8954         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8955   "TARGET_ARM && arm_arch5"
8956   "clz\\t%0, %1")
8958 (define_expand "ffssi2"
8959   [(set (match_operand:SI 0 "s_register_operand" "")
8960         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
8961   "TARGET_ARM && arm_arch5"
8962   "
8963   {
8964     rtx t1, t2, t3;
8966     t1 = gen_reg_rtx (SImode);
8967     t2 = gen_reg_rtx (SImode);
8968     t3 = gen_reg_rtx (SImode);
8970     emit_insn (gen_negsi2 (t1, operands[1]));
8971     emit_insn (gen_andsi3 (t2, operands[1], t1));
8972     emit_insn (gen_clzsi2 (t3, t2));
8973     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
8974     DONE;
8975   }"
8978 (define_expand "ctzsi2"
8979   [(set (match_operand:SI 0 "s_register_operand" "")
8980         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
8981   "TARGET_ARM && arm_arch5"
8982   "
8983   {
8984     rtx t1, t2, t3;
8986     t1 = gen_reg_rtx (SImode);
8987     t2 = gen_reg_rtx (SImode);
8988     t3 = gen_reg_rtx (SImode);
8990     emit_insn (gen_negsi2 (t1, operands[1]));
8991     emit_insn (gen_andsi3 (t2, operands[1], t1));
8992     emit_insn (gen_clzsi2 (t3, t2));
8993     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
8994     DONE;
8995   }"
8998 ;; V5E instructions.
9000 (define_insn "prefetch"
9001   [(prefetch (match_operand:SI 0 "address_operand" "p")
9002              (match_operand:SI 1 "" "")
9003              (match_operand:SI 2 "" ""))]
9004   "TARGET_ARM && arm_arch5e"
9005   "pld\\t%a0")
9007 ;; General predication pattern
9009 (define_cond_exec
9010   [(match_operator 0 "arm_comparison_operator"
9011     [(match_operand 1 "cc_register" "")
9012      (const_int 0)])]
9013   "TARGET_ARM"
9014   ""
9017 (define_insn "prologue_use"
9018   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9019   ""
9020   "%@ %0 needed for prologue"