* arm.c (arm_addimm_operand): MODE arguemnt is unused.
[official-gcc.git] / gcc / config / arm / arm.md
blob502b8d205781ba7584e09ddb4935dc7ba78a48ff
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 intrinsic form of the iWMMXt WSHUFH instruction.
79    (UNSPEC_WACC      9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80    (UNSPEC_TMOVMSK  10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81    (UNSPEC_WSAD     11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82    (UNSPEC_WSADZ    12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83    (UNSPEC_WMACS    13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84    (UNSPEC_WMACU    14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85    (UNSPEC_WMACSZ   15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86    (UNSPEC_WMACUZ   16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87    (UNSPEC_CLRDI    17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88    (UNSPEC_WMADDS   18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89    (UNSPEC_WMADDU   19) ; Used by the intrinsic 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 warrant 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 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
671 ;; addend is a constant.
672 (define_insn "*cmpsi2_addneg"
673   [(set (reg:CC CC_REGNUM)
674         (compare:CC
675          (match_operand:SI 1 "s_register_operand" "r,r")
676          (match_operand:SI 2 "arm_addimm_operand" "I,L")))
677    (set (match_operand:SI 0 "s_register_operand" "=r,r")
678         (plus:SI (match_dup 1)
679                  (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
680   "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
681   "@
682    sub%?s\\t%0, %1, %2
683    add%?s\\t%0, %1, #%n2"
684   [(set_attr "conds" "set")]
687 ;; Convert the sequence
688 ;;  sub  rd, rn, #1
689 ;;  cmn  rd, #1 (equivalent to cmp rd, #-1)
690 ;;  bne  dest
691 ;; into
692 ;;  subs rd, rn, #1
693 ;;  bcs  dest   ((unsigned)rn >= 1)
694 ;; similarly for the beq variant using bcc.
695 ;; This is a common looping idiom (while (n--))
696 (define_peephole2
697   [(set (match_operand:SI 0 "s_register_operand" "")
698         (plus:SI (match_operand:SI 1 "s_register_operand" "")
699                  (const_int -1)))
700    (set (match_operand 2 "cc_register" "")
701         (compare (match_dup 0) (const_int -1)))
702    (set (pc)
703         (if_then_else (match_operator 3 "equality_operator"
704                        [(match_dup 2) (const_int 0)])
705                       (match_operand 4 "" "")
706                       (match_operand 5 "" "")))]
707   "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
708   [(parallel[
709     (set (match_dup 2)
710          (compare:CC
711           (match_dup 1) (const_int 1)))
712     (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
713    (set (pc)
714         (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
715                       (match_dup 4)
716                       (match_dup 5)))]
717   "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
718    operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
719                                   ? GEU : LTU),
720                                  VOIDmode, 
721                                  operands[2], const0_rtx);"
724 ;; The next four insns work because they compare the result with one of
725 ;; the operands, and we know that the use of the condition code is
726 ;; either GEU or LTU, so we can use the carry flag from the addition
727 ;; instead of doing the compare a second time.
728 (define_insn "*addsi3_compare_op1"
729   [(set (reg:CC_C CC_REGNUM)
730         (compare:CC_C
731          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
732                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
733          (match_dup 1)))
734    (set (match_operand:SI 0 "s_register_operand" "=r,r")
735         (plus:SI (match_dup 1) (match_dup 2)))]
736   "TARGET_ARM"
737   "@
738    add%?s\\t%0, %1, %2
739    sub%?s\\t%0, %1, #%n2"
740   [(set_attr "conds" "set")]
743 (define_insn "*addsi3_compare_op2"
744   [(set (reg:CC_C CC_REGNUM)
745         (compare:CC_C
746          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
747                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
748          (match_dup 2)))
749    (set (match_operand:SI 0 "s_register_operand" "=r,r")
750         (plus:SI (match_dup 1) (match_dup 2)))]
751   "TARGET_ARM"
752   "@
753    add%?s\\t%0, %1, %2
754    sub%?s\\t%0, %1, #%n2"
755   [(set_attr "conds" "set")]
758 (define_insn "*compare_addsi2_op0"
759   [(set (reg:CC_C CC_REGNUM)
760         (compare:CC_C
761          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
762                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
763          (match_dup 0)))]
764   "TARGET_ARM"
765   "@
766    cmn%?\\t%0, %1
767    cmp%?\\t%0, #%n1"
768   [(set_attr "conds" "set")]
771 (define_insn "*compare_addsi2_op1"
772   [(set (reg:CC_C CC_REGNUM)
773         (compare:CC_C
774          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
775                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
776          (match_dup 1)))]
777   "TARGET_ARM"
778   "@
779    cmn%?\\t%0, %1
780    cmp%?\\t%0, #%n1"
781   [(set_attr "conds" "set")]
784 (define_insn "*addsi3_carryin"
785   [(set (match_operand:SI 0 "s_register_operand" "=r")
786         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
787                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
788                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
789   "TARGET_ARM"
790   "adc%?\\t%0, %1, %2"
791   [(set_attr "conds" "use")]
794 (define_insn "*addsi3_carryin_shift"
795   [(set (match_operand:SI 0 "s_register_operand" "")
796         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
797                  (plus:SI
798                    (match_operator:SI 2 "shift_operator"
799                       [(match_operand:SI 3 "s_register_operand" "")
800                        (match_operand:SI 4 "reg_or_int_operand" "")])
801                     (match_operand:SI 1 "s_register_operand" ""))))]
802   "TARGET_ARM"
803   "adc%?\\t%0, %1, %3%S2"
804   [(set_attr "conds" "use")]
807 (define_insn "*addsi3_carryin_alt1"
808   [(set (match_operand:SI 0 "s_register_operand" "=r")
809         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
810                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
811                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
812   "TARGET_ARM"
813   "adc%?\\t%0, %1, %2"
814   [(set_attr "conds" "use")]
817 (define_insn "*addsi3_carryin_alt2"
818   [(set (match_operand:SI 0 "s_register_operand" "=r")
819         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
820                           (match_operand:SI 1 "s_register_operand" "r"))
821                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
822   "TARGET_ARM"
823   "adc%?\\t%0, %1, %2"
824   [(set_attr "conds" "use")]
827 (define_insn "*addsi3_carryin_alt3"
828   [(set (match_operand:SI 0 "s_register_operand" "=r")
829         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
830                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
831                  (match_operand:SI 1 "s_register_operand" "r")))]
832   "TARGET_ARM"
833   "adc%?\\t%0, %1, %2"
834   [(set_attr "conds" "use")]
837 (define_insn "incscc"
838   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
839         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
840                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
841                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
842   "TARGET_ARM"
843   "@
844   add%d2\\t%0, %1, #1
845   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
846   [(set_attr "conds" "use")
847    (set_attr "length" "4,8")]
850 (define_expand "addsf3"
851   [(set (match_operand:SF          0 "s_register_operand" "")
852         (plus:SF (match_operand:SF 1 "s_register_operand" "")
853                  (match_operand:SF 2 "fpa_add_operand" "")))]
854   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
855   "
856   if (TARGET_CIRRUS
857       && !cirrus_fp_register (operands[2], SFmode))
858     operands[2] = force_reg (SFmode, operands[2]);
861 (define_expand "adddf3"
862   [(set (match_operand:DF          0 "s_register_operand" "")
863         (plus:DF (match_operand:DF 1 "s_register_operand" "")
864                  (match_operand:DF 2 "fpa_add_operand" "")))]
865   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
866   "
867   if (TARGET_CIRRUS
868       && !cirrus_fp_register (operands[2], DFmode))
869     operands[2] = force_reg (DFmode, operands[2]);
872 (define_expand "subdi3"
873  [(parallel
874    [(set (match_operand:DI            0 "s_register_operand" "")
875           (minus:DI (match_operand:DI 1 "s_register_operand" "")
876                     (match_operand:DI 2 "s_register_operand" "")))
877     (clobber (reg:CC CC_REGNUM))])]
878   "TARGET_EITHER"
879   "
880   if (TARGET_CIRRUS
881       && TARGET_ARM
882       && cirrus_fp_register (operands[0], DImode)
883       && cirrus_fp_register (operands[1], DImode))
884     {
885       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
886       DONE;
887     }
889   if (TARGET_THUMB)
890     {
891       if (GET_CODE (operands[1]) != REG)
892         operands[1] = force_reg (SImode, operands[1]);
893       if (GET_CODE (operands[2]) != REG)
894         operands[2] = force_reg (SImode, operands[2]);
895      }  
896   "
899 (define_insn "*arm_subdi3"
900   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
901         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
902                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
903    (clobber (reg:CC CC_REGNUM))]
904   "TARGET_ARM"
905   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
906   [(set_attr "conds" "clob")
907    (set_attr "length" "8")]
910 (define_insn "*thumb_subdi3"
911   [(set (match_operand:DI           0 "register_operand" "=l")
912         (minus:DI (match_operand:DI 1 "register_operand"  "0")
913                   (match_operand:DI 2 "register_operand"  "l")))
914    (clobber (reg:CC CC_REGNUM))]
915   "TARGET_THUMB"
916   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
917   [(set_attr "length" "4")]
920 (define_insn "*subdi_di_zesidi"
921   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
922         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
923                   (zero_extend:DI
924                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
925    (clobber (reg:CC CC_REGNUM))]
926   "TARGET_ARM"
927   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
928   [(set_attr "conds" "clob")
929    (set_attr "length" "8")]
932 (define_insn "*subdi_di_sesidi"
933   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
934         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
935                   (sign_extend:DI
936                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
937    (clobber (reg:CC CC_REGNUM))]
938   "TARGET_ARM"
939   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
940   [(set_attr "conds" "clob")
941    (set_attr "length" "8")]
944 (define_insn "*subdi_zesidi_di"
945   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
946         (minus:DI (zero_extend:DI
947                    (match_operand:SI 2 "s_register_operand"  "r,r"))
948                   (match_operand:DI  1 "s_register_operand" "?r,0")))
949    (clobber (reg:CC CC_REGNUM))]
950   "TARGET_ARM"
951   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
952   [(set_attr "conds" "clob")
953    (set_attr "length" "8")]
956 (define_insn "*subdi_sesidi_di"
957   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
958         (minus:DI (sign_extend:DI
959                    (match_operand:SI 2 "s_register_operand"   "r,r"))
960                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
961    (clobber (reg:CC CC_REGNUM))]
962   "TARGET_ARM"
963   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
964   [(set_attr "conds" "clob")
965    (set_attr "length" "8")]
968 (define_insn "*subdi_zesidi_zesidi"
969   [(set (match_operand:DI            0 "s_register_operand" "=r")
970         (minus:DI (zero_extend:DI
971                    (match_operand:SI 1 "s_register_operand"  "r"))
972                   (zero_extend:DI
973                    (match_operand:SI 2 "s_register_operand"  "r"))))
974    (clobber (reg:CC CC_REGNUM))]
975   "TARGET_ARM"
976   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
977   [(set_attr "conds" "clob")
978    (set_attr "length" "8")]
981 (define_expand "subsi3"
982   [(set (match_operand:SI           0 "s_register_operand" "")
983         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
984                   (match_operand:SI 2 "s_register_operand" "")))]
985   "TARGET_EITHER"
986   "
987   if (GET_CODE (operands[1]) == CONST_INT)
988     {
989       if (TARGET_ARM)
990         {
991           arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
992                               operands[2],
993                               (no_new_pseudos ? 0
994                                :  preserve_subexpressions_p ()));
995           DONE;
996         }
997       else /* TARGET_THUMB */
998         operands[1] = force_reg (SImode, operands[1]);
999     }
1000   "
1003 (define_insn "*thumb_subsi3_insn"
1004   [(set (match_operand:SI           0 "register_operand" "=l")
1005         (minus:SI (match_operand:SI 1 "register_operand" "l")
1006                   (match_operand:SI 2 "register_operand" "l")))]
1007   "TARGET_THUMB"
1008   "sub\\t%0, %1, %2"
1009   [(set_attr "length" "2")]
1012 (define_insn_and_split "*arm_subsi3_insn"
1013   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
1014         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1015                   (match_operand:SI 2 "s_register_operand" "r,r")))]
1016   "TARGET_ARM"
1017   "@
1018    rsb%?\\t%0, %2, %1
1019    #"
1020   "TARGET_ARM
1021    && GET_CODE (operands[1]) == CONST_INT
1022    && !const_ok_for_arm (INTVAL (operands[1]))"
1023   [(clobber (const_int 0))]
1024   "
1025   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1026                       operands[2], 0);
1027   DONE;
1028   "
1029   [(set_attr "length" "4,16")
1030    (set_attr "predicable" "yes")]
1033 (define_peephole2
1034   [(match_scratch:SI 3 "r")
1035    (set (match_operand:SI           0 "s_register_operand" "")
1036         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1037                   (match_operand:SI 2 "s_register_operand" "")))]
1038   "TARGET_ARM
1039    && !const_ok_for_arm (INTVAL (operands[1]))
1040    && const_ok_for_arm (~INTVAL (operands[1]))"
1041   [(set (match_dup 3) (match_dup 1))
1042    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1043   ""
1046 (define_insn "*subsi3_compare0"
1047   [(set (reg:CC_NOOV CC_REGNUM)
1048         (compare:CC_NOOV
1049          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1050                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1051          (const_int 0)))
1052    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1053         (minus:SI (match_dup 1) (match_dup 2)))]
1054   "TARGET_ARM"
1055   "@
1056    sub%?s\\t%0, %1, %2
1057    rsb%?s\\t%0, %2, %1"
1058   [(set_attr "conds" "set")]
1061 (define_insn "decscc"
1062   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1063         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1064                   (match_operator:SI 2 "arm_comparison_operator"
1065                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1066   "TARGET_ARM"
1067   "@
1068    sub%d2\\t%0, %1, #1
1069    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1070   [(set_attr "conds" "use")
1071    (set_attr "length" "*,8")]
1074 (define_expand "subsf3"
1075   [(set (match_operand:SF           0 "s_register_operand" "")
1076         (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1077                   (match_operand:SF 2 "fpa_rhs_operand" "")))]
1078   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1079   "
1080   if (TARGET_CIRRUS)
1081     {
1082       if (!cirrus_fp_register (operands[1], SFmode))
1083         operands[1] = force_reg (SFmode, operands[1]);
1084       if (!cirrus_fp_register (operands[2], SFmode))
1085         operands[2] = force_reg (SFmode, operands[2]);
1086     }
1089 (define_expand "subdf3"
1090   [(set (match_operand:DF           0 "s_register_operand" "")
1091         (minus:DF (match_operand:DF 1 "fpa_rhs_operand"     "")
1092                   (match_operand:DF 2 "fpa_rhs_operand"    "")))]
1093   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1094   "
1095   if (TARGET_CIRRUS)
1096     {
1097        if (!cirrus_fp_register (operands[1], DFmode))
1098          operands[1] = force_reg (DFmode, operands[1]);
1099        if (!cirrus_fp_register (operands[2], DFmode))
1100          operands[2] = force_reg (DFmode, operands[2]);
1101     }
1105 ;; Multiplication insns
1107 (define_expand "mulsi3"
1108   [(set (match_operand:SI          0 "s_register_operand" "")
1109         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1110                  (match_operand:SI 1 "s_register_operand" "")))]
1111   "TARGET_EITHER"
1112   ""
1115 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1116 (define_insn "*arm_mulsi3"
1117   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1118         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1119                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1120   "TARGET_ARM"
1121   "mul%?\\t%0, %2, %1"
1122   [(set_attr "type" "mult")
1123    (set_attr "predicable" "yes")]
1126 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1127 ; 1 and 2; are the same, because reload will make operand 0 match 
1128 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1129 ; this by adding another alternative to match this case, and then `reload' 
1130 ; it ourselves.  This alternative must come first.
1131 (define_insn "*thumb_mulsi3"
1132   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1133         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1134                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1135   "TARGET_THUMB"
1136   "*
1137   if (which_alternative < 2)
1138     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1139   else
1140     return \"mul\\t%0, %0, %2\";
1141   "
1142   [(set_attr "length" "4,4,2")
1143    (set_attr "type" "mult")]
1146 (define_insn "*mulsi3_compare0"
1147   [(set (reg:CC_NOOV CC_REGNUM)
1148         (compare:CC_NOOV (mult:SI
1149                           (match_operand:SI 2 "s_register_operand" "r,r")
1150                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1151                          (const_int 0)))
1152    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1153         (mult:SI (match_dup 2) (match_dup 1)))]
1154   "TARGET_ARM && !arm_arch_xscale"
1155   "mul%?s\\t%0, %2, %1"
1156   [(set_attr "conds" "set")
1157    (set_attr "type" "mult")]
1160 (define_insn "*mulsi_compare0_scratch"
1161   [(set (reg:CC_NOOV CC_REGNUM)
1162         (compare:CC_NOOV (mult:SI
1163                           (match_operand:SI 2 "s_register_operand" "r,r")
1164                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1165                          (const_int 0)))
1166    (clobber (match_scratch:SI 0 "=&r,&r"))]
1167   "TARGET_ARM && !arm_arch_xscale"
1168   "mul%?s\\t%0, %2, %1"
1169   [(set_attr "conds" "set")
1170    (set_attr "type" "mult")]
1173 ;; Unnamed templates to match MLA instruction.
1175 (define_insn "*mulsi3addsi"
1176   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1177         (plus:SI
1178           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1179                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1180           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1181   "TARGET_ARM"
1182   "mla%?\\t%0, %2, %1, %3"
1183   [(set_attr "type" "mult")
1184    (set_attr "predicable" "yes")]
1187 (define_insn "*mulsi3addsi_compare0"
1188   [(set (reg:CC_NOOV CC_REGNUM)
1189         (compare:CC_NOOV
1190          (plus:SI (mult:SI
1191                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1192                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1193                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1194          (const_int 0)))
1195    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1196         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1197                  (match_dup 3)))]
1198   "TARGET_ARM && !arm_arch_xscale"
1199   "mla%?s\\t%0, %2, %1, %3"
1200   [(set_attr "conds" "set")
1201    (set_attr "type" "mult")]
1204 (define_insn "*mulsi3addsi_compare0_scratch"
1205   [(set (reg:CC_NOOV CC_REGNUM)
1206         (compare:CC_NOOV
1207          (plus:SI (mult:SI
1208                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1209                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1210                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1211          (const_int 0)))
1212    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1213   "TARGET_ARM && !arm_arch_xscale"
1214   "mla%?s\\t%0, %2, %1, %3"
1215   [(set_attr "conds" "set")
1216    (set_attr "type" "mult")]
1219 ;; Unnamed template to match long long multiply-accumlate (smlal)
1221 (define_insn "*mulsidi3adddi"
1222   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1223         (plus:DI
1224          (mult:DI
1225           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1226           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1227          (match_operand:DI 1 "s_register_operand" "0")))]
1228   "TARGET_ARM && arm_fast_multiply"
1229   "smlal%?\\t%Q0, %R0, %3, %2"
1230   [(set_attr "type" "mult")
1231    (set_attr "predicable" "yes")]
1234 (define_insn "mulsidi3"
1235   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1236         (mult:DI
1237          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1238          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1239   "TARGET_ARM && arm_fast_multiply"
1240   "smull%?\\t%Q0, %R0, %1, %2"
1241   [(set_attr "type" "mult")
1242    (set_attr "predicable" "yes")]
1245 (define_insn "umulsidi3"
1246   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1247         (mult:DI
1248          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1249          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1250   "TARGET_ARM && arm_fast_multiply"
1251   "umull%?\\t%Q0, %R0, %1, %2"
1252   [(set_attr "type" "mult")
1253    (set_attr "predicable" "yes")]
1256 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1258 (define_insn "*umulsidi3adddi"
1259   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1260         (plus:DI
1261          (mult:DI
1262           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1263           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1264          (match_operand:DI 1 "s_register_operand" "0")))]
1265   "TARGET_ARM && arm_fast_multiply"
1266   "umlal%?\\t%Q0, %R0, %3, %2"
1267   [(set_attr "type" "mult")
1268    (set_attr "predicable" "yes")]
1271 (define_insn "smulsi3_highpart"
1272   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1273         (truncate:SI
1274          (lshiftrt:DI
1275           (mult:DI
1276            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1277            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1278           (const_int 32))))
1279    (clobber (match_scratch:SI 3 "=&r,&r"))]
1280   "TARGET_ARM && arm_fast_multiply"
1281   "smull%?\\t%3, %0, %2, %1"
1282   [(set_attr "type" "mult")
1283    (set_attr "predicable" "yes")]
1286 (define_insn "umulsi3_highpart"
1287   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1288         (truncate:SI
1289          (lshiftrt:DI
1290           (mult:DI
1291            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1292            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1293           (const_int 32))))
1294    (clobber (match_scratch:SI 3 "=&r,&r"))]
1295   "TARGET_ARM && arm_fast_multiply"
1296   "umull%?\\t%3, %0, %2, %1"
1297   [(set_attr "type" "mult")
1298    (set_attr "predicable" "yes")]
1301 (define_insn "mulhisi3"
1302   [(set (match_operand:SI 0 "s_register_operand" "=r")
1303         (mult:SI (sign_extend:SI
1304                   (match_operand:HI 1 "s_register_operand" "%r"))
1305                  (sign_extend:SI
1306                   (match_operand:HI 2 "s_register_operand" "r"))))]
1307   "TARGET_ARM && arm_arch5e"
1308   "smulbb%?\\t%0, %1, %2"
1309   [(set_attr "type" "mult")
1310    (set_attr "predicable" "yes")]
1313 (define_insn "*mulhisi3tb"
1314   [(set (match_operand:SI 0 "s_register_operand" "=r")
1315         (mult:SI (ashiftrt:SI
1316                   (match_operand:SI 1 "s_register_operand" "r")
1317                   (const_int 16))
1318                  (sign_extend:SI
1319                   (match_operand:HI 2 "s_register_operand" "r"))))]
1320   "TARGET_ARM && arm_arch5e"
1321   "smultb%?\\t%0, %1, %2"
1322   [(set_attr "type" "mult")
1323    (set_attr "predicable" "yes")]
1326 (define_insn "*mulhisi3bt"
1327   [(set (match_operand:SI 0 "s_register_operand" "=r")
1328         (mult:SI (sign_extend:SI
1329                   (match_operand:HI 1 "s_register_operand" "r"))
1330                  (ashiftrt:SI
1331                   (match_operand:SI 2 "s_register_operand" "r")
1332                   (const_int 16))))]
1333   "TARGET_ARM && arm_arch5e"
1334   "smulbt%?\\t%0, %1, %2"
1335   [(set_attr "type" "mult")
1336    (set_attr "predicable" "yes")]
1339 (define_insn "*mulhisi3tt"
1340   [(set (match_operand:SI 0 "s_register_operand" "=r")
1341         (mult:SI (ashiftrt:SI
1342                   (match_operand:SI 1 "s_register_operand" "r")
1343                   (const_int 16))
1344                  (ashiftrt:SI
1345                   (match_operand:SI 2 "s_register_operand" "r")
1346                   (const_int 16))))]
1347   "TARGET_ARM && arm_arch5e"
1348   "smultt%?\\t%0, %1, %2"
1349   [(set_attr "type" "mult")
1350    (set_attr "predicable" "yes")]
1353 (define_insn "*mulhisi3addsi"
1354   [(set (match_operand:SI 0 "s_register_operand" "=r")
1355         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1356                  (mult:SI (sign_extend:SI
1357                            (match_operand:HI 2 "s_register_operand" "%r"))
1358                           (sign_extend:SI
1359                            (match_operand:HI 3 "s_register_operand" "r")))))]
1360   "TARGET_ARM && arm_arch5e"
1361   "smlabb%?\\t%0, %2, %3, %1"
1362   [(set_attr "type" "mult")
1363    (set_attr "predicable" "yes")]
1366 (define_insn "*mulhidi3adddi"
1367   [(set (match_operand:DI 0 "s_register_operand" "=r")
1368         (plus:DI
1369           (match_operand:DI 1 "s_register_operand" "0")
1370           (mult:DI (sign_extend:DI
1371                     (match_operand:HI 2 "s_register_operand" "%r"))
1372                    (sign_extend:DI
1373                     (match_operand:HI 3 "s_register_operand" "r")))))]
1374   "TARGET_ARM && arm_arch5e"
1375   "smlalbb%?\\t%Q0, %R0, %2, %3"
1376   [(set_attr "type" "mult")
1377    (set_attr "predicable" "yes")])
1379 (define_expand "mulsf3"
1380   [(set (match_operand:SF          0 "s_register_operand" "")
1381         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1382                  (match_operand:SF 2 "fpa_rhs_operand" "")))]
1383   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1384   "
1385   if (TARGET_CIRRUS
1386       && !cirrus_fp_register (operands[2], SFmode))
1387     operands[2] = force_reg (SFmode, operands[2]);
1390 (define_expand "muldf3"
1391   [(set (match_operand:DF          0 "s_register_operand" "")
1392         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1393                  (match_operand:DF 2 "fpa_rhs_operand" "")))]
1394   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1395   "
1396   if (TARGET_CIRRUS
1397       && !cirrus_fp_register (operands[2], DFmode))
1398     operands[2] = force_reg (DFmode, operands[2]);
1401 ;; Division insns
1403 (define_expand "divsf3"
1404   [(set (match_operand:SF 0 "s_register_operand" "")
1405         (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1406                 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1407   "TARGET_ARM && TARGET_HARD_FLOAT"
1408   "")
1410 (define_expand "divdf3"
1411   [(set (match_operand:DF 0 "s_register_operand" "")
1412         (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1413                 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1414   "TARGET_ARM && TARGET_HARD_FLOAT"
1415   "")
1417 ;; Modulo insns
1419 (define_expand "modsf3"
1420   [(set (match_operand:SF 0 "s_register_operand" "")
1421         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1422                 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1423   "TARGET_ARM && TARGET_HARD_FLOAT"
1424   "")
1426 (define_expand "moddf3"
1427   [(set (match_operand:DF 0 "s_register_operand" "")
1428         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1429                 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1430   "TARGET_ARM && TARGET_HARD_FLOAT"
1431   "")
1433 ;; Boolean and,ior,xor insns
1435 ;; Split up double word logical operations
1437 ;; Split up simple DImode logical operations.  Simply perform the logical
1438 ;; operation on the upper and lower halves of the registers.
1439 (define_split
1440   [(set (match_operand:DI 0 "s_register_operand" "")
1441         (match_operator:DI 6 "logical_binary_operator"
1442           [(match_operand:DI 1 "s_register_operand" "")
1443            (match_operand:DI 2 "s_register_operand" "")]))]
1444   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1445   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1446    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1447   "
1448   {
1449     operands[3] = gen_highpart (SImode, operands[0]);
1450     operands[0] = gen_lowpart (SImode, operands[0]);
1451     operands[4] = gen_highpart (SImode, operands[1]);
1452     operands[1] = gen_lowpart (SImode, operands[1]);
1453     operands[5] = gen_highpart (SImode, operands[2]);
1454     operands[2] = gen_lowpart (SImode, operands[2]);
1455   }"
1458 (define_split
1459   [(set (match_operand:DI 0 "s_register_operand" "")
1460         (match_operator:DI 6 "logical_binary_operator"
1461           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1462            (match_operand:DI 1 "s_register_operand" "")]))]
1463   "TARGET_ARM && reload_completed"
1464   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1465    (set (match_dup 3) (match_op_dup:SI 6
1466                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1467                          (match_dup 4)]))]
1468   "
1469   {
1470     operands[3] = gen_highpart (SImode, operands[0]);
1471     operands[0] = gen_lowpart (SImode, operands[0]);
1472     operands[4] = gen_highpart (SImode, operands[1]);
1473     operands[1] = gen_lowpart (SImode, operands[1]);
1474     operands[5] = gen_highpart (SImode, operands[2]);
1475     operands[2] = gen_lowpart (SImode, operands[2]);
1476   }"
1479 ;; The zero extend of operand 2 means we can just copy the high part of
1480 ;; operand1 into operand0.
1481 (define_split
1482   [(set (match_operand:DI 0 "s_register_operand" "")
1483         (ior:DI
1484           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1485           (match_operand:DI 1 "s_register_operand" "")))]
1486   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1487   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1488    (set (match_dup 3) (match_dup 4))]
1489   "
1490   {
1491     operands[4] = gen_highpart (SImode, operands[1]);
1492     operands[3] = gen_highpart (SImode, operands[0]);
1493     operands[0] = gen_lowpart (SImode, operands[0]);
1494     operands[1] = gen_lowpart (SImode, operands[1]);
1495   }"
1498 ;; The zero extend of operand 2 means we can just copy the high part of
1499 ;; operand1 into operand0.
1500 (define_split
1501   [(set (match_operand:DI 0 "s_register_operand" "")
1502         (xor:DI
1503           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1504           (match_operand:DI 1 "s_register_operand" "")))]
1505   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1506   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1507    (set (match_dup 3) (match_dup 4))]
1508   "
1509   {
1510     operands[4] = gen_highpart (SImode, operands[1]);
1511     operands[3] = gen_highpart (SImode, operands[0]);
1512     operands[0] = gen_lowpart (SImode, operands[0]);
1513     operands[1] = gen_lowpart (SImode, operands[1]);
1514   }"
1517 (define_insn "anddi3"
1518   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1519         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1520                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1521   "TARGET_ARM && ! TARGET_IWMMXT"
1522   "#"
1523   [(set_attr "length" "8")]
1526 (define_insn_and_split "*anddi_zesidi_di"
1527   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1528         (and:DI (zero_extend:DI
1529                  (match_operand:SI 2 "s_register_operand" "r,r"))
1530                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1531   "TARGET_ARM"
1532   "#"
1533   "TARGET_ARM && reload_completed"
1534   ; The zero extend of operand 2 clears the high word of the output
1535   ; operand.
1536   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1537    (set (match_dup 3) (const_int 0))]
1538   "
1539   {
1540     operands[3] = gen_highpart (SImode, operands[0]);
1541     operands[0] = gen_lowpart (SImode, operands[0]);
1542     operands[1] = gen_lowpart (SImode, operands[1]);
1543   }"
1544   [(set_attr "length" "8")]
1547 (define_insn "*anddi_sesdi_di"
1548   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1549         (and:DI (sign_extend:DI
1550                  (match_operand:SI 2 "s_register_operand" "r,r"))
1551                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1552   "TARGET_ARM"
1553   "#"
1554   [(set_attr "length" "8")]
1557 (define_expand "andsi3"
1558   [(set (match_operand:SI         0 "s_register_operand" "")
1559         (and:SI (match_operand:SI 1 "s_register_operand" "")
1560                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1561   "TARGET_EITHER"
1562   "
1563   if (TARGET_ARM)
1564     {
1565       if (GET_CODE (operands[2]) == CONST_INT)
1566         {
1567           arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1568                               operands[1],
1569                               (no_new_pseudos
1570                                ? 0 : preserve_subexpressions_p ()));
1571           DONE;
1572         }
1573     }
1574   else /* TARGET_THUMB */
1575     {
1576       if (GET_CODE (operands[2]) != CONST_INT)
1577         operands[2] = force_reg (SImode, operands[2]);
1578       else
1579         {
1580           int i;
1581           
1582           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1583             {
1584               operands[2] = force_reg (SImode,
1585                                        GEN_INT (~INTVAL (operands[2])));
1586               
1587               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1588               
1589               DONE;
1590             }
1592           for (i = 9; i <= 31; i++)
1593             {
1594               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1595                 {
1596                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1597                                         const0_rtx));
1598                   DONE;
1599                 }
1600               else if ((((HOST_WIDE_INT) 1) << i) - 1
1601                        == ~INTVAL (operands[2]))
1602                 {
1603                   rtx shift = GEN_INT (i);
1604                   rtx reg = gen_reg_rtx (SImode);
1605                 
1606                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1607                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1608                   
1609                   DONE;
1610                 }
1611             }
1613           operands[2] = force_reg (SImode, operands[2]);
1614         }
1615     }
1616   "
1619 (define_insn_and_split "*arm_andsi3_insn"
1620   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1621         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1622                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1623   "TARGET_ARM"
1624   "@
1625    and%?\\t%0, %1, %2
1626    bic%?\\t%0, %1, #%B2
1627    #"
1628   "TARGET_ARM
1629    && GET_CODE (operands[2]) == CONST_INT
1630    && !(const_ok_for_arm (INTVAL (operands[2]))
1631         || const_ok_for_arm (~INTVAL (operands[2])))"
1632   [(clobber (const_int 0))]
1633   "
1634   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1635                        operands[1], 0);
1636   DONE;
1637   "
1638   [(set_attr "length" "4,4,16")
1639    (set_attr "predicable" "yes")]
1642 (define_insn "*thumb_andsi3_insn"
1643   [(set (match_operand:SI         0 "register_operand" "=l")
1644         (and:SI (match_operand:SI 1 "register_operand" "%0")
1645                 (match_operand:SI 2 "register_operand" "l")))]
1646   "TARGET_THUMB"
1647   "and\\t%0, %0, %2"
1648   [(set_attr "length" "2")]
1651 (define_insn "*andsi3_compare0"
1652   [(set (reg:CC_NOOV CC_REGNUM)
1653         (compare:CC_NOOV
1654          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1655                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1656          (const_int 0)))
1657    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1658         (and:SI (match_dup 1) (match_dup 2)))]
1659   "TARGET_ARM"
1660   "@
1661    and%?s\\t%0, %1, %2
1662    bic%?s\\t%0, %1, #%B2"
1663   [(set_attr "conds" "set")]
1666 (define_insn "*andsi3_compare0_scratch"
1667   [(set (reg:CC_NOOV CC_REGNUM)
1668         (compare:CC_NOOV
1669          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1670                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1671          (const_int 0)))
1672    (clobber (match_scratch:SI 2 "=X,r"))]
1673   "TARGET_ARM"
1674   "@
1675    tst%?\\t%0, %1
1676    bic%?s\\t%2, %0, #%B1"
1677   [(set_attr "conds" "set")]
1680 (define_insn "*zeroextractsi_compare0_scratch"
1681   [(set (reg:CC_NOOV CC_REGNUM)
1682         (compare:CC_NOOV (zero_extract:SI
1683                           (match_operand:SI 0 "s_register_operand" "r")
1684                           (match_operand 1 "const_int_operand" "n")
1685                           (match_operand 2 "const_int_operand" "n"))
1686                          (const_int 0)))]
1687   "TARGET_ARM
1688   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1689       && INTVAL (operands[1]) > 0 
1690       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1691       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1692   "*
1693   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1694                          << INTVAL (operands[2]));
1695   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1696   return \"\";
1697   "
1698   [(set_attr "conds" "set")]
1701 (define_insn "*ne_zeroextractsi"
1702   [(set (match_operand:SI 0 "s_register_operand" "=r")
1703         (ne:SI (zero_extract:SI
1704                 (match_operand:SI 1 "s_register_operand" "r")
1705                 (match_operand:SI 2 "const_int_operand" "n")
1706                 (match_operand:SI 3 "const_int_operand" "n"))
1707                (const_int 0)))
1708    (clobber (reg:CC CC_REGNUM))]
1709   "TARGET_ARM
1710    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1711        && INTVAL (operands[2]) > 0 
1712        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1713        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1714   "*
1715   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1716                          << INTVAL (operands[3]));
1717   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1718   return \"movne\\t%0, #1\";
1719   "
1720   [(set_attr "conds" "clob")
1721    (set_attr "length" "8")]
1724 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1725 ;;; represented by the bitfield, then this will produce incorrect results.
1726 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1727 ;;; which have a real bit-field insert instruction, the truncation happens
1728 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1729 ;;; bit-field insert instruction, we would have to emit code here to truncate
1730 ;;; the value before we insert.  This loses some of the advantage of having
1731 ;;; this insv pattern, so this pattern needs to be reevalutated.
1733 (define_expand "insv"
1734   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1735                          (match_operand:SI 1 "general_operand" "")
1736                          (match_operand:SI 2 "general_operand" ""))
1737         (match_operand:SI 3 "reg_or_int_operand" ""))]
1738   "TARGET_ARM"
1739   "
1740   {
1741     int start_bit = INTVAL (operands[2]);
1742     int width = INTVAL (operands[1]);
1743     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1744     rtx target, subtarget;
1746     target = operands[0];
1747     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1748        subreg as the final target.  */
1749     if (GET_CODE (target) == SUBREG)
1750       {
1751         subtarget = gen_reg_rtx (SImode);
1752         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1753             < GET_MODE_SIZE (SImode))
1754           target = SUBREG_REG (target);
1755       }
1756     else
1757       subtarget = target;    
1759     if (GET_CODE (operands[3]) == CONST_INT)
1760       {
1761         /* Since we are inserting a known constant, we may be able to
1762            reduce the number of bits that we have to clear so that
1763            the mask becomes simple.  */
1764         /* ??? This code does not check to see if the new mask is actually
1765            simpler.  It may not be.  */
1766         rtx op1 = gen_reg_rtx (SImode);
1767         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1768            start of this pattern.  */
1769         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1770         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1772         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1773         emit_insn (gen_iorsi3 (subtarget, op1,
1774                                GEN_INT (op3_value << start_bit)));
1775       }
1776     else if (start_bit == 0
1777              && !(const_ok_for_arm (mask)
1778                   || const_ok_for_arm (~mask)))
1779       {
1780         /* A Trick, since we are setting the bottom bits in the word,
1781            we can shift operand[3] up, operand[0] down, OR them together
1782            and rotate the result back again.  This takes 3 insns, and
1783            the third might be mergeable into another op.  */
1784         /* The shift up copes with the possibility that operand[3] is
1785            wider than the bitfield.  */
1786         rtx op0 = gen_reg_rtx (SImode);
1787         rtx op1 = gen_reg_rtx (SImode);
1789         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1790         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1791         emit_insn (gen_iorsi3  (op1, op1, op0));
1792         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1793       }
1794     else if ((width + start_bit == 32)
1795              && !(const_ok_for_arm (mask)
1796                   || const_ok_for_arm (~mask)))
1797       {
1798         /* Similar trick, but slightly less efficient.  */
1800         rtx op0 = gen_reg_rtx (SImode);
1801         rtx op1 = gen_reg_rtx (SImode);
1803         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1804         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1805         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1806         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1807       }
1808     else
1809       {
1810         rtx op0 = GEN_INT (mask);
1811         rtx op1 = gen_reg_rtx (SImode);
1812         rtx op2 = gen_reg_rtx (SImode);
1814         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1815           {
1816             rtx tmp = gen_reg_rtx (SImode);
1818             emit_insn (gen_movsi (tmp, op0));
1819             op0 = tmp;
1820           }
1822         /* Mask out any bits in operand[3] that are not needed.  */
1823            emit_insn (gen_andsi3 (op1, operands[3], op0));
1825         if (GET_CODE (op0) == CONST_INT
1826             && (const_ok_for_arm (mask << start_bit)
1827                 || const_ok_for_arm (~(mask << start_bit))))
1828           {
1829             op0 = GEN_INT (~(mask << start_bit));
1830             emit_insn (gen_andsi3 (op2, operands[0], op0));
1831           }
1832         else
1833           {
1834             if (GET_CODE (op0) == CONST_INT)
1835               {
1836                 rtx tmp = gen_reg_rtx (SImode);
1838                 emit_insn (gen_movsi (tmp, op0));
1839                 op0 = tmp;
1840               }
1842             if (start_bit != 0)
1843               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1844             
1845             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1846           }
1848         if (start_bit != 0)
1849           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1851         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1852       }
1854     if (subtarget != target)
1855       {
1856         /* If TARGET is still a SUBREG, then it must be wider than a word,
1857            so we must be careful only to set the subword we were asked to.  */
1858         if (GET_CODE (target) == SUBREG)
1859           emit_move_insn (target, subtarget);
1860         else
1861           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1862       }
1864     DONE;
1865   }"
1868 ; constants for op 2 will never be given to these patterns.
1869 (define_insn_and_split "*anddi_notdi_di"
1870   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1871         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1872                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1873   "TARGET_ARM"
1874   "#"
1875   "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1876   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1877    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1878   "
1879   {
1880     operands[3] = gen_highpart (SImode, operands[0]);
1881     operands[0] = gen_lowpart (SImode, operands[0]);
1882     operands[4] = gen_highpart (SImode, operands[1]);
1883     operands[1] = gen_lowpart (SImode, operands[1]);
1884     operands[5] = gen_highpart (SImode, operands[2]);
1885     operands[2] = gen_lowpart (SImode, operands[2]);
1886   }"
1887   [(set_attr "length" "8")
1888    (set_attr "predicable" "yes")]
1890   
1891 (define_insn_and_split "*anddi_notzesidi_di"
1892   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1893         (and:DI (not:DI (zero_extend:DI
1894                          (match_operand:SI 2 "s_register_operand" "r,r")))
1895                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1896   "TARGET_ARM"
1897   "@
1898    bic%?\\t%Q0, %Q1, %2
1899    #"
1900   ; (not (zero_extend ...)) allows us to just copy the high word from
1901   ; operand1 to operand0.
1902   "TARGET_ARM
1903    && reload_completed
1904    && operands[0] != operands[1]"
1905   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1906    (set (match_dup 3) (match_dup 4))]
1907   "
1908   {
1909     operands[3] = gen_highpart (SImode, operands[0]);
1910     operands[0] = gen_lowpart (SImode, operands[0]);
1911     operands[4] = gen_highpart (SImode, operands[1]);
1912     operands[1] = gen_lowpart (SImode, operands[1]);
1913   }"
1914   [(set_attr "length" "4,8")
1915    (set_attr "predicable" "yes")]
1917   
1918 (define_insn_and_split "*anddi_notsesidi_di"
1919   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1920         (and:DI (not:DI (sign_extend:DI
1921                          (match_operand:SI 2 "s_register_operand" "r,r")))
1922                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1923   "TARGET_ARM"
1924   "#"
1925   "TARGET_ARM && reload_completed"
1926   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1927    (set (match_dup 3) (and:SI (not:SI
1928                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
1929                                (match_dup 4)))]
1930   "
1931   {
1932     operands[3] = gen_highpart (SImode, operands[0]);
1933     operands[0] = gen_lowpart (SImode, operands[0]);
1934     operands[4] = gen_highpart (SImode, operands[1]);
1935     operands[1] = gen_lowpart (SImode, operands[1]);
1936   }"
1937   [(set_attr "length" "8")
1938    (set_attr "predicable" "yes")]
1940   
1941 (define_insn "andsi_notsi_si"
1942   [(set (match_operand:SI 0 "s_register_operand" "=r")
1943         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1944                 (match_operand:SI 1 "s_register_operand" "r")))]
1945   "TARGET_ARM"
1946   "bic%?\\t%0, %1, %2"
1947   [(set_attr "predicable" "yes")]
1950 (define_insn "bicsi3"
1951   [(set (match_operand:SI                 0 "register_operand" "=l")
1952         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1953                 (match_operand:SI         2 "register_operand" "0")))]
1954   "TARGET_THUMB"
1955   "bic\\t%0, %0, %1"
1956   [(set_attr "length" "2")]
1959 (define_insn "andsi_not_shiftsi_si"
1960   [(set (match_operand:SI                   0 "s_register_operand" "=r")
1961         (and:SI (not:SI (match_operator:SI  4 "shift_operator"
1962                          [(match_operand:SI 2 "s_register_operand"  "r")
1963                           (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
1964                 (match_operand:SI           1 "s_register_operand"  "r")))]
1965   "TARGET_ARM"
1966   "bic%?\\t%0, %1, %2%S4"
1967   [(set_attr "predicable" "yes")
1968    (set_attr "shift" "2")
1969    ]
1972 (define_insn "*andsi_notsi_si_compare0"
1973   [(set (reg:CC_NOOV CC_REGNUM)
1974         (compare:CC_NOOV
1975          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1976                  (match_operand:SI 1 "s_register_operand" "r"))
1977          (const_int 0)))
1978    (set (match_operand:SI 0 "s_register_operand" "=r")
1979         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1980   "TARGET_ARM"
1981   "bic%?s\\t%0, %1, %2"
1982   [(set_attr "conds" "set")]
1985 (define_insn "*andsi_notsi_si_compare0_scratch"
1986   [(set (reg:CC_NOOV CC_REGNUM)
1987         (compare:CC_NOOV
1988          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1989                  (match_operand:SI 1 "s_register_operand" "r"))
1990          (const_int 0)))
1991    (clobber (match_scratch:SI 0 "=r"))]
1992   "TARGET_ARM"
1993   "bic%?s\\t%0, %1, %2"
1994   [(set_attr "conds" "set")]
1997 (define_insn "iordi3"
1998   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1999         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2000                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2001   "TARGET_ARM && ! TARGET_IWMMXT"
2002   "#"
2003   [(set_attr "length" "8")
2004    (set_attr "predicable" "yes")]
2007 (define_insn "*iordi_zesidi_di"
2008   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2009         (ior:DI (zero_extend:DI
2010                  (match_operand:SI 2 "s_register_operand" "r,r"))
2011                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2012   "TARGET_ARM"
2013   "@
2014    orr%?\\t%Q0, %Q1, %2
2015    #"
2016   [(set_attr "length" "4,8")
2017    (set_attr "predicable" "yes")]
2020 (define_insn "*iordi_sesidi_di"
2021   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2022         (ior:DI (sign_extend:DI
2023                  (match_operand:SI 2 "s_register_operand" "r,r"))
2024                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2025   "TARGET_ARM"
2026   "#"
2027   [(set_attr "length" "8")
2028    (set_attr "predicable" "yes")]
2031 (define_expand "iorsi3"
2032   [(set (match_operand:SI         0 "s_register_operand" "")
2033         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2034                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2035   "TARGET_EITHER"
2036   "
2037   if (GET_CODE (operands[2]) == CONST_INT)
2038     {
2039       if (TARGET_ARM)
2040         {
2041           arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2042                               operands[1],
2043                               (no_new_pseudos
2044                               ? 0 : preserve_subexpressions_p ()));
2045           DONE;
2046         }
2047       else /* TARGET_THUMB */
2048         operands [2] = force_reg (SImode, operands [2]);
2049     }
2050   "
2053 (define_insn_and_split "*arm_iorsi3"
2054   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2055         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2056                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2057   "TARGET_ARM"
2058   "@
2059    orr%?\\t%0, %1, %2
2060    #"
2061   "TARGET_ARM
2062    && GET_CODE (operands[2]) == CONST_INT
2063    && !const_ok_for_arm (INTVAL (operands[2]))"
2064   [(clobber (const_int 0))]
2065   "
2066   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2067                       operands[1], 0);
2068   DONE;
2069   "
2070   [(set_attr "length" "4,16")
2071    (set_attr "predicable" "yes")]
2074 (define_insn "*thumb_iorsi3"
2075   [(set (match_operand:SI         0 "register_operand" "=l")
2076         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2077                 (match_operand:SI 2 "register_operand" "l")))]
2078   "TARGET_THUMB"
2079   "orr\\t%0, %0, %2"
2080   [(set_attr "length" "2")]
2083 (define_peephole2
2084   [(match_scratch:SI 3 "r")
2085    (set (match_operand:SI         0 "s_register_operand" "")
2086         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2087                 (match_operand:SI 2 "const_int_operand" "")))]
2088   "TARGET_ARM
2089    && !const_ok_for_arm (INTVAL (operands[2]))
2090    && const_ok_for_arm (~INTVAL (operands[2]))"
2091   [(set (match_dup 3) (match_dup 2))
2092    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2093   ""
2096 (define_insn "*iorsi3_compare0"
2097   [(set (reg:CC_NOOV CC_REGNUM)
2098         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2099                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2100                          (const_int 0)))
2101    (set (match_operand:SI 0 "s_register_operand" "=r")
2102         (ior:SI (match_dup 1) (match_dup 2)))]
2103   "TARGET_ARM"
2104   "orr%?s\\t%0, %1, %2"
2105   [(set_attr "conds" "set")]
2108 (define_insn "*iorsi3_compare0_scratch"
2109   [(set (reg:CC_NOOV CC_REGNUM)
2110         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2111                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2112                          (const_int 0)))
2113    (clobber (match_scratch:SI 0 "=r"))]
2114   "TARGET_ARM"
2115   "orr%?s\\t%0, %1, %2"
2116   [(set_attr "conds" "set")]
2119 (define_insn "xordi3"
2120   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2121         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2122                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2123   "TARGET_ARM && !TARGET_IWMMXT"
2124   "#"
2125   [(set_attr "length" "8")
2126    (set_attr "predicable" "yes")]
2129 (define_insn "*xordi_zesidi_di"
2130   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2131         (xor:DI (zero_extend:DI
2132                  (match_operand:SI 2 "s_register_operand" "r,r"))
2133                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2134   "TARGET_ARM"
2135   "@
2136    eor%?\\t%Q0, %Q1, %2
2137    #"
2138   [(set_attr "length" "4,8")
2139    (set_attr "predicable" "yes")]
2142 (define_insn "*xordi_sesidi_di"
2143   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2144         (xor:DI (sign_extend:DI
2145                  (match_operand:SI 2 "s_register_operand" "r,r"))
2146                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2147   "TARGET_ARM"
2148   "#"
2149   [(set_attr "length" "8")
2150    (set_attr "predicable" "yes")]
2153 (define_expand "xorsi3"
2154   [(set (match_operand:SI         0 "s_register_operand" "")
2155         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2156                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2157   "TARGET_EITHER"
2158   "if (TARGET_THUMB)
2159      if (GET_CODE (operands[2]) == CONST_INT)
2160        operands[2] = force_reg (SImode, operands[2]);
2161   "
2164 (define_insn "*arm_xorsi3"
2165   [(set (match_operand:SI         0 "s_register_operand" "=r")
2166         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2167                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2168   "TARGET_ARM"
2169   "eor%?\\t%0, %1, %2"
2170   [(set_attr "predicable" "yes")]
2173 (define_insn "*thumb_xorsi3"
2174   [(set (match_operand:SI         0 "register_operand" "=l")
2175         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2176                 (match_operand:SI 2 "register_operand" "l")))]
2177   "TARGET_THUMB"
2178   "eor\\t%0, %0, %2"
2179   [(set_attr "length" "2")]
2182 (define_insn "*xorsi3_compare0"
2183   [(set (reg:CC_NOOV CC_REGNUM)
2184         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2185                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2186                          (const_int 0)))
2187    (set (match_operand:SI 0 "s_register_operand" "=r")
2188         (xor:SI (match_dup 1) (match_dup 2)))]
2189   "TARGET_ARM"
2190   "eor%?s\\t%0, %1, %2"
2191   [(set_attr "conds" "set")]
2194 (define_insn "*xorsi3_compare0_scratch"
2195   [(set (reg:CC_NOOV CC_REGNUM)
2196         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2197                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2198                          (const_int 0)))]
2199   "TARGET_ARM"
2200   "teq%?\\t%0, %1"
2201   [(set_attr "conds" "set")]
2204 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2205 ; (NOT D) we can sometimes merge the final NOT into one of the following
2206 ; insns.
2208 (define_split
2209   [(set (match_operand:SI 0 "s_register_operand" "")
2210         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2211                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2212                 (match_operand:SI 3 "arm_rhs_operand" "")))
2213    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2214   "TARGET_ARM"
2215   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2216                               (not:SI (match_dup 3))))
2217    (set (match_dup 0) (not:SI (match_dup 4)))]
2218   ""
2221 (define_insn "*andsi_iorsi3_notsi"
2222   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2223         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2224                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2225                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2226   "TARGET_ARM"
2227   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2228   [(set_attr "length" "8")
2229    (set_attr "predicable" "yes")]
2234 ;; Minimum and maximum insns
2236 (define_insn "smaxsi3"
2237   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2238         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2239                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2240    (clobber (reg:CC CC_REGNUM))]
2241   "TARGET_ARM"
2242   "@
2243    cmp\\t%1, %2\;movlt\\t%0, %2
2244    cmp\\t%1, %2\;movge\\t%0, %1
2245    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2246   [(set_attr "conds" "clob")
2247    (set_attr "length" "8,8,12")]
2250 (define_insn "sminsi3"
2251   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2252         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2253                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2254    (clobber (reg:CC CC_REGNUM))]
2255   "TARGET_ARM"
2256   "@
2257    cmp\\t%1, %2\;movge\\t%0, %2
2258    cmp\\t%1, %2\;movlt\\t%0, %1
2259    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2260   [(set_attr "conds" "clob")
2261    (set_attr "length" "8,8,12")]
2264 (define_insn "umaxsi3"
2265   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2266         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2267                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2268    (clobber (reg:CC CC_REGNUM))]
2269   "TARGET_ARM"
2270   "@
2271    cmp\\t%1, %2\;movcc\\t%0, %2
2272    cmp\\t%1, %2\;movcs\\t%0, %1
2273    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2274   [(set_attr "conds" "clob")
2275    (set_attr "length" "8,8,12")]
2278 (define_insn "uminsi3"
2279   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2280         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2281                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2282    (clobber (reg:CC CC_REGNUM))]
2283   "TARGET_ARM"
2284   "@
2285    cmp\\t%1, %2\;movcs\\t%0, %2
2286    cmp\\t%1, %2\;movcc\\t%0, %1
2287    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2288   [(set_attr "conds" "clob")
2289    (set_attr "length" "8,8,12")]
2292 (define_insn "*store_minmaxsi"
2293   [(set (match_operand:SI 0 "memory_operand" "=m")
2294         (match_operator:SI 3 "minmax_operator"
2295          [(match_operand:SI 1 "s_register_operand" "r")
2296           (match_operand:SI 2 "s_register_operand" "r")]))
2297    (clobber (reg:CC CC_REGNUM))]
2298   "TARGET_ARM"
2299   "*
2300   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2301                          operands[2]);
2302   output_asm_insn (\"cmp\\t%1, %2\", operands);
2303   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2304   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2305   return \"\";
2306   "
2307   [(set_attr "conds" "clob")
2308    (set_attr "length" "12")
2309    (set_attr "type" "store1")]
2312 ; Reject the frame pointer in operand[1], since reloading this after
2313 ; it has been eliminated can cause carnage.
2314 (define_insn "*minmax_arithsi"
2315   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2316         (match_operator:SI 4 "shiftable_operator"
2317          [(match_operator:SI 5 "minmax_operator"
2318            [(match_operand:SI 2 "s_register_operand" "r,r")
2319             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2320           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2321    (clobber (reg:CC CC_REGNUM))]
2322   "TARGET_ARM
2323    && (GET_CODE (operands[1]) != REG
2324        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2325            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2326   "*
2327   {
2328     enum rtx_code code = GET_CODE (operands[4]);
2330     operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2331                            operands[3]);
2332     output_asm_insn (\"cmp\\t%2, %3\", operands);
2333     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2334     if (which_alternative != 0 || operands[3] != const0_rtx
2335         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2336       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2337     return \"\";
2338   }"
2339   [(set_attr "conds" "clob")
2340    (set_attr "length" "12")]
2344 ;; Shift and rotation insns
2346 (define_expand "ashlsi3"
2347   [(set (match_operand:SI            0 "s_register_operand" "")
2348         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2349                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2350   "TARGET_EITHER"
2351   "
2352   if (GET_CODE (operands[2]) == CONST_INT
2353       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2354     {
2355       emit_insn (gen_movsi (operands[0], const0_rtx));
2356       DONE;
2357     }
2358   "
2361 (define_insn "*thumb_ashlsi3"
2362   [(set (match_operand:SI            0 "register_operand" "=l,l")
2363         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2364                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2365   "TARGET_THUMB"
2366   "lsl\\t%0, %1, %2"
2367   [(set_attr "length" "2")]
2370 (define_expand "ashrsi3"
2371   [(set (match_operand:SI              0 "s_register_operand" "")
2372         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2373                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2374   "TARGET_EITHER"
2375   "
2376   if (GET_CODE (operands[2]) == CONST_INT
2377       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2378     operands[2] = GEN_INT (31);
2379   "
2382 (define_insn "*thumb_ashrsi3"
2383   [(set (match_operand:SI              0 "register_operand" "=l,l")
2384         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2385                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2386   "TARGET_THUMB"
2387   "asr\\t%0, %1, %2"
2388   [(set_attr "length" "2")]
2391 (define_expand "lshrsi3"
2392   [(set (match_operand:SI              0 "s_register_operand" "")
2393         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2394                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2395   "TARGET_EITHER"
2396   "
2397   if (GET_CODE (operands[2]) == CONST_INT
2398       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2399     {
2400       emit_insn (gen_movsi (operands[0], const0_rtx));
2401       DONE;
2402     }
2403   "
2406 (define_insn "*thumb_lshrsi3"
2407   [(set (match_operand:SI              0 "register_operand" "=l,l")
2408         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2409                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2410   "TARGET_THUMB"
2411   "lsr\\t%0, %1, %2"
2412   [(set_attr "length" "2")]
2415 (define_expand "rotlsi3"
2416   [(set (match_operand:SI              0 "s_register_operand" "")
2417         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2418                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2419   "TARGET_ARM"
2420   "
2421   if (GET_CODE (operands[2]) == CONST_INT)
2422     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2423   else
2424     {
2425       rtx reg = gen_reg_rtx (SImode);
2426       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2427       operands[2] = reg;
2428     }
2429   "
2432 (define_expand "rotrsi3"
2433   [(set (match_operand:SI              0 "s_register_operand" "")
2434         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2435                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2436   "TARGET_EITHER"
2437   "
2438   if (TARGET_ARM)
2439     {
2440       if (GET_CODE (operands[2]) == CONST_INT
2441           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2442         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2443     }
2444   else /* TARGET_THUMB */
2445     {
2446       if (GET_CODE (operands [2]) == CONST_INT)
2447         operands [2] = force_reg (SImode, operands[2]);
2448     }
2449   "
2452 (define_insn "*thumb_rotrsi3"
2453   [(set (match_operand:SI              0 "register_operand" "=l")
2454         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2455                      (match_operand:SI 2 "register_operand" "l")))]
2456   "TARGET_THUMB"
2457   "ror\\t%0, %0, %2"
2458   [(set_attr "length" "2")]
2461 (define_expand "ashldi3"
2462   [(set (match_operand:DI            0 "s_register_operand" "")
2463         (ashift:DI (match_operand:DI 1 "general_operand"    "")
2464                    (match_operand:SI 2 "general_operand"    "")))]
2465   "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)"
2466   "
2467   if (! s_register_operand (operands[1], DImode))
2468     operands[1] = copy_to_mode_reg (DImode, operands[1]);
2469   if (! s_register_operand (operands[2], SImode))
2470     operands[2] = copy_to_mode_reg (SImode, operands[2]);
2471   "
2474 (define_insn "*arm_shiftsi3"
2475   [(set (match_operand:SI   0 "s_register_operand" "=r")
2476         (match_operator:SI  3 "shift_operator"
2477          [(match_operand:SI 1 "s_register_operand"  "r")
2478           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2479   "TARGET_ARM"
2480   "mov%?\\t%0, %1%S3"
2481   [(set_attr "predicable" "yes")
2482    (set_attr "shift" "1")
2483    ]
2486 (define_insn "*shiftsi3_compare0"
2487   [(set (reg:CC_NOOV CC_REGNUM)
2488         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2489                           [(match_operand:SI 1 "s_register_operand" "r")
2490                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2491                          (const_int 0)))
2492    (set (match_operand:SI 0 "s_register_operand" "=r")
2493         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2494   "TARGET_ARM"
2495   "mov%?s\\t%0, %1%S3"
2496   [(set_attr "conds" "set")
2497    (set_attr "shift" "1")
2498    ]
2501 (define_insn "*shiftsi3_compare0_scratch"
2502   [(set (reg:CC_NOOV CC_REGNUM)
2503         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2504                           [(match_operand:SI 1 "s_register_operand" "r")
2505                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2506                          (const_int 0)))
2507    (clobber (match_scratch:SI 0 "=r"))]
2508   "TARGET_ARM"
2509   "mov%?s\\t%0, %1%S3"
2510   [(set_attr "conds" "set")
2511    (set_attr "shift" "1")
2512    ]
2515 (define_insn "*notsi_shiftsi"
2516   [(set (match_operand:SI 0 "s_register_operand" "=r")
2517         (not:SI (match_operator:SI 3 "shift_operator"
2518                  [(match_operand:SI 1 "s_register_operand" "r")
2519                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2520   "TARGET_ARM"
2521   "mvn%?\\t%0, %1%S3"
2522   [(set_attr "predicable" "yes")
2523    (set_attr "shift" "1")
2524    ]
2527 (define_insn "*notsi_shiftsi_compare0"
2528   [(set (reg:CC_NOOV CC_REGNUM)
2529         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2530                           [(match_operand:SI 1 "s_register_operand" "r")
2531                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2532                          (const_int 0)))
2533    (set (match_operand:SI 0 "s_register_operand" "=r")
2534         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2535   "TARGET_ARM"
2536   "mvn%?s\\t%0, %1%S3"
2537   [(set_attr "conds" "set")
2538    (set_attr "shift" "1")
2539    ]
2542 (define_insn "*not_shiftsi_compare0_scratch"
2543   [(set (reg:CC_NOOV CC_REGNUM)
2544         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2545                           [(match_operand:SI 1 "s_register_operand" "r")
2546                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2547                          (const_int 0)))
2548    (clobber (match_scratch:SI 0 "=r"))]
2549   "TARGET_ARM"
2550   "mvn%?s\\t%0, %1%S3"
2551   [(set_attr "conds" "set")
2552    (set_attr "shift" "1")
2553   ]
2556 ;; We don't really have extzv, but defining this using shifts helps
2557 ;; to reduce register pressure later on.
2559 (define_expand "extzv"
2560   [(set (match_dup 4)
2561         (ashift:SI (match_operand:SI   1 "register_operand" "")
2562                    (match_operand:SI   2 "const_int_operand" "")))
2563    (set (match_operand:SI              0 "register_operand" "")
2564         (lshiftrt:SI (match_dup 4)
2565                      (match_operand:SI 3 "const_int_operand" "")))]
2566   "TARGET_THUMB"
2567   "
2568   {
2569     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2570     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2571     
2572     operands[3] = GEN_INT (rshift);
2573     
2574     if (lshift == 0)
2575       {
2576         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2577         DONE;
2578       }
2579       
2580     operands[2] = GEN_INT (lshift);
2581     operands[4] = gen_reg_rtx (SImode);
2582   }"
2586 ;; Unary arithmetic insns
2588 (define_expand "negdi2"
2589  [(parallel
2590    [(set (match_operand:DI          0 "s_register_operand" "")
2591           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2592     (clobber (reg:CC CC_REGNUM))])]
2593   "TARGET_EITHER"
2594   "
2595   if (TARGET_THUMB)
2596     {
2597       if (GET_CODE (operands[1]) != REG)
2598         operands[1] = force_reg (SImode, operands[1]);
2599      }
2600   "
2603 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2604 ;; The second alternative is to allow the common case of a *full* overlap.
2605 (define_insn "*arm_negdi2"
2606   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2607         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2608    (clobber (reg:CC CC_REGNUM))]
2609   "TARGET_ARM"
2610   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2611   [(set_attr "conds" "clob")
2612    (set_attr "length" "8")]
2615 (define_insn "*thumb_negdi2"
2616   [(set (match_operand:DI         0 "register_operand" "=&l")
2617         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2618    (clobber (reg:CC CC_REGNUM))]
2619   "TARGET_THUMB"
2620   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2621   [(set_attr "length" "6")]
2624 (define_expand "negsi2"
2625   [(set (match_operand:SI         0 "s_register_operand" "")
2626         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2627   "TARGET_EITHER"
2628   ""
2631 (define_insn "*arm_negsi2"
2632   [(set (match_operand:SI         0 "s_register_operand" "=r")
2633         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2634   "TARGET_ARM"
2635   "rsb%?\\t%0, %1, #0"
2636   [(set_attr "predicable" "yes")]
2639 (define_insn "*thumb_negsi2"
2640   [(set (match_operand:SI         0 "register_operand" "=l")
2641         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2642   "TARGET_THUMB"
2643   "neg\\t%0, %1"
2644   [(set_attr "length" "2")]
2647 (define_expand "negsf2"
2648   [(set (match_operand:SF         0 "s_register_operand" "")
2649         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2650   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2651   ""
2654 (define_expand "negdf2"
2655   [(set (match_operand:DF         0 "s_register_operand" "")
2656         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2657   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2658   "")
2660 ;; abssi2 doesn't really clobber the condition codes if a different register
2661 ;; is being set.  To keep things simple, assume during rtl manipulations that
2662 ;; it does, but tell the final scan operator the truth.  Similarly for
2663 ;; (neg (abs...))
2665 (define_expand "abssi2"
2666   [(parallel
2667     [(set (match_operand:SI         0 "s_register_operand" "")
2668           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2669      (clobber (reg:CC CC_REGNUM))])]
2670   "TARGET_ARM"
2671   "")
2673 (define_insn "*arm_abssi2"
2674   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2675         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2676    (clobber (reg:CC CC_REGNUM))]
2677   "TARGET_ARM"
2678   "@
2679    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2680    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2681   [(set_attr "conds" "clob,*")
2682    (set_attr "shift" "1")
2683    ;; predicable can't be set based on the variant, so left as no
2684    (set_attr "length" "8")]
2687 (define_insn "*neg_abssi2"
2688   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2689         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2690    (clobber (reg:CC CC_REGNUM))]
2691   "TARGET_ARM"
2692   "@
2693    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2694    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2695   [(set_attr "conds" "clob,*")
2696    (set_attr "shift" "1")
2697    ;; predicable can't be set based on the variant, so left as no
2698    (set_attr "length" "8")]
2701 (define_expand "abssf2"
2702   [(set (match_operand:SF         0 "s_register_operand" "")
2703         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2704   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2705   "")
2707 (define_expand "absdf2"
2708   [(set (match_operand:DF         0 "s_register_operand" "")
2709         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2710   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2711   "")
2713 (define_expand "sqrtsf2"
2714   [(set (match_operand:SF 0 "s_register_operand" "")
2715         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2716   "TARGET_ARM && TARGET_HARD_FLOAT"
2717   "")
2719 (define_expand "sqrtdf2"
2720   [(set (match_operand:DF 0 "s_register_operand" "")
2721         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2722   "TARGET_ARM && TARGET_HARD_FLOAT"
2723   "")
2725 (define_insn_and_split "one_cmpldi2"
2726   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2727         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2728   "TARGET_ARM"
2729   "#"
2730   "TARGET_ARM && reload_completed"
2731   [(set (match_dup 0) (not:SI (match_dup 1)))
2732    (set (match_dup 2) (not:SI (match_dup 3)))]
2733   "
2734   {
2735     operands[2] = gen_highpart (SImode, operands[0]);
2736     operands[0] = gen_lowpart (SImode, operands[0]);
2737     operands[3] = gen_highpart (SImode, operands[1]);
2738     operands[1] = gen_lowpart (SImode, operands[1]);
2739   }"
2740   [(set_attr "length" "8")
2741    (set_attr "predicable" "yes")]
2744 (define_expand "one_cmplsi2"
2745   [(set (match_operand:SI         0 "s_register_operand" "")
2746         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2747   "TARGET_EITHER"
2748   ""
2751 (define_insn "*arm_one_cmplsi2"
2752   [(set (match_operand:SI         0 "s_register_operand" "=r")
2753         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2754   "TARGET_ARM"
2755   "mvn%?\\t%0, %1"
2756   [(set_attr "predicable" "yes")]
2759 (define_insn "*thumb_one_cmplsi2"
2760   [(set (match_operand:SI         0 "register_operand" "=l")
2761         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
2762   "TARGET_THUMB"
2763   "mvn\\t%0, %1"
2764   [(set_attr "length" "2")]
2767 (define_insn "*notsi_compare0"
2768   [(set (reg:CC_NOOV CC_REGNUM)
2769         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2770                          (const_int 0)))
2771    (set (match_operand:SI 0 "s_register_operand" "=r")
2772         (not:SI (match_dup 1)))]
2773   "TARGET_ARM"
2774   "mvn%?s\\t%0, %1"
2775   [(set_attr "conds" "set")]
2778 (define_insn "*notsi_compare0_scratch"
2779   [(set (reg:CC_NOOV CC_REGNUM)
2780         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2781                          (const_int 0)))
2782    (clobber (match_scratch:SI 0 "=r"))]
2783   "TARGET_ARM"
2784   "mvn%?s\\t%0, %1"
2785   [(set_attr "conds" "set")]
2788 ;; Fixed <--> Floating conversion insns
2790 (define_expand "floatsisf2"
2791   [(set (match_operand:SF           0 "s_register_operand" "")
2792         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2793   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2794   "
2795   if (TARGET_CIRRUS)
2796     {
2797       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2798       DONE;
2799     }
2802 (define_expand "floatsidf2"
2803   [(set (match_operand:DF           0 "s_register_operand" "")
2804         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2805   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2806   "
2807   if (TARGET_CIRRUS)
2808     {
2809       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
2810       DONE;
2811     }
2814 (define_expand "fix_truncsfsi2"
2815   [(set (match_operand:SI         0 "s_register_operand" "")
2816         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
2817   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2818   "
2819   if (TARGET_CIRRUS)
2820     {
2821       if (!cirrus_fp_register (operands[0], SImode))
2822         operands[0] = force_reg (SImode, operands[0]);
2823       if (!cirrus_fp_register (operands[1], SFmode))
2824         operands[1] = force_reg (SFmode, operands[0]);
2825       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
2826       DONE;
2827     }
2830 (define_expand "fix_truncdfsi2"
2831   [(set (match_operand:SI         0 "s_register_operand" "")
2832         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
2833   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2834   "
2835   if (TARGET_CIRRUS)
2836     {
2837       if (!cirrus_fp_register (operands[1], DFmode))
2838         operands[1] = force_reg (DFmode, operands[0]);
2839       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
2840       DONE;
2841     }
2844 ;; Truncation insns
2846 (define_expand "truncdfsf2"
2847   [(set (match_operand:SF  0 "s_register_operand" "")
2848         (float_truncate:SF
2849          (match_operand:DF 1 "s_register_operand" "")))]
2850   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2851   ""
2854 ;; Zero and sign extension instructions.
2856 (define_insn "zero_extendsidi2"
2857   [(set (match_operand:DI 0 "s_register_operand" "=r")
2858         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2859   "TARGET_ARM"
2860   "*
2861     if (REGNO (operands[1])
2862         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2863       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2864     return \"mov%?\\t%R0, #0\";
2865   "
2866   [(set_attr "length" "8")
2867    (set_attr "predicable" "yes")]
2870 (define_insn "zero_extendqidi2"
2871   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
2872         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2873   "TARGET_ARM"
2874   "@
2875    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2876    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2877   [(set_attr "length" "8")
2878    (set_attr "predicable" "yes")
2879    (set_attr "type" "*,load")
2880    (set_attr "pool_range" "*,4092")
2881    (set_attr "neg_pool_range" "*,4084")]
2884 (define_insn "extendsidi2"
2885   [(set (match_operand:DI 0 "s_register_operand" "=r")
2886         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2887   "TARGET_ARM"
2888   "*
2889     if (REGNO (operands[1])
2890         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2891       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2892     return \"mov%?\\t%R0, %Q0, asr #31\";
2893   "
2894   [(set_attr "length" "8")
2895    (set_attr "shift" "1")
2896    (set_attr "predicable" "yes")]
2899 (define_expand "zero_extendhisi2"
2900   [(set (match_dup 2)
2901         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2902                    (const_int 16)))
2903    (set (match_operand:SI 0 "s_register_operand" "")
2904         (lshiftrt:SI (match_dup 2) (const_int 16)))]
2905   "TARGET_EITHER"
2906   "
2907   {
2908     if (TARGET_ARM)
2909       {
2910         if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2911           {
2912            /* Note: We do not have to worry about TARGET_MMU_TRAPS
2913               here because the insn below will generate an LDRH instruction
2914               rather than an LDR instruction, so we cannot get an unaligned
2915               word access.  */
2916             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2917                                     gen_rtx_ZERO_EXTEND (SImode,
2918                                                          operands[1])));
2919             DONE;
2920           }
2921         if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2922           {
2923             emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2924             DONE;
2925           }
2926         if (!s_register_operand (operands[1], HImode))
2927           operands[1] = copy_to_mode_reg (HImode, operands[1]);
2928         operands[1] = gen_lowpart (SImode, operands[1]);
2929         operands[2] = gen_reg_rtx (SImode);
2930       }
2931     else /* TARGET_THUMB */
2932       {
2933         if (GET_CODE (operands[1]) == MEM)
2934           {
2935             rtx tmp;
2937             tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
2938             tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
2939             emit_insn (tmp);
2940           }
2941         else
2942           {
2943             rtx ops[3];
2944             
2945             if (!s_register_operand (operands[1], HImode))
2946               operands[1] = copy_to_mode_reg (HImode, operands[1]);
2947             operands[1] = gen_lowpart (SImode, operands[1]);
2948             operands[2] = gen_reg_rtx (SImode);
2949             
2950             ops[0] = operands[2];
2951             ops[1] = operands[1];
2952             ops[2] = GEN_INT (16);
2953             
2954             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2955                                     gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
2957             ops[0] = operands[0];
2958             ops[1] = operands[2];
2959             ops[2] = GEN_INT (16);
2961             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2962                                     gen_rtx_LSHIFTRT (SImode, ops[1],
2963                                                       ops[2])));
2964           }
2965         DONE; 
2966       }
2967   }"
2970 (define_insn "*thumb_zero_extendhisi2"
2971   [(set (match_operand:SI                 0 "register_operand" "=l")
2972         (zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
2973   "TARGET_THUMB"
2974   "*
2975   rtx mem = XEXP (operands[1], 0);
2977   if (GET_CODE (mem) == CONST)
2978     mem = XEXP (mem, 0);
2979     
2980   if (GET_CODE (mem) == LABEL_REF)
2981     return \"ldr\\t%0, %1\";
2982     
2983   if (GET_CODE (mem) == PLUS)
2984     {
2985       rtx a = XEXP (mem, 0);
2986       rtx b = XEXP (mem, 1);
2988       /* This can happen due to bugs in reload.  */
2989       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
2990         {
2991           rtx ops[2];
2992           ops[0] = operands[0];
2993           ops[1] = a;
2994       
2995           output_asm_insn (\"mov        %0, %1\", ops);
2997           XEXP (mem, 0) = operands[0];
2998        }
3000       else if (   GET_CODE (a) == LABEL_REF
3001                && GET_CODE (b) == CONST_INT)
3002         return \"ldr\\t%0, %1\";
3003     }
3004     
3005   return \"ldrh\\t%0, %1\";
3006   "
3007   [(set_attr "length" "4")
3008    (set_attr "type" "load")
3009    (set_attr "pool_range" "60")]
3012 (define_insn "*arm_zero_extendhisi2"
3013   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3014         (zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3015   "TARGET_ARM && arm_arch4"
3016   "ldr%?h\\t%0, %1"
3017   [(set_attr "type" "load")
3018    (set_attr "predicable" "yes")
3019    (set_attr "pool_range" "256")
3020    (set_attr "neg_pool_range" "244")]
3023 (define_split
3024   [(set (match_operand:SI 0 "s_register_operand" "")
3025         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3026    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3027   "TARGET_ARM && (!arm_arch4)"
3028   [(set (match_dup 2) (match_dup 1))
3029    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3030   "
3031   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3032     FAIL;
3033   "
3036 (define_split
3037   [(set (match_operand:SI 0 "s_register_operand" "")
3038         (match_operator:SI 3 "shiftable_operator"
3039          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3040           (match_operand:SI 4 "s_register_operand" "")]))
3041    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3042   "TARGET_ARM && (!arm_arch4)"
3043   [(set (match_dup 2) (match_dup 1))
3044    (set (match_dup 0)
3045         (match_op_dup 3
3046          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3047   "
3048   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3049     FAIL;
3050   "
3053 (define_expand "zero_extendqisi2"
3054   [(set (match_operand:SI 0 "s_register_operand" "")
3055         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3056   "TARGET_EITHER"
3057   "
3058   if (GET_CODE (operands[1]) != MEM)
3059     {
3060       if (TARGET_ARM)
3061         {
3062           emit_insn (gen_andsi3 (operands[0],
3063                                  gen_lowpart (SImode, operands[1]),
3064                                  GEN_INT (255)));
3065         }
3066       else /* TARGET_THUMB */
3067         {
3068           rtx temp = gen_reg_rtx (SImode);
3069           rtx ops[3];
3070           
3071           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3072           operands[1] = gen_lowpart (SImode, operands[1]);
3074           ops[0] = temp;
3075           ops[1] = operands[1];
3076           ops[2] = GEN_INT (24);
3078           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3079                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3080           
3081           ops[0] = operands[0];
3082           ops[1] = temp;
3083           ops[2] = GEN_INT (24);
3085           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3086                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3087         }
3088       DONE;
3089     }
3090   "
3093 (define_insn "*thumb_zero_extendqisi2"
3094   [(set (match_operand:SI                 0 "register_operand" "=l")
3095         (zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3096   "TARGET_THUMB"
3097   "ldrb\\t%0, %1"
3098   [(set_attr "length" "2")
3099    (set_attr "type" "load")
3100    (set_attr "pool_range" "32")]
3103 (define_insn "*arm_zero_extendqisi2"
3104   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3105         (zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3106   "TARGET_ARM"
3107   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3108   [(set_attr "type" "load")
3109    (set_attr "predicable" "yes")
3110    (set_attr "pool_range" "4096")
3111    (set_attr "neg_pool_range" "4084")]
3114 (define_split
3115   [(set (match_operand:SI 0 "s_register_operand" "")
3116         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3117    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3118   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3119   [(set (match_dup 2) (match_dup 1))
3120    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3121   ""
3124 (define_insn "*compareqi_eq0"
3125   [(set (reg:CC_Z CC_REGNUM)
3126         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3127                          (const_int 0)))]
3128   "TARGET_ARM"
3129   "tst\\t%0, #255"
3130   [(set_attr "conds" "set")]
3133 (define_expand "extendhisi2"
3134   [(set (match_dup 2)
3135         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3136                    (const_int 16)))
3137    (set (match_operand:SI 0 "s_register_operand" "")
3138         (ashiftrt:SI (match_dup 2)
3139                      (const_int 16)))]
3140   "TARGET_EITHER"
3141   "
3142   {
3143     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3144       {
3145        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3146           here because the insn below will generate an LDRH instruction
3147           rather than an LDR instruction, so we cannot get an unaligned
3148           word access.  */
3149         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3150                    gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3151         DONE;
3152       }
3154     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3155       {
3156         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3157         DONE;
3158       }
3159     if (!s_register_operand (operands[1], HImode))
3160       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3161     operands[1] = gen_lowpart (SImode, operands[1]);
3162     operands[2] = gen_reg_rtx (SImode);
3164     if (TARGET_THUMB)
3165       {
3166         rtx ops[3];
3167         
3168         ops[0] = operands[2];
3169         ops[1] = operands[1];
3170         ops[2] = GEN_INT (16);
3171         
3172         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3173                                 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3174             
3175         ops[0] = operands[0];
3176         ops[1] = operands[2];
3177         ops[2] = GEN_INT (16);
3178         
3179         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3180                                 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3181         
3182         DONE;
3183       }
3184   }"
3187 (define_insn "*thumb_extendhisi2_insn"
3188   [(set (match_operand:SI                 0 "register_operand" "=l")
3189         (sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3190    (clobber (match_scratch:SI             2                   "=&l"))]
3191   "TARGET_THUMB"
3192   "*
3193   {
3194     rtx ops[4];
3195     rtx mem = XEXP (operands[1], 0);
3197     /* This code used to try to use 'V', and fix the address only if it was
3198        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3199        range of QImode offsets, and offsettable_address_p does a QImode
3200        address check.  */
3201        
3202     if (GET_CODE (mem) == CONST)
3203       mem = XEXP (mem, 0);
3204     
3205     if (GET_CODE (mem) == LABEL_REF)
3206       return \"ldr\\t%0, %1\";
3207     
3208     if (GET_CODE (mem) == PLUS)
3209       {
3210         rtx a = XEXP (mem, 0);
3211         rtx b = XEXP (mem, 1);
3213         if (GET_CODE (a) == LABEL_REF
3214             && GET_CODE (b) == CONST_INT)
3215           return \"ldr\\t%0, %1\";
3217         if (GET_CODE (b) == REG)
3218           return \"ldrsh\\t%0, %1\";
3219           
3220         ops[1] = a;
3221         ops[2] = b;
3222       }
3223     else
3224       {
3225         ops[1] = mem;
3226         ops[2] = const0_rtx;
3227       }
3228       
3229     if (GET_CODE (ops[1]) != REG)
3230       {
3231         debug_rtx (ops[1]);
3232         abort ();
3233       }
3235     ops[0] = operands[0];
3236     ops[3] = operands[2];
3237     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3238     return \"\";
3239   }"
3240   [(set_attr "length" "4")
3241    (set_attr "type" "load")
3242    (set_attr "pool_range" "1020")]
3245 (define_expand "extendhisi2_mem"
3246   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3247    (set (match_dup 3)
3248         (zero_extend:SI (match_dup 7)))
3249    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3250    (set (match_operand:SI 0 "" "")
3251         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3252   "TARGET_ARM"
3253   "
3254   {
3255     rtx mem1, mem2;
3256     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3258     mem1 = gen_rtx_MEM (QImode, addr);
3259     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3260     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3261     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3262     operands[0] = gen_lowpart (SImode, operands[0]);
3263     operands[1] = mem1;
3264     operands[2] = gen_reg_rtx (SImode);
3265     operands[3] = gen_reg_rtx (SImode);
3266     operands[6] = gen_reg_rtx (SImode);
3267     operands[7] = mem2;
3269     if (BYTES_BIG_ENDIAN)
3270       {
3271         operands[4] = operands[2];
3272         operands[5] = operands[3];
3273       }
3274     else
3275       {
3276         operands[4] = operands[3];
3277         operands[5] = operands[2];
3278       }
3279   }"
3282 (define_insn "*arm_extendhisi_insn"
3283   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3284         (sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3285   "TARGET_ARM && arm_arch4"
3286   "ldr%?sh\\t%0, %1"
3287   [(set_attr "type" "load")
3288    (set_attr "predicable" "yes")
3289    (set_attr "pool_range" "256")
3290    (set_attr "neg_pool_range" "244")]
3293 (define_split
3294   [(set (match_operand:SI                 0 "s_register_operand" "")
3295         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3296    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3297   "TARGET_ARM && (!arm_arch4)"
3298   [(set (match_dup 2) (match_dup 1))
3299    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3300   "
3301   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3302     FAIL;
3303   "
3306 (define_split
3307   [(set (match_operand:SI                   0 "s_register_operand" "")
3308         (match_operator:SI                  3 "shiftable_operator"
3309          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3310           (match_operand:SI                 4 "s_register_operand" "")]))
3311    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3312   "TARGET_ARM && (!arm_arch4)"
3313   [(set (match_dup 2) (match_dup 1))
3314    (set (match_dup 0)
3315         (match_op_dup 3
3316          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3317   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3318      FAIL;
3319   "
3322 (define_expand "extendqihi2"
3323   [(set (match_dup 2)
3324         (ashift:SI (match_operand:QI 1 "general_operand" "")
3325                    (const_int 24)))
3326    (set (match_operand:HI 0 "s_register_operand" "")
3327         (ashiftrt:SI (match_dup 2)
3328                      (const_int 24)))]
3329   "TARGET_ARM"
3330   "
3331   {
3332     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3333       {
3334         emit_insn (gen_rtx_SET (VOIDmode,
3335                                 operands[0],
3336                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3337         DONE;
3338       }
3339     if (!s_register_operand (operands[1], QImode))
3340       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3341     operands[0] = gen_lowpart (SImode, operands[0]);
3342     operands[1] = gen_lowpart (SImode, operands[1]);
3343     operands[2] = gen_reg_rtx (SImode);
3344   }"
3347 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3348 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3349 (define_insn "*extendqihi_insn"
3350   [(set (match_operand:HI                 0 "s_register_operand" "=r")
3351         (sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3352   "TARGET_ARM && arm_arch4"
3353   "*
3354   /* If the address is invalid, this will split the instruction into two. */
3355   if (bad_signed_byte_operand (operands[1], VOIDmode))
3356     return \"#\";
3357   return \"ldr%?sb\\t%0, %1\";
3358   "
3359   [(set_attr "type" "load")
3360    (set_attr "predicable" "yes")
3361    (set_attr "length" "8")
3362    (set_attr "pool_range" "256")
3363    (set_attr "neg_pool_range" "244")]
3366 (define_split
3367   [(set (match_operand:HI 0 "s_register_operand" "")
3368         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3369   "TARGET_ARM && arm_arch4 && reload_completed"
3370   [(set (match_dup 3) (match_dup 1))
3371    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3372   "
3373   {
3374     HOST_WIDE_INT offset;
3376     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3377     operands[2] = gen_rtx_MEM (QImode, operands[3]);
3378     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3379     operands[1] = XEXP (operands[1], 0);
3380     if (GET_CODE (operands[1]) == PLUS
3381         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3382         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3383              || const_ok_for_arm (-offset)))
3384       {
3385         HOST_WIDE_INT low = (offset > 0
3386                              ? (offset & 0xff) : -((-offset) & 0xff));
3387         XEXP (operands[2], 0) = plus_constant (operands[3], low);
3388         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3389       }
3390     /* Ensure the sum is in correct canonical form */
3391     else if (GET_CODE (operands[1]) == PLUS
3392              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3393              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3394       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3395                                            XEXP (operands[1], 1),
3396                                            XEXP (operands[1], 0));
3397   }"
3400 (define_expand "extendqisi2"
3401   [(set (match_dup 2)
3402         (ashift:SI (match_operand:QI 1 "general_operand" "")
3403                    (const_int 24)))
3404    (set (match_operand:SI 0 "s_register_operand" "")
3405         (ashiftrt:SI (match_dup 2)
3406                      (const_int 24)))]
3407   "TARGET_EITHER"
3408   "
3409   {
3410     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3411       {
3412         emit_insn (gen_rtx_SET (VOIDmode,
3413                                 operands[0],
3414                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3415         DONE;
3416       }
3417     if (!s_register_operand (operands[1], QImode))
3418       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3419     operands[1] = gen_lowpart (SImode, operands[1]);
3420     operands[2] = gen_reg_rtx (SImode);
3421     
3422     if (TARGET_THUMB)
3423       {
3424         rtx ops[3];
3425         
3426         ops[0] = operands[2];
3427         ops[1] = operands[1];
3428         ops[2] = GEN_INT (24);
3429         
3430         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3431                    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3433         ops[0] = operands[0];
3434         ops[1] = operands[2];
3435         ops[2] = GEN_INT (24);
3436         
3437         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3438                    gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3439         
3440         DONE;
3441       }
3442   }"
3445 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3446 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3447 (define_insn "*arm_extendqisi_insn"
3448   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3449         (sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3450   "TARGET_ARM && arm_arch4"
3451   "*
3452   /* If the address is invalid, this will split the instruction into two. */
3453   if (bad_signed_byte_operand (operands[1], VOIDmode))
3454     return \"#\";
3455   return \"ldr%?sb\\t%0, %1\";
3456   "
3457   [(set_attr "type" "load")
3458    (set_attr "predicable" "yes")
3459    (set_attr "length" "8")
3460    (set_attr "pool_range" "256")
3461    (set_attr "neg_pool_range" "244")]
3464 (define_split
3465   [(set (match_operand:SI 0 "s_register_operand" "")
3466         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3467   "TARGET_ARM && arm_arch4 && reload_completed"
3468   [(set (match_dup 0) (match_dup 1))
3469    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3470   "
3471   {
3472     HOST_WIDE_INT offset;
3474     operands[2] = gen_rtx_MEM (QImode, operands[0]);
3475     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3476     operands[1] = XEXP (operands[1], 0);
3477     if (GET_CODE (operands[1]) == PLUS
3478         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3479         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3480              || const_ok_for_arm (-offset)))
3481       {
3482         HOST_WIDE_INT low = (offset > 0
3483                              ? (offset & 0xff) : -((-offset) & 0xff));
3484         XEXP (operands[2], 0) = plus_constant (operands[0], low);
3485         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3486       }
3487     /* Ensure the sum is in correct canonical form */
3488     else if (GET_CODE (operands[1]) == PLUS
3489              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3490              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3491       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3492                                            XEXP (operands[1], 1),
3493                                            XEXP (operands[1], 0));
3494   }"
3497 (define_insn "*thumb_extendqisi2_insn"
3498   [(set (match_operand:SI                 0 "register_operand" "=l,l")
3499         (sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3500   "TARGET_THUMB"
3501   "*
3502   {
3503     rtx ops[3];
3504     rtx mem = XEXP (operands[1], 0);
3505     
3506     if (GET_CODE (mem) == CONST)
3507       mem = XEXP (mem, 0);
3508     
3509     if (GET_CODE (mem) == LABEL_REF)
3510       return \"ldr\\t%0, %1\";
3512     if (GET_CODE (mem) == PLUS
3513         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3514       return \"ldr\\t%0, %1\";
3515       
3516     if (which_alternative == 0)
3517       return \"ldrsb\\t%0, %1\";
3518       
3519     ops[0] = operands[0];
3520     
3521     if (GET_CODE (mem) == PLUS)
3522       {
3523         rtx a = XEXP (mem, 0);
3524         rtx b = XEXP (mem, 1);
3525         
3526         ops[1] = a;
3527         ops[2] = b;
3529         if (GET_CODE (a) == REG)
3530           {
3531             if (GET_CODE (b) == REG)
3532               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3533             else if (REGNO (a) == REGNO (ops[0]))
3534               {
3535                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3536                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3537                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3538               }
3539             else
3540               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3541           }
3542         else if (GET_CODE (b) != REG)
3543           abort ();
3544         else
3545           {
3546             if (REGNO (b) == REGNO (ops[0]))
3547               {
3548                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3549                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3550                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3551               }
3552             else
3553               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3554           }
3555       }
3556     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3557       {
3558         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3559         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3560         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3561       }
3562     else
3563       {
3564         ops[1] = mem;
3565         ops[2] = const0_rtx;
3566         
3567         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3568       }
3569     return \"\";
3570   }"
3571   [(set_attr "length" "2,6")
3572    (set_attr "type" "load,load")
3573    (set_attr "pool_range" "32,32")]
3576 (define_expand "extendsfdf2"
3577   [(set (match_operand:DF                  0 "s_register_operand" "")
3578         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
3579   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3580   ""
3583 ;; Move insns (including loads and stores)
3585 ;; XXX Just some ideas about movti.
3586 ;; I don't think these are a good idea on the arm, there just aren't enough
3587 ;; registers
3588 ;;(define_expand "loadti"
3589 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3590 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3591 ;;  "" "")
3593 ;;(define_expand "storeti"
3594 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3595 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3596 ;;  "" "")
3598 ;;(define_expand "movti"
3599 ;;  [(set (match_operand:TI 0 "general_operand" "")
3600 ;;      (match_operand:TI 1 "general_operand" ""))]
3601 ;;  ""
3602 ;;  "
3604 ;;  rtx insn;
3606 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3607 ;;    operands[1] = copy_to_reg (operands[1]);
3608 ;;  if (GET_CODE (operands[0]) == MEM)
3609 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3610 ;;  else if (GET_CODE (operands[1]) == MEM)
3611 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3612 ;;  else
3613 ;;    FAIL;
3615 ;;  emit_insn (insn);
3616 ;;  DONE;
3617 ;;}")
3619 ;; Recognize garbage generated above.
3621 ;;(define_insn ""
3622 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3623 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3624 ;;  ""
3625 ;;  "*
3626 ;;  {
3627 ;;    register mem = (which_alternative < 3);
3628 ;;    register const char *template;
3630 ;;    operands[mem] = XEXP (operands[mem], 0);
3631 ;;    switch (which_alternative)
3632 ;;      {
3633 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3634 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3635 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3636 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3637 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3638 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3639 ;;      }
3640 ;;    output_asm_insn (template, operands);
3641 ;;    return \"\";
3642 ;;  }")
3644 (define_expand "movdi"
3645   [(set (match_operand:DI 0 "general_operand" "")
3646         (match_operand:DI 1 "general_operand" ""))]
3647   "TARGET_EITHER"
3648   "
3649   if (TARGET_THUMB)
3650     {
3651       if (!no_new_pseudos)
3652         {
3653           if (GET_CODE (operands[0]) != REG)
3654             operands[1] = force_reg (DImode, operands[1]);
3655         }
3656     }
3657   "
3660 (define_insn "*arm_movdi"
3661   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3662         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3663   "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT"
3664   "*
3665   return (output_move_double (operands));
3666   "
3667   [(set_attr "length" "8")
3668    (set_attr "type" "*,load,store2")
3669    (set_attr "pool_range" "*,1020,*")
3670    (set_attr "neg_pool_range" "*,1008,*")]
3673 ;;; ??? This should have alternatives for constants.
3674 ;;; ??? This was originally identical to the movdf_insn pattern.
3675 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3676 ;;; thumb_reorg with a memory reference.
3677 (define_insn "*thumb_movdi_insn"
3678   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3679         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3680   "TARGET_THUMB
3681    && !TARGET_CIRRUS
3682    && (   register_operand (operands[0], DImode)
3683        || register_operand (operands[1], DImode))"
3684   "*
3685   {
3686   switch (which_alternative)
3687     {
3688     default:
3689     case 0:
3690       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3691         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3692       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3693     case 1:
3694       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3695     case 2:
3696       operands[1] = GEN_INT (- INTVAL (operands[1]));
3697       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3698     case 3:
3699       return \"ldmia\\t%1, {%0, %H0}\";
3700     case 4:
3701       return \"stmia\\t%0, {%1, %H1}\";
3702     case 5:
3703       return thumb_load_double_from_address (operands);
3704     case 6:
3705       operands[2] = gen_rtx (MEM, SImode,
3706                              plus_constant (XEXP (operands[0], 0), 4));
3707       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3708       return \"\";
3709     case 7:
3710       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3711         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3712       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3713     }
3714   }"
3715   [(set_attr "length" "4,4,6,2,2,6,4,4")
3716    (set_attr "type" "*,*,*,load,store2,load,store2,*")
3717    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3720 (define_expand "movsi"
3721   [(set (match_operand:SI 0 "general_operand" "")
3722         (match_operand:SI 1 "general_operand" ""))]
3723   "TARGET_EITHER"
3724   "
3725   if (TARGET_ARM)
3726     {
3727       /* Everything except mem = const or mem = mem can be done easily */
3728       if (GET_CODE (operands[0]) == MEM)
3729         operands[1] = force_reg (SImode, operands[1]);
3730       if (GET_CODE (operands[1]) == CONST_INT
3731           && !(const_ok_for_arm (INTVAL (operands[1]))
3732                || const_ok_for_arm (~INTVAL (operands[1]))))
3733         {
3734            arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3735                               NULL_RTX,
3736                               (no_new_pseudos ? 0
3737                                : preserve_subexpressions_p ()));
3738           DONE;
3739         }
3740     }
3741   else /* TARGET_THUMB.... */
3742     {
3743       if (!no_new_pseudos)
3744         {
3745           if (GET_CODE (operands[0]) != REG)
3746             operands[1] = force_reg (SImode, operands[1]);
3747         }
3748     }
3749     
3750   if (flag_pic
3751       && (CONSTANT_P (operands[1])
3752          || symbol_mentioned_p (operands[1])
3753          || label_mentioned_p (operands[1])))
3754     operands[1] = legitimize_pic_address (operands[1], SImode,
3755                                           (no_new_pseudos ? operands[0] : 0));
3756   "
3759 (define_insn "*arm_movsi_insn"
3760   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3761         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
3762   "TARGET_ARM && ! TARGET_IWMMXT
3763    && (   register_operand (operands[0], SImode)
3764        || register_operand (operands[1], SImode))"
3765   "@
3766    mov%?\\t%0, %1
3767    mvn%?\\t%0, #%B1
3768    ldr%?\\t%0, %1
3769    str%?\\t%1, %0"
3770   [(set_attr "type" "*,*,load,store1")
3771    (set_attr "predicable" "yes")
3772    (set_attr "pool_range" "*,*,4096,*")
3773    (set_attr "neg_pool_range" "*,*,4084,*")]
3776 (define_split
3777   [(set (match_operand:SI 0 "s_register_operand" "")
3778         (match_operand:SI 1 "const_int_operand" ""))]
3779   "TARGET_ARM
3780   && (!(const_ok_for_arm (INTVAL (operands[1]))
3781         || const_ok_for_arm (~INTVAL (operands[1]))))"
3782   [(clobber (const_int 0))]
3783   "
3784   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3785                       NULL_RTX, 0);
3786   DONE;
3787   "
3790 (define_insn "*thumb_movsi_insn"
3791   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3792         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
3793   "TARGET_THUMB
3794    && (   register_operand (operands[0], SImode) 
3795        || register_operand (operands[1], SImode))"
3796   "@
3797    mov  %0, %1
3798    mov  %0, %1
3799    #
3800    #
3801    ldmia\\t%1, {%0}
3802    stmia\\t%0, {%1}
3803    ldr\\t%0, %1
3804    str\\t%1, %0
3805    mov\\t%0, %1"
3806   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3807    (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3808    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3811 (define_split 
3812   [(set (match_operand:SI 0 "register_operand" "")
3813         (match_operand:SI 1 "const_int_operand" ""))]
3814   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3815   [(set (match_dup 0) (match_dup 1))
3816    (set (match_dup 0) (neg:SI (match_dup 0)))]
3817   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3820 (define_split 
3821   [(set (match_operand:SI 0 "register_operand" "")
3822         (match_operand:SI 1 "const_int_operand" ""))]
3823   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3824   [(set (match_dup 0) (match_dup 1))
3825    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3826   "
3827   {
3828     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3829     unsigned HOST_WIDE_INT mask = 0xff;
3830     int i;
3831     
3832     for (i = 0; i < 25; i++)
3833       if ((val & (mask << i)) == val)
3834         break;
3836     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
3837     if (i == 0)
3838       FAIL;
3840     operands[1] = GEN_INT (val >> i);
3841     operands[2] = GEN_INT (i);
3842   }"
3845 ;; When generating pic, we need to load the symbol offset into a register.
3846 ;; So that the optimizer does not confuse this with a normal symbol load
3847 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
3848 ;; since that is the only type of relocation we can use.
3850 ;; The rather odd constraints on the following are to force reload to leave
3851 ;; the insn alone, and to force the minipool generation pass to then move
3852 ;; the GOT symbol to memory.
3854 (define_insn "pic_load_addr_arm"
3855   [(set (match_operand:SI 0 "s_register_operand" "=r")
3856         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3857   "TARGET_ARM && flag_pic"
3858   "ldr%?\\t%0, %1"
3859   [(set_attr "type" "load")
3860    (set (attr "pool_range")     (const_int 4096))
3861    (set (attr "neg_pool_range") (const_int 4084))]
3864 (define_insn "pic_load_addr_thumb"
3865   [(set (match_operand:SI 0 "s_register_operand" "=l")
3866         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3867   "TARGET_THUMB && flag_pic"
3868   "ldr\\t%0, %1"
3869   [(set_attr "type" "load")
3870    (set (attr "pool_range") (const_int 1024))]
3873 ;; This variant is used for AOF assembly, since it needs to mention the
3874 ;; pic register in the rtl.
3875 (define_expand "pic_load_addr_based"
3876   [(set (match_operand:SI 0 "s_register_operand" "")
3877         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
3878   "TARGET_ARM && flag_pic"
3879   "operands[2] = pic_offset_table_rtx;"
3882 (define_insn "*pic_load_addr_based_insn"
3883   [(set (match_operand:SI 0 "s_register_operand" "=r")
3884         (unspec:SI [(match_operand 1 "" "")
3885                     (match_operand 2 "s_register_operand" "r")]
3886                    UNSPEC_PIC_SYM))]
3887   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
3888   "*
3889 #ifdef AOF_ASSEMBLER
3890   operands[1] = aof_pic_entry (operands[1]);
3891 #endif
3892   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3893   return \"\";
3894   "
3895   [(set_attr "type" "load")
3896    (set (attr "pool_range")
3897         (if_then_else (eq_attr "is_thumb" "yes")
3898                       (const_int 1024)
3899                       (const_int 4096)))
3900    (set (attr "neg_pool_range")
3901         (if_then_else (eq_attr "is_thumb" "yes")
3902                       (const_int 0)
3903                       (const_int 4084)))]
3906 (define_insn "pic_add_dot_plus_four"
3907   [(set (match_operand:SI 0 "register_operand" "+r")
3908         (unspec:SI [(plus:SI (match_dup 0)
3909                              (const (plus:SI (pc) (const_int 4))))]
3910                    UNSPEC_PIC_BASE))
3911    (use (label_ref (match_operand 1 "" "")))]
3912   "TARGET_THUMB && flag_pic"
3913   "*
3914   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3915                              CODE_LABEL_NUMBER (operands[1]));
3916   return \"add\\t%0, %|pc\";
3917   "
3918   [(set_attr "length" "2")]
3921 (define_insn "pic_add_dot_plus_eight"
3922   [(set (match_operand:SI 0 "register_operand" "+r")
3923         (unspec:SI [(plus:SI (match_dup 0)
3924                              (const (plus:SI (pc) (const_int 8))))]
3925                    UNSPEC_PIC_BASE))
3926    (use (label_ref (match_operand 1 "" "")))]
3927   "TARGET_ARM && flag_pic"
3928   "*
3929     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3930                                CODE_LABEL_NUMBER (operands[1]));
3931     return \"add%?\\t%0, %|pc, %0\";
3932   "
3933   [(set_attr "predicable" "yes")]
3936 (define_expand "builtin_setjmp_receiver"
3937   [(label_ref (match_operand 0 "" ""))]
3938   "flag_pic"
3939   "
3941   arm_finalize_pic (0);
3942   DONE;
3945 ;; If copying one reg to another we can set the condition codes according to
3946 ;; its value.  Such a move is common after a return from subroutine and the
3947 ;; result is being tested against zero.
3949 (define_insn "*movsi_compare0"
3950   [(set (reg:CC CC_REGNUM)
3951         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
3952                     (const_int 0)))
3953    (set (match_operand:SI 0 "s_register_operand" "=r,r")
3954         (match_dup 1))]
3955   "TARGET_ARM"
3956   "@
3957    cmp%?\\t%0, #0
3958    sub%?s\\t%0, %1, #0"
3959   [(set_attr "conds" "set")]
3962 ;; Subroutine to store a half word from a register into memory.
3963 ;; Operand 0 is the source register (HImode)
3964 ;; Operand 1 is the destination address in a register (SImode)
3966 ;; In both this routine and the next, we must be careful not to spill
3967 ;; a memory address of reg+large_const into a separate PLUS insn, since this
3968 ;; can generate unrecognizable rtl.
3970 (define_expand "storehi"
3971   [;; store the low byte
3972    (set (match_operand 1 "" "") (match_dup 3))
3973    ;; extract the high byte
3974    (set (match_dup 2)
3975         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3976    ;; store the high byte
3977    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
3978   "TARGET_ARM"
3979   "
3980   {
3981     rtx op1 = operands[1];
3982     rtx addr = XEXP (op1, 0);
3983     enum rtx_code code = GET_CODE (addr);
3985     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3986         || code == MINUS)
3987       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
3989     operands[4] = adjust_address (op1, QImode, 1);
3990     operands[1] = adjust_address (operands[1], QImode, 0);
3991     operands[3] = gen_lowpart (QImode, operands[0]);
3992     operands[0] = gen_lowpart (SImode, operands[0]);
3993     operands[2] = gen_reg_rtx (SImode); 
3994   }"
3997 (define_expand "storehi_bigend"
3998   [(set (match_dup 4) (match_dup 3))
3999    (set (match_dup 2)
4000         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4001    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4002   "TARGET_ARM"
4003   "
4004   {
4005     rtx op1 = operands[1];
4006     rtx addr = XEXP (op1, 0);
4007     enum rtx_code code = GET_CODE (addr);
4009     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4010         || code == MINUS)
4011       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4013     operands[4] = adjust_address (op1, QImode, 1);
4014     operands[1] = adjust_address (operands[1], QImode, 0);
4015     operands[3] = gen_lowpart (QImode, operands[0]);
4016     operands[0] = gen_lowpart (SImode, operands[0]);
4017     operands[2] = gen_reg_rtx (SImode);
4018   }"
4021 ;; Subroutine to store a half word integer constant into memory.
4022 (define_expand "storeinthi"
4023   [(set (match_operand 0 "" "")
4024         (subreg:QI (match_operand 1 "" "") 0))
4025    (set (match_dup 3) (match_dup 2))]
4026   "TARGET_ARM"
4027   "
4028   {
4029     HOST_WIDE_INT value = INTVAL (operands[1]);
4030     rtx addr = XEXP (operands[0], 0);
4031     rtx op0 = operands[0];
4032     enum rtx_code code = GET_CODE (addr);
4034     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4035         || code == MINUS)
4036       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4038     operands[1] = gen_reg_rtx (SImode);
4039     if (BYTES_BIG_ENDIAN)
4040       {
4041         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4042         if ((value & 255) == ((value >> 8) & 255))
4043           operands[2] = operands[1];
4044         else
4045           {
4046             operands[2] = gen_reg_rtx (SImode);
4047             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4048           }
4049       }
4050     else
4051       {
4052         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4053         if ((value & 255) == ((value >> 8) & 255))
4054           operands[2] = operands[1];
4055         else
4056           {
4057             operands[2] = gen_reg_rtx (SImode);
4058             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4059           }
4060       }
4062     operands[3] = adjust_address (op0, QImode, 1);
4063     operands[0] = adjust_address (operands[0], QImode, 0);
4064     operands[2] = gen_lowpart (QImode, operands[2]);
4065   }"
4068 (define_expand "storehi_single_op"
4069   [(set (match_operand:HI 0 "memory_operand" "")
4070         (match_operand:HI 1 "general_operand" ""))]
4071   "TARGET_ARM && arm_arch4"
4072   "
4073   if (!s_register_operand (operands[1], HImode))
4074     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4075   "
4078 (define_expand "movhi"
4079   [(set (match_operand:HI 0 "general_operand" "")
4080         (match_operand:HI 1 "general_operand" ""))]
4081   "TARGET_EITHER"
4082   "
4083   if (TARGET_ARM)
4084     {
4085       if (!no_new_pseudos)
4086         {
4087           if (GET_CODE (operands[0]) == MEM)
4088             {
4089               if (arm_arch4)
4090                 {
4091                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4092                   DONE;
4093                 }
4094               if (GET_CODE (operands[1]) == CONST_INT)
4095                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4096               else
4097                 {
4098                   if (GET_CODE (operands[1]) == MEM)
4099                     operands[1] = force_reg (HImode, operands[1]);
4100                   if (BYTES_BIG_ENDIAN)
4101                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4102                   else
4103                    emit_insn (gen_storehi (operands[1], operands[0]));
4104                 }
4105               DONE;
4106             }
4107           /* Sign extend a constant, and keep it in an SImode reg.  */
4108           else if (GET_CODE (operands[1]) == CONST_INT)
4109             {
4110               rtx reg = gen_reg_rtx (SImode);
4111               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4113               /* If the constant is already valid, leave it alone.  */
4114               if (!const_ok_for_arm (val))
4115                 {
4116                   /* If setting all the top bits will make the constant 
4117                      loadable in a single instruction, then set them.  
4118                      Otherwise, sign extend the number.  */
4120                   if (const_ok_for_arm (~(val | ~0xffff)))
4121                     val |= ~0xffff;
4122                   else if (val & 0x8000)
4123                     val |= ~0xffff;
4124                 }
4126               emit_insn (gen_movsi (reg, GEN_INT (val)));
4127               operands[1] = gen_lowpart (HImode, reg);
4128             }
4129           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4130                    && GET_CODE (operands[1]) == MEM)
4131             {
4132               rtx reg = gen_reg_rtx (SImode);
4134               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4135               operands[1] = gen_lowpart (HImode, reg);
4136             }
4137           else if (!arm_arch4)
4138             {
4139              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4140                 for v4 and up architectures because LDRH instructions will
4141                 be used to access the HI values, and these cannot generate
4142                 unaligned word access faults in the MMU.  */
4143               if (GET_CODE (operands[1]) == MEM)
4144                 {
4145                   if (TARGET_MMU_TRAPS)
4146                     {
4147                       rtx base;
4148                       rtx offset = const0_rtx;
4149                       rtx reg = gen_reg_rtx (SImode);
4151                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4152                            || (GET_CODE (base) == PLUS
4153                                && (GET_CODE (offset = XEXP (base, 1))
4154                                    == CONST_INT)
4155                                && ((INTVAL(offset) & 1) != 1)
4156                                && GET_CODE (base = XEXP (base, 0)) == REG))
4157                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4158                         {
4159                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4160                           rtx new;
4162                           new = gen_rtx_MEM (SImode,
4163                                              plus_constant (base, new_offset));
4164                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4165                           emit_insn (gen_movsi (reg, new));
4166                           if (((INTVAL (offset) & 2) != 0)
4167                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4168                             {
4169                               rtx reg2 = gen_reg_rtx (SImode);
4171                               emit_insn (gen_lshrsi3 (reg2, reg,
4172                                          GEN_INT (16)));
4173                               reg = reg2;
4174                             }
4175                         }
4176                       else
4177                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4179                       operands[1] = gen_lowpart (HImode, reg);
4180                     }
4181                   else if (BYTES_BIG_ENDIAN)
4182                     {
4183                       rtx base;
4184                       rtx offset = const0_rtx;
4186                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4187                            || (GET_CODE (base) == PLUS
4188                               && (GET_CODE (offset = XEXP (base, 1))
4189                                   == CONST_INT)
4190                               && GET_CODE (base = XEXP (base, 0)) == REG))
4191                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4192                         {
4193                           rtx reg = gen_reg_rtx (SImode);
4194                           rtx new;
4196                           if ((INTVAL (offset) & 2) == 2)
4197                             {
4198                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4199                               new = gen_rtx_MEM (SImode,
4200                                                  plus_constant (base,
4201                                                                 new_offset));
4202                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4203                               emit_insn (gen_movsi (reg, new));
4204                             }
4205                           else
4206                             {
4207                               new = gen_rtx_MEM (SImode,
4208                                                  XEXP (operands[1], 0));
4209                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4210                               emit_insn (gen_rotated_loadsi (reg, new));
4211                             }
4213                           operands[1] = gen_lowpart (HImode, reg);
4214                         }
4215                       else
4216                         {
4217                           emit_insn (gen_movhi_bigend (operands[0],
4218                                                        operands[1]));
4219                           DONE;
4220                         }
4221                     }
4222                }
4223            }
4224         }
4225       /* Handle loading a large integer during reload */
4226       else if (GET_CODE (operands[1]) == CONST_INT
4227                && !const_ok_for_arm (INTVAL (operands[1]))
4228                && !const_ok_for_arm (~INTVAL (operands[1])))
4229         {
4230           /* Writing a constant to memory needs a scratch, which should
4231              be handled with SECONDARY_RELOADs.  */
4232           if (GET_CODE (operands[0]) != REG)
4233             abort ();
4235           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4236           emit_insn (gen_movsi (operands[0], operands[1]));
4237           DONE;
4238        }
4239     }
4240   else /* TARGET_THUMB */
4241     {
4242       if (!no_new_pseudos)
4243         {
4244           if (GET_CODE (operands[0]) != REG)
4245             operands[1] = force_reg (HImode, operands[1]);
4247           /* ??? We shouldn't really get invalid addresses here, but this can
4248              happen if we are passed a SP (never OK for HImode/QImode) or 
4249              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4250              HImode/QImode) relative address.  */
4251           /* ??? This should perhaps be fixed elsewhere, for instance, in
4252              fixup_stack_1, by checking for other kinds of invalid addresses,
4253              e.g. a bare reference to a virtual register.  This may confuse the
4254              alpha though, which must handle this case differently.  */
4255           if (GET_CODE (operands[0]) == MEM
4256               && !memory_address_p (GET_MODE (operands[0]),
4257                                     XEXP (operands[0], 0)))
4258             operands[0]
4259               = replace_equiv_address (operands[0],
4260                                        copy_to_reg (XEXP (operands[0], 0)));
4261    
4262           if (GET_CODE (operands[1]) == MEM
4263               && !memory_address_p (GET_MODE (operands[1]),
4264                                     XEXP (operands[1], 0)))
4265             operands[1]
4266               = replace_equiv_address (operands[1],
4267                                        copy_to_reg (XEXP (operands[1], 0)));
4268         }
4269       /* Handle loading a large integer during reload */
4270       else if (GET_CODE (operands[1]) == CONST_INT
4271                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4272         {
4273           /* Writing a constant to memory needs a scratch, which should
4274              be handled with SECONDARY_RELOADs.  */
4275           if (GET_CODE (operands[0]) != REG)
4276             abort ();
4278           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4279           emit_insn (gen_movsi (operands[0], operands[1]));
4280           DONE;
4281         }
4282     }
4283   "
4286 (define_insn "*thumb_movhi_insn"
4287   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4288         (match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4289   "TARGET_THUMB
4290    && (   register_operand (operands[0], HImode)
4291        || register_operand (operands[1], HImode))"
4292   "*
4293   switch (which_alternative)
4294     {
4295     case 0: return \"add        %0, %1, #0\";
4296     case 2: return \"strh       %1, %0\";
4297     case 3: return \"mov        %0, %1\";
4298     case 4: return \"mov        %0, %1\";
4299     case 5: return \"mov        %0, %1\";
4300     default: abort ();
4301     case 1:
4302       /* The stack pointer can end up being taken as an index register.
4303           Catch this case here and deal with it.  */
4304       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4305           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4306           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4307         {
4308           rtx ops[2];
4309           ops[0] = operands[0];
4310           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4311       
4312           output_asm_insn (\"mov        %0, %1\", ops);
4314           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4315     
4316         }
4317       return \"ldrh     %0, %1\";
4318     }"
4319   [(set_attr "length" "2,4,2,2,2,2")
4320    (set_attr "type" "*,load,store1,*,*,*")
4321    (set_attr "pool_range" "*,64,*,*,*,*")]
4325 (define_insn "rotated_loadsi"
4326   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4327         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4328                    (const_int 16)))]
4329   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4330   "*
4331   {
4332     rtx ops[2];
4334     ops[0] = operands[0];
4335     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4336     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4337     return \"\";
4338   }"
4339   [(set_attr "type" "load")
4340    (set_attr "predicable" "yes")]
4343 (define_expand "movhi_bytes"
4344   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4345    (set (match_dup 3)
4346         (zero_extend:SI (match_dup 6)))
4347    (set (match_operand:SI 0 "" "")
4348          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4349   "TARGET_ARM"
4350   "
4351   {
4352     rtx mem1, mem2;
4353     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4355     mem1 = gen_rtx_MEM (QImode, addr);
4356     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4357     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4358     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4359     operands[0] = gen_lowpart (SImode, operands[0]);
4360     operands[1] = mem1;
4361     operands[2] = gen_reg_rtx (SImode);
4362     operands[3] = gen_reg_rtx (SImode);
4363     operands[6] = mem2;
4365     if (BYTES_BIG_ENDIAN)
4366       {
4367         operands[4] = operands[2];
4368         operands[5] = operands[3];
4369       }
4370     else
4371       {
4372         operands[4] = operands[3];
4373         operands[5] = operands[2];
4374       }
4375   }"
4378 (define_expand "movhi_bigend"
4379   [(set (match_dup 2)
4380         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4381                    (const_int 16)))
4382    (set (match_dup 3)
4383         (ashiftrt:SI (match_dup 2) (const_int 16)))
4384    (set (match_operand:HI 0 "s_register_operand" "")
4385         (subreg:HI (match_dup 3) 0))]
4386   "TARGET_ARM"
4387   "
4388   operands[2] = gen_reg_rtx (SImode);
4389   operands[3] = gen_reg_rtx (SImode);
4390   "
4393 ;; Pattern to recognize insn generated default case above
4394 (define_insn "*movhi_insn_arch4"
4395   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4396         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4397   "TARGET_ARM
4398    && arm_arch4
4399    && (GET_CODE (operands[1]) != CONST_INT
4400        || const_ok_for_arm (INTVAL (operands[1]))
4401        || const_ok_for_arm (~INTVAL (operands[1])))"
4402   "@
4403    mov%?\\t%0, %1\\t%@ movhi
4404    mvn%?\\t%0, #%B1\\t%@ movhi
4405    str%?h\\t%1, %0\\t%@ movhi 
4406    ldr%?h\\t%0, %1\\t%@ movhi"
4407   [(set_attr "type" "*,*,store1,load")
4408    (set_attr "predicable" "yes")
4409    (set_attr "pool_range" "*,*,*,256")
4410    (set_attr "neg_pool_range" "*,*,*,244")]
4413 (define_insn "*movhi_insn_littleend"
4414   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4415         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4416   "TARGET_ARM
4417    && !arm_arch4
4418    && !BYTES_BIG_ENDIAN
4419    && !TARGET_MMU_TRAPS
4420    && (GET_CODE (operands[1]) != CONST_INT
4421        || const_ok_for_arm (INTVAL (operands[1]))
4422        || const_ok_for_arm (~INTVAL (operands[1])))"
4423   "@
4424    mov%?\\t%0, %1\\t%@ movhi
4425    mvn%?\\t%0, #%B1\\t%@ movhi
4426    ldr%?\\t%0, %1\\t%@ movhi"
4427   [(set_attr "type" "*,*,load")
4428    (set_attr "predicable" "yes")
4429    (set_attr "pool_range" "4096")
4430    (set_attr "neg_pool_range" "4084")]
4433 (define_insn "*movhi_insn_bigend"
4434   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4435         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4436   "TARGET_ARM
4437    && !arm_arch4
4438    && BYTES_BIG_ENDIAN
4439    && !TARGET_MMU_TRAPS
4440    && (GET_CODE (operands[1]) != CONST_INT
4441        || const_ok_for_arm (INTVAL (operands[1]))
4442        || const_ok_for_arm (~INTVAL (operands[1])))"
4443   "@
4444    mov%?\\t%0, %1\\t%@ movhi
4445    mvn%?\\t%0, #%B1\\t%@ movhi
4446    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4447   [(set_attr "type" "*,*,load")
4448    (set_attr "predicable" "yes")
4449    (set_attr "length" "4,4,8")
4450    (set_attr "pool_range" "*,*,4092")
4451    (set_attr "neg_pool_range" "*,*,4084")]
4454 (define_insn "*loadhi_si_bigend"
4455   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4456         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4457                    (const_int 16)))]
4458   "TARGET_ARM
4459    && BYTES_BIG_ENDIAN
4460    && !TARGET_MMU_TRAPS"
4461   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4462   [(set_attr "type" "load")
4463    (set_attr "predicable" "yes")
4464    (set_attr "pool_range" "4096")
4465    (set_attr "neg_pool_range" "4084")]
4468 (define_insn "*movhi_bytes"
4469   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4470         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4471   "TARGET_ARM && TARGET_MMU_TRAPS"
4472   "@
4473    mov%?\\t%0, %1\\t%@ movhi
4474    mvn%?\\t%0, #%B1\\t%@ movhi"
4475   [(set_attr "predicable" "yes")]
4478 (define_insn "thumb_movhi_clobber"
4479   [(set (match_operand:HI     0 "memory_operand"   "=m")
4480         (match_operand:HI     1 "register_operand" "l"))
4481    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4482   "TARGET_THUMB"
4483   "*
4484   abort ();"
4486         
4487 ;; We use a DImode scratch because we may occasionally need an additional
4488 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4489 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4490 (define_expand "reload_outhi"
4491   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4492               (match_operand:HI 1 "s_register_operand"        "r")
4493               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4494   "TARGET_EITHER"
4495   "if (TARGET_ARM)
4496      arm_reload_out_hi (operands);
4497    else
4498      thumb_reload_out_hi (operands);
4499   DONE;
4500   "
4503 (define_expand "reload_inhi"
4504   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4505               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4506               (match_operand:DI 2 "s_register_operand" "=&r")])]
4507   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4508   "
4509   if (TARGET_ARM)
4510     arm_reload_in_hi (operands);
4511   else
4512     thumb_reload_out_hi (operands);
4513   DONE;
4516 (define_expand "movqi"
4517   [(set (match_operand:QI 0 "general_operand" "")
4518         (match_operand:QI 1 "general_operand" ""))]
4519   "TARGET_EITHER"
4520   "
4521   if (TARGET_ARM)
4522     {
4523       /* Everything except mem = const or mem = mem can be done easily */
4525       if (!no_new_pseudos)
4526         {
4527           if (GET_CODE (operands[1]) == CONST_INT)
4528             {
4529               rtx reg = gen_reg_rtx (SImode);
4531               emit_insn (gen_movsi (reg, operands[1]));
4532               operands[1] = gen_lowpart (QImode, reg);
4533             }
4534           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4535             {
4536               rtx reg = gen_reg_rtx (SImode);
4538               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4539               operands[1] = gen_lowpart (QImode, reg);
4540             }
4541           if (GET_CODE (operands[0]) == MEM)
4542             operands[1] = force_reg (QImode, operands[1]);
4543         }
4544     }
4545   else /* TARGET_THUMB */
4546     {
4547       if (!no_new_pseudos)
4548         {
4549           if (GET_CODE (operands[0]) != REG)
4550             operands[1] = force_reg (QImode, operands[1]);
4552           /* ??? We shouldn't really get invalid addresses here, but this can
4553              happen if we are passed a SP (never OK for HImode/QImode) or
4554              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4555              HImode/QImode) relative address.  */
4556           /* ??? This should perhaps be fixed elsewhere, for instance, in
4557              fixup_stack_1, by checking for other kinds of invalid addresses,
4558              e.g. a bare reference to a virtual register.  This may confuse the
4559              alpha though, which must handle this case differently.  */
4560           if (GET_CODE (operands[0]) == MEM
4561               && !memory_address_p (GET_MODE (operands[0]),
4562                                      XEXP (operands[0], 0)))
4563             operands[0]
4564               = replace_equiv_address (operands[0],
4565                                        copy_to_reg (XEXP (operands[0], 0)));
4566           if (GET_CODE (operands[1]) == MEM
4567               && !memory_address_p (GET_MODE (operands[1]),
4568                                     XEXP (operands[1], 0)))
4569              operands[1]
4570                = replace_equiv_address (operands[1],
4571                                         copy_to_reg (XEXP (operands[1], 0)));
4572         }
4573       /* Handle loading a large integer during reload */
4574       else if (GET_CODE (operands[1]) == CONST_INT
4575                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4576         {
4577           /* Writing a constant to memory needs a scratch, which should
4578              be handled with SECONDARY_RELOADs.  */
4579           if (GET_CODE (operands[0]) != REG)
4580             abort ();
4582           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4583           emit_insn (gen_movsi (operands[0], operands[1]));
4584           DONE;
4585        }
4586     }
4587   "
4591 (define_insn "*arm_movqi_insn"
4592   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4593         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4594   "TARGET_ARM
4595    && (   register_operand (operands[0], QImode)
4596        || register_operand (operands[1], QImode))"
4597   "@
4598    mov%?\\t%0, %1
4599    mvn%?\\t%0, #%B1
4600    ldr%?b\\t%0, %1
4601    str%?b\\t%1, %0"
4602   [(set_attr "type" "*,*,load,store1")
4603    (set_attr "predicable" "yes")]
4606 (define_insn "*thumb_movqi_insn"
4607   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4608         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4609   "TARGET_THUMB
4610    && (   register_operand (operands[0], QImode)
4611        || register_operand (operands[1], QImode))"
4612   "@
4613    add\\t%0, %1, #0
4614    ldrb\\t%0, %1
4615    strb\\t%1, %0
4616    mov\\t%0, %1
4617    mov\\t%0, %1
4618    mov\\t%0, %1"
4619   [(set_attr "length" "2")
4620    (set_attr "type" "*,load,store1,*,*,*")
4621    (set_attr "pool_range" "*,32,*,*,*,*")]
4624 (define_expand "movsf"
4625   [(set (match_operand:SF 0 "general_operand" "")
4626         (match_operand:SF 1 "general_operand" ""))]
4627   "TARGET_EITHER"
4628   "
4629   if (TARGET_ARM)
4630     {
4631       if (GET_CODE (operands[0]) == MEM)
4632         operands[1] = force_reg (SFmode, operands[1]);
4633     }
4634   else /* TARGET_THUMB */
4635     {
4636       if (!no_new_pseudos)
4637         {
4638            if (GET_CODE (operands[0]) != REG)
4639              operands[1] = force_reg (SFmode, operands[1]);
4640         }
4641     }
4642   "
4645 (define_split
4646   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4647         (match_operand:SF 1 "immediate_operand" ""))]
4648   "TARGET_ARM
4649    && !TARGET_HARD_FLOAT
4650    && reload_completed
4651    && GET_CODE (operands[1]) == CONST_DOUBLE"
4652   [(set (match_dup 2) (match_dup 3))]
4653   "
4654   operands[2] = gen_lowpart (SImode, operands[0]);
4655   operands[3] = gen_lowpart (SImode, operands[1]);
4656   if (operands[2] == 0 || operands[3] == 0)
4657     FAIL;
4658   "
4661 (define_insn "*arm_movsf_soft_insn"
4662   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4663         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4664   "TARGET_ARM
4665    && !TARGET_CIRRUS
4666    && TARGET_SOFT_FLOAT
4667    && (GET_CODE (operands[0]) != MEM
4668        || register_operand (operands[1], SFmode))"
4669   "@
4670    mov%?\\t%0, %1
4671    ldr%?\\t%0, %1\\t%@ float
4672    str%?\\t%1, %0\\t%@ float"
4673   [(set_attr "length" "4,4,4")
4674    (set_attr "predicable" "yes")
4675    (set_attr "type" "*,load,store1")
4676    (set_attr "pool_range" "*,4096,*")
4677    (set_attr "neg_pool_range" "*,4084,*")]
4680 ;;; ??? This should have alternatives for constants.
4681 (define_insn "*thumb_movsf_insn"
4682   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4683         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4684   "TARGET_THUMB
4685    && (   register_operand (operands[0], SFmode) 
4686        || register_operand (operands[1], SFmode))"
4687   "@
4688    add\\t%0, %1, #0
4689    ldmia\\t%1, {%0}
4690    stmia\\t%0, {%1}
4691    ldr\\t%0, %1
4692    str\\t%1, %0
4693    mov\\t%0, %1
4694    mov\\t%0, %1"
4695   [(set_attr "length" "2")
4696    (set_attr "type" "*,load,store1,load,store1,*,*")
4697    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4700 (define_expand "movdf"
4701   [(set (match_operand:DF 0 "general_operand" "")
4702         (match_operand:DF 1 "general_operand" ""))]
4703   "TARGET_EITHER"
4704   "
4705   if (TARGET_ARM)
4706     {
4707       if (GET_CODE (operands[0]) == MEM)
4708         operands[1] = force_reg (DFmode, operands[1]);
4709     }
4710   else /* TARGET_THUMB */
4711     {
4712       if (!no_new_pseudos)
4713         {
4714           if (GET_CODE (operands[0]) != REG)
4715             operands[1] = force_reg (DFmode, operands[1]);
4716         }
4717     }
4718   "
4721 ;; Reloading a df mode value stored in integer regs to memory can require a
4722 ;; scratch reg.
4723 (define_expand "reload_outdf"
4724   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4725    (match_operand:DF 1 "s_register_operand" "r")
4726    (match_operand:SI 2 "s_register_operand" "=&r")]
4727   "TARGET_ARM"
4728   "
4729   {
4730     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4732     if (code == REG)
4733       operands[2] = XEXP (operands[0], 0);
4734     else if (code == POST_INC || code == PRE_DEC)
4735       {
4736         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4737         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4738         emit_insn (gen_movdi (operands[0], operands[1]));
4739         DONE;
4740       }
4741     else if (code == PRE_INC)
4742       {
4743         rtx reg = XEXP (XEXP (operands[0], 0), 0);
4745         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4746         operands[2] = reg;
4747       }
4748     else if (code == POST_DEC)
4749       operands[2] = XEXP (XEXP (operands[0], 0), 0);
4750     else
4751       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4752                              XEXP (XEXP (operands[0], 0), 1)));
4754     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4755                             operands[1]));
4757     if (code == POST_DEC)
4758       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4760     DONE;
4761   }"
4764 (define_insn "*movdf_soft_insn"
4765   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4766         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4767   "TARGET_ARM && TARGET_SOFT_FLOAT
4768    && !TARGET_CIRRUS
4769   "
4770   "* return output_move_double (operands);"
4771   [(set_attr "length" "8,8,8")
4772    (set_attr "type" "*,load,store2")
4773    (set_attr "pool_range" "1020")
4774    (set_attr "neg_pool_range" "1008")]
4777 ;;; ??? This should have alternatives for constants.
4778 ;;; ??? This was originally identical to the movdi_insn pattern.
4779 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4780 ;;; thumb_reorg with a memory reference.
4781 (define_insn "*thumb_movdf_insn"
4782   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4783         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
4784   "TARGET_THUMB
4785    && (   register_operand (operands[0], DFmode)
4786        || register_operand (operands[1], DFmode))"
4787   "*
4788   switch (which_alternative)
4789     {
4790     default:
4791     case 0:
4792       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4793         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4794       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4795     case 1:
4796       return \"ldmia\\t%1, {%0, %H0}\";
4797     case 2:
4798       return \"stmia\\t%0, {%1, %H1}\";
4799     case 3:
4800       return thumb_load_double_from_address (operands);
4801     case 4:
4802       operands[2] = gen_rtx (MEM, SImode,
4803                              plus_constant (XEXP (operands[0], 0), 4));
4804       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4805       return \"\";
4806     case 5:
4807       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4808         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4809       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4810     }
4811   "
4812   [(set_attr "length" "4,2,2,6,4,4")
4813    (set_attr "type" "*,load,store2,load,store2,*")
4814    (set_attr "pool_range" "*,*,*,1020,*,*")]
4817 ;; Vector Moves
4818 (define_expand "movv2si"
4819   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
4820         (match_operand:V2SI 1 "general_operand" ""))]
4821   "TARGET_REALLY_IWMMXT"
4825 (define_expand "movv4hi"
4826   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
4827         (match_operand:V4HI 1 "general_operand" ""))]
4828   "TARGET_REALLY_IWMMXT"
4832 (define_expand "movv8qi"
4833   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
4834         (match_operand:V8QI 1 "general_operand" ""))]
4835   "TARGET_REALLY_IWMMXT"
4840 ;; load- and store-multiple insns
4841 ;; The arm can load/store any set of registers, provided that they are in
4842 ;; ascending order; but that is beyond GCC so stick with what it knows.
4844 (define_expand "load_multiple"
4845   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4846                           (match_operand:SI 1 "" ""))
4847                      (use (match_operand:SI 2 "" ""))])]
4848   "TARGET_ARM"
4849   "
4850   /* Support only fixed point registers.  */
4851   if (GET_CODE (operands[2]) != CONST_INT
4852       || INTVAL (operands[2]) > 14
4853       || INTVAL (operands[2]) < 2
4854       || GET_CODE (operands[1]) != MEM
4855       || GET_CODE (operands[0]) != REG
4856       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
4857       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4858     FAIL;
4860   operands[3]
4861     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
4862                              force_reg (SImode, XEXP (operands[1], 0)),
4863                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
4864                              MEM_IN_STRUCT_P(operands[1]),
4865                              MEM_SCALAR_P (operands[1]));
4866   "
4869 ;; Load multiple with write-back
4871 (define_insn "*ldmsi_postinc4"
4872   [(match_parallel 0 "load_multiple_operation"
4873     [(set (match_operand:SI 1 "s_register_operand" "=r")
4874           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4875                    (const_int 16)))
4876      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4877           (mem:SI (match_dup 2)))
4878      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4879           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4880      (set (match_operand:SI 5 "arm_hard_register_operand" "")
4881           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
4882      (set (match_operand:SI 6 "arm_hard_register_operand" "")
4883           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
4884   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4885   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
4886   [(set_attr "type" "load")
4887    (set_attr "predicable" "yes")]
4890 (define_insn "*ldmsi_postinc3"
4891   [(match_parallel 0 "load_multiple_operation"
4892     [(set (match_operand:SI 1 "s_register_operand" "=r")
4893           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4894                    (const_int 12)))
4895      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4896           (mem:SI (match_dup 2)))
4897      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4898           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4899      (set (match_operand:SI 5 "arm_hard_register_operand" "")
4900           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
4901   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4902   "ldm%?ia\\t%1!, {%3, %4, %5}"
4903   [(set_attr "type" "load")
4904    (set_attr "predicable" "yes")]
4907 (define_insn "*ldmsi_postinc2"
4908   [(match_parallel 0 "load_multiple_operation"
4909     [(set (match_operand:SI 1 "s_register_operand" "=r")
4910           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4911                    (const_int 8)))
4912      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4913           (mem:SI (match_dup 2)))
4914      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4915           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
4916   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4917   "ldm%?ia\\t%1!, {%3, %4}"
4918   [(set_attr "type" "load")
4919    (set_attr "predicable" "yes")]
4922 ;; Ordinary load multiple
4924 (define_insn "*ldmsi4"
4925   [(match_parallel 0 "load_multiple_operation"
4926     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4927           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4928      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4929           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4930      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4931           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4932      (set (match_operand:SI 5 "arm_hard_register_operand" "")
4933           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
4934   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4935   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
4936   [(set_attr "type" "load")
4937    (set_attr "predicable" "yes")]
4940 (define_insn "*ldmsi3"
4941   [(match_parallel 0 "load_multiple_operation"
4942     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4943           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4944      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4945           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4946      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4947           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
4948   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4949   "ldm%?ia\\t%1, {%2, %3, %4}"
4950   [(set_attr "type" "load")
4951    (set_attr "predicable" "yes")]
4954 (define_insn "*ldmsi2"
4955   [(match_parallel 0 "load_multiple_operation"
4956     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4957           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4958      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4959           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
4960   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4961   "ldm%?ia\\t%1, {%2, %3}"
4962   [(set_attr "type" "load")
4963    (set_attr "predicable" "yes")]
4966 (define_expand "store_multiple"
4967   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4968                           (match_operand:SI 1 "" ""))
4969                      (use (match_operand:SI 2 "" ""))])]
4970   "TARGET_ARM"
4971   "
4972   /* Support only fixed point registers */
4973   if (GET_CODE (operands[2]) != CONST_INT
4974       || INTVAL (operands[2]) > 14
4975       || INTVAL (operands[2]) < 2
4976       || GET_CODE (operands[1]) != REG
4977       || GET_CODE (operands[0]) != MEM
4978       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
4979       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4980     FAIL;
4982   operands[3]
4983     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
4984                               force_reg (SImode, XEXP (operands[0], 0)),
4985                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
4986                               MEM_IN_STRUCT_P(operands[0]), 
4987                               MEM_SCALAR_P (operands[0]));
4988   "
4991 ;; Store multiple with write-back
4993 (define_insn "*stmsi_postinc4"
4994   [(match_parallel 0 "store_multiple_operation"
4995     [(set (match_operand:SI 1 "s_register_operand" "=r")
4996           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4997                    (const_int 16)))
4998      (set (mem:SI (match_dup 2))
4999           (match_operand:SI 3 "arm_hard_register_operand" ""))
5000      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5001           (match_operand:SI 4 "arm_hard_register_operand" ""))
5002      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5003           (match_operand:SI 5 "arm_hard_register_operand" ""))
5004      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5005           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5006   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5007   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5008   [(set_attr "predicable" "yes")
5009    (set_attr "type" "store4")]
5012 (define_insn "*stmsi_postinc3"
5013   [(match_parallel 0 "store_multiple_operation"
5014     [(set (match_operand:SI 1 "s_register_operand" "=r")
5015           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5016                    (const_int 12)))
5017      (set (mem:SI (match_dup 2))
5018           (match_operand:SI 3 "arm_hard_register_operand" ""))
5019      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5020           (match_operand:SI 4 "arm_hard_register_operand" ""))
5021      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5022           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5023   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5024   "stm%?ia\\t%1!, {%3, %4, %5}"
5025   [(set_attr "predicable" "yes")
5026    (set_attr "type" "store3")]
5029 (define_insn "*stmsi_postinc2"
5030   [(match_parallel 0 "store_multiple_operation"
5031     [(set (match_operand:SI 1 "s_register_operand" "=r")
5032           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5033                    (const_int 8)))
5034      (set (mem:SI (match_dup 2))
5035           (match_operand:SI 3 "arm_hard_register_operand" ""))
5036      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5037           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5038   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5039   "stm%?ia\\t%1!, {%3, %4}"
5040   [(set_attr "predicable" "yes")
5041    (set_attr "type" "store2")]
5044 ;; Ordinary store multiple
5046 (define_insn "*stmsi4"
5047   [(match_parallel 0 "store_multiple_operation"
5048     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5049           (match_operand:SI 2 "arm_hard_register_operand" ""))
5050      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5051           (match_operand:SI 3 "arm_hard_register_operand" ""))
5052      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5053           (match_operand:SI 4 "arm_hard_register_operand" ""))
5054      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5055           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5056   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5057   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5058   [(set_attr "predicable" "yes")
5059    (set_attr "type" "store4")]
5062 (define_insn "*stmsi3"
5063   [(match_parallel 0 "store_multiple_operation"
5064     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5065           (match_operand:SI 2 "arm_hard_register_operand" ""))
5066      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5067           (match_operand:SI 3 "arm_hard_register_operand" ""))
5068      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5069           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5070   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5071   "stm%?ia\\t%1, {%2, %3, %4}"
5072   [(set_attr "predicable" "yes")
5073    (set_attr "type" "store3")]
5076 (define_insn "*stmsi2"
5077   [(match_parallel 0 "store_multiple_operation"
5078     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5079           (match_operand:SI 2 "arm_hard_register_operand" ""))
5080      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5081           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5082   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5083   "stm%?ia\\t%1, {%2, %3}"
5084   [(set_attr "predicable" "yes")
5085    (set_attr "type" "store2")]
5088 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5089 ;; We could let this apply for blocks of less than this, but it clobbers so
5090 ;; many registers that there is then probably a better way.
5092 (define_expand "movstrqi"
5093   [(match_operand:BLK 0 "general_operand" "")
5094    (match_operand:BLK 1 "general_operand" "")
5095    (match_operand:SI 2 "const_int_operand" "")
5096    (match_operand:SI 3 "const_int_operand" "")]
5097   "TARGET_EITHER"
5098   "
5099   if (TARGET_ARM)
5100     {
5101       if (arm_gen_movstrqi (operands))
5102         DONE;
5103       FAIL;
5104     }
5105   else /* TARGET_THUMB */
5106     {
5107       if (   INTVAL (operands[3]) != 4
5108           || INTVAL (operands[2]) > 48)
5109         FAIL;
5111       thumb_expand_movstrqi (operands);
5112       DONE;
5113     }
5114   "
5117 ;; Thumb block-move insns
5119 (define_insn "movmem12b"
5120   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5121         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5122    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5123         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5124    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5125         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5126    (set (match_operand:SI 0 "register_operand" "=l")
5127         (plus:SI (match_dup 2) (const_int 12)))
5128    (set (match_operand:SI 1 "register_operand" "=l")
5129         (plus:SI (match_dup 3) (const_int 12)))
5130    (clobber (match_scratch:SI 4 "=&l"))
5131    (clobber (match_scratch:SI 5 "=&l"))
5132    (clobber (match_scratch:SI 6 "=&l"))]
5133   "TARGET_THUMB"
5134   "* return thumb_output_move_mem_multiple (3, operands);"
5135   [(set_attr "length" "4")
5136    ; This isn't entirely accurate...  It loads as well, but in terms of
5137    ; scheduling the following insn it is better to consider it as a store
5138    (set_attr "type" "store3")]
5141 (define_insn "movmem8b"
5142   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5143         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5144    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5145         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5146    (set (match_operand:SI 0 "register_operand" "=l")
5147         (plus:SI (match_dup 2) (const_int 8)))
5148    (set (match_operand:SI 1 "register_operand" "=l")
5149         (plus:SI (match_dup 3) (const_int 8)))
5150    (clobber (match_scratch:SI 4 "=&l"))
5151    (clobber (match_scratch:SI 5 "=&l"))]
5152   "TARGET_THUMB"
5153   "* return thumb_output_move_mem_multiple (2, operands);"
5154   [(set_attr "length" "4")
5155    ; This isn't entirely accurate...  It loads as well, but in terms of
5156    ; scheduling the following insn it is better to consider it as a store
5157    (set_attr "type" "store2")]
5162 ;; Compare & branch insns
5163 ;; The range calculations are based as follows:
5164 ;; For forward branches, the address calculation returns the address of
5165 ;; the next instruction.  This is 2 beyond the branch instruction.
5166 ;; For backward branches, the address calculation returns the address of
5167 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5168 ;; instruction for the shortest sequence, and 4 before the branch instruction
5169 ;; if we have to jump around an unconditional branch.
5170 ;; To the basic branch range the PC offset must be added (this is +4).
5171 ;; So for forward branches we have 
5172 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5173 ;; And for backward branches we have 
5174 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5176 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5177 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5179 (define_insn "cbranchsi4"
5180   [(set (pc)
5181         (if_then_else
5182             (match_operator                    0 "arm_comparison_operator"
5183                             [(match_operand:SI 1 "register_operand"   "l,r")
5184                              (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5185             (label_ref       (match_operand    3 "" ""))
5186             (pc)))]
5187   "TARGET_THUMB"
5188   "*
5189   output_asm_insn (\"cmp\\t%1, %2\", operands);
5190   switch (get_attr_length (insn))
5191     {
5192     case 4:  return \"b%d0\\t%l3\";
5193     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5194     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5195     }
5196   "
5197   [(set (attr "far_jump")
5198         (if_then_else
5199             (eq_attr "length" "8")
5200             (const_string "yes")
5201             (const_string "no")))
5202    (set (attr "length") 
5203         (if_then_else
5204             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5205                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5206             (const_int 4)
5207             (if_then_else
5208                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5209                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5210                 (const_int 6)
5211                 (const_int 8))))]
5214 (define_insn "*negated_cbranchsi4"
5215   [(set (pc)
5216         (if_then_else
5217          (match_operator             0 "arm_comparison_operator"
5218           [(match_operand:SI         1 "register_operand"  "l")
5219            (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5220          (label_ref (match_operand   3 "" ""))
5221          (pc)))]
5222   "TARGET_THUMB"
5223   "*
5224   output_asm_insn (\"cmn\\t%1, %2\", operands);
5225   switch (get_attr_length (insn))
5226     {
5227     case 4:  return \"b%d0\\t%l3\";
5228     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5229     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5230     }
5231   "
5232   [(set (attr "far_jump")
5233         (if_then_else
5234             (eq_attr "length" "8")
5235             (const_string "yes")
5236             (const_string "no")))
5237    (set (attr "length") 
5238         (if_then_else
5239             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5240                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5241             (const_int 4)
5242             (if_then_else
5243                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5244                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5245                 (const_int 6)
5246                 (const_int 8))))]
5249 (define_insn "*cbranchne_decr1"
5250   [(set (pc)
5251         (if_then_else (match_operator 3 "equality_operator"
5252                        [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
5253                         (const_int 0)])
5254                       (label_ref (match_operand 4 "" ""))
5255                       (pc)))
5256    (set (match_operand:SI 0 "s_register_operand" "=l,?h,?m,?m")
5257         (plus:SI (match_dup 2) (const_int -1)))
5258    (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5259   "TARGET_THUMB"
5260   "*
5261    {
5262      rtx cond[2];
5263      cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
5264                                 ? GEU : LTU),
5265                                VOIDmode, NULL, NULL);
5266      cond[1] = operands[4];
5268      if (which_alternative == 0)
5269        output_asm_insn (\"sub\\t%0, %2, #1\", operands);
5270      else if (which_alternative == 1)
5271        {
5272          /* We must provide an alternative for a hi reg because reload 
5273             cannot handle output reloads on a jump instruction, but we
5274             can't subtract into that.  Fortunately a mov from lo to hi
5275             does not clobber the condition codes.  */
5276          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
5277          output_asm_insn (\"mov\\t%0, %1\", operands);
5278        }
5279      else
5280        {
5281          /* Similarly, but the target is memory.  */
5282          output_asm_insn (\"sub\\t%1, %2, #1\", operands);
5283          output_asm_insn (\"str\\t%1, %0\", operands);
5284        }
5286      switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5287        {
5288          case 4:
5289            output_asm_insn (\"b%d0\\t%l1\", cond);
5290            return \"\";
5291          case 6:
5292            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
5293            return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
5294          default:
5295            output_asm_insn (\"b%D0\\t.LCB%=\", cond);
5296            return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5297        }
5298    }
5299   "
5300   [(set (attr "far_jump")
5301         (if_then_else
5302             (ior (and (eq (symbol_ref ("which_alternative"))
5303                           (const_int 0))
5304                       (eq_attr "length" "8"))
5305                  (eq_attr "length" "10"))
5306             (const_string "yes")
5307             (const_string "no")))
5308    (set_attr_alternative "length"
5309       [
5310        ;; Alternative 0
5311        (if_then_else
5312          (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5313               (le (minus (match_dup 4) (pc)) (const_int 256)))
5314          (const_int 4)
5315          (if_then_else
5316            (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5317                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5318            (const_int 6)
5319            (const_int 8)))
5320        ;; Alternative 1
5321        (if_then_else
5322          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5323               (le (minus (match_dup 4) (pc)) (const_int 256)))
5324          (const_int 6)
5325          (if_then_else
5326            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5327                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5328            (const_int 8)
5329            (const_int 10)))
5330        ;; Alternative 2
5331        (if_then_else
5332          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5333               (le (minus (match_dup 4) (pc)) (const_int 256)))
5334          (const_int 6)
5335          (if_then_else
5336            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5337                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5338            (const_int 8)
5339            (const_int 10)))
5340        ;; Alternative 3
5341        (if_then_else
5342          (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5343               (le (minus (match_dup 4) (pc)) (const_int 256)))
5344          (const_int 6)
5345          (if_then_else
5346            (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5347                 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5348            (const_int 8)
5349            (const_int 10)))])]
5352 ;; Comparison and test insns
5354 (define_expand "cmpsi"
5355   [(match_operand:SI 0 "s_register_operand" "")
5356    (match_operand:SI 1 "arm_add_operand" "")]
5357   "TARGET_ARM"
5358   "{
5359     arm_compare_op0 = operands[0];
5360     arm_compare_op1 = operands[1];
5361     DONE;
5362   }"
5365 (define_expand "cmpsf"
5366   [(match_operand:SF 0 "s_register_operand" "")
5367    (match_operand:SF 1 "fpa_rhs_operand" "")]
5368   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5369   "
5370   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5371     operands[1] = force_reg (SFmode, operands[1]);
5373   arm_compare_op0 = operands[0];
5374   arm_compare_op1 = operands[1];
5375   DONE;
5376   "
5379 (define_expand "cmpdf"
5380   [(match_operand:DF 0 "s_register_operand" "")
5381    (match_operand:DF 1 "fpa_rhs_operand" "")]
5382   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5383   "
5384   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5385     operands[1] = force_reg (DFmode, operands[1]);
5387   arm_compare_op0 = operands[0];
5388   arm_compare_op1 = operands[1];
5389   DONE;
5390   "
5393 (define_insn "*arm_cmpsi_insn"
5394   [(set (reg:CC CC_REGNUM)
5395         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5396                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5397   "TARGET_ARM"
5398   "@
5399    cmp%?\\t%0, %1
5400    cmn%?\\t%0, #%n1"
5401   [(set_attr "conds" "set")]
5404 (define_insn "*cmpsi_shiftsi"
5405   [(set (reg:CC CC_REGNUM)
5406         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
5407                     (match_operator:SI  3 "shift_operator"
5408                      [(match_operand:SI 1 "s_register_operand" "r")
5409                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5410   "TARGET_ARM"
5411   "cmp%?\\t%0, %1%S3"
5412   [(set_attr "conds" "set")
5413    (set_attr "shift" "1")
5414    ]
5417 (define_insn "*cmpsi_shiftsi_swp"
5418   [(set (reg:CC_SWP CC_REGNUM)
5419         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5420                          [(match_operand:SI 1 "s_register_operand" "r")
5421                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
5422                         (match_operand:SI 0 "s_register_operand" "r")))]
5423   "TARGET_ARM"
5424   "cmp%?\\t%0, %1%S3"
5425   [(set_attr "conds" "set")
5426    (set_attr "shift" "1")
5427    ]
5430 (define_insn "*cmpsi_neg_shiftsi"
5431   [(set (reg:CC CC_REGNUM)
5432         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5433                     (neg:SI (match_operator:SI 3 "shift_operator"
5434                              [(match_operand:SI 1 "s_register_operand" "r")
5435                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5436   "TARGET_ARM"
5437   "cmn%?\\t%0, %1%S3"
5438   [(set_attr "conds" "set")
5439    (set_attr "shift" "1")
5440    ]
5443 ;; Cirrus SF compare instruction
5444 (define_insn "*cirrus_cmpsf"
5445   [(set (reg:CCFP CC_REGNUM)
5446         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5447                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
5448   "TARGET_ARM && TARGET_CIRRUS"
5449   "cfcmps%?\\tr15, %V0, %V1"
5450   [(set_attr "type"   "mav_farith")
5451    (set_attr "cirrus" "compare")]
5454 ;; Cirrus DF compare instruction
5455 (define_insn "*cirrus_cmpdf"
5456   [(set (reg:CCFP CC_REGNUM)
5457         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5458                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
5459   "TARGET_ARM && TARGET_CIRRUS"
5460   "cfcmpd%?\\tr15, %V0, %V1"
5461   [(set_attr "type"   "mav_farith")
5462    (set_attr "cirrus" "compare")]
5465 ;; Cirrus DI compare instruction
5466 (define_expand "cmpdi"
5467   [(match_operand:DI 0 "cirrus_fp_register" "")
5468    (match_operand:DI 1 "cirrus_fp_register" "")]
5469   "TARGET_ARM && TARGET_CIRRUS"
5470   "{
5471      arm_compare_op0 = operands[0];
5472      arm_compare_op1 = operands[1];
5473      DONE;
5474    }")
5476 (define_insn "*cirrus_cmpdi"
5477   [(set (reg:CC CC_REGNUM)
5478         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5479                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
5480   "TARGET_ARM && TARGET_CIRRUS"
5481   "cfcmp64%?\\tr15, %V0, %V1"
5482   [(set_attr "type"   "mav_farith")
5483    (set_attr "cirrus" "compare")]
5486 ; This insn allows redundant compares to be removed by cse, nothing should
5487 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5488 ; is deleted later on. The match_dup will match the mode here, so that
5489 ; mode changes of the condition codes aren't lost by this even though we don't
5490 ; specify what they are.
5492 (define_insn "*deleted_compare"
5493   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5494   "TARGET_ARM"
5495   "\\t%@ deleted compare"
5496   [(set_attr "conds" "set")
5497    (set_attr "length" "0")]
5501 ;; Conditional branch insns
5503 (define_expand "beq"
5504   [(set (pc)
5505         (if_then_else (eq (match_dup 1) (const_int 0))
5506                       (label_ref (match_operand 0 "" ""))
5507                       (pc)))]
5508   "TARGET_ARM"
5509   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5512 (define_expand "bne"
5513   [(set (pc)
5514         (if_then_else (ne (match_dup 1) (const_int 0))
5515                       (label_ref (match_operand 0 "" ""))
5516                       (pc)))]
5517   "TARGET_ARM"
5518   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5521 (define_expand "bgt"
5522   [(set (pc)
5523         (if_then_else (gt (match_dup 1) (const_int 0))
5524                       (label_ref (match_operand 0 "" ""))
5525                       (pc)))]
5526   "TARGET_ARM"
5527   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5530 (define_expand "ble"
5531   [(set (pc)
5532         (if_then_else (le (match_dup 1) (const_int 0))
5533                       (label_ref (match_operand 0 "" ""))
5534                       (pc)))]
5535   "TARGET_ARM"
5536   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5539 (define_expand "bge"
5540   [(set (pc)
5541         (if_then_else (ge (match_dup 1) (const_int 0))
5542                       (label_ref (match_operand 0 "" ""))
5543                       (pc)))]
5544   "TARGET_ARM"
5545   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5548 (define_expand "blt"
5549   [(set (pc)
5550         (if_then_else (lt (match_dup 1) (const_int 0))
5551                       (label_ref (match_operand 0 "" ""))
5552                       (pc)))]
5553   "TARGET_ARM"
5554   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5557 (define_expand "bgtu"
5558   [(set (pc)
5559         (if_then_else (gtu (match_dup 1) (const_int 0))
5560                       (label_ref (match_operand 0 "" ""))
5561                       (pc)))]
5562   "TARGET_ARM"
5563   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5566 (define_expand "bleu"
5567   [(set (pc)
5568         (if_then_else (leu (match_dup 1) (const_int 0))
5569                       (label_ref (match_operand 0 "" ""))
5570                       (pc)))]
5571   "TARGET_ARM"
5572   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5575 (define_expand "bgeu"
5576   [(set (pc)
5577         (if_then_else (geu (match_dup 1) (const_int 0))
5578                       (label_ref (match_operand 0 "" ""))
5579                       (pc)))]
5580   "TARGET_ARM"
5581   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5584 (define_expand "bltu"
5585   [(set (pc)
5586         (if_then_else (ltu (match_dup 1) (const_int 0))
5587                       (label_ref (match_operand 0 "" ""))
5588                       (pc)))]
5589   "TARGET_ARM"
5590   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5593 (define_expand "bunordered"
5594   [(set (pc)
5595         (if_then_else (unordered (match_dup 1) (const_int 0))
5596                       (label_ref (match_operand 0 "" ""))
5597                       (pc)))]
5598   "TARGET_ARM && TARGET_HARD_FLOAT"
5599   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5600                                       arm_compare_op1);"
5603 (define_expand "bordered"
5604   [(set (pc)
5605         (if_then_else (ordered (match_dup 1) (const_int 0))
5606                       (label_ref (match_operand 0 "" ""))
5607                       (pc)))]
5608   "TARGET_ARM && TARGET_HARD_FLOAT"
5609   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5610                                       arm_compare_op1);"
5613 (define_expand "bungt"
5614   [(set (pc)
5615         (if_then_else (ungt (match_dup 1) (const_int 0))
5616                       (label_ref (match_operand 0 "" ""))
5617                       (pc)))]
5618   "TARGET_ARM && TARGET_HARD_FLOAT"
5619   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5622 (define_expand "bunlt"
5623   [(set (pc)
5624         (if_then_else (unlt (match_dup 1) (const_int 0))
5625                       (label_ref (match_operand 0 "" ""))
5626                       (pc)))]
5627   "TARGET_ARM && TARGET_HARD_FLOAT"
5628   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5631 (define_expand "bunge"
5632   [(set (pc)
5633         (if_then_else (unge (match_dup 1) (const_int 0))
5634                       (label_ref (match_operand 0 "" ""))
5635                       (pc)))]
5636   "TARGET_ARM && TARGET_HARD_FLOAT"
5637   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5640 (define_expand "bunle"
5641   [(set (pc)
5642         (if_then_else (unle (match_dup 1) (const_int 0))
5643                       (label_ref (match_operand 0 "" ""))
5644                       (pc)))]
5645   "TARGET_ARM && TARGET_HARD_FLOAT"
5646   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5649 ;; The following two patterns need two branch instructions, since there is
5650 ;; no single instruction that will handle all cases.
5651 (define_expand "buneq"
5652   [(set (pc)
5653         (if_then_else (uneq (match_dup 1) (const_int 0))
5654                       (label_ref (match_operand 0 "" ""))
5655                       (pc)))]
5656   "TARGET_ARM && TARGET_HARD_FLOAT"
5657   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5660 (define_expand "bltgt"
5661   [(set (pc)
5662         (if_then_else (ltgt (match_dup 1) (const_int 0))
5663                       (label_ref (match_operand 0 "" ""))
5664                       (pc)))]
5665   "TARGET_ARM && TARGET_HARD_FLOAT"
5666   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5670 ;; Patterns to match conditional branch insns.
5673 ; Special pattern to match UNEQ.
5674 (define_insn "*arm_buneq"
5675   [(set (pc)
5676         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5677                       (label_ref (match_operand 0 "" ""))
5678                       (pc)))]
5679   "TARGET_ARM && TARGET_HARD_FLOAT"
5680   "*
5681   if (arm_ccfsm_state != 0)
5682     abort ();
5684   return \"bvs\\t%l0\;beq\\t%l0\";
5685   "
5686   [(set_attr "conds" "jump_clob")
5687    (set_attr "length" "8")]
5690 ; Special pattern to match LTGT.
5691 (define_insn "*arm_bltgt"
5692   [(set (pc)
5693         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5694                       (label_ref (match_operand 0 "" ""))
5695                       (pc)))]
5696   "TARGET_ARM && TARGET_HARD_FLOAT"
5697   "*
5698   if (arm_ccfsm_state != 0)
5699     abort ();
5701   return \"bmi\\t%l0\;bgt\\t%l0\";
5702   "
5703   [(set_attr "conds" "jump_clob")
5704    (set_attr "length" "8")]
5707 (define_insn "*arm_cond_branch"
5708   [(set (pc)
5709         (if_then_else (match_operator 1 "arm_comparison_operator"
5710                        [(match_operand 2 "cc_register" "") (const_int 0)])
5711                       (label_ref (match_operand 0 "" ""))
5712                       (pc)))]
5713   "TARGET_ARM"
5714   "*
5715   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5716     {
5717       arm_ccfsm_state += 2;
5718       return \"\";
5719     }
5720   return \"b%d1\\t%l0\";
5721   "
5722   [(set_attr "conds" "use")]
5725 ; Special pattern to match reversed UNEQ.
5726 (define_insn "*arm_buneq_reversed"
5727   [(set (pc)
5728         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5729                       (pc)
5730                       (label_ref (match_operand 0 "" ""))))]
5731   "TARGET_ARM && TARGET_HARD_FLOAT"
5732   "*
5733   if (arm_ccfsm_state != 0)
5734     abort ();
5736   return \"bmi\\t%l0\;bgt\\t%l0\";
5737   "
5738   [(set_attr "conds" "jump_clob")
5739    (set_attr "length" "8")]
5742 ; Special pattern to match reversed LTGT.
5743 (define_insn "*arm_bltgt_reversed"
5744   [(set (pc)
5745         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5746                       (pc)
5747                       (label_ref (match_operand 0 "" ""))))]
5748   "TARGET_ARM && TARGET_HARD_FLOAT"
5749   "*
5750   if (arm_ccfsm_state != 0)
5751     abort ();
5753   return \"bvs\\t%l0\;beq\\t%l0\";
5754   "
5755   [(set_attr "conds" "jump_clob")
5756    (set_attr "length" "8")]
5759 (define_insn "*arm_cond_branch_reversed"
5760   [(set (pc)
5761         (if_then_else (match_operator 1 "arm_comparison_operator"
5762                        [(match_operand 2 "cc_register" "") (const_int 0)])
5763                       (pc)
5764                       (label_ref (match_operand 0 "" ""))))]
5765   "TARGET_ARM"
5766   "*
5767   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5768     {
5769       arm_ccfsm_state += 2;
5770       return \"\";
5771     }
5772   return \"b%D1\\t%l0\";
5773   "
5774   [(set_attr "conds" "use")]
5779 ; scc insns
5781 (define_expand "seq"
5782   [(set (match_operand:SI 0 "s_register_operand" "")
5783         (eq:SI (match_dup 1) (const_int 0)))]
5784   "TARGET_ARM"
5785   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5788 (define_expand "sne"
5789   [(set (match_operand:SI 0 "s_register_operand" "")
5790         (ne:SI (match_dup 1) (const_int 0)))]
5791   "TARGET_ARM"
5792   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5795 (define_expand "sgt"
5796   [(set (match_operand:SI 0 "s_register_operand" "")
5797         (gt:SI (match_dup 1) (const_int 0)))]
5798   "TARGET_ARM"
5799   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5802 (define_expand "sle"
5803   [(set (match_operand:SI 0 "s_register_operand" "")
5804         (le:SI (match_dup 1) (const_int 0)))]
5805   "TARGET_ARM"
5806   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5809 (define_expand "sge"
5810   [(set (match_operand:SI 0 "s_register_operand" "")
5811         (ge:SI (match_dup 1) (const_int 0)))]
5812   "TARGET_ARM"
5813   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5816 (define_expand "slt"
5817   [(set (match_operand:SI 0 "s_register_operand" "")
5818         (lt:SI (match_dup 1) (const_int 0)))]
5819   "TARGET_ARM"
5820   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5823 (define_expand "sgtu"
5824   [(set (match_operand:SI 0 "s_register_operand" "")
5825         (gtu:SI (match_dup 1) (const_int 0)))]
5826   "TARGET_ARM"
5827   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5830 (define_expand "sleu"
5831   [(set (match_operand:SI 0 "s_register_operand" "")
5832         (leu:SI (match_dup 1) (const_int 0)))]
5833   "TARGET_ARM"
5834   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5837 (define_expand "sgeu"
5838   [(set (match_operand:SI 0 "s_register_operand" "")
5839         (geu:SI (match_dup 1) (const_int 0)))]
5840   "TARGET_ARM"
5841   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5844 (define_expand "sltu"
5845   [(set (match_operand:SI 0 "s_register_operand" "")
5846         (ltu:SI (match_dup 1) (const_int 0)))]
5847   "TARGET_ARM"
5848   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5851 (define_expand "sunordered"
5852   [(set (match_operand:SI 0 "s_register_operand" "")
5853         (unordered:SI (match_dup 1) (const_int 0)))]
5854   "TARGET_ARM && TARGET_HARD_FLOAT"
5855   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5856                                       arm_compare_op1);"
5859 (define_expand "sordered"
5860   [(set (match_operand:SI 0 "s_register_operand" "")
5861         (ordered:SI (match_dup 1) (const_int 0)))]
5862   "TARGET_ARM && TARGET_HARD_FLOAT"
5863   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5864                                       arm_compare_op1);"
5867 (define_expand "sungt"
5868   [(set (match_operand:SI 0 "s_register_operand" "")
5869         (ungt:SI (match_dup 1) (const_int 0)))]
5870   "TARGET_ARM && TARGET_HARD_FLOAT"
5871   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
5872                                       arm_compare_op1);"
5875 (define_expand "sunge"
5876   [(set (match_operand:SI 0 "s_register_operand" "")
5877         (unge:SI (match_dup 1) (const_int 0)))]
5878   "TARGET_ARM && TARGET_HARD_FLOAT"
5879   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
5880                                       arm_compare_op1);"
5883 (define_expand "sunlt"
5884   [(set (match_operand:SI 0 "s_register_operand" "")
5885         (unlt:SI (match_dup 1) (const_int 0)))]
5886   "TARGET_ARM && TARGET_HARD_FLOAT"
5887   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
5888                                       arm_compare_op1);"
5891 (define_expand "sunle"
5892   [(set (match_operand:SI 0 "s_register_operand" "")
5893         (unle:SI (match_dup 1) (const_int 0)))]
5894   "TARGET_ARM && TARGET_HARD_FLOAT"
5895   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
5896                                       arm_compare_op1);"
5899 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
5900 ;;; simple ARM instructions. 
5902 ; (define_expand "suneq"
5903 ;   [(set (match_operand:SI 0 "s_register_operand" "")
5904 ;       (uneq:SI (match_dup 1) (const_int 0)))]
5905 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
5906 ;   "abort ();"
5907 ; )
5909 ; (define_expand "sltgt"
5910 ;   [(set (match_operand:SI 0 "s_register_operand" "")
5911 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
5912 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
5913 ;   "abort ();"
5914 ; )
5916 (define_insn "*mov_scc"
5917   [(set (match_operand:SI 0 "s_register_operand" "=r")
5918         (match_operator:SI 1 "arm_comparison_operator"
5919          [(match_operand 2 "cc_register" "") (const_int 0)]))]
5920   "TARGET_ARM"
5921   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
5922   [(set_attr "conds" "use")
5923    (set_attr "length" "8")]
5926 (define_insn "*mov_negscc"
5927   [(set (match_operand:SI 0 "s_register_operand" "=r")
5928         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
5929                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
5930   "TARGET_ARM"
5931   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
5932   [(set_attr "conds" "use")
5933    (set_attr "length" "8")]
5936 (define_insn "*mov_notscc"
5937   [(set (match_operand:SI 0 "s_register_operand" "=r")
5938         (not:SI (match_operator:SI 1 "arm_comparison_operator"
5939                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
5940   "TARGET_ARM"
5941   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
5942   [(set_attr "conds" "use")
5943    (set_attr "length" "8")]
5947 ;; Conditional move insns
5949 (define_expand "movsicc"
5950   [(set (match_operand:SI 0 "s_register_operand" "")
5951         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
5952                          (match_operand:SI 2 "arm_not_operand" "")
5953                          (match_operand:SI 3 "arm_not_operand" "")))]
5954   "TARGET_ARM"
5955   "
5956   {
5957     enum rtx_code code = GET_CODE (operands[1]);
5958     rtx ccreg;
5960     if (code == UNEQ || code == LTGT)
5961       FAIL;
5963     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5964     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5965   }"
5968 (define_expand "movsfcc"
5969   [(set (match_operand:SF 0 "s_register_operand" "")
5970         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
5971                          (match_operand:SF 2 "s_register_operand" "")
5972                          (match_operand:SF 3 "nonmemory_operand" "")))]
5973   "TARGET_ARM"
5974   "
5975   {
5976     enum rtx_code code = GET_CODE (operands[1]);
5977     rtx ccreg;
5979     if (code == UNEQ || code == LTGT)
5980       FAIL;
5982     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
5983        Otherwise, ensure it is a valid FP add operand */
5984     if ((!TARGET_HARD_FLOAT)
5985         || (!fpa_add_operand (operands[3], SFmode)))
5986       operands[3] = force_reg (SFmode, operands[3]);
5988     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5989     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5990   }"
5993 (define_expand "movdfcc"
5994   [(set (match_operand:DF 0 "s_register_operand" "")
5995         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
5996                          (match_operand:DF 2 "s_register_operand" "")
5997                          (match_operand:DF 3 "fpa_add_operand" "")))]
5998   "TARGET_ARM && TARGET_HARD_FLOAT"
5999   "
6000   {
6001     enum rtx_code code = GET_CODE (operands[1]);
6002     rtx ccreg;
6004     if (code == UNEQ || code == LTGT)
6005       FAIL;
6007     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6008     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6009   }"
6012 (define_insn "*movsicc_insn"
6013   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6014         (if_then_else:SI
6015          (match_operator 3 "arm_comparison_operator"
6016           [(match_operand 4 "cc_register" "") (const_int 0)])
6017          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6018          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6019   "TARGET_ARM"
6020   "@
6021    mov%D3\\t%0, %2
6022    mvn%D3\\t%0, #%B2
6023    mov%d3\\t%0, %1
6024    mvn%d3\\t%0, #%B1
6025    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6026    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6027    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6028    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6029   [(set_attr "length" "4,4,4,4,8,8,8,8")
6030    (set_attr "conds" "use")]
6033 (define_insn "*movsfcc_soft_insn"
6034   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6035         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6036                           [(match_operand 4 "cc_register" "") (const_int 0)])
6037                          (match_operand:SF 1 "s_register_operand" "0,r")
6038                          (match_operand:SF 2 "s_register_operand" "r,0")))]
6039   "TARGET_ARM && TARGET_SOFT_FLOAT"
6040   "@
6041    mov%D3\\t%0, %2
6042    mov%d3\\t%0, %1"
6043   [(set_attr "conds" "use")]
6047 ;; Jump and linkage insns
6049 (define_expand "jump"
6050   [(set (pc)
6051         (label_ref (match_operand 0 "" "")))]
6052   "TARGET_EITHER"
6053   ""
6056 (define_insn "*arm_jump"
6057   [(set (pc)
6058         (label_ref (match_operand 0 "" "")))]
6059   "TARGET_ARM"
6060   "*
6061   {
6062     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6063       {
6064         arm_ccfsm_state += 2;
6065         return \"\";
6066       }
6067     return \"b%?\\t%l0\";
6068   }
6069   "
6070   [(set_attr "predicable" "yes")]
6073 (define_insn "*thumb_jump"
6074   [(set (pc)
6075         (label_ref (match_operand 0 "" "")))]
6076   "TARGET_THUMB"
6077   "*
6078   if (get_attr_length (insn) == 2)
6079     return \"b\\t%l0\";
6080   return \"bl\\t%l0\\t%@ far jump\";
6081   "
6082   [(set (attr "far_jump")
6083         (if_then_else
6084             (eq_attr "length" "4")
6085             (const_string "yes")
6086             (const_string "no")))
6087    (set (attr "length") 
6088         (if_then_else
6089             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6090                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
6091             (const_int 2)
6092             (const_int 4)))]
6095 (define_expand "call"
6096   [(parallel [(call (match_operand 0 "memory_operand" "")
6097                     (match_operand 1 "general_operand" ""))
6098               (use (match_operand 2 "" ""))
6099               (clobber (reg:SI LR_REGNUM))])]
6100   "TARGET_EITHER"
6101   "
6102   {
6103     rtx callee;
6104     
6105     /* In an untyped call, we can get NULL for operand 2.  */
6106     if (operands[2] == NULL_RTX)
6107       operands[2] = const0_rtx;
6108       
6109     /* This is to decide if we should generate indirect calls by loading the
6110        32 bit address of the callee into a register before performing the
6111        branch and link.  operand[2] encodes the long_call/short_call
6112        attribute of the function being called.  This attribute is set whenever
6113        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6114        is used, and the short_call attribute can also be set if function is
6115        declared as static or if it has already been defined in the current
6116        compilation unit.  See arm.c and arm.h for info about this.  The third
6117        parameter to arm_is_longcall_p is used to tell it which pattern
6118        invoked it.  */
6119     callee  = XEXP (operands[0], 0);
6120     
6121     if (GET_CODE (callee) != REG
6122        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6123       XEXP (operands[0], 0) = force_reg (Pmode, callee);
6124   }"
6127 (define_insn "*call_reg"
6128   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6129          (match_operand 1 "" ""))
6130    (use (match_operand 2 "" ""))
6131    (clobber (reg:SI LR_REGNUM))]
6132   "TARGET_ARM"
6133   "*
6134   return output_call (operands);
6135   "
6136   ;; length is worst case, normally it is only two
6137   [(set_attr "length" "12")
6138    (set_attr "type" "call")]
6141 (define_insn "*call_mem"
6142   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6143          (match_operand 1 "" ""))
6144    (use (match_operand 2 "" ""))
6145    (clobber (reg:SI LR_REGNUM))]
6146   "TARGET_ARM"
6147   "*
6148   return output_call_mem (operands);
6149   "
6150   [(set_attr "length" "12")
6151    (set_attr "type" "call")]
6154 (define_insn "*call_indirect"
6155   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6156          (match_operand 1 "" ""))
6157    (use (match_operand 2 "" ""))
6158    (clobber (reg:SI LR_REGNUM))]
6159   "TARGET_THUMB"
6160   "*
6161   {
6162     if (TARGET_CALLER_INTERWORKING)
6163       return \"bl\\t%__interwork_call_via_%0\";
6164     else
6165       return \"bl\\t%__call_via_%0\";
6166   }"
6167   [(set_attr "type" "call")]
6170 (define_insn "*call_value_indirect"
6171   [(set (match_operand 0 "" "")
6172         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6173               (match_operand 2 "" "")))
6174    (use (match_operand 3 "" ""))
6175    (clobber (reg:SI LR_REGNUM))]
6176   "TARGET_THUMB"
6177   "*
6178   {
6179     if (TARGET_CALLER_INTERWORKING)
6180       return \"bl\\t%__interwork_call_via_%1\";
6181     else
6182       return \"bl\\t%__call_via_%1\";
6183   }"
6184   [(set_attr "type" "call")]
6187 (define_expand "call_value"
6188   [(parallel [(set (match_operand       0 "" "")
6189                    (call (match_operand 1 "memory_operand" "")
6190                          (match_operand 2 "general_operand" "")))
6191               (use (match_operand 3 "" ""))
6192               (clobber (reg:SI LR_REGNUM))])]
6193   "TARGET_EITHER"
6194   "
6195   {
6196     rtx callee = XEXP (operands[1], 0);
6197     
6198     /* In an untyped call, we can get NULL for operand 2.  */
6199     if (operands[3] == 0)
6200       operands[3] = const0_rtx;
6201       
6202     /* See the comment in define_expand \"call\".  */
6203     if (GET_CODE (callee) != REG
6204         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6205       XEXP (operands[1], 0) = force_reg (Pmode, callee);
6206   }"
6209 (define_insn "*call_value_reg"
6210   [(set (match_operand 0 "" "")
6211         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6212               (match_operand 2 "" "")))
6213    (use (match_operand 3 "" ""))
6214    (clobber (reg:SI LR_REGNUM))]
6215   "TARGET_ARM"
6216   "*
6217   return output_call (&operands[1]);
6218   "
6219   [(set_attr "length" "12")
6220    (set_attr "type" "call")]
6223 (define_insn "*call_value_mem"
6224   [(set (match_operand 0 "" "")
6225         (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
6226               (match_operand 2 "" "")))
6227    (use (match_operand 3 "" ""))
6228    (clobber (reg:SI LR_REGNUM))]
6229   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6230   "*
6231   return output_call_mem (&operands[1]);
6232   "
6233   [(set_attr "length" "12")
6234    (set_attr "type" "call")]
6237 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6238 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6240 (define_insn "*call_symbol"
6241   [(call (mem:SI (match_operand:SI 0 "" ""))
6242          (match_operand 1 "" ""))
6243    (use (match_operand 2 "" ""))
6244    (clobber (reg:SI LR_REGNUM))]
6245   "TARGET_ARM
6246    && (GET_CODE (operands[0]) == SYMBOL_REF)
6247    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6248   "*
6249   {
6250     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6251   }"
6252   [(set_attr "type" "call")]
6255 (define_insn "*call_value_symbol"
6256   [(set (match_operand 0 "s_register_operand" "")
6257         (call (mem:SI (match_operand:SI 1 "" ""))
6258         (match_operand:SI 2 "" "")))
6259    (use (match_operand 3 "" ""))
6260    (clobber (reg:SI LR_REGNUM))]
6261   "TARGET_ARM
6262    && (GET_CODE (operands[1]) == SYMBOL_REF)
6263    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6264   "*
6265   {
6266     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6267   }"
6268   [(set_attr "type" "call")]
6271 (define_insn "*call_insn"
6272   [(call (mem:SI (match_operand:SI 0 "" ""))
6273          (match_operand:SI 1 "" ""))
6274    (use (match_operand 2 "" ""))
6275    (clobber (reg:SI LR_REGNUM))]
6276   "TARGET_THUMB
6277    && GET_CODE (operands[0]) == SYMBOL_REF
6278    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6279   "bl\\t%a0"
6280   [(set_attr "length" "4")
6281    (set_attr "type" "call")]
6284 (define_insn "*call_value_insn"
6285   [(set (match_operand 0 "register_operand" "")
6286         (call (mem:SI (match_operand 1 "" ""))
6287               (match_operand 2 "" "")))
6288    (use (match_operand 3 "" ""))
6289    (clobber (reg:SI LR_REGNUM))]
6290   "TARGET_THUMB
6291    && GET_CODE (operands[1]) == SYMBOL_REF
6292    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6293   "bl\\t%a1"
6294   [(set_attr "length" "4")
6295    (set_attr "type" "call")]
6298 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6299 (define_expand "sibcall"
6300   [(parallel [(call (match_operand 0 "memory_operand" "")
6301                     (match_operand 1 "general_operand" ""))
6302               (return)
6303               (use (match_operand 2 "" ""))])]
6304   "TARGET_ARM"
6305   "
6306   {
6307     if (operands[2] == NULL_RTX)
6308       operands[2] = const0_rtx;
6309   }"
6312 (define_expand "sibcall_value"
6313   [(parallel [(set (match_operand 0 "register_operand" "")
6314                    (call (match_operand 1 "memory_operand" "")
6315                          (match_operand 2 "general_operand" "")))
6316               (return)
6317               (use (match_operand 3 "" ""))])]
6318   "TARGET_ARM"
6319   "
6320   {
6321     if (operands[3] == NULL_RTX)
6322       operands[3] = const0_rtx;
6323   }"
6326 (define_insn "*sibcall_insn"
6327  [(call (mem:SI (match_operand:SI 0 "" "X"))
6328         (match_operand 1 "" ""))
6329   (return)
6330   (use (match_operand 2 "" ""))]
6331   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6332   "*
6333   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6334   "
6335   [(set_attr "type" "call")]
6338 (define_insn "*sibcall_value_insn"
6339  [(set (match_operand 0 "s_register_operand" "")
6340        (call (mem:SI (match_operand:SI 1 "" "X"))
6341              (match_operand 2 "" "")))
6342   (return)
6343   (use (match_operand 3 "" ""))]
6344   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6345   "*
6346   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6347   "
6348   [(set_attr "type" "call")]
6351 ;; Often the return insn will be the same as loading from memory, so set attr
6352 (define_insn "return"
6353   [(return)]
6354   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6355   "*
6356   {
6357     if (arm_ccfsm_state == 2)
6358       {
6359         arm_ccfsm_state += 2;
6360         return \"\";
6361       }
6362     return output_return_instruction (const_true_rtx, TRUE, FALSE);
6363   }"
6364   [(set_attr "type" "load")
6365    (set_attr "length" "12")
6366    (set_attr "predicable" "yes")]
6369 (define_insn "*cond_return"
6370   [(set (pc)
6371         (if_then_else (match_operator 0 "arm_comparison_operator"
6372                        [(match_operand 1 "cc_register" "") (const_int 0)])
6373                       (return)
6374                       (pc)))]
6375   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6376   "*
6377   {
6378     if (arm_ccfsm_state == 2)
6379       {
6380         arm_ccfsm_state += 2;
6381         return \"\";
6382       }
6383     return output_return_instruction (operands[0], TRUE, FALSE);
6384   }"
6385   [(set_attr "conds" "use")
6386    (set_attr "length" "12")
6387    (set_attr "type" "load")]
6390 (define_insn "*cond_return_inverted"
6391   [(set (pc)
6392         (if_then_else (match_operator 0 "arm_comparison_operator"
6393                        [(match_operand 1 "cc_register" "") (const_int 0)])
6394                       (pc)
6395                       (return)))]
6396   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6397   "*
6398   {
6399     if (arm_ccfsm_state == 2)
6400       {
6401         arm_ccfsm_state += 2;
6402         return \"\";
6403       }
6404     return output_return_instruction (operands[0], TRUE, TRUE);
6405   }"
6406   [(set_attr "conds" "use")
6407    (set_attr "type" "load")]
6410 ;; Generate a sequence of instructions to determine if the processor is
6411 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6412 ;; mask.
6414 (define_expand "return_addr_mask"
6415   [(set (match_dup 1)
6416       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6417                        (const_int 0)))
6418    (set (match_operand:SI 0 "s_register_operand" "")
6419       (if_then_else:SI (eq (match_dup 1) (const_int 0))
6420                        (const_int -1)
6421                        (const_int 67108860)))] ; 0x03fffffc
6422   "TARGET_ARM"
6423   "
6424   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6425   ")
6427 (define_insn "*check_arch2"
6428   [(set (match_operand:CC_NOOV 0 "cc_register" "")
6429       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6430                        (const_int 0)))]
6431   "TARGET_ARM"
6432   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6433   [(set_attr "length" "8")
6434    (set_attr "conds" "set")]
6437 ;; Call subroutine returning any type.
6439 (define_expand "untyped_call"
6440   [(parallel [(call (match_operand 0 "" "")
6441                     (const_int 0))
6442               (match_operand 1 "" "")
6443               (match_operand 2 "" "")])]
6444   "TARGET_ARM"
6445   "
6446   {
6447     int i;
6449     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6451     for (i = 0; i < XVECLEN (operands[2], 0); i++)
6452       {
6453         rtx set = XVECEXP (operands[2], 0, i);
6455         emit_move_insn (SET_DEST (set), SET_SRC (set));
6456       }
6458     /* The optimizer does not know that the call sets the function value
6459        registers we stored in the result block.  We avoid problems by
6460        claiming that all hard registers are used and clobbered at this
6461        point.  */
6462     emit_insn (gen_blockage ());
6464     DONE;
6465   }"
6468 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6469 ;; all of memory.  This blocks insns from being moved across this point.
6471 (define_insn "blockage"
6472   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6473   "TARGET_EITHER"
6474   ""
6475   [(set_attr "length" "0")
6476    (set_attr "type" "block")]
6479 (define_expand "casesi"
6480   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6481    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
6482    (match_operand:SI 2 "const_int_operand" "")  ; total range
6483    (match_operand:SI 3 "" "")                   ; table label
6484    (match_operand:SI 4 "" "")]                  ; Out of range label
6485   "TARGET_ARM"
6486   "
6487   {
6488     rtx reg;
6489     if (operands[1] != const0_rtx)
6490       {
6491         reg = gen_reg_rtx (SImode);
6493         emit_insn (gen_addsi3 (reg, operands[0],
6494                                GEN_INT (-INTVAL (operands[1]))));
6495         operands[0] = reg;
6496       }
6498     if (!const_ok_for_arm (INTVAL (operands[2])))
6499       operands[2] = force_reg (SImode, operands[2]);
6501     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6502                                          operands[4]));
6503     DONE;
6504   }"
6507 ;; The USE in this pattern is needed to tell flow analysis that this is
6508 ;; a CASESI insn.  It has no other purpose.
6509 (define_insn "casesi_internal"
6510   [(parallel [(set (pc)
6511                (if_then_else
6512                 (leu (match_operand:SI 0 "s_register_operand" "r")
6513                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
6514                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6515                                  (label_ref (match_operand 2 "" ""))))
6516                 (label_ref (match_operand 3 "" ""))))
6517               (clobber (reg:CC CC_REGNUM))
6518               (use (label_ref (match_dup 2)))])]
6519   "TARGET_ARM"
6520   "*
6521     if (flag_pic)
6522       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6523     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6524   "
6525   [(set_attr "conds" "clob")
6526    (set_attr "length" "12")]
6529 (define_expand "indirect_jump"
6530   [(set (pc)
6531         (match_operand:SI 0 "s_register_operand" ""))]
6532   "TARGET_EITHER"
6533   ""
6536 (define_insn "*arm_indirect_jump"
6537   [(set (pc)
6538         (match_operand:SI 0 "s_register_operand" "r"))]
6539   "TARGET_ARM"
6540   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6541   [(set_attr "predicable" "yes")]
6544 ;; Although not supported by the define_expand above,
6545 ;; cse/combine may generate this form.
6546 (define_insn "*load_indirect_jump"
6547   [(set (pc)
6548         (match_operand:SI 0 "memory_operand" "m"))]
6549   "TARGET_ARM"
6550   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6551   [(set_attr "type" "load")
6552    (set_attr "pool_range" "4096")
6553    (set_attr "neg_pool_range" "4084")
6554    (set_attr "predicable" "yes")]
6557 (define_insn "*thumb_indirect_jump"
6558   [(set (pc)
6559         (match_operand:SI 0 "register_operand" "l*r"))]
6560   "TARGET_THUMB"
6561   "mov\\tpc, %0"
6562   [(set_attr "conds" "clob")
6563    (set_attr "length" "2")]
6567 ;; Misc insns
6569 (define_insn "nop"
6570   [(const_int 0)]
6571   "TARGET_EITHER"
6572   "*
6573   if (TARGET_ARM)
6574     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6575   return  \"mov\\tr8, r8\";
6576   "
6577   [(set (attr "length")
6578         (if_then_else (eq_attr "is_thumb" "yes")
6579                       (const_int 2)
6580                       (const_int 4)))]
6584 ;; Patterns to allow combination of arithmetic, cond code and shifts
6586 (define_insn "*arith_shiftsi"
6587   [(set (match_operand:SI 0 "s_register_operand" "=r")
6588         (match_operator:SI 1 "shiftable_operator"
6589           [(match_operator:SI 3 "shift_operator"
6590              [(match_operand:SI 4 "s_register_operand" "r")
6591               (match_operand:SI 5 "reg_or_int_operand" "rI")])
6592            (match_operand:SI 2 "s_register_operand" "r")]))]
6593   "TARGET_ARM"
6594   "%i1%?\\t%0, %2, %4%S3"
6595   [(set_attr "predicable" "yes")
6596    (set_attr "shift" "4")
6597    ]
6600 (define_insn "*arith_shiftsi_compare0"
6601   [(set (reg:CC_NOOV CC_REGNUM)
6602         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6603                           [(match_operator:SI 3 "shift_operator"
6604                             [(match_operand:SI 4 "s_register_operand" "r")
6605                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6606                            (match_operand:SI 2 "s_register_operand" "r")])
6607                          (const_int 0)))
6608    (set (match_operand:SI 0 "s_register_operand" "=r")
6609         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6610                          (match_dup 2)]))]
6611   "TARGET_ARM"
6612   "%i1%?s\\t%0, %2, %4%S3"
6613   [(set_attr "conds" "set")
6614    (set_attr "shift" "4")
6615    ]
6618 (define_insn "*arith_shiftsi_compare0_scratch"
6619   [(set (reg:CC_NOOV CC_REGNUM)
6620         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6621                           [(match_operator:SI 3 "shift_operator"
6622                             [(match_operand:SI 4 "s_register_operand" "r")
6623                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6624                            (match_operand:SI 2 "s_register_operand" "r")])
6625                          (const_int 0)))
6626    (clobber (match_scratch:SI 0 "=r"))]
6627   "TARGET_ARM"
6628   "%i1%?s\\t%0, %2, %4%S3"
6629   [(set_attr "conds" "set")
6630    (set_attr "shift" "4")
6631    ]
6634 (define_insn "*sub_shiftsi"
6635   [(set (match_operand:SI 0 "s_register_operand" "=r")
6636         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6637                   (match_operator:SI 2 "shift_operator"
6638                    [(match_operand:SI 3 "s_register_operand" "r")
6639                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6640   "TARGET_ARM"
6641   "sub%?\\t%0, %1, %3%S2"
6642   [(set_attr "predicable" "yes")
6643    (set_attr "shift" "3")
6644    ]
6647 (define_insn "*sub_shiftsi_compare0"
6648   [(set (reg:CC_NOOV CC_REGNUM)
6649         (compare:CC_NOOV
6650          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6651                    (match_operator:SI 2 "shift_operator"
6652                     [(match_operand:SI 3 "s_register_operand" "r")
6653                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6654          (const_int 0)))
6655    (set (match_operand:SI 0 "s_register_operand" "=r")
6656         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6657                                                  (match_dup 4)])))]
6658   "TARGET_ARM"
6659   "sub%?s\\t%0, %1, %3%S2"
6660   [(set_attr "conds" "set")
6661    (set_attr "shift" "3") 
6662    ]
6665 (define_insn "*sub_shiftsi_compare0_scratch"
6666   [(set (reg:CC_NOOV CC_REGNUM)
6667         (compare:CC_NOOV
6668          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6669                    (match_operator:SI 2 "shift_operator"
6670                     [(match_operand:SI 3 "s_register_operand" "r")
6671                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6672          (const_int 0)))
6673    (clobber (match_scratch:SI 0 "=r"))]
6674   "TARGET_ARM"
6675   "sub%?s\\t%0, %1, %3%S2"
6676   [(set_attr "conds" "set")
6677    (set_attr "shift" "3") 
6678    ]
6683 (define_insn "*and_scc"
6684   [(set (match_operand:SI 0 "s_register_operand" "=r")
6685         (and:SI (match_operator:SI 1 "arm_comparison_operator"
6686                  [(match_operand 3 "cc_register" "") (const_int 0)])
6687                 (match_operand:SI 2 "s_register_operand" "r")))]
6688   "TARGET_ARM"
6689   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6690   [(set_attr "conds" "use")
6691    (set_attr "length" "8")]
6694 (define_insn "*ior_scc"
6695   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6696         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6697                  [(match_operand 3 "cc_register" "") (const_int 0)])
6698                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6699   "TARGET_ARM"
6700   "@
6701    orr%d2\\t%0, %1, #1
6702    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6703   [(set_attr "conds" "use")
6704    (set_attr "length" "4,8")]
6707 (define_insn "*compare_scc"
6708   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6709         (match_operator:SI 1 "arm_comparison_operator"
6710          [(match_operand:SI 2 "s_register_operand" "r,r")
6711           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6712    (clobber (reg:CC CC_REGNUM))]
6713   "TARGET_ARM"
6714   "*
6715     if (operands[3] == const0_rtx)
6716       {
6717         if (GET_CODE (operands[1]) == LT)
6718           return \"mov\\t%0, %2, lsr #31\";
6720         if (GET_CODE (operands[1]) == GE)
6721           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6723         if (GET_CODE (operands[1]) == EQ)
6724           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
6725       }
6727     if (GET_CODE (operands[1]) == NE)
6728       {
6729         if (which_alternative == 1)
6730           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
6731         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
6732       }
6733     if (which_alternative == 1)
6734       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6735     else
6736       output_asm_insn (\"cmp\\t%2, %3\", operands);
6737     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
6738   "
6739   [(set_attr "conds" "clob")
6740    (set_attr "length" "12")]
6743 (define_insn "*cond_move"
6744   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6745         (if_then_else:SI (match_operator 3 "equality_operator"
6746                           [(match_operator 4 "arm_comparison_operator"
6747                             [(match_operand 5 "cc_register" "") (const_int 0)])
6748                            (const_int 0)])
6749                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6750                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
6751   "TARGET_ARM"
6752   "*
6753     if (GET_CODE (operands[3]) == NE)
6754       {
6755         if (which_alternative != 1)
6756           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
6757         if (which_alternative != 0)
6758           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6759         return \"\";
6760       }
6761     if (which_alternative != 0)
6762       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6763     if (which_alternative != 1)
6764       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
6765     return \"\";
6766   "
6767   [(set_attr "conds" "use")
6768    (set_attr "length" "4,4,8")]
6771 (define_insn "*cond_arith"
6772   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6773         (match_operator:SI 5 "shiftable_operator" 
6774          [(match_operator:SI 4 "arm_comparison_operator"
6775            [(match_operand:SI 2 "s_register_operand" "r,r")
6776             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
6777           (match_operand:SI 1 "s_register_operand" "0,?r")]))
6778    (clobber (reg:CC CC_REGNUM))]
6779   "TARGET_ARM"
6780   "*
6781     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
6782       return \"%i5\\t%0, %1, %2, lsr #31\";
6784     output_asm_insn (\"cmp\\t%2, %3\", operands);
6785     if (GET_CODE (operands[5]) == AND)
6786       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
6787     else if (GET_CODE (operands[5]) == MINUS)
6788       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
6789     else if (which_alternative != 0)
6790       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6791     return \"%i5%d4\\t%0, %1, #1\";
6792   "
6793   [(set_attr "conds" "clob")
6794    (set_attr "length" "12")]
6797 (define_insn "*cond_sub"
6798   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6799         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
6800                   (match_operator:SI 4 "arm_comparison_operator"
6801                    [(match_operand:SI 2 "s_register_operand" "r,r")
6802                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
6803    (clobber (reg:CC CC_REGNUM))]
6804   "TARGET_ARM"
6805   "*
6806     output_asm_insn (\"cmp\\t%2, %3\", operands);
6807     if (which_alternative != 0)
6808       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6809     return \"sub%d4\\t%0, %1, #1\";
6810   "
6811   [(set_attr "conds" "clob")
6812    (set_attr "length" "8,12")]
6815 (define_insn "*cmp_ite0"
6816   [(set (match_operand 6 "dominant_cc_register" "")
6817         (compare
6818          (if_then_else:SI
6819           (match_operator 4 "arm_comparison_operator"
6820            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6821             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6822           (match_operator:SI 5 "arm_comparison_operator"
6823            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6824             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6825           (const_int 0))
6826          (const_int 0)))]
6827   "TARGET_ARM"
6828   "*
6829   {
6830     static const char * const opcodes[4][2] =
6831     {
6832       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6833        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6834       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6835        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6836       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6837        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6838       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6839        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6840     };
6841     int swap =
6842       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6844     return opcodes[which_alternative][swap];
6845   }"
6846   [(set_attr "conds" "set")
6847    (set_attr "length" "8")]
6850 (define_insn "*cmp_ite1"
6851   [(set (match_operand 6 "dominant_cc_register" "")
6852         (compare
6853          (if_then_else:SI
6854           (match_operator 4 "arm_comparison_operator"
6855            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6856             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6857           (match_operator:SI 5 "arm_comparison_operator"
6858            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6859             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6860           (const_int 1))
6861          (const_int 0)))]
6862   "TARGET_ARM"
6863   "*
6864   {
6865     static const char * const opcodes[4][2] =
6866     {
6867       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
6868        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6869       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
6870        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6871       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
6872        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6873       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
6874        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6875     };
6876     int swap =
6877       comparison_dominates_p (GET_CODE (operands[5]),
6878                               reverse_condition (GET_CODE (operands[4])));
6880     return opcodes[which_alternative][swap];
6881   }"
6882   [(set_attr "conds" "set")
6883    (set_attr "length" "8")]
6886 (define_insn "*cmp_and"
6887   [(set (match_operand 6 "dominant_cc_register" "")
6888         (compare
6889          (and:SI
6890           (match_operator 4 "arm_comparison_operator"
6891            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6892             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6893           (match_operator:SI 5 "arm_comparison_operator"
6894            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6895             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6896          (const_int 0)))]
6897   "TARGET_ARM"
6898   "*
6899   {
6900     static const char *const opcodes[4][2] =
6901     {
6902       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6903        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6904       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6905        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6906       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6907        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6908       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6909        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6910     };
6911     int swap =
6912       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6914     return opcodes[which_alternative][swap];
6915   }"
6916   [(set_attr "conds" "set")
6917    (set_attr "predicable" "no")
6918    (set_attr "length" "8")]
6921 (define_insn "*cmp_ior"
6922   [(set (match_operand 6 "dominant_cc_register" "")
6923         (compare
6924          (ior:SI
6925           (match_operator 4 "arm_comparison_operator"
6926            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6927             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6928           (match_operator:SI 5 "arm_comparison_operator"
6929            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6930             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6931          (const_int 0)))]
6932   "TARGET_ARM"
6933   "*
6935   static const char *const opcodes[4][2] =
6936   {
6937     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
6938      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6939     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
6940      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6941     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
6942      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6943     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
6944      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6945   };
6946   int swap =
6947     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6949   return opcodes[which_alternative][swap];
6952   [(set_attr "conds" "set")
6953    (set_attr "length" "8")]
6956 (define_insn_and_split "*ior_scc_scc"
6957   [(set (match_operand:SI 0 "s_register_operand" "=r")
6958         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6959                  [(match_operand:SI 1 "s_register_operand" "r")
6960                   (match_operand:SI 2 "arm_add_operand" "rIL")])
6961                 (match_operator:SI 6 "arm_comparison_operator"
6962                  [(match_operand:SI 4 "s_register_operand" "r")
6963                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
6964    (clobber (reg:CC CC_REGNUM))]
6965   "TARGET_ARM
6966    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
6967        != CCmode)"
6968   "#"
6969   "TARGET_ARM && reload_completed"
6970   [(set (match_dup 7)
6971         (compare
6972          (ior:SI
6973           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6974           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6975          (const_int 0)))
6976    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
6977   "operands[7]
6978      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
6979                                                   DOM_CC_X_OR_Y),
6980                     CC_REGNUM);"
6981   [(set_attr "conds" "clob")
6982    (set_attr "length" "16")])
6984 ; If the above pattern is followed by a CMP insn, then the compare is 
6985 ; redundant, since we can rework the conditional instruction that follows.
6986 (define_insn_and_split "*ior_scc_scc_cmp"
6987   [(set (match_operand 0 "dominant_cc_register" "")
6988         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6989                           [(match_operand:SI 1 "s_register_operand" "r")
6990                            (match_operand:SI 2 "arm_add_operand" "rIL")])
6991                          (match_operator:SI 6 "arm_comparison_operator"
6992                           [(match_operand:SI 4 "s_register_operand" "r")
6993                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
6994                  (const_int 0)))
6995    (set (match_operand:SI 7 "s_register_operand" "=r")
6996         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6997                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
6998   "TARGET_ARM"
6999   "#"
7000   "TARGET_ARM && reload_completed"
7001   [(set (match_dup 0)
7002         (compare
7003          (ior:SI
7004           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7005           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7006          (const_int 0)))
7007    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
7008   ""
7009   [(set_attr "conds" "set")
7010    (set_attr "length" "16")])
7012 (define_insn_and_split "*and_scc_scc"
7013   [(set (match_operand:SI 0 "s_register_operand" "=r")
7014         (and:SI (match_operator:SI 3 "arm_comparison_operator"
7015                  [(match_operand:SI 1 "s_register_operand" "r")
7016                   (match_operand:SI 2 "arm_add_operand" "rIL")])
7017                 (match_operator:SI 6 "arm_comparison_operator"
7018                  [(match_operand:SI 4 "s_register_operand" "r")
7019                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
7020    (clobber (reg:CC CC_REGNUM))]
7021   "TARGET_ARM
7022    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7023        != CCmode)"
7024   "#"
7025   "TARGET_ARM && reload_completed
7026    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7027        != CCmode)"
7028   [(set (match_dup 7)
7029         (compare
7030          (and:SI
7031           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7032           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7033          (const_int 0)))
7034    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
7035   "operands[7]
7036      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
7037                                                   DOM_CC_X_AND_Y),
7038                     CC_REGNUM);"
7039   [(set_attr "conds" "clob")
7040    (set_attr "length" "16")])
7042 ; If the above pattern is followed by a CMP insn, then the compare is 
7043 ; redundant, since we can rework the conditional instruction that follows.
7044 (define_insn_and_split "*and_scc_scc_cmp"
7045   [(set (match_operand 0 "dominant_cc_register" "")
7046         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
7047                           [(match_operand:SI 1 "s_register_operand" "r")
7048                            (match_operand:SI 2 "arm_add_operand" "rIL")])
7049                          (match_operator:SI 6 "arm_comparison_operator"
7050                           [(match_operand:SI 4 "s_register_operand" "r")
7051                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
7052                  (const_int 0)))
7053    (set (match_operand:SI 7 "s_register_operand" "=r")
7054         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7055                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
7056   "TARGET_ARM"
7057   "#"
7058   "TARGET_ARM && reload_completed"
7059   [(set (match_dup 0)
7060         (compare
7061          (and:SI
7062           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7063           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7064          (const_int 0)))
7065    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
7066   ""
7067   [(set_attr "conds" "set")
7068    (set_attr "length" "16")])
7070 ;; If there is no dominance in the comparison, then we can still save an
7071 ;; instruction in the AND case, since we can know that the second compare
7072 ;; need only zero the value if false (if true, then the value is already
7073 ;; correct).
7074 (define_insn_and_split "*and_scc_scc_nodom"
7075   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
7076         (and:SI (match_operator:SI 3 "arm_comparison_operator"
7077                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
7078                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
7079                 (match_operator:SI 6 "arm_comparison_operator"
7080                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
7081                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
7082    (clobber (reg:CC CC_REGNUM))]
7083   "TARGET_ARM
7084    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7085        == CCmode)"
7086   "#"
7087   "TARGET_ARM && reload_completed"
7088   [(parallel [(set (match_dup 0)
7089                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
7090               (clobber (reg:CC CC_REGNUM))])
7091    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
7092    (set (match_dup 0)
7093         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
7094                          (match_dup 0)
7095                          (const_int 0)))]
7096   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
7097                                               operands[4], operands[5]),
7098                               CC_REGNUM);
7099    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
7100                                   operands[5]);"
7101   [(set_attr "conds" "clob")
7102    (set_attr "length" "20")])
7104 (define_insn "*negscc"
7105   [(set (match_operand:SI 0 "s_register_operand" "=r")
7106         (neg:SI (match_operator 3 "arm_comparison_operator"
7107                  [(match_operand:SI 1 "s_register_operand" "r")
7108                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7109    (clobber (reg:CC CC_REGNUM))]
7110   "TARGET_ARM"
7111   "*
7112   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7113     return \"mov\\t%0, %1, asr #31\";
7115   if (GET_CODE (operands[3]) == NE)
7116     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7118   if (GET_CODE (operands[3]) == GT)
7119     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7121   output_asm_insn (\"cmp\\t%1, %2\", operands);
7122   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7123   return \"mvn%d3\\t%0, #0\";
7124   "
7125   [(set_attr "conds" "clob")
7126    (set_attr "length" "12")]
7129 (define_insn "movcond"
7130   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7131         (if_then_else:SI
7132          (match_operator 5 "arm_comparison_operator"
7133           [(match_operand:SI 3 "s_register_operand" "r,r,r")
7134            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7135          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7136          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7137    (clobber (reg:CC CC_REGNUM))]
7138   "TARGET_ARM"
7139   "*
7140   if (GET_CODE (operands[5]) == LT
7141       && (operands[4] == const0_rtx))
7142     {
7143       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7144         {
7145           if (operands[2] == const0_rtx)
7146             return \"and\\t%0, %1, %3, asr #31\";
7147           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7148         }
7149       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7150         {
7151           if (operands[1] == const0_rtx)
7152             return \"bic\\t%0, %2, %3, asr #31\";
7153           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7154         }
7155       /* The only case that falls through to here is when both ops 1 & 2
7156          are constants */
7157     }
7159   if (GET_CODE (operands[5]) == GE
7160       && (operands[4] == const0_rtx))
7161     {
7162       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7163         {
7164           if (operands[2] == const0_rtx)
7165             return \"bic\\t%0, %1, %3, asr #31\";
7166           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7167         }
7168       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7169         {
7170           if (operands[1] == const0_rtx)
7171             return \"and\\t%0, %2, %3, asr #31\";
7172           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7173         }
7174       /* The only case that falls through to here is when both ops 1 & 2
7175          are constants */
7176     }
7177   if (GET_CODE (operands[4]) == CONST_INT
7178       && !const_ok_for_arm (INTVAL (operands[4])))
7179     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7180   else
7181     output_asm_insn (\"cmp\\t%3, %4\", operands);
7182   if (which_alternative != 0)
7183     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7184   if (which_alternative != 1)
7185     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7186   return \"\";
7187   "
7188   [(set_attr "conds" "clob")
7189    (set_attr "length" "8,8,12")]
7192 (define_insn "*ifcompare_plus_move"
7193   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7194         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7195                           [(match_operand:SI 4 "s_register_operand" "r,r")
7196                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7197                          (plus:SI
7198                           (match_operand:SI 2 "s_register_operand" "r,r")
7199                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7200                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7201    (clobber (reg:CC CC_REGNUM))]
7202   "TARGET_ARM"
7203   "#"
7204   [(set_attr "conds" "clob")
7205    (set_attr "length" "8,12")]
7208 (define_insn "*if_plus_move"
7209   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7210         (if_then_else:SI
7211          (match_operator 4 "arm_comparison_operator"
7212           [(match_operand 5 "cc_register" "") (const_int 0)])
7213          (plus:SI
7214           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7215           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7216          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7217   "TARGET_ARM"
7218   "@
7219    add%d4\\t%0, %2, %3
7220    sub%d4\\t%0, %2, #%n3
7221    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7222    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7223   [(set_attr "conds" "use")
7224    (set_attr "length" "4,4,8,8")
7225    (set_attr "type" "*,*,*,*")]
7228 (define_insn "*ifcompare_move_plus"
7229   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7230         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7231                           [(match_operand:SI 4 "s_register_operand" "r,r")
7232                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7233                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7234                          (plus:SI
7235                           (match_operand:SI 2 "s_register_operand" "r,r")
7236                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7237    (clobber (reg:CC CC_REGNUM))]
7238   "TARGET_ARM"
7239   "#"
7240   [(set_attr "conds" "clob")
7241    (set_attr "length" "8,12")]
7244 (define_insn "*if_move_plus"
7245   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7246         (if_then_else:SI
7247          (match_operator 4 "arm_comparison_operator"
7248           [(match_operand 5 "cc_register" "") (const_int 0)])
7249          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7250          (plus:SI
7251           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7252           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7253   "TARGET_ARM"
7254   "@
7255    add%D4\\t%0, %2, %3
7256    sub%D4\\t%0, %2, #%n3
7257    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7258    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7259   [(set_attr "conds" "use")
7260    (set_attr "length" "4,4,8,8")
7261    (set_attr "type" "*,*,*,*")]
7264 (define_insn "*ifcompare_arith_arith"
7265   [(set (match_operand:SI 0 "s_register_operand" "=r")
7266         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7267                           [(match_operand:SI 5 "s_register_operand" "r")
7268                            (match_operand:SI 6 "arm_add_operand" "rIL")])
7269                          (match_operator:SI 8 "shiftable_operator"
7270                           [(match_operand:SI 1 "s_register_operand" "r")
7271                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7272                          (match_operator:SI 7 "shiftable_operator"
7273                           [(match_operand:SI 3 "s_register_operand" "r")
7274                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7275    (clobber (reg:CC CC_REGNUM))]
7276   "TARGET_ARM"
7277   "#"
7278   [(set_attr "conds" "clob")
7279    (set_attr "length" "12")]
7282 (define_insn "*if_arith_arith"
7283   [(set (match_operand:SI 0 "s_register_operand" "=r")
7284         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7285                           [(match_operand 8 "cc_register" "") (const_int 0)])
7286                          (match_operator:SI 6 "shiftable_operator"
7287                           [(match_operand:SI 1 "s_register_operand" "r")
7288                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7289                          (match_operator:SI 7 "shiftable_operator"
7290                           [(match_operand:SI 3 "s_register_operand" "r")
7291                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7292   "TARGET_ARM"
7293   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7294   [(set_attr "conds" "use")
7295    (set_attr "length" "8")]
7298 (define_insn "*ifcompare_arith_move"
7299   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7300         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7301                           [(match_operand:SI 2 "s_register_operand" "r,r")
7302                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7303                          (match_operator:SI 7 "shiftable_operator"
7304                           [(match_operand:SI 4 "s_register_operand" "r,r")
7305                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7306                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7307    (clobber (reg:CC CC_REGNUM))]
7308   "TARGET_ARM"
7309   "*
7310   /* If we have an operation where (op x 0) is the identity operation and
7311      the conditional operator is LT or GE and we are comparing against zero and
7312      everything is in registers then we can do this in two instructions */
7313   if (operands[3] == const0_rtx
7314       && GET_CODE (operands[7]) != AND
7315       && GET_CODE (operands[5]) == REG
7316       && GET_CODE (operands[1]) == REG 
7317       && REGNO (operands[1]) == REGNO (operands[4])
7318       && REGNO (operands[4]) != REGNO (operands[0]))
7319     {
7320       if (GET_CODE (operands[6]) == LT)
7321         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7322       else if (GET_CODE (operands[6]) == GE)
7323         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7324     }
7325   if (GET_CODE (operands[3]) == CONST_INT
7326       && !const_ok_for_arm (INTVAL (operands[3])))
7327     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7328   else
7329     output_asm_insn (\"cmp\\t%2, %3\", operands);
7330   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7331   if (which_alternative != 0)
7332     return \"mov%D6\\t%0, %1\";
7333   return \"\";
7334   "
7335   [(set_attr "conds" "clob")
7336    (set_attr "length" "8,12")]
7339 (define_insn "*if_arith_move"
7340   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7341         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7342                           [(match_operand 6 "cc_register" "") (const_int 0)])
7343                          (match_operator:SI 5 "shiftable_operator"
7344                           [(match_operand:SI 2 "s_register_operand" "r,r")
7345                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7346                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7347   "TARGET_ARM"
7348   "@
7349    %I5%d4\\t%0, %2, %3
7350    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7351   [(set_attr "conds" "use")
7352    (set_attr "length" "4,8")
7353    (set_attr "type" "*,*")]
7356 (define_insn "*ifcompare_move_arith"
7357   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7358         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7359                           [(match_operand:SI 4 "s_register_operand" "r,r")
7360                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7361                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7362                          (match_operator:SI 7 "shiftable_operator"
7363                           [(match_operand:SI 2 "s_register_operand" "r,r")
7364                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7365    (clobber (reg:CC CC_REGNUM))]
7366   "TARGET_ARM"
7367   "*
7368   /* If we have an operation where (op x 0) is the identity operation and
7369      the conditional operator is LT or GE and we are comparing against zero and
7370      everything is in registers then we can do this in two instructions */
7371   if (operands[5] == const0_rtx
7372       && GET_CODE (operands[7]) != AND
7373       && GET_CODE (operands[3]) == REG
7374       && GET_CODE (operands[1]) == REG 
7375       && REGNO (operands[1]) == REGNO (operands[2])
7376       && REGNO (operands[2]) != REGNO (operands[0]))
7377     {
7378       if (GET_CODE (operands[6]) == GE)
7379         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7380       else if (GET_CODE (operands[6]) == LT)
7381         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7382     }
7384   if (GET_CODE (operands[5]) == CONST_INT
7385       && !const_ok_for_arm (INTVAL (operands[5])))
7386     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7387   else
7388     output_asm_insn (\"cmp\\t%4, %5\", operands);
7390   if (which_alternative != 0)
7391     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7392   return \"%I7%D6\\t%0, %2, %3\";
7393   "
7394   [(set_attr "conds" "clob")
7395    (set_attr "length" "8,12")]
7398 (define_insn "*if_move_arith"
7399   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7400         (if_then_else:SI
7401          (match_operator 4 "arm_comparison_operator"
7402           [(match_operand 6 "cc_register" "") (const_int 0)])
7403          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7404          (match_operator:SI 5 "shiftable_operator"
7405           [(match_operand:SI 2 "s_register_operand" "r,r")
7406            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7407   "TARGET_ARM"
7408   "@
7409    %I5%D4\\t%0, %2, %3
7410    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7411   [(set_attr "conds" "use")
7412    (set_attr "length" "4,8")
7413    (set_attr "type" "*,*")]
7416 (define_insn "*ifcompare_move_not"
7417   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7418         (if_then_else:SI
7419          (match_operator 5 "arm_comparison_operator"
7420           [(match_operand:SI 3 "s_register_operand" "r,r")
7421            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7422          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7423          (not:SI
7424           (match_operand:SI 2 "s_register_operand" "r,r"))))
7425    (clobber (reg:CC CC_REGNUM))]
7426   "TARGET_ARM"
7427   "#"
7428   [(set_attr "conds" "clob")
7429    (set_attr "length" "8,12")]
7432 (define_insn "*if_move_not"
7433   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7434         (if_then_else:SI
7435          (match_operator 4 "arm_comparison_operator"
7436           [(match_operand 3 "cc_register" "") (const_int 0)])
7437          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7438          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7439   "TARGET_ARM"
7440   "@
7441    mvn%D4\\t%0, %2
7442    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7443    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7444   [(set_attr "conds" "use")
7445    (set_attr "length" "4,8,8")]
7448 (define_insn "*ifcompare_not_move"
7449   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7450         (if_then_else:SI 
7451          (match_operator 5 "arm_comparison_operator"
7452           [(match_operand:SI 3 "s_register_operand" "r,r")
7453            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7454          (not:SI
7455           (match_operand:SI 2 "s_register_operand" "r,r"))
7456          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7457    (clobber (reg:CC CC_REGNUM))]
7458   "TARGET_ARM"
7459   "#"
7460   [(set_attr "conds" "clob")
7461    (set_attr "length" "8,12")]
7464 (define_insn "*if_not_move"
7465   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7466         (if_then_else:SI
7467          (match_operator 4 "arm_comparison_operator"
7468           [(match_operand 3 "cc_register" "") (const_int 0)])
7469          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7470          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7471   "TARGET_ARM"
7472   "@
7473    mvn%d4\\t%0, %2
7474    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7475    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7476   [(set_attr "conds" "use")
7477    (set_attr "length" "4,8,8")]
7480 (define_insn "*ifcompare_shift_move"
7481   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7482         (if_then_else:SI
7483          (match_operator 6 "arm_comparison_operator"
7484           [(match_operand:SI 4 "s_register_operand" "r,r")
7485            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7486          (match_operator:SI 7 "shift_operator"
7487           [(match_operand:SI 2 "s_register_operand" "r,r")
7488            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7489          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7490    (clobber (reg:CC CC_REGNUM))]
7491   "TARGET_ARM"
7492   "#"
7493   [(set_attr "conds" "clob")
7494    (set_attr "length" "8,12")]
7497 (define_insn "*if_shift_move"
7498   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7499         (if_then_else:SI
7500          (match_operator 5 "arm_comparison_operator"
7501           [(match_operand 6 "cc_register" "") (const_int 0)])
7502          (match_operator:SI 4 "shift_operator"
7503           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7504            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7505          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7506   "TARGET_ARM"
7507   "@
7508    mov%d5\\t%0, %2%S4
7509    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7510    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7511   [(set_attr "conds" "use")
7512    (set_attr "shift" "2")
7513    (set_attr "length" "4,8,8")]
7516 (define_insn "*ifcompare_move_shift"
7517   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7518         (if_then_else:SI
7519          (match_operator 6 "arm_comparison_operator"
7520           [(match_operand:SI 4 "s_register_operand" "r,r")
7521            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7522          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7523          (match_operator:SI 7 "shift_operator"
7524           [(match_operand:SI 2 "s_register_operand" "r,r")
7525            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7526    (clobber (reg:CC CC_REGNUM))]
7527   "TARGET_ARM"
7528   "#"
7529   [(set_attr "conds" "clob")
7530    (set_attr "length" "8,12")]
7533 (define_insn "*if_move_shift"
7534   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7535         (if_then_else:SI
7536          (match_operator 5 "arm_comparison_operator"
7537           [(match_operand 6 "cc_register" "") (const_int 0)])
7538          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7539          (match_operator:SI 4 "shift_operator"
7540           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7541            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7542   "TARGET_ARM"
7543   "@
7544    mov%D5\\t%0, %2%S4
7545    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7546    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7547   [(set_attr "conds" "use")
7548    (set_attr "shift" "2")
7549    (set_attr "length" "4,8,8")]
7552 (define_insn "*ifcompare_shift_shift"
7553   [(set (match_operand:SI 0 "s_register_operand" "=r")
7554         (if_then_else:SI
7555          (match_operator 7 "arm_comparison_operator"
7556           [(match_operand:SI 5 "s_register_operand" "r")
7557            (match_operand:SI 6 "arm_add_operand" "rIL")])
7558          (match_operator:SI 8 "shift_operator"
7559           [(match_operand:SI 1 "s_register_operand" "r")
7560            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7561          (match_operator:SI 9 "shift_operator"
7562           [(match_operand:SI 3 "s_register_operand" "r")
7563            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7564    (clobber (reg:CC CC_REGNUM))]
7565   "TARGET_ARM"
7566   "#"
7567   [(set_attr "conds" "clob")
7568    (set_attr "length" "12")]
7571 (define_insn "*if_shift_shift"
7572   [(set (match_operand:SI 0 "s_register_operand" "=r")
7573         (if_then_else:SI
7574          (match_operator 5 "arm_comparison_operator"
7575           [(match_operand 8 "cc_register" "") (const_int 0)])
7576          (match_operator:SI 6 "shift_operator"
7577           [(match_operand:SI 1 "s_register_operand" "r")
7578            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7579          (match_operator:SI 7 "shift_operator"
7580           [(match_operand:SI 3 "s_register_operand" "r")
7581            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7582   "TARGET_ARM"
7583   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7584   [(set_attr "conds" "use")
7585    (set_attr "shift" "1")
7586    (set_attr "length" "8")]
7589 (define_insn "*ifcompare_not_arith"
7590   [(set (match_operand:SI 0 "s_register_operand" "=r")
7591         (if_then_else:SI
7592          (match_operator 6 "arm_comparison_operator"
7593           [(match_operand:SI 4 "s_register_operand" "r")
7594            (match_operand:SI 5 "arm_add_operand" "rIL")])
7595          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7596          (match_operator:SI 7 "shiftable_operator"
7597           [(match_operand:SI 2 "s_register_operand" "r")
7598            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7599    (clobber (reg:CC CC_REGNUM))]
7600   "TARGET_ARM"
7601   "#"
7602   [(set_attr "conds" "clob")
7603    (set_attr "length" "12")]
7606 (define_insn "*if_not_arith"
7607   [(set (match_operand:SI 0 "s_register_operand" "=r")
7608         (if_then_else:SI
7609          (match_operator 5 "arm_comparison_operator"
7610           [(match_operand 4 "cc_register" "") (const_int 0)])
7611          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7612          (match_operator:SI 6 "shiftable_operator"
7613           [(match_operand:SI 2 "s_register_operand" "r")
7614            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7615   "TARGET_ARM"
7616   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7617   [(set_attr "conds" "use")
7618    (set_attr "length" "8")]
7621 (define_insn "*ifcompare_arith_not"
7622   [(set (match_operand:SI 0 "s_register_operand" "=r")
7623         (if_then_else:SI
7624          (match_operator 6 "arm_comparison_operator"
7625           [(match_operand:SI 4 "s_register_operand" "r")
7626            (match_operand:SI 5 "arm_add_operand" "rIL")])
7627          (match_operator:SI 7 "shiftable_operator"
7628           [(match_operand:SI 2 "s_register_operand" "r")
7629            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7630          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7631    (clobber (reg:CC CC_REGNUM))]
7632   "TARGET_ARM"
7633   "#"
7634   [(set_attr "conds" "clob")
7635    (set_attr "length" "12")]
7638 (define_insn "*if_arith_not"
7639   [(set (match_operand:SI 0 "s_register_operand" "=r")
7640         (if_then_else:SI
7641          (match_operator 5 "arm_comparison_operator"
7642           [(match_operand 4 "cc_register" "") (const_int 0)])
7643          (match_operator:SI 6 "shiftable_operator"
7644           [(match_operand:SI 2 "s_register_operand" "r")
7645            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7646          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7647   "TARGET_ARM"
7648   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7649   [(set_attr "conds" "use")
7650    (set_attr "length" "8")]
7653 (define_insn "*ifcompare_neg_move"
7654   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7655         (if_then_else:SI
7656          (match_operator 5 "arm_comparison_operator"
7657           [(match_operand:SI 3 "s_register_operand" "r,r")
7658            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7659          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7660          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7661    (clobber (reg:CC CC_REGNUM))]
7662   "TARGET_ARM"
7663   "#"
7664   [(set_attr "conds" "clob")
7665    (set_attr "length" "8,12")]
7668 (define_insn "*if_neg_move"
7669   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7670         (if_then_else:SI
7671          (match_operator 4 "arm_comparison_operator"
7672           [(match_operand 3 "cc_register" "") (const_int 0)])
7673          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7674          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7675   "TARGET_ARM"
7676   "@
7677    rsb%d4\\t%0, %2, #0
7678    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7679    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7680   [(set_attr "conds" "use")
7681    (set_attr "length" "4,8,8")]
7684 (define_insn "*ifcompare_move_neg"
7685   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7686         (if_then_else:SI
7687          (match_operator 5 "arm_comparison_operator"
7688           [(match_operand:SI 3 "s_register_operand" "r,r")
7689            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7690          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7691          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7692    (clobber (reg:CC CC_REGNUM))]
7693   "TARGET_ARM"
7694   "#"
7695   [(set_attr "conds" "clob")
7696    (set_attr "length" "8,12")]
7699 (define_insn "*if_move_neg"
7700   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7701         (if_then_else:SI
7702          (match_operator 4 "arm_comparison_operator"
7703           [(match_operand 3 "cc_register" "") (const_int 0)])
7704          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7705          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7706   "TARGET_ARM"
7707   "@
7708    rsb%D4\\t%0, %2, #0
7709    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7710    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7711   [(set_attr "conds" "use")
7712    (set_attr "length" "4,8,8")]
7715 (define_insn "*arith_adjacentmem"
7716   [(set (match_operand:SI 0 "s_register_operand" "=r")
7717         (match_operator:SI 1 "shiftable_operator"
7718          [(match_operand:SI 2 "memory_operand" "m")
7719           (match_operand:SI 3 "memory_operand" "m")]))
7720    (clobber (match_scratch:SI 4 "=r"))]
7721   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7722   "*
7723   {
7724     rtx ldm[3];
7725     rtx arith[4];
7726     int val1 = 0, val2 = 0;
7728     if (REGNO (operands[0]) > REGNO (operands[4]))
7729       {
7730         ldm[1] = operands[4];
7731         ldm[2] = operands[0];
7732       }
7733     else
7734       {
7735         ldm[1] = operands[0];
7736         ldm[2] = operands[4];
7737       }
7738     if (GET_CODE (XEXP (operands[2], 0)) != REG)
7739       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7740     if (GET_CODE (XEXP (operands[3], 0)) != REG)
7741       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7742     arith[0] = operands[0];
7743     arith[3] = operands[1];
7744     if (val1 < val2)
7745       {
7746         arith[1] = ldm[1];
7747         arith[2] = ldm[2];
7748       }
7749     else
7750       {
7751         arith[1] = ldm[2];
7752         arith[2] = ldm[1];
7753       }
7754    if (val1 && val2)
7755       {
7756         rtx ops[3];
7757         ldm[0] = ops[0] = operands[4];
7758         ops[1] = XEXP (XEXP (operands[2], 0), 0);
7759         ops[2] = XEXP (XEXP (operands[2], 0), 1);
7760         output_add_immediate (ops);
7761         if (val1 < val2)
7762           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7763         else
7764           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7765       }
7766     else if (val1)
7767       {
7768         ldm[0] = XEXP (operands[3], 0);
7769         if (val1 < val2)
7770           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7771         else
7772           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7773       }
7774     else
7775       {
7776         ldm[0] = XEXP (operands[2], 0);
7777         if (val1 < val2)
7778           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7779         else
7780           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7781       }
7782     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7783     return \"\";
7784   }"
7785   [(set_attr "length" "12")
7786    (set_attr "predicable" "yes")
7787    (set_attr "type" "load")]
7790 ;; the arm can support extended pre-inc instructions
7792 ;; In all these cases, we use operands 0 and 1 for the register being
7793 ;; incremented because those are the operands that local-alloc will
7794 ;; tie and these are the pair most likely to be tieable (and the ones
7795 ;; that will benefit the most).
7797 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7798 ;; elimination will cause too many headaches.
7800 (define_insn "*strqi_preinc"
7801   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7802                          (match_operand:SI 2 "index_operand" "rJ")))
7803         (match_operand:QI 3 "s_register_operand" "r"))
7804    (set (match_operand:SI 0 "s_register_operand" "=r")
7805         (plus:SI (match_dup 1) (match_dup 2)))]
7806   "TARGET_ARM
7807    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7808    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7809    && (GET_CODE (operands[2]) != REG
7810        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7811   "str%?b\\t%3, [%0, %2]!"
7812   [(set_attr "type" "store1")
7813    (set_attr "predicable" "yes")]
7816 (define_insn "*strqi_predec"
7817   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7818                           (match_operand:SI 2 "s_register_operand" "r")))
7819         (match_operand:QI 3 "s_register_operand" "r"))
7820    (set (match_operand:SI 0 "s_register_operand" "=r")
7821         (minus:SI (match_dup 1) (match_dup 2)))]
7822   "TARGET_ARM
7823    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7824    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7825    && (GET_CODE (operands[2]) != REG
7826        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7827   "str%?b\\t%3, [%0, -%2]!"
7828   [(set_attr "type" "store1")
7829    (set_attr "predicable" "yes")]
7832 (define_insn "*loadqi_preinc"
7833   [(set (match_operand:QI 3 "s_register_operand" "=r")
7834         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7835                          (match_operand:SI 2 "index_operand" "rJ"))))
7836    (set (match_operand:SI 0 "s_register_operand" "=r")
7837         (plus:SI (match_dup 1) (match_dup 2)))]
7838   "TARGET_ARM
7839    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7840    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7841    && (GET_CODE (operands[2]) != REG
7842        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7843   "ldr%?b\\t%3, [%0, %2]!"
7844   [(set_attr "type" "load")
7845    (set_attr "predicable" "yes")]
7848 (define_insn "*loadqi_predec"
7849   [(set (match_operand:QI 3 "s_register_operand" "=r")
7850         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7851                           (match_operand:SI 2 "s_register_operand" "r"))))
7852    (set (match_operand:SI 0 "s_register_operand" "=r")
7853         (minus:SI (match_dup 1) (match_dup 2)))]
7854   "TARGET_ARM
7855    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7856    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7857    && (GET_CODE (operands[2]) != REG
7858        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7859   "ldr%?b\\t%3, [%0, -%2]!"
7860   [(set_attr "type" "load")
7861    (set_attr "predicable" "yes")]
7864 (define_insn "*loadqisi_preinc"
7865   [(set (match_operand:SI 3 "s_register_operand" "=r")
7866         (zero_extend:SI
7867          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7868                           (match_operand:SI 2 "index_operand" "rJ")))))
7869    (set (match_operand:SI 0 "s_register_operand" "=r")
7870         (plus:SI (match_dup 1) (match_dup 2)))]
7871   "TARGET_ARM
7872    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7873    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7874    && (GET_CODE (operands[2]) != REG
7875        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7876   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
7877   [(set_attr "type" "load")
7878    (set_attr "predicable" "yes")]
7881 (define_insn "*loadqisi_predec"
7882   [(set (match_operand:SI 3 "s_register_operand" "=r")
7883         (zero_extend:SI
7884          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7885                            (match_operand:SI 2 "s_register_operand" "r")))))
7886    (set (match_operand:SI 0 "s_register_operand" "=r")
7887         (minus:SI (match_dup 1) (match_dup 2)))]
7888   "TARGET_ARM
7889    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7890    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7891    && (GET_CODE (operands[2]) != REG
7892        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7893   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
7894   [(set_attr "type" "load")
7895    (set_attr "predicable" "yes")]
7898 (define_insn "*strsi_preinc"
7899   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7900                          (match_operand:SI 2 "index_operand" "rJ")))
7901         (match_operand:SI 3 "s_register_operand" "r"))
7902    (set (match_operand:SI 0 "s_register_operand" "=r")
7903         (plus:SI (match_dup 1) (match_dup 2)))]
7904   "TARGET_ARM
7905    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7906    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7907    && (GET_CODE (operands[2]) != REG
7908        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7909   "str%?\\t%3, [%0, %2]!"
7910   [(set_attr "type" "store1")
7911    (set_attr "predicable" "yes")]
7914 (define_insn "*strsi_predec"
7915   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7916                           (match_operand:SI 2 "s_register_operand" "r")))
7917         (match_operand:SI 3 "s_register_operand" "r"))
7918    (set (match_operand:SI 0 "s_register_operand" "=r")
7919         (minus:SI (match_dup 1) (match_dup 2)))]
7920   "TARGET_ARM
7921    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7922    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7923    && (GET_CODE (operands[2]) != REG
7924        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7925   "str%?\\t%3, [%0, -%2]!"
7926   [(set_attr "type" "store1")
7927    (set_attr "predicable" "yes")]
7930 (define_insn "*loadsi_preinc"
7931   [(set (match_operand:SI 3 "s_register_operand" "=r")
7932         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7933                          (match_operand:SI 2 "index_operand" "rJ"))))
7934    (set (match_operand:SI 0 "s_register_operand" "=r")
7935         (plus:SI (match_dup 1) (match_dup 2)))]
7936   "TARGET_ARM
7937    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7938    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7939    && (GET_CODE (operands[2]) != REG
7940        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7941   "ldr%?\\t%3, [%0, %2]!"
7942   [(set_attr "type" "load")
7943    (set_attr "predicable" "yes")]
7946 (define_insn "*loadsi_predec"
7947   [(set (match_operand:SI 3 "s_register_operand" "=r")
7948         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7949                           (match_operand:SI 2 "s_register_operand" "r"))))
7950    (set (match_operand:SI 0 "s_register_operand" "=r")
7951         (minus:SI (match_dup 1) (match_dup 2)))]
7952   "TARGET_ARM
7953    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7954    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7955    && (GET_CODE (operands[2]) != REG
7956        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7957   "ldr%?\\t%3, [%0, -%2]!"
7958   [(set_attr "type" "load")
7959    (set_attr "predicable" "yes")]
7962 (define_insn "*loadhi_preinc"
7963   [(set (match_operand:HI 3 "s_register_operand" "=r")
7964         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7965                          (match_operand:SI 2 "index_operand" "rJ"))))
7966    (set (match_operand:SI 0 "s_register_operand" "=r")
7967         (plus:SI (match_dup 1) (match_dup 2)))]
7968   "TARGET_ARM
7969    && !BYTES_BIG_ENDIAN
7970    && !TARGET_MMU_TRAPS
7971    && !arm_arch4
7972    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7973    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7974    && (GET_CODE (operands[2]) != REG
7975        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7976   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
7977   [(set_attr "type" "load")
7978    (set_attr "predicable" "yes")]
7981 (define_insn "*loadhi_predec"
7982   [(set (match_operand:HI 3 "s_register_operand" "=r")
7983         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7984                           (match_operand:SI 2 "s_register_operand" "r"))))
7985    (set (match_operand:SI 0 "s_register_operand" "=r")
7986         (minus:SI (match_dup 1) (match_dup 2)))]
7987   "TARGET_ARM
7988    && !BYTES_BIG_ENDIAN
7989    && !TARGET_MMU_TRAPS
7990    && !arm_arch4
7991    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7992    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7993    && (GET_CODE (operands[2]) != REG
7994        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7995   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
7996   [(set_attr "type" "load")
7997    (set_attr "predicable" "yes")]
8000 (define_insn "*strqi_shiftpreinc"
8001   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8002                           [(match_operand:SI 3 "s_register_operand" "r")
8003                            (match_operand:SI 4 "const_shift_operand" "n")])
8004                          (match_operand:SI 1 "s_register_operand" "0")))
8005         (match_operand:QI 5 "s_register_operand" "r"))
8006    (set (match_operand:SI 0 "s_register_operand" "=r")
8007         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8008                  (match_dup 1)))]
8009   "TARGET_ARM
8010    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8011    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8012    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8013   "str%?b\\t%5, [%0, %3%S2]!"
8014   [(set_attr "type" "store1")
8015    (set_attr "predicable" "yes")]
8018 (define_insn "*strqi_shiftpredec"
8019   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8020                           (match_operator:SI 2 "shift_operator"
8021                            [(match_operand:SI 3 "s_register_operand" "r")
8022                             (match_operand:SI 4 "const_shift_operand" "n")])))
8023         (match_operand:QI 5 "s_register_operand" "r"))
8024    (set (match_operand:SI 0 "s_register_operand" "=r")
8025         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8026                                                  (match_dup 4)])))]
8027   "TARGET_ARM
8028    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8029    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8030    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8031   "str%?b\\t%5, [%0, -%3%S2]!"
8032   [(set_attr "type" "store1")
8033    (set_attr "predicable" "yes")]
8036 (define_insn "*loadqi_shiftpreinc"
8037   [(set (match_operand:QI 5 "s_register_operand" "=r")
8038         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8039                           [(match_operand:SI 3 "s_register_operand" "r")
8040                            (match_operand:SI 4 "const_shift_operand" "n")])
8041                          (match_operand:SI 1 "s_register_operand" "0"))))
8042    (set (match_operand:SI 0 "s_register_operand" "=r")
8043         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8044                  (match_dup 1)))]
8045   "TARGET_ARM
8046    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8047    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8048    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8049   "ldr%?b\\t%5, [%0, %3%S2]!"
8050   [(set_attr "type" "load")
8051    (set_attr "predicable" "yes")]
8054 (define_insn "*loadqi_shiftpredec"
8055   [(set (match_operand:QI 5 "s_register_operand" "=r")
8056         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8057                           (match_operator:SI 2 "shift_operator"
8058                            [(match_operand:SI 3 "s_register_operand" "r")
8059                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8060    (set (match_operand:SI 0 "s_register_operand" "=r")
8061         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8062                                                  (match_dup 4)])))]
8063   "TARGET_ARM
8064    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8065    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8066    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8067   "ldr%?b\\t%5, [%0, -%3%S2]!"
8068   [(set_attr "type" "load")
8069    (set_attr "predicable" "yes")]
8072 (define_insn "*strsi_shiftpreinc"
8073   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8074                           [(match_operand:SI 3 "s_register_operand" "r")
8075                            (match_operand:SI 4 "const_shift_operand" "n")])
8076                          (match_operand:SI 1 "s_register_operand" "0")))
8077         (match_operand:SI 5 "s_register_operand" "r"))
8078    (set (match_operand:SI 0 "s_register_operand" "=r")
8079         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8080                  (match_dup 1)))]
8081   "TARGET_ARM
8082    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8083    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8084    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8085   "str%?\\t%5, [%0, %3%S2]!"
8086   [(set_attr "type" "store1")
8087    (set_attr "predicable" "yes")]
8090 (define_insn "*strsi_shiftpredec"
8091   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8092                           (match_operator:SI 2 "shift_operator"
8093                            [(match_operand:SI 3 "s_register_operand" "r")
8094                             (match_operand:SI 4 "const_shift_operand" "n")])))
8095         (match_operand:SI 5 "s_register_operand" "r"))
8096    (set (match_operand:SI 0 "s_register_operand" "=r")
8097         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8098                                                  (match_dup 4)])))]
8099   "TARGET_ARM
8100    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8101    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8102    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8103   "str%?\\t%5, [%0, -%3%S2]!"
8104   [(set_attr "type" "store1")
8105    (set_attr "predicable" "yes")]
8108 (define_insn "*loadsi_shiftpreinc"
8109   [(set (match_operand:SI 5 "s_register_operand" "=r")
8110         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8111                           [(match_operand:SI 3 "s_register_operand" "r")
8112                            (match_operand:SI 4 "const_shift_operand" "n")])
8113                          (match_operand:SI 1 "s_register_operand" "0"))))
8114    (set (match_operand:SI 0 "s_register_operand" "=r")
8115         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8116                  (match_dup 1)))]
8117   "TARGET_ARM
8118    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8119    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8120    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8121   "ldr%?\\t%5, [%0, %3%S2]!"
8122   [(set_attr "type" "load")
8123    (set_attr "predicable" "yes")]
8126 (define_insn "*loadsi_shiftpredec"
8127   [(set (match_operand:SI 5 "s_register_operand" "=r")
8128         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8129                           (match_operator:SI 2 "shift_operator"
8130                            [(match_operand:SI 3 "s_register_operand" "r")
8131                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8132    (set (match_operand:SI 0 "s_register_operand" "=r")
8133         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8134                                                  (match_dup 4)])))]
8135   "TARGET_ARM
8136    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8137    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8138    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8139   "ldr%?\\t%5, [%0, -%3%S2]!"
8140   [(set_attr "type" "load")
8141    (set_attr "predicable" "yes")])
8143 (define_insn "*loadhi_shiftpreinc"
8144   [(set (match_operand:HI 5 "s_register_operand" "=r")
8145         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8146                           [(match_operand:SI 3 "s_register_operand" "r")
8147                            (match_operand:SI 4 "const_shift_operand" "n")])
8148                          (match_operand:SI 1 "s_register_operand" "0"))))
8149    (set (match_operand:SI 0 "s_register_operand" "=r")
8150         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8151                  (match_dup 1)))]
8152   "TARGET_ARM
8153    && !BYTES_BIG_ENDIAN
8154    && !TARGET_MMU_TRAPS
8155    && !arm_arch4
8156    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8157    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8158    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8159   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8160   [(set_attr "type" "load")
8161    (set_attr "predicable" "yes")]
8164 (define_insn "*loadhi_shiftpredec"
8165   [(set (match_operand:HI 5 "s_register_operand" "=r")
8166         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8167                           (match_operator:SI 2 "shift_operator"
8168                            [(match_operand:SI 3 "s_register_operand" "r")
8169                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8170    (set (match_operand:SI 0 "s_register_operand" "=r")
8171         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8172                                                  (match_dup 4)])))]
8173   "TARGET_ARM
8174    && !BYTES_BIG_ENDIAN
8175    && !TARGET_MMU_TRAPS
8176    && !arm_arch4
8177    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8178    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8179    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8180   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8181   [(set_attr "type" "load")
8182    (set_attr "predicable" "yes")]
8185 ; It can also support extended post-inc expressions, but combine doesn't
8186 ; try these....
8187 ; It doesn't seem worth adding peepholes for anything but the most common
8188 ; cases since, unlike combine, the increment must immediately follow the load
8189 ; for this pattern to match.
8190 ; We must watch to see that the source/destination register isn't also the
8191 ; same as the base address register, and that if the index is a register,
8192 ; that it is not the same as the base address register.  In such cases the
8193 ; instruction that we would generate would have UNPREDICTABLE behavior so 
8194 ; we cannot use it.
8196 (define_peephole
8197   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8198         (match_operand:QI 2 "s_register_operand" "r"))
8199    (set (match_dup 0)
8200         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8201   "TARGET_ARM
8202    && (REGNO (operands[2]) != REGNO (operands[0]))
8203    && (GET_CODE (operands[1]) != REG
8204        || (REGNO (operands[1]) != REGNO (operands[0])))"
8205   "str%?b\\t%2, [%0], %1"
8208 (define_peephole
8209   [(set (match_operand:QI 0 "s_register_operand" "=r")
8210         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8211    (set (match_dup 1)
8212         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8213   "TARGET_ARM
8214    && REGNO (operands[0]) != REGNO(operands[1])
8215    && (GET_CODE (operands[2]) != REG
8216        || REGNO(operands[0]) != REGNO (operands[2]))"
8217   "ldr%?b\\t%0, [%1], %2"
8220 (define_peephole
8221   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8222         (match_operand:SI 2 "s_register_operand" "r"))
8223    (set (match_dup 0)
8224         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8225   "TARGET_ARM
8226    && (REGNO (operands[2]) != REGNO (operands[0]))
8227    && (GET_CODE (operands[1]) != REG
8228        || (REGNO (operands[1]) != REGNO (operands[0])))"
8229   "str%?\\t%2, [%0], %1"
8232 (define_peephole
8233   [(set (match_operand:HI 0 "s_register_operand" "=r")
8234         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8235    (set (match_dup 1)
8236         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8237   "TARGET_ARM
8238    && !BYTES_BIG_ENDIAN
8239    && !TARGET_MMU_TRAPS
8240    && !arm_arch4
8241    && REGNO (operands[0]) != REGNO(operands[1])
8242    && (GET_CODE (operands[2]) != REG
8243        || REGNO(operands[0]) != REGNO (operands[2]))"
8244   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8247 (define_peephole
8248   [(set (match_operand:SI 0 "s_register_operand" "=r")
8249         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8250    (set (match_dup 1)
8251         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8252   "TARGET_ARM
8253    && REGNO (operands[0]) != REGNO(operands[1])
8254    && (GET_CODE (operands[2]) != REG
8255        || REGNO(operands[0]) != REGNO (operands[2]))"
8256   "ldr%?\\t%0, [%1], %2"
8259 (define_peephole
8260   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8261                          (match_operand:SI 1 "index_operand" "rJ")))
8262         (match_operand:QI 2 "s_register_operand" "r"))
8263    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8264   "TARGET_ARM
8265    && (REGNO (operands[2]) != REGNO (operands[0]))
8266    && (GET_CODE (operands[1]) != REG
8267        || (REGNO (operands[1]) != REGNO (operands[0])))"
8268   "str%?b\\t%2, [%0, %1]!"
8271 (define_peephole
8272   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8273                           [(match_operand:SI 0 "s_register_operand" "r")
8274                            (match_operand:SI 1 "const_int_operand" "n")])
8275                          (match_operand:SI 2 "s_register_operand" "+r")))
8276         (match_operand:QI 3 "s_register_operand" "r"))
8277    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8278                                (match_dup 2)))]
8279   "TARGET_ARM
8280    && (REGNO (operands[3]) != REGNO (operands[2]))
8281    && (REGNO (operands[0]) != REGNO (operands[2]))"
8282   "str%?b\\t%3, [%2, %0%S4]!"
8285 ; This pattern is never tried by combine, so do it as a peephole
8287 (define_peephole2
8288   [(set (match_operand:SI 0 "s_register_operand" "")
8289         (match_operand:SI 1 "s_register_operand" ""))
8290    (set (reg:CC CC_REGNUM)
8291         (compare:CC (match_dup 1) (const_int 0)))]
8292   "TARGET_ARM
8293    && (!TARGET_CIRRUS
8294        || (!cirrus_fp_register (operands[0], SImode)
8295            && !cirrus_fp_register (operands[1], SImode)))
8296   "
8297   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8298               (set (match_dup 0) (match_dup 1))])]
8299   ""
8302 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8303 ; reversed, check that the memory references aren't volatile.
8305 (define_peephole
8306   [(set (match_operand:SI 0 "s_register_operand" "=r")
8307         (match_operand:SI 4 "memory_operand" "m"))
8308    (set (match_operand:SI 1 "s_register_operand" "=r")
8309         (match_operand:SI 5 "memory_operand" "m"))
8310    (set (match_operand:SI 2 "s_register_operand" "=r")
8311         (match_operand:SI 6 "memory_operand" "m"))
8312    (set (match_operand:SI 3 "s_register_operand" "=r")
8313         (match_operand:SI 7 "memory_operand" "m"))]
8314   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8315   "*
8316   return emit_ldm_seq (operands, 4);
8317   "
8320 (define_peephole
8321   [(set (match_operand:SI 0 "s_register_operand" "=r")
8322         (match_operand:SI 3 "memory_operand" "m"))
8323    (set (match_operand:SI 1 "s_register_operand" "=r")
8324         (match_operand:SI 4 "memory_operand" "m"))
8325    (set (match_operand:SI 2 "s_register_operand" "=r")
8326         (match_operand:SI 5 "memory_operand" "m"))]
8327   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8328   "*
8329   return emit_ldm_seq (operands, 3);
8330   "
8333 (define_peephole
8334   [(set (match_operand:SI 0 "s_register_operand" "=r")
8335         (match_operand:SI 2 "memory_operand" "m"))
8336    (set (match_operand:SI 1 "s_register_operand" "=r")
8337         (match_operand:SI 3 "memory_operand" "m"))]
8338   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8339   "*
8340   return emit_ldm_seq (operands, 2);
8341   "
8344 (define_peephole
8345   [(set (match_operand:SI 4 "memory_operand" "=m")
8346         (match_operand:SI 0 "s_register_operand" "r"))
8347    (set (match_operand:SI 5 "memory_operand" "=m")
8348         (match_operand:SI 1 "s_register_operand" "r"))
8349    (set (match_operand:SI 6 "memory_operand" "=m")
8350         (match_operand:SI 2 "s_register_operand" "r"))
8351    (set (match_operand:SI 7 "memory_operand" "=m")
8352         (match_operand:SI 3 "s_register_operand" "r"))]
8353   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8354   "*
8355   return emit_stm_seq (operands, 4);
8356   "
8359 (define_peephole
8360   [(set (match_operand:SI 3 "memory_operand" "=m")
8361         (match_operand:SI 0 "s_register_operand" "r"))
8362    (set (match_operand:SI 4 "memory_operand" "=m")
8363         (match_operand:SI 1 "s_register_operand" "r"))
8364    (set (match_operand:SI 5 "memory_operand" "=m")
8365         (match_operand:SI 2 "s_register_operand" "r"))]
8366   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8367   "*
8368   return emit_stm_seq (operands, 3);
8369   "
8372 (define_peephole
8373   [(set (match_operand:SI 2 "memory_operand" "=m")
8374         (match_operand:SI 0 "s_register_operand" "r"))
8375    (set (match_operand:SI 3 "memory_operand" "=m")
8376         (match_operand:SI 1 "s_register_operand" "r"))]
8377   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8378   "*
8379   return emit_stm_seq (operands, 2);
8380   "
8383 (define_split
8384   [(set (match_operand:SI 0 "s_register_operand" "")
8385         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8386                        (const_int 0))
8387                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8388                          [(match_operand:SI 3 "s_register_operand" "")
8389                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
8390    (clobber (match_operand:SI 5 "s_register_operand" ""))]
8391   "TARGET_ARM"
8392   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8393    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8394                               (match_dup 5)))]
8395   ""
8398 ;; This split can be used because CC_Z mode implies that the following
8399 ;; branch will be an equality, or an unsigned inequality, so the sign
8400 ;; extension is not needed.
8402 (define_split
8403   [(set (reg:CC_Z CC_REGNUM)
8404         (compare:CC_Z
8405          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8406                     (const_int 24))
8407          (match_operand 1 "const_int_operand" "")))
8408    (clobber (match_scratch:SI 2 ""))]
8409   "TARGET_ARM
8410    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8411        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8412   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8413    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8414   "
8415   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8416   "
8419 (define_expand "prologue"
8420   [(clobber (const_int 0))]
8421   "TARGET_EITHER"
8422   "if (TARGET_ARM)
8423      arm_expand_prologue ();
8424    else
8425      thumb_expand_prologue ();
8426   DONE;
8427   "
8430 (define_expand "epilogue"
8431   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8432   "TARGET_EITHER"
8433   "
8434   if (TARGET_THUMB)
8435     thumb_expand_epilogue ();
8436   else if (USE_RETURN_INSN (FALSE))
8437     {
8438       emit_jump_insn (gen_return ());
8439       DONE;
8440     }
8441   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8442         gen_rtvec (1,
8443                 gen_rtx_RETURN (VOIDmode)),
8444         VUNSPEC_EPILOGUE));
8445   DONE;
8446   "
8449 ;; Note - although unspec_volatile's USE all hard registers,
8450 ;; USEs are ignored after relaod has completed.  Thus we need
8451 ;; to add an unspec of the link register to ensure that flow
8452 ;; does not think that it is unused by the sibcall branch that
8453 ;; will replace the standard function epilogue.
8454 (define_insn "sibcall_epilogue"
8455   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8456               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8457   "TARGET_ARM"
8458   "*
8459   if (USE_RETURN_INSN (FALSE))
8460     return output_return_instruction (const_true_rtx, FALSE, FALSE);
8461   return arm_output_epilogue (FALSE);
8462   "
8463 ;; Length is absolute worst case
8464   [(set_attr "length" "44")
8465    (set_attr "type" "block")
8466    ;; We don't clobber the conditions, but the potential length of this
8467    ;; operation is sufficient to make conditionalizing the sequence 
8468    ;; unlikely to be profitable.
8469    (set_attr "conds" "clob")]
8472 (define_insn "*epilogue_insns"
8473   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8474   "TARGET_EITHER"
8475   "*
8476   if (TARGET_ARM)
8477     return arm_output_epilogue (TRUE);
8478   else /* TARGET_THUMB */
8479     return thumb_unexpanded_epilogue ();
8480   "
8481   ; Length is absolute worst case
8482   [(set_attr "length" "44")
8483    (set_attr "type" "block")
8484    ;; We don't clobber the conditions, but the potential length of this
8485    ;; operation is sufficient to make conditionalizing the sequence 
8486    ;; unlikely to be profitable.
8487    (set_attr "conds" "clob")]
8490 (define_expand "eh_epilogue"
8491   [(use (match_operand:SI 0 "register_operand" ""))
8492    (use (match_operand:SI 1 "register_operand" ""))
8493    (use (match_operand:SI 2 "register_operand" ""))]
8494   "TARGET_EITHER"
8495   "
8496   {
8497     cfun->machine->eh_epilogue_sp_ofs = operands[1];
8498     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8499       {
8500         rtx ra = gen_rtx_REG (Pmode, 2);
8502         emit_move_insn (ra, operands[2]);
8503         operands[2] = ra;
8504       }
8505     /* This is a hack -- we may have crystalized the function type too
8506        early.  */
8507     cfun->machine->func_type = 0;
8508   }"
8511 ;; This split is only used during output to reduce the number of patterns
8512 ;; that need assembler instructions adding to them.  We allowed the setting
8513 ;; of the conditions to be implicit during rtl generation so that
8514 ;; the conditional compare patterns would work.  However this conflicts to
8515 ;; some extent with the conditional data operations, so we have to split them
8516 ;; up again here.
8518 (define_split
8519   [(set (match_operand:SI 0 "s_register_operand" "")
8520         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8521                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8522                          (match_dup 0)
8523                          (match_operand 4 "" "")))
8524    (clobber (reg:CC CC_REGNUM))]
8525   "TARGET_ARM && reload_completed"
8526   [(set (match_dup 5) (match_dup 6))
8527    (cond_exec (match_dup 7)
8528               (set (match_dup 0) (match_dup 4)))]
8529   "
8530   {
8531     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8532                                              operands[2], operands[3]);
8533     enum rtx_code rc = GET_CODE (operands[1]);
8535     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8536     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8537     if (mode == CCFPmode || mode == CCFPEmode)
8538       rc = reverse_condition_maybe_unordered (rc);
8539     else
8540       rc = reverse_condition (rc);
8542     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8543   }"
8546 (define_split
8547   [(set (match_operand:SI 0 "s_register_operand" "")
8548         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8549                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8550                          (match_operand 4 "" "")
8551                          (match_dup 0)))
8552    (clobber (reg:CC CC_REGNUM))]
8553   "TARGET_ARM && reload_completed"
8554   [(set (match_dup 5) (match_dup 6))
8555    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8556               (set (match_dup 0) (match_dup 4)))]
8557   "
8558   {
8559     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8560                                              operands[2], operands[3]);
8562     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8563     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8564   }"
8567 (define_split
8568   [(set (match_operand:SI 0 "s_register_operand" "")
8569         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8570                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8571                          (match_operand 4 "" "")
8572                          (match_operand 5 "" "")))
8573    (clobber (reg:CC CC_REGNUM))]
8574   "TARGET_ARM && reload_completed"
8575   [(set (match_dup 6) (match_dup 7))
8576    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8577               (set (match_dup 0) (match_dup 4)))
8578    (cond_exec (match_dup 8)
8579               (set (match_dup 0) (match_dup 5)))]
8580   "
8581   {
8582     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8583                                              operands[2], operands[3]);
8584     enum rtx_code rc = GET_CODE (operands[1]);
8586     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8587     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8588     if (mode == CCFPmode || mode == CCFPEmode)
8589       rc = reverse_condition_maybe_unordered (rc);
8590     else
8591       rc = reverse_condition (rc);
8593     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8594   }"
8597 (define_split
8598   [(set (match_operand:SI 0 "s_register_operand" "")
8599         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8600                           [(match_operand:SI 2 "s_register_operand" "")
8601                            (match_operand:SI 3 "arm_add_operand" "")])
8602                          (match_operand:SI 4 "arm_rhs_operand" "")
8603                          (not:SI
8604                           (match_operand:SI 5 "s_register_operand" ""))))
8605    (clobber (reg:CC CC_REGNUM))]
8606   "TARGET_ARM && reload_completed"
8607   [(set (match_dup 6) (match_dup 7))
8608    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8609               (set (match_dup 0) (match_dup 4)))
8610    (cond_exec (match_dup 8)
8611               (set (match_dup 0) (not:SI (match_dup 5))))]
8612   "
8613   {
8614     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8615                                              operands[2], operands[3]);
8616     enum rtx_code rc = GET_CODE (operands[1]);
8618     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8619     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8620     if (mode == CCFPmode || mode == CCFPEmode)
8621       rc = reverse_condition_maybe_unordered (rc);
8622     else
8623       rc = reverse_condition (rc);
8625     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8626   }"
8629 (define_insn "*cond_move_not"
8630   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8631         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8632                           [(match_operand 3 "cc_register" "") (const_int 0)])
8633                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8634                          (not:SI
8635                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
8636   "TARGET_ARM"
8637   "@
8638    mvn%D4\\t%0, %2
8639    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8640   [(set_attr "conds" "use")
8641    (set_attr "length" "4,8")]
8644 ;; The next two patterns occur when an AND operation is followed by a
8645 ;; scc insn sequence 
8647 (define_insn "*sign_extract_onebit"
8648   [(set (match_operand:SI 0 "s_register_operand" "=r")
8649         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8650                          (const_int 1)
8651                          (match_operand:SI 2 "const_int_operand" "n")))
8652     (clobber (reg:CC CC_REGNUM))]
8653   "TARGET_ARM"
8654   "*
8655     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8656     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8657     return \"mvnne\\t%0, #0\";
8658   "
8659   [(set_attr "conds" "clob")
8660    (set_attr "length" "8")]
8663 (define_insn "*not_signextract_onebit"
8664   [(set (match_operand:SI 0 "s_register_operand" "=r")
8665         (not:SI
8666          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8667                           (const_int 1)
8668                           (match_operand:SI 2 "const_int_operand" "n"))))
8669    (clobber (reg:CC CC_REGNUM))]
8670   "TARGET_ARM"
8671   "*
8672     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8673     output_asm_insn (\"tst\\t%1, %2\", operands);
8674     output_asm_insn (\"mvneq\\t%0, #0\", operands);
8675     return \"movne\\t%0, #0\";
8676   "
8677   [(set_attr "conds" "clob")
8678    (set_attr "length" "12")]
8681 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8682 ;; expressions.  For simplicity, the first register is also in the unspec
8683 ;; part.
8684 (define_insn "*push_multi"
8685   [(match_parallel 2 "multi_register_push"
8686     [(set (match_operand:BLK 0 "memory_operand" "=m")
8687           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8688                       UNSPEC_PUSH_MULT))])]
8689   "TARGET_ARM"
8690   "*
8691   {
8692     int num_saves = XVECLEN (operands[2], 0);
8693      
8694     /* For the StrongARM at least it is faster to
8695        use STR to store only a single register.  */
8696     if (num_saves == 1)
8697       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8698     else
8699       {
8700         int i;
8701         char pattern[100];
8703         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8705         for (i = 1; i < num_saves; i++)
8706           {
8707             strcat (pattern, \", %|\");
8708             strcat (pattern,
8709                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8710           }
8712         strcat (pattern, \"}\");
8713         output_asm_insn (pattern, operands);
8714       }
8716     return \"\";
8717   }"
8718   [(set_attr "type" "store4")]
8721 (define_insn "stack_tie"
8722   [(set (mem:BLK (scratch))
8723         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8724                      (match_operand:SI 1 "s_register_operand" "r")]
8725                     UNSPEC_PRLG_STK))]
8726   ""
8727   ""
8728   [(set_attr "length" "0")]
8731 ;; Similarly for the floating point registers
8732 (define_insn "*push_fp_multi"
8733   [(match_parallel 2 "multi_register_push"
8734     [(set (match_operand:BLK 0 "memory_operand" "=m")
8735           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8736                       UNSPEC_PUSH_MULT))])]
8737   "TARGET_ARM"
8738   "*
8739   {
8740     char pattern[100];
8742     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8743     output_asm_insn (pattern, operands);
8744     return \"\";
8745   }"
8746   [(set_attr "type" "f_store")]
8749 ;; Special patterns for dealing with the constant pool
8751 (define_insn "align_4"
8752   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8753   "TARGET_EITHER"
8754   "*
8755   assemble_align (32);
8756   return \"\";
8757   "
8760 (define_insn "align_8"
8761   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
8762   "TARGET_REALLY_IWMMXT"
8763   "*
8764   assemble_align (64);
8765   return \"\";
8766   "
8769 (define_insn "consttable_end"
8770   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8771   "TARGET_EITHER"
8772   "*
8773   making_const_table = FALSE;
8774   return \"\";
8775   "
8778 (define_insn "consttable_1"
8779   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8780   "TARGET_THUMB"
8781   "*
8782   making_const_table = TRUE;
8783   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8784   assemble_zeros (3);
8785   return \"\";
8786   "
8787   [(set_attr "length" "4")]
8790 (define_insn "consttable_2"
8791   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8792   "TARGET_THUMB"
8793   "*
8794   making_const_table = TRUE;
8795   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8796   assemble_zeros (2);
8797   return \"\";
8798   "
8799   [(set_attr "length" "4")]
8802 (define_insn "consttable_4"
8803   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8804   "TARGET_EITHER"
8805   "*
8806   {
8807     making_const_table = TRUE;
8808     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8809       {
8810       case MODE_FLOAT:
8811       {
8812         REAL_VALUE_TYPE r;
8813         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8814         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8815         break;
8816       }
8817       default:
8818         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8819         break;
8820       }
8821     return \"\";
8822   }"
8823   [(set_attr "length" "4")]
8826 (define_insn "consttable_8"
8827   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8828   "TARGET_EITHER"
8829   "*
8830   {
8831     making_const_table = TRUE;
8832     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8833       {
8834        case MODE_FLOAT:
8835         {
8836           REAL_VALUE_TYPE r;
8837           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8838           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8839           break;
8840         }
8841       default:
8842         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8843         break;
8844       }
8845     return \"\";
8846   }"
8847   [(set_attr "length" "8")]
8850 ;; Miscellaneous Thumb patterns
8852 (define_expand "tablejump"
8853   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
8854               (use (label_ref (match_operand 1 "" "")))])]
8855   "TARGET_THUMB"
8856   "
8857   if (flag_pic)
8858     {
8859       /* Hopefully, CSE will eliminate this copy.  */
8860       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8861       rtx reg2 = gen_reg_rtx (SImode);
8863       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8864       operands[0] = reg2;
8865     }
8866   "
8869 (define_insn "*thumb_tablejump"
8870   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8871    (use (label_ref (match_operand 1 "" "")))]
8872   "TARGET_THUMB"
8873   "mov\\t%|pc, %0"
8874   [(set_attr "length" "2")]
8877 ;; V5 Instructions,
8879 (define_insn "clzsi2"
8880   [(set (match_operand:SI 0 "s_register_operand" "=r")
8881         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8882   "TARGET_ARM && arm_arch5"
8883   "clz%?\\t%0, %1"
8884   [(set_attr "predicable" "yes")])
8886 (define_expand "ffssi2"
8887   [(set (match_operand:SI 0 "s_register_operand" "")
8888         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
8889   "TARGET_ARM && arm_arch5"
8890   "
8891   {
8892     rtx t1, t2, t3;
8894     t1 = gen_reg_rtx (SImode);
8895     t2 = gen_reg_rtx (SImode);
8896     t3 = gen_reg_rtx (SImode);
8898     emit_insn (gen_negsi2 (t1, operands[1]));
8899     emit_insn (gen_andsi3 (t2, operands[1], t1));
8900     emit_insn (gen_clzsi2 (t3, t2));
8901     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
8902     DONE;
8903   }"
8906 (define_expand "ctzsi2"
8907   [(set (match_operand:SI 0 "s_register_operand" "")
8908         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
8909   "TARGET_ARM && arm_arch5"
8910   "
8911   {
8912     rtx t1, t2, t3;
8914     t1 = gen_reg_rtx (SImode);
8915     t2 = gen_reg_rtx (SImode);
8916     t3 = gen_reg_rtx (SImode);
8918     emit_insn (gen_negsi2 (t1, operands[1]));
8919     emit_insn (gen_andsi3 (t2, operands[1], t1));
8920     emit_insn (gen_clzsi2 (t3, t2));
8921     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
8922     DONE;
8923   }"
8926 ;; V5E instructions.
8928 (define_insn "prefetch"
8929   [(prefetch (match_operand:SI 0 "address_operand" "p")
8930              (match_operand:SI 1 "" "")
8931              (match_operand:SI 2 "" ""))]
8932   "TARGET_ARM && arm_arch5e"
8933   "pld\\t%a0")
8935 ;; General predication pattern
8937 (define_cond_exec
8938   [(match_operator 0 "arm_comparison_operator"
8939     [(match_operand 1 "cc_register" "")
8940      (const_int 0)])]
8941   "TARGET_ARM"
8942   ""
8945 (define_insn "prologue_use"
8946   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
8947   ""
8948   "%@ %0 needed for prologue"
8951 ;; Load the FPA co-processor patterns
8952 (include "fpa.md")
8953 ;; Load the Maverick co-processor patterns
8954 (include "cirrus.md")
8955 ;; Load the Intel Wireless Multimedia Extension patterns
8956 (include "iwmmxt.md")