* arm.md (all call_value patterns): Remove register constraints on
[official-gcc.git] / gcc / config / arm / arm.md
blob339763ad627279b12927e7efe5446486ac0be3cc
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   ]
41 ;; 3rd operand to select_dominance_cc_mode
42 (define_constants
43   [(DOM_CC_X_AND_Y  0)
44    (DOM_CC_NX_OR_Y  1)
45    (DOM_CC_X_OR_Y   2)
46   ]
49 ;; UNSPEC Usage:
50 ;; Note: sin and cos are no-longer used.
52 (define_constants
53   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
54                         ;   operand 0 is the result,
55                         ;   operand 1 the parameter.
56    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
57                         ;   operand 0 is the result,
58                         ;   operand 1 the parameter.
59    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60                         ;   operand 0 is the first register,
61                         ;   subsequent registers are in parallel (use ...)
62                         ;   expressions.
63    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
64                         ;   usage, that is, we will add the pic_register
65                         ;   value to it before trying to dereference it.
66    (UNSPEC_PIC_BASE  4) ; Adding the PC value to the offset to the
67                         ;   GLOBAL_OFFSET_TABLE.  The operation is fully
68                         ;   described by the RTL but must be wrapped to
69                         ;   prevent combine from trying to rip it apart.
70    (UNSPEC_PRLG_STK  5) ; A special barrier that prevents frame accesses 
71                         ;   being scheduled before the stack adjustment insn.
72    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73                         ; this unspec is used to prevent the deletion of
74                         ; instructions setting registers for EH handling
75                         ; and stack frame generation.  Operand 0 is the
76                         ; register to "use".
77    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78    (UNSPEC_WSHUFH    8) ; Used by the instrinsic form of the iWMMXt WSHUFH instruction.
79    (UNSPEC_WACC      9) ; Used by the instrinsic form of the iWMMXt WACC instruction.
80    (UNSPEC_TMOVMSK  10) ; Used by the instrinsic form of the iWMMXt TMOVMSK instruction.
81    (UNSPEC_WSAD     11) ; Used by the instrinsic form of the iWMMXt WSAD instruction.
82    (UNSPEC_WSADZ    12) ; Used by the instrinsic form of the iWMMXt WSADZ instruction.
83    (UNSPEC_WMACS    13) ; Used by the instrinsic form of the iWMMXt WMACS instruction.
84    (UNSPEC_WMACU    14) ; Used by the instrinsic form of the iWMMXt WMACU instruction.
85    (UNSPEC_WMACSZ   15) ; Used by the instrinsic form of the iWMMXt WMACSZ instruction.
86    (UNSPEC_WMACUZ   16) ; Used by the instrinsic form of the iWMMXt WMACUZ instruction.
87    (UNSPEC_CLRDI    17) ; Used by the instrinsic form of the iWMMXt CLRDI instruction.
88    (UNSPEC_WMADDS   18) ; Used by the instrinsic form of the iWMMXt WMADDS instruction.
89    (UNSPEC_WMADDU   19) ; Used by the instrinsic form of the iWMMXt WMADDU instruction.
90   ]
93 ;; UNSPEC_VOLATILE Usage:
95 (define_constants
96   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
97                         ;   insn in the code.
98    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99                         ;   instruction epilogue sequence that isn't expanded
100                         ;   into normal RTL.  Used for both normal and sibcall
101                         ;   epilogues.
102    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
103                         ;   for inlined constants.
104    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
105                         ;   table.
106    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
107                         ;   an 8-bit object.
108    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
109                         ;   a 16-bit object.
110    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
111                         ;   a 32-bit object.
112    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
113                         ;   a 64-bit object.
114    (VUNSPEC_TMRC     8) ; Used by the iWMMXt TMRC instruction.
115    (VUNSPEC_TMCR     9) ; Used by the iWMMXt TMCR instruction.
116    (VUNSPEC_ALIGN8   10) ; 8-byte alignment version of VUNSPEC_ALIGN
117    (VUNSPEC_WCMP_EQ  11) ; Used by the iWMMXt WCMPEQ instructions
118    (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119    (VUNSPEC_WCMP_GT  13) ; Used by the iwMMXT WCMPGT instructions
120   ]
123 ;;---------------------------------------------------------------------------
124 ;; Attributes
126 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127 ; generating ARM code.  This is used to control the length of some insn
128 ; patterns that share the same RTL in both ARM and Thumb code.
129 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
131 ; PROG_MODE attribute is used to determine whether condition codes are
132 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
133 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
134 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
140 ;; Operand number of an input operand that is shifted.  Zero if the
141 ;; given instruction does not shift one of its input operands.
142 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 (define_attr "shift" "" (const_int 0))
145 ; Floating Point Unit.  If we only have floating point emulation, then there
146 ; is no point in scheduling the floating point insns.  (Well, for best
147 ; performance we should try and group them together).
148 (define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
149   (const (symbol_ref "arm_fpu_attr")))
151 ; LENGTH of an instruction (in bytes)
152 (define_attr "length" "" (const_int 4))
154 ; POOL_RANGE is how far away from a constant pool entry that this insn
155 ; can be placed.  If the distance is zero, then this insn will never
156 ; reference the pool.
157 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
158 ; before its address.
159 (define_attr "pool_range" "" (const_int 0))
160 (define_attr "neg_pool_range" "" (const_int 0))
162 ; An assembler sequence may clobber the condition codes without us knowing.
163 ; If such an insn references the pool, then we have no way of knowing how,
164 ; so use the most conservative value for pool_range.
165 (define_asm_attributes
166  [(set_attr "conds" "clob")
167   (set_attr "length" "4")
168   (set_attr "pool_range" "250")])
170 ; TYPE attribute is used to detect floating point instructions which, if
171 ; running on a co-processor can run in parallel with other, basic instructions
172 ; If write-buffer scheduling is enabled then it can also be used in the
173 ; scheduling of writes.
175 ; Classification of each insn
176 ; normal        any data instruction that doesn't hit memory or fp regs
177 ; mult          a multiply instruction
178 ; block         blockage insn, this blocks all functional units
179 ; float         a floating point arithmetic operation (subject to expansion)
180 ; fdivd         DFmode floating point division
181 ; fdivs         SFmode floating point division
182 ; fmul          Floating point multiply
183 ; ffmul         Fast floating point multiply
184 ; farith        Floating point arithmetic (4 cycle)
185 ; ffarith       Fast floating point arithmetic (2 cycle)
186 ; float_em      a floating point arithmetic operation that is normally emulated
187 ;               even on a machine with an fpa.
188 ; f_load        a floating point load from memory
189 ; f_store       a floating point store to memory
190 ; f_mem_r       a transfer of a floating point register to a real reg via mem
191 ; r_mem_f       the reverse of f_mem_r
192 ; f_2_r         fast transfer float to arm (no memory needed)
193 ; r_2_f         fast transfer arm to float
194 ; call          a subroutine call
195 ; load          any load from memory
196 ; store1        store 1 word to memory from arm registers
197 ; store2        store 2 words
198 ; store3        store 3 words
199 ; store4        store 4 words
200 ;  Additions for Cirrus Maverick co-processor:
201 ; mav_farith    Floating point arithmetic (4 cycle)
202 ; mav_dmult     Double multiplies (7 cycle)
204 (define_attr "type"
205         "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" 
206         (const_string "normal"))
208 ; Load scheduling, set from the arm_ld_sched variable
209 ; initialized by arm_override_options() 
210 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
212 ; condition codes: this one is used by final_prescan_insn to speed up
213 ; conditionalizing instructions.  It saves having to scan the rtl to see if
214 ; it uses or alters the condition codes.
216 ; USE means that the condition codes are used by the insn in the process of
217 ;   outputting code, this means (at present) that we can't use the insn in
218 ;   inlined branches
220 ; SET means that the purpose of the insn is to set the condition codes in a
221 ;   well defined manner.
223 ; CLOB means that the condition codes are altered in an undefined manner, if
224 ;   they are altered at all
226 ; JUMP_CLOB is used when the condition cannot be represented by a single
227 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
229 ; NOCOND means that the condition codes are neither altered nor affect the
230 ;   output of this insn
232 (define_attr "conds" "use,set,clob,jump_clob,nocond"
233         (if_then_else (eq_attr "type" "call")
234          (if_then_else (eq_attr "prog_mode" "prog32")
235           (const_string "clob") (const_string "nocond"))
236          (const_string "nocond")))
238 ; Predicable means that the insn can be conditionally executed based on
239 ; an automatically added predicate (additional patterns are generated by 
240 ; gen...).  We default to 'no' because no Thumb patterns match this rule
241 ; and not all ARM patterns do.
242 (define_attr "predicable" "no,yes" (const_string "no"))
244 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
245 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
246 ; suffer blockages enough to warrent modelling this (and it can adversely
247 ; affect the schedule).
248 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
250 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
251 ; to stall the processor.  Used with model_wbuf above.
252 (define_attr "write_conflict" "no,yes"
253   (if_then_else (eq_attr "type"
254                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
255                 (const_string "yes")
256                 (const_string "no")))
258 ; Classify the insns into those that take one cycle and those that take more
259 ; than one on the main cpu execution unit.
260 (define_attr "core_cycles" "single,multi"
261   (if_then_else (eq_attr "type"
262                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
263                 (const_string "single")
264                 (const_string "multi")))
266 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
267 ;; distant label.  Only applicable to Thumb code.
268 (define_attr "far_jump" "yes,no" (const_string "no"))
270 (define_automaton "arm")
272 ;; Write buffer
274 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
276 ; The write buffer on some of the arm6 processors is hard to model exactly.
277 ; There is room in the buffer for up to two addresses and up to eight words
278 ; of memory, but the two needn't be split evenly.  When writing the two
279 ; addresses are fully pipelined.  However, a read from memory that is not
280 ; currently in the cache will block until the writes have completed.
281 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
282 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
283 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
284 ; cycle to add as well.
285 (define_cpu_unit "write_buf" "arm")
287 ;; Write blockage unit
289 ; The write_blockage unit models (partially), the fact that reads will stall
290 ; until the write buffer empties.
291 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
292 ; so we don't model them here
293 (define_cpu_unit "write_blockage" "arm")
295 ;; Core
297 (define_cpu_unit "core" "arm")
299 (define_insn_reservation "r_mem_f_wbuf" 5
300   (and (eq_attr "model_wbuf" "yes")
301        (eq_attr "type" "r_mem_f"))
302   "core+write_buf*3")
304 (define_insn_reservation "store1_wbuf" 5
305   (and (eq_attr "model_wbuf" "yes")
306        (eq_attr "type" "store1"))
307   "core+write_buf*3+write_blockage*5")
309 (define_insn_reservation "store2_wbuf" 7
310   (and (eq_attr "model_wbuf" "yes")
311        (eq_attr "type" "store2"))
312   "core+write_buf*4+write_blockage*7")
314 (define_insn_reservation "store3_wbuf" 9
315   (and (eq_attr "model_wbuf" "yes")
316        (eq_attr "type" "store3"))
317   "core+write_buf*5+write_blockage*9")
319 (define_insn_reservation "store4_wbuf" 11
320   (and (eq_attr "model_wbuf" "yes")
321        (eq_attr "type" "store4"))
322   "core+write_buf*6+write_blockage*11")
324 (define_insn_reservation "store2" 3
325   (and (eq_attr "model_wbuf" "no")
326        (eq_attr "type" "store2"))
327   "core*3")
329 (define_insn_reservation "store3" 4
330   (and (eq_attr "model_wbuf" "no")
331        (eq_attr "type" "store3"))
332   "core*4")
334 (define_insn_reservation "store4" 5
335   (and (eq_attr "model_wbuf" "no")
336        (eq_attr "type" "store4"))
337   "core*5")
339 (define_insn_reservation "store1_ldsched" 1
340   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1"))
341   "core")
343 (define_insn_reservation "load_ldsched_xscale" 3
344   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
345        (eq_attr "is_xscale" "yes"))
346   "core")
348 (define_insn_reservation "load_ldsched" 2
349   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
350        (eq_attr "is_xscale" "no"))
351   "core")
353 (define_insn_reservation "load_or_store" 2
354   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1"))
355   "core*2")
357 (define_insn_reservation "mult" 16
358   (and (eq_attr "ldsched" "no") (eq_attr "type" "mult"))
359   "core*16")
361 (define_insn_reservation "mult_ldsched_strongarm" 3
362   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
363        (eq_attr "type" "mult"))
364   "core*2")
366 (define_insn_reservation "mult_ldsched" 4
367   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
368        (eq_attr "type" "mult"))
369   "core*4")
371 (define_insn_reservation "multi_cycle" 32
372   (and (eq_attr "core_cycles" "multi")
373        (eq_attr "type" "!mult,load,store1,store2,store3,store4"))
374   "core*32")
376 (define_insn_reservation "single_cycle" 1
377   (eq_attr "core_cycles" "single")
378   "core")
381 ;;---------------------------------------------------------------------------
382 ;; Insn patterns
384 ;; Addition insns.
386 ;; Note: For DImode insns, there is normally no reason why operands should
387 ;; not be in the same register, what we don't want is for something being
388 ;; written to partially overlap something that is an input.
389 ;; Cirrus 64bit additions should not be split because we have a native
390 ;; 64bit addition instructions.
392 (define_expand "adddi3"
393  [(parallel
394    [(set (match_operand:DI           0 "s_register_operand" "")
395           (plus:DI (match_operand:DI 1 "s_register_operand" "")
396                    (match_operand:DI 2 "s_register_operand" "")))
397     (clobber (reg:CC CC_REGNUM))])]
398   "TARGET_EITHER"
399   "
400   if (TARGET_CIRRUS)
401     {
402       if (!cirrus_fp_register (operands[0], DImode))
403         operands[0] = force_reg (DImode, operands[0]);
404       if (!cirrus_fp_register (operands[1], DImode))
405         operands[1] = force_reg (DImode, operands[1]);
406       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
407       DONE;
408     }
410   if (TARGET_THUMB)
411     {
412       if (GET_CODE (operands[1]) != REG)
413         operands[1] = force_reg (SImode, operands[1]);
414       if (GET_CODE (operands[2]) != REG)
415         operands[2] = force_reg (SImode, operands[2]);
416      }
417   "
420 (define_insn "*thumb_adddi3"
421   [(set (match_operand:DI          0 "register_operand" "=l")
422         (plus:DI (match_operand:DI 1 "register_operand" "%0")
423                  (match_operand:DI 2 "register_operand" "l")))
424    (clobber (reg:CC CC_REGNUM))
425   ]
426   "TARGET_THUMB"
427   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
428   [(set_attr "length" "4")]
431 (define_insn_and_split "*arm_adddi3"
432   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
433         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
434                  (match_operand:DI 2 "s_register_operand" "r,  0")))
435    (clobber (reg:CC CC_REGNUM))]
436   "TARGET_ARM && !TARGET_CIRRUS"
437   "#"
438   "TARGET_ARM && reload_completed"
439   [(parallel [(set (reg:CC_C CC_REGNUM)
440                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
441                                  (match_dup 1)))
442               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
443    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
444                                (plus:SI (match_dup 4) (match_dup 5))))]
445   "
446   {
447     operands[3] = gen_highpart (SImode, operands[0]);
448     operands[0] = gen_lowpart (SImode, operands[0]);
449     operands[4] = gen_highpart (SImode, operands[1]);
450     operands[1] = gen_lowpart (SImode, operands[1]);
451     operands[5] = gen_highpart (SImode, operands[2]);
452     operands[2] = gen_lowpart (SImode, operands[2]);
453   }"
454   [(set_attr "conds" "clob")
455    (set_attr "length" "8")]
458 (define_insn_and_split "*adddi_sesidi_di"
459   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
460         (plus:DI (sign_extend:DI
461                   (match_operand:SI 2 "s_register_operand" "r,r"))
462                  (match_operand:DI 1 "s_register_operand" "r,0")))
463    (clobber (reg:CC CC_REGNUM))]
464   "TARGET_ARM && !TARGET_CIRRUS"
465   "#"
466   "TARGET_ARM && reload_completed"
467   [(parallel [(set (reg:CC_C CC_REGNUM)
468                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
469                                  (match_dup 1)))
470               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
471    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
472                                (plus:SI (ashiftrt:SI (match_dup 2)
473                                                      (const_int 31))
474                                         (match_dup 4))))]
475   "
476   {
477     operands[3] = gen_highpart (SImode, operands[0]);
478     operands[0] = gen_lowpart (SImode, operands[0]);
479     operands[4] = gen_highpart (SImode, operands[1]);
480     operands[1] = gen_lowpart (SImode, operands[1]);
481     operands[2] = gen_lowpart (SImode, operands[2]);
482   }"
483   [(set_attr "conds" "clob")
484    (set_attr "length" "8")]
487 (define_insn_and_split "*adddi_zesidi_di"
488   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
489         (plus:DI (zero_extend:DI
490                   (match_operand:SI 2 "s_register_operand" "r,r"))
491                  (match_operand:DI 1 "s_register_operand" "r,0")))
492    (clobber (reg:CC CC_REGNUM))]
493   "TARGET_ARM && !TARGET_CIRRUS"
494   "#"
495   "TARGET_ARM && reload_completed"
496   [(parallel [(set (reg:CC_C CC_REGNUM)
497                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
498                                  (match_dup 1)))
499               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
500    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
501                                (plus:SI (match_dup 4) (const_int 0))))]
502   "
503   {
504     operands[3] = gen_highpart (SImode, operands[0]);
505     operands[0] = gen_lowpart (SImode, operands[0]);
506     operands[4] = gen_highpart (SImode, operands[1]);
507     operands[1] = gen_lowpart (SImode, operands[1]);
508     operands[2] = gen_lowpart (SImode, operands[2]);
509   }"
510   [(set_attr "conds" "clob")
511    (set_attr "length" "8")]
514 (define_expand "addsi3"
515   [(set (match_operand:SI          0 "s_register_operand" "")
516         (plus:SI (match_operand:SI 1 "s_register_operand" "")
517                  (match_operand:SI 2 "reg_or_int_operand" "")))]
518   "TARGET_EITHER"
519   "
520   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
521     {
522       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
523                           operands[1],
524                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
525       DONE;
526     }
527   "
530 ; If there is a scratch available, this will be faster than synthesizing the
531 ; addition.
532 (define_peephole2
533   [(match_scratch:SI 3 "r")
534    (set (match_operand:SI          0 "s_register_operand" "")
535         (plus:SI (match_operand:SI 1 "s_register_operand" "")
536                  (match_operand:SI 2 "const_int_operand"  "")))]
537   "TARGET_ARM &&
538    !(const_ok_for_arm (INTVAL (operands[2]))
539      || const_ok_for_arm (-INTVAL (operands[2])))
540     && const_ok_for_arm (~INTVAL (operands[2]))"
541   [(set (match_dup 3) (match_dup 2))
542    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
543   ""
546 (define_insn_and_split "*arm_addsi3"
547   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
548         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
549                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
550   "TARGET_ARM"
551   "@
552    add%?\\t%0, %1, %2
553    sub%?\\t%0, %1, #%n2
554    #"
555   "TARGET_ARM &&
556    GET_CODE (operands[2]) == CONST_INT
557    && !(const_ok_for_arm (INTVAL (operands[2]))
558         || const_ok_for_arm (-INTVAL (operands[2])))"
559   [(clobber (const_int 0))]
560   "
561   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
562                       operands[1], 0);
563   DONE;
564   "
565   [(set_attr "length" "4,4,16")
566    (set_attr "predicable" "yes")]
569 ;; Register group 'k' is a single register group containing only the stack
570 ;; register.  Trying to reload it will always fail catastrophically,
571 ;; so never allow those alternatives to match if reloading is needed.
573 (define_insn "*thumb_addsi3"
574   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
575         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
576                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
577   "TARGET_THUMB"
578   "*
579    static const char * const asms[] = 
580    {
581      \"add\\t%0, %0, %2\",
582      \"sub\\t%0, %0, #%n2\",
583      \"add\\t%0, %1, %2\",
584      \"add\\t%0, %0, %2\",
585      \"add\\t%0, %0, %2\",
586      \"add\\t%0, %1, %2\",
587      \"add\\t%0, %1, %2\"
588    };
589    if ((which_alternative == 2 || which_alternative == 6)
590        && GET_CODE (operands[2]) == CONST_INT
591        && INTVAL (operands[2]) < 0)
592      return \"sub\\t%0, %1, #%n2\";
593    return asms[which_alternative];
594   "
595   [(set_attr "length" "2")]
598 ;; Reloading and elimination of the frame pointer can
599 ;; sometimes cause this optimization to be missed.
600 (define_peephole2
601   [(set (match_operand:SI 0 "register_operand" "")
602         (match_operand:SI 1 "const_int_operand" ""))
603    (set (match_dup 0)
604         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
605   "TARGET_THUMB
606    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
607    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
608    && (INTVAL (operands[1]) & 3) == 0"
609   [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
610   ""
613 (define_insn "*addsi3_compare0"
614   [(set (reg:CC_NOOV CC_REGNUM)
615         (compare:CC_NOOV
616          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
617                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
618          (const_int 0)))
619    (set (match_operand:SI 0 "s_register_operand" "=r,r")
620         (plus:SI (match_dup 1) (match_dup 2)))]
621   "TARGET_ARM"
622   "@
623    add%?s\\t%0, %1, %2
624    sub%?s\\t%0, %1, #%n2"
625   [(set_attr "conds" "set")]
628 (define_insn "*addsi3_compare0_scratch"
629   [(set (reg:CC_NOOV CC_REGNUM)
630         (compare:CC_NOOV
631          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
632                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
633          (const_int 0)))]
634   "TARGET_ARM"
635   "@
636    cmn%?\\t%0, %1
637    cmp%?\\t%0, #%n1"
638   [(set_attr "conds" "set")]
641 ;; These patterns are the same ones as the two regular addsi3_compare0
642 ;; patterns, except we write them slightly different - the combiner
643 ;; tends to generate them this way.
644 (define_insn "*addsi3_compare0_for_combiner"
645   [(set (reg:CC CC_REGNUM)
646         (compare:CC
647          (match_operand:SI 1 "s_register_operand" "r,r")
648          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
649    (set (match_operand:SI 0 "s_register_operand" "=r,r")
650         (plus:SI (match_dup 1) (match_dup 2)))]
651   "TARGET_ARM"
652   "@
653    add%?s\\t%0, %1, %2
654    sub%?s\\t%0, %1, #%n2"
655   [(set_attr "conds" "set")]
658 (define_insn "*addsi3_compare0_scratch_for_combiner"
659   [(set (reg:CC CC_REGNUM)
660         (compare:CC
661          (match_operand:SI 0 "s_register_operand" "r,r")
662          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
663   "TARGET_ARM"
664   "@
665    cmn%?\\t%0, %1
666    cmp%?\\t%0, #%n1"
667   [(set_attr "conds" "set")]
670 ;; The next four insns work because they compare the result with one of
671 ;; the operands, and we know that the use of the condition code is
672 ;; either GEU or LTU, so we can use the carry flag from the addition
673 ;; instead of doing the compare a second time.
674 (define_insn "*addsi3_compare_op1"
675   [(set (reg:CC_C CC_REGNUM)
676         (compare:CC_C
677          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
678                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
679          (match_dup 1)))
680    (set (match_operand:SI 0 "s_register_operand" "=r,r")
681         (plus:SI (match_dup 1) (match_dup 2)))]
682   "TARGET_ARM"
683   "@
684    add%?s\\t%0, %1, %2
685    sub%?s\\t%0, %1, #%n2"
686   [(set_attr "conds" "set")]
689 (define_insn "*addsi3_compare_op2"
690   [(set (reg:CC_C CC_REGNUM)
691         (compare:CC_C
692          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
693                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
694          (match_dup 2)))
695    (set (match_operand:SI 0 "s_register_operand" "=r,r")
696         (plus:SI (match_dup 1) (match_dup 2)))]
697   "TARGET_ARM"
698   "@
699    add%?s\\t%0, %1, %2
700    sub%?s\\t%0, %1, #%n2"
701   [(set_attr "conds" "set")]
704 (define_insn "*compare_addsi2_op0"
705   [(set (reg:CC_C CC_REGNUM)
706         (compare:CC_C
707          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
708                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
709          (match_dup 0)))]
710   "TARGET_ARM"
711   "@
712    cmn%?\\t%0, %1
713    cmp%?\\t%0, #%n1"
714   [(set_attr "conds" "set")]
717 (define_insn "*compare_addsi2_op1"
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 1)))]
723   "TARGET_ARM"
724   "@
725    cmn%?\\t%0, %1
726    cmp%?\\t%0, #%n1"
727   [(set_attr "conds" "set")]
730 (define_insn "*addsi3_carryin"
731   [(set (match_operand:SI 0 "s_register_operand" "=r")
732         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
733                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
734                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
735   "TARGET_ARM"
736   "adc%?\\t%0, %1, %2"
737   [(set_attr "conds" "use")]
740 (define_insn "*addsi3_carryin_shift"
741   [(set (match_operand:SI 0 "s_register_operand" "")
742         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
743                  (plus:SI
744                    (match_operator:SI 2 "shift_operator"
745                       [(match_operand:SI 3 "s_register_operand" "")
746                        (match_operand:SI 4 "reg_or_int_operand" "")])
747                     (match_operand:SI 1 "s_register_operand" ""))))]
748   "TARGET_ARM"
749   "adc%?\\t%0, %1, %3%S2"
750   [(set_attr "conds" "use")]
753 (define_insn "*addsi3_carryin_alt1"
754   [(set (match_operand:SI 0 "s_register_operand" "=r")
755         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
756                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
757                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
758   "TARGET_ARM"
759   "adc%?\\t%0, %1, %2"
760   [(set_attr "conds" "use")]
763 (define_insn "*addsi3_carryin_alt2"
764   [(set (match_operand:SI 0 "s_register_operand" "=r")
765         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
766                           (match_operand:SI 1 "s_register_operand" "r"))
767                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
768   "TARGET_ARM"
769   "adc%?\\t%0, %1, %2"
770   [(set_attr "conds" "use")]
773 (define_insn "*addsi3_carryin_alt3"
774   [(set (match_operand:SI 0 "s_register_operand" "=r")
775         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
776                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
777                  (match_operand:SI 1 "s_register_operand" "r")))]
778   "TARGET_ARM"
779   "adc%?\\t%0, %1, %2"
780   [(set_attr "conds" "use")]
783 (define_insn "incscc"
784   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
785         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
786                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
787                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
788   "TARGET_ARM"
789   "@
790   add%d2\\t%0, %1, #1
791   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
792   [(set_attr "conds" "use")
793    (set_attr "length" "4,8")]
796 (define_expand "addsf3"
797   [(set (match_operand:SF          0 "s_register_operand" "")
798         (plus:SF (match_operand:SF 1 "s_register_operand" "")
799                  (match_operand:SF 2 "fpa_add_operand" "")))]
800   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
801   "
802   if (TARGET_CIRRUS
803       && !cirrus_fp_register (operands[2], SFmode))
804     operands[2] = force_reg (SFmode, operands[2]);
807 (define_expand "adddf3"
808   [(set (match_operand:DF          0 "s_register_operand" "")
809         (plus:DF (match_operand:DF 1 "s_register_operand" "")
810                  (match_operand:DF 2 "fpa_add_operand" "")))]
811   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
812   "
813   if (TARGET_CIRRUS
814       && !cirrus_fp_register (operands[2], DFmode))
815     operands[2] = force_reg (DFmode, operands[2]);
818 (define_expand "subdi3"
819  [(parallel
820    [(set (match_operand:DI            0 "s_register_operand" "")
821           (minus:DI (match_operand:DI 1 "s_register_operand" "")
822                     (match_operand:DI 2 "s_register_operand" "")))
823     (clobber (reg:CC CC_REGNUM))])]
824   "TARGET_EITHER"
825   "
826   if (TARGET_CIRRUS
827       && TARGET_ARM
828       && cirrus_fp_register (operands[0], DImode)
829       && cirrus_fp_register (operands[1], DImode))
830     {
831       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
832       DONE;
833     }
835   if (TARGET_THUMB)
836     {
837       if (GET_CODE (operands[1]) != REG)
838         operands[1] = force_reg (SImode, operands[1]);
839       if (GET_CODE (operands[2]) != REG)
840         operands[2] = force_reg (SImode, operands[2]);
841      }  
842   "
845 (define_insn "*arm_subdi3"
846   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
847         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
848                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
849    (clobber (reg:CC CC_REGNUM))]
850   "TARGET_ARM"
851   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
852   [(set_attr "conds" "clob")
853    (set_attr "length" "8")]
856 (define_insn "*thumb_subdi3"
857   [(set (match_operand:DI           0 "register_operand" "=l")
858         (minus:DI (match_operand:DI 1 "register_operand"  "0")
859                   (match_operand:DI 2 "register_operand"  "l")))
860    (clobber (reg:CC CC_REGNUM))]
861   "TARGET_THUMB"
862   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
863   [(set_attr "length" "4")]
866 (define_insn "*subdi_di_zesidi"
867   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
868         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
869                   (zero_extend:DI
870                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
871    (clobber (reg:CC CC_REGNUM))]
872   "TARGET_ARM"
873   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
874   [(set_attr "conds" "clob")
875    (set_attr "length" "8")]
878 (define_insn "*subdi_di_sesidi"
879   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
880         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
881                   (sign_extend:DI
882                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
883    (clobber (reg:CC CC_REGNUM))]
884   "TARGET_ARM"
885   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
886   [(set_attr "conds" "clob")
887    (set_attr "length" "8")]
890 (define_insn "*subdi_zesidi_di"
891   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
892         (minus:DI (zero_extend:DI
893                    (match_operand:SI 2 "s_register_operand"  "r,r"))
894                   (match_operand:DI  1 "s_register_operand" "?r,0")))
895    (clobber (reg:CC CC_REGNUM))]
896   "TARGET_ARM"
897   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
898   [(set_attr "conds" "clob")
899    (set_attr "length" "8")]
902 (define_insn "*subdi_sesidi_di"
903   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
904         (minus:DI (sign_extend:DI
905                    (match_operand:SI 2 "s_register_operand"   "r,r"))
906                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
907    (clobber (reg:CC CC_REGNUM))]
908   "TARGET_ARM"
909   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
910   [(set_attr "conds" "clob")
911    (set_attr "length" "8")]
914 (define_insn "*subdi_zesidi_zesidi"
915   [(set (match_operand:DI            0 "s_register_operand" "=r")
916         (minus:DI (zero_extend:DI
917                    (match_operand:SI 1 "s_register_operand"  "r"))
918                   (zero_extend:DI
919                    (match_operand:SI 2 "s_register_operand"  "r"))))
920    (clobber (reg:CC CC_REGNUM))]
921   "TARGET_ARM"
922   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
923   [(set_attr "conds" "clob")
924    (set_attr "length" "8")]
927 (define_expand "subsi3"
928   [(set (match_operand:SI           0 "s_register_operand" "")
929         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
930                   (match_operand:SI 2 "s_register_operand" "")))]
931   "TARGET_EITHER"
932   "
933   if (GET_CODE (operands[1]) == CONST_INT)
934     {
935       if (TARGET_ARM)
936         {
937           arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
938                               operands[2],
939                               (no_new_pseudos ? 0
940                                :  preserve_subexpressions_p ()));
941           DONE;
942         }
943       else /* TARGET_THUMB */
944         operands[1] = force_reg (SImode, operands[1]);
945     }
946   "
949 (define_insn "*thumb_subsi3_insn"
950   [(set (match_operand:SI           0 "register_operand" "=l")
951         (minus:SI (match_operand:SI 1 "register_operand" "l")
952                   (match_operand:SI 2 "register_operand" "l")))]
953   "TARGET_THUMB"
954   "sub\\t%0, %1, %2"
955   [(set_attr "length" "2")]
958 (define_insn_and_split "*arm_subsi3_insn"
959   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
960         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
961                   (match_operand:SI 2 "s_register_operand" "r,r")))]
962   "TARGET_ARM"
963   "@
964    rsb%?\\t%0, %2, %1
965    #"
966   "TARGET_ARM
967    && GET_CODE (operands[1]) == CONST_INT
968    && !const_ok_for_arm (INTVAL (operands[1]))"
969   [(clobber (const_int 0))]
970   "
971   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
972                       operands[2], 0);
973   DONE;
974   "
975   [(set_attr "length" "4,16")
976    (set_attr "predicable" "yes")]
979 (define_peephole2
980   [(match_scratch:SI 3 "r")
981    (set (match_operand:SI           0 "s_register_operand" "")
982         (minus:SI (match_operand:SI 1 "const_int_operand" "")
983                   (match_operand:SI 2 "s_register_operand" "")))]
984   "TARGET_ARM
985    && !const_ok_for_arm (INTVAL (operands[1]))
986    && const_ok_for_arm (~INTVAL (operands[1]))"
987   [(set (match_dup 3) (match_dup 1))
988    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
989   ""
992 (define_insn "*subsi3_compare0"
993   [(set (reg:CC_NOOV CC_REGNUM)
994         (compare:CC_NOOV
995          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
996                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
997          (const_int 0)))
998    (set (match_operand:SI 0 "s_register_operand" "=r,r")
999         (minus:SI (match_dup 1) (match_dup 2)))]
1000   "TARGET_ARM"
1001   "@
1002    sub%?s\\t%0, %1, %2
1003    rsb%?s\\t%0, %2, %1"
1004   [(set_attr "conds" "set")]
1007 (define_insn "decscc"
1008   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1009         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1010                   (match_operator:SI 2 "arm_comparison_operator"
1011                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1012   "TARGET_ARM"
1013   "@
1014    sub%d2\\t%0, %1, #1
1015    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1016   [(set_attr "conds" "use")
1017    (set_attr "length" "*,8")]
1020 (define_expand "subsf3"
1021   [(set (match_operand:SF           0 "s_register_operand" "")
1022         (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1023                   (match_operand:SF 2 "fpa_rhs_operand" "")))]
1024   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1025   "
1026   if (TARGET_CIRRUS)
1027     {
1028       if (!cirrus_fp_register (operands[1], SFmode))
1029         operands[1] = force_reg (SFmode, operands[1]);
1030       if (!cirrus_fp_register (operands[2], SFmode))
1031         operands[2] = force_reg (SFmode, operands[2]);
1032     }
1035 (define_expand "subdf3"
1036   [(set (match_operand:DF           0 "s_register_operand" "")
1037         (minus:DF (match_operand:DF 1 "fpa_rhs_operand"     "")
1038                   (match_operand:DF 2 "fpa_rhs_operand"    "")))]
1039   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1040   "
1041   if (TARGET_CIRRUS)
1042     {
1043        if (!cirrus_fp_register (operands[1], DFmode))
1044          operands[1] = force_reg (DFmode, operands[1]);
1045        if (!cirrus_fp_register (operands[2], DFmode))
1046          operands[2] = force_reg (DFmode, operands[2]);
1047     }
1051 ;; Multiplication insns
1053 (define_expand "mulsi3"
1054   [(set (match_operand:SI          0 "s_register_operand" "")
1055         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1056                  (match_operand:SI 1 "s_register_operand" "")))]
1057   "TARGET_EITHER"
1058   ""
1061 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1062 (define_insn "*arm_mulsi3"
1063   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1064         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1065                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1066   "TARGET_ARM"
1067   "mul%?\\t%0, %2, %1"
1068   [(set_attr "type" "mult")
1069    (set_attr "predicable" "yes")]
1072 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1073 ; 1 and 2; are the same, because reload will make operand 0 match 
1074 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1075 ; this by adding another alternative to match this case, and then `reload' 
1076 ; it ourselves.  This alternative must come first.
1077 (define_insn "*thumb_mulsi3"
1078   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1079         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1080                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1081   "TARGET_THUMB"
1082   "*
1083   if (which_alternative < 2)
1084     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1085   else
1086     return \"mul\\t%0, %0, %2\";
1087   "
1088   [(set_attr "length" "4,4,2")
1089    (set_attr "type" "mult")]
1092 (define_insn "*mulsi3_compare0"
1093   [(set (reg:CC_NOOV CC_REGNUM)
1094         (compare:CC_NOOV (mult:SI
1095                           (match_operand:SI 2 "s_register_operand" "r,r")
1096                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1097                          (const_int 0)))
1098    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1099         (mult:SI (match_dup 2) (match_dup 1)))]
1100   "TARGET_ARM && !arm_arch_xscale"
1101   "mul%?s\\t%0, %2, %1"
1102   [(set_attr "conds" "set")
1103    (set_attr "type" "mult")]
1106 (define_insn "*mulsi_compare0_scratch"
1107   [(set (reg:CC_NOOV CC_REGNUM)
1108         (compare:CC_NOOV (mult:SI
1109                           (match_operand:SI 2 "s_register_operand" "r,r")
1110                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1111                          (const_int 0)))
1112    (clobber (match_scratch:SI 0 "=&r,&r"))]
1113   "TARGET_ARM && !arm_arch_xscale"
1114   "mul%?s\\t%0, %2, %1"
1115   [(set_attr "conds" "set")
1116    (set_attr "type" "mult")]
1119 ;; Unnamed templates to match MLA instruction.
1121 (define_insn "*mulsi3addsi"
1122   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1123         (plus:SI
1124           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1125                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1126           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1127   "TARGET_ARM"
1128   "mla%?\\t%0, %2, %1, %3"
1129   [(set_attr "type" "mult")
1130    (set_attr "predicable" "yes")]
1133 (define_insn "*mulsi3addsi_compare0"
1134   [(set (reg:CC_NOOV CC_REGNUM)
1135         (compare:CC_NOOV
1136          (plus:SI (mult:SI
1137                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1138                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1139                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1140          (const_int 0)))
1141    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1142         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1143                  (match_dup 3)))]
1144   "TARGET_ARM && !arm_arch_xscale"
1145   "mla%?s\\t%0, %2, %1, %3"
1146   [(set_attr "conds" "set")
1147    (set_attr "type" "mult")]
1150 (define_insn "*mulsi3addsi_compare0_scratch"
1151   [(set (reg:CC_NOOV CC_REGNUM)
1152         (compare:CC_NOOV
1153          (plus:SI (mult:SI
1154                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1155                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1156                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1157          (const_int 0)))
1158    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1159   "TARGET_ARM && !arm_arch_xscale"
1160   "mla%?s\\t%0, %2, %1, %3"
1161   [(set_attr "conds" "set")
1162    (set_attr "type" "mult")]
1165 ;; Unnamed template to match long long multiply-accumlate (smlal)
1167 (define_insn "*mulsidi3adddi"
1168   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1169         (plus:DI
1170          (mult:DI
1171           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1172           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1173          (match_operand:DI 1 "s_register_operand" "0")))]
1174   "TARGET_ARM && arm_fast_multiply"
1175   "smlal%?\\t%Q0, %R0, %3, %2"
1176   [(set_attr "type" "mult")
1177    (set_attr "predicable" "yes")]
1180 (define_insn "mulsidi3"
1181   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1182         (mult:DI
1183          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1184          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1185   "TARGET_ARM && arm_fast_multiply"
1186   "smull%?\\t%Q0, %R0, %1, %2"
1187   [(set_attr "type" "mult")
1188    (set_attr "predicable" "yes")]
1191 (define_insn "umulsidi3"
1192   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1193         (mult:DI
1194          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1196   "TARGET_ARM && arm_fast_multiply"
1197   "umull%?\\t%Q0, %R0, %1, %2"
1198   [(set_attr "type" "mult")
1199    (set_attr "predicable" "yes")]
1202 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1204 (define_insn "*umulsidi3adddi"
1205   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1206         (plus:DI
1207          (mult:DI
1208           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1209           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1210          (match_operand:DI 1 "s_register_operand" "0")))]
1211   "TARGET_ARM && arm_fast_multiply"
1212   "umlal%?\\t%Q0, %R0, %3, %2"
1213   [(set_attr "type" "mult")
1214    (set_attr "predicable" "yes")]
1217 (define_insn "smulsi3_highpart"
1218   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1219         (truncate:SI
1220          (lshiftrt:DI
1221           (mult:DI
1222            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1223            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1224           (const_int 32))))
1225    (clobber (match_scratch:SI 3 "=&r,&r"))]
1226   "TARGET_ARM && arm_fast_multiply"
1227   "smull%?\\t%3, %0, %2, %1"
1228   [(set_attr "type" "mult")
1229    (set_attr "predicable" "yes")]
1232 (define_insn "umulsi3_highpart"
1233   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1234         (truncate:SI
1235          (lshiftrt:DI
1236           (mult:DI
1237            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1238            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1239           (const_int 32))))
1240    (clobber (match_scratch:SI 3 "=&r,&r"))]
1241   "TARGET_ARM && arm_fast_multiply"
1242   "umull%?\\t%3, %0, %2, %1"
1243   [(set_attr "type" "mult")
1244    (set_attr "predicable" "yes")]
1247 (define_insn "mulhisi3"
1248   [(set (match_operand:SI 0 "s_register_operand" "=r")
1249         (mult:SI (sign_extend:SI
1250                   (match_operand:HI 1 "s_register_operand" "%r"))
1251                  (sign_extend:SI
1252                   (match_operand:HI 2 "s_register_operand" "r"))))]
1253   "TARGET_ARM && arm_arch5e"
1254   "smulbb%?\\t%0, %1, %2"
1255   [(set_attr "type" "mult")
1256    (set_attr "predicable" "yes")]
1259 (define_insn "*mulhisi3tb"
1260   [(set (match_operand:SI 0 "s_register_operand" "=r")
1261         (mult:SI (ashiftrt:SI
1262                   (match_operand:SI 1 "s_register_operand" "r")
1263                   (const_int 16))
1264                  (sign_extend:SI
1265                   (match_operand:HI 2 "s_register_operand" "r"))))]
1266   "TARGET_ARM && arm_arch5e"
1267   "smultb%?\\t%0, %1, %2"
1268   [(set_attr "type" "mult")
1269    (set_attr "predicable" "yes")]
1272 (define_insn "*mulhisi3bt"
1273   [(set (match_operand:SI 0 "s_register_operand" "=r")
1274         (mult:SI (sign_extend:SI
1275                   (match_operand:HI 1 "s_register_operand" "r"))
1276                  (ashiftrt:SI
1277                   (match_operand:SI 2 "s_register_operand" "r")
1278                   (const_int 16))))]
1279   "TARGET_ARM && arm_arch5e"
1280   "smulbt%?\\t%0, %1, %2"
1281   [(set_attr "type" "mult")
1282    (set_attr "predicable" "yes")]
1285 (define_insn "*mulhisi3tt"
1286   [(set (match_operand:SI 0 "s_register_operand" "=r")
1287         (mult:SI (ashiftrt:SI
1288                   (match_operand:SI 1 "s_register_operand" "r")
1289                   (const_int 16))
1290                  (ashiftrt:SI
1291                   (match_operand:SI 2 "s_register_operand" "r")
1292                   (const_int 16))))]
1293   "TARGET_ARM && arm_arch5e"
1294   "smultt%?\\t%0, %1, %2"
1295   [(set_attr "type" "mult")
1296    (set_attr "predicable" "yes")]
1299 (define_insn "*mulhisi3addsi"
1300   [(set (match_operand:SI 0 "s_register_operand" "=r")
1301         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1302                  (mult:SI (sign_extend:SI
1303                            (match_operand:HI 2 "s_register_operand" "%r"))
1304                           (sign_extend:SI
1305                            (match_operand:HI 3 "s_register_operand" "r")))))]
1306   "TARGET_ARM && arm_arch5e"
1307   "smlabb%?\\t%0, %2, %3, %1"
1308   [(set_attr "type" "mult")
1309    (set_attr "predicable" "yes")]
1312 (define_insn "*mulhidi3adddi"
1313   [(set (match_operand:DI 0 "s_register_operand" "=r")
1314         (plus:DI
1315           (match_operand:DI 1 "s_register_operand" "0")
1316           (mult:DI (sign_extend:DI
1317                     (match_operand:HI 2 "s_register_operand" "%r"))
1318                    (sign_extend:DI
1319                     (match_operand:HI 3 "s_register_operand" "r")))))]
1320   "TARGET_ARM && arm_arch5e"
1321   "smlalbb%?\\t%Q0, %R0, %2, %3"
1322   [(set_attr "type" "mult")
1323    (set_attr "predicable" "yes")])
1325 (define_expand "mulsf3"
1326   [(set (match_operand:SF          0 "s_register_operand" "")
1327         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1328                  (match_operand:SF 2 "fpa_rhs_operand" "")))]
1329   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1330   "
1331   if (TARGET_CIRRUS
1332       && !cirrus_fp_register (operands[2], SFmode))
1333     operands[2] = force_reg (SFmode, operands[2]);
1336 (define_expand "muldf3"
1337   [(set (match_operand:DF          0 "s_register_operand" "")
1338         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1339                  (match_operand:DF 2 "fpa_rhs_operand" "")))]
1340   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1341   "
1342   if (TARGET_CIRRUS
1343       && !cirrus_fp_register (operands[2], DFmode))
1344     operands[2] = force_reg (DFmode, operands[2]);
1347 ;; Division insns
1349 (define_expand "divsf3"
1350   [(set (match_operand:SF 0 "s_register_operand" "")
1351         (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1352                 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1353   "TARGET_ARM && TARGET_HARD_FLOAT"
1354   "")
1356 (define_expand "divdf3"
1357   [(set (match_operand:DF 0 "s_register_operand" "")
1358         (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1359                 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1360   "TARGET_ARM && TARGET_HARD_FLOAT"
1361   "")
1363 ;; Modulo insns
1365 (define_expand "modsf3"
1366   [(set (match_operand:SF 0 "s_register_operand" "")
1367         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1368                 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1369   "TARGET_ARM && TARGET_HARD_FLOAT"
1370   "")
1372 (define_expand "moddf3"
1373   [(set (match_operand:DF 0 "s_register_operand" "")
1374         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1375                 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1376   "TARGET_ARM && TARGET_HARD_FLOAT"
1377   "")
1379 ;; Boolean and,ior,xor insns
1381 ;; Split up double word logical operations
1383 ;; Split up simple DImode logical operations.  Simply perform the logical
1384 ;; operation on the upper and lower halves of the registers.
1385 (define_split
1386   [(set (match_operand:DI 0 "s_register_operand" "")
1387         (match_operator:DI 6 "logical_binary_operator"
1388           [(match_operand:DI 1 "s_register_operand" "")
1389            (match_operand:DI 2 "s_register_operand" "")]))]
1390   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1391   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1392    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1393   "
1394   {
1395     operands[3] = gen_highpart (SImode, operands[0]);
1396     operands[0] = gen_lowpart (SImode, operands[0]);
1397     operands[4] = gen_highpart (SImode, operands[1]);
1398     operands[1] = gen_lowpart (SImode, operands[1]);
1399     operands[5] = gen_highpart (SImode, operands[2]);
1400     operands[2] = gen_lowpart (SImode, operands[2]);
1401   }"
1404 (define_split
1405   [(set (match_operand:DI 0 "s_register_operand" "")
1406         (match_operator:DI 6 "logical_binary_operator"
1407           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1408            (match_operand:DI 1 "s_register_operand" "")]))]
1409   "TARGET_ARM && reload_completed"
1410   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1411    (set (match_dup 3) (match_op_dup:SI 6
1412                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1413                          (match_dup 4)]))]
1414   "
1415   {
1416     operands[3] = gen_highpart (SImode, operands[0]);
1417     operands[0] = gen_lowpart (SImode, operands[0]);
1418     operands[4] = gen_highpart (SImode, operands[1]);
1419     operands[1] = gen_lowpart (SImode, operands[1]);
1420     operands[5] = gen_highpart (SImode, operands[2]);
1421     operands[2] = gen_lowpart (SImode, operands[2]);
1422   }"
1425 ;; The zero extend of operand 2 means we can just copy the high part of
1426 ;; operand1 into operand0.
1427 (define_split
1428   [(set (match_operand:DI 0 "s_register_operand" "")
1429         (ior:DI
1430           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1431           (match_operand:DI 1 "s_register_operand" "")))]
1432   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1433   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1434    (set (match_dup 3) (match_dup 4))]
1435   "
1436   {
1437     operands[4] = gen_highpart (SImode, operands[1]);
1438     operands[3] = gen_highpart (SImode, operands[0]);
1439     operands[0] = gen_lowpart (SImode, operands[0]);
1440     operands[1] = gen_lowpart (SImode, operands[1]);
1441   }"
1444 ;; The zero extend of operand 2 means we can just copy the high part of
1445 ;; operand1 into operand0.
1446 (define_split
1447   [(set (match_operand:DI 0 "s_register_operand" "")
1448         (xor:DI
1449           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1450           (match_operand:DI 1 "s_register_operand" "")))]
1451   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1452   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1453    (set (match_dup 3) (match_dup 4))]
1454   "
1455   {
1456     operands[4] = gen_highpart (SImode, operands[1]);
1457     operands[3] = gen_highpart (SImode, operands[0]);
1458     operands[0] = gen_lowpart (SImode, operands[0]);
1459     operands[1] = gen_lowpart (SImode, operands[1]);
1460   }"
1463 (define_insn "anddi3"
1464   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1465         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1466                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1467   "TARGET_ARM && ! TARGET_IWMMXT"
1468   "#"
1469   [(set_attr "length" "8")]
1472 (define_insn_and_split "*anddi_zesidi_di"
1473   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1474         (and:DI (zero_extend:DI
1475                  (match_operand:SI 2 "s_register_operand" "r,r"))
1476                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1477   "TARGET_ARM"
1478   "#"
1479   "TARGET_ARM && reload_completed"
1480   ; The zero extend of operand 2 clears the high word of the output
1481   ; operand.
1482   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1483    (set (match_dup 3) (const_int 0))]
1484   "
1485   {
1486     operands[3] = gen_highpart (SImode, operands[0]);
1487     operands[0] = gen_lowpart (SImode, operands[0]);
1488     operands[1] = gen_lowpart (SImode, operands[1]);
1489   }"
1490   [(set_attr "length" "8")]
1493 (define_insn "*anddi_sesdi_di"
1494   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1495         (and:DI (sign_extend:DI
1496                  (match_operand:SI 2 "s_register_operand" "r,r"))
1497                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1498   "TARGET_ARM"
1499   "#"
1500   [(set_attr "length" "8")]
1503 (define_expand "andsi3"
1504   [(set (match_operand:SI         0 "s_register_operand" "")
1505         (and:SI (match_operand:SI 1 "s_register_operand" "")
1506                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1507   "TARGET_EITHER"
1508   "
1509   if (TARGET_ARM)
1510     {
1511       if (GET_CODE (operands[2]) == CONST_INT)
1512         {
1513           arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1514                               operands[1],
1515                               (no_new_pseudos
1516                                ? 0 : preserve_subexpressions_p ()));
1517           DONE;
1518         }
1519     }
1520   else /* TARGET_THUMB */
1521     {
1522       if (GET_CODE (operands[2]) != CONST_INT)
1523         operands[2] = force_reg (SImode, operands[2]);
1524       else
1525         {
1526           int i;
1527           
1528           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1529             {
1530               operands[2] = force_reg (SImode,
1531                                        GEN_INT (~INTVAL (operands[2])));
1532               
1533               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1534               
1535               DONE;
1536             }
1538           for (i = 9; i <= 31; i++)
1539             {
1540               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1541                 {
1542                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1543                                         const0_rtx));
1544                   DONE;
1545                 }
1546               else if ((((HOST_WIDE_INT) 1) << i) - 1
1547                        == ~INTVAL (operands[2]))
1548                 {
1549                   rtx shift = GEN_INT (i);
1550                   rtx reg = gen_reg_rtx (SImode);
1551                 
1552                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1553                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1554                   
1555                   DONE;
1556                 }
1557             }
1559           operands[2] = force_reg (SImode, operands[2]);
1560         }
1561     }
1562   "
1565 (define_insn_and_split "*arm_andsi3_insn"
1566   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1567         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1568                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1569   "TARGET_ARM"
1570   "@
1571    and%?\\t%0, %1, %2
1572    bic%?\\t%0, %1, #%B2
1573    #"
1574   "TARGET_ARM
1575    && GET_CODE (operands[2]) == CONST_INT
1576    && !(const_ok_for_arm (INTVAL (operands[2]))
1577         || const_ok_for_arm (~INTVAL (operands[2])))"
1578   [(clobber (const_int 0))]
1579   "
1580   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1581                        operands[1], 0);
1582   DONE;
1583   "
1584   [(set_attr "length" "4,4,16")
1585    (set_attr "predicable" "yes")]
1588 (define_insn "*thumb_andsi3_insn"
1589   [(set (match_operand:SI         0 "register_operand" "=l")
1590         (and:SI (match_operand:SI 1 "register_operand" "%0")
1591                 (match_operand:SI 2 "register_operand" "l")))]
1592   "TARGET_THUMB"
1593   "and\\t%0, %0, %2"
1594   [(set_attr "length" "2")]
1597 (define_insn "*andsi3_compare0"
1598   [(set (reg:CC_NOOV CC_REGNUM)
1599         (compare:CC_NOOV
1600          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1601                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1602          (const_int 0)))
1603    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1604         (and:SI (match_dup 1) (match_dup 2)))]
1605   "TARGET_ARM"
1606   "@
1607    and%?s\\t%0, %1, %2
1608    bic%?s\\t%0, %1, #%B2"
1609   [(set_attr "conds" "set")]
1612 (define_insn "*andsi3_compare0_scratch"
1613   [(set (reg:CC_NOOV CC_REGNUM)
1614         (compare:CC_NOOV
1615          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1616                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1617          (const_int 0)))
1618    (clobber (match_scratch:SI 2 "=X,r"))]
1619   "TARGET_ARM"
1620   "@
1621    tst%?\\t%0, %1
1622    bic%?s\\t%2, %0, #%B1"
1623   [(set_attr "conds" "set")]
1626 (define_insn "*zeroextractsi_compare0_scratch"
1627   [(set (reg:CC_NOOV CC_REGNUM)
1628         (compare:CC_NOOV (zero_extract:SI
1629                           (match_operand:SI 0 "s_register_operand" "r")
1630                           (match_operand 1 "const_int_operand" "n")
1631                           (match_operand 2 "const_int_operand" "n"))
1632                          (const_int 0)))]
1633   "TARGET_ARM
1634   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1635       && INTVAL (operands[1]) > 0 
1636       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1637       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1638   "*
1639   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1640                          << INTVAL (operands[2]));
1641   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1642   return \"\";
1643   "
1644   [(set_attr "conds" "set")]
1647 (define_insn "*ne_zeroextractsi"
1648   [(set (match_operand:SI 0 "s_register_operand" "=r")
1649         (ne:SI (zero_extract:SI
1650                 (match_operand:SI 1 "s_register_operand" "r")
1651                 (match_operand:SI 2 "const_int_operand" "n")
1652                 (match_operand:SI 3 "const_int_operand" "n"))
1653                (const_int 0)))
1654    (clobber (reg:CC CC_REGNUM))]
1655   "TARGET_ARM
1656    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1657        && INTVAL (operands[2]) > 0 
1658        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1659        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1660   "*
1661   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1662                          << INTVAL (operands[3]));
1663   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1664   return \"movne\\t%0, #1\";
1665   "
1666   [(set_attr "conds" "clob")
1667    (set_attr "length" "8")]
1670 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1671 ;;; represented by the bitfield, then this will produce incorrect results.
1672 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1673 ;;; which have a real bit-field insert instruction, the truncation happens
1674 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1675 ;;; bit-field insert instruction, we would have to emit code here to truncate
1676 ;;; the value before we insert.  This loses some of the advantage of having
1677 ;;; this insv pattern, so this pattern needs to be reevalutated.
1679 (define_expand "insv"
1680   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1681                          (match_operand:SI 1 "general_operand" "")
1682                          (match_operand:SI 2 "general_operand" ""))
1683         (match_operand:SI 3 "reg_or_int_operand" ""))]
1684   "TARGET_ARM"
1685   "
1686   {
1687     int start_bit = INTVAL (operands[2]);
1688     int width = INTVAL (operands[1]);
1689     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1690     rtx target, subtarget;
1692     target = operands[0];
1693     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1694        subreg as the final target.  */
1695     if (GET_CODE (target) == SUBREG)
1696       {
1697         subtarget = gen_reg_rtx (SImode);
1698         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1699             < GET_MODE_SIZE (SImode))
1700           target = SUBREG_REG (target);
1701       }
1702     else
1703       subtarget = target;    
1705     if (GET_CODE (operands[3]) == CONST_INT)
1706       {
1707         /* Since we are inserting a known constant, we may be able to
1708            reduce the number of bits that we have to clear so that
1709            the mask becomes simple.  */
1710         /* ??? This code does not check to see if the new mask is actually
1711            simpler.  It may not be.  */
1712         rtx op1 = gen_reg_rtx (SImode);
1713         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1714            start of this pattern.  */
1715         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1716         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1718         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1719         emit_insn (gen_iorsi3 (subtarget, op1,
1720                                GEN_INT (op3_value << start_bit)));
1721       }
1722     else if (start_bit == 0
1723              && !(const_ok_for_arm (mask)
1724                   || const_ok_for_arm (~mask)))
1725       {
1726         /* A Trick, since we are setting the bottom bits in the word,
1727            we can shift operand[3] up, operand[0] down, OR them together
1728            and rotate the result back again.  This takes 3 insns, and
1729            the third might be mergable into another op.  */
1730         /* The shift up copes with the possibility that operand[3] is
1731            wider than the bitfield.  */
1732         rtx op0 = gen_reg_rtx (SImode);
1733         rtx op1 = gen_reg_rtx (SImode);
1735         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1736         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1737         emit_insn (gen_iorsi3  (op1, op1, op0));
1738         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1739       }
1740     else if ((width + start_bit == 32)
1741              && !(const_ok_for_arm (mask)
1742                   || const_ok_for_arm (~mask)))
1743       {
1744         /* Similar trick, but slightly less efficient.  */
1746         rtx op0 = gen_reg_rtx (SImode);
1747         rtx op1 = gen_reg_rtx (SImode);
1749         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1750         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1751         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1752         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1753       }
1754     else
1755       {
1756         rtx op0 = GEN_INT (mask);
1757         rtx op1 = gen_reg_rtx (SImode);
1758         rtx op2 = gen_reg_rtx (SImode);
1760         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1761           {
1762             rtx tmp = gen_reg_rtx (SImode);
1764             emit_insn (gen_movsi (tmp, op0));
1765             op0 = tmp;
1766           }
1768         /* Mask out any bits in operand[3] that are not needed.  */
1769            emit_insn (gen_andsi3 (op1, operands[3], op0));
1771         if (GET_CODE (op0) == CONST_INT
1772             && (const_ok_for_arm (mask << start_bit)
1773                 || const_ok_for_arm (~(mask << start_bit))))
1774           {
1775             op0 = GEN_INT (~(mask << start_bit));
1776             emit_insn (gen_andsi3 (op2, operands[0], op0));
1777           }
1778         else
1779           {
1780             if (GET_CODE (op0) == CONST_INT)
1781               {
1782                 rtx tmp = gen_reg_rtx (SImode);
1784                 emit_insn (gen_movsi (tmp, op0));
1785                 op0 = tmp;
1786               }
1788             if (start_bit != 0)
1789               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1790             
1791             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1792           }
1794         if (start_bit != 0)
1795           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1797         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1798       }
1800     if (subtarget != target)
1801       {
1802         /* If TARGET is still a SUBREG, then it must be wider than a word,
1803            so we must be careful only to set the subword we were asked to.  */
1804         if (GET_CODE (target) == SUBREG)
1805           emit_move_insn (target, subtarget);
1806         else
1807           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1808       }
1810     DONE;
1811   }"
1814 ; constants for op 2 will never be given to these patterns.
1815 (define_insn_and_split "*anddi_notdi_di"
1816   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1817         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1818                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1819   "TARGET_ARM"
1820   "#"
1821   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1822   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1823    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1824   "
1825   {
1826     operands[3] = gen_highpart (SImode, operands[0]);
1827     operands[0] = gen_lowpart (SImode, operands[0]);
1828     operands[4] = gen_highpart (SImode, operands[1]);
1829     operands[1] = gen_lowpart (SImode, operands[1]);
1830     operands[5] = gen_highpart (SImode, operands[2]);
1831     operands[2] = gen_lowpart (SImode, operands[2]);
1832   }"
1833   [(set_attr "length" "8")
1834    (set_attr "predicable" "yes")]
1836   
1837 (define_insn_and_split "*anddi_notzesidi_di"
1838   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1839         (and:DI (not:DI (zero_extend:DI
1840                          (match_operand:SI 2 "s_register_operand" "r,r")))
1841                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1842   "TARGET_ARM"
1843   "@
1844    bic%?\\t%Q0, %Q1, %2
1845    #"
1846   ; (not (zero_extend ...)) allows us to just copy the high word from
1847   ; operand1 to operand0.
1848   "TARGET_ARM
1849    && reload_completed
1850    && operands[0] != operands[1]"
1851   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1852    (set (match_dup 3) (match_dup 4))]
1853   "
1854   {
1855     operands[3] = gen_highpart (SImode, operands[0]);
1856     operands[0] = gen_lowpart (SImode, operands[0]);
1857     operands[4] = gen_highpart (SImode, operands[1]);
1858     operands[1] = gen_lowpart (SImode, operands[1]);
1859   }"
1860   [(set_attr "length" "4,8")
1861    (set_attr "predicable" "yes")]
1863   
1864 (define_insn_and_split "*anddi_notsesidi_di"
1865   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1866         (and:DI (not:DI (sign_extend:DI
1867                          (match_operand:SI 2 "s_register_operand" "r,r")))
1868                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1869   "TARGET_ARM"
1870   "#"
1871   "TARGET_ARM && reload_completed"
1872   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1873    (set (match_dup 3) (and:SI (not:SI
1874                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
1875                                (match_dup 4)))]
1876   "
1877   {
1878     operands[3] = gen_highpart (SImode, operands[0]);
1879     operands[0] = gen_lowpart (SImode, operands[0]);
1880     operands[4] = gen_highpart (SImode, operands[1]);
1881     operands[1] = gen_lowpart (SImode, operands[1]);
1882   }"
1883   [(set_attr "length" "8")
1884    (set_attr "predicable" "yes")]
1886   
1887 (define_insn "andsi_notsi_si"
1888   [(set (match_operand:SI 0 "s_register_operand" "=r")
1889         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1890                 (match_operand:SI 1 "s_register_operand" "r")))]
1891   "TARGET_ARM"
1892   "bic%?\\t%0, %1, %2"
1893   [(set_attr "predicable" "yes")]
1896 (define_insn "bicsi3"
1897   [(set (match_operand:SI                 0 "register_operand" "=l")
1898         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1899                 (match_operand:SI         2 "register_operand" "0")))]
1900   "TARGET_THUMB"
1901   "bic\\t%0, %0, %1"
1902   [(set_attr "length" "2")]
1905 (define_insn "andsi_not_shiftsi_si"
1906   [(set (match_operand:SI                   0 "s_register_operand" "=r")
1907         (and:SI (not:SI (match_operator:SI  4 "shift_operator"
1908                          [(match_operand:SI 2 "s_register_operand"  "r")
1909                           (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
1910                 (match_operand:SI           1 "s_register_operand"  "r")))]
1911   "TARGET_ARM"
1912   "bic%?\\t%0, %1, %2%S4"
1913   [(set_attr "predicable" "yes")
1914    (set_attr "shift" "2")
1915    ]
1918 (define_insn "*andsi_notsi_si_compare0"
1919   [(set (reg:CC_NOOV CC_REGNUM)
1920         (compare:CC_NOOV
1921          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1922                  (match_operand:SI 1 "s_register_operand" "r"))
1923          (const_int 0)))
1924    (set (match_operand:SI 0 "s_register_operand" "=r")
1925         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1926   "TARGET_ARM"
1927   "bic%?s\\t%0, %1, %2"
1928   [(set_attr "conds" "set")]
1931 (define_insn "*andsi_notsi_si_compare0_scratch"
1932   [(set (reg:CC_NOOV CC_REGNUM)
1933         (compare:CC_NOOV
1934          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1935                  (match_operand:SI 1 "s_register_operand" "r"))
1936          (const_int 0)))
1937    (clobber (match_scratch:SI 0 "=r"))]
1938   "TARGET_ARM"
1939   "bic%?s\\t%0, %1, %2"
1940   [(set_attr "conds" "set")]
1943 (define_insn "iordi3"
1944   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1945         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1946                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1947   "TARGET_ARM && ! TARGET_IWMMXT"
1948   "#"
1949   [(set_attr "length" "8")
1950    (set_attr "predicable" "yes")]
1953 (define_insn "*iordi_zesidi_di"
1954   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1955         (ior:DI (zero_extend:DI
1956                  (match_operand:SI 2 "s_register_operand" "r,r"))
1957                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1958   "TARGET_ARM"
1959   "@
1960    orr%?\\t%Q0, %Q1, %2
1961    #"
1962   [(set_attr "length" "4,8")
1963    (set_attr "predicable" "yes")]
1966 (define_insn "*iordi_sesidi_di"
1967   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1968         (ior:DI (sign_extend:DI
1969                  (match_operand:SI 2 "s_register_operand" "r,r"))
1970                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1971   "TARGET_ARM"
1972   "#"
1973   [(set_attr "length" "8")
1974    (set_attr "predicable" "yes")]
1977 (define_expand "iorsi3"
1978   [(set (match_operand:SI         0 "s_register_operand" "")
1979         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1980                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1981   "TARGET_EITHER"
1982   "
1983   if (GET_CODE (operands[2]) == CONST_INT)
1984     {
1985       if (TARGET_ARM)
1986         {
1987           arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1988                               operands[1],
1989                               (no_new_pseudos
1990                               ? 0 : preserve_subexpressions_p ()));
1991           DONE;
1992         }
1993       else /* TARGET_THUMB */
1994         operands [2] = force_reg (SImode, operands [2]);
1995     }
1996   "
1999 (define_insn_and_split "*arm_iorsi3"
2000   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2001         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2002                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2003   "TARGET_ARM"
2004   "@
2005    orr%?\\t%0, %1, %2
2006    #"
2007   "TARGET_ARM
2008    && GET_CODE (operands[2]) == CONST_INT
2009    && !const_ok_for_arm (INTVAL (operands[2]))"
2010   [(clobber (const_int 0))]
2011   "
2012   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2013                       operands[1], 0);
2014   DONE;
2015   "
2016   [(set_attr "length" "4,16")
2017    (set_attr "predicable" "yes")]
2020 (define_insn "*thumb_iorsi3"
2021   [(set (match_operand:SI         0 "register_operand" "=l")
2022         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2023                 (match_operand:SI 2 "register_operand" "l")))]
2024   "TARGET_THUMB"
2025   "orr\\t%0, %0, %2"
2026   [(set_attr "length" "2")]
2029 (define_peephole2
2030   [(match_scratch:SI 3 "r")
2031    (set (match_operand:SI         0 "s_register_operand" "")
2032         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2033                 (match_operand:SI 2 "const_int_operand" "")))]
2034   "TARGET_ARM
2035    && !const_ok_for_arm (INTVAL (operands[2]))
2036    && const_ok_for_arm (~INTVAL (operands[2]))"
2037   [(set (match_dup 3) (match_dup 2))
2038    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2039   ""
2042 (define_insn "*iorsi3_compare0"
2043   [(set (reg:CC_NOOV CC_REGNUM)
2044         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2045                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2046                          (const_int 0)))
2047    (set (match_operand:SI 0 "s_register_operand" "=r")
2048         (ior:SI (match_dup 1) (match_dup 2)))]
2049   "TARGET_ARM"
2050   "orr%?s\\t%0, %1, %2"
2051   [(set_attr "conds" "set")]
2054 (define_insn "*iorsi3_compare0_scratch"
2055   [(set (reg:CC_NOOV CC_REGNUM)
2056         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2057                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2058                          (const_int 0)))
2059    (clobber (match_scratch:SI 0 "=r"))]
2060   "TARGET_ARM"
2061   "orr%?s\\t%0, %1, %2"
2062   [(set_attr "conds" "set")]
2065 (define_insn "xordi3"
2066   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2067         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2068                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2069   "TARGET_ARM && !TARGET_IWMMXT"
2070   "#"
2071   [(set_attr "length" "8")
2072    (set_attr "predicable" "yes")]
2075 (define_insn "*xordi_zesidi_di"
2076   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2077         (xor:DI (zero_extend:DI
2078                  (match_operand:SI 2 "s_register_operand" "r,r"))
2079                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2080   "TARGET_ARM"
2081   "@
2082    eor%?\\t%Q0, %Q1, %2
2083    #"
2084   [(set_attr "length" "4,8")
2085    (set_attr "predicable" "yes")]
2088 (define_insn "*xordi_sesidi_di"
2089   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2090         (xor:DI (sign_extend:DI
2091                  (match_operand:SI 2 "s_register_operand" "r,r"))
2092                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2093   "TARGET_ARM"
2094   "#"
2095   [(set_attr "length" "8")
2096    (set_attr "predicable" "yes")]
2099 (define_expand "xorsi3"
2100   [(set (match_operand:SI         0 "s_register_operand" "")
2101         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2102                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2103   "TARGET_EITHER"
2104   "if (TARGET_THUMB)
2105      if (GET_CODE (operands[2]) == CONST_INT)
2106        operands[2] = force_reg (SImode, operands[2]);
2107   "
2110 (define_insn "*arm_xorsi3"
2111   [(set (match_operand:SI         0 "s_register_operand" "=r")
2112         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2113                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2114   "TARGET_ARM"
2115   "eor%?\\t%0, %1, %2"
2116   [(set_attr "predicable" "yes")]
2119 (define_insn "*thumb_xorsi3"
2120   [(set (match_operand:SI         0 "register_operand" "=l")
2121         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2122                 (match_operand:SI 2 "register_operand" "l")))]
2123   "TARGET_THUMB"
2124   "eor\\t%0, %0, %2"
2125   [(set_attr "length" "2")]
2128 (define_insn "*xorsi3_compare0"
2129   [(set (reg:CC_NOOV CC_REGNUM)
2130         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2131                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2132                          (const_int 0)))
2133    (set (match_operand:SI 0 "s_register_operand" "=r")
2134         (xor:SI (match_dup 1) (match_dup 2)))]
2135   "TARGET_ARM"
2136   "eor%?s\\t%0, %1, %2"
2137   [(set_attr "conds" "set")]
2140 (define_insn "*xorsi3_compare0_scratch"
2141   [(set (reg:CC_NOOV CC_REGNUM)
2142         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2143                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2144                          (const_int 0)))]
2145   "TARGET_ARM"
2146   "teq%?\\t%0, %1"
2147   [(set_attr "conds" "set")]
2150 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2151 ; (NOT D) we can sometimes merge the final NOT into one of the following
2152 ; insns.
2154 (define_split
2155   [(set (match_operand:SI 0 "s_register_operand" "")
2156         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2157                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2158                 (match_operand:SI 3 "arm_rhs_operand" "")))
2159    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2160   "TARGET_ARM"
2161   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2162                               (not:SI (match_dup 3))))
2163    (set (match_dup 0) (not:SI (match_dup 4)))]
2164   ""
2167 (define_insn "*andsi_iorsi3_notsi"
2168   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2169         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2170                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2171                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2172   "TARGET_ARM"
2173   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2174   [(set_attr "length" "8")
2175    (set_attr "predicable" "yes")]
2180 ;; Minimum and maximum insns
2182 (define_insn "smaxsi3"
2183   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2184         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2185                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2186    (clobber (reg:CC CC_REGNUM))]
2187   "TARGET_ARM"
2188   "@
2189    cmp\\t%1, %2\;movlt\\t%0, %2
2190    cmp\\t%1, %2\;movge\\t%0, %1
2191    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2192   [(set_attr "conds" "clob")
2193    (set_attr "length" "8,8,12")]
2196 (define_insn "sminsi3"
2197   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2198         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2199                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2200    (clobber (reg:CC CC_REGNUM))]
2201   "TARGET_ARM"
2202   "@
2203    cmp\\t%1, %2\;movge\\t%0, %2
2204    cmp\\t%1, %2\;movlt\\t%0, %1
2205    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2206   [(set_attr "conds" "clob")
2207    (set_attr "length" "8,8,12")]
2210 (define_insn "umaxsi3"
2211   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2212         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2213                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2214    (clobber (reg:CC CC_REGNUM))]
2215   "TARGET_ARM"
2216   "@
2217    cmp\\t%1, %2\;movcc\\t%0, %2
2218    cmp\\t%1, %2\;movcs\\t%0, %1
2219    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2220   [(set_attr "conds" "clob")
2221    (set_attr "length" "8,8,12")]
2224 (define_insn "uminsi3"
2225   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2226         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2227                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2228    (clobber (reg:CC CC_REGNUM))]
2229   "TARGET_ARM"
2230   "@
2231    cmp\\t%1, %2\;movcs\\t%0, %2
2232    cmp\\t%1, %2\;movcc\\t%0, %1
2233    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2234   [(set_attr "conds" "clob")
2235    (set_attr "length" "8,8,12")]
2238 (define_insn "*store_minmaxsi"
2239   [(set (match_operand:SI 0 "memory_operand" "=m")
2240         (match_operator:SI 3 "minmax_operator"
2241          [(match_operand:SI 1 "s_register_operand" "r")
2242           (match_operand:SI 2 "s_register_operand" "r")]))
2243    (clobber (reg:CC CC_REGNUM))]
2244   "TARGET_ARM"
2245   "*
2246   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2247                          operands[2]);
2248   output_asm_insn (\"cmp\\t%1, %2\", operands);
2249   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2250   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2251   return \"\";
2252   "
2253   [(set_attr "conds" "clob")
2254    (set_attr "length" "12")
2255    (set_attr "type" "store1")]
2258 ; Reject the frame pointer in operand[1], since reloading this after
2259 ; it has been eliminated can cause carnage.
2260 (define_insn "*minmax_arithsi"
2261   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2262         (match_operator:SI 4 "shiftable_operator"
2263          [(match_operator:SI 5 "minmax_operator"
2264            [(match_operand:SI 2 "s_register_operand" "r,r")
2265             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2266           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2267    (clobber (reg:CC CC_REGNUM))]
2268   "TARGET_ARM
2269    && (GET_CODE (operands[1]) != REG
2270        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2271            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2272   "*
2273   {
2274     enum rtx_code code = GET_CODE (operands[4]);
2276     operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2277                            operands[3]);
2278     output_asm_insn (\"cmp\\t%2, %3\", operands);
2279     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2280     if (which_alternative != 0 || operands[3] != const0_rtx
2281         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2282       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2283     return \"\";
2284   }"
2285   [(set_attr "conds" "clob")
2286    (set_attr "length" "12")]
2290 ;; Shift and rotation insns
2292 (define_expand "ashlsi3"
2293   [(set (match_operand:SI            0 "s_register_operand" "")
2294         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2295                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2296   "TARGET_EITHER"
2297   "
2298   if (GET_CODE (operands[2]) == CONST_INT
2299       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2300     {
2301       emit_insn (gen_movsi (operands[0], const0_rtx));
2302       DONE;
2303     }
2304   "
2307 (define_insn "*thumb_ashlsi3"
2308   [(set (match_operand:SI            0 "register_operand" "=l,l")
2309         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2310                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2311   "TARGET_THUMB"
2312   "lsl\\t%0, %1, %2"
2313   [(set_attr "length" "2")]
2316 (define_expand "ashrsi3"
2317   [(set (match_operand:SI              0 "s_register_operand" "")
2318         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2319                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2320   "TARGET_EITHER"
2321   "
2322   if (GET_CODE (operands[2]) == CONST_INT
2323       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2324     operands[2] = GEN_INT (31);
2325   "
2328 (define_insn "*thumb_ashrsi3"
2329   [(set (match_operand:SI              0 "register_operand" "=l,l")
2330         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2331                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2332   "TARGET_THUMB"
2333   "asr\\t%0, %1, %2"
2334   [(set_attr "length" "2")]
2337 (define_expand "lshrsi3"
2338   [(set (match_operand:SI              0 "s_register_operand" "")
2339         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2340                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2341   "TARGET_EITHER"
2342   "
2343   if (GET_CODE (operands[2]) == CONST_INT
2344       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2345     {
2346       emit_insn (gen_movsi (operands[0], const0_rtx));
2347       DONE;
2348     }
2349   "
2352 (define_insn "*thumb_lshrsi3"
2353   [(set (match_operand:SI              0 "register_operand" "=l,l")
2354         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2355                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2356   "TARGET_THUMB"
2357   "lsr\\t%0, %1, %2"
2358   [(set_attr "length" "2")]
2361 (define_expand "rotlsi3"
2362   [(set (match_operand:SI              0 "s_register_operand" "")
2363         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2364                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2365   "TARGET_ARM"
2366   "
2367   if (GET_CODE (operands[2]) == CONST_INT)
2368     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2369   else
2370     {
2371       rtx reg = gen_reg_rtx (SImode);
2372       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2373       operands[2] = reg;
2374     }
2375   "
2378 (define_expand "rotrsi3"
2379   [(set (match_operand:SI              0 "s_register_operand" "")
2380         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2381                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2382   "TARGET_EITHER"
2383   "
2384   if (TARGET_ARM)
2385     {
2386       if (GET_CODE (operands[2]) == CONST_INT
2387           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2388         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2389     }
2390   else /* TARGET_THUMB */
2391     {
2392       if (GET_CODE (operands [2]) == CONST_INT)
2393         operands [2] = force_reg (SImode, operands[2]);
2394     }
2395   "
2398 (define_insn "*thumb_rotrsi3"
2399   [(set (match_operand:SI              0 "register_operand" "=l")
2400         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2401                      (match_operand:SI 2 "register_operand" "l")))]
2402   "TARGET_THUMB"
2403   "ror\\t%0, %0, %2"
2404   [(set_attr "length" "2")]
2407 (define_expand "ashldi3"
2408   [(set (match_operand:DI            0 "s_register_operand" "")
2409         (ashift:DI (match_operand:DI 1 "general_operand"    "")
2410                    (match_operand:SI 2 "general_operand"    "")))]
2411   "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)"
2412   "
2413   if (! s_register_operand (operands[1], DImode))
2414     operands[1] = copy_to_mode_reg (DImode, operands[1]);
2415   if (! s_register_operand (operands[2], SImode))
2416     operands[2] = copy_to_mode_reg (SImode, operands[2]);
2417   "
2420 (define_insn "*arm_shiftsi3"
2421   [(set (match_operand:SI   0 "s_register_operand" "=r")
2422         (match_operator:SI  3 "shift_operator"
2423          [(match_operand:SI 1 "s_register_operand"  "r")
2424           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2425   "TARGET_ARM"
2426   "mov%?\\t%0, %1%S3"
2427   [(set_attr "predicable" "yes")
2428    (set_attr "shift" "1")
2429    ]
2432 (define_insn "*shiftsi3_compare0"
2433   [(set (reg:CC_NOOV CC_REGNUM)
2434         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2435                           [(match_operand:SI 1 "s_register_operand" "r")
2436                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2437                          (const_int 0)))
2438    (set (match_operand:SI 0 "s_register_operand" "=r")
2439         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2440   "TARGET_ARM"
2441   "mov%?s\\t%0, %1%S3"
2442   [(set_attr "conds" "set")
2443    (set_attr "shift" "1")
2444    ]
2447 (define_insn "*shiftsi3_compare0_scratch"
2448   [(set (reg:CC_NOOV CC_REGNUM)
2449         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2450                           [(match_operand:SI 1 "s_register_operand" "r")
2451                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2452                          (const_int 0)))
2453    (clobber (match_scratch:SI 0 "=r"))]
2454   "TARGET_ARM"
2455   "mov%?s\\t%0, %1%S3"
2456   [(set_attr "conds" "set")
2457    (set_attr "shift" "1")
2458    ]
2461 (define_insn "*notsi_shiftsi"
2462   [(set (match_operand:SI 0 "s_register_operand" "=r")
2463         (not:SI (match_operator:SI 3 "shift_operator"
2464                  [(match_operand:SI 1 "s_register_operand" "r")
2465                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2466   "TARGET_ARM"
2467   "mvn%?\\t%0, %1%S3"
2468   [(set_attr "predicable" "yes")
2469    (set_attr "shift" "1")
2470    ]
2473 (define_insn "*notsi_shiftsi_compare0"
2474   [(set (reg:CC_NOOV CC_REGNUM)
2475         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2476                           [(match_operand:SI 1 "s_register_operand" "r")
2477                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2478                          (const_int 0)))
2479    (set (match_operand:SI 0 "s_register_operand" "=r")
2480         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2481   "TARGET_ARM"
2482   "mvn%?s\\t%0, %1%S3"
2483   [(set_attr "conds" "set")
2484    (set_attr "shift" "1")
2485    ]
2488 (define_insn "*not_shiftsi_compare0_scratch"
2489   [(set (reg:CC_NOOV CC_REGNUM)
2490         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2491                           [(match_operand:SI 1 "s_register_operand" "r")
2492                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2493                          (const_int 0)))
2494    (clobber (match_scratch:SI 0 "=r"))]
2495   "TARGET_ARM"
2496   "mvn%?s\\t%0, %1%S3"
2497   [(set_attr "conds" "set")
2498    (set_attr "shift" "1")
2499   ]
2502 ;; We don't really have extzv, but defining this using shifts helps
2503 ;; to reduce register pressure later on.
2505 (define_expand "extzv"
2506   [(set (match_dup 4)
2507         (ashift:SI (match_operand:SI   1 "register_operand" "")
2508                    (match_operand:SI   2 "const_int_operand" "")))
2509    (set (match_operand:SI              0 "register_operand" "")
2510         (lshiftrt:SI (match_dup 4)
2511                      (match_operand:SI 3 "const_int_operand" "")))]
2512   "TARGET_THUMB"
2513   "
2514   {
2515     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2516     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2517     
2518     operands[3] = GEN_INT (rshift);
2519     
2520     if (lshift == 0)
2521       {
2522         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2523         DONE;
2524       }
2525       
2526     operands[2] = GEN_INT (lshift);
2527     operands[4] = gen_reg_rtx (SImode);
2528   }"
2532 ;; Unary arithmetic insns
2534 (define_expand "negdi2"
2535  [(parallel
2536    [(set (match_operand:DI          0 "s_register_operand" "")
2537           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2538     (clobber (reg:CC CC_REGNUM))])]
2539   "TARGET_EITHER"
2540   "
2541   if (TARGET_THUMB)
2542     {
2543       if (GET_CODE (operands[1]) != REG)
2544         operands[1] = force_reg (SImode, operands[1]);
2545      }
2546   "
2549 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2550 ;; The second alternative is to allow the common case of a *full* overlap.
2551 (define_insn "*arm_negdi2"
2552   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2553         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2554    (clobber (reg:CC CC_REGNUM))]
2555   "TARGET_ARM"
2556   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2557   [(set_attr "conds" "clob")
2558    (set_attr "length" "8")]
2561 (define_insn "*thumb_negdi2"
2562   [(set (match_operand:DI         0 "register_operand" "=&l")
2563         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2564    (clobber (reg:CC CC_REGNUM))]
2565   "TARGET_THUMB"
2566   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2567   [(set_attr "length" "6")]
2570 (define_expand "negsi2"
2571   [(set (match_operand:SI         0 "s_register_operand" "")
2572         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2573   "TARGET_EITHER"
2574   ""
2577 (define_insn "*arm_negsi2"
2578   [(set (match_operand:SI         0 "s_register_operand" "=r")
2579         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2580   "TARGET_ARM"
2581   "rsb%?\\t%0, %1, #0"
2582   [(set_attr "predicable" "yes")]
2585 (define_insn "*thumb_negsi2"
2586   [(set (match_operand:SI         0 "register_operand" "=l")
2587         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2588   "TARGET_THUMB"
2589   "neg\\t%0, %1"
2590   [(set_attr "length" "2")]
2593 (define_expand "negsf2"
2594   [(set (match_operand:SF         0 "s_register_operand" "")
2595         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2596   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2597   ""
2600 (define_expand "negdf2"
2601   [(set (match_operand:DF         0 "s_register_operand" "")
2602         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2603   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2604   "")
2606 ;; abssi2 doesn't really clobber the condition codes if a different register
2607 ;; is being set.  To keep things simple, assume during rtl manipulations that
2608 ;; it does, but tell the final scan operator the truth.  Similarly for
2609 ;; (neg (abs...))
2611 (define_expand "abssi2"
2612   [(parallel
2613     [(set (match_operand:SI         0 "s_register_operand" "")
2614           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2615      (clobber (reg:CC CC_REGNUM))])]
2616   "TARGET_ARM"
2617   "")
2619 (define_insn "*arm_abssi2"
2620   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2621         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2622    (clobber (reg:CC CC_REGNUM))]
2623   "TARGET_ARM"
2624   "@
2625    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2626    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2627   [(set_attr "conds" "clob,*")
2628    (set_attr "shift" "1")
2629    ;; predicable can't be set based on the variant, so left as no
2630    (set_attr "length" "8")]
2633 (define_insn "*neg_abssi2"
2634   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2635         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2636    (clobber (reg:CC CC_REGNUM))]
2637   "TARGET_ARM"
2638   "@
2639    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2640    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2641   [(set_attr "conds" "clob,*")
2642    (set_attr "shift" "1")
2643    ;; predicable can't be set based on the variant, so left as no
2644    (set_attr "length" "8")]
2647 (define_expand "abssf2"
2648   [(set (match_operand:SF         0 "s_register_operand" "")
2649         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2650   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2651   "")
2653 (define_expand "absdf2"
2654   [(set (match_operand:DF         0 "s_register_operand" "")
2655         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2656   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2657   "")
2659 (define_expand "sqrtsf2"
2660   [(set (match_operand:SF 0 "s_register_operand" "")
2661         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2662   "TARGET_ARM && TARGET_HARD_FLOAT"
2663   "")
2665 (define_expand "sqrtdf2"
2666   [(set (match_operand:DF 0 "s_register_operand" "")
2667         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2668   "TARGET_ARM && TARGET_HARD_FLOAT"
2669   "")
2671 (define_insn_and_split "one_cmpldi2"
2672   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2673         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2674   "TARGET_ARM"
2675   "#"
2676   "TARGET_ARM && reload_completed"
2677   [(set (match_dup 0) (not:SI (match_dup 1)))
2678    (set (match_dup 2) (not:SI (match_dup 3)))]
2679   "
2680   {
2681     operands[2] = gen_highpart (SImode, operands[0]);
2682     operands[0] = gen_lowpart (SImode, operands[0]);
2683     operands[3] = gen_highpart (SImode, operands[1]);
2684     operands[1] = gen_lowpart (SImode, operands[1]);
2685   }"
2686   [(set_attr "length" "8")
2687    (set_attr "predicable" "yes")]
2690 (define_expand "one_cmplsi2"
2691   [(set (match_operand:SI         0 "s_register_operand" "")
2692         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2693   "TARGET_EITHER"
2694   ""
2697 (define_insn "*arm_one_cmplsi2"
2698   [(set (match_operand:SI         0 "s_register_operand" "=r")
2699         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2700   "TARGET_ARM"
2701   "mvn%?\\t%0, %1"
2702   [(set_attr "predicable" "yes")]
2705 (define_insn "*thumb_one_cmplsi2"
2706   [(set (match_operand:SI         0 "register_operand" "=l")
2707         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
2708   "TARGET_THUMB"
2709   "mvn\\t%0, %1"
2710   [(set_attr "length" "2")]
2713 (define_insn "*notsi_compare0"
2714   [(set (reg:CC_NOOV CC_REGNUM)
2715         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2716                          (const_int 0)))
2717    (set (match_operand:SI 0 "s_register_operand" "=r")
2718         (not:SI (match_dup 1)))]
2719   "TARGET_ARM"
2720   "mvn%?s\\t%0, %1"
2721   [(set_attr "conds" "set")]
2724 (define_insn "*notsi_compare0_scratch"
2725   [(set (reg:CC_NOOV CC_REGNUM)
2726         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2727                          (const_int 0)))
2728    (clobber (match_scratch:SI 0 "=r"))]
2729   "TARGET_ARM"
2730   "mvn%?s\\t%0, %1"
2731   [(set_attr "conds" "set")]
2734 ;; Fixed <--> Floating conversion insns
2736 (define_expand "floatsisf2"
2737   [(set (match_operand:SF           0 "s_register_operand" "")
2738         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2739   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2740   "
2741   if (TARGET_CIRRUS)
2742     {
2743       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2744       DONE;
2745     }
2748 (define_expand "floatsidf2"
2749   [(set (match_operand:DF           0 "s_register_operand" "")
2750         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2751   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2752   "
2753   if (TARGET_CIRRUS)
2754     {
2755       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
2756       DONE;
2757     }
2760 (define_expand "fix_truncsfsi2"
2761   [(set (match_operand:SI         0 "s_register_operand" "")
2762         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
2763   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2764   "
2765   if (TARGET_CIRRUS)
2766     {
2767       if (!cirrus_fp_register (operands[0], SImode))
2768         operands[0] = force_reg (SImode, operands[0]);
2769       if (!cirrus_fp_register (operands[1], SFmode))
2770         operands[1] = force_reg (SFmode, operands[0]);
2771       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
2772       DONE;
2773     }
2776 (define_expand "fix_truncdfsi2"
2777   [(set (match_operand:SI         0 "s_register_operand" "")
2778         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
2779   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2780   "
2781   if (TARGET_CIRRUS)
2782     {
2783       if (!cirrus_fp_register (operands[1], DFmode))
2784         operands[1] = force_reg (DFmode, operands[0]);
2785       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
2786       DONE;
2787     }
2790 ;; Truncation insns
2792 (define_expand "truncdfsf2"
2793   [(set (match_operand:SF  0 "s_register_operand" "")
2794         (float_truncate:SF
2795          (match_operand:DF 1 "s_register_operand" "")))]
2796   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2797   ""
2800 ;; Zero and sign extension instructions.
2802 (define_insn "zero_extendsidi2"
2803   [(set (match_operand:DI 0 "s_register_operand" "=r")
2804         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2805   "TARGET_ARM"
2806   "*
2807     if (REGNO (operands[1])
2808         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2809       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2810     return \"mov%?\\t%R0, #0\";
2811   "
2812   [(set_attr "length" "8")
2813    (set_attr "predicable" "yes")]
2816 (define_insn "zero_extendqidi2"
2817   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
2818         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2819   "TARGET_ARM"
2820   "@
2821    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2822    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2823   [(set_attr "length" "8")
2824    (set_attr "predicable" "yes")
2825    (set_attr "type" "*,load")
2826    (set_attr "pool_range" "*,4092")
2827    (set_attr "neg_pool_range" "*,4084")]
2830 (define_insn "extendsidi2"
2831   [(set (match_operand:DI 0 "s_register_operand" "=r")
2832         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2833   "TARGET_ARM"
2834   "*
2835     if (REGNO (operands[1])
2836         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2837       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2838     return \"mov%?\\t%R0, %Q0, asr #31\";
2839   "
2840   [(set_attr "length" "8")
2841    (set_attr "shift" "1")
2842    (set_attr "predicable" "yes")]
2845 (define_expand "zero_extendhisi2"
2846   [(set (match_dup 2)
2847         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2848                    (const_int 16)))
2849    (set (match_operand:SI 0 "s_register_operand" "")
2850         (lshiftrt:SI (match_dup 2) (const_int 16)))]
2851   "TARGET_EITHER"
2852   "
2853   {
2854     if (TARGET_ARM)
2855       {
2856         if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2857           {
2858            /* Note: We do not have to worry about TARGET_MMU_TRAPS
2859               here because the insn below will generate an LDRH instruction
2860               rather than an LDR instruction, so we cannot get an unaligned
2861               word access.  */
2862             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2863                                     gen_rtx_ZERO_EXTEND (SImode,
2864                                                          operands[1])));
2865             DONE;
2866           }
2867         if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2868           {
2869             emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2870             DONE;
2871           }
2872         if (!s_register_operand (operands[1], HImode))
2873           operands[1] = copy_to_mode_reg (HImode, operands[1]);
2874         operands[1] = gen_lowpart (SImode, operands[1]);
2875         operands[2] = gen_reg_rtx (SImode);
2876       }
2877     else /* TARGET_THUMB */
2878       {
2879         if (GET_CODE (operands[1]) == MEM)
2880           {
2881             rtx tmp;
2883             tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
2884             tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
2885             emit_insn (tmp);
2886           }
2887         else
2888           {
2889             rtx ops[3];
2890             
2891             if (!s_register_operand (operands[1], HImode))
2892               operands[1] = copy_to_mode_reg (HImode, operands[1]);
2893             operands[1] = gen_lowpart (SImode, operands[1]);
2894             operands[2] = gen_reg_rtx (SImode);
2895             
2896             ops[0] = operands[2];
2897             ops[1] = operands[1];
2898             ops[2] = GEN_INT (16);
2899             
2900             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2901                                     gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
2903             ops[0] = operands[0];
2904             ops[1] = operands[2];
2905             ops[2] = GEN_INT (16);
2907             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2908                                     gen_rtx_LSHIFTRT (SImode, ops[1],
2909                                                       ops[2])));
2910           }
2911         DONE; 
2912       }
2913   }"
2916 (define_insn "*thumb_zero_extendhisi2"
2917   [(set (match_operand:SI                 0 "register_operand" "=l")
2918         (zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
2919   "TARGET_THUMB"
2920   "*
2921   rtx mem = XEXP (operands[1], 0);
2923   if (GET_CODE (mem) == CONST)
2924     mem = XEXP (mem, 0);
2925     
2926   if (GET_CODE (mem) == LABEL_REF)
2927     return \"ldr\\t%0, %1\";
2928     
2929   if (GET_CODE (mem) == PLUS)
2930     {
2931       rtx a = XEXP (mem, 0);
2932       rtx b = XEXP (mem, 1);
2934       /* This can happen due to bugs in reload.  */
2935       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
2936         {
2937           rtx ops[2];
2938           ops[0] = operands[0];
2939           ops[1] = a;
2940       
2941           output_asm_insn (\"mov        %0, %1\", ops);
2943           XEXP (mem, 0) = operands[0];
2944        }
2946       else if (   GET_CODE (a) == LABEL_REF
2947                && GET_CODE (b) == CONST_INT)
2948         return \"ldr\\t%0, %1\";
2949     }
2950     
2951   return \"ldrh\\t%0, %1\";
2952   "
2953   [(set_attr "length" "4")
2954    (set_attr "type" "load")
2955    (set_attr "pool_range" "60")]
2958 (define_insn "*arm_zero_extendhisi2"
2959   [(set (match_operand:SI                 0 "s_register_operand" "=r")
2960         (zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
2961   "TARGET_ARM && arm_arch4"
2962   "ldr%?h\\t%0, %1"
2963   [(set_attr "type" "load")
2964    (set_attr "predicable" "yes")
2965    (set_attr "pool_range" "256")
2966    (set_attr "neg_pool_range" "244")]
2969 (define_split
2970   [(set (match_operand:SI 0 "s_register_operand" "")
2971         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2972    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2973   "TARGET_ARM && (!arm_arch4)"
2974   [(set (match_dup 2) (match_dup 1))
2975    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2976   "
2977   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
2978     FAIL;
2979   "
2982 (define_split
2983   [(set (match_operand:SI 0 "s_register_operand" "")
2984         (match_operator:SI 3 "shiftable_operator"
2985          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2986           (match_operand:SI 4 "s_register_operand" "")]))
2987    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2988   "TARGET_ARM && (!arm_arch4)"
2989   [(set (match_dup 2) (match_dup 1))
2990    (set (match_dup 0)
2991         (match_op_dup 3
2992          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2993   "
2994   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
2995     FAIL;
2996   "
2999 (define_expand "zero_extendqisi2"
3000   [(set (match_operand:SI 0 "s_register_operand" "")
3001         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3002   "TARGET_EITHER"
3003   "
3004   if (GET_CODE (operands[1]) != MEM)
3005     {
3006       if (TARGET_ARM)
3007         {
3008           emit_insn (gen_andsi3 (operands[0],
3009                                  gen_lowpart (SImode, operands[1]),
3010                                  GEN_INT (255)));
3011         }
3012       else /* TARGET_THUMB */
3013         {
3014           rtx temp = gen_reg_rtx (SImode);
3015           rtx ops[3];
3016           
3017           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3018           operands[1] = gen_lowpart (SImode, operands[1]);
3020           ops[0] = temp;
3021           ops[1] = operands[1];
3022           ops[2] = GEN_INT (24);
3024           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3025                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3026           
3027           ops[0] = operands[0];
3028           ops[1] = temp;
3029           ops[2] = GEN_INT (24);
3031           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3032                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3033         }
3034       DONE;
3035     }
3036   "
3039 (define_insn "*thumb_zero_extendqisi2"
3040   [(set (match_operand:SI                 0 "register_operand" "=l")
3041         (zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3042   "TARGET_THUMB"
3043   "ldrb\\t%0, %1"
3044   [(set_attr "length" "2")
3045    (set_attr "type" "load")
3046    (set_attr "pool_range" "32")]
3049 (define_insn "*arm_zero_extendqisi2"
3050   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3051         (zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3052   "TARGET_ARM"
3053   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3054   [(set_attr "type" "load")
3055    (set_attr "predicable" "yes")
3056    (set_attr "pool_range" "4096")
3057    (set_attr "neg_pool_range" "4084")]
3060 (define_split
3061   [(set (match_operand:SI 0 "s_register_operand" "")
3062         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3063    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3064   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3065   [(set (match_dup 2) (match_dup 1))
3066    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3067   ""
3070 (define_insn "*compareqi_eq0"
3071   [(set (reg:CC_Z CC_REGNUM)
3072         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3073                          (const_int 0)))]
3074   "TARGET_ARM"
3075   "tst\\t%0, #255"
3076   [(set_attr "conds" "set")]
3079 (define_expand "extendhisi2"
3080   [(set (match_dup 2)
3081         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3082                    (const_int 16)))
3083    (set (match_operand:SI 0 "s_register_operand" "")
3084         (ashiftrt:SI (match_dup 2)
3085                      (const_int 16)))]
3086   "TARGET_EITHER"
3087   "
3088   {
3089     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3090       {
3091        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3092           here because the insn below will generate an LDRH instruction
3093           rather than an LDR instruction, so we cannot get an unaligned
3094           word access.  */
3095         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3096                    gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3097         DONE;
3098       }
3100     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3101       {
3102         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3103         DONE;
3104       }
3105     if (!s_register_operand (operands[1], HImode))
3106       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3107     operands[1] = gen_lowpart (SImode, operands[1]);
3108     operands[2] = gen_reg_rtx (SImode);
3110     if (TARGET_THUMB)
3111       {
3112         rtx ops[3];
3113         
3114         ops[0] = operands[2];
3115         ops[1] = operands[1];
3116         ops[2] = GEN_INT (16);
3117         
3118         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3119                                 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3120             
3121         ops[0] = operands[0];
3122         ops[1] = operands[2];
3123         ops[2] = GEN_INT (16);
3124         
3125         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3126                                 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3127         
3128         DONE;
3129       }
3130   }"
3133 (define_insn "*thumb_extendhisi2_insn"
3134   [(set (match_operand:SI                 0 "register_operand" "=l")
3135         (sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3136    (clobber (match_scratch:SI             2                   "=&l"))]
3137   "TARGET_THUMB"
3138   "*
3139   {
3140     rtx ops[4];
3141     rtx mem = XEXP (operands[1], 0);
3143     /* This code used to try to use 'V', and fix the address only if it was
3144        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3145        range of QImode offsets, and offsettable_address_p does a QImode
3146        address check.  */
3147        
3148     if (GET_CODE (mem) == CONST)
3149       mem = XEXP (mem, 0);
3150     
3151     if (GET_CODE (mem) == LABEL_REF)
3152       return \"ldr\\t%0, %1\";
3153     
3154     if (GET_CODE (mem) == PLUS)
3155       {
3156         rtx a = XEXP (mem, 0);
3157         rtx b = XEXP (mem, 1);
3159         if (GET_CODE (a) == LABEL_REF
3160             && GET_CODE (b) == CONST_INT)
3161           return \"ldr\\t%0, %1\";
3163         if (GET_CODE (b) == REG)
3164           return \"ldrsh\\t%0, %1\";
3165           
3166         ops[1] = a;
3167         ops[2] = b;
3168       }
3169     else
3170       {
3171         ops[1] = mem;
3172         ops[2] = const0_rtx;
3173       }
3174       
3175     if (GET_CODE (ops[1]) != REG)
3176       {
3177         debug_rtx (ops[1]);
3178         abort ();
3179       }
3181     ops[0] = operands[0];
3182     ops[3] = operands[2];
3183     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3184     return \"\";
3185   }"
3186   [(set_attr "length" "4")
3187    (set_attr "type" "load")
3188    (set_attr "pool_range" "1020")]
3191 (define_expand "extendhisi2_mem"
3192   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3193    (set (match_dup 3)
3194         (zero_extend:SI (match_dup 7)))
3195    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3196    (set (match_operand:SI 0 "" "")
3197         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3198   "TARGET_ARM"
3199   "
3200   {
3201     rtx mem1, mem2;
3202     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3204     mem1 = gen_rtx_MEM (QImode, addr);
3205     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3206     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3207     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3208     operands[0] = gen_lowpart (SImode, operands[0]);
3209     operands[1] = mem1;
3210     operands[2] = gen_reg_rtx (SImode);
3211     operands[3] = gen_reg_rtx (SImode);
3212     operands[6] = gen_reg_rtx (SImode);
3213     operands[7] = mem2;
3215     if (BYTES_BIG_ENDIAN)
3216       {
3217         operands[4] = operands[2];
3218         operands[5] = operands[3];
3219       }
3220     else
3221       {
3222         operands[4] = operands[3];
3223         operands[5] = operands[2];
3224       }
3225   }"
3228 (define_insn "*arm_extendhisi_insn"
3229   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3230         (sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3231   "TARGET_ARM && arm_arch4"
3232   "ldr%?sh\\t%0, %1"
3233   [(set_attr "type" "load")
3234    (set_attr "predicable" "yes")
3235    (set_attr "pool_range" "256")
3236    (set_attr "neg_pool_range" "244")]
3239 (define_split
3240   [(set (match_operand:SI                 0 "s_register_operand" "")
3241         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3242    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3243   "TARGET_ARM && (!arm_arch4)"
3244   [(set (match_dup 2) (match_dup 1))
3245    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3246   "
3247   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3248     FAIL;
3249   "
3252 (define_split
3253   [(set (match_operand:SI                   0 "s_register_operand" "")
3254         (match_operator:SI                  3 "shiftable_operator"
3255          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3256           (match_operand:SI                 4 "s_register_operand" "")]))
3257    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3258   "TARGET_ARM && (!arm_arch4)"
3259   [(set (match_dup 2) (match_dup 1))
3260    (set (match_dup 0)
3261         (match_op_dup 3
3262          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3263   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3264      FAIL;
3265   "
3268 (define_expand "extendqihi2"
3269   [(set (match_dup 2)
3270         (ashift:SI (match_operand:QI 1 "general_operand" "")
3271                    (const_int 24)))
3272    (set (match_operand:HI 0 "s_register_operand" "")
3273         (ashiftrt:SI (match_dup 2)
3274                      (const_int 24)))]
3275   "TARGET_ARM"
3276   "
3277   {
3278     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3279       {
3280         emit_insn (gen_rtx_SET (VOIDmode,
3281                                 operands[0],
3282                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3283         DONE;
3284       }
3285     if (!s_register_operand (operands[1], QImode))
3286       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3287     operands[0] = gen_lowpart (SImode, operands[0]);
3288     operands[1] = gen_lowpart (SImode, operands[1]);
3289     operands[2] = gen_reg_rtx (SImode);
3290   }"
3293 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3294 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3295 (define_insn "*extendqihi_insn"
3296   [(set (match_operand:HI                 0 "s_register_operand" "=r")
3297         (sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3298   "TARGET_ARM && arm_arch4"
3299   "*
3300   /* If the address is invalid, this will split the instruction into two. */
3301   if (bad_signed_byte_operand (operands[1], VOIDmode))
3302     return \"#\";
3303   return \"ldr%?sb\\t%0, %1\";
3304   "
3305   [(set_attr "type" "load")
3306    (set_attr "predicable" "yes")
3307    (set_attr "length" "8")
3308    (set_attr "pool_range" "256")
3309    (set_attr "neg_pool_range" "244")]
3312 (define_split
3313   [(set (match_operand:HI 0 "s_register_operand" "")
3314         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3315   "TARGET_ARM && arm_arch4 && reload_completed"
3316   [(set (match_dup 3) (match_dup 1))
3317    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3318   "
3319   {
3320     HOST_WIDE_INT offset;
3322     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3323     operands[2] = gen_rtx_MEM (QImode, operands[3]);
3324     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3325     operands[1] = XEXP (operands[1], 0);
3326     if (GET_CODE (operands[1]) == PLUS
3327         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3328         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3329              || const_ok_for_arm (-offset)))
3330       {
3331         HOST_WIDE_INT low = (offset > 0
3332                              ? (offset & 0xff) : -((-offset) & 0xff));
3333         XEXP (operands[2], 0) = plus_constant (operands[3], low);
3334         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3335       }
3336     /* Ensure the sum is in correct canonical form */
3337     else if (GET_CODE (operands[1]) == PLUS
3338              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3339              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3340       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3341                                            XEXP (operands[1], 1),
3342                                            XEXP (operands[1], 0));
3343   }"
3346 (define_expand "extendqisi2"
3347   [(set (match_dup 2)
3348         (ashift:SI (match_operand:QI 1 "general_operand" "")
3349                    (const_int 24)))
3350    (set (match_operand:SI 0 "s_register_operand" "")
3351         (ashiftrt:SI (match_dup 2)
3352                      (const_int 24)))]
3353   "TARGET_EITHER"
3354   "
3355   {
3356     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3357       {
3358         emit_insn (gen_rtx_SET (VOIDmode,
3359                                 operands[0],
3360                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3361         DONE;
3362       }
3363     if (!s_register_operand (operands[1], QImode))
3364       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3365     operands[1] = gen_lowpart (SImode, operands[1]);
3366     operands[2] = gen_reg_rtx (SImode);
3367     
3368     if (TARGET_THUMB)
3369       {
3370         rtx ops[3];
3371         
3372         ops[0] = operands[2];
3373         ops[1] = operands[1];
3374         ops[2] = GEN_INT (24);
3375         
3376         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3377                    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3379         ops[0] = operands[0];
3380         ops[1] = operands[2];
3381         ops[2] = GEN_INT (24);
3382         
3383         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3384                    gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3385         
3386         DONE;
3387       }
3388   }"
3391 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3392 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3393 (define_insn "*arm_extendqisi_insn"
3394   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3395         (sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3396   "TARGET_ARM && arm_arch4"
3397   "*
3398   /* If the address is invalid, this will split the instruction into two. */
3399   if (bad_signed_byte_operand (operands[1], VOIDmode))
3400     return \"#\";
3401   return \"ldr%?sb\\t%0, %1\";
3402   "
3403   [(set_attr "type" "load")
3404    (set_attr "predicable" "yes")
3405    (set_attr "length" "8")
3406    (set_attr "pool_range" "256")
3407    (set_attr "neg_pool_range" "244")]
3410 (define_split
3411   [(set (match_operand:SI 0 "s_register_operand" "")
3412         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3413   "TARGET_ARM && arm_arch4 && reload_completed"
3414   [(set (match_dup 0) (match_dup 1))
3415    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3416   "
3417   {
3418     HOST_WIDE_INT offset;
3420     operands[2] = gen_rtx_MEM (QImode, operands[0]);
3421     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3422     operands[1] = XEXP (operands[1], 0);
3423     if (GET_CODE (operands[1]) == PLUS
3424         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3425         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3426              || const_ok_for_arm (-offset)))
3427       {
3428         HOST_WIDE_INT low = (offset > 0
3429                              ? (offset & 0xff) : -((-offset) & 0xff));
3430         XEXP (operands[2], 0) = plus_constant (operands[0], low);
3431         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3432       }
3433     /* Ensure the sum is in correct canonical form */
3434     else if (GET_CODE (operands[1]) == PLUS
3435              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3436              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3437       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3438                                            XEXP (operands[1], 1),
3439                                            XEXP (operands[1], 0));
3440   }"
3443 (define_insn "*thumb_extendqisi2_insn"
3444   [(set (match_operand:SI                 0 "register_operand" "=l,l")
3445         (sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3446   "TARGET_THUMB"
3447   "*
3448   {
3449     rtx ops[3];
3450     rtx mem = XEXP (operands[1], 0);
3451     
3452     if (GET_CODE (mem) == CONST)
3453       mem = XEXP (mem, 0);
3454     
3455     if (GET_CODE (mem) == LABEL_REF)
3456       return \"ldr\\t%0, %1\";
3458     if (GET_CODE (mem) == PLUS
3459         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3460       return \"ldr\\t%0, %1\";
3461       
3462     if (which_alternative == 0)
3463       return \"ldrsb\\t%0, %1\";
3464       
3465     ops[0] = operands[0];
3466     
3467     if (GET_CODE (mem) == PLUS)
3468       {
3469         rtx a = XEXP (mem, 0);
3470         rtx b = XEXP (mem, 1);
3471         
3472         ops[1] = a;
3473         ops[2] = b;
3475         if (GET_CODE (a) == REG)
3476           {
3477             if (GET_CODE (b) == REG)
3478               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3479             else if (REGNO (a) == REGNO (ops[0]))
3480               {
3481                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3482                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3483                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3484               }
3485             else
3486               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3487           }
3488         else if (GET_CODE (b) != REG)
3489           abort ();
3490         else
3491           {
3492             if (REGNO (b) == REGNO (ops[0]))
3493               {
3494                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3495                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3496                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3497               }
3498             else
3499               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3500           }
3501       }
3502     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3503       {
3504         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3505         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3506         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3507       }
3508     else
3509       {
3510         ops[1] = mem;
3511         ops[2] = const0_rtx;
3512         
3513         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3514       }
3515     return \"\";
3516   }"
3517   [(set_attr "length" "2,6")
3518    (set_attr "type" "load,load")
3519    (set_attr "pool_range" "32,32")]
3522 (define_expand "extendsfdf2"
3523   [(set (match_operand:DF                  0 "s_register_operand" "")
3524         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
3525   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3526   ""
3529 ;; Move insns (including loads and stores)
3531 ;; XXX Just some ideas about movti.
3532 ;; I don't think these are a good idea on the arm, there just aren't enough
3533 ;; registers
3534 ;;(define_expand "loadti"
3535 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3536 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3537 ;;  "" "")
3539 ;;(define_expand "storeti"
3540 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3541 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3542 ;;  "" "")
3544 ;;(define_expand "movti"
3545 ;;  [(set (match_operand:TI 0 "general_operand" "")
3546 ;;      (match_operand:TI 1 "general_operand" ""))]
3547 ;;  ""
3548 ;;  "
3550 ;;  rtx insn;
3552 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3553 ;;    operands[1] = copy_to_reg (operands[1]);
3554 ;;  if (GET_CODE (operands[0]) == MEM)
3555 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3556 ;;  else if (GET_CODE (operands[1]) == MEM)
3557 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3558 ;;  else
3559 ;;    FAIL;
3561 ;;  emit_insn (insn);
3562 ;;  DONE;
3563 ;;}")
3565 ;; Recognize garbage generated above.
3567 ;;(define_insn ""
3568 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3569 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3570 ;;  ""
3571 ;;  "*
3572 ;;  {
3573 ;;    register mem = (which_alternative < 3);
3574 ;;    register const char *template;
3576 ;;    operands[mem] = XEXP (operands[mem], 0);
3577 ;;    switch (which_alternative)
3578 ;;      {
3579 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3580 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3581 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3582 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3583 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3584 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3585 ;;      }
3586 ;;    output_asm_insn (template, operands);
3587 ;;    return \"\";
3588 ;;  }")
3590 (define_expand "movdi"
3591   [(set (match_operand:DI 0 "general_operand" "")
3592         (match_operand:DI 1 "general_operand" ""))]
3593   "TARGET_EITHER"
3594   "
3595   if (TARGET_THUMB)
3596     {
3597       if (!no_new_pseudos)
3598         {
3599           if (GET_CODE (operands[0]) != REG)
3600             operands[1] = force_reg (DImode, operands[1]);
3601         }
3602     }
3603   "
3606 (define_insn "*arm_movdi"
3607   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3608         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3609   "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT"
3610   "*
3611   return (output_move_double (operands));
3612   "
3613   [(set_attr "length" "8")
3614    (set_attr "type" "*,load,store2")
3615    (set_attr "pool_range" "*,1020,*")
3616    (set_attr "neg_pool_range" "*,1008,*")]
3619 ;;; ??? This should have alternatives for constants.
3620 ;;; ??? This was originally identical to the movdf_insn pattern.
3621 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3622 ;;; thumb_reorg with a memory reference.
3623 (define_insn "*thumb_movdi_insn"
3624   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3625         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3626   "TARGET_THUMB
3627    && !TARGET_CIRRUS
3628    && (   register_operand (operands[0], DImode)
3629        || register_operand (operands[1], DImode))"
3630   "*
3631   {
3632   switch (which_alternative)
3633     {
3634     default:
3635     case 0:
3636       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3637         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3638       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3639     case 1:
3640       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3641     case 2:
3642       operands[1] = GEN_INT (- INTVAL (operands[1]));
3643       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3644     case 3:
3645       return \"ldmia\\t%1, {%0, %H0}\";
3646     case 4:
3647       return \"stmia\\t%0, {%1, %H1}\";
3648     case 5:
3649       return thumb_load_double_from_address (operands);
3650     case 6:
3651       operands[2] = gen_rtx (MEM, SImode,
3652                              plus_constant (XEXP (operands[0], 0), 4));
3653       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3654       return \"\";
3655     case 7:
3656       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3657         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3658       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3659     }
3660   }"
3661   [(set_attr "length" "4,4,6,2,2,6,4,4")
3662    (set_attr "type" "*,*,*,load,store2,load,store2,*")
3663    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3666 (define_expand "movsi"
3667   [(set (match_operand:SI 0 "general_operand" "")
3668         (match_operand:SI 1 "general_operand" ""))]
3669   "TARGET_EITHER"
3670   "
3671   if (TARGET_ARM)
3672     {
3673       /* Everything except mem = const or mem = mem can be done easily */
3674       if (GET_CODE (operands[0]) == MEM)
3675         operands[1] = force_reg (SImode, operands[1]);
3676       if (GET_CODE (operands[1]) == CONST_INT
3677           && !(const_ok_for_arm (INTVAL (operands[1]))
3678                || const_ok_for_arm (~INTVAL (operands[1]))))
3679         {
3680            arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3681                               NULL_RTX,
3682                               (no_new_pseudos ? 0
3683                                : preserve_subexpressions_p ()));
3684           DONE;
3685         }
3686     }
3687   else /* TARGET_THUMB.... */
3688     {
3689       if (!no_new_pseudos)
3690         {
3691           if (GET_CODE (operands[0]) != REG)
3692             operands[1] = force_reg (SImode, operands[1]);
3693         }
3694     }
3695     
3696   if (flag_pic
3697       && (CONSTANT_P (operands[1])
3698          || symbol_mentioned_p (operands[1])
3699          || label_mentioned_p (operands[1])))
3700     operands[1] = legitimize_pic_address (operands[1], SImode,
3701                                           (no_new_pseudos ? operands[0] : 0));
3702   "
3705 (define_insn "*arm_movsi_insn"
3706   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3707         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
3708   "TARGET_ARM && ! TARGET_IWMMXT
3709    && (   register_operand (operands[0], SImode)
3710        || register_operand (operands[1], SImode))"
3711   "@
3712    mov%?\\t%0, %1
3713    mvn%?\\t%0, #%B1
3714    ldr%?\\t%0, %1
3715    str%?\\t%1, %0"
3716   [(set_attr "type" "*,*,load,store1")
3717    (set_attr "predicable" "yes")
3718    (set_attr "pool_range" "*,*,4096,*")
3719    (set_attr "neg_pool_range" "*,*,4084,*")]
3722 (define_split
3723   [(set (match_operand:SI 0 "s_register_operand" "")
3724         (match_operand:SI 1 "const_int_operand" ""))]
3725   "TARGET_ARM
3726   && (!(const_ok_for_arm (INTVAL (operands[1]))
3727         || const_ok_for_arm (~INTVAL (operands[1]))))"
3728   [(clobber (const_int 0))]
3729   "
3730   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3731                       NULL_RTX, 0);
3732   DONE;
3733   "
3736 (define_insn "*thumb_movsi_insn"
3737   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3738         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
3739   "TARGET_THUMB
3740    && (   register_operand (operands[0], SImode) 
3741        || register_operand (operands[1], SImode))"
3742   "@
3743    mov  %0, %1
3744    mov  %0, %1
3745    #
3746    #
3747    ldmia\\t%1, {%0}
3748    stmia\\t%0, {%1}
3749    ldr\\t%0, %1
3750    str\\t%1, %0
3751    mov\\t%0, %1"
3752   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3753    (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3754    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3757 (define_split 
3758   [(set (match_operand:SI 0 "register_operand" "")
3759         (match_operand:SI 1 "const_int_operand" ""))]
3760   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3761   [(set (match_dup 0) (match_dup 1))
3762    (set (match_dup 0) (neg:SI (match_dup 0)))]
3763   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3766 (define_split 
3767   [(set (match_operand:SI 0 "register_operand" "")
3768         (match_operand:SI 1 "const_int_operand" ""))]
3769   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3770   [(set (match_dup 0) (match_dup 1))
3771    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3772   "
3773   {
3774     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3775     unsigned HOST_WIDE_INT mask = 0xff;
3776     int i;
3777     
3778     for (i = 0; i < 25; i++)
3779       if ((val & (mask << i)) == val)
3780         break;
3782     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
3783     if (i == 0)
3784       FAIL;
3786     operands[1] = GEN_INT (val >> i);
3787     operands[2] = GEN_INT (i);
3788   }"
3791 ;; When generating pic, we need to load the symbol offset into a register.
3792 ;; So that the optimizer does not confuse this with a normal symbol load
3793 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
3794 ;; since that is the only type of relocation we can use.
3796 ;; The rather odd constraints on the following are to force reload to leave
3797 ;; the insn alone, and to force the minipool generation pass to then move
3798 ;; the GOT symbol to memory.
3800 (define_insn "pic_load_addr_arm"
3801   [(set (match_operand:SI 0 "s_register_operand" "=r")
3802         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3803   "TARGET_ARM && flag_pic"
3804   "ldr%?\\t%0, %1"
3805   [(set_attr "type" "load")
3806    (set (attr "pool_range")     (const_int 4096))
3807    (set (attr "neg_pool_range") (const_int 4084))]
3810 (define_insn "pic_load_addr_thumb"
3811   [(set (match_operand:SI 0 "s_register_operand" "=l")
3812         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3813   "TARGET_THUMB && flag_pic"
3814   "ldr\\t%0, %1"
3815   [(set_attr "type" "load")
3816    (set (attr "pool_range") (const_int 1024))]
3819 ;; This variant is used for AOF assembly, since it needs to mention the
3820 ;; pic register in the rtl.
3821 (define_expand "pic_load_addr_based"
3822   [(set (match_operand:SI 0 "s_register_operand" "")
3823         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
3824   "TARGET_ARM && flag_pic"
3825   "operands[2] = pic_offset_table_rtx;"
3828 (define_insn "*pic_load_addr_based_insn"
3829   [(set (match_operand:SI 0 "s_register_operand" "=r")
3830         (unspec:SI [(match_operand 1 "" "")
3831                     (match_operand 2 "s_register_operand" "r")]
3832                    UNSPEC_PIC_SYM))]
3833   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
3834   "*
3835 #ifdef AOF_ASSEMBLER
3836   operands[1] = aof_pic_entry (operands[1]);
3837 #endif
3838   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3839   return \"\";
3840   "
3841   [(set_attr "type" "load")
3842    (set (attr "pool_range")
3843         (if_then_else (eq_attr "is_thumb" "yes")
3844                       (const_int 1024)
3845                       (const_int 4096)))
3846    (set (attr "neg_pool_range")
3847         (if_then_else (eq_attr "is_thumb" "yes")
3848                       (const_int 0)
3849                       (const_int 4084)))]
3852 (define_insn "pic_add_dot_plus_four"
3853   [(set (match_operand:SI 0 "register_operand" "+r")
3854         (unspec:SI [(plus:SI (match_dup 0)
3855                              (const (plus:SI (pc) (const_int 4))))]
3856                    UNSPEC_PIC_BASE))
3857    (use (label_ref (match_operand 1 "" "")))]
3858   "TARGET_THUMB && flag_pic"
3859   "*
3860   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3861                              CODE_LABEL_NUMBER (operands[1]));
3862   return \"add\\t%0, %|pc\";
3863   "
3864   [(set_attr "length" "2")]
3867 (define_insn "pic_add_dot_plus_eight"
3868   [(set (match_operand:SI 0 "register_operand" "+r")
3869         (unspec:SI [(plus:SI (match_dup 0)
3870                              (const (plus:SI (pc) (const_int 8))))]
3871                    UNSPEC_PIC_BASE))
3872    (use (label_ref (match_operand 1 "" "")))]
3873   "TARGET_ARM && flag_pic"
3874   "*
3875     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3876                                CODE_LABEL_NUMBER (operands[1]));
3877     return \"add%?\\t%0, %|pc, %0\";
3878   "
3879   [(set_attr "predicable" "yes")]
3882 (define_expand "builtin_setjmp_receiver"
3883   [(label_ref (match_operand 0 "" ""))]
3884   "flag_pic"
3885   "
3887   arm_finalize_pic (0);
3888   DONE;
3891 ;; If copying one reg to another we can set the condition codes according to
3892 ;; its value.  Such a move is common after a return from subroutine and the
3893 ;; result is being tested against zero.
3895 (define_insn "*movsi_compare0"
3896   [(set (reg:CC CC_REGNUM)
3897         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
3898                     (const_int 0)))
3899    (set (match_operand:SI 0 "s_register_operand" "=r,r")
3900         (match_dup 1))]
3901   "TARGET_ARM"
3902   "@
3903    cmp%?\\t%0, #0
3904    sub%?s\\t%0, %1, #0"
3905   [(set_attr "conds" "set")]
3908 ;; Subroutine to store a half word from a register into memory.
3909 ;; Operand 0 is the source register (HImode)
3910 ;; Operand 1 is the destination address in a register (SImode)
3912 ;; In both this routine and the next, we must be careful not to spill
3913 ;; a memory address of reg+large_const into a separate PLUS insn, since this
3914 ;; can generate unrecognizable rtl.
3916 (define_expand "storehi"
3917   [;; store the low byte
3918    (set (match_operand 1 "" "") (match_dup 3))
3919    ;; extract the high byte
3920    (set (match_dup 2)
3921         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3922    ;; store the high byte
3923    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
3924   "TARGET_ARM"
3925   "
3926   {
3927     rtx op1 = operands[1];
3928     rtx addr = XEXP (op1, 0);
3929     enum rtx_code code = GET_CODE (addr);
3931     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3932         || code == MINUS)
3933       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
3935     operands[4] = adjust_address (op1, QImode, 1);
3936     operands[1] = adjust_address (operands[1], QImode, 0);
3937     operands[3] = gen_lowpart (QImode, operands[0]);
3938     operands[0] = gen_lowpart (SImode, operands[0]);
3939     operands[2] = gen_reg_rtx (SImode); 
3940   }"
3943 (define_expand "storehi_bigend"
3944   [(set (match_dup 4) (match_dup 3))
3945    (set (match_dup 2)
3946         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3947    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
3948   "TARGET_ARM"
3949   "
3950   {
3951     rtx op1 = operands[1];
3952     rtx addr = XEXP (op1, 0);
3953     enum rtx_code code = GET_CODE (addr);
3955     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3956         || code == MINUS)
3957       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
3959     operands[4] = adjust_address (op1, QImode, 1);
3960     operands[1] = adjust_address (operands[1], QImode, 0);
3961     operands[3] = gen_lowpart (QImode, operands[0]);
3962     operands[0] = gen_lowpart (SImode, operands[0]);
3963     operands[2] = gen_reg_rtx (SImode);
3964   }"
3967 ;; Subroutine to store a half word integer constant into memory.
3968 (define_expand "storeinthi"
3969   [(set (match_operand 0 "" "")
3970         (subreg:QI (match_operand 1 "" "") 0))
3971    (set (match_dup 3) (match_dup 2))]
3972   "TARGET_ARM"
3973   "
3974   {
3975     HOST_WIDE_INT value = INTVAL (operands[1]);
3976     rtx addr = XEXP (operands[0], 0);
3977     rtx op0 = operands[0];
3978     enum rtx_code code = GET_CODE (addr);
3980     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3981         || code == MINUS)
3982       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
3984     operands[1] = gen_reg_rtx (SImode);
3985     if (BYTES_BIG_ENDIAN)
3986       {
3987         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
3988         if ((value & 255) == ((value >> 8) & 255))
3989           operands[2] = operands[1];
3990         else
3991           {
3992             operands[2] = gen_reg_rtx (SImode);
3993             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
3994           }
3995       }
3996     else
3997       {
3998         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
3999         if ((value & 255) == ((value >> 8) & 255))
4000           operands[2] = operands[1];
4001         else
4002           {
4003             operands[2] = gen_reg_rtx (SImode);
4004             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4005           }
4006       }
4008     operands[3] = adjust_address (op0, QImode, 1);
4009     operands[0] = adjust_address (operands[0], QImode, 0);
4010     operands[2] = gen_lowpart (QImode, operands[2]);
4011   }"
4014 (define_expand "storehi_single_op"
4015   [(set (match_operand:HI 0 "memory_operand" "")
4016         (match_operand:HI 1 "general_operand" ""))]
4017   "TARGET_ARM && arm_arch4"
4018   "
4019   if (!s_register_operand (operands[1], HImode))
4020     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4021   "
4024 (define_expand "movhi"
4025   [(set (match_operand:HI 0 "general_operand" "")
4026         (match_operand:HI 1 "general_operand" ""))]
4027   "TARGET_EITHER"
4028   "
4029   if (TARGET_ARM)
4030     {
4031       if (!no_new_pseudos)
4032         {
4033           if (GET_CODE (operands[0]) == MEM)
4034             {
4035               if (arm_arch4)
4036                 {
4037                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4038                   DONE;
4039                 }
4040               if (GET_CODE (operands[1]) == CONST_INT)
4041                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4042               else
4043                 {
4044                   if (GET_CODE (operands[1]) == MEM)
4045                     operands[1] = force_reg (HImode, operands[1]);
4046                   if (BYTES_BIG_ENDIAN)
4047                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4048                   else
4049                    emit_insn (gen_storehi (operands[1], operands[0]));
4050                 }
4051               DONE;
4052             }
4053           /* Sign extend a constant, and keep it in an SImode reg.  */
4054           else if (GET_CODE (operands[1]) == CONST_INT)
4055             {
4056               rtx reg = gen_reg_rtx (SImode);
4057               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4059               /* If the constant is already valid, leave it alone.  */
4060               if (!const_ok_for_arm (val))
4061                 {
4062                   /* If setting all the top bits will make the constant 
4063                      loadable in a single instruction, then set them.  
4064                      Otherwise, sign extend the number.  */
4066                   if (const_ok_for_arm (~(val | ~0xffff)))
4067                     val |= ~0xffff;
4068                   else if (val & 0x8000)
4069                     val |= ~0xffff;
4070                 }
4072               emit_insn (gen_movsi (reg, GEN_INT (val)));
4073               operands[1] = gen_lowpart (HImode, reg);
4074             }
4075           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4076                    && GET_CODE (operands[1]) == MEM)
4077             {
4078               rtx reg = gen_reg_rtx (SImode);
4080               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4081               operands[1] = gen_lowpart (HImode, reg);
4082             }
4083           else if (!arm_arch4)
4084             {
4085              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4086                 for v4 and up architectures because LDRH instructions will
4087                 be used to access the HI values, and these cannot generate
4088                 unaligned word access faults in the MMU.  */
4089               if (GET_CODE (operands[1]) == MEM)
4090                 {
4091                   if (TARGET_MMU_TRAPS)
4092                     {
4093                       rtx base;
4094                       rtx offset = const0_rtx;
4095                       rtx reg = gen_reg_rtx (SImode);
4097                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4098                            || (GET_CODE (base) == PLUS
4099                                && (GET_CODE (offset = XEXP (base, 1))
4100                                    == CONST_INT)
4101                                && ((INTVAL(offset) & 1) != 1)
4102                                && GET_CODE (base = XEXP (base, 0)) == REG))
4103                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4104                         {
4105                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4106                           rtx new;
4108                           new = gen_rtx_MEM (SImode,
4109                                              plus_constant (base, new_offset));
4110                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4111                           emit_insn (gen_movsi (reg, new));
4112                           if (((INTVAL (offset) & 2) != 0)
4113                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4114                             {
4115                               rtx reg2 = gen_reg_rtx (SImode);
4117                               emit_insn (gen_lshrsi3 (reg2, reg,
4118                                          GEN_INT (16)));
4119                               reg = reg2;
4120                             }
4121                         }
4122                       else
4123                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4125                       operands[1] = gen_lowpart (HImode, reg);
4126                     }
4127                   else if (BYTES_BIG_ENDIAN)
4128                     {
4129                       rtx base;
4130                       rtx offset = const0_rtx;
4132                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4133                            || (GET_CODE (base) == PLUS
4134                               && (GET_CODE (offset = XEXP (base, 1))
4135                                   == CONST_INT)
4136                               && GET_CODE (base = XEXP (base, 0)) == REG))
4137                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4138                         {
4139                           rtx reg = gen_reg_rtx (SImode);
4140                           rtx new;
4142                           if ((INTVAL (offset) & 2) == 2)
4143                             {
4144                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4145                               new = gen_rtx_MEM (SImode,
4146                                                  plus_constant (base,
4147                                                                 new_offset));
4148                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4149                               emit_insn (gen_movsi (reg, new));
4150                             }
4151                           else
4152                             {
4153                               new = gen_rtx_MEM (SImode,
4154                                                  XEXP (operands[1], 0));
4155                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4156                               emit_insn (gen_rotated_loadsi (reg, new));
4157                             }
4159                           operands[1] = gen_lowpart (HImode, reg);
4160                         }
4161                       else
4162                         {
4163                           emit_insn (gen_movhi_bigend (operands[0],
4164                                                        operands[1]));
4165                           DONE;
4166                         }
4167                     }
4168                }
4169            }
4170         }
4171       /* Handle loading a large integer during reload */
4172       else if (GET_CODE (operands[1]) == CONST_INT
4173                && !const_ok_for_arm (INTVAL (operands[1]))
4174                && !const_ok_for_arm (~INTVAL (operands[1])))
4175         {
4176           /* Writing a constant to memory needs a scratch, which should
4177              be handled with SECONDARY_RELOADs.  */
4178           if (GET_CODE (operands[0]) != REG)
4179             abort ();
4181           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4182           emit_insn (gen_movsi (operands[0], operands[1]));
4183           DONE;
4184        }
4185     }
4186   else /* TARGET_THUMB */
4187     {
4188       if (!no_new_pseudos)
4189         {
4190           if (GET_CODE (operands[0]) != REG)
4191             operands[1] = force_reg (HImode, operands[1]);
4193           /* ??? We shouldn't really get invalid addresses here, but this can
4194              happen if we are passed a SP (never OK for HImode/QImode) or 
4195              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4196              HImode/QImode) relative address.  */
4197           /* ??? This should perhaps be fixed elsewhere, for instance, in
4198              fixup_stack_1, by checking for other kinds of invalid addresses,
4199              e.g. a bare reference to a virtual register.  This may confuse the
4200              alpha though, which must handle this case differently.  */
4201           if (GET_CODE (operands[0]) == MEM
4202               && !memory_address_p (GET_MODE (operands[0]),
4203                                     XEXP (operands[0], 0)))
4204             operands[0]
4205               = replace_equiv_address (operands[0],
4206                                        copy_to_reg (XEXP (operands[0], 0)));
4207    
4208           if (GET_CODE (operands[1]) == MEM
4209               && !memory_address_p (GET_MODE (operands[1]),
4210                                     XEXP (operands[1], 0)))
4211             operands[1]
4212               = replace_equiv_address (operands[1],
4213                                        copy_to_reg (XEXP (operands[1], 0)));
4214         }
4215       /* Handle loading a large integer during reload */
4216       else if (GET_CODE (operands[1]) == CONST_INT
4217                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4218         {
4219           /* Writing a constant to memory needs a scratch, which should
4220              be handled with SECONDARY_RELOADs.  */
4221           if (GET_CODE (operands[0]) != REG)
4222             abort ();
4224           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4225           emit_insn (gen_movsi (operands[0], operands[1]));
4226           DONE;
4227         }
4228     }
4229   "
4232 (define_insn "*thumb_movhi_insn"
4233   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4234         (match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4235   "TARGET_THUMB
4236    && (   register_operand (operands[0], HImode)
4237        || register_operand (operands[1], HImode))"
4238   "*
4239   switch (which_alternative)
4240     {
4241     case 0: return \"add        %0, %1, #0\";
4242     case 2: return \"strh       %1, %0\";
4243     case 3: return \"mov        %0, %1\";
4244     case 4: return \"mov        %0, %1\";
4245     case 5: return \"mov        %0, %1\";
4246     default: abort ();
4247     case 1:
4248       /* The stack pointer can end up being taken as an index register.
4249           Catch this case here and deal with it.  */
4250       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4251           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4252           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4253         {
4254           rtx ops[2];
4255           ops[0] = operands[0];
4256           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4257       
4258           output_asm_insn (\"mov        %0, %1\", ops);
4260           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4261     
4262         }
4263       return \"ldrh     %0, %1\";
4264     }"
4265   [(set_attr "length" "2,4,2,2,2,2")
4266    (set_attr "type" "*,load,store1,*,*,*")
4267    (set_attr "pool_range" "*,64,*,*,*,*")]
4271 (define_insn "rotated_loadsi"
4272   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4273         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4274                    (const_int 16)))]
4275   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4276   "*
4277   {
4278     rtx ops[2];
4280     ops[0] = operands[0];
4281     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4282     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4283     return \"\";
4284   }"
4285   [(set_attr "type" "load")
4286    (set_attr "predicable" "yes")]
4289 (define_expand "movhi_bytes"
4290   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4291    (set (match_dup 3)
4292         (zero_extend:SI (match_dup 6)))
4293    (set (match_operand:SI 0 "" "")
4294          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4295   "TARGET_ARM"
4296   "
4297   {
4298     rtx mem1, mem2;
4299     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4301     mem1 = gen_rtx_MEM (QImode, addr);
4302     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4303     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4304     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4305     operands[0] = gen_lowpart (SImode, operands[0]);
4306     operands[1] = mem1;
4307     operands[2] = gen_reg_rtx (SImode);
4308     operands[3] = gen_reg_rtx (SImode);
4309     operands[6] = mem2;
4311     if (BYTES_BIG_ENDIAN)
4312       {
4313         operands[4] = operands[2];
4314         operands[5] = operands[3];
4315       }
4316     else
4317       {
4318         operands[4] = operands[3];
4319         operands[5] = operands[2];
4320       }
4321   }"
4324 (define_expand "movhi_bigend"
4325   [(set (match_dup 2)
4326         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4327                    (const_int 16)))
4328    (set (match_dup 3)
4329         (ashiftrt:SI (match_dup 2) (const_int 16)))
4330    (set (match_operand:HI 0 "s_register_operand" "")
4331         (subreg:HI (match_dup 3) 0))]
4332   "TARGET_ARM"
4333   "
4334   operands[2] = gen_reg_rtx (SImode);
4335   operands[3] = gen_reg_rtx (SImode);
4336   "
4339 ;; Pattern to recognize insn generated default case above
4340 (define_insn "*movhi_insn_arch4"
4341   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4342         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4343   "TARGET_ARM
4344    && arm_arch4
4345    && (GET_CODE (operands[1]) != CONST_INT
4346        || const_ok_for_arm (INTVAL (operands[1]))
4347        || const_ok_for_arm (~INTVAL (operands[1])))"
4348   "@
4349    mov%?\\t%0, %1\\t%@ movhi
4350    mvn%?\\t%0, #%B1\\t%@ movhi
4351    str%?h\\t%1, %0\\t%@ movhi 
4352    ldr%?h\\t%0, %1\\t%@ movhi"
4353   [(set_attr "type" "*,*,store1,load")
4354    (set_attr "predicable" "yes")
4355    (set_attr "pool_range" "*,*,*,256")
4356    (set_attr "neg_pool_range" "*,*,*,244")]
4359 (define_insn "*movhi_insn_littleend"
4360   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4361         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4362   "TARGET_ARM
4363    && !arm_arch4
4364    && !BYTES_BIG_ENDIAN
4365    && !TARGET_MMU_TRAPS
4366    && (GET_CODE (operands[1]) != CONST_INT
4367        || const_ok_for_arm (INTVAL (operands[1]))
4368        || const_ok_for_arm (~INTVAL (operands[1])))"
4369   "@
4370    mov%?\\t%0, %1\\t%@ movhi
4371    mvn%?\\t%0, #%B1\\t%@ movhi
4372    ldr%?\\t%0, %1\\t%@ movhi"
4373   [(set_attr "type" "*,*,load")
4374    (set_attr "predicable" "yes")
4375    (set_attr "pool_range" "4096")
4376    (set_attr "neg_pool_range" "4084")]
4379 (define_insn "*movhi_insn_bigend"
4380   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4381         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4382   "TARGET_ARM
4383    && !arm_arch4
4384    && BYTES_BIG_ENDIAN
4385    && !TARGET_MMU_TRAPS
4386    && (GET_CODE (operands[1]) != CONST_INT
4387        || const_ok_for_arm (INTVAL (operands[1]))
4388        || const_ok_for_arm (~INTVAL (operands[1])))"
4389   "@
4390    mov%?\\t%0, %1\\t%@ movhi
4391    mvn%?\\t%0, #%B1\\t%@ movhi
4392    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4393   [(set_attr "type" "*,*,load")
4394    (set_attr "predicable" "yes")
4395    (set_attr "length" "4,4,8")
4396    (set_attr "pool_range" "*,*,4092")
4397    (set_attr "neg_pool_range" "*,*,4084")]
4400 (define_insn "*loadhi_si_bigend"
4401   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4402         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4403                    (const_int 16)))]
4404   "TARGET_ARM
4405    && BYTES_BIG_ENDIAN
4406    && !TARGET_MMU_TRAPS"
4407   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4408   [(set_attr "type" "load")
4409    (set_attr "predicable" "yes")
4410    (set_attr "pool_range" "4096")
4411    (set_attr "neg_pool_range" "4084")]
4414 (define_insn "*movhi_bytes"
4415   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4416         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4417   "TARGET_ARM && TARGET_MMU_TRAPS"
4418   "@
4419    mov%?\\t%0, %1\\t%@ movhi
4420    mvn%?\\t%0, #%B1\\t%@ movhi"
4421   [(set_attr "predicable" "yes")]
4424 (define_insn "thumb_movhi_clobber"
4425   [(set (match_operand:HI     0 "memory_operand"   "=m")
4426         (match_operand:HI     1 "register_operand" "l"))
4427    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4428   "TARGET_THUMB"
4429   "*
4430   abort ();"
4432         
4433 ;; We use a DImode scratch because we may occasionally need an additional
4434 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4435 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4436 (define_expand "reload_outhi"
4437   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4438               (match_operand:HI 1 "s_register_operand"        "r")
4439               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4440   "TARGET_EITHER"
4441   "if (TARGET_ARM)
4442      arm_reload_out_hi (operands);
4443    else
4444      thumb_reload_out_hi (operands);
4445   DONE;
4446   "
4449 (define_expand "reload_inhi"
4450   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4451               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4452               (match_operand:DI 2 "s_register_operand" "=&r")])]
4453   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4454   "
4455   if (TARGET_ARM)
4456     arm_reload_in_hi (operands);
4457   else
4458     thumb_reload_out_hi (operands);
4459   DONE;
4462 (define_expand "movqi"
4463   [(set (match_operand:QI 0 "general_operand" "")
4464         (match_operand:QI 1 "general_operand" ""))]
4465   "TARGET_EITHER"
4466   "
4467   if (TARGET_ARM)
4468     {
4469       /* Everything except mem = const or mem = mem can be done easily */
4471       if (!no_new_pseudos)
4472         {
4473           if (GET_CODE (operands[1]) == CONST_INT)
4474             {
4475               rtx reg = gen_reg_rtx (SImode);
4477               emit_insn (gen_movsi (reg, operands[1]));
4478               operands[1] = gen_lowpart (QImode, reg);
4479             }
4480           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4481             {
4482               rtx reg = gen_reg_rtx (SImode);
4484               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4485               operands[1] = gen_lowpart (QImode, reg);
4486             }
4487           if (GET_CODE (operands[0]) == MEM)
4488             operands[1] = force_reg (QImode, operands[1]);
4489         }
4490     }
4491   else /* TARGET_THUMB */
4492     {
4493       if (!no_new_pseudos)
4494         {
4495           if (GET_CODE (operands[0]) != REG)
4496             operands[1] = force_reg (QImode, operands[1]);
4498           /* ??? We shouldn't really get invalid addresses here, but this can
4499              happen if we are passed a SP (never OK for HImode/QImode) or
4500              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4501              HImode/QImode) relative address.  */
4502           /* ??? This should perhaps be fixed elsewhere, for instance, in
4503              fixup_stack_1, by checking for other kinds of invalid addresses,
4504              e.g. a bare reference to a virtual register.  This may confuse the
4505              alpha though, which must handle this case differently.  */
4506           if (GET_CODE (operands[0]) == MEM
4507               && !memory_address_p (GET_MODE (operands[0]),
4508                                      XEXP (operands[0], 0)))
4509             operands[0]
4510               = replace_equiv_address (operands[0],
4511                                        copy_to_reg (XEXP (operands[0], 0)));
4512           if (GET_CODE (operands[1]) == MEM
4513               && !memory_address_p (GET_MODE (operands[1]),
4514                                     XEXP (operands[1], 0)))
4515              operands[1]
4516                = replace_equiv_address (operands[1],
4517                                         copy_to_reg (XEXP (operands[1], 0)));
4518         }
4519       /* Handle loading a large integer during reload */
4520       else if (GET_CODE (operands[1]) == CONST_INT
4521                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4522         {
4523           /* Writing a constant to memory needs a scratch, which should
4524              be handled with SECONDARY_RELOADs.  */
4525           if (GET_CODE (operands[0]) != REG)
4526             abort ();
4528           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4529           emit_insn (gen_movsi (operands[0], operands[1]));
4530           DONE;
4531        }
4532     }
4533   "
4537 (define_insn "*arm_movqi_insn"
4538   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4539         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4540   "TARGET_ARM
4541    && (   register_operand (operands[0], QImode)
4542        || register_operand (operands[1], QImode))"
4543   "@
4544    mov%?\\t%0, %1
4545    mvn%?\\t%0, #%B1
4546    ldr%?b\\t%0, %1
4547    str%?b\\t%1, %0"
4548   [(set_attr "type" "*,*,load,store1")
4549    (set_attr "predicable" "yes")]
4552 (define_insn "*thumb_movqi_insn"
4553   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4554         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4555   "TARGET_THUMB
4556    && (   register_operand (operands[0], QImode)
4557        || register_operand (operands[1], QImode))"
4558   "@
4559    add\\t%0, %1, #0
4560    ldrb\\t%0, %1
4561    strb\\t%1, %0
4562    mov\\t%0, %1
4563    mov\\t%0, %1
4564    mov\\t%0, %1"
4565   [(set_attr "length" "2")
4566    (set_attr "type" "*,load,store1,*,*,*")
4567    (set_attr "pool_range" "*,32,*,*,*,*")]
4570 (define_expand "movsf"
4571   [(set (match_operand:SF 0 "general_operand" "")
4572         (match_operand:SF 1 "general_operand" ""))]
4573   "TARGET_EITHER"
4574   "
4575   if (TARGET_ARM)
4576     {
4577       if (GET_CODE (operands[0]) == MEM)
4578         operands[1] = force_reg (SFmode, operands[1]);
4579     }
4580   else /* TARGET_THUMB */
4581     {
4582       if (!no_new_pseudos)
4583         {
4584            if (GET_CODE (operands[0]) != REG)
4585              operands[1] = force_reg (SFmode, operands[1]);
4586         }
4587     }
4588   "
4591 (define_split
4592   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4593         (match_operand:SF 1 "immediate_operand" ""))]
4594   "TARGET_ARM
4595    && !TARGET_HARD_FLOAT
4596    && reload_completed
4597    && GET_CODE (operands[1]) == CONST_DOUBLE"
4598   [(set (match_dup 2) (match_dup 3))]
4599   "
4600   operands[2] = gen_lowpart (SImode, operands[0]);
4601   operands[3] = gen_lowpart (SImode, operands[1]);
4602   if (operands[2] == 0 || operands[3] == 0)
4603     FAIL;
4604   "
4607 (define_insn "*arm_movsf_soft_insn"
4608   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4609         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4610   "TARGET_ARM
4611    && !TARGET_CIRRUS
4612    && TARGET_SOFT_FLOAT
4613    && (GET_CODE (operands[0]) != MEM
4614        || register_operand (operands[1], SFmode))"
4615   "@
4616    mov%?\\t%0, %1
4617    ldr%?\\t%0, %1\\t%@ float
4618    str%?\\t%1, %0\\t%@ float"
4619   [(set_attr "length" "4,4,4")
4620    (set_attr "predicable" "yes")
4621    (set_attr "type" "*,load,store1")
4622    (set_attr "pool_range" "*,4096,*")
4623    (set_attr "neg_pool_range" "*,4084,*")]
4626 ;;; ??? This should have alternatives for constants.
4627 (define_insn "*thumb_movsf_insn"
4628   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4629         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4630   "TARGET_THUMB
4631    && (   register_operand (operands[0], SFmode) 
4632        || register_operand (operands[1], SFmode))"
4633   "@
4634    add\\t%0, %1, #0
4635    ldmia\\t%1, {%0}
4636    stmia\\t%0, {%1}
4637    ldr\\t%0, %1
4638    str\\t%1, %0
4639    mov\\t%0, %1
4640    mov\\t%0, %1"
4641   [(set_attr "length" "2")
4642    (set_attr "type" "*,load,store1,load,store1,*,*")
4643    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4646 (define_expand "movdf"
4647   [(set (match_operand:DF 0 "general_operand" "")
4648         (match_operand:DF 1 "general_operand" ""))]
4649   "TARGET_EITHER"
4650   "
4651   if (TARGET_ARM)
4652     {
4653       if (GET_CODE (operands[0]) == MEM)
4654         operands[1] = force_reg (DFmode, operands[1]);
4655     }
4656   else /* TARGET_THUMB */
4657     {
4658       if (!no_new_pseudos)
4659         {
4660           if (GET_CODE (operands[0]) != REG)
4661             operands[1] = force_reg (DFmode, operands[1]);
4662         }
4663     }
4664   "
4667 ;; Reloading a df mode value stored in integer regs to memory can require a
4668 ;; scratch reg.
4669 (define_expand "reload_outdf"
4670   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4671    (match_operand:DF 1 "s_register_operand" "r")
4672    (match_operand:SI 2 "s_register_operand" "=&r")]
4673   "TARGET_ARM"
4674   "
4675   {
4676     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4678     if (code == REG)
4679       operands[2] = XEXP (operands[0], 0);
4680     else if (code == POST_INC || code == PRE_DEC)
4681       {
4682         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4683         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4684         emit_insn (gen_movdi (operands[0], operands[1]));
4685         DONE;
4686       }
4687     else if (code == PRE_INC)
4688       {
4689         rtx reg = XEXP (XEXP (operands[0], 0), 0);
4691         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4692         operands[2] = reg;
4693       }
4694     else if (code == POST_DEC)
4695       operands[2] = XEXP (XEXP (operands[0], 0), 0);
4696     else
4697       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4698                              XEXP (XEXP (operands[0], 0), 1)));
4700     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4701                             operands[1]));
4703     if (code == POST_DEC)
4704       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4706     DONE;
4707   }"
4710 (define_insn "*movdf_soft_insn"
4711   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4712         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4713   "TARGET_ARM && TARGET_SOFT_FLOAT
4714    && !TARGET_CIRRUS
4715   "
4716   "* return output_move_double (operands);"
4717   [(set_attr "length" "8,8,8")
4718    (set_attr "type" "*,load,store2")
4719    (set_attr "pool_range" "1020")
4720    (set_attr "neg_pool_range" "1008")]
4723 ;;; ??? This should have alternatives for constants.
4724 ;;; ??? This was originally identical to the movdi_insn pattern.
4725 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4726 ;;; thumb_reorg with a memory reference.
4727 (define_insn "*thumb_movdf_insn"
4728   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4729         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
4730   "TARGET_THUMB
4731    && (   register_operand (operands[0], DFmode)
4732        || register_operand (operands[1], DFmode))"
4733   "*
4734   switch (which_alternative)
4735     {
4736     default:
4737     case 0:
4738       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4739         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4740       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4741     case 1:
4742       return \"ldmia\\t%1, {%0, %H0}\";
4743     case 2:
4744       return \"stmia\\t%0, {%1, %H1}\";
4745     case 3:
4746       return thumb_load_double_from_address (operands);
4747     case 4:
4748       operands[2] = gen_rtx (MEM, SImode,
4749                              plus_constant (XEXP (operands[0], 0), 4));
4750       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4751       return \"\";
4752     case 5:
4753       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4754         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4755       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4756     }
4757   "
4758   [(set_attr "length" "4,2,2,6,4,4")
4759    (set_attr "type" "*,load,store2,load,store2,*")
4760    (set_attr "pool_range" "*,*,*,1020,*,*")]
4763 ;; Vector Moves
4764 (define_expand "movv2si"
4765   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
4766         (match_operand:V2SI 1 "general_operand" ""))]
4767   "TARGET_REALLY_IWMMXT"
4771 (define_expand "movv4hi"
4772   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
4773         (match_operand:V4HI 1 "general_operand" ""))]
4774   "TARGET_REALLY_IWMMXT"
4778 (define_expand "movv8qi"
4779   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
4780         (match_operand:V8QI 1 "general_operand" ""))]
4781   "TARGET_REALLY_IWMMXT"
4786 ;; load- and store-multiple insns
4787 ;; The arm can load/store any set of registers, provided that they are in
4788 ;; ascending order; but that is beyond GCC so stick with what it knows.
4790 (define_expand "load_multiple"
4791   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4792                           (match_operand:SI 1 "" ""))
4793                      (use (match_operand:SI 2 "" ""))])]
4794   "TARGET_ARM"
4795   "
4796   /* Support only fixed point registers.  */
4797   if (GET_CODE (operands[2]) != CONST_INT
4798       || INTVAL (operands[2]) > 14
4799       || INTVAL (operands[2]) < 2
4800       || GET_CODE (operands[1]) != MEM
4801       || GET_CODE (operands[0]) != REG
4802       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
4803       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4804     FAIL;
4806   operands[3]
4807     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
4808                              force_reg (SImode, XEXP (operands[1], 0)),
4809                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
4810                              MEM_IN_STRUCT_P(operands[1]),
4811                              MEM_SCALAR_P (operands[1]));
4812   "
4815 ;; Load multiple with write-back
4817 (define_insn "*ldmsi_postinc4"
4818   [(match_parallel 0 "load_multiple_operation"
4819     [(set (match_operand:SI 1 "s_register_operand" "=r")
4820           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4821                    (const_int 16)))
4822      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4823           (mem:SI (match_dup 2)))
4824      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4825           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4826      (set (match_operand:SI 5 "arm_hard_register_operand" "")
4827           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
4828      (set (match_operand:SI 6 "arm_hard_register_operand" "")
4829           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
4830   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4831   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
4832   [(set_attr "type" "load")
4833    (set_attr "predicable" "yes")]
4836 (define_insn "*ldmsi_postinc3"
4837   [(match_parallel 0 "load_multiple_operation"
4838     [(set (match_operand:SI 1 "s_register_operand" "=r")
4839           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4840                    (const_int 12)))
4841      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4842           (mem:SI (match_dup 2)))
4843      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4844           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4845      (set (match_operand:SI 5 "arm_hard_register_operand" "")
4846           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
4847   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4848   "ldm%?ia\\t%1!, {%3, %4, %5}"
4849   [(set_attr "type" "load")
4850    (set_attr "predicable" "yes")]
4853 (define_insn "*ldmsi_postinc2"
4854   [(match_parallel 0 "load_multiple_operation"
4855     [(set (match_operand:SI 1 "s_register_operand" "=r")
4856           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4857                    (const_int 8)))
4858      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4859           (mem:SI (match_dup 2)))
4860      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4861           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
4862   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4863   "ldm%?ia\\t%1!, {%3, %4}"
4864   [(set_attr "type" "load")
4865    (set_attr "predicable" "yes")]
4868 ;; Ordinary load multiple
4870 (define_insn "*ldmsi4"
4871   [(match_parallel 0 "load_multiple_operation"
4872     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4873           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4874      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4875           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4876      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4877           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4878      (set (match_operand:SI 5 "arm_hard_register_operand" "")
4879           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
4880   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4881   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
4882   [(set_attr "type" "load")
4883    (set_attr "predicable" "yes")]
4886 (define_insn "*ldmsi3"
4887   [(match_parallel 0 "load_multiple_operation"
4888     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4889           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4890      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4891           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4892      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4893           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
4894   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4895   "ldm%?ia\\t%1, {%2, %3, %4}"
4896   [(set_attr "type" "load")
4897    (set_attr "predicable" "yes")]
4900 (define_insn "*ldmsi2"
4901   [(match_parallel 0 "load_multiple_operation"
4902     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4903           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4904      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4905           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
4906   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4907   "ldm%?ia\\t%1, {%2, %3}"
4908   [(set_attr "type" "load")
4909    (set_attr "predicable" "yes")]
4912 (define_expand "store_multiple"
4913   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4914                           (match_operand:SI 1 "" ""))
4915                      (use (match_operand:SI 2 "" ""))])]
4916   "TARGET_ARM"
4917   "
4918   /* Support only fixed point registers */
4919   if (GET_CODE (operands[2]) != CONST_INT
4920       || INTVAL (operands[2]) > 14
4921       || INTVAL (operands[2]) < 2
4922       || GET_CODE (operands[1]) != REG
4923       || GET_CODE (operands[0]) != MEM
4924       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
4925       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4926     FAIL;
4928   operands[3]
4929     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
4930                               force_reg (SImode, XEXP (operands[0], 0)),
4931                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
4932                               MEM_IN_STRUCT_P(operands[0]), 
4933                               MEM_SCALAR_P (operands[0]));
4934   "
4937 ;; Store multiple with write-back
4939 (define_insn "*stmsi_postinc4"
4940   [(match_parallel 0 "store_multiple_operation"
4941     [(set (match_operand:SI 1 "s_register_operand" "=r")
4942           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4943                    (const_int 16)))
4944      (set (mem:SI (match_dup 2))
4945           (match_operand:SI 3 "arm_hard_register_operand" ""))
4946      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4947           (match_operand:SI 4 "arm_hard_register_operand" ""))
4948      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
4949           (match_operand:SI 5 "arm_hard_register_operand" ""))
4950      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
4951           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
4952   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4953   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
4954   [(set_attr "predicable" "yes")
4955    (set_attr "type" "store4")]
4958 (define_insn "*stmsi_postinc3"
4959   [(match_parallel 0 "store_multiple_operation"
4960     [(set (match_operand:SI 1 "s_register_operand" "=r")
4961           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4962                    (const_int 12)))
4963      (set (mem:SI (match_dup 2))
4964           (match_operand:SI 3 "arm_hard_register_operand" ""))
4965      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4966           (match_operand:SI 4 "arm_hard_register_operand" ""))
4967      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
4968           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
4969   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4970   "stm%?ia\\t%1!, {%3, %4, %5}"
4971   [(set_attr "predicable" "yes")
4972    (set_attr "type" "store3")]
4975 (define_insn "*stmsi_postinc2"
4976   [(match_parallel 0 "store_multiple_operation"
4977     [(set (match_operand:SI 1 "s_register_operand" "=r")
4978           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4979                    (const_int 8)))
4980      (set (mem:SI (match_dup 2))
4981           (match_operand:SI 3 "arm_hard_register_operand" ""))
4982      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4983           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
4984   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4985   "stm%?ia\\t%1!, {%3, %4}"
4986   [(set_attr "predicable" "yes")
4987    (set_attr "type" "store2")]
4990 ;; Ordinary store multiple
4992 (define_insn "*stmsi4"
4993   [(match_parallel 0 "store_multiple_operation"
4994     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4995           (match_operand:SI 2 "arm_hard_register_operand" ""))
4996      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4997           (match_operand:SI 3 "arm_hard_register_operand" ""))
4998      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
4999           (match_operand:SI 4 "arm_hard_register_operand" ""))
5000      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5001           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5002   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5003   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5004   [(set_attr "predicable" "yes")
5005    (set_attr "type" "store4")]
5008 (define_insn "*stmsi3"
5009   [(match_parallel 0 "store_multiple_operation"
5010     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5011           (match_operand:SI 2 "arm_hard_register_operand" ""))
5012      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5013           (match_operand:SI 3 "arm_hard_register_operand" ""))
5014      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5015           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5016   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5017   "stm%?ia\\t%1, {%2, %3, %4}"
5018   [(set_attr "predicable" "yes")
5019    (set_attr "type" "store3")]
5022 (define_insn "*stmsi2"
5023   [(match_parallel 0 "store_multiple_operation"
5024     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5025           (match_operand:SI 2 "arm_hard_register_operand" ""))
5026      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5027           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5028   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5029   "stm%?ia\\t%1, {%2, %3}"
5030   [(set_attr "predicable" "yes")
5031    (set_attr "type" "store2")]
5034 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5035 ;; We could let this apply for blocks of less than this, but it clobbers so
5036 ;; many registers that there is then probably a better way.
5038 (define_expand "movstrqi"
5039   [(match_operand:BLK 0 "general_operand" "")
5040    (match_operand:BLK 1 "general_operand" "")
5041    (match_operand:SI 2 "const_int_operand" "")
5042    (match_operand:SI 3 "const_int_operand" "")]
5043   "TARGET_EITHER"
5044   "
5045   if (TARGET_ARM)
5046     {
5047       if (arm_gen_movstrqi (operands))
5048         DONE;
5049       FAIL;
5050     }
5051   else /* TARGET_THUMB */
5052     {
5053       if (   INTVAL (operands[3]) != 4
5054           || INTVAL (operands[2]) > 48)
5055         FAIL;
5057       thumb_expand_movstrqi (operands);
5058       DONE;
5059     }
5060   "
5063 ;; Thumb block-move insns
5065 (define_insn "movmem12b"
5066   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5067         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5068    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5069         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5070    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5071         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5072    (set (match_operand:SI 0 "register_operand" "=l")
5073         (plus:SI (match_dup 2) (const_int 12)))
5074    (set (match_operand:SI 1 "register_operand" "=l")
5075         (plus:SI (match_dup 3) (const_int 12)))
5076    (clobber (match_scratch:SI 4 "=&l"))
5077    (clobber (match_scratch:SI 5 "=&l"))
5078    (clobber (match_scratch:SI 6 "=&l"))]
5079   "TARGET_THUMB"
5080   "* return thumb_output_move_mem_multiple (3, operands);"
5081   [(set_attr "length" "4")
5082    ; This isn't entirely accurate...  It loads as well, but in terms of
5083    ; scheduling the following insn it is better to consider it as a store
5084    (set_attr "type" "store3")]
5087 (define_insn "movmem8b"
5088   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5089         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5090    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5091         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5092    (set (match_operand:SI 0 "register_operand" "=l")
5093         (plus:SI (match_dup 2) (const_int 8)))
5094    (set (match_operand:SI 1 "register_operand" "=l")
5095         (plus:SI (match_dup 3) (const_int 8)))
5096    (clobber (match_scratch:SI 4 "=&l"))
5097    (clobber (match_scratch:SI 5 "=&l"))]
5098   "TARGET_THUMB"
5099   "* return thumb_output_move_mem_multiple (2, operands);"
5100   [(set_attr "length" "4")
5101    ; This isn't entirely accurate...  It loads as well, but in terms of
5102    ; scheduling the following insn it is better to consider it as a store
5103    (set_attr "type" "store2")]
5108 ;; Compare & branch insns
5109 ;; The range calcualations are based as follows:
5110 ;; For forward branches, the address calculation returns the address of
5111 ;; the next instruction.  This is 2 beyond the branch instruction.
5112 ;; For backward branches, the address calculation returns the address of
5113 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5114 ;; instruction for the shortest sequence, and 4 before the branch instruction
5115 ;; if we have to jump around an unconditional branch.
5116 ;; To the basic branch range the PC offset must be added (this is +4).
5117 ;; So for forward branches we have 
5118 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5119 ;; And for backward branches we have 
5120 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5122 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5123 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5125 (define_insn "cbranchsi4"
5126   [(set (pc)
5127         (if_then_else
5128             (match_operator                    0 "arm_comparison_operator"
5129                             [(match_operand:SI 1 "register_operand"   "l,r")
5130                              (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5131             (label_ref       (match_operand    3 "" ""))
5132             (pc)))]
5133   "TARGET_THUMB"
5134   "*
5135   output_asm_insn (\"cmp\\t%1, %2\", operands);
5136   switch (get_attr_length (insn))
5137     {
5138     case 4:  return \"b%d0\\t%l3\";
5139     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5140     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5141     }
5142   "
5143   [(set (attr "far_jump")
5144         (if_then_else
5145             (eq_attr "length" "8")
5146             (const_string "yes")
5147             (const_string "no")))
5148    (set (attr "length") 
5149         (if_then_else
5150             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5151                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5152             (const_int 4)
5153             (if_then_else
5154                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5155                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5156                 (const_int 6)
5157                 (const_int 8))))]
5160 (define_insn "*negated_cbranchsi4"
5161   [(set (pc)
5162         (if_then_else
5163          (match_operator             0 "arm_comparison_operator"
5164           [(match_operand:SI         1 "register_operand"  "l")
5165            (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5166          (label_ref (match_operand   3 "" ""))
5167          (pc)))]
5168   "TARGET_THUMB"
5169   "*
5170   output_asm_insn (\"cmn\\t%1, %2\", operands);
5171   switch (get_attr_length (insn))
5172     {
5173     case 4:  return \"b%d0\\t%l3\";
5174     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5175     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5176     }
5177   "
5178   [(set (attr "far_jump")
5179         (if_then_else
5180             (eq_attr "length" "8")
5181             (const_string "yes")
5182             (const_string "no")))
5183    (set (attr "length") 
5184         (if_then_else
5185             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5186                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5187             (const_int 4)
5188             (if_then_else
5189                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5190                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5191                 (const_int 6)
5192                 (const_int 8))))]
5196 ;; Comparison and test insns
5198 (define_expand "cmpsi"
5199   [(match_operand:SI 0 "s_register_operand" "")
5200    (match_operand:SI 1 "arm_add_operand" "")]
5201   "TARGET_ARM"
5202   "{
5203     arm_compare_op0 = operands[0];
5204     arm_compare_op1 = operands[1];
5205     DONE;
5206   }"
5209 (define_expand "cmpsf"
5210   [(match_operand:SF 0 "s_register_operand" "")
5211    (match_operand:SF 1 "fpa_rhs_operand" "")]
5212   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5213   "
5214   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5215     operands[1] = force_reg (SFmode, operands[1]);
5217   arm_compare_op0 = operands[0];
5218   arm_compare_op1 = operands[1];
5219   DONE;
5220   "
5223 (define_expand "cmpdf"
5224   [(match_operand:DF 0 "s_register_operand" "")
5225    (match_operand:DF 1 "fpa_rhs_operand" "")]
5226   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5227   "
5228   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5229     operands[1] = force_reg (DFmode, operands[1]);
5231   arm_compare_op0 = operands[0];
5232   arm_compare_op1 = operands[1];
5233   DONE;
5234   "
5237 (define_insn "*arm_cmpsi_insn"
5238   [(set (reg:CC CC_REGNUM)
5239         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5240                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5241   "TARGET_ARM"
5242   "@
5243    cmp%?\\t%0, %1
5244    cmn%?\\t%0, #%n1"
5245   [(set_attr "conds" "set")]
5248 (define_insn "*cmpsi_shiftsi"
5249   [(set (reg:CC CC_REGNUM)
5250         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
5251                     (match_operator:SI  3 "shift_operator"
5252                      [(match_operand:SI 1 "s_register_operand" "r")
5253                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5254   "TARGET_ARM"
5255   "cmp%?\\t%0, %1%S3"
5256   [(set_attr "conds" "set")
5257    (set_attr "shift" "1")
5258    ]
5261 (define_insn "*cmpsi_shiftsi_swp"
5262   [(set (reg:CC_SWP CC_REGNUM)
5263         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5264                          [(match_operand:SI 1 "s_register_operand" "r")
5265                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
5266                         (match_operand:SI 0 "s_register_operand" "r")))]
5267   "TARGET_ARM"
5268   "cmp%?\\t%0, %1%S3"
5269   [(set_attr "conds" "set")
5270    (set_attr "shift" "1")
5271    ]
5274 (define_insn "*cmpsi_neg_shiftsi"
5275   [(set (reg:CC CC_REGNUM)
5276         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5277                     (neg:SI (match_operator:SI 3 "shift_operator"
5278                              [(match_operand:SI 1 "s_register_operand" "r")
5279                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5280   "TARGET_ARM"
5281   "cmn%?\\t%0, %1%S3"
5282   [(set_attr "conds" "set")
5283    (set_attr "shift" "1")
5284    ]
5287 ;; Cirrus SF compare instruction
5288 (define_insn "*cirrus_cmpsf"
5289   [(set (reg:CCFP CC_REGNUM)
5290         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5291                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
5292   "TARGET_ARM && TARGET_CIRRUS"
5293   "cfcmps%?\\tr15, %V0, %V1"
5294   [(set_attr "type"   "mav_farith")
5295    (set_attr "cirrus" "compare")]
5298 ;; Cirrus DF compare instruction
5299 (define_insn "*cirrus_cmpdf"
5300   [(set (reg:CCFP CC_REGNUM)
5301         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5302                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
5303   "TARGET_ARM && TARGET_CIRRUS"
5304   "cfcmpd%?\\tr15, %V0, %V1"
5305   [(set_attr "type"   "mav_farith")
5306    (set_attr "cirrus" "compare")]
5309 ;; Cirrus DI compare instruction
5310 (define_expand "cmpdi"
5311   [(match_operand:DI 0 "cirrus_fp_register" "")
5312    (match_operand:DI 1 "cirrus_fp_register" "")]
5313   "TARGET_ARM && TARGET_CIRRUS"
5314   "{
5315      arm_compare_op0 = operands[0];
5316      arm_compare_op1 = operands[1];
5317      DONE;
5318    }")
5320 (define_insn "*cirrus_cmpdi"
5321   [(set (reg:CC CC_REGNUM)
5322         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5323                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
5324   "TARGET_ARM && TARGET_CIRRUS"
5325   "cfcmp64%?\\tr15, %V0, %V1"
5326   [(set_attr "type"   "mav_farith")
5327    (set_attr "cirrus" "compare")]
5330 ; This insn allows redundant compares to be removed by cse, nothing should
5331 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5332 ; is deleted later on. The match_dup will match the mode here, so that
5333 ; mode changes of the condition codes aren't lost by this even though we don't
5334 ; specify what they are.
5336 (define_insn "*deleted_compare"
5337   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5338   "TARGET_ARM"
5339   "\\t%@ deleted compare"
5340   [(set_attr "conds" "set")
5341    (set_attr "length" "0")]
5345 ;; Conditional branch insns
5347 (define_expand "beq"
5348   [(set (pc)
5349         (if_then_else (eq (match_dup 1) (const_int 0))
5350                       (label_ref (match_operand 0 "" ""))
5351                       (pc)))]
5352   "TARGET_ARM"
5353   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5356 (define_expand "bne"
5357   [(set (pc)
5358         (if_then_else (ne (match_dup 1) (const_int 0))
5359                       (label_ref (match_operand 0 "" ""))
5360                       (pc)))]
5361   "TARGET_ARM"
5362   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5365 (define_expand "bgt"
5366   [(set (pc)
5367         (if_then_else (gt (match_dup 1) (const_int 0))
5368                       (label_ref (match_operand 0 "" ""))
5369                       (pc)))]
5370   "TARGET_ARM"
5371   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5374 (define_expand "ble"
5375   [(set (pc)
5376         (if_then_else (le (match_dup 1) (const_int 0))
5377                       (label_ref (match_operand 0 "" ""))
5378                       (pc)))]
5379   "TARGET_ARM"
5380   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5383 (define_expand "bge"
5384   [(set (pc)
5385         (if_then_else (ge (match_dup 1) (const_int 0))
5386                       (label_ref (match_operand 0 "" ""))
5387                       (pc)))]
5388   "TARGET_ARM"
5389   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5392 (define_expand "blt"
5393   [(set (pc)
5394         (if_then_else (lt (match_dup 1) (const_int 0))
5395                       (label_ref (match_operand 0 "" ""))
5396                       (pc)))]
5397   "TARGET_ARM"
5398   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5401 (define_expand "bgtu"
5402   [(set (pc)
5403         (if_then_else (gtu (match_dup 1) (const_int 0))
5404                       (label_ref (match_operand 0 "" ""))
5405                       (pc)))]
5406   "TARGET_ARM"
5407   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5410 (define_expand "bleu"
5411   [(set (pc)
5412         (if_then_else (leu (match_dup 1) (const_int 0))
5413                       (label_ref (match_operand 0 "" ""))
5414                       (pc)))]
5415   "TARGET_ARM"
5416   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5419 (define_expand "bgeu"
5420   [(set (pc)
5421         (if_then_else (geu (match_dup 1) (const_int 0))
5422                       (label_ref (match_operand 0 "" ""))
5423                       (pc)))]
5424   "TARGET_ARM"
5425   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5428 (define_expand "bltu"
5429   [(set (pc)
5430         (if_then_else (ltu (match_dup 1) (const_int 0))
5431                       (label_ref (match_operand 0 "" ""))
5432                       (pc)))]
5433   "TARGET_ARM"
5434   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5437 (define_expand "bunordered"
5438   [(set (pc)
5439         (if_then_else (unordered (match_dup 1) (const_int 0))
5440                       (label_ref (match_operand 0 "" ""))
5441                       (pc)))]
5442   "TARGET_ARM && TARGET_HARD_FLOAT"
5443   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5444                                       arm_compare_op1);"
5447 (define_expand "bordered"
5448   [(set (pc)
5449         (if_then_else (ordered (match_dup 1) (const_int 0))
5450                       (label_ref (match_operand 0 "" ""))
5451                       (pc)))]
5452   "TARGET_ARM && TARGET_HARD_FLOAT"
5453   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5454                                       arm_compare_op1);"
5457 (define_expand "bungt"
5458   [(set (pc)
5459         (if_then_else (ungt (match_dup 1) (const_int 0))
5460                       (label_ref (match_operand 0 "" ""))
5461                       (pc)))]
5462   "TARGET_ARM && TARGET_HARD_FLOAT"
5463   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5466 (define_expand "bunlt"
5467   [(set (pc)
5468         (if_then_else (unlt (match_dup 1) (const_int 0))
5469                       (label_ref (match_operand 0 "" ""))
5470                       (pc)))]
5471   "TARGET_ARM && TARGET_HARD_FLOAT"
5472   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5475 (define_expand "bunge"
5476   [(set (pc)
5477         (if_then_else (unge (match_dup 1) (const_int 0))
5478                       (label_ref (match_operand 0 "" ""))
5479                       (pc)))]
5480   "TARGET_ARM && TARGET_HARD_FLOAT"
5481   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5484 (define_expand "bunle"
5485   [(set (pc)
5486         (if_then_else (unle (match_dup 1) (const_int 0))
5487                       (label_ref (match_operand 0 "" ""))
5488                       (pc)))]
5489   "TARGET_ARM && TARGET_HARD_FLOAT"
5490   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5493 ;; The following two patterns need two branch instructions, since there is
5494 ;; no single instruction that will handle all cases.
5495 (define_expand "buneq"
5496   [(set (pc)
5497         (if_then_else (uneq (match_dup 1) (const_int 0))
5498                       (label_ref (match_operand 0 "" ""))
5499                       (pc)))]
5500   "TARGET_ARM && TARGET_HARD_FLOAT"
5501   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5504 (define_expand "bltgt"
5505   [(set (pc)
5506         (if_then_else (ltgt (match_dup 1) (const_int 0))
5507                       (label_ref (match_operand 0 "" ""))
5508                       (pc)))]
5509   "TARGET_ARM && TARGET_HARD_FLOAT"
5510   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5514 ;; Patterns to match conditional branch insns.
5517 ; Special pattern to match UNEQ.
5518 (define_insn "*arm_buneq"
5519   [(set (pc)
5520         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5521                       (label_ref (match_operand 0 "" ""))
5522                       (pc)))]
5523   "TARGET_ARM && TARGET_HARD_FLOAT"
5524   "*
5525   if (arm_ccfsm_state != 0)
5526     abort ();
5528   return \"bvs\\t%l0\;beq\\t%l0\";
5529   "
5530   [(set_attr "conds" "jump_clob")
5531    (set_attr "length" "8")]
5534 ; Special pattern to match LTGT.
5535 (define_insn "*arm_bltgt"
5536   [(set (pc)
5537         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5538                       (label_ref (match_operand 0 "" ""))
5539                       (pc)))]
5540   "TARGET_ARM && TARGET_HARD_FLOAT"
5541   "*
5542   if (arm_ccfsm_state != 0)
5543     abort ();
5545   return \"bmi\\t%l0\;bgt\\t%l0\";
5546   "
5547   [(set_attr "conds" "jump_clob")
5548    (set_attr "length" "8")]
5551 (define_insn "*arm_cond_branch"
5552   [(set (pc)
5553         (if_then_else (match_operator 1 "arm_comparison_operator"
5554                        [(match_operand 2 "cc_register" "") (const_int 0)])
5555                       (label_ref (match_operand 0 "" ""))
5556                       (pc)))]
5557   "TARGET_ARM"
5558   "*
5559   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5560     {
5561       arm_ccfsm_state += 2;
5562       return \"\";
5563     }
5564   return \"b%d1\\t%l0\";
5565   "
5566   [(set_attr "conds" "use")]
5569 ; Special pattern to match reversed UNEQ.
5570 (define_insn "*arm_buneq_reversed"
5571   [(set (pc)
5572         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5573                       (pc)
5574                       (label_ref (match_operand 0 "" ""))))]
5575   "TARGET_ARM && TARGET_HARD_FLOAT"
5576   "*
5577   if (arm_ccfsm_state != 0)
5578     abort ();
5580   return \"bmi\\t%l0\;bgt\\t%l0\";
5581   "
5582   [(set_attr "conds" "jump_clob")
5583    (set_attr "length" "8")]
5586 ; Special pattern to match reversed LTGT.
5587 (define_insn "*arm_bltgt_reversed"
5588   [(set (pc)
5589         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5590                       (pc)
5591                       (label_ref (match_operand 0 "" ""))))]
5592   "TARGET_ARM && TARGET_HARD_FLOAT"
5593   "*
5594   if (arm_ccfsm_state != 0)
5595     abort ();
5597   return \"bvs\\t%l0\;beq\\t%l0\";
5598   "
5599   [(set_attr "conds" "jump_clob")
5600    (set_attr "length" "8")]
5603 (define_insn "*arm_cond_branch_reversed"
5604   [(set (pc)
5605         (if_then_else (match_operator 1 "arm_comparison_operator"
5606                        [(match_operand 2 "cc_register" "") (const_int 0)])
5607                       (pc)
5608                       (label_ref (match_operand 0 "" ""))))]
5609   "TARGET_ARM"
5610   "*
5611   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5612     {
5613       arm_ccfsm_state += 2;
5614       return \"\";
5615     }
5616   return \"b%D1\\t%l0\";
5617   "
5618   [(set_attr "conds" "use")]
5623 ; scc insns
5625 (define_expand "seq"
5626   [(set (match_operand:SI 0 "s_register_operand" "")
5627         (eq:SI (match_dup 1) (const_int 0)))]
5628   "TARGET_ARM"
5629   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5632 (define_expand "sne"
5633   [(set (match_operand:SI 0 "s_register_operand" "")
5634         (ne:SI (match_dup 1) (const_int 0)))]
5635   "TARGET_ARM"
5636   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5639 (define_expand "sgt"
5640   [(set (match_operand:SI 0 "s_register_operand" "")
5641         (gt:SI (match_dup 1) (const_int 0)))]
5642   "TARGET_ARM"
5643   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5646 (define_expand "sle"
5647   [(set (match_operand:SI 0 "s_register_operand" "")
5648         (le:SI (match_dup 1) (const_int 0)))]
5649   "TARGET_ARM"
5650   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5653 (define_expand "sge"
5654   [(set (match_operand:SI 0 "s_register_operand" "")
5655         (ge:SI (match_dup 1) (const_int 0)))]
5656   "TARGET_ARM"
5657   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5660 (define_expand "slt"
5661   [(set (match_operand:SI 0 "s_register_operand" "")
5662         (lt:SI (match_dup 1) (const_int 0)))]
5663   "TARGET_ARM"
5664   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5667 (define_expand "sgtu"
5668   [(set (match_operand:SI 0 "s_register_operand" "")
5669         (gtu:SI (match_dup 1) (const_int 0)))]
5670   "TARGET_ARM"
5671   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5674 (define_expand "sleu"
5675   [(set (match_operand:SI 0 "s_register_operand" "")
5676         (leu:SI (match_dup 1) (const_int 0)))]
5677   "TARGET_ARM"
5678   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5681 (define_expand "sgeu"
5682   [(set (match_operand:SI 0 "s_register_operand" "")
5683         (geu:SI (match_dup 1) (const_int 0)))]
5684   "TARGET_ARM"
5685   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5688 (define_expand "sltu"
5689   [(set (match_operand:SI 0 "s_register_operand" "")
5690         (ltu:SI (match_dup 1) (const_int 0)))]
5691   "TARGET_ARM"
5692   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5695 (define_expand "sunordered"
5696   [(set (match_operand:SI 0 "s_register_operand" "")
5697         (unordered:SI (match_dup 1) (const_int 0)))]
5698   "TARGET_ARM && TARGET_HARD_FLOAT"
5699   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5700                                       arm_compare_op1);"
5703 (define_expand "sordered"
5704   [(set (match_operand:SI 0 "s_register_operand" "")
5705         (ordered:SI (match_dup 1) (const_int 0)))]
5706   "TARGET_ARM && TARGET_HARD_FLOAT"
5707   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5708                                       arm_compare_op1);"
5711 (define_expand "sungt"
5712   [(set (match_operand:SI 0 "s_register_operand" "")
5713         (ungt:SI (match_dup 1) (const_int 0)))]
5714   "TARGET_ARM && TARGET_HARD_FLOAT"
5715   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
5716                                       arm_compare_op1);"
5719 (define_expand "sunge"
5720   [(set (match_operand:SI 0 "s_register_operand" "")
5721         (unge:SI (match_dup 1) (const_int 0)))]
5722   "TARGET_ARM && TARGET_HARD_FLOAT"
5723   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
5724                                       arm_compare_op1);"
5727 (define_expand "sunlt"
5728   [(set (match_operand:SI 0 "s_register_operand" "")
5729         (unlt:SI (match_dup 1) (const_int 0)))]
5730   "TARGET_ARM && TARGET_HARD_FLOAT"
5731   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
5732                                       arm_compare_op1);"
5735 (define_expand "sunle"
5736   [(set (match_operand:SI 0 "s_register_operand" "")
5737         (unle:SI (match_dup 1) (const_int 0)))]
5738   "TARGET_ARM && TARGET_HARD_FLOAT"
5739   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
5740                                       arm_compare_op1);"
5743 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
5744 ;;; simple ARM instructions. 
5746 ; (define_expand "suneq"
5747 ;   [(set (match_operand:SI 0 "s_register_operand" "")
5748 ;       (uneq:SI (match_dup 1) (const_int 0)))]
5749 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
5750 ;   "abort ();"
5751 ; )
5753 ; (define_expand "sltgt"
5754 ;   [(set (match_operand:SI 0 "s_register_operand" "")
5755 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
5756 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
5757 ;   "abort ();"
5758 ; )
5760 (define_insn "*mov_scc"
5761   [(set (match_operand:SI 0 "s_register_operand" "=r")
5762         (match_operator:SI 1 "arm_comparison_operator"
5763          [(match_operand 2 "cc_register" "") (const_int 0)]))]
5764   "TARGET_ARM"
5765   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
5766   [(set_attr "conds" "use")
5767    (set_attr "length" "8")]
5770 (define_insn "*mov_negscc"
5771   [(set (match_operand:SI 0 "s_register_operand" "=r")
5772         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
5773                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
5774   "TARGET_ARM"
5775   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
5776   [(set_attr "conds" "use")
5777    (set_attr "length" "8")]
5780 (define_insn "*mov_notscc"
5781   [(set (match_operand:SI 0 "s_register_operand" "=r")
5782         (not:SI (match_operator:SI 1 "arm_comparison_operator"
5783                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
5784   "TARGET_ARM"
5785   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
5786   [(set_attr "conds" "use")
5787    (set_attr "length" "8")]
5791 ;; Conditional move insns
5793 (define_expand "movsicc"
5794   [(set (match_operand:SI 0 "s_register_operand" "")
5795         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
5796                          (match_operand:SI 2 "arm_not_operand" "")
5797                          (match_operand:SI 3 "arm_not_operand" "")))]
5798   "TARGET_ARM"
5799   "
5800   {
5801     enum rtx_code code = GET_CODE (operands[1]);
5802     rtx ccreg;
5804     if (code == UNEQ || code == LTGT)
5805       FAIL;
5807     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5808     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5809   }"
5812 (define_expand "movsfcc"
5813   [(set (match_operand:SF 0 "s_register_operand" "")
5814         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
5815                          (match_operand:SF 2 "s_register_operand" "")
5816                          (match_operand:SF 3 "nonmemory_operand" "")))]
5817   "TARGET_ARM"
5818   "
5819   {
5820     enum rtx_code code = GET_CODE (operands[1]);
5821     rtx ccreg;
5823     if (code == UNEQ || code == LTGT)
5824       FAIL;
5826     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
5827        Otherwise, ensure it is a valid FP add operand */
5828     if ((!TARGET_HARD_FLOAT)
5829         || (!fpa_add_operand (operands[3], SFmode)))
5830       operands[3] = force_reg (SFmode, operands[3]);
5832     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5833     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5834   }"
5837 (define_expand "movdfcc"
5838   [(set (match_operand:DF 0 "s_register_operand" "")
5839         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
5840                          (match_operand:DF 2 "s_register_operand" "")
5841                          (match_operand:DF 3 "fpa_add_operand" "")))]
5842   "TARGET_ARM && TARGET_HARD_FLOAT"
5843   "
5844   {
5845     enum rtx_code code = GET_CODE (operands[1]);
5846     rtx ccreg;
5848     if (code == UNEQ || code == LTGT)
5849       FAIL;
5851     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5852     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5853   }"
5856 (define_insn "*movsicc_insn"
5857   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
5858         (if_then_else:SI
5859          (match_operator 3 "arm_comparison_operator"
5860           [(match_operand 4 "cc_register" "") (const_int 0)])
5861          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
5862          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
5863   "TARGET_ARM"
5864   "@
5865    mov%D3\\t%0, %2
5866    mvn%D3\\t%0, #%B2
5867    mov%d3\\t%0, %1
5868    mvn%d3\\t%0, #%B1
5869    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
5870    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
5871    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
5872    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
5873   [(set_attr "length" "4,4,4,4,8,8,8,8")
5874    (set_attr "conds" "use")]
5877 (define_insn "*movsfcc_soft_insn"
5878   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
5879         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
5880                           [(match_operand 4 "cc_register" "") (const_int 0)])
5881                          (match_operand:SF 1 "s_register_operand" "0,r")
5882                          (match_operand:SF 2 "s_register_operand" "r,0")))]
5883   "TARGET_ARM && TARGET_SOFT_FLOAT"
5884   "@
5885    mov%D3\\t%0, %2
5886    mov%d3\\t%0, %1"
5887   [(set_attr "conds" "use")]
5891 ;; Jump and linkage insns
5893 (define_expand "jump"
5894   [(set (pc)
5895         (label_ref (match_operand 0 "" "")))]
5896   "TARGET_EITHER"
5897   ""
5900 (define_insn "*arm_jump"
5901   [(set (pc)
5902         (label_ref (match_operand 0 "" "")))]
5903   "TARGET_ARM"
5904   "*
5905   {
5906     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5907       {
5908         arm_ccfsm_state += 2;
5909         return \"\";
5910       }
5911     return \"b%?\\t%l0\";
5912   }
5913   "
5914   [(set_attr "predicable" "yes")]
5917 (define_insn "*thumb_jump"
5918   [(set (pc)
5919         (label_ref (match_operand 0 "" "")))]
5920   "TARGET_THUMB"
5921   "*
5922   if (get_attr_length (insn) == 2)
5923     return \"b\\t%l0\";
5924   return \"bl\\t%l0\\t%@ far jump\";
5925   "
5926   [(set (attr "far_jump")
5927         (if_then_else
5928             (eq_attr "length" "4")
5929             (const_string "yes")
5930             (const_string "no")))
5931    (set (attr "length") 
5932         (if_then_else
5933             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
5934                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
5935             (const_int 2)
5936             (const_int 4)))]
5939 (define_expand "call"
5940   [(parallel [(call (match_operand 0 "memory_operand" "")
5941                     (match_operand 1 "general_operand" ""))
5942               (use (match_operand 2 "" ""))
5943               (clobber (reg:SI LR_REGNUM))])]
5944   "TARGET_EITHER"
5945   "
5946   {
5947     rtx callee;
5948     
5949     /* In an untyped call, we can get NULL for operand 2.  */
5950     if (operands[2] == NULL_RTX)
5951       operands[2] = const0_rtx;
5952       
5953     /* This is to decide if we should generate indirect calls by loading the
5954        32 bit address of the callee into a register before performing the
5955        branch and link.  operand[2] encodes the long_call/short_call
5956        attribute of the function being called.  This attribute is set whenever
5957        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
5958        is used, and the short_call attribute can also be set if function is
5959        declared as static or if it has already been defined in the current
5960        compilation unit.  See arm.c and arm.h for info about this.  The third
5961        parameter to arm_is_longcall_p is used to tell it which pattern
5962        invoked it.  */
5963     callee  = XEXP (operands[0], 0);
5964     
5965     if (GET_CODE (callee) != REG
5966        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
5967       XEXP (operands[0], 0) = force_reg (Pmode, callee);
5968   }"
5971 (define_insn "*call_reg"
5972   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
5973          (match_operand 1 "" ""))
5974    (use (match_operand 2 "" ""))
5975    (clobber (reg:SI LR_REGNUM))]
5976   "TARGET_ARM"
5977   "*
5978   return output_call (operands);
5979   "
5980   ;; length is worst case, normally it is only two
5981   [(set_attr "length" "12")
5982    (set_attr "type" "call")]
5985 (define_insn "*call_mem"
5986   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
5987          (match_operand 1 "" ""))
5988    (use (match_operand 2 "" ""))
5989    (clobber (reg:SI LR_REGNUM))]
5990   "TARGET_ARM"
5991   "*
5992   return output_call_mem (operands);
5993   "
5994   [(set_attr "length" "12")
5995    (set_attr "type" "call")]
5998 (define_insn "*call_indirect"
5999   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6000          (match_operand 1 "" ""))
6001    (use (match_operand 2 "" ""))
6002    (clobber (reg:SI LR_REGNUM))]
6003   "TARGET_THUMB"
6004   "*
6005   {
6006     if (TARGET_CALLER_INTERWORKING)
6007       return \"bl\\t%__interwork_call_via_%0\";
6008     else
6009       return \"bl\\t%__call_via_%0\";
6010   }"
6011   [(set_attr "type" "call")]
6014 (define_insn "*call_value_indirect"
6015   [(set (match_operand 0 "" "")
6016         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6017               (match_operand 2 "" "")))
6018    (use (match_operand 3 "" ""))
6019    (clobber (reg:SI LR_REGNUM))]
6020   "TARGET_THUMB"
6021   "*
6022   {
6023     if (TARGET_CALLER_INTERWORKING)
6024       return \"bl\\t%__interwork_call_via_%1\";
6025     else
6026       return \"bl\\t%__call_via_%1\";
6027   }"
6028   [(set_attr "type" "call")]
6031 (define_expand "call_value"
6032   [(parallel [(set (match_operand       0 "" "")
6033                    (call (match_operand 1 "memory_operand" "")
6034                          (match_operand 2 "general_operand" "")))
6035               (use (match_operand 3 "" ""))
6036               (clobber (reg:SI LR_REGNUM))])]
6037   "TARGET_EITHER"
6038   "
6039   {
6040     rtx callee = XEXP (operands[1], 0);
6041     
6042     /* In an untyped call, we can get NULL for operand 2.  */
6043     if (operands[3] == 0)
6044       operands[3] = const0_rtx;
6045       
6046     /* See the comment in define_expand \"call\".  */
6047     if (GET_CODE (callee) != REG
6048         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6049       XEXP (operands[1], 0) = force_reg (Pmode, callee);
6050   }"
6053 (define_insn "*call_value_reg"
6054   [(set (match_operand 0 "" "")
6055         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6056               (match_operand 2 "" "")))
6057    (use (match_operand 3 "" ""))
6058    (clobber (reg:SI LR_REGNUM))]
6059   "TARGET_ARM"
6060   "*
6061   return output_call (&operands[1]);
6062   "
6063   [(set_attr "length" "12")
6064    (set_attr "type" "call")]
6067 (define_insn "*call_value_mem"
6068   [(set (match_operand 0 "" "")
6069         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
6070               (match_operand 2 "" "")))
6071    (use (match_operand 3 "" ""))
6072    (clobber (reg:SI LR_REGNUM))]
6073   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6074   "*
6075   return output_call_mem (&operands[1]);
6076   "
6077   [(set_attr "length" "12")
6078    (set_attr "type" "call")]
6081 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6082 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6084 (define_insn "*call_symbol"
6085   [(call (mem:SI (match_operand:SI 0 "" ""))
6086          (match_operand 1 "" ""))
6087    (use (match_operand 2 "" ""))
6088    (clobber (reg:SI LR_REGNUM))]
6089   "TARGET_ARM
6090    && (GET_CODE (operands[0]) == SYMBOL_REF)
6091    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6092   "*
6093   {
6094     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6095   }"
6096   [(set_attr "type" "call")]
6099 (define_insn "*call_value_symbol"
6100   [(set (match_operand 0 "s_register_operand" "")
6101         (call (mem:SI (match_operand:SI 1 "" ""))
6102         (match_operand:SI 2 "" "")))
6103    (use (match_operand 3 "" ""))
6104    (clobber (reg:SI LR_REGNUM))]
6105   "TARGET_ARM
6106    && (GET_CODE (operands[1]) == SYMBOL_REF)
6107    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6108   "*
6109   {
6110     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6111   }"
6112   [(set_attr "type" "call")]
6115 (define_insn "*call_insn"
6116   [(call (mem:SI (match_operand:SI 0 "" ""))
6117          (match_operand:SI 1 "" ""))
6118    (use (match_operand 2 "" ""))
6119    (clobber (reg:SI LR_REGNUM))]
6120   "TARGET_THUMB
6121    && GET_CODE (operands[0]) == SYMBOL_REF
6122    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6123   "bl\\t%a0"
6124   [(set_attr "length" "4")
6125    (set_attr "type" "call")]
6128 (define_insn "*call_value_insn"
6129   [(set (match_operand 0 "register_operand" "")
6130         (call (mem:SI (match_operand 1 "" ""))
6131               (match_operand 2 "" "")))
6132    (use (match_operand 3 "" ""))
6133    (clobber (reg:SI LR_REGNUM))]
6134   "TARGET_THUMB
6135    && GET_CODE (operands[1]) == SYMBOL_REF
6136    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6137   "bl\\t%a1"
6138   [(set_attr "length" "4")
6139    (set_attr "type" "call")]
6142 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6143 (define_expand "sibcall"
6144   [(parallel [(call (match_operand 0 "memory_operand" "")
6145                     (match_operand 1 "general_operand" ""))
6146               (return)
6147               (use (match_operand 2 "" ""))])]
6148   "TARGET_ARM"
6149   "
6150   {
6151     if (operands[2] == NULL_RTX)
6152       operands[2] = const0_rtx;
6153   }"
6156 (define_expand "sibcall_value"
6157   [(parallel [(set (match_operand 0 "register_operand" "")
6158                    (call (match_operand 1 "memory_operand" "")
6159                          (match_operand 2 "general_operand" "")))
6160               (return)
6161               (use (match_operand 3 "" ""))])]
6162   "TARGET_ARM"
6163   "
6164   {
6165     if (operands[3] == NULL_RTX)
6166       operands[3] = const0_rtx;
6167   }"
6170 (define_insn "*sibcall_insn"
6171  [(call (mem:SI (match_operand:SI 0 "" "X"))
6172         (match_operand 1 "" ""))
6173   (return)
6174   (use (match_operand 2 "" ""))]
6175   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6176   "*
6177   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6178   "
6179   [(set_attr "type" "call")]
6182 (define_insn "*sibcall_value_insn"
6183  [(set (match_operand 0 "s_register_operand" "")
6184        (call (mem:SI (match_operand:SI 1 "" "X"))
6185              (match_operand 2 "" "")))
6186   (return)
6187   (use (match_operand 3 "" ""))]
6188   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6189   "*
6190   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6191   "
6192   [(set_attr "type" "call")]
6195 ;; Often the return insn will be the same as loading from memory, so set attr
6196 (define_insn "return"
6197   [(return)]
6198   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6199   "*
6200   {
6201     if (arm_ccfsm_state == 2)
6202       {
6203         arm_ccfsm_state += 2;
6204         return \"\";
6205       }
6206     return output_return_instruction (const_true_rtx, TRUE, FALSE);
6207   }"
6208   [(set_attr "type" "load")
6209    (set_attr "length" "12")
6210    (set_attr "predicable" "yes")]
6213 (define_insn "*cond_return"
6214   [(set (pc)
6215         (if_then_else (match_operator 0 "arm_comparison_operator"
6216                        [(match_operand 1 "cc_register" "") (const_int 0)])
6217                       (return)
6218                       (pc)))]
6219   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6220   "*
6221   {
6222     if (arm_ccfsm_state == 2)
6223       {
6224         arm_ccfsm_state += 2;
6225         return \"\";
6226       }
6227     return output_return_instruction (operands[0], TRUE, FALSE);
6228   }"
6229   [(set_attr "conds" "use")
6230    (set_attr "length" "12")
6231    (set_attr "type" "load")]
6234 (define_insn "*cond_return_inverted"
6235   [(set (pc)
6236         (if_then_else (match_operator 0 "arm_comparison_operator"
6237                        [(match_operand 1 "cc_register" "") (const_int 0)])
6238                       (pc)
6239                       (return)))]
6240   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6241   "*
6242   {
6243     if (arm_ccfsm_state == 2)
6244       {
6245         arm_ccfsm_state += 2;
6246         return \"\";
6247       }
6248     return output_return_instruction (operands[0], TRUE, TRUE);
6249   }"
6250   [(set_attr "conds" "use")
6251    (set_attr "type" "load")]
6254 ;; Generate a sequence of instructions to determine if the processor is
6255 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6256 ;; mask.
6258 (define_expand "return_addr_mask"
6259   [(set (match_dup 1)
6260       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6261                        (const_int 0)))
6262    (set (match_operand:SI 0 "s_register_operand" "")
6263       (if_then_else:SI (eq (match_dup 1) (const_int 0))
6264                        (const_int -1)
6265                        (const_int 67108860)))] ; 0x03fffffc
6266   "TARGET_ARM"
6267   "
6268   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6269   ")
6271 (define_insn "*check_arch2"
6272   [(set (match_operand:CC_NOOV 0 "cc_register" "")
6273       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6274                        (const_int 0)))]
6275   "TARGET_ARM"
6276   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6277   [(set_attr "length" "8")
6278    (set_attr "conds" "set")]
6281 ;; Call subroutine returning any type.
6283 (define_expand "untyped_call"
6284   [(parallel [(call (match_operand 0 "" "")
6285                     (const_int 0))
6286               (match_operand 1 "" "")
6287               (match_operand 2 "" "")])]
6288   "TARGET_ARM"
6289   "
6290   {
6291     int i;
6293     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6295     for (i = 0; i < XVECLEN (operands[2], 0); i++)
6296       {
6297         rtx set = XVECEXP (operands[2], 0, i);
6299         emit_move_insn (SET_DEST (set), SET_SRC (set));
6300       }
6302     /* The optimizer does not know that the call sets the function value
6303        registers we stored in the result block.  We avoid problems by
6304        claiming that all hard registers are used and clobbered at this
6305        point.  */
6306     emit_insn (gen_blockage ());
6308     DONE;
6309   }"
6312 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6313 ;; all of memory.  This blocks insns from being moved across this point.
6315 (define_insn "blockage"
6316   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6317   "TARGET_EITHER"
6318   ""
6319   [(set_attr "length" "0")
6320    (set_attr "type" "block")]
6323 (define_expand "casesi"
6324   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6325    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
6326    (match_operand:SI 2 "const_int_operand" "")  ; total range
6327    (match_operand:SI 3 "" "")                   ; table label
6328    (match_operand:SI 4 "" "")]                  ; Out of range label
6329   "TARGET_ARM"
6330   "
6331   {
6332     rtx reg;
6333     if (operands[1] != const0_rtx)
6334       {
6335         reg = gen_reg_rtx (SImode);
6337         emit_insn (gen_addsi3 (reg, operands[0],
6338                                GEN_INT (-INTVAL (operands[1]))));
6339         operands[0] = reg;
6340       }
6342     if (!const_ok_for_arm (INTVAL (operands[2])))
6343       operands[2] = force_reg (SImode, operands[2]);
6345     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6346                                          operands[4]));
6347     DONE;
6348   }"
6351 ;; The USE in this pattern is needed to tell flow analysis that this is
6352 ;; a CASESI insn.  It has no other purpose.
6353 (define_insn "casesi_internal"
6354   [(parallel [(set (pc)
6355                (if_then_else
6356                 (leu (match_operand:SI 0 "s_register_operand" "r")
6357                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
6358                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6359                                  (label_ref (match_operand 2 "" ""))))
6360                 (label_ref (match_operand 3 "" ""))))
6361               (clobber (reg:CC CC_REGNUM))
6362               (use (label_ref (match_dup 2)))])]
6363   "TARGET_ARM"
6364   "*
6365     if (flag_pic)
6366       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6367     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6368   "
6369   [(set_attr "conds" "clob")
6370    (set_attr "length" "12")]
6373 (define_expand "indirect_jump"
6374   [(set (pc)
6375         (match_operand:SI 0 "s_register_operand" ""))]
6376   "TARGET_EITHER"
6377   ""
6380 (define_insn "*arm_indirect_jump"
6381   [(set (pc)
6382         (match_operand:SI 0 "s_register_operand" "r"))]
6383   "TARGET_ARM"
6384   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6385   [(set_attr "predicable" "yes")]
6388 ;; Although not supported by the define_expand above,
6389 ;; cse/combine may generate this form.
6390 (define_insn "*load_indirect_jump"
6391   [(set (pc)
6392         (match_operand:SI 0 "memory_operand" "m"))]
6393   "TARGET_ARM"
6394   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6395   [(set_attr "type" "load")
6396    (set_attr "pool_range" "4096")
6397    (set_attr "neg_pool_range" "4084")
6398    (set_attr "predicable" "yes")]
6401 (define_insn "*thumb_indirect_jump"
6402   [(set (pc)
6403         (match_operand:SI 0 "register_operand" "l*r"))]
6404   "TARGET_THUMB"
6405   "mov\\tpc, %0"
6406   [(set_attr "conds" "clob")
6407    (set_attr "length" "2")]
6411 ;; Misc insns
6413 (define_insn "nop"
6414   [(const_int 0)]
6415   "TARGET_EITHER"
6416   "*
6417   if (TARGET_ARM)
6418     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6419   return  \"mov\\tr8, r8\";
6420   "
6421   [(set (attr "length")
6422         (if_then_else (eq_attr "is_thumb" "yes")
6423                       (const_int 2)
6424                       (const_int 4)))]
6428 ;; Patterns to allow combination of arithmetic, cond code and shifts
6430 (define_insn "*arith_shiftsi"
6431   [(set (match_operand:SI 0 "s_register_operand" "=r")
6432         (match_operator:SI 1 "shiftable_operator"
6433           [(match_operator:SI 3 "shift_operator"
6434              [(match_operand:SI 4 "s_register_operand" "r")
6435               (match_operand:SI 5 "reg_or_int_operand" "rI")])
6436            (match_operand:SI 2 "s_register_operand" "r")]))]
6437   "TARGET_ARM"
6438   "%i1%?\\t%0, %2, %4%S3"
6439   [(set_attr "predicable" "yes")
6440    (set_attr "shift" "4")
6441    ]
6444 (define_insn "*arith_shiftsi_compare0"
6445   [(set (reg:CC_NOOV CC_REGNUM)
6446         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6447                           [(match_operator:SI 3 "shift_operator"
6448                             [(match_operand:SI 4 "s_register_operand" "r")
6449                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6450                            (match_operand:SI 2 "s_register_operand" "r")])
6451                          (const_int 0)))
6452    (set (match_operand:SI 0 "s_register_operand" "=r")
6453         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6454                          (match_dup 2)]))]
6455   "TARGET_ARM"
6456   "%i1%?s\\t%0, %2, %4%S3"
6457   [(set_attr "conds" "set")
6458    (set_attr "shift" "4")
6459    ]
6462 (define_insn "*arith_shiftsi_compare0_scratch"
6463   [(set (reg:CC_NOOV CC_REGNUM)
6464         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6465                           [(match_operator:SI 3 "shift_operator"
6466                             [(match_operand:SI 4 "s_register_operand" "r")
6467                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6468                            (match_operand:SI 2 "s_register_operand" "r")])
6469                          (const_int 0)))
6470    (clobber (match_scratch:SI 0 "=r"))]
6471   "TARGET_ARM"
6472   "%i1%?s\\t%0, %2, %4%S3"
6473   [(set_attr "conds" "set")
6474    (set_attr "shift" "4")
6475    ]
6478 (define_insn "*sub_shiftsi"
6479   [(set (match_operand:SI 0 "s_register_operand" "=r")
6480         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6481                   (match_operator:SI 2 "shift_operator"
6482                    [(match_operand:SI 3 "s_register_operand" "r")
6483                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6484   "TARGET_ARM"
6485   "sub%?\\t%0, %1, %3%S2"
6486   [(set_attr "predicable" "yes")
6487    (set_attr "shift" "3")
6488    ]
6491 (define_insn "*sub_shiftsi_compare0"
6492   [(set (reg:CC_NOOV CC_REGNUM)
6493         (compare:CC_NOOV
6494          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6495                    (match_operator:SI 2 "shift_operator"
6496                     [(match_operand:SI 3 "s_register_operand" "r")
6497                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6498          (const_int 0)))
6499    (set (match_operand:SI 0 "s_register_operand" "=r")
6500         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6501                                                  (match_dup 4)])))]
6502   "TARGET_ARM"
6503   "sub%?s\\t%0, %1, %3%S2"
6504   [(set_attr "conds" "set")
6505    (set_attr "shift" "3") 
6506    ]
6509 (define_insn "*sub_shiftsi_compare0_scratch"
6510   [(set (reg:CC_NOOV CC_REGNUM)
6511         (compare:CC_NOOV
6512          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6513                    (match_operator:SI 2 "shift_operator"
6514                     [(match_operand:SI 3 "s_register_operand" "r")
6515                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6516          (const_int 0)))
6517    (clobber (match_scratch:SI 0 "=r"))]
6518   "TARGET_ARM"
6519   "sub%?s\\t%0, %1, %3%S2"
6520   [(set_attr "conds" "set")
6521    (set_attr "shift" "3") 
6522    ]
6527 (define_insn "*and_scc"
6528   [(set (match_operand:SI 0 "s_register_operand" "=r")
6529         (and:SI (match_operator:SI 1 "arm_comparison_operator"
6530                  [(match_operand 3 "cc_register" "") (const_int 0)])
6531                 (match_operand:SI 2 "s_register_operand" "r")))]
6532   "TARGET_ARM"
6533   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6534   [(set_attr "conds" "use")
6535    (set_attr "length" "8")]
6538 (define_insn "*ior_scc"
6539   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6540         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6541                  [(match_operand 3 "cc_register" "") (const_int 0)])
6542                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6543   "TARGET_ARM"
6544   "@
6545    orr%d2\\t%0, %1, #1
6546    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6547   [(set_attr "conds" "use")
6548    (set_attr "length" "4,8")]
6551 (define_insn "*compare_scc"
6552   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6553         (match_operator:SI 1 "arm_comparison_operator"
6554          [(match_operand:SI 2 "s_register_operand" "r,r")
6555           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6556    (clobber (reg:CC CC_REGNUM))]
6557   "TARGET_ARM"
6558   "*
6559     if (operands[3] == const0_rtx)
6560       {
6561         if (GET_CODE (operands[1]) == LT)
6562           return \"mov\\t%0, %2, lsr #31\";
6564         if (GET_CODE (operands[1]) == GE)
6565           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6567         if (GET_CODE (operands[1]) == EQ)
6568           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
6569       }
6571     if (GET_CODE (operands[1]) == NE)
6572       {
6573         if (which_alternative == 1)
6574           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
6575         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
6576       }
6577     if (which_alternative == 1)
6578       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6579     else
6580       output_asm_insn (\"cmp\\t%2, %3\", operands);
6581     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
6582   "
6583   [(set_attr "conds" "clob")
6584    (set_attr "length" "12")]
6587 (define_insn "*cond_move"
6588   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6589         (if_then_else:SI (match_operator 3 "equality_operator"
6590                           [(match_operator 4 "arm_comparison_operator"
6591                             [(match_operand 5 "cc_register" "") (const_int 0)])
6592                            (const_int 0)])
6593                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6594                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
6595   "TARGET_ARM"
6596   "*
6597     if (GET_CODE (operands[3]) == NE)
6598       {
6599         if (which_alternative != 1)
6600           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
6601         if (which_alternative != 0)
6602           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6603         return \"\";
6604       }
6605     if (which_alternative != 0)
6606       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6607     if (which_alternative != 1)
6608       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
6609     return \"\";
6610   "
6611   [(set_attr "conds" "use")
6612    (set_attr "length" "4,4,8")]
6615 (define_insn "*cond_arith"
6616   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6617         (match_operator:SI 5 "shiftable_operator" 
6618          [(match_operator:SI 4 "arm_comparison_operator"
6619            [(match_operand:SI 2 "s_register_operand" "r,r")
6620             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
6621           (match_operand:SI 1 "s_register_operand" "0,?r")]))
6622    (clobber (reg:CC CC_REGNUM))]
6623   "TARGET_ARM"
6624   "*
6625     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
6626       return \"%i5\\t%0, %1, %2, lsr #31\";
6628     output_asm_insn (\"cmp\\t%2, %3\", operands);
6629     if (GET_CODE (operands[5]) == AND)
6630       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
6631     else if (GET_CODE (operands[5]) == MINUS)
6632       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
6633     else if (which_alternative != 0)
6634       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6635     return \"%i5%d4\\t%0, %1, #1\";
6636   "
6637   [(set_attr "conds" "clob")
6638    (set_attr "length" "12")]
6641 (define_insn "*cond_sub"
6642   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6643         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
6644                   (match_operator:SI 4 "arm_comparison_operator"
6645                    [(match_operand:SI 2 "s_register_operand" "r,r")
6646                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
6647    (clobber (reg:CC CC_REGNUM))]
6648   "TARGET_ARM"
6649   "*
6650     output_asm_insn (\"cmp\\t%2, %3\", operands);
6651     if (which_alternative != 0)
6652       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6653     return \"sub%d4\\t%0, %1, #1\";
6654   "
6655   [(set_attr "conds" "clob")
6656    (set_attr "length" "8,12")]
6659 (define_insn "*cmp_ite0"
6660   [(set (match_operand 6 "dominant_cc_register" "")
6661         (compare
6662          (if_then_else:SI
6663           (match_operator 4 "arm_comparison_operator"
6664            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6665             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6666           (match_operator:SI 5 "arm_comparison_operator"
6667            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6668             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6669           (const_int 0))
6670          (const_int 0)))]
6671   "TARGET_ARM"
6672   "*
6673   {
6674     static const char * const opcodes[4][2] =
6675     {
6676       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6677        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6678       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6679        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6680       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6681        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6682       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6683        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6684     };
6685     int swap =
6686       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6688     return opcodes[which_alternative][swap];
6689   }"
6690   [(set_attr "conds" "set")
6691    (set_attr "length" "8")]
6694 (define_insn "*cmp_ite1"
6695   [(set (match_operand 6 "dominant_cc_register" "")
6696         (compare
6697          (if_then_else:SI
6698           (match_operator 4 "arm_comparison_operator"
6699            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6700             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6701           (match_operator:SI 5 "arm_comparison_operator"
6702            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6703             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6704           (const_int 1))
6705          (const_int 0)))]
6706   "TARGET_ARM"
6707   "*
6708   {
6709     static const char * const opcodes[4][2] =
6710     {
6711       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
6712        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6713       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
6714        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6715       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
6716        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6717       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
6718        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6719     };
6720     int swap =
6721       comparison_dominates_p (GET_CODE (operands[5]),
6722                               reverse_condition (GET_CODE (operands[4])));
6724     return opcodes[which_alternative][swap];
6725   }"
6726   [(set_attr "conds" "set")
6727    (set_attr "length" "8")]
6730 (define_insn "*cmp_and"
6731   [(set (match_operand 6 "dominant_cc_register" "")
6732         (compare
6733          (and:SI
6734           (match_operator 4 "arm_comparison_operator"
6735            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6736             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6737           (match_operator:SI 5 "arm_comparison_operator"
6738            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6739             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6740          (const_int 0)))]
6741   "TARGET_ARM"
6742   "*
6743   {
6744     static const char *const opcodes[4][2] =
6745     {
6746       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6747        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6748       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6749        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6750       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6751        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6752       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6753        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6754     };
6755     int swap =
6756       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6758     return opcodes[which_alternative][swap];
6759   }"
6760   [(set_attr "conds" "set")
6761    (set_attr "predicable" "no")
6762    (set_attr "length" "8")]
6765 (define_insn "*cmp_ior"
6766   [(set (match_operand 6 "dominant_cc_register" "")
6767         (compare
6768          (ior:SI
6769           (match_operator 4 "arm_comparison_operator"
6770            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6771             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6772           (match_operator:SI 5 "arm_comparison_operator"
6773            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6774             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6775          (const_int 0)))]
6776   "TARGET_ARM"
6777   "*
6779   static const char *const opcodes[4][2] =
6780   {
6781     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
6782      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6783     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
6784      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6785     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
6786      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6787     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
6788      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6789   };
6790   int swap =
6791     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6793   return opcodes[which_alternative][swap];
6796   [(set_attr "conds" "set")
6797    (set_attr "length" "8")]
6800 (define_insn_and_split "*ior_scc_scc"
6801   [(set (match_operand:SI 0 "s_register_operand" "=r")
6802         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6803                  [(match_operand:SI 1 "s_register_operand" "r")
6804                   (match_operand:SI 2 "arm_add_operand" "rIL")])
6805                 (match_operator:SI 6 "arm_comparison_operator"
6806                  [(match_operand:SI 4 "s_register_operand" "r")
6807                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
6808    (clobber (reg:CC CC_REGNUM))]
6809   "TARGET_ARM
6810    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
6811        != CCmode)"
6812   "#"
6813   "TARGET_ARM && reload_completed"
6814   [(set (match_dup 7)
6815         (compare
6816          (ior:SI
6817           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6818           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6819          (const_int 0)))
6820    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
6821   "operands[7]
6822      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
6823                                                   DOM_CC_X_OR_Y),
6824                     CC_REGNUM);"
6825   [(set_attr "conds" "clob")
6826    (set_attr "length" "16")])
6828 ; If the above pattern is followed by a CMP insn, then the compare is 
6829 ; redundant, since we can rework the conditional instruction that follows.
6830 (define_insn_and_split "*ior_scc_scc_cmp"
6831   [(set (match_operand 0 "dominant_cc_register" "")
6832         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6833                           [(match_operand:SI 1 "s_register_operand" "r")
6834                            (match_operand:SI 2 "arm_add_operand" "rIL")])
6835                          (match_operator:SI 6 "arm_comparison_operator"
6836                           [(match_operand:SI 4 "s_register_operand" "r")
6837                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
6838                  (const_int 0)))
6839    (set (match_operand:SI 7 "s_register_operand" "=r")
6840         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6841                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
6842   "TARGET_ARM"
6843   "#"
6844   "TARGET_ARM && reload_completed"
6845   [(set (match_dup 0)
6846         (compare
6847          (ior:SI
6848           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6849           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6850          (const_int 0)))
6851    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
6852   ""
6853   [(set_attr "conds" "set")
6854    (set_attr "length" "16")])
6856 (define_insn_and_split "*and_scc_scc"
6857   [(set (match_operand:SI 0 "s_register_operand" "=r")
6858         (and:SI (match_operator:SI 3 "arm_comparison_operator"
6859                  [(match_operand:SI 1 "s_register_operand" "r")
6860                   (match_operand:SI 2 "arm_add_operand" "rIL")])
6861                 (match_operator:SI 6 "arm_comparison_operator"
6862                  [(match_operand:SI 4 "s_register_operand" "r")
6863                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
6864    (clobber (reg:CC CC_REGNUM))]
6865   "TARGET_ARM
6866    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6867        != CCmode)"
6868   "#"
6869   "TARGET_ARM && reload_completed
6870    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6871        != CCmode)"
6872   [(set (match_dup 7)
6873         (compare
6874          (and:SI
6875           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6876           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6877          (const_int 0)))
6878    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
6879   "operands[7]
6880      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
6881                                                   DOM_CC_X_AND_Y),
6882                     CC_REGNUM);"
6883   [(set_attr "conds" "clob")
6884    (set_attr "length" "16")])
6886 ; If the above pattern is followed by a CMP insn, then the compare is 
6887 ; redundant, since we can rework the conditional instruction that follows.
6888 (define_insn_and_split "*and_scc_scc_cmp"
6889   [(set (match_operand 0 "dominant_cc_register" "")
6890         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
6891                           [(match_operand:SI 1 "s_register_operand" "r")
6892                            (match_operand:SI 2 "arm_add_operand" "rIL")])
6893                          (match_operator:SI 6 "arm_comparison_operator"
6894                           [(match_operand:SI 4 "s_register_operand" "r")
6895                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
6896                  (const_int 0)))
6897    (set (match_operand:SI 7 "s_register_operand" "=r")
6898         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6899                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
6900   "TARGET_ARM"
6901   "#"
6902   "TARGET_ARM && reload_completed"
6903   [(set (match_dup 0)
6904         (compare
6905          (and:SI
6906           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6907           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6908          (const_int 0)))
6909    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
6910   ""
6911   [(set_attr "conds" "set")
6912    (set_attr "length" "16")])
6914 ;; If there is no dominance in the comparison, then we can still save an
6915 ;; instruction in the AND case, since we can know that the second compare
6916 ;; need only zero the value if false (if true, then the value is already
6917 ;; correct).
6918 (define_insn_and_split "*and_scc_scc_nodom"
6919   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
6920         (and:SI (match_operator:SI 3 "arm_comparison_operator"
6921                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
6922                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
6923                 (match_operator:SI 6 "arm_comparison_operator"
6924                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
6925                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
6926    (clobber (reg:CC CC_REGNUM))]
6927   "TARGET_ARM
6928    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6929        == CCmode)"
6930   "#"
6931   "TARGET_ARM && reload_completed"
6932   [(parallel [(set (match_dup 0)
6933                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
6934               (clobber (reg:CC CC_REGNUM))])
6935    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
6936    (set (match_dup 0)
6937         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
6938                          (match_dup 0)
6939                          (const_int 0)))]
6940   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
6941                                               operands[4], operands[5]),
6942                               CC_REGNUM);
6943    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
6944                                   operands[5]);"
6945   [(set_attr "conds" "clob")
6946    (set_attr "length" "20")])
6948 (define_insn "*negscc"
6949   [(set (match_operand:SI 0 "s_register_operand" "=r")
6950         (neg:SI (match_operator 3 "arm_comparison_operator"
6951                  [(match_operand:SI 1 "s_register_operand" "r")
6952                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
6953    (clobber (reg:CC CC_REGNUM))]
6954   "TARGET_ARM"
6955   "*
6956   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
6957     return \"mov\\t%0, %1, asr #31\";
6959   if (GET_CODE (operands[3]) == NE)
6960     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
6962   if (GET_CODE (operands[3]) == GT)
6963     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
6965   output_asm_insn (\"cmp\\t%1, %2\", operands);
6966   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
6967   return \"mvn%d3\\t%0, #0\";
6968   "
6969   [(set_attr "conds" "clob")
6970    (set_attr "length" "12")]
6973 (define_insn "movcond"
6974   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6975         (if_then_else:SI
6976          (match_operator 5 "arm_comparison_operator"
6977           [(match_operand:SI 3 "s_register_operand" "r,r,r")
6978            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
6979          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6980          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
6981    (clobber (reg:CC CC_REGNUM))]
6982   "TARGET_ARM"
6983   "*
6984   if (GET_CODE (operands[5]) == LT
6985       && (operands[4] == const0_rtx))
6986     {
6987       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6988         {
6989           if (operands[2] == const0_rtx)
6990             return \"and\\t%0, %1, %3, asr #31\";
6991           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
6992         }
6993       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6994         {
6995           if (operands[1] == const0_rtx)
6996             return \"bic\\t%0, %2, %3, asr #31\";
6997           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
6998         }
6999       /* The only case that falls through to here is when both ops 1 & 2
7000          are constants */
7001     }
7003   if (GET_CODE (operands[5]) == GE
7004       && (operands[4] == const0_rtx))
7005     {
7006       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7007         {
7008           if (operands[2] == const0_rtx)
7009             return \"bic\\t%0, %1, %3, asr #31\";
7010           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7011         }
7012       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7013         {
7014           if (operands[1] == const0_rtx)
7015             return \"and\\t%0, %2, %3, asr #31\";
7016           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7017         }
7018       /* The only case that falls through to here is when both ops 1 & 2
7019          are constants */
7020     }
7021   if (GET_CODE (operands[4]) == CONST_INT
7022       && !const_ok_for_arm (INTVAL (operands[4])))
7023     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7024   else
7025     output_asm_insn (\"cmp\\t%3, %4\", operands);
7026   if (which_alternative != 0)
7027     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7028   if (which_alternative != 1)
7029     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7030   return \"\";
7031   "
7032   [(set_attr "conds" "clob")
7033    (set_attr "length" "8,8,12")]
7036 (define_insn "*ifcompare_plus_move"
7037   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7038         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7039                           [(match_operand:SI 4 "s_register_operand" "r,r")
7040                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7041                          (plus:SI
7042                           (match_operand:SI 2 "s_register_operand" "r,r")
7043                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7044                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7045    (clobber (reg:CC CC_REGNUM))]
7046   "TARGET_ARM"
7047   "#"
7048   [(set_attr "conds" "clob")
7049    (set_attr "length" "8,12")]
7052 (define_insn "*if_plus_move"
7053   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7054         (if_then_else:SI
7055          (match_operator 4 "arm_comparison_operator"
7056           [(match_operand 5 "cc_register" "") (const_int 0)])
7057          (plus:SI
7058           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7059           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7060          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7061   "TARGET_ARM"
7062   "@
7063    add%d4\\t%0, %2, %3
7064    sub%d4\\t%0, %2, #%n3
7065    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7066    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7067   [(set_attr "conds" "use")
7068    (set_attr "length" "4,4,8,8")
7069    (set_attr "type" "*,*,*,*")]
7072 (define_insn "*ifcompare_move_plus"
7073   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7074         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7075                           [(match_operand:SI 4 "s_register_operand" "r,r")
7076                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7077                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7078                          (plus:SI
7079                           (match_operand:SI 2 "s_register_operand" "r,r")
7080                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7081    (clobber (reg:CC CC_REGNUM))]
7082   "TARGET_ARM"
7083   "#"
7084   [(set_attr "conds" "clob")
7085    (set_attr "length" "8,12")]
7088 (define_insn "*if_move_plus"
7089   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7090         (if_then_else:SI
7091          (match_operator 4 "arm_comparison_operator"
7092           [(match_operand 5 "cc_register" "") (const_int 0)])
7093          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7094          (plus:SI
7095           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7096           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7097   "TARGET_ARM"
7098   "@
7099    add%D4\\t%0, %2, %3
7100    sub%D4\\t%0, %2, #%n3
7101    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7102    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7103   [(set_attr "conds" "use")
7104    (set_attr "length" "4,4,8,8")
7105    (set_attr "type" "*,*,*,*")]
7108 (define_insn "*ifcompare_arith_arith"
7109   [(set (match_operand:SI 0 "s_register_operand" "=r")
7110         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7111                           [(match_operand:SI 5 "s_register_operand" "r")
7112                            (match_operand:SI 6 "arm_add_operand" "rIL")])
7113                          (match_operator:SI 8 "shiftable_operator"
7114                           [(match_operand:SI 1 "s_register_operand" "r")
7115                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7116                          (match_operator:SI 7 "shiftable_operator"
7117                           [(match_operand:SI 3 "s_register_operand" "r")
7118                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7119    (clobber (reg:CC CC_REGNUM))]
7120   "TARGET_ARM"
7121   "#"
7122   [(set_attr "conds" "clob")
7123    (set_attr "length" "12")]
7126 (define_insn "*if_arith_arith"
7127   [(set (match_operand:SI 0 "s_register_operand" "=r")
7128         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7129                           [(match_operand 8 "cc_register" "") (const_int 0)])
7130                          (match_operator:SI 6 "shiftable_operator"
7131                           [(match_operand:SI 1 "s_register_operand" "r")
7132                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7133                          (match_operator:SI 7 "shiftable_operator"
7134                           [(match_operand:SI 3 "s_register_operand" "r")
7135                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7136   "TARGET_ARM"
7137   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7138   [(set_attr "conds" "use")
7139    (set_attr "length" "8")]
7142 (define_insn "*ifcompare_arith_move"
7143   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7144         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7145                           [(match_operand:SI 2 "s_register_operand" "r,r")
7146                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7147                          (match_operator:SI 7 "shiftable_operator"
7148                           [(match_operand:SI 4 "s_register_operand" "r,r")
7149                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7150                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7151    (clobber (reg:CC CC_REGNUM))]
7152   "TARGET_ARM"
7153   "*
7154   /* If we have an operation where (op x 0) is the identity operation and
7155      the conditional operator is LT or GE and we are comparing against zero and
7156      everything is in registers then we can do this in two instructions */
7157   if (operands[3] == const0_rtx
7158       && GET_CODE (operands[7]) != AND
7159       && GET_CODE (operands[5]) == REG
7160       && GET_CODE (operands[1]) == REG 
7161       && REGNO (operands[1]) == REGNO (operands[4])
7162       && REGNO (operands[4]) != REGNO (operands[0]))
7163     {
7164       if (GET_CODE (operands[6]) == LT)
7165         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7166       else if (GET_CODE (operands[6]) == GE)
7167         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7168     }
7169   if (GET_CODE (operands[3]) == CONST_INT
7170       && !const_ok_for_arm (INTVAL (operands[3])))
7171     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7172   else
7173     output_asm_insn (\"cmp\\t%2, %3\", operands);
7174   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7175   if (which_alternative != 0)
7176     return \"mov%D6\\t%0, %1\";
7177   return \"\";
7178   "
7179   [(set_attr "conds" "clob")
7180    (set_attr "length" "8,12")]
7183 (define_insn "*if_arith_move"
7184   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7185         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7186                           [(match_operand 6 "cc_register" "") (const_int 0)])
7187                          (match_operator:SI 5 "shiftable_operator"
7188                           [(match_operand:SI 2 "s_register_operand" "r,r")
7189                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7190                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7191   "TARGET_ARM"
7192   "@
7193    %I5%d4\\t%0, %2, %3
7194    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7195   [(set_attr "conds" "use")
7196    (set_attr "length" "4,8")
7197    (set_attr "type" "*,*")]
7200 (define_insn "*ifcompare_move_arith"
7201   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7202         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7203                           [(match_operand:SI 4 "s_register_operand" "r,r")
7204                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7205                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7206                          (match_operator:SI 7 "shiftable_operator"
7207                           [(match_operand:SI 2 "s_register_operand" "r,r")
7208                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7209    (clobber (reg:CC CC_REGNUM))]
7210   "TARGET_ARM"
7211   "*
7212   /* If we have an operation where (op x 0) is the identity operation and
7213      the conditional operator is LT or GE and we are comparing against zero and
7214      everything is in registers then we can do this in two instructions */
7215   if (operands[5] == const0_rtx
7216       && GET_CODE (operands[7]) != AND
7217       && GET_CODE (operands[3]) == REG
7218       && GET_CODE (operands[1]) == REG 
7219       && REGNO (operands[1]) == REGNO (operands[2])
7220       && REGNO (operands[2]) != REGNO (operands[0]))
7221     {
7222       if (GET_CODE (operands[6]) == GE)
7223         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7224       else if (GET_CODE (operands[6]) == LT)
7225         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7226     }
7228   if (GET_CODE (operands[5]) == CONST_INT
7229       && !const_ok_for_arm (INTVAL (operands[5])))
7230     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7231   else
7232     output_asm_insn (\"cmp\\t%4, %5\", operands);
7234   if (which_alternative != 0)
7235     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7236   return \"%I7%D6\\t%0, %2, %3\";
7237   "
7238   [(set_attr "conds" "clob")
7239    (set_attr "length" "8,12")]
7242 (define_insn "*if_move_arith"
7243   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7244         (if_then_else:SI
7245          (match_operator 4 "arm_comparison_operator"
7246           [(match_operand 6 "cc_register" "") (const_int 0)])
7247          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7248          (match_operator:SI 5 "shiftable_operator"
7249           [(match_operand:SI 2 "s_register_operand" "r,r")
7250            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7251   "TARGET_ARM"
7252   "@
7253    %I5%D4\\t%0, %2, %3
7254    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7255   [(set_attr "conds" "use")
7256    (set_attr "length" "4,8")
7257    (set_attr "type" "*,*")]
7260 (define_insn "*ifcompare_move_not"
7261   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7262         (if_then_else:SI
7263          (match_operator 5 "arm_comparison_operator"
7264           [(match_operand:SI 3 "s_register_operand" "r,r")
7265            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7266          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7267          (not:SI
7268           (match_operand:SI 2 "s_register_operand" "r,r"))))
7269    (clobber (reg:CC CC_REGNUM))]
7270   "TARGET_ARM"
7271   "#"
7272   [(set_attr "conds" "clob")
7273    (set_attr "length" "8,12")]
7276 (define_insn "*if_move_not"
7277   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7278         (if_then_else:SI
7279          (match_operator 4 "arm_comparison_operator"
7280           [(match_operand 3 "cc_register" "") (const_int 0)])
7281          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7282          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7283   "TARGET_ARM"
7284   "@
7285    mvn%D4\\t%0, %2
7286    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7287    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7288   [(set_attr "conds" "use")
7289    (set_attr "length" "4,8,8")]
7292 (define_insn "*ifcompare_not_move"
7293   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7294         (if_then_else:SI 
7295          (match_operator 5 "arm_comparison_operator"
7296           [(match_operand:SI 3 "s_register_operand" "r,r")
7297            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7298          (not:SI
7299           (match_operand:SI 2 "s_register_operand" "r,r"))
7300          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7301    (clobber (reg:CC CC_REGNUM))]
7302   "TARGET_ARM"
7303   "#"
7304   [(set_attr "conds" "clob")
7305    (set_attr "length" "8,12")]
7308 (define_insn "*if_not_move"
7309   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7310         (if_then_else:SI
7311          (match_operator 4 "arm_comparison_operator"
7312           [(match_operand 3 "cc_register" "") (const_int 0)])
7313          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7314          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7315   "TARGET_ARM"
7316   "@
7317    mvn%d4\\t%0, %2
7318    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7319    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7320   [(set_attr "conds" "use")
7321    (set_attr "length" "4,8,8")]
7324 (define_insn "*ifcompare_shift_move"
7325   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7326         (if_then_else:SI
7327          (match_operator 6 "arm_comparison_operator"
7328           [(match_operand:SI 4 "s_register_operand" "r,r")
7329            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7330          (match_operator:SI 7 "shift_operator"
7331           [(match_operand:SI 2 "s_register_operand" "r,r")
7332            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7333          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7334    (clobber (reg:CC CC_REGNUM))]
7335   "TARGET_ARM"
7336   "#"
7337   [(set_attr "conds" "clob")
7338    (set_attr "length" "8,12")]
7341 (define_insn "*if_shift_move"
7342   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7343         (if_then_else:SI
7344          (match_operator 5 "arm_comparison_operator"
7345           [(match_operand 6 "cc_register" "") (const_int 0)])
7346          (match_operator:SI 4 "shift_operator"
7347           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7348            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7349          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7350   "TARGET_ARM"
7351   "@
7352    mov%d5\\t%0, %2%S4
7353    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7354    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7355   [(set_attr "conds" "use")
7356    (set_attr "shift" "2")
7357    (set_attr "length" "4,8,8")]
7360 (define_insn "*ifcompare_move_shift"
7361   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7362         (if_then_else:SI
7363          (match_operator 6 "arm_comparison_operator"
7364           [(match_operand:SI 4 "s_register_operand" "r,r")
7365            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7366          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7367          (match_operator:SI 7 "shift_operator"
7368           [(match_operand:SI 2 "s_register_operand" "r,r")
7369            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7370    (clobber (reg:CC CC_REGNUM))]
7371   "TARGET_ARM"
7372   "#"
7373   [(set_attr "conds" "clob")
7374    (set_attr "length" "8,12")]
7377 (define_insn "*if_move_shift"
7378   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7379         (if_then_else:SI
7380          (match_operator 5 "arm_comparison_operator"
7381           [(match_operand 6 "cc_register" "") (const_int 0)])
7382          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7383          (match_operator:SI 4 "shift_operator"
7384           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7385            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7386   "TARGET_ARM"
7387   "@
7388    mov%D5\\t%0, %2%S4
7389    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7390    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7391   [(set_attr "conds" "use")
7392    (set_attr "shift" "2")
7393    (set_attr "length" "4,8,8")]
7396 (define_insn "*ifcompare_shift_shift"
7397   [(set (match_operand:SI 0 "s_register_operand" "=r")
7398         (if_then_else:SI
7399          (match_operator 7 "arm_comparison_operator"
7400           [(match_operand:SI 5 "s_register_operand" "r")
7401            (match_operand:SI 6 "arm_add_operand" "rIL")])
7402          (match_operator:SI 8 "shift_operator"
7403           [(match_operand:SI 1 "s_register_operand" "r")
7404            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7405          (match_operator:SI 9 "shift_operator"
7406           [(match_operand:SI 3 "s_register_operand" "r")
7407            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7408    (clobber (reg:CC CC_REGNUM))]
7409   "TARGET_ARM"
7410   "#"
7411   [(set_attr "conds" "clob")
7412    (set_attr "length" "12")]
7415 (define_insn "*if_shift_shift"
7416   [(set (match_operand:SI 0 "s_register_operand" "=r")
7417         (if_then_else:SI
7418          (match_operator 5 "arm_comparison_operator"
7419           [(match_operand 8 "cc_register" "") (const_int 0)])
7420          (match_operator:SI 6 "shift_operator"
7421           [(match_operand:SI 1 "s_register_operand" "r")
7422            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7423          (match_operator:SI 7 "shift_operator"
7424           [(match_operand:SI 3 "s_register_operand" "r")
7425            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7426   "TARGET_ARM"
7427   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7428   [(set_attr "conds" "use")
7429    (set_attr "shift" "1")
7430    (set_attr "length" "8")]
7433 (define_insn "*ifcompare_not_arith"
7434   [(set (match_operand:SI 0 "s_register_operand" "=r")
7435         (if_then_else:SI
7436          (match_operator 6 "arm_comparison_operator"
7437           [(match_operand:SI 4 "s_register_operand" "r")
7438            (match_operand:SI 5 "arm_add_operand" "rIL")])
7439          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7440          (match_operator:SI 7 "shiftable_operator"
7441           [(match_operand:SI 2 "s_register_operand" "r")
7442            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7443    (clobber (reg:CC CC_REGNUM))]
7444   "TARGET_ARM"
7445   "#"
7446   [(set_attr "conds" "clob")
7447    (set_attr "length" "12")]
7450 (define_insn "*if_not_arith"
7451   [(set (match_operand:SI 0 "s_register_operand" "=r")
7452         (if_then_else:SI
7453          (match_operator 5 "arm_comparison_operator"
7454           [(match_operand 4 "cc_register" "") (const_int 0)])
7455          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7456          (match_operator:SI 6 "shiftable_operator"
7457           [(match_operand:SI 2 "s_register_operand" "r")
7458            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7459   "TARGET_ARM"
7460   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7461   [(set_attr "conds" "use")
7462    (set_attr "length" "8")]
7465 (define_insn "*ifcompare_arith_not"
7466   [(set (match_operand:SI 0 "s_register_operand" "=r")
7467         (if_then_else:SI
7468          (match_operator 6 "arm_comparison_operator"
7469           [(match_operand:SI 4 "s_register_operand" "r")
7470            (match_operand:SI 5 "arm_add_operand" "rIL")])
7471          (match_operator:SI 7 "shiftable_operator"
7472           [(match_operand:SI 2 "s_register_operand" "r")
7473            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7474          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7475    (clobber (reg:CC CC_REGNUM))]
7476   "TARGET_ARM"
7477   "#"
7478   [(set_attr "conds" "clob")
7479    (set_attr "length" "12")]
7482 (define_insn "*if_arith_not"
7483   [(set (match_operand:SI 0 "s_register_operand" "=r")
7484         (if_then_else:SI
7485          (match_operator 5 "arm_comparison_operator"
7486           [(match_operand 4 "cc_register" "") (const_int 0)])
7487          (match_operator:SI 6 "shiftable_operator"
7488           [(match_operand:SI 2 "s_register_operand" "r")
7489            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7490          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7491   "TARGET_ARM"
7492   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7493   [(set_attr "conds" "use")
7494    (set_attr "length" "8")]
7497 (define_insn "*ifcompare_neg_move"
7498   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7499         (if_then_else:SI
7500          (match_operator 5 "arm_comparison_operator"
7501           [(match_operand:SI 3 "s_register_operand" "r,r")
7502            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7503          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7504          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7505    (clobber (reg:CC CC_REGNUM))]
7506   "TARGET_ARM"
7507   "#"
7508   [(set_attr "conds" "clob")
7509    (set_attr "length" "8,12")]
7512 (define_insn "*if_neg_move"
7513   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7514         (if_then_else:SI
7515          (match_operator 4 "arm_comparison_operator"
7516           [(match_operand 3 "cc_register" "") (const_int 0)])
7517          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7518          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7519   "TARGET_ARM"
7520   "@
7521    rsb%d4\\t%0, %2, #0
7522    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7523    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7524   [(set_attr "conds" "use")
7525    (set_attr "length" "4,8,8")]
7528 (define_insn "*ifcompare_move_neg"
7529   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7530         (if_then_else:SI
7531          (match_operator 5 "arm_comparison_operator"
7532           [(match_operand:SI 3 "s_register_operand" "r,r")
7533            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7534          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7535          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7536    (clobber (reg:CC CC_REGNUM))]
7537   "TARGET_ARM"
7538   "#"
7539   [(set_attr "conds" "clob")
7540    (set_attr "length" "8,12")]
7543 (define_insn "*if_move_neg"
7544   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7545         (if_then_else:SI
7546          (match_operator 4 "arm_comparison_operator"
7547           [(match_operand 3 "cc_register" "") (const_int 0)])
7548          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7549          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7550   "TARGET_ARM"
7551   "@
7552    rsb%D4\\t%0, %2, #0
7553    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7554    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7555   [(set_attr "conds" "use")
7556    (set_attr "length" "4,8,8")]
7559 (define_insn "*arith_adjacentmem"
7560   [(set (match_operand:SI 0 "s_register_operand" "=r")
7561         (match_operator:SI 1 "shiftable_operator"
7562          [(match_operand:SI 2 "memory_operand" "m")
7563           (match_operand:SI 3 "memory_operand" "m")]))
7564    (clobber (match_scratch:SI 4 "=r"))]
7565   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7566   "*
7567   {
7568     rtx ldm[3];
7569     rtx arith[4];
7570     int val1 = 0, val2 = 0;
7572     if (REGNO (operands[0]) > REGNO (operands[4]))
7573       {
7574         ldm[1] = operands[4];
7575         ldm[2] = operands[0];
7576       }
7577     else
7578       {
7579         ldm[1] = operands[0];
7580         ldm[2] = operands[4];
7581       }
7582     if (GET_CODE (XEXP (operands[2], 0)) != REG)
7583       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7584     if (GET_CODE (XEXP (operands[3], 0)) != REG)
7585       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7586     arith[0] = operands[0];
7587     arith[3] = operands[1];
7588     if (val1 < val2)
7589       {
7590         arith[1] = ldm[1];
7591         arith[2] = ldm[2];
7592       }
7593     else
7594       {
7595         arith[1] = ldm[2];
7596         arith[2] = ldm[1];
7597       }
7598    if (val1 && val2)
7599       {
7600         rtx ops[3];
7601         ldm[0] = ops[0] = operands[4];
7602         ops[1] = XEXP (XEXP (operands[2], 0), 0);
7603         ops[2] = XEXP (XEXP (operands[2], 0), 1);
7604         output_add_immediate (ops);
7605         if (val1 < val2)
7606           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7607         else
7608           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7609       }
7610     else if (val1)
7611       {
7612         ldm[0] = XEXP (operands[3], 0);
7613         if (val1 < val2)
7614           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7615         else
7616           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7617       }
7618     else
7619       {
7620         ldm[0] = XEXP (operands[2], 0);
7621         if (val1 < val2)
7622           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7623         else
7624           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7625       }
7626     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7627     return \"\";
7628   }"
7629   [(set_attr "length" "12")
7630    (set_attr "predicable" "yes")
7631    (set_attr "type" "load")]
7634 ;; the arm can support extended pre-inc instructions
7636 ;; In all these cases, we use operands 0 and 1 for the register being
7637 ;; incremented because those are the operands that local-alloc will
7638 ;; tie and these are the pair most likely to be tieable (and the ones
7639 ;; that will benefit the most).
7641 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7642 ;; elimination will cause too many headaches.
7644 (define_insn "*strqi_preinc"
7645   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7646                          (match_operand:SI 2 "index_operand" "rJ")))
7647         (match_operand:QI 3 "s_register_operand" "r"))
7648    (set (match_operand:SI 0 "s_register_operand" "=r")
7649         (plus:SI (match_dup 1) (match_dup 2)))]
7650   "TARGET_ARM
7651    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7652    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7653    && (GET_CODE (operands[2]) != REG
7654        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7655   "str%?b\\t%3, [%0, %2]!"
7656   [(set_attr "type" "store1")
7657    (set_attr "predicable" "yes")]
7660 (define_insn "*strqi_predec"
7661   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7662                           (match_operand:SI 2 "s_register_operand" "r")))
7663         (match_operand:QI 3 "s_register_operand" "r"))
7664    (set (match_operand:SI 0 "s_register_operand" "=r")
7665         (minus:SI (match_dup 1) (match_dup 2)))]
7666   "TARGET_ARM
7667    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7668    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7669    && (GET_CODE (operands[2]) != REG
7670        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7671   "str%?b\\t%3, [%0, -%2]!"
7672   [(set_attr "type" "store1")
7673    (set_attr "predicable" "yes")]
7676 (define_insn "*loadqi_preinc"
7677   [(set (match_operand:QI 3 "s_register_operand" "=r")
7678         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7679                          (match_operand:SI 2 "index_operand" "rJ"))))
7680    (set (match_operand:SI 0 "s_register_operand" "=r")
7681         (plus:SI (match_dup 1) (match_dup 2)))]
7682   "TARGET_ARM
7683    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7684    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7685    && (GET_CODE (operands[2]) != REG
7686        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7687   "ldr%?b\\t%3, [%0, %2]!"
7688   [(set_attr "type" "load")
7689    (set_attr "predicable" "yes")]
7692 (define_insn "*loadqi_predec"
7693   [(set (match_operand:QI 3 "s_register_operand" "=r")
7694         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7695                           (match_operand:SI 2 "s_register_operand" "r"))))
7696    (set (match_operand:SI 0 "s_register_operand" "=r")
7697         (minus:SI (match_dup 1) (match_dup 2)))]
7698   "TARGET_ARM
7699    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7700    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7701    && (GET_CODE (operands[2]) != REG
7702        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7703   "ldr%?b\\t%3, [%0, -%2]!"
7704   [(set_attr "type" "load")
7705    (set_attr "predicable" "yes")]
7708 (define_insn "*loadqisi_preinc"
7709   [(set (match_operand:SI 3 "s_register_operand" "=r")
7710         (zero_extend:SI
7711          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7712                           (match_operand:SI 2 "index_operand" "rJ")))))
7713    (set (match_operand:SI 0 "s_register_operand" "=r")
7714         (plus:SI (match_dup 1) (match_dup 2)))]
7715   "TARGET_ARM
7716    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7717    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7718    && (GET_CODE (operands[2]) != REG
7719        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7720   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
7721   [(set_attr "type" "load")
7722    (set_attr "predicable" "yes")]
7725 (define_insn "*loadqisi_predec"
7726   [(set (match_operand:SI 3 "s_register_operand" "=r")
7727         (zero_extend:SI
7728          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7729                            (match_operand:SI 2 "s_register_operand" "r")))))
7730    (set (match_operand:SI 0 "s_register_operand" "=r")
7731         (minus:SI (match_dup 1) (match_dup 2)))]
7732   "TARGET_ARM
7733    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7734    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7735    && (GET_CODE (operands[2]) != REG
7736        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7737   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
7738   [(set_attr "type" "load")
7739    (set_attr "predicable" "yes")]
7742 (define_insn "*strsi_preinc"
7743   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7744                          (match_operand:SI 2 "index_operand" "rJ")))
7745         (match_operand:SI 3 "s_register_operand" "r"))
7746    (set (match_operand:SI 0 "s_register_operand" "=r")
7747         (plus:SI (match_dup 1) (match_dup 2)))]
7748   "TARGET_ARM
7749    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7750    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7751    && (GET_CODE (operands[2]) != REG
7752        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7753   "str%?\\t%3, [%0, %2]!"
7754   [(set_attr "type" "store1")
7755    (set_attr "predicable" "yes")]
7758 (define_insn "*strsi_predec"
7759   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7760                           (match_operand:SI 2 "s_register_operand" "r")))
7761         (match_operand:SI 3 "s_register_operand" "r"))
7762    (set (match_operand:SI 0 "s_register_operand" "=r")
7763         (minus:SI (match_dup 1) (match_dup 2)))]
7764   "TARGET_ARM
7765    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7766    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7767    && (GET_CODE (operands[2]) != REG
7768        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7769   "str%?\\t%3, [%0, -%2]!"
7770   [(set_attr "type" "store1")
7771    (set_attr "predicable" "yes")]
7774 (define_insn "*loadsi_preinc"
7775   [(set (match_operand:SI 3 "s_register_operand" "=r")
7776         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7777                          (match_operand:SI 2 "index_operand" "rJ"))))
7778    (set (match_operand:SI 0 "s_register_operand" "=r")
7779         (plus:SI (match_dup 1) (match_dup 2)))]
7780   "TARGET_ARM
7781    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7782    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7783    && (GET_CODE (operands[2]) != REG
7784        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7785   "ldr%?\\t%3, [%0, %2]!"
7786   [(set_attr "type" "load")
7787    (set_attr "predicable" "yes")]
7790 (define_insn "*loadsi_predec"
7791   [(set (match_operand:SI 3 "s_register_operand" "=r")
7792         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7793                           (match_operand:SI 2 "s_register_operand" "r"))))
7794    (set (match_operand:SI 0 "s_register_operand" "=r")
7795         (minus:SI (match_dup 1) (match_dup 2)))]
7796   "TARGET_ARM
7797    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7798    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7799    && (GET_CODE (operands[2]) != REG
7800        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7801   "ldr%?\\t%3, [%0, -%2]!"
7802   [(set_attr "type" "load")
7803    (set_attr "predicable" "yes")]
7806 (define_insn "*loadhi_preinc"
7807   [(set (match_operand:HI 3 "s_register_operand" "=r")
7808         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7809                          (match_operand:SI 2 "index_operand" "rJ"))))
7810    (set (match_operand:SI 0 "s_register_operand" "=r")
7811         (plus:SI (match_dup 1) (match_dup 2)))]
7812   "TARGET_ARM
7813    && !BYTES_BIG_ENDIAN
7814    && !TARGET_MMU_TRAPS
7815    && !arm_arch4
7816    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7817    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7818    && (GET_CODE (operands[2]) != REG
7819        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7820   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
7821   [(set_attr "type" "load")
7822    (set_attr "predicable" "yes")]
7825 (define_insn "*loadhi_predec"
7826   [(set (match_operand:HI 3 "s_register_operand" "=r")
7827         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7828                           (match_operand:SI 2 "s_register_operand" "r"))))
7829    (set (match_operand:SI 0 "s_register_operand" "=r")
7830         (minus:SI (match_dup 1) (match_dup 2)))]
7831   "TARGET_ARM
7832    && !BYTES_BIG_ENDIAN
7833    && !TARGET_MMU_TRAPS
7834    && !arm_arch4
7835    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7836    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7837    && (GET_CODE (operands[2]) != REG
7838        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7839   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
7840   [(set_attr "type" "load")
7841    (set_attr "predicable" "yes")]
7844 (define_insn "*strqi_shiftpreinc"
7845   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7846                           [(match_operand:SI 3 "s_register_operand" "r")
7847                            (match_operand:SI 4 "const_shift_operand" "n")])
7848                          (match_operand:SI 1 "s_register_operand" "0")))
7849         (match_operand:QI 5 "s_register_operand" "r"))
7850    (set (match_operand:SI 0 "s_register_operand" "=r")
7851         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7852                  (match_dup 1)))]
7853   "TARGET_ARM
7854    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7855    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7856    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7857   "str%?b\\t%5, [%0, %3%S2]!"
7858   [(set_attr "type" "store1")
7859    (set_attr "predicable" "yes")]
7862 (define_insn "*strqi_shiftpredec"
7863   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7864                           (match_operator:SI 2 "shift_operator"
7865                            [(match_operand:SI 3 "s_register_operand" "r")
7866                             (match_operand:SI 4 "const_shift_operand" "n")])))
7867         (match_operand:QI 5 "s_register_operand" "r"))
7868    (set (match_operand:SI 0 "s_register_operand" "=r")
7869         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7870                                                  (match_dup 4)])))]
7871   "TARGET_ARM
7872    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7873    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7874    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7875   "str%?b\\t%5, [%0, -%3%S2]!"
7876   [(set_attr "type" "store1")
7877    (set_attr "predicable" "yes")]
7880 (define_insn "*loadqi_shiftpreinc"
7881   [(set (match_operand:QI 5 "s_register_operand" "=r")
7882         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7883                           [(match_operand:SI 3 "s_register_operand" "r")
7884                            (match_operand:SI 4 "const_shift_operand" "n")])
7885                          (match_operand:SI 1 "s_register_operand" "0"))))
7886    (set (match_operand:SI 0 "s_register_operand" "=r")
7887         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7888                  (match_dup 1)))]
7889   "TARGET_ARM
7890    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7891    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7892    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7893   "ldr%?b\\t%5, [%0, %3%S2]!"
7894   [(set_attr "type" "load")
7895    (set_attr "predicable" "yes")]
7898 (define_insn "*loadqi_shiftpredec"
7899   [(set (match_operand:QI 5 "s_register_operand" "=r")
7900         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7901                           (match_operator:SI 2 "shift_operator"
7902                            [(match_operand:SI 3 "s_register_operand" "r")
7903                             (match_operand:SI 4 "const_shift_operand" "n")]))))
7904    (set (match_operand:SI 0 "s_register_operand" "=r")
7905         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7906                                                  (match_dup 4)])))]
7907   "TARGET_ARM
7908    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7909    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7910    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7911   "ldr%?b\\t%5, [%0, -%3%S2]!"
7912   [(set_attr "type" "load")
7913    (set_attr "predicable" "yes")]
7916 (define_insn "*strsi_shiftpreinc"
7917   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7918                           [(match_operand:SI 3 "s_register_operand" "r")
7919                            (match_operand:SI 4 "const_shift_operand" "n")])
7920                          (match_operand:SI 1 "s_register_operand" "0")))
7921         (match_operand:SI 5 "s_register_operand" "r"))
7922    (set (match_operand:SI 0 "s_register_operand" "=r")
7923         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7924                  (match_dup 1)))]
7925   "TARGET_ARM
7926    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7927    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7928    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7929   "str%?\\t%5, [%0, %3%S2]!"
7930   [(set_attr "type" "store1")
7931    (set_attr "predicable" "yes")]
7934 (define_insn "*strsi_shiftpredec"
7935   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7936                           (match_operator:SI 2 "shift_operator"
7937                            [(match_operand:SI 3 "s_register_operand" "r")
7938                             (match_operand:SI 4 "const_shift_operand" "n")])))
7939         (match_operand:SI 5 "s_register_operand" "r"))
7940    (set (match_operand:SI 0 "s_register_operand" "=r")
7941         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7942                                                  (match_dup 4)])))]
7943   "TARGET_ARM
7944    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7945    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7946    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7947   "str%?\\t%5, [%0, -%3%S2]!"
7948   [(set_attr "type" "store1")
7949    (set_attr "predicable" "yes")]
7952 (define_insn "*loadsi_shiftpreinc"
7953   [(set (match_operand:SI 5 "s_register_operand" "=r")
7954         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7955                           [(match_operand:SI 3 "s_register_operand" "r")
7956                            (match_operand:SI 4 "const_shift_operand" "n")])
7957                          (match_operand:SI 1 "s_register_operand" "0"))))
7958    (set (match_operand:SI 0 "s_register_operand" "=r")
7959         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7960                  (match_dup 1)))]
7961   "TARGET_ARM
7962    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7963    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7964    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7965   "ldr%?\\t%5, [%0, %3%S2]!"
7966   [(set_attr "type" "load")
7967    (set_attr "predicable" "yes")]
7970 (define_insn "*loadsi_shiftpredec"
7971   [(set (match_operand:SI 5 "s_register_operand" "=r")
7972         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7973                           (match_operator:SI 2 "shift_operator"
7974                            [(match_operand:SI 3 "s_register_operand" "r")
7975                             (match_operand:SI 4 "const_shift_operand" "n")]))))
7976    (set (match_operand:SI 0 "s_register_operand" "=r")
7977         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7978                                                  (match_dup 4)])))]
7979   "TARGET_ARM
7980    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7981    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7982    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7983   "ldr%?\\t%5, [%0, -%3%S2]!"
7984   [(set_attr "type" "load")
7985    (set_attr "predicable" "yes")])
7987 (define_insn "*loadhi_shiftpreinc"
7988   [(set (match_operand:HI 5 "s_register_operand" "=r")
7989         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
7990                           [(match_operand:SI 3 "s_register_operand" "r")
7991                            (match_operand:SI 4 "const_shift_operand" "n")])
7992                          (match_operand:SI 1 "s_register_operand" "0"))))
7993    (set (match_operand:SI 0 "s_register_operand" "=r")
7994         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7995                  (match_dup 1)))]
7996   "TARGET_ARM
7997    && !BYTES_BIG_ENDIAN
7998    && !TARGET_MMU_TRAPS
7999    && !arm_arch4
8000    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8001    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8002    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8003   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8004   [(set_attr "type" "load")
8005    (set_attr "predicable" "yes")]
8008 (define_insn "*loadhi_shiftpredec"
8009   [(set (match_operand:HI 5 "s_register_operand" "=r")
8010         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8011                           (match_operator:SI 2 "shift_operator"
8012                            [(match_operand:SI 3 "s_register_operand" "r")
8013                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8014    (set (match_operand:SI 0 "s_register_operand" "=r")
8015         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8016                                                  (match_dup 4)])))]
8017   "TARGET_ARM
8018    && !BYTES_BIG_ENDIAN
8019    && !TARGET_MMU_TRAPS
8020    && !arm_arch4
8021    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8022    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8023    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8024   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8025   [(set_attr "type" "load")
8026    (set_attr "predicable" "yes")]
8029 ; It can also support extended post-inc expressions, but combine doesn't
8030 ; try these....
8031 ; It doesn't seem worth adding peepholes for anything but the most common
8032 ; cases since, unlike combine, the increment must immediately follow the load
8033 ; for this pattern to match.
8034 ; We must watch to see that the source/destination register isn't also the
8035 ; same as the base address register, and that if the index is a register,
8036 ; that it is not the same as the base address register.  In such cases the
8037 ; instruction that we would generate would have UNPREDICTABLE behavior so 
8038 ; we cannot use it.
8040 (define_peephole
8041   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8042         (match_operand:QI 2 "s_register_operand" "r"))
8043    (set (match_dup 0)
8044         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8045   "TARGET_ARM
8046    && (REGNO (operands[2]) != REGNO (operands[0]))
8047    && (GET_CODE (operands[1]) != REG
8048        || (REGNO (operands[1]) != REGNO (operands[0])))"
8049   "str%?b\\t%2, [%0], %1"
8052 (define_peephole
8053   [(set (match_operand:QI 0 "s_register_operand" "=r")
8054         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8055    (set (match_dup 1)
8056         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8057   "TARGET_ARM
8058    && REGNO (operands[0]) != REGNO(operands[1])
8059    && (GET_CODE (operands[2]) != REG
8060        || REGNO(operands[0]) != REGNO (operands[2]))"
8061   "ldr%?b\\t%0, [%1], %2"
8064 (define_peephole
8065   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8066         (match_operand:SI 2 "s_register_operand" "r"))
8067    (set (match_dup 0)
8068         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8069   "TARGET_ARM
8070    && (REGNO (operands[2]) != REGNO (operands[0]))
8071    && (GET_CODE (operands[1]) != REG
8072        || (REGNO (operands[1]) != REGNO (operands[0])))"
8073   "str%?\\t%2, [%0], %1"
8076 (define_peephole
8077   [(set (match_operand:HI 0 "s_register_operand" "=r")
8078         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8079    (set (match_dup 1)
8080         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8081   "TARGET_ARM
8082    && !BYTES_BIG_ENDIAN
8083    && !TARGET_MMU_TRAPS
8084    && !arm_arch4
8085    && REGNO (operands[0]) != REGNO(operands[1])
8086    && (GET_CODE (operands[2]) != REG
8087        || REGNO(operands[0]) != REGNO (operands[2]))"
8088   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8091 (define_peephole
8092   [(set (match_operand:SI 0 "s_register_operand" "=r")
8093         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8094    (set (match_dup 1)
8095         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8096   "TARGET_ARM
8097    && REGNO (operands[0]) != REGNO(operands[1])
8098    && (GET_CODE (operands[2]) != REG
8099        || REGNO(operands[0]) != REGNO (operands[2]))"
8100   "ldr%?\\t%0, [%1], %2"
8103 (define_peephole
8104   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8105                          (match_operand:SI 1 "index_operand" "rJ")))
8106         (match_operand:QI 2 "s_register_operand" "r"))
8107    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8108   "TARGET_ARM
8109    && (REGNO (operands[2]) != REGNO (operands[0]))
8110    && (GET_CODE (operands[1]) != REG
8111        || (REGNO (operands[1]) != REGNO (operands[0])))"
8112   "str%?b\\t%2, [%0, %1]!"
8115 (define_peephole
8116   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8117                           [(match_operand:SI 0 "s_register_operand" "r")
8118                            (match_operand:SI 1 "const_int_operand" "n")])
8119                          (match_operand:SI 2 "s_register_operand" "+r")))
8120         (match_operand:QI 3 "s_register_operand" "r"))
8121    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8122                                (match_dup 2)))]
8123   "TARGET_ARM
8124    && (REGNO (operands[3]) != REGNO (operands[2]))
8125    && (REGNO (operands[0]) != REGNO (operands[2]))"
8126   "str%?b\\t%3, [%2, %0%S4]!"
8129 ; This pattern is never tried by combine, so do it as a peephole
8131 (define_peephole2
8132   [(set (match_operand:SI 0 "s_register_operand" "")
8133         (match_operand:SI 1 "s_register_operand" ""))
8134    (set (reg:CC CC_REGNUM)
8135         (compare:CC (match_dup 1) (const_int 0)))]
8136   "TARGET_ARM
8137    && (!TARGET_CIRRUS
8138        || (!cirrus_fp_register (operands[0], SImode)
8139            && !cirrus_fp_register (operands[1], SImode)))
8140   "
8141   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8142               (set (match_dup 0) (match_dup 1))])]
8143   ""
8146 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8147 ; reversed, check that the memory references aren't volatile.
8149 (define_peephole
8150   [(set (match_operand:SI 0 "s_register_operand" "=r")
8151         (match_operand:SI 4 "memory_operand" "m"))
8152    (set (match_operand:SI 1 "s_register_operand" "=r")
8153         (match_operand:SI 5 "memory_operand" "m"))
8154    (set (match_operand:SI 2 "s_register_operand" "=r")
8155         (match_operand:SI 6 "memory_operand" "m"))
8156    (set (match_operand:SI 3 "s_register_operand" "=r")
8157         (match_operand:SI 7 "memory_operand" "m"))]
8158   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8159   "*
8160   return emit_ldm_seq (operands, 4);
8161   "
8164 (define_peephole
8165   [(set (match_operand:SI 0 "s_register_operand" "=r")
8166         (match_operand:SI 3 "memory_operand" "m"))
8167    (set (match_operand:SI 1 "s_register_operand" "=r")
8168         (match_operand:SI 4 "memory_operand" "m"))
8169    (set (match_operand:SI 2 "s_register_operand" "=r")
8170         (match_operand:SI 5 "memory_operand" "m"))]
8171   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8172   "*
8173   return emit_ldm_seq (operands, 3);
8174   "
8177 (define_peephole
8178   [(set (match_operand:SI 0 "s_register_operand" "=r")
8179         (match_operand:SI 2 "memory_operand" "m"))
8180    (set (match_operand:SI 1 "s_register_operand" "=r")
8181         (match_operand:SI 3 "memory_operand" "m"))]
8182   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8183   "*
8184   return emit_ldm_seq (operands, 2);
8185   "
8188 (define_peephole
8189   [(set (match_operand:SI 4 "memory_operand" "=m")
8190         (match_operand:SI 0 "s_register_operand" "r"))
8191    (set (match_operand:SI 5 "memory_operand" "=m")
8192         (match_operand:SI 1 "s_register_operand" "r"))
8193    (set (match_operand:SI 6 "memory_operand" "=m")
8194         (match_operand:SI 2 "s_register_operand" "r"))
8195    (set (match_operand:SI 7 "memory_operand" "=m")
8196         (match_operand:SI 3 "s_register_operand" "r"))]
8197   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8198   "*
8199   return emit_stm_seq (operands, 4);
8200   "
8203 (define_peephole
8204   [(set (match_operand:SI 3 "memory_operand" "=m")
8205         (match_operand:SI 0 "s_register_operand" "r"))
8206    (set (match_operand:SI 4 "memory_operand" "=m")
8207         (match_operand:SI 1 "s_register_operand" "r"))
8208    (set (match_operand:SI 5 "memory_operand" "=m")
8209         (match_operand:SI 2 "s_register_operand" "r"))]
8210   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8211   "*
8212   return emit_stm_seq (operands, 3);
8213   "
8216 (define_peephole
8217   [(set (match_operand:SI 2 "memory_operand" "=m")
8218         (match_operand:SI 0 "s_register_operand" "r"))
8219    (set (match_operand:SI 3 "memory_operand" "=m")
8220         (match_operand:SI 1 "s_register_operand" "r"))]
8221   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8222   "*
8223   return emit_stm_seq (operands, 2);
8224   "
8227 (define_split
8228   [(set (match_operand:SI 0 "s_register_operand" "")
8229         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8230                        (const_int 0))
8231                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8232                          [(match_operand:SI 3 "s_register_operand" "")
8233                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
8234    (clobber (match_operand:SI 5 "s_register_operand" ""))]
8235   "TARGET_ARM"
8236   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8237    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8238                               (match_dup 5)))]
8239   ""
8242 ;; This split can be used because CC_Z mode implies that the following
8243 ;; branch will be an equality, or an unsigned inequality, so the sign
8244 ;; extension is not needed.
8246 (define_split
8247   [(set (reg:CC_Z CC_REGNUM)
8248         (compare:CC_Z
8249          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8250                     (const_int 24))
8251          (match_operand 1 "const_int_operand" "")))
8252    (clobber (match_scratch:SI 2 ""))]
8253   "TARGET_ARM
8254    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8255        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8256   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8257    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8258   "
8259   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8260   "
8263 (define_expand "prologue"
8264   [(clobber (const_int 0))]
8265   "TARGET_EITHER"
8266   "if (TARGET_ARM)
8267      arm_expand_prologue ();
8268    else
8269      thumb_expand_prologue ();
8270   DONE;
8271   "
8274 (define_expand "epilogue"
8275   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8276   "TARGET_EITHER"
8277   "
8278   if (TARGET_THUMB)
8279     thumb_expand_epilogue ();
8280   else if (USE_RETURN_INSN (FALSE))
8281     {
8282       emit_jump_insn (gen_return ());
8283       DONE;
8284     }
8285   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8286         gen_rtvec (1,
8287                 gen_rtx_RETURN (VOIDmode)),
8288         VUNSPEC_EPILOGUE));
8289   DONE;
8290   "
8293 ;; Note - although unspec_volatile's USE all hard registers,
8294 ;; USEs are ignored after relaod has completed.  Thus we need
8295 ;; to add an unspec of the link register to ensure that flow
8296 ;; does not think that it is unused by the sibcall branch that
8297 ;; will replace the standard function epilogue.
8298 (define_insn "sibcall_epilogue"
8299   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8300               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8301   "TARGET_ARM"
8302   "*
8303   if (USE_RETURN_INSN (FALSE))
8304     return output_return_instruction (const_true_rtx, FALSE, FALSE);
8305   return arm_output_epilogue (FALSE);
8306   "
8307 ;; Length is absolute worst case
8308   [(set_attr "length" "44")
8309    (set_attr "type" "block")
8310    ;; We don't clobber the conditions, but the potential length of this
8311    ;; operation is sufficient to make conditionalizing the sequence 
8312    ;; unlikely to be profitable.
8313    (set_attr "conds" "clob")]
8316 (define_insn "*epilogue_insns"
8317   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8318   "TARGET_EITHER"
8319   "*
8320   if (TARGET_ARM)
8321     return arm_output_epilogue (TRUE);
8322   else /* TARGET_THUMB */
8323     return thumb_unexpanded_epilogue ();
8324   "
8325   ; Length is absolute worst case
8326   [(set_attr "length" "44")
8327    (set_attr "type" "block")
8328    ;; We don't clobber the conditions, but the potential length of this
8329    ;; operation is sufficient to make conditionalizing the sequence 
8330    ;; unlikely to be profitable.
8331    (set_attr "conds" "clob")]
8334 (define_expand "eh_epilogue"
8335   [(use (match_operand:SI 0 "register_operand" ""))
8336    (use (match_operand:SI 1 "register_operand" ""))
8337    (use (match_operand:SI 2 "register_operand" ""))]
8338   "TARGET_EITHER"
8339   "
8340   {
8341     cfun->machine->eh_epilogue_sp_ofs = operands[1];
8342     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8343       {
8344         rtx ra = gen_rtx_REG (Pmode, 2);
8346         emit_move_insn (ra, operands[2]);
8347         operands[2] = ra;
8348       }
8349     /* This is a hack -- we may have crystalized the function type too
8350        early.  */
8351     cfun->machine->func_type = 0;
8352   }"
8355 ;; This split is only used during output to reduce the number of patterns
8356 ;; that need assembler instructions adding to them.  We allowed the setting
8357 ;; of the conditions to be implicit during rtl generation so that
8358 ;; the conditional compare patterns would work.  However this conflicts to
8359 ;; some extent with the conditional data operations, so we have to split them
8360 ;; up again here.
8362 (define_split
8363   [(set (match_operand:SI 0 "s_register_operand" "")
8364         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8365                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8366                          (match_dup 0)
8367                          (match_operand 4 "" "")))
8368    (clobber (reg:CC CC_REGNUM))]
8369   ;; Note we have to suppress this split for the iwmmxt because it
8370   ;; creates a conditional movsi and the iwmmxt_movsi_insn pattern
8371   ;; is not predicable.  This sucks.
8372   "TARGET_ARM && reload_completed && ! TARGET_IWMMXT"
8373   [(set (match_dup 5) (match_dup 6))
8374    (cond_exec (match_dup 7)
8375               (set (match_dup 0) (match_dup 4)))]
8376   "
8377   {
8378     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8379                                              operands[2], operands[3]);
8380     enum rtx_code rc = GET_CODE (operands[1]);
8382     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8383     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8384     if (mode == CCFPmode || mode == CCFPEmode)
8385       rc = reverse_condition_maybe_unordered (rc);
8386     else
8387       rc = reverse_condition (rc);
8389     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8390   }"
8393 (define_split
8394   [(set (match_operand:SI 0 "s_register_operand" "")
8395         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8396                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8397                          (match_operand 4 "" "")
8398                          (match_dup 0)))
8399    (clobber (reg:CC CC_REGNUM))]
8400   ;; Note we have to suppress this split for the iwmmxt because it
8401   ;; creates a conditional movsi and the iwmmxt_movsi_insn pattern
8402   ;; is not predicable.  This sucks.
8403   "TARGET_ARM && reload_completed && ! TARGET_IWMMXT"
8404   [(set (match_dup 5) (match_dup 6))
8405    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8406               (set (match_dup 0) (match_dup 4)))]
8407   "
8408   {
8409     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8410                                              operands[2], operands[3]);
8412     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8413     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8414   }"
8417 (define_split
8418   [(set (match_operand:SI 0 "s_register_operand" "")
8419         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8420                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8421                          (match_operand 4 "" "")
8422                          (match_operand 5 "" "")))
8423    (clobber (reg:CC CC_REGNUM))]
8424   ;; Note we have to suppress this split for the iwmmxt because it
8425   ;; creates a conditional movsi and the iwmmxt_movsi_insn pattern
8426   ;; is not predicable.  This sucks.
8427   "TARGET_ARM && reload_completed && ! TARGET_IWMMXT"
8428   [(set (match_dup 6) (match_dup 7))
8429    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8430               (set (match_dup 0) (match_dup 4)))
8431    (cond_exec (match_dup 8)
8432               (set (match_dup 0) (match_dup 5)))]
8433   "
8434   {
8435     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8436                                              operands[2], operands[3]);
8437     enum rtx_code rc = GET_CODE (operands[1]);
8439     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8440     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8441     if (mode == CCFPmode || mode == CCFPEmode)
8442       rc = reverse_condition_maybe_unordered (rc);
8443     else
8444       rc = reverse_condition (rc);
8446     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8447   }"
8450 (define_split
8451   [(set (match_operand:SI 0 "s_register_operand" "")
8452         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8453                           [(match_operand:SI 2 "s_register_operand" "")
8454                            (match_operand:SI 3 "arm_add_operand" "")])
8455                          (match_operand:SI 4 "arm_rhs_operand" "")
8456                          (not:SI
8457                           (match_operand:SI 5 "s_register_operand" ""))))
8458    (clobber (reg:CC CC_REGNUM))]
8459   ;; Note we have to suppress this split for the iwmmxt because it
8460   ;; creates a conditional movsi and the iwmmxt_movsi_insn pattern
8461   ;; is not predicable.  This sucks.
8462   "TARGET_ARM && reload_completed && ! TARGET_IWMMXT"
8463   [(set (match_dup 6) (match_dup 7))
8464    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8465               (set (match_dup 0) (match_dup 4)))
8466    (cond_exec (match_dup 8)
8467               (set (match_dup 0) (not:SI (match_dup 5))))]
8468   "
8469   {
8470     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8471                                              operands[2], operands[3]);
8472     enum rtx_code rc = GET_CODE (operands[1]);
8474     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8475     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8476     if (mode == CCFPmode || mode == CCFPEmode)
8477       rc = reverse_condition_maybe_unordered (rc);
8478     else
8479       rc = reverse_condition (rc);
8481     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8482   }"
8485 (define_insn "*cond_move_not"
8486   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8487         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8488                           [(match_operand 3 "cc_register" "") (const_int 0)])
8489                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8490                          (not:SI
8491                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
8492   "TARGET_ARM"
8493   "@
8494    mvn%D4\\t%0, %2
8495    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8496   [(set_attr "conds" "use")
8497    (set_attr "length" "4,8")]
8500 ;; The next two patterns occur when an AND operation is followed by a
8501 ;; scc insn sequence 
8503 (define_insn "*sign_extract_onebit"
8504   [(set (match_operand:SI 0 "s_register_operand" "=r")
8505         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8506                          (const_int 1)
8507                          (match_operand:SI 2 "const_int_operand" "n")))
8508     (clobber (reg:CC CC_REGNUM))]
8509   "TARGET_ARM"
8510   "*
8511     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8512     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8513     return \"mvnne\\t%0, #0\";
8514   "
8515   [(set_attr "conds" "clob")
8516    (set_attr "length" "8")]
8519 (define_insn "*not_signextract_onebit"
8520   [(set (match_operand:SI 0 "s_register_operand" "=r")
8521         (not:SI
8522          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8523                           (const_int 1)
8524                           (match_operand:SI 2 "const_int_operand" "n"))))
8525    (clobber (reg:CC CC_REGNUM))]
8526   "TARGET_ARM"
8527   "*
8528     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8529     output_asm_insn (\"tst\\t%1, %2\", operands);
8530     output_asm_insn (\"mvneq\\t%0, #0\", operands);
8531     return \"movne\\t%0, #0\";
8532   "
8533   [(set_attr "conds" "clob")
8534    (set_attr "length" "12")]
8537 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8538 ;; expressions.  For simplicity, the first register is also in the unspec
8539 ;; part.
8540 (define_insn "*push_multi"
8541   [(match_parallel 2 "multi_register_push"
8542     [(set (match_operand:BLK 0 "memory_operand" "=m")
8543           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8544                       UNSPEC_PUSH_MULT))])]
8545   "TARGET_ARM"
8546   "*
8547   {
8548     int num_saves = XVECLEN (operands[2], 0);
8549      
8550     /* For the StrongARM at least it is faster to
8551        use STR to store only a single register.  */
8552     if (num_saves == 1)
8553       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8554     else
8555       {
8556         int i;
8557         char pattern[100];
8559         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8561         for (i = 1; i < num_saves; i++)
8562           {
8563             strcat (pattern, \", %|\");
8564             strcat (pattern,
8565                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8566           }
8568         strcat (pattern, \"}\");
8569         output_asm_insn (pattern, operands);
8570       }
8572     return \"\";
8573   }"
8574   [(set_attr "type" "store4")]
8577 (define_insn "stack_tie"
8578   [(set (mem:BLK (scratch))
8579         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8580                      (match_operand:SI 1 "s_register_operand" "r")]
8581                     UNSPEC_PRLG_STK))]
8582   ""
8583   ""
8584   [(set_attr "length" "0")]
8587 ;; Similarly for the floating point registers
8588 (define_insn "*push_fp_multi"
8589   [(match_parallel 2 "multi_register_push"
8590     [(set (match_operand:BLK 0 "memory_operand" "=m")
8591           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8592                       UNSPEC_PUSH_MULT))])]
8593   "TARGET_ARM"
8594   "*
8595   {
8596     char pattern[100];
8598     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8599     output_asm_insn (pattern, operands);
8600     return \"\";
8601   }"
8602   [(set_attr "type" "f_store")]
8605 ;; Special patterns for dealing with the constant pool
8607 (define_insn "align_4"
8608   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8609   "TARGET_EITHER"
8610   "*
8611   assemble_align (32);
8612   return \"\";
8613   "
8616 (define_insn "align_8"
8617   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
8618   "TARGET_REALLY_IWMMXT"
8619   "*
8620   assemble_align (64);
8621   return \"\";
8622   "
8625 (define_insn "consttable_end"
8626   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8627   "TARGET_EITHER"
8628   "*
8629   making_const_table = FALSE;
8630   return \"\";
8631   "
8634 (define_insn "consttable_1"
8635   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8636   "TARGET_THUMB"
8637   "*
8638   making_const_table = TRUE;
8639   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8640   assemble_zeros (3);
8641   return \"\";
8642   "
8643   [(set_attr "length" "4")]
8646 (define_insn "consttable_2"
8647   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8648   "TARGET_THUMB"
8649   "*
8650   making_const_table = TRUE;
8651   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8652   assemble_zeros (2);
8653   return \"\";
8654   "
8655   [(set_attr "length" "4")]
8658 (define_insn "consttable_4"
8659   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8660   "TARGET_EITHER"
8661   "*
8662   {
8663     making_const_table = TRUE;
8664     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8665       {
8666       case MODE_FLOAT:
8667       {
8668         REAL_VALUE_TYPE r;
8669         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8670         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8671         break;
8672       }
8673       default:
8674         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8675         break;
8676       }
8677     return \"\";
8678   }"
8679   [(set_attr "length" "4")]
8682 (define_insn "consttable_8"
8683   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8684   "TARGET_EITHER"
8685   "*
8686   {
8687     making_const_table = TRUE;
8688     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8689       {
8690        case MODE_FLOAT:
8691         {
8692           REAL_VALUE_TYPE r;
8693           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8694           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8695           break;
8696         }
8697       default:
8698         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8699         break;
8700       }
8701     return \"\";
8702   }"
8703   [(set_attr "length" "8")]
8706 ;; Miscellaneous Thumb patterns
8708 (define_expand "tablejump"
8709   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
8710               (use (label_ref (match_operand 1 "" "")))])]
8711   "TARGET_THUMB"
8712   "
8713   if (flag_pic)
8714     {
8715       /* Hopefully, CSE will eliminate this copy.  */
8716       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8717       rtx reg2 = gen_reg_rtx (SImode);
8719       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8720       operands[0] = reg2;
8721     }
8722   "
8725 (define_insn "*thumb_tablejump"
8726   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8727    (use (label_ref (match_operand 1 "" "")))]
8728   "TARGET_THUMB"
8729   "mov\\t%|pc, %0"
8730   [(set_attr "length" "2")]
8733 ;; V5 Instructions,
8735 (define_insn "clzsi2"
8736   [(set (match_operand:SI 0 "s_register_operand" "=r")
8737         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8738   "TARGET_ARM && arm_arch5"
8739   "clz%?\\t%0, %1"
8740   [(set_attr "predicable" "yes")])
8742 (define_expand "ffssi2"
8743   [(set (match_operand:SI 0 "s_register_operand" "")
8744         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
8745   "TARGET_ARM && arm_arch5"
8746   "
8747   {
8748     rtx t1, t2, t3;
8750     t1 = gen_reg_rtx (SImode);
8751     t2 = gen_reg_rtx (SImode);
8752     t3 = gen_reg_rtx (SImode);
8754     emit_insn (gen_negsi2 (t1, operands[1]));
8755     emit_insn (gen_andsi3 (t2, operands[1], t1));
8756     emit_insn (gen_clzsi2 (t3, t2));
8757     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
8758     DONE;
8759   }"
8762 (define_expand "ctzsi2"
8763   [(set (match_operand:SI 0 "s_register_operand" "")
8764         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
8765   "TARGET_ARM && arm_arch5"
8766   "
8767   {
8768     rtx t1, t2, t3;
8770     t1 = gen_reg_rtx (SImode);
8771     t2 = gen_reg_rtx (SImode);
8772     t3 = gen_reg_rtx (SImode);
8774     emit_insn (gen_negsi2 (t1, operands[1]));
8775     emit_insn (gen_andsi3 (t2, operands[1], t1));
8776     emit_insn (gen_clzsi2 (t3, t2));
8777     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
8778     DONE;
8779   }"
8782 ;; V5E instructions.
8784 (define_insn "prefetch"
8785   [(prefetch (match_operand:SI 0 "address_operand" "p")
8786              (match_operand:SI 1 "" "")
8787              (match_operand:SI 2 "" ""))]
8788   "TARGET_ARM && arm_arch5e"
8789   "pld\\t%a0")
8791 ;; General predication pattern
8793 (define_cond_exec
8794   [(match_operator 0 "arm_comparison_operator"
8795     [(match_operand 1 "cc_register" "")
8796      (const_int 0)])]
8797   "TARGET_ARM"
8798   ""
8801 (define_insn "prologue_use"
8802   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
8803   ""
8804   "%@ %0 needed for prologue"
8807 ;; Load the FPA co-processor patterns
8808 (include "fpa.md")
8809 ;; Load the Maverick co-processor patterns
8810 (include "cirrus.md")
8811 ;; Load the Intel Wireless Multimedia Extension patterns
8812 (include "iwmmxt.md")