* arm.md (compare_scc): Use shorter sequence for EQ case.
[official-gcc.git] / gcc / config / arm / arm.md
blob6fb75d0d93dbe059ee018dd7506020a6958073ca
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   ]
81 ;; UNSPEC_VOLATILE Usage:
83 (define_constants
84   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
85                         ;   insn in the code.
86    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
87                         ;   instruction epilogue sequence that isn't expanded
88                         ;   into normal RTL.  Used for both normal and sibcall
89                         ;   epilogues.
90    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
91                         ;   for inlined constants.
92    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
93                         ;   table.
94    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
95                         ;   an 8-bit object.
96    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
97                         ;   a 16-bit object.
98    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
99                         ;   a 32-bit object.
100    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
101                         ;   a 64-bit object.
102   ]
105 ;;---------------------------------------------------------------------------
106 ;; Attributes
108 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
109 ; generating ARM code.  This is used to control the length of some insn
110 ; patterns that share the same RTL in both ARM and Thumb code.
111 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
113 ; PROG_MODE attribute is used to determine whether condition codes are
114 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
115 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
116 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
118 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
119 ; scheduling decisions for the load unit and the multiplier.
120 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
122 ;; Operand number of an input operand that is shifted.  Zero if the
123 ;; given instruction does not shift one of its input operands.
124 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
125 (define_attr "shift" "" (const_int 0))
127 ; Floating Point Unit.  If we only have floating point emulation, then there
128 ; is no point in scheduling the floating point insns.  (Well, for best
129 ; performance we should try and group them together).
130 (define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
131   (const (symbol_ref "arm_fpu_attr")))
133 ; LENGTH of an instruction (in bytes)
134 (define_attr "length" "" (const_int 4))
136 ; POOL_RANGE is how far away from a constant pool entry that this insn
137 ; can be placed.  If the distance is zero, then this insn will never
138 ; reference the pool.
139 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
140 ; before its address.
141 (define_attr "pool_range" "" (const_int 0))
142 (define_attr "neg_pool_range" "" (const_int 0))
144 ; An assembler sequence may clobber the condition codes without us knowing.
145 ; If such an insn references the pool, then we have no way of knowing how,
146 ; so use the most conservative value for pool_range.
147 (define_asm_attributes
148  [(set_attr "conds" "clob")
149   (set_attr "length" "4")
150   (set_attr "pool_range" "250")])
152 ; TYPE attribute is used to detect floating point instructions which, if
153 ; running on a co-processor can run in parallel with other, basic instructions
154 ; If write-buffer scheduling is enabled then it can also be used in the
155 ; scheduling of writes.
157 ; Classification of each insn
158 ; normal        any data instruction that doesn't hit memory or fp regs
159 ; mult          a multiply instruction
160 ; block         blockage insn, this blocks all functional units
161 ; float         a floating point arithmetic operation (subject to expansion)
162 ; fdivd         DFmode floating point division
163 ; fdivs         SFmode floating point division
164 ; fmul          Floating point multiply
165 ; ffmul         Fast floating point multiply
166 ; farith        Floating point arithmetic (4 cycle)
167 ; ffarith       Fast floating point arithmetic (2 cycle)
168 ; float_em      a floating point arithmetic operation that is normally emulated
169 ;               even on a machine with an fpa.
170 ; f_load        a floating point load from memory
171 ; f_store       a floating point store to memory
172 ; f_mem_r       a transfer of a floating point register to a real reg via mem
173 ; r_mem_f       the reverse of f_mem_r
174 ; f_2_r         fast transfer float to arm (no memory needed)
175 ; r_2_f         fast transfer arm to float
176 ; call          a subroutine call
177 ; load          any load from memory
178 ; store1        store 1 word to memory from arm registers
179 ; store2        store 2 words
180 ; store3        store 3 words
181 ; store4        store 4 words
182 ;  Additions for Cirrus Maverick co-processor:
183 ; mav_farith    Floating point arithmetic (4 cycle)
184 ; mav_dmult     Double multiplies (7 cycle)
186 (define_attr "type"
187         "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" 
188         (const_string "normal"))
190 ; Load scheduling, set from the arm_ld_sched variable
191 ; initialized by arm_override_options() 
192 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
194 ; condition codes: this one is used by final_prescan_insn to speed up
195 ; conditionalizing instructions.  It saves having to scan the rtl to see if
196 ; it uses or alters the condition codes.
198 ; USE means that the condition codes are used by the insn in the process of
199 ;   outputting code, this means (at present) that we can't use the insn in
200 ;   inlined branches
202 ; SET means that the purpose of the insn is to set the condition codes in a
203 ;   well defined manner.
205 ; CLOB means that the condition codes are altered in an undefined manner, if
206 ;   they are altered at all
208 ; JUMP_CLOB is used when the condition cannot be represented by a single
209 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
211 ; NOCOND means that the condition codes are neither altered nor affect the
212 ;   output of this insn
214 (define_attr "conds" "use,set,clob,jump_clob,nocond"
215         (if_then_else (eq_attr "type" "call")
216          (if_then_else (eq_attr "prog_mode" "prog32")
217           (const_string "clob") (const_string "nocond"))
218          (const_string "nocond")))
220 ; Predicable means that the insn can be conditionally executed based on
221 ; an automatically added predicate (additional patterns are generated by 
222 ; gen...).  We default to 'no' because no Thumb patterns match this rule
223 ; and not all ARM patterns do.
224 (define_attr "predicable" "no,yes" (const_string "no"))
226 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
227 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
228 ; suffer blockages enough to warrent modelling this (and it can adversely
229 ; affect the schedule).
230 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
232 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
233 ; to stall the processor.  Used with model_wbuf above.
234 (define_attr "write_conflict" "no,yes"
235   (if_then_else (eq_attr "type"
236                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
237                 (const_string "yes")
238                 (const_string "no")))
240 ; Classify the insns into those that take one cycle and those that take more
241 ; than one on the main cpu execution unit.
242 (define_attr "core_cycles" "single,multi"
243   (if_then_else (eq_attr "type"
244                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
245                 (const_string "single")
246                 (const_string "multi")))
248 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
249 ;; distant label.  Only applicable to Thumb code.
250 (define_attr "far_jump" "yes,no" (const_string "no"))
252 ;; (define_function_unit {name} {num-units} {n-users} {test}
253 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
255 ;;--------------------------------------------------------------------
256 ;; Write buffer
257 ;;--------------------------------------------------------------------
258 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
260 ; The write buffer on some of the arm6 processors is hard to model exactly.
261 ; There is room in the buffer for up to two addresses and up to eight words
262 ; of memory, but the two needn't be split evenly.  When writing the two
263 ; addresses are fully pipelined.  However, a read from memory that is not
264 ; currently in the cache will block until the writes have completed.
265 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
266 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
267 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
268 ; cycle to add as well.
270 (define_function_unit "write_buf" 1 2
271   (and (eq_attr "model_wbuf" "yes")
272        (eq_attr "type" "store1,r_mem_f")) 5 3)
273 (define_function_unit "write_buf" 1 2 
274   (and (eq_attr "model_wbuf" "yes")
275        (eq_attr "type" "store2")) 7 4)
276 (define_function_unit "write_buf" 1 2
277   (and (eq_attr "model_wbuf" "yes")
278        (eq_attr "type" "store3")) 9 5)
279 (define_function_unit "write_buf" 1 2
280   (and (eq_attr "model_wbuf" "yes")
281        (eq_attr "type" "store4")) 11 6)
283 ;;--------------------------------------------------------------------
284 ;; Write blockage unit
285 ;;--------------------------------------------------------------------
286 ; The write_blockage unit models (partially), the fact that reads will stall
287 ; until the write buffer empties.
288 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
289 ; so we don't model them here
290 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
291                                                 (eq_attr "type" "store1")) 5 5
292         [(eq_attr "write_conflict" "yes")])
293 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
294                                                 (eq_attr "type" "store2")) 7 7
295         [(eq_attr "write_conflict" "yes")])
296 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
297                                                 (eq_attr "type" "store3")) 9 9
298         [(eq_attr "write_conflict" "yes")])
299 (define_function_unit "write_blockage" 1 0
300         (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
301         [(eq_attr "write_conflict" "yes")])
302 (define_function_unit "write_blockage" 1 0
303         (and (eq_attr "model_wbuf" "yes")
304              (eq_attr "write_conflict" "yes")) 1 1)
306 ;;--------------------------------------------------------------------
307 ;; Core unit
308 ;;--------------------------------------------------------------------
309 ; Everything must spend at least one cycle in the core unit
310 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
312 (define_function_unit "core" 1 0
313   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
315 (define_function_unit "core" 1 0
316   (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
318 ;; We do not need to conditionalize the define_function_unit immediately
319 ;; above.  This one will be ignored for anything other than xscale
320 ;; compiles and for xscale compiles it provides a larger delay
321 ;; and the scheduler will DTRT.
322 ;; FIXME: this test needs to be revamped to not depend on this feature 
323 ;; of the scheduler.
325 (define_function_unit "core" 1 0
326   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
327        (eq_attr "is_xscale" "yes"))
328    3 1)
330 (define_function_unit "core" 1 0
331   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
333 (define_function_unit "core" 1 0
334   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
336 (define_function_unit "core" 1 0
337   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
339 (define_function_unit "core" 1 0
340   (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
342 (define_function_unit "core" 1 0
343   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
345 (define_function_unit "core" 1 0
346   (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
348 (define_function_unit "core" 1 0
349   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
350        (eq_attr "type" "mult")) 4 4)
352 (define_function_unit "core" 1 0
353   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
354        (eq_attr "type" "mult")) 3 2)
356 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
358 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
360 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
362 (define_function_unit "core" 1 0
363   (and (eq_attr "core_cycles" "multi")
364        (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
366 ;;---------------------------------------------------------------------------
367 ;; Insn patterns
369 ;; Addition insns.
371 ;; Note: For DImode insns, there is normally no reason why operands should
372 ;; not be in the same register, what we don't want is for something being
373 ;; written to partially overlap something that is an input.
374 ;; Cirrus 64bit additions should not be split because we have a native
375 ;; 64bit addition instructions.
377 (define_expand "adddi3"
378  [(parallel
379    [(set (match_operand:DI           0 "s_register_operand" "")
380           (plus:DI (match_operand:DI 1 "s_register_operand" "")
381                    (match_operand:DI 2 "s_register_operand" "")))
382     (clobber (reg:CC CC_REGNUM))])]
383   "TARGET_EITHER"
384   "
385   if (TARGET_CIRRUS)
386     {
387       if (!cirrus_fp_register (operands[0], DImode))
388         operands[0] = force_reg (DImode, operands[0]);
389       if (!cirrus_fp_register (operands[1], DImode))
390         operands[1] = force_reg (DImode, operands[1]);
391       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
392       DONE;
393     }
395   if (TARGET_THUMB)
396     {
397       if (GET_CODE (operands[1]) != REG)
398         operands[1] = force_reg (SImode, operands[1]);
399       if (GET_CODE (operands[2]) != REG)
400         operands[2] = force_reg (SImode, operands[2]);
401      }
402   "
405 (define_insn "*thumb_adddi3"
406   [(set (match_operand:DI          0 "register_operand" "=l")
407         (plus:DI (match_operand:DI 1 "register_operand" "%0")
408                  (match_operand:DI 2 "register_operand" "l")))
409    (clobber (reg:CC CC_REGNUM))
410   ]
411   "TARGET_THUMB"
412   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
413   [(set_attr "length" "4")]
416 (define_insn_and_split "*arm_adddi3"
417   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
418         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
419                  (match_operand:DI 2 "s_register_operand" "r,  0")))
420    (clobber (reg:CC CC_REGNUM))]
421   "TARGET_ARM && !TARGET_CIRRUS"
422   "#"
423   "TARGET_ARM && reload_completed"
424   [(parallel [(set (reg:CC_C CC_REGNUM)
425                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
426                                  (match_dup 1)))
427               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
428    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
429                                (plus:SI (match_dup 4) (match_dup 5))))]
430   "
431   {
432     operands[3] = gen_highpart (SImode, operands[0]);
433     operands[0] = gen_lowpart (SImode, operands[0]);
434     operands[4] = gen_highpart (SImode, operands[1]);
435     operands[1] = gen_lowpart (SImode, operands[1]);
436     operands[5] = gen_highpart (SImode, operands[2]);
437     operands[2] = gen_lowpart (SImode, operands[2]);
438   }"
439   [(set_attr "conds" "clob")
440    (set_attr "length" "8")]
443 (define_insn_and_split "*adddi_sesidi_di"
444   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
445         (plus:DI (sign_extend:DI
446                   (match_operand:SI 2 "s_register_operand" "r,r"))
447                  (match_operand:DI 1 "s_register_operand" "r,0")))
448    (clobber (reg:CC CC_REGNUM))]
449   "TARGET_ARM && !TARGET_CIRRUS"
450   "#"
451   "TARGET_ARM && reload_completed"
452   [(parallel [(set (reg:CC_C CC_REGNUM)
453                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
454                                  (match_dup 1)))
455               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
456    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
457                                (plus:SI (ashiftrt:SI (match_dup 2)
458                                                      (const_int 31))
459                                         (match_dup 4))))]
460   "
461   {
462     operands[3] = gen_highpart (SImode, operands[0]);
463     operands[0] = gen_lowpart (SImode, operands[0]);
464     operands[4] = gen_highpart (SImode, operands[1]);
465     operands[1] = gen_lowpart (SImode, operands[1]);
466     operands[2] = gen_lowpart (SImode, operands[2]);
467   }"
468   [(set_attr "conds" "clob")
469    (set_attr "length" "8")]
472 (define_insn_and_split "*adddi_zesidi_di"
473   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
474         (plus:DI (zero_extend:DI
475                   (match_operand:SI 2 "s_register_operand" "r,r"))
476                  (match_operand:DI 1 "s_register_operand" "r,0")))
477    (clobber (reg:CC CC_REGNUM))]
478   "TARGET_ARM && !TARGET_CIRRUS"
479   "#"
480   "TARGET_ARM && reload_completed"
481   [(parallel [(set (reg:CC_C CC_REGNUM)
482                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
483                                  (match_dup 1)))
484               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
485    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
486                                (plus:SI (match_dup 4) (const_int 0))))]
487   "
488   {
489     operands[3] = gen_highpart (SImode, operands[0]);
490     operands[0] = gen_lowpart (SImode, operands[0]);
491     operands[4] = gen_highpart (SImode, operands[1]);
492     operands[1] = gen_lowpart (SImode, operands[1]);
493     operands[2] = gen_lowpart (SImode, operands[2]);
494   }"
495   [(set_attr "conds" "clob")
496    (set_attr "length" "8")]
499 (define_expand "addsi3"
500   [(set (match_operand:SI          0 "s_register_operand" "")
501         (plus:SI (match_operand:SI 1 "s_register_operand" "")
502                  (match_operand:SI 2 "reg_or_int_operand" "")))]
503   "TARGET_EITHER"
504   "
505   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
506     {
507       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
508                           operands[1],
509                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
510       DONE;
511     }
512   "
515 ; If there is a scratch available, this will be faster than synthesising the
516 ; addition.
517 (define_peephole2
518   [(match_scratch:SI 3 "r")
519    (set (match_operand:SI          0 "s_register_operand" "")
520         (plus:SI (match_operand:SI 1 "s_register_operand" "")
521                  (match_operand:SI 2 "const_int_operand"  "")))]
522   "TARGET_ARM &&
523    !(const_ok_for_arm (INTVAL (operands[2]))
524      || const_ok_for_arm (-INTVAL (operands[2])))
525     && const_ok_for_arm (~INTVAL (operands[2]))"
526   [(set (match_dup 3) (match_dup 2))
527    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
528   ""
531 (define_insn_and_split "*arm_addsi3"
532   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
533         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
534                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
535   "TARGET_ARM"
536   "@
537    add%?\\t%0, %1, %2
538    sub%?\\t%0, %1, #%n2
539    #"
540   "TARGET_ARM &&
541    GET_CODE (operands[2]) == CONST_INT
542    && !(const_ok_for_arm (INTVAL (operands[2]))
543         || const_ok_for_arm (-INTVAL (operands[2])))"
544   [(clobber (const_int 0))]
545   "
546   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
547                       operands[1], 0);
548   DONE;
549   "
550   [(set_attr "length" "4,4,16")
551    (set_attr "predicable" "yes")]
554 ;; Register group 'k' is a single register group containing only the stack
555 ;; register.  Trying to reload it will always fail catastrophically,
556 ;; so never allow those alternatives to match if reloading is needed.
558 (define_insn "*thumb_addsi3"
559   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
560         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
561                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
562   "TARGET_THUMB"
563   "*
564    static const char * const asms[] = 
565    {
566      \"add\\t%0, %0, %2\",
567      \"sub\\t%0, %0, #%n2\",
568      \"add\\t%0, %1, %2\",
569      \"add\\t%0, %0, %2\",
570      \"add\\t%0, %0, %2\",
571      \"add\\t%0, %1, %2\",
572      \"add\\t%0, %1, %2\"
573    };
574    if ((which_alternative == 2 || which_alternative == 6)
575        && GET_CODE (operands[2]) == CONST_INT
576        && INTVAL (operands[2]) < 0)
577      return \"sub\\t%0, %1, #%n2\";
578    return asms[which_alternative];
579   "
580   [(set_attr "length" "2")]
583 ;; Reloading and elimination of the frame pointer can
584 ;; sometimes cause this optimization to be missed.
585 (define_peephole2
586   [(set (match_operand:SI 0 "register_operand" "")
587         (match_operand:SI 1 "const_int_operand" ""))
588    (set (match_dup 0)
589         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
590   "TARGET_THUMB
591    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
592    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
593    && (INTVAL (operands[1]) & 3) == 0"
594   [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
595   ""
598 (define_insn "*addsi3_compare0"
599   [(set (reg:CC_NOOV CC_REGNUM)
600         (compare:CC_NOOV
601          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
602                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
603          (const_int 0)))
604    (set (match_operand:SI 0 "s_register_operand" "=r,r")
605         (plus:SI (match_dup 1) (match_dup 2)))]
606   "TARGET_ARM"
607   "@
608    add%?s\\t%0, %1, %2
609    sub%?s\\t%0, %1, #%n2"
610   [(set_attr "conds" "set")]
613 (define_insn "*addsi3_compare0_scratch"
614   [(set (reg:CC_NOOV CC_REGNUM)
615         (compare:CC_NOOV
616          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
617                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
618          (const_int 0)))]
619   "TARGET_ARM"
620   "@
621    cmn%?\\t%0, %1
622    cmp%?\\t%0, #%n1"
623   [(set_attr "conds" "set")]
626 ;; These patterns are the same ones as the two regular addsi3_compare0
627 ;; patterns, except we write them slightly different - the combiner
628 ;; tends to generate them this way.
629 (define_insn "*addsi3_compare0_for_combiner"
630   [(set (reg:CC CC_REGNUM)
631         (compare:CC
632          (match_operand:SI 1 "s_register_operand" "r,r")
633          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
634    (set (match_operand:SI 0 "s_register_operand" "=r,r")
635         (plus:SI (match_dup 1) (match_dup 2)))]
636   "TARGET_ARM"
637   "@
638    add%?s\\t%0, %1, %2
639    sub%?s\\t%0, %1, #%n2"
640   [(set_attr "conds" "set")]
643 (define_insn "*addsi3_compare0_scratch_for_combiner"
644   [(set (reg:CC CC_REGNUM)
645         (compare:CC
646          (match_operand:SI 0 "s_register_operand" "r,r")
647          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
648   "TARGET_ARM"
649   "@
650    cmn%?\\t%0, %1
651    cmp%?\\t%0, #%n1"
652   [(set_attr "conds" "set")]
655 ;; The next four insns work because they compare the result with one of
656 ;; the operands, and we know that the use of the condition code is
657 ;; either GEU or LTU, so we can use the carry flag from the addition
658 ;; instead of doing the compare a second time.
659 (define_insn "*addsi3_compare_op1"
660   [(set (reg:CC_C CC_REGNUM)
661         (compare:CC_C
662          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
663                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
664          (match_dup 1)))
665    (set (match_operand:SI 0 "s_register_operand" "=r,r")
666         (plus:SI (match_dup 1) (match_dup 2)))]
667   "TARGET_ARM"
668   "@
669    add%?s\\t%0, %1, %2
670    sub%?s\\t%0, %1, #%n2"
671   [(set_attr "conds" "set")]
674 (define_insn "*addsi3_compare_op2"
675   [(set (reg:CC_C CC_REGNUM)
676         (compare:CC_C
677          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
678                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
679          (match_dup 2)))
680    (set (match_operand:SI 0 "s_register_operand" "=r,r")
681         (plus:SI (match_dup 1) (match_dup 2)))]
682   "TARGET_ARM"
683   "@
684    add%?s\\t%0, %1, %2
685    sub%?s\\t%0, %1, #%n2"
686   [(set_attr "conds" "set")]
689 (define_insn "*compare_addsi2_op0"
690   [(set (reg:CC_C CC_REGNUM)
691         (compare:CC_C
692          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
693                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
694          (match_dup 0)))]
695   "TARGET_ARM"
696   "@
697    cmn%?\\t%0, %1
698    cmp%?\\t%0, #%n1"
699   [(set_attr "conds" "set")]
702 (define_insn "*compare_addsi2_op1"
703   [(set (reg:CC_C CC_REGNUM)
704         (compare:CC_C
705          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
706                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
707          (match_dup 1)))]
708   "TARGET_ARM"
709   "@
710    cmn%?\\t%0, %1
711    cmp%?\\t%0, #%n1"
712   [(set_attr "conds" "set")]
715 (define_insn "*addsi3_carryin"
716   [(set (match_operand:SI 0 "s_register_operand" "=r")
717         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
718                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
719                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
720   "TARGET_ARM"
721   "adc%?\\t%0, %1, %2"
722   [(set_attr "conds" "use")]
725 (define_insn "*addsi3_carryin_shift"
726   [(set (match_operand:SI 0 "s_register_operand" "")
727         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
728                  (plus:SI
729                    (match_operator:SI 2 "shift_operator"
730                       [(match_operand:SI 3 "s_register_operand" "")
731                        (match_operand:SI 4 "reg_or_int_operand" "")])
732                     (match_operand:SI 1 "s_register_operand" ""))))]
733   "TARGET_ARM"
734   "adc%?\\t%0, %1, %3%S2"
735   [(set_attr "conds" "use")]
738 (define_insn "*addsi3_carryin_alt1"
739   [(set (match_operand:SI 0 "s_register_operand" "=r")
740         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
741                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
742                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
743   "TARGET_ARM"
744   "adc%?\\t%0, %1, %2"
745   [(set_attr "conds" "use")]
748 (define_insn "*addsi3_carryin_alt2"
749   [(set (match_operand:SI 0 "s_register_operand" "=r")
750         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
751                           (match_operand:SI 1 "s_register_operand" "r"))
752                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
753   "TARGET_ARM"
754   "adc%?\\t%0, %1, %2"
755   [(set_attr "conds" "use")]
758 (define_insn "*addsi3_carryin_alt3"
759   [(set (match_operand:SI 0 "s_register_operand" "=r")
760         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
761                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
762                  (match_operand:SI 1 "s_register_operand" "r")))]
763   "TARGET_ARM"
764   "adc%?\\t%0, %1, %2"
765   [(set_attr "conds" "use")]
768 (define_insn "incscc"
769   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
770         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
771                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
772                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
773   "TARGET_ARM"
774   "@
775   add%d2\\t%0, %1, #1
776   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
777   [(set_attr "conds" "use")
778    (set_attr "length" "4,8")]
781 (define_expand "addsf3"
782   [(set (match_operand:SF          0 "s_register_operand" "")
783         (plus:SF (match_operand:SF 1 "s_register_operand" "")
784                  (match_operand:SF 2 "fpa_add_operand" "")))]
785   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
786   "
787   if (TARGET_CIRRUS
788       && !cirrus_fp_register (operands[2], SFmode))
789     operands[2] = force_reg (SFmode, operands[2]);
792 (define_expand "adddf3"
793   [(set (match_operand:DF          0 "s_register_operand" "")
794         (plus:DF (match_operand:DF 1 "s_register_operand" "")
795                  (match_operand:DF 2 "fpa_add_operand" "")))]
796   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
797   "
798   if (TARGET_CIRRUS
799       && !cirrus_fp_register (operands[2], DFmode))
800     operands[2] = force_reg (DFmode, operands[2]);
803 (define_expand "subdi3"
804  [(parallel
805    [(set (match_operand:DI            0 "s_register_operand" "")
806           (minus:DI (match_operand:DI 1 "s_register_operand" "")
807                     (match_operand:DI 2 "s_register_operand" "")))
808     (clobber (reg:CC CC_REGNUM))])]
809   "TARGET_EITHER"
810   "
811   if (TARGET_CIRRUS
812       && TARGET_ARM
813       && cirrus_fp_register (operands[0], DImode)
814       && cirrus_fp_register (operands[1], DImode))
815     {
816       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
817       DONE;
818     }
820   if (TARGET_THUMB)
821     {
822       if (GET_CODE (operands[1]) != REG)
823         operands[1] = force_reg (SImode, operands[1]);
824       if (GET_CODE (operands[2]) != REG)
825         operands[2] = force_reg (SImode, operands[2]);
826      }  
827   "
830 (define_insn "*arm_subdi3"
831   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
832         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
833                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
834    (clobber (reg:CC CC_REGNUM))]
835   "TARGET_ARM"
836   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
837   [(set_attr "conds" "clob")
838    (set_attr "length" "8")]
841 (define_insn "*thumb_subdi3"
842   [(set (match_operand:DI           0 "register_operand" "=l")
843         (minus:DI (match_operand:DI 1 "register_operand"  "0")
844                   (match_operand:DI 2 "register_operand"  "l")))
845    (clobber (reg:CC CC_REGNUM))]
846   "TARGET_THUMB"
847   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
848   [(set_attr "length" "4")]
851 (define_insn "*subdi_di_zesidi"
852   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
853         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
854                   (zero_extend:DI
855                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
856    (clobber (reg:CC CC_REGNUM))]
857   "TARGET_ARM"
858   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
859   [(set_attr "conds" "clob")
860    (set_attr "length" "8")]
863 (define_insn "*subdi_di_sesidi"
864   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
865         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
866                   (sign_extend:DI
867                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
868    (clobber (reg:CC CC_REGNUM))]
869   "TARGET_ARM"
870   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
871   [(set_attr "conds" "clob")
872    (set_attr "length" "8")]
875 (define_insn "*subdi_zesidi_di"
876   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
877         (minus:DI (zero_extend:DI
878                    (match_operand:SI 2 "s_register_operand"  "r,r"))
879                   (match_operand:DI  1 "s_register_operand" "?r,0")))
880    (clobber (reg:CC CC_REGNUM))]
881   "TARGET_ARM"
882   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
883   [(set_attr "conds" "clob")
884    (set_attr "length" "8")]
887 (define_insn "*subdi_sesidi_di"
888   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
889         (minus:DI (sign_extend:DI
890                    (match_operand:SI 2 "s_register_operand"   "r,r"))
891                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
892    (clobber (reg:CC CC_REGNUM))]
893   "TARGET_ARM"
894   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
895   [(set_attr "conds" "clob")
896    (set_attr "length" "8")]
899 (define_insn "*subdi_zesidi_zesidi"
900   [(set (match_operand:DI            0 "s_register_operand" "=r")
901         (minus:DI (zero_extend:DI
902                    (match_operand:SI 1 "s_register_operand"  "r"))
903                   (zero_extend:DI
904                    (match_operand:SI 2 "s_register_operand"  "r"))))
905    (clobber (reg:CC CC_REGNUM))]
906   "TARGET_ARM"
907   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
908   [(set_attr "conds" "clob")
909    (set_attr "length" "8")]
912 (define_expand "subsi3"
913   [(set (match_operand:SI           0 "s_register_operand" "")
914         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
915                   (match_operand:SI 2 "s_register_operand" "")))]
916   "TARGET_EITHER"
917   "
918   if (GET_CODE (operands[1]) == CONST_INT)
919     {
920       if (TARGET_ARM)
921         {
922           arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
923                               operands[2],
924                               (no_new_pseudos ? 0
925                                :  preserve_subexpressions_p ()));
926           DONE;
927         }
928       else /* TARGET_THUMB */
929         operands[1] = force_reg (SImode, operands[1]);
930     }
931   "
934 (define_insn "*thumb_subsi3_insn"
935   [(set (match_operand:SI           0 "register_operand" "=l")
936         (minus:SI (match_operand:SI 1 "register_operand" "l")
937                   (match_operand:SI 2 "register_operand" "l")))]
938   "TARGET_THUMB"
939   "sub\\t%0, %1, %2"
940   [(set_attr "length" "2")]
943 (define_insn_and_split "*arm_subsi3_insn"
944   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
945         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
946                   (match_operand:SI 2 "s_register_operand" "r,r")))]
947   "TARGET_ARM"
948   "@
949    rsb%?\\t%0, %2, %1
950    #"
951   "TARGET_ARM
952    && GET_CODE (operands[1]) == CONST_INT
953    && !const_ok_for_arm (INTVAL (operands[1]))"
954   [(clobber (const_int 0))]
955   "
956   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
957                       operands[2], 0);
958   DONE;
959   "
960   [(set_attr "length" "4,16")
961    (set_attr "predicable" "yes")]
964 (define_peephole2
965   [(match_scratch:SI 3 "r")
966    (set (match_operand:SI           0 "s_register_operand" "")
967         (minus:SI (match_operand:SI 1 "const_int_operand" "")
968                   (match_operand:SI 2 "s_register_operand" "")))]
969   "TARGET_ARM
970    && !const_ok_for_arm (INTVAL (operands[1]))
971    && const_ok_for_arm (~INTVAL (operands[1]))"
972   [(set (match_dup 3) (match_dup 1))
973    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
974   ""
977 (define_insn "*subsi3_compare0"
978   [(set (reg:CC_NOOV CC_REGNUM)
979         (compare:CC_NOOV
980          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
981                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
982          (const_int 0)))
983    (set (match_operand:SI 0 "s_register_operand" "=r,r")
984         (minus:SI (match_dup 1) (match_dup 2)))]
985   "TARGET_ARM"
986   "@
987    sub%?s\\t%0, %1, %2
988    rsb%?s\\t%0, %2, %1"
989   [(set_attr "conds" "set")]
992 (define_insn "decscc"
993   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
994         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
995                   (match_operator:SI 2 "arm_comparison_operator"
996                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
997   "TARGET_ARM"
998   "@
999    sub%d2\\t%0, %1, #1
1000    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1001   [(set_attr "conds" "use")
1002    (set_attr "length" "*,8")]
1005 (define_expand "subsf3"
1006   [(set (match_operand:SF           0 "s_register_operand" "")
1007         (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1008                   (match_operand:SF 2 "fpa_rhs_operand" "")))]
1009   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1010   "
1011   if (TARGET_CIRRUS)
1012     {
1013       if (!cirrus_fp_register (operands[1], SFmode))
1014         operands[1] = force_reg (SFmode, operands[1]);
1015       if (!cirrus_fp_register (operands[2], SFmode))
1016         operands[2] = force_reg (SFmode, operands[2]);
1017     }
1020 (define_expand "subdf3"
1021   [(set (match_operand:DF           0 "s_register_operand" "")
1022         (minus:DF (match_operand:DF 1 "fpa_rhs_operand"     "")
1023                   (match_operand:DF 2 "fpa_rhs_operand"    "")))]
1024   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1025   "
1026   if (TARGET_CIRRUS)
1027     {
1028        if (!cirrus_fp_register (operands[1], DFmode))
1029          operands[1] = force_reg (DFmode, operands[1]);
1030        if (!cirrus_fp_register (operands[2], DFmode))
1031          operands[2] = force_reg (DFmode, operands[2]);
1032     }
1036 ;; Multiplication insns
1038 (define_expand "mulsi3"
1039   [(set (match_operand:SI          0 "s_register_operand" "")
1040         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1041                  (match_operand:SI 1 "s_register_operand" "")))]
1042   "TARGET_EITHER"
1043   ""
1046 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1047 (define_insn "*arm_mulsi3"
1048   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1049         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1050                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1051   "TARGET_ARM"
1052   "mul%?\\t%0, %2, %1"
1053   [(set_attr "type" "mult")
1054    (set_attr "predicable" "yes")]
1057 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1058 ; 1 and 2; are the same, because reload will make operand 0 match 
1059 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1060 ; this by adding another alternative to match this case, and then `reload' 
1061 ; it ourselves.  This alternative must come first.
1062 (define_insn "*thumb_mulsi3"
1063   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1064         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1065                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1066   "TARGET_THUMB"
1067   "*
1068   if (which_alternative < 2)
1069     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1070   else
1071     return \"mul\\t%0, %0, %2\";
1072   "
1073   [(set_attr "length" "4,4,2")
1074    (set_attr "type" "mult")]
1077 (define_insn "*mulsi3_compare0"
1078   [(set (reg:CC_NOOV CC_REGNUM)
1079         (compare:CC_NOOV (mult:SI
1080                           (match_operand:SI 2 "s_register_operand" "r,r")
1081                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1082                          (const_int 0)))
1083    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1084         (mult:SI (match_dup 2) (match_dup 1)))]
1085   "TARGET_ARM && !arm_is_xscale"
1086   "mul%?s\\t%0, %2, %1"
1087   [(set_attr "conds" "set")
1088    (set_attr "type" "mult")]
1091 (define_insn "*mulsi_compare0_scratch"
1092   [(set (reg:CC_NOOV CC_REGNUM)
1093         (compare:CC_NOOV (mult:SI
1094                           (match_operand:SI 2 "s_register_operand" "r,r")
1095                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1096                          (const_int 0)))
1097    (clobber (match_scratch:SI 0 "=&r,&r"))]
1098   "TARGET_ARM && !arm_is_xscale"
1099   "mul%?s\\t%0, %2, %1"
1100   [(set_attr "conds" "set")
1101    (set_attr "type" "mult")]
1104 ;; Unnamed templates to match MLA instruction.
1106 (define_insn "*mulsi3addsi"
1107   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1108         (plus:SI
1109           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1110                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1111           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1112   "TARGET_ARM"
1113   "mla%?\\t%0, %2, %1, %3"
1114   [(set_attr "type" "mult")
1115    (set_attr "predicable" "yes")]
1118 (define_insn "*mulsi3addsi_compare0"
1119   [(set (reg:CC_NOOV CC_REGNUM)
1120         (compare:CC_NOOV
1121          (plus:SI (mult:SI
1122                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1123                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1124                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1125          (const_int 0)))
1126    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1127         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1128                  (match_dup 3)))]
1129   "TARGET_ARM && !arm_is_xscale"
1130   "mla%?s\\t%0, %2, %1, %3"
1131   [(set_attr "conds" "set")
1132    (set_attr "type" "mult")]
1135 (define_insn "*mulsi3addsi_compare0_scratch"
1136   [(set (reg:CC_NOOV CC_REGNUM)
1137         (compare:CC_NOOV
1138          (plus:SI (mult:SI
1139                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1140                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1141                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1142          (const_int 0)))
1143    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1144   "TARGET_ARM && !arm_is_xscale"
1145   "mla%?s\\t%0, %2, %1, %3"
1146   [(set_attr "conds" "set")
1147    (set_attr "type" "mult")]
1150 ;; Unnamed template to match long long multiply-accumlate (smlal)
1152 (define_insn "*mulsidi3adddi"
1153   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1154         (plus:DI
1155          (mult:DI
1156           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1157           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1158          (match_operand:DI 1 "s_register_operand" "0")))]
1159   "TARGET_ARM && arm_fast_multiply"
1160   "smlal%?\\t%Q0, %R0, %3, %2"
1161   [(set_attr "type" "mult")
1162    (set_attr "predicable" "yes")]
1165 (define_insn "mulsidi3"
1166   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1167         (mult:DI
1168          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1169          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1170   "TARGET_ARM && arm_fast_multiply"
1171   "smull%?\\t%Q0, %R0, %1, %2"
1172   [(set_attr "type" "mult")
1173    (set_attr "predicable" "yes")]
1176 (define_insn "umulsidi3"
1177   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1178         (mult:DI
1179          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1180          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1181   "TARGET_ARM && arm_fast_multiply"
1182   "umull%?\\t%Q0, %R0, %1, %2"
1183   [(set_attr "type" "mult")
1184    (set_attr "predicable" "yes")]
1187 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1189 (define_insn "*umulsidi3adddi"
1190   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1191         (plus:DI
1192          (mult:DI
1193           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1194           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1195          (match_operand:DI 1 "s_register_operand" "0")))]
1196   "TARGET_ARM && arm_fast_multiply"
1197   "umlal%?\\t%Q0, %R0, %3, %2"
1198   [(set_attr "type" "mult")
1199    (set_attr "predicable" "yes")]
1202 (define_insn "smulsi3_highpart"
1203   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1204         (truncate:SI
1205          (lshiftrt:DI
1206           (mult:DI
1207            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1208            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1209           (const_int 32))))
1210    (clobber (match_scratch:SI 3 "=&r,&r"))]
1211   "TARGET_ARM && arm_fast_multiply"
1212   "smull%?\\t%3, %0, %2, %1"
1213   [(set_attr "type" "mult")
1214    (set_attr "predicable" "yes")]
1217 (define_insn "umulsi3_highpart"
1218   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1219         (truncate:SI
1220          (lshiftrt:DI
1221           (mult:DI
1222            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1223            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1224           (const_int 32))))
1225    (clobber (match_scratch:SI 3 "=&r,&r"))]
1226   "TARGET_ARM && arm_fast_multiply"
1227   "umull%?\\t%3, %0, %2, %1"
1228   [(set_attr "type" "mult")
1229    (set_attr "predicable" "yes")]
1232 (define_insn "mulhisi3"
1233   [(set (match_operand:SI 0 "s_register_operand" "=r")
1234         (mult:SI (sign_extend:SI
1235                   (match_operand:HI 1 "s_register_operand" "%r"))
1236                  (sign_extend:SI
1237                   (match_operand:HI 2 "s_register_operand" "r"))))]
1238   "TARGET_ARM && arm_arch5e"
1239   "smulbb%?\\t%0, %1, %2"
1240   [(set_attr "type" "mult")
1241    (set_attr "predicable" "yes")]
1244 (define_insn "*mulhisi3tb"
1245   [(set (match_operand:SI 0 "s_register_operand" "=r")
1246         (mult:SI (ashiftrt:SI
1247                   (match_operand:SI 1 "s_register_operand" "r")
1248                   (const_int 16))
1249                  (sign_extend:SI
1250                   (match_operand:HI 2 "s_register_operand" "r"))))]
1251   "TARGET_ARM && arm_arch5e"
1252   "smultb%?\\t%0, %1, %2"
1253   [(set_attr "type" "mult")
1254    (set_attr "predicable" "yes")]
1257 (define_insn "*mulhisi3bt"
1258   [(set (match_operand:SI 0 "s_register_operand" "=r")
1259         (mult:SI (sign_extend:SI
1260                   (match_operand:HI 1 "s_register_operand" "r"))
1261                  (ashiftrt:SI
1262                   (match_operand:SI 2 "s_register_operand" "r")
1263                   (const_int 16))))]
1264   "TARGET_ARM && arm_arch5e"
1265   "smulbt%?\\t%0, %1, %2"
1266   [(set_attr "type" "mult")
1267    (set_attr "predicable" "yes")]
1270 (define_insn "*mulhisi3tt"
1271   [(set (match_operand:SI 0 "s_register_operand" "=r")
1272         (mult:SI (ashiftrt:SI
1273                   (match_operand:SI 1 "s_register_operand" "r")
1274                   (const_int 16))
1275                  (ashiftrt:SI
1276                   (match_operand:SI 2 "s_register_operand" "r")
1277                   (const_int 16))))]
1278   "TARGET_ARM && arm_arch5e"
1279   "smultt%?\\t%0, %1, %2"
1280   [(set_attr "type" "mult")
1281    (set_attr "predicable" "yes")]
1284 (define_insn "*mulhisi3addsi"
1285   [(set (match_operand:SI 0 "s_register_operand" "=r")
1286         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1287                  (mult:SI (sign_extend:SI
1288                            (match_operand:HI 2 "s_register_operand" "%r"))
1289                           (sign_extend:SI
1290                            (match_operand:HI 3 "s_register_operand" "r")))))]
1291   "TARGET_ARM && arm_arch5e"
1292   "smlabb%?\\t%0, %2, %3, %1"
1293   [(set_attr "type" "mult")
1294    (set_attr "predicable" "yes")]
1297 (define_insn "*mulhidi3adddi"
1298   [(set (match_operand:DI 0 "s_register_operand" "=r")
1299         (plus:DI
1300           (match_operand:DI 1 "s_register_operand" "0")
1301           (mult:DI (sign_extend:DI
1302                     (match_operand:HI 2 "s_register_operand" "%r"))
1303                    (sign_extend:DI
1304                     (match_operand:HI 3 "s_register_operand" "r")))))]
1305   "TARGET_ARM && arm_arch5e"
1306   "smlalbb%?\\t%Q0, %R0, %2, %3"
1307   [(set_attr "type" "mult")
1308    (set_attr "predicable" "yes")])
1310 (define_expand "mulsf3"
1311   [(set (match_operand:SF          0 "s_register_operand" "")
1312         (mult:SF (match_operand:SF 1 "s_register_operand" "")
1313                  (match_operand:SF 2 "fpa_rhs_operand" "")))]
1314   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1315   "
1316   if (TARGET_CIRRUS
1317       && !cirrus_fp_register (operands[2], SFmode))
1318     operands[2] = force_reg (SFmode, operands[2]);
1321 (define_expand "muldf3"
1322   [(set (match_operand:DF          0 "s_register_operand" "")
1323         (mult:DF (match_operand:DF 1 "s_register_operand" "")
1324                  (match_operand:DF 2 "fpa_rhs_operand" "")))]
1325   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1326   "
1327   if (TARGET_CIRRUS
1328       && !cirrus_fp_register (operands[2], DFmode))
1329     operands[2] = force_reg (DFmode, operands[2]);
1332 ;; Division insns
1334 (define_expand "divsf3"
1335   [(set (match_operand:SF 0 "s_register_operand" "")
1336         (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1337                 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1338   "TARGET_ARM && TARGET_HARD_FLOAT"
1339   "")
1341 (define_expand "divdf3"
1342   [(set (match_operand:DF 0 "s_register_operand" "")
1343         (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1344                 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1345   "TARGET_ARM && TARGET_HARD_FLOAT"
1346   "")
1348 ;; Modulo insns
1350 (define_expand "modsf3"
1351   [(set (match_operand:SF 0 "s_register_operand" "")
1352         (mod:SF (match_operand:SF 1 "s_register_operand" "")
1353                 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1354   "TARGET_ARM && TARGET_HARD_FLOAT"
1355   "")
1357 (define_expand "moddf3"
1358   [(set (match_operand:DF 0 "s_register_operand" "")
1359         (mod:DF (match_operand:DF 1 "s_register_operand" "")
1360                 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1361   "TARGET_ARM && TARGET_HARD_FLOAT"
1362   "")
1364 ;; Boolean and,ior,xor insns
1366 ;; Split up double word logical operations
1368 ;; Split up simple DImode logical operations.  Simply perform the logical
1369 ;; operation on the upper and lower halves of the registers.
1370 (define_split
1371   [(set (match_operand:DI 0 "s_register_operand" "")
1372         (match_operator:DI 6 "logical_binary_operator"
1373           [(match_operand:DI 1 "s_register_operand" "")
1374            (match_operand:DI 2 "s_register_operand" "")]))]
1375   "TARGET_ARM && reload_completed"
1376   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1377    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1378   "
1379   {
1380     operands[3] = gen_highpart (SImode, operands[0]);
1381     operands[0] = gen_lowpart (SImode, operands[0]);
1382     operands[4] = gen_highpart (SImode, operands[1]);
1383     operands[1] = gen_lowpart (SImode, operands[1]);
1384     operands[5] = gen_highpart (SImode, operands[2]);
1385     operands[2] = gen_lowpart (SImode, operands[2]);
1386   }"
1389 (define_split
1390   [(set (match_operand:DI 0 "s_register_operand" "")
1391         (match_operator:DI 6 "logical_binary_operator"
1392           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1393            (match_operand:DI 1 "s_register_operand" "")]))]
1394   "TARGET_ARM && reload_completed"
1395   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1396    (set (match_dup 3) (match_op_dup:SI 6
1397                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1398                          (match_dup 4)]))]
1399   "
1400   {
1401     operands[3] = gen_highpart (SImode, operands[0]);
1402     operands[0] = gen_lowpart (SImode, operands[0]);
1403     operands[4] = gen_highpart (SImode, operands[1]);
1404     operands[1] = gen_lowpart (SImode, operands[1]);
1405     operands[5] = gen_highpart (SImode, operands[2]);
1406     operands[2] = gen_lowpart (SImode, operands[2]);
1407   }"
1410 ;; The zero extend of operand 2 means we can just copy the high part of
1411 ;; operand1 into operand0.
1412 (define_split
1413   [(set (match_operand:DI 0 "s_register_operand" "")
1414         (ior:DI
1415           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1416           (match_operand:DI 1 "s_register_operand" "")))]
1417   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1418   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1419    (set (match_dup 3) (match_dup 4))]
1420   "
1421   {
1422     operands[4] = gen_highpart (SImode, operands[1]);
1423     operands[3] = gen_highpart (SImode, operands[0]);
1424     operands[0] = gen_lowpart (SImode, operands[0]);
1425     operands[1] = gen_lowpart (SImode, operands[1]);
1426   }"
1429 ;; The zero extend of operand 2 means we can just copy the high part of
1430 ;; operand1 into operand0.
1431 (define_split
1432   [(set (match_operand:DI 0 "s_register_operand" "")
1433         (xor:DI
1434           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1435           (match_operand:DI 1 "s_register_operand" "")))]
1436   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1437   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1438    (set (match_dup 3) (match_dup 4))]
1439   "
1440   {
1441     operands[4] = gen_highpart (SImode, operands[1]);
1442     operands[3] = gen_highpart (SImode, operands[0]);
1443     operands[0] = gen_lowpart (SImode, operands[0]);
1444     operands[1] = gen_lowpart (SImode, operands[1]);
1445   }"
1448 (define_insn "anddi3"
1449   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1450         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1451                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1452   "TARGET_ARM"
1453   "#"
1454   [(set_attr "length" "8")]
1457 (define_insn_and_split "*anddi_zesidi_di"
1458   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1459         (and:DI (zero_extend:DI
1460                  (match_operand:SI 2 "s_register_operand" "r,r"))
1461                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1462   "TARGET_ARM"
1463   "#"
1464   "TARGET_ARM && reload_completed"
1465   ; The zero extend of operand 2 clears the high word of the output
1466   ; operand.
1467   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1468    (set (match_dup 3) (const_int 0))]
1469   "
1470   {
1471     operands[3] = gen_highpart (SImode, operands[0]);
1472     operands[0] = gen_lowpart (SImode, operands[0]);
1473     operands[1] = gen_lowpart (SImode, operands[1]);
1474   }"
1475   [(set_attr "length" "8")]
1478 (define_insn "*anddi_sesdi_di"
1479   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1480         (and:DI (sign_extend:DI
1481                  (match_operand:SI 2 "s_register_operand" "r,r"))
1482                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1483   "TARGET_ARM"
1484   "#"
1485   [(set_attr "length" "8")]
1488 (define_expand "andsi3"
1489   [(set (match_operand:SI         0 "s_register_operand" "")
1490         (and:SI (match_operand:SI 1 "s_register_operand" "")
1491                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1492   "TARGET_EITHER"
1493   "
1494   if (TARGET_ARM)
1495     {
1496       if (GET_CODE (operands[2]) == CONST_INT)
1497         {
1498           arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1499                               operands[1],
1500                               (no_new_pseudos
1501                                ? 0 : preserve_subexpressions_p ()));
1502           DONE;
1503         }
1504     }
1505   else /* TARGET_THUMB */
1506     {
1507       if (GET_CODE (operands[2]) != CONST_INT)
1508         operands[2] = force_reg (SImode, operands[2]);
1509       else
1510         {
1511           int i;
1512           
1513           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1514             {
1515               operands[2] = force_reg (SImode,
1516                                        GEN_INT (~INTVAL (operands[2])));
1517               
1518               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1519               
1520               DONE;
1521             }
1523           for (i = 9; i <= 31; i++)
1524             {
1525               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1526                 {
1527                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1528                                         const0_rtx));
1529                   DONE;
1530                 }
1531               else if ((((HOST_WIDE_INT) 1) << i) - 1
1532                        == ~INTVAL (operands[2]))
1533                 {
1534                   rtx shift = GEN_INT (i);
1535                   rtx reg = gen_reg_rtx (SImode);
1536                 
1537                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1538                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1539                   
1540                   DONE;
1541                 }
1542             }
1544           operands[2] = force_reg (SImode, operands[2]);
1545         }
1546     }
1547   "
1550 (define_insn_and_split "*arm_andsi3_insn"
1551   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1552         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1553                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1554   "TARGET_ARM"
1555   "@
1556    and%?\\t%0, %1, %2
1557    bic%?\\t%0, %1, #%B2
1558    #"
1559   "TARGET_ARM
1560    && GET_CODE (operands[2]) == CONST_INT
1561    && !(const_ok_for_arm (INTVAL (operands[2]))
1562         || const_ok_for_arm (~INTVAL (operands[2])))"
1563   [(clobber (const_int 0))]
1564   "
1565   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1566                        operands[1], 0);
1567   DONE;
1568   "
1569   [(set_attr "length" "4,4,16")
1570    (set_attr "predicable" "yes")]
1573 (define_insn "*thumb_andsi3_insn"
1574   [(set (match_operand:SI         0 "register_operand" "=l")
1575         (and:SI (match_operand:SI 1 "register_operand" "%0")
1576                 (match_operand:SI 2 "register_operand" "l")))]
1577   "TARGET_THUMB"
1578   "and\\t%0, %0, %2"
1579   [(set_attr "length" "2")]
1582 (define_insn "*andsi3_compare0"
1583   [(set (reg:CC_NOOV CC_REGNUM)
1584         (compare:CC_NOOV
1585          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1586                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1587          (const_int 0)))
1588    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1589         (and:SI (match_dup 1) (match_dup 2)))]
1590   "TARGET_ARM"
1591   "@
1592    and%?s\\t%0, %1, %2
1593    bic%?s\\t%0, %1, #%B2"
1594   [(set_attr "conds" "set")]
1597 (define_insn "*andsi3_compare0_scratch"
1598   [(set (reg:CC_NOOV CC_REGNUM)
1599         (compare:CC_NOOV
1600          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1601                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1602          (const_int 0)))
1603    (clobber (match_scratch:SI 2 "=X,r"))]
1604   "TARGET_ARM"
1605   "@
1606    tst%?\\t%0, %1
1607    bic%?s\\t%2, %0, #%B1"
1608   [(set_attr "conds" "set")]
1611 (define_insn "*zeroextractsi_compare0_scratch"
1612   [(set (reg:CC_NOOV CC_REGNUM)
1613         (compare:CC_NOOV (zero_extract:SI
1614                           (match_operand:SI 0 "s_register_operand" "r")
1615                           (match_operand 1 "const_int_operand" "n")
1616                           (match_operand 2 "const_int_operand" "n"))
1617                          (const_int 0)))]
1618   "TARGET_ARM
1619   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1620       && INTVAL (operands[1]) > 0 
1621       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1622       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1623   "*
1624   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1625                          << INTVAL (operands[2]));
1626   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1627   return \"\";
1628   "
1629   [(set_attr "conds" "set")]
1632 (define_insn "*ne_zeroextractsi"
1633   [(set (match_operand:SI 0 "s_register_operand" "=r")
1634         (ne:SI (zero_extract:SI
1635                 (match_operand:SI 1 "s_register_operand" "r")
1636                 (match_operand:SI 2 "const_int_operand" "n")
1637                 (match_operand:SI 3 "const_int_operand" "n"))
1638                (const_int 0)))
1639    (clobber (reg:CC CC_REGNUM))]
1640   "TARGET_ARM
1641    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1642        && INTVAL (operands[2]) > 0 
1643        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1644        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1645   "*
1646   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1647                          << INTVAL (operands[3]));
1648   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1649   return \"movne\\t%0, #1\";
1650   "
1651   [(set_attr "conds" "clob")
1652    (set_attr "length" "8")]
1655 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1656 ;;; represented by the bitfield, then this will produce incorrect results.
1657 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1658 ;;; which have a real bit-field insert instruction, the truncation happens
1659 ;;; in the bit-field insert instruction itself.  Since arm does not have a
1660 ;;; bit-field insert instruction, we would have to emit code here to truncate
1661 ;;; the value before we insert.  This loses some of the advantage of having
1662 ;;; this insv pattern, so this pattern needs to be reevalutated.
1664 (define_expand "insv"
1665   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1666                          (match_operand:SI 1 "general_operand" "")
1667                          (match_operand:SI 2 "general_operand" ""))
1668         (match_operand:SI 3 "reg_or_int_operand" ""))]
1669   "TARGET_ARM"
1670   "
1671   {
1672     int start_bit = INTVAL (operands[2]);
1673     int width = INTVAL (operands[1]);
1674     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1675     rtx target, subtarget;
1677     target = operands[0];
1678     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1679        subreg as the final target.  */
1680     if (GET_CODE (target) == SUBREG)
1681       {
1682         subtarget = gen_reg_rtx (SImode);
1683         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1684             < GET_MODE_SIZE (SImode))
1685           target = SUBREG_REG (target);
1686       }
1687     else
1688       subtarget = target;    
1690     if (GET_CODE (operands[3]) == CONST_INT)
1691       {
1692         /* Since we are inserting a known constant, we may be able to
1693            reduce the number of bits that we have to clear so that
1694            the mask becomes simple.  */
1695         /* ??? This code does not check to see if the new mask is actually
1696            simpler.  It may not be.  */
1697         rtx op1 = gen_reg_rtx (SImode);
1698         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1699            start of this pattern.  */
1700         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1701         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1703         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1704         emit_insn (gen_iorsi3 (subtarget, op1,
1705                                GEN_INT (op3_value << start_bit)));
1706       }
1707     else if (start_bit == 0
1708              && !(const_ok_for_arm (mask)
1709                   || const_ok_for_arm (~mask)))
1710       {
1711         /* A Trick, since we are setting the bottom bits in the word,
1712            we can shift operand[3] up, operand[0] down, OR them together
1713            and rotate the result back again.  This takes 3 insns, and
1714            the third might be mergable into another op.  */
1715         /* The shift up copes with the possibility that operand[3] is
1716            wider than the bitfield.  */
1717         rtx op0 = gen_reg_rtx (SImode);
1718         rtx op1 = gen_reg_rtx (SImode);
1720         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1721         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1722         emit_insn (gen_iorsi3  (op1, op1, op0));
1723         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1724       }
1725     else if ((width + start_bit == 32)
1726              && !(const_ok_for_arm (mask)
1727                   || const_ok_for_arm (~mask)))
1728       {
1729         /* Similar trick, but slightly less efficient.  */
1731         rtx op0 = gen_reg_rtx (SImode);
1732         rtx op1 = gen_reg_rtx (SImode);
1734         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1735         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1736         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1737         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1738       }
1739     else
1740       {
1741         rtx op0 = GEN_INT (mask);
1742         rtx op1 = gen_reg_rtx (SImode);
1743         rtx op2 = gen_reg_rtx (SImode);
1745         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1746           {
1747             rtx tmp = gen_reg_rtx (SImode);
1749             emit_insn (gen_movsi (tmp, op0));
1750             op0 = tmp;
1751           }
1753         /* Mask out any bits in operand[3] that are not needed.  */
1754            emit_insn (gen_andsi3 (op1, operands[3], op0));
1756         if (GET_CODE (op0) == CONST_INT
1757             && (const_ok_for_arm (mask << start_bit)
1758                 || const_ok_for_arm (~(mask << start_bit))))
1759           {
1760             op0 = GEN_INT (~(mask << start_bit));
1761             emit_insn (gen_andsi3 (op2, operands[0], op0));
1762           }
1763         else
1764           {
1765             if (GET_CODE (op0) == CONST_INT)
1766               {
1767                 rtx tmp = gen_reg_rtx (SImode);
1769                 emit_insn (gen_movsi (tmp, op0));
1770                 op0 = tmp;
1771               }
1773             if (start_bit != 0)
1774               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1775             
1776             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1777           }
1779         if (start_bit != 0)
1780           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1782         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1783       }
1785     if (subtarget != target)
1786       {
1787         /* If TARGET is still a SUBREG, then it must be wider than a word,
1788            so we must be careful only to set the subword we were asked to.  */
1789         if (GET_CODE (target) == SUBREG)
1790           emit_move_insn (target, subtarget);
1791         else
1792           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1793       }
1795     DONE;
1796   }"
1799 ; constants for op 2 will never be given to these patterns.
1800 (define_insn_and_split "*anddi_notdi_di"
1801   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1802         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1803                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1804   "TARGET_ARM"
1805   "#"
1806   "TARGET_ARM && reload_completed"
1807   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1808    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1809   "
1810   {
1811     operands[3] = gen_highpart (SImode, operands[0]);
1812     operands[0] = gen_lowpart (SImode, operands[0]);
1813     operands[4] = gen_highpart (SImode, operands[1]);
1814     operands[1] = gen_lowpart (SImode, operands[1]);
1815     operands[5] = gen_highpart (SImode, operands[2]);
1816     operands[2] = gen_lowpart (SImode, operands[2]);
1817   }"
1818   [(set_attr "length" "8")
1819    (set_attr "predicable" "yes")]
1821   
1822 (define_insn_and_split "*anddi_notzesidi_di"
1823   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1824         (and:DI (not:DI (zero_extend:DI
1825                          (match_operand:SI 2 "s_register_operand" "r,r")))
1826                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1827   "TARGET_ARM"
1828   "@
1829    bic%?\\t%Q0, %Q1, %2
1830    #"
1831   ; (not (zero_extend ...)) allows us to just copy the high word from
1832   ; operand1 to operand0.
1833   "TARGET_ARM
1834    && reload_completed
1835    && operands[0] != operands[1]"
1836   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1837    (set (match_dup 3) (match_dup 4))]
1838   "
1839   {
1840     operands[3] = gen_highpart (SImode, operands[0]);
1841     operands[0] = gen_lowpart (SImode, operands[0]);
1842     operands[4] = gen_highpart (SImode, operands[1]);
1843     operands[1] = gen_lowpart (SImode, operands[1]);
1844   }"
1845   [(set_attr "length" "4,8")
1846    (set_attr "predicable" "yes")]
1848   
1849 (define_insn_and_split "*anddi_notsesidi_di"
1850   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1851         (and:DI (not:DI (sign_extend:DI
1852                          (match_operand:SI 2 "s_register_operand" "r,r")))
1853                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1854   "TARGET_ARM"
1855   "#"
1856   "TARGET_ARM && reload_completed"
1857   [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1858    (set (match_dup 3) (and:SI (not:SI
1859                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
1860                                (match_dup 4)))]
1861   "
1862   {
1863     operands[3] = gen_highpart (SImode, operands[0]);
1864     operands[0] = gen_lowpart (SImode, operands[0]);
1865     operands[4] = gen_highpart (SImode, operands[1]);
1866     operands[1] = gen_lowpart (SImode, operands[1]);
1867   }"
1868   [(set_attr "length" "8")
1869    (set_attr "predicable" "yes")]
1871   
1872 (define_insn "andsi_notsi_si"
1873   [(set (match_operand:SI 0 "s_register_operand" "=r")
1874         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1875                 (match_operand:SI 1 "s_register_operand" "r")))]
1876   "TARGET_ARM"
1877   "bic%?\\t%0, %1, %2"
1878   [(set_attr "predicable" "yes")]
1881 (define_insn "bicsi3"
1882   [(set (match_operand:SI                 0 "register_operand" "=l")
1883         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1884                 (match_operand:SI         2 "register_operand" "0")))]
1885   "TARGET_THUMB"
1886   "bic\\t%0, %0, %1"
1887   [(set_attr "length" "2")]
1890 (define_insn "andsi_not_shiftsi_si"
1891   [(set (match_operand:SI                   0 "s_register_operand" "=r")
1892         (and:SI (not:SI (match_operator:SI  4 "shift_operator"
1893                          [(match_operand:SI 2 "s_register_operand"  "r")
1894                           (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
1895                 (match_operand:SI           1 "s_register_operand"  "r")))]
1896   "TARGET_ARM"
1897   "bic%?\\t%0, %1, %2%S4"
1898   [(set_attr "predicable" "yes")
1899    (set_attr "shift" "2")
1900    ]
1903 (define_insn "*andsi_notsi_si_compare0"
1904   [(set (reg:CC_NOOV CC_REGNUM)
1905         (compare:CC_NOOV
1906          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1907                  (match_operand:SI 1 "s_register_operand" "r"))
1908          (const_int 0)))
1909    (set (match_operand:SI 0 "s_register_operand" "=r")
1910         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1911   "TARGET_ARM"
1912   "bic%?s\\t%0, %1, %2"
1913   [(set_attr "conds" "set")]
1916 (define_insn "*andsi_notsi_si_compare0_scratch"
1917   [(set (reg:CC_NOOV CC_REGNUM)
1918         (compare:CC_NOOV
1919          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1920                  (match_operand:SI 1 "s_register_operand" "r"))
1921          (const_int 0)))
1922    (clobber (match_scratch:SI 0 "=r"))]
1923   "TARGET_ARM"
1924   "bic%?s\\t%0, %1, %2"
1925   [(set_attr "conds" "set")]
1928 (define_insn "iordi3"
1929   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1930         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1931                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1932   "TARGET_ARM"
1933   "#"
1934   [(set_attr "length" "8")
1935    (set_attr "predicable" "yes")]
1938 (define_insn "*iordi_zesidi_di"
1939   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1940         (ior:DI (zero_extend:DI
1941                  (match_operand:SI 2 "s_register_operand" "r,r"))
1942                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1943   "TARGET_ARM"
1944   "@
1945    orr%?\\t%Q0, %Q1, %2
1946    #"
1947   [(set_attr "length" "4,8")
1948    (set_attr "predicable" "yes")]
1951 (define_insn "*iordi_sesidi_di"
1952   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1953         (ior:DI (sign_extend:DI
1954                  (match_operand:SI 2 "s_register_operand" "r,r"))
1955                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1956   "TARGET_ARM"
1957   "#"
1958   [(set_attr "length" "8")
1959    (set_attr "predicable" "yes")]
1962 (define_expand "iorsi3"
1963   [(set (match_operand:SI         0 "s_register_operand" "")
1964         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1965                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1966   "TARGET_EITHER"
1967   "
1968   if (GET_CODE (operands[2]) == CONST_INT)
1969     {
1970       if (TARGET_ARM)
1971         {
1972           arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1973                               operands[1],
1974                               (no_new_pseudos
1975                               ? 0 : preserve_subexpressions_p ()));
1976           DONE;
1977         }
1978       else /* TARGET_THUMB */
1979         operands [2] = force_reg (SImode, operands [2]);
1980     }
1981   "
1984 (define_insn_and_split "*arm_iorsi3"
1985   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
1986         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1987                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1988   "TARGET_ARM"
1989   "@
1990    orr%?\\t%0, %1, %2
1991    #"
1992   "TARGET_ARM
1993    && GET_CODE (operands[2]) == CONST_INT
1994    && !const_ok_for_arm (INTVAL (operands[2]))"
1995   [(clobber (const_int 0))]
1996   "
1997   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1998                       operands[1], 0);
1999   DONE;
2000   "
2001   [(set_attr "length" "4,16")
2002    (set_attr "predicable" "yes")]
2005 (define_insn "*thumb_iorsi3"
2006   [(set (match_operand:SI         0 "register_operand" "=l")
2007         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2008                 (match_operand:SI 2 "register_operand" "l")))]
2009   "TARGET_THUMB"
2010   "orr\\t%0, %0, %2"
2011   [(set_attr "length" "2")]
2014 (define_peephole2
2015   [(match_scratch:SI 3 "r")
2016    (set (match_operand:SI         0 "s_register_operand" "")
2017         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2018                 (match_operand:SI 2 "const_int_operand" "")))]
2019   "TARGET_ARM
2020    && !const_ok_for_arm (INTVAL (operands[2]))
2021    && const_ok_for_arm (~INTVAL (operands[2]))"
2022   [(set (match_dup 3) (match_dup 2))
2023    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2024   ""
2027 (define_insn "*iorsi3_compare0"
2028   [(set (reg:CC_NOOV CC_REGNUM)
2029         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2030                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2031                          (const_int 0)))
2032    (set (match_operand:SI 0 "s_register_operand" "=r")
2033         (ior:SI (match_dup 1) (match_dup 2)))]
2034   "TARGET_ARM"
2035   "orr%?s\\t%0, %1, %2"
2036   [(set_attr "conds" "set")]
2039 (define_insn "*iorsi3_compare0_scratch"
2040   [(set (reg:CC_NOOV CC_REGNUM)
2041         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2042                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2043                          (const_int 0)))
2044    (clobber (match_scratch:SI 0 "=r"))]
2045   "TARGET_ARM"
2046   "orr%?s\\t%0, %1, %2"
2047   [(set_attr "conds" "set")]
2050 (define_insn "xordi3"
2051   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2052         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2053                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2054   "TARGET_ARM"
2055   "#"
2056   [(set_attr "length" "8")
2057    (set_attr "predicable" "yes")]
2060 (define_insn "*xordi_zesidi_di"
2061   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2062         (xor:DI (zero_extend:DI
2063                  (match_operand:SI 2 "s_register_operand" "r,r"))
2064                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2065   "TARGET_ARM"
2066   "@
2067    eor%?\\t%Q0, %Q1, %2
2068    #"
2069   [(set_attr "length" "4,8")
2070    (set_attr "predicable" "yes")]
2073 (define_insn "*xordi_sesidi_di"
2074   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2075         (xor:DI (sign_extend:DI
2076                  (match_operand:SI 2 "s_register_operand" "r,r"))
2077                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2078   "TARGET_ARM"
2079   "#"
2080   [(set_attr "length" "8")
2081    (set_attr "predicable" "yes")]
2084 (define_expand "xorsi3"
2085   [(set (match_operand:SI         0 "s_register_operand" "")
2086         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2087                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2088   "TARGET_EITHER"
2089   "if (TARGET_THUMB)
2090      if (GET_CODE (operands[2]) == CONST_INT)
2091        operands[2] = force_reg (SImode, operands[2]);
2092   "
2095 (define_insn "*arm_xorsi3"
2096   [(set (match_operand:SI         0 "s_register_operand" "=r")
2097         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2098                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2099   "TARGET_ARM"
2100   "eor%?\\t%0, %1, %2"
2101   [(set_attr "predicable" "yes")]
2104 (define_insn "*thumb_xorsi3"
2105   [(set (match_operand:SI         0 "register_operand" "=l")
2106         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2107                 (match_operand:SI 2 "register_operand" "l")))]
2108   "TARGET_THUMB"
2109   "eor\\t%0, %0, %2"
2110   [(set_attr "length" "2")]
2113 (define_insn "*xorsi3_compare0"
2114   [(set (reg:CC_NOOV CC_REGNUM)
2115         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2116                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2117                          (const_int 0)))
2118    (set (match_operand:SI 0 "s_register_operand" "=r")
2119         (xor:SI (match_dup 1) (match_dup 2)))]
2120   "TARGET_ARM"
2121   "eor%?s\\t%0, %1, %2"
2122   [(set_attr "conds" "set")]
2125 (define_insn "*xorsi3_compare0_scratch"
2126   [(set (reg:CC_NOOV CC_REGNUM)
2127         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2128                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2129                          (const_int 0)))]
2130   "TARGET_ARM"
2131   "teq%?\\t%0, %1"
2132   [(set_attr "conds" "set")]
2135 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2136 ; (NOT D) we can sometimes merge the final NOT into one of the following
2137 ; insns.
2139 (define_split
2140   [(set (match_operand:SI 0 "s_register_operand" "")
2141         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2142                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2143                 (match_operand:SI 3 "arm_rhs_operand" "")))
2144    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2145   "TARGET_ARM"
2146   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2147                               (not:SI (match_dup 3))))
2148    (set (match_dup 0) (not:SI (match_dup 4)))]
2149   ""
2152 (define_insn "*andsi_iorsi3_notsi"
2153   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2154         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2155                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2156                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2157   "TARGET_ARM"
2158   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2159   [(set_attr "length" "8")
2160    (set_attr "predicable" "yes")]
2165 ;; Minimum and maximum insns
2167 (define_insn "smaxsi3"
2168   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2169         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2170                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2171    (clobber (reg:CC CC_REGNUM))]
2172   "TARGET_ARM"
2173   "@
2174    cmp\\t%1, %2\;movlt\\t%0, %2
2175    cmp\\t%1, %2\;movge\\t%0, %1
2176    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2177   [(set_attr "conds" "clob")
2178    (set_attr "length" "8,8,12")]
2181 (define_insn "sminsi3"
2182   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2183         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2184                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2185    (clobber (reg:CC CC_REGNUM))]
2186   "TARGET_ARM"
2187   "@
2188    cmp\\t%1, %2\;movge\\t%0, %2
2189    cmp\\t%1, %2\;movlt\\t%0, %1
2190    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2191   [(set_attr "conds" "clob")
2192    (set_attr "length" "8,8,12")]
2195 (define_insn "umaxsi3"
2196   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2197         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2198                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2199    (clobber (reg:CC CC_REGNUM))]
2200   "TARGET_ARM"
2201   "@
2202    cmp\\t%1, %2\;movcc\\t%0, %2
2203    cmp\\t%1, %2\;movcs\\t%0, %1
2204    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2205   [(set_attr "conds" "clob")
2206    (set_attr "length" "8,8,12")]
2209 (define_insn "uminsi3"
2210   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2211         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2212                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2213    (clobber (reg:CC CC_REGNUM))]
2214   "TARGET_ARM"
2215   "@
2216    cmp\\t%1, %2\;movcs\\t%0, %2
2217    cmp\\t%1, %2\;movcc\\t%0, %1
2218    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2219   [(set_attr "conds" "clob")
2220    (set_attr "length" "8,8,12")]
2223 (define_insn "*store_minmaxsi"
2224   [(set (match_operand:SI 0 "memory_operand" "=m")
2225         (match_operator:SI 3 "minmax_operator"
2226          [(match_operand:SI 1 "s_register_operand" "r")
2227           (match_operand:SI 2 "s_register_operand" "r")]))
2228    (clobber (reg:CC CC_REGNUM))]
2229   "TARGET_ARM"
2230   "*
2231   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2232                          operands[2]);
2233   output_asm_insn (\"cmp\\t%1, %2\", operands);
2234   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2235   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2236   return \"\";
2237   "
2238   [(set_attr "conds" "clob")
2239    (set_attr "length" "12")
2240    (set_attr "type" "store1")]
2243 ; Reject the frame pointer in operand[1], since reloading this after
2244 ; it has been eliminated can cause carnage.
2245 (define_insn "*minmax_arithsi"
2246   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2247         (match_operator:SI 4 "shiftable_operator"
2248          [(match_operator:SI 5 "minmax_operator"
2249            [(match_operand:SI 2 "s_register_operand" "r,r")
2250             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2251           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2252    (clobber (reg:CC CC_REGNUM))]
2253   "TARGET_ARM
2254    && (GET_CODE (operands[1]) != REG
2255        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2256            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2257   "*
2258   {
2259     enum rtx_code code = GET_CODE (operands[4]);
2261     operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2262                            operands[3]);
2263     output_asm_insn (\"cmp\\t%2, %3\", operands);
2264     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2265     if (which_alternative != 0 || operands[3] != const0_rtx
2266         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2267       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2268     return \"\";
2269   }"
2270   [(set_attr "conds" "clob")
2271    (set_attr "length" "12")]
2275 ;; Shift and rotation insns
2277 (define_expand "ashlsi3"
2278   [(set (match_operand:SI            0 "s_register_operand" "")
2279         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2280                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2281   "TARGET_EITHER"
2282   "
2283   if (GET_CODE (operands[2]) == CONST_INT
2284       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2285     {
2286       emit_insn (gen_movsi (operands[0], const0_rtx));
2287       DONE;
2288     }
2289   "
2292 (define_insn "*thumb_ashlsi3"
2293   [(set (match_operand:SI            0 "register_operand" "=l,l")
2294         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2295                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2296   "TARGET_THUMB"
2297   "lsl\\t%0, %1, %2"
2298   [(set_attr "length" "2")]
2301 (define_expand "ashrsi3"
2302   [(set (match_operand:SI              0 "s_register_operand" "")
2303         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2304                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2305   "TARGET_EITHER"
2306   "
2307   if (GET_CODE (operands[2]) == CONST_INT
2308       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2309     operands[2] = GEN_INT (31);
2310   "
2313 (define_insn "*thumb_ashrsi3"
2314   [(set (match_operand:SI              0 "register_operand" "=l,l")
2315         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2316                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2317   "TARGET_THUMB"
2318   "asr\\t%0, %1, %2"
2319   [(set_attr "length" "2")]
2322 (define_expand "lshrsi3"
2323   [(set (match_operand:SI              0 "s_register_operand" "")
2324         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2325                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2326   "TARGET_EITHER"
2327   "
2328   if (GET_CODE (operands[2]) == CONST_INT
2329       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2330     {
2331       emit_insn (gen_movsi (operands[0], const0_rtx));
2332       DONE;
2333     }
2334   "
2337 (define_insn "*thumb_lshrsi3"
2338   [(set (match_operand:SI              0 "register_operand" "=l,l")
2339         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2340                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2341   "TARGET_THUMB"
2342   "lsr\\t%0, %1, %2"
2343   [(set_attr "length" "2")]
2346 (define_expand "rotlsi3"
2347   [(set (match_operand:SI              0 "s_register_operand" "")
2348         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2349                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2350   "TARGET_ARM"
2351   "
2352   if (GET_CODE (operands[2]) == CONST_INT)
2353     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2354   else
2355     {
2356       rtx reg = gen_reg_rtx (SImode);
2357       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2358       operands[2] = reg;
2359     }
2360   "
2363 (define_expand "rotrsi3"
2364   [(set (match_operand:SI              0 "s_register_operand" "")
2365         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2366                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2367   "TARGET_EITHER"
2368   "
2369   if (TARGET_ARM)
2370     {
2371       if (GET_CODE (operands[2]) == CONST_INT
2372           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2373         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2374     }
2375   else /* TARGET_THUMB */
2376     {
2377       if (GET_CODE (operands [2]) == CONST_INT)
2378         operands [2] = force_reg (SImode, operands[2]);
2379     }
2380   "
2383 (define_insn "*thumb_rotrsi3"
2384   [(set (match_operand:SI              0 "register_operand" "=l")
2385         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2386                      (match_operand:SI 2 "register_operand" "l")))]
2387   "TARGET_THUMB"
2388   "ror\\t%0, %0, %2"
2389   [(set_attr "length" "2")]
2392 (define_expand "ashldi3"
2393   [(set (match_operand:DI            0 "s_register_operand" "")
2394         (ashift:DI (match_operand:DI 1 "general_operand"    "")
2395                    (match_operand:SI 2 "general_operand"    "")))]
2396   "TARGET_ARM && (TARGET_CIRRUS)"
2397   "
2398   if (! s_register_operand (operands[1], DImode))
2399     operands[1] = copy_to_mode_reg (DImode, operands[1]);
2400   if (! s_register_operand (operands[2], SImode))
2401     operands[2] = copy_to_mode_reg (SImode, operands[2]);
2402   "
2405 (define_insn "*arm_shiftsi3"
2406   [(set (match_operand:SI   0 "s_register_operand" "=r")
2407         (match_operator:SI  3 "shift_operator"
2408          [(match_operand:SI 1 "s_register_operand"  "r")
2409           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2410   "TARGET_ARM"
2411   "mov%?\\t%0, %1%S3"
2412   [(set_attr "predicable" "yes")
2413    (set_attr "shift" "1")
2414    ]
2417 (define_insn "*shiftsi3_compare0"
2418   [(set (reg:CC_NOOV CC_REGNUM)
2419         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2420                           [(match_operand:SI 1 "s_register_operand" "r")
2421                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2422                          (const_int 0)))
2423    (set (match_operand:SI 0 "s_register_operand" "=r")
2424         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2425   "TARGET_ARM"
2426   "mov%?s\\t%0, %1%S3"
2427   [(set_attr "conds" "set")
2428    (set_attr "shift" "1")
2429    ]
2432 (define_insn "*shiftsi3_compare0_scratch"
2433   [(set (reg:CC_NOOV CC_REGNUM)
2434         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2435                           [(match_operand:SI 1 "s_register_operand" "r")
2436                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2437                          (const_int 0)))
2438    (clobber (match_scratch:SI 0 "=r"))]
2439   "TARGET_ARM"
2440   "mov%?s\\t%0, %1%S3"
2441   [(set_attr "conds" "set")
2442    (set_attr "shift" "1")
2443    ]
2446 (define_insn "*notsi_shiftsi"
2447   [(set (match_operand:SI 0 "s_register_operand" "=r")
2448         (not:SI (match_operator:SI 3 "shift_operator"
2449                  [(match_operand:SI 1 "s_register_operand" "r")
2450                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2451   "TARGET_ARM"
2452   "mvn%?\\t%0, %1%S3"
2453   [(set_attr "predicable" "yes")
2454    (set_attr "shift" "1")
2455    ]
2458 (define_insn "*notsi_shiftsi_compare0"
2459   [(set (reg:CC_NOOV CC_REGNUM)
2460         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2461                           [(match_operand:SI 1 "s_register_operand" "r")
2462                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2463                          (const_int 0)))
2464    (set (match_operand:SI 0 "s_register_operand" "=r")
2465         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2466   "TARGET_ARM"
2467   "mvn%?s\\t%0, %1%S3"
2468   [(set_attr "conds" "set")
2469    (set_attr "shift" "1")
2470    ]
2473 (define_insn "*not_shiftsi_compare0_scratch"
2474   [(set (reg:CC_NOOV CC_REGNUM)
2475         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2476                           [(match_operand:SI 1 "s_register_operand" "r")
2477                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2478                          (const_int 0)))
2479    (clobber (match_scratch:SI 0 "=r"))]
2480   "TARGET_ARM"
2481   "mvn%?s\\t%0, %1%S3"
2482   [(set_attr "conds" "set")
2483    (set_attr "shift" "1")
2484   ]
2487 ;; We don't really have extzv, but defining this using shifts helps
2488 ;; to reduce register pressure later on.
2490 (define_expand "extzv"
2491   [(set (match_dup 4)
2492         (ashift:SI (match_operand:SI   1 "register_operand" "")
2493                    (match_operand:SI   2 "const_int_operand" "")))
2494    (set (match_operand:SI              0 "register_operand" "")
2495         (lshiftrt:SI (match_dup 4)
2496                      (match_operand:SI 3 "const_int_operand" "")))]
2497   "TARGET_THUMB"
2498   "
2499   {
2500     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2501     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2502     
2503     operands[3] = GEN_INT (rshift);
2504     
2505     if (lshift == 0)
2506       {
2507         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2508         DONE;
2509       }
2510       
2511     operands[2] = GEN_INT (lshift);
2512     operands[4] = gen_reg_rtx (SImode);
2513   }"
2517 ;; Unary arithmetic insns
2519 (define_expand "negdi2"
2520  [(parallel
2521    [(set (match_operand:DI          0 "s_register_operand" "")
2522           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2523     (clobber (reg:CC CC_REGNUM))])]
2524   "TARGET_EITHER"
2525   "
2526   if (TARGET_THUMB)
2527     {
2528       if (GET_CODE (operands[1]) != REG)
2529         operands[1] = force_reg (SImode, operands[1]);
2530      }
2531   "
2534 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2535 ;; The second alternative is to allow the common case of a *full* overlap.
2536 (define_insn "*arm_negdi2"
2537   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2538         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2539    (clobber (reg:CC CC_REGNUM))]
2540   "TARGET_ARM"
2541   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2542   [(set_attr "conds" "clob")
2543    (set_attr "length" "8")]
2546 (define_insn "*thumb_negdi2"
2547   [(set (match_operand:DI         0 "register_operand" "=&l")
2548         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2549    (clobber (reg:CC CC_REGNUM))]
2550   "TARGET_THUMB"
2551   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2552   [(set_attr "length" "6")]
2555 (define_expand "negsi2"
2556   [(set (match_operand:SI         0 "s_register_operand" "")
2557         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2558   "TARGET_EITHER"
2559   ""
2562 (define_insn "*arm_negsi2"
2563   [(set (match_operand:SI         0 "s_register_operand" "=r")
2564         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2565   "TARGET_ARM"
2566   "rsb%?\\t%0, %1, #0"
2567   [(set_attr "predicable" "yes")]
2570 (define_insn "*thumb_negsi2"
2571   [(set (match_operand:SI         0 "register_operand" "=l")
2572         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2573   "TARGET_THUMB"
2574   "neg\\t%0, %1"
2575   [(set_attr "length" "2")]
2578 (define_expand "negsf2"
2579   [(set (match_operand:SF         0 "s_register_operand" "")
2580         (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2581   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2582   ""
2585 (define_expand "negdf2"
2586   [(set (match_operand:DF         0 "s_register_operand" "")
2587         (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2588   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2589   "")
2591 ;; abssi2 doesn't really clobber the condition codes if a different register
2592 ;; is being set.  To keep things simple, assume during rtl manipulations that
2593 ;; it does, but tell the final scan operator the truth.  Similarly for
2594 ;; (neg (abs...))
2596 (define_expand "abssi2"
2597   [(parallel
2598     [(set (match_operand:SI         0 "s_register_operand" "")
2599           (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2600      (clobber (reg:CC CC_REGNUM))])]
2601   "TARGET_ARM"
2602   "")
2604 (define_insn "*arm_abssi2"
2605   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2606         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2607    (clobber (reg:CC CC_REGNUM))]
2608   "TARGET_ARM"
2609   "@
2610    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2611    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2612   [(set_attr "conds" "clob,*")
2613    (set_attr "shift" "1")
2614    ;; predicable can't be set based on the variant, so left as no
2615    (set_attr "length" "8")]
2618 (define_insn "*neg_abssi2"
2619   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2620         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2621    (clobber (reg:CC CC_REGNUM))]
2622   "TARGET_ARM"
2623   "@
2624    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2625    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2626   [(set_attr "conds" "clob,*")
2627    (set_attr "shift" "1")
2628    ;; predicable can't be set based on the variant, so left as no
2629    (set_attr "length" "8")]
2632 (define_expand "abssf2"
2633   [(set (match_operand:SF         0 "s_register_operand" "")
2634         (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2635   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2636   "")
2638 (define_expand "absdf2"
2639   [(set (match_operand:DF         0 "s_register_operand" "")
2640         (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2641   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2642   "")
2644 (define_expand "sqrtsf2"
2645   [(set (match_operand:SF 0 "s_register_operand" "")
2646         (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2647   "TARGET_ARM && TARGET_HARD_FLOAT"
2648   "")
2650 (define_expand "sqrtdf2"
2651   [(set (match_operand:DF 0 "s_register_operand" "")
2652         (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2653   "TARGET_ARM && TARGET_HARD_FLOAT"
2654   "")
2656 (define_insn_and_split "one_cmpldi2"
2657   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2658         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2659   "TARGET_ARM"
2660   "#"
2661   "TARGET_ARM && reload_completed"
2662   [(set (match_dup 0) (not:SI (match_dup 1)))
2663    (set (match_dup 2) (not:SI (match_dup 3)))]
2664   "
2665   {
2666     operands[2] = gen_highpart (SImode, operands[0]);
2667     operands[0] = gen_lowpart (SImode, operands[0]);
2668     operands[3] = gen_highpart (SImode, operands[1]);
2669     operands[1] = gen_lowpart (SImode, operands[1]);
2670   }"
2671   [(set_attr "length" "8")
2672    (set_attr "predicable" "yes")]
2675 (define_expand "one_cmplsi2"
2676   [(set (match_operand:SI         0 "s_register_operand" "")
2677         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2678   "TARGET_EITHER"
2679   ""
2682 (define_insn "*arm_one_cmplsi2"
2683   [(set (match_operand:SI         0 "s_register_operand" "=r")
2684         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2685   "TARGET_ARM"
2686   "mvn%?\\t%0, %1"
2687   [(set_attr "predicable" "yes")]
2690 (define_insn "*thumb_one_cmplsi2"
2691   [(set (match_operand:SI         0 "register_operand" "=l")
2692         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
2693   "TARGET_THUMB"
2694   "mvn\\t%0, %1"
2695   [(set_attr "length" "2")]
2698 (define_insn "*notsi_compare0"
2699   [(set (reg:CC_NOOV CC_REGNUM)
2700         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2701                          (const_int 0)))
2702    (set (match_operand:SI 0 "s_register_operand" "=r")
2703         (not:SI (match_dup 1)))]
2704   "TARGET_ARM"
2705   "mvn%?s\\t%0, %1"
2706   [(set_attr "conds" "set")]
2709 (define_insn "*notsi_compare0_scratch"
2710   [(set (reg:CC_NOOV CC_REGNUM)
2711         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2712                          (const_int 0)))
2713    (clobber (match_scratch:SI 0 "=r"))]
2714   "TARGET_ARM"
2715   "mvn%?s\\t%0, %1"
2716   [(set_attr "conds" "set")]
2719 ;; Fixed <--> Floating conversion insns
2721 (define_expand "floatsisf2"
2722   [(set (match_operand:SF           0 "s_register_operand" "")
2723         (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2724   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2725   "
2726   if (TARGET_CIRRUS)
2727     {
2728       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2729       DONE;
2730     }
2733 (define_expand "floatsidf2"
2734   [(set (match_operand:DF           0 "s_register_operand" "")
2735         (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2736   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2737   "
2738   if (TARGET_CIRRUS)
2739     {
2740       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
2741       DONE;
2742     }
2745 (define_expand "fix_truncsfsi2"
2746   [(set (match_operand:SI         0 "s_register_operand" "")
2747         (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand"  ""))))]
2748   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2749   "
2750   if (TARGET_CIRRUS)
2751     {
2752       if (!cirrus_fp_register (operands[0], SImode))
2753         operands[0] = force_reg (SImode, operands[0]);
2754       if (!cirrus_fp_register (operands[1], SFmode))
2755         operands[1] = force_reg (SFmode, operands[0]);
2756       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
2757       DONE;
2758     }
2761 (define_expand "fix_truncdfsi2"
2762   [(set (match_operand:SI         0 "s_register_operand" "")
2763         (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand"  ""))))]
2764   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2765   "
2766   if (TARGET_CIRRUS)
2767     {
2768       if (!cirrus_fp_register (operands[1], DFmode))
2769         operands[1] = force_reg (DFmode, operands[0]);
2770       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
2771       DONE;
2772     }
2775 ;; Truncation insns
2777 (define_expand "truncdfsf2"
2778   [(set (match_operand:SF  0 "s_register_operand" "")
2779         (float_truncate:SF
2780          (match_operand:DF 1 "s_register_operand" "")))]
2781   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2782   ""
2785 ;; Zero and sign extension instructions.
2787 (define_insn "zero_extendsidi2"
2788   [(set (match_operand:DI 0 "s_register_operand" "=r")
2789         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2790   "TARGET_ARM"
2791   "*
2792     if (REGNO (operands[1])
2793         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2794       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2795     return \"mov%?\\t%R0, #0\";
2796   "
2797   [(set_attr "length" "8")
2798    (set_attr "predicable" "yes")]
2801 (define_insn "zero_extendqidi2"
2802   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
2803         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2804   "TARGET_ARM"
2805   "@
2806    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2807    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2808   [(set_attr "length" "8")
2809    (set_attr "predicable" "yes")
2810    (set_attr "type" "*,load")
2811    (set_attr "pool_range" "*,4092")
2812    (set_attr "neg_pool_range" "*,4084")]
2815 (define_insn "extendsidi2"
2816   [(set (match_operand:DI 0 "s_register_operand" "=r")
2817         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2818   "TARGET_ARM"
2819   "*
2820     if (REGNO (operands[1])
2821         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2822       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2823     return \"mov%?\\t%R0, %Q0, asr #31\";
2824   "
2825   [(set_attr "length" "8")
2826    (set_attr "shift" "1")
2827    (set_attr "predicable" "yes")]
2830 (define_expand "zero_extendhisi2"
2831   [(set (match_dup 2)
2832         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2833                    (const_int 16)))
2834    (set (match_operand:SI 0 "s_register_operand" "")
2835         (lshiftrt:SI (match_dup 2) (const_int 16)))]
2836   "TARGET_EITHER"
2837   "
2838   {
2839     if (TARGET_ARM)
2840       {
2841         if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2842           {
2843            /* Note: We do not have to worry about TARGET_MMU_TRAPS
2844               here because the insn below will generate an LDRH instruction
2845               rather than an LDR instruction, so we cannot get an unaligned
2846               word access.  */
2847             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2848                                     gen_rtx_ZERO_EXTEND (SImode,
2849                                                          operands[1])));
2850             DONE;
2851           }
2852         if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2853           {
2854             emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2855             DONE;
2856           }
2857         if (!s_register_operand (operands[1], HImode))
2858           operands[1] = copy_to_mode_reg (HImode, operands[1]);
2859         operands[1] = gen_lowpart (SImode, operands[1]);
2860         operands[2] = gen_reg_rtx (SImode);
2861       }
2862     else /* TARGET_THUMB */
2863       {
2864         if (GET_CODE (operands[1]) == MEM)
2865           {
2866             rtx tmp;
2868             tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
2869             tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
2870             emit_insn (tmp);
2871           }
2872         else
2873           {
2874             rtx ops[3];
2875             
2876             if (!s_register_operand (operands[1], HImode))
2877               operands[1] = copy_to_mode_reg (HImode, operands[1]);
2878             operands[1] = gen_lowpart (SImode, operands[1]);
2879             operands[2] = gen_reg_rtx (SImode);
2880             
2881             ops[0] = operands[2];
2882             ops[1] = operands[1];
2883             ops[2] = GEN_INT (16);
2884             
2885             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2886                                     gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
2888             ops[0] = operands[0];
2889             ops[1] = operands[2];
2890             ops[2] = GEN_INT (16);
2892             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2893                                     gen_rtx_LSHIFTRT (SImode, ops[1],
2894                                                       ops[2])));
2895           }
2896         DONE; 
2897       }
2898   }"
2901 (define_insn "*thumb_zero_extendhisi2"
2902   [(set (match_operand:SI                 0 "register_operand" "=l")
2903         (zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
2904   "TARGET_THUMB"
2905   "*
2906   rtx mem = XEXP (operands[1], 0);
2908   if (GET_CODE (mem) == CONST)
2909     mem = XEXP (mem, 0);
2910     
2911   if (GET_CODE (mem) == LABEL_REF)
2912     return \"ldr\\t%0, %1\";
2913     
2914   if (GET_CODE (mem) == PLUS)
2915     {
2916       rtx a = XEXP (mem, 0);
2917       rtx b = XEXP (mem, 1);
2919       /* This can happen due to bugs in reload.  */
2920       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
2921         {
2922           rtx ops[2];
2923           ops[0] = operands[0];
2924           ops[1] = a;
2925       
2926           output_asm_insn (\"mov        %0, %1\", ops);
2928           XEXP (mem, 0) = operands[0];
2929        }
2931       else if (   GET_CODE (a) == LABEL_REF
2932                && GET_CODE (b) == CONST_INT)
2933         return \"ldr\\t%0, %1\";
2934     }
2935     
2936   return \"ldrh\\t%0, %1\";
2937   "
2938   [(set_attr "length" "4")
2939    (set_attr "type" "load")
2940    (set_attr "pool_range" "60")]
2943 (define_insn "*arm_zero_extendhisi2"
2944   [(set (match_operand:SI                 0 "s_register_operand" "=r")
2945         (zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
2946   "TARGET_ARM && arm_arch4"
2947   "ldr%?h\\t%0, %1"
2948   [(set_attr "type" "load")
2949    (set_attr "predicable" "yes")
2950    (set_attr "pool_range" "256")
2951    (set_attr "neg_pool_range" "244")]
2954 (define_split
2955   [(set (match_operand:SI 0 "s_register_operand" "")
2956         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2957    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2958   "TARGET_ARM && (!arm_arch4)"
2959   [(set (match_dup 2) (match_dup 1))
2960    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2961   "
2962   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
2963     FAIL;
2964   "
2967 (define_split
2968   [(set (match_operand:SI 0 "s_register_operand" "")
2969         (match_operator:SI 3 "shiftable_operator"
2970          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2971           (match_operand:SI 4 "s_register_operand" "")]))
2972    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2973   "TARGET_ARM && (!arm_arch4)"
2974   [(set (match_dup 2) (match_dup 1))
2975    (set (match_dup 0)
2976         (match_op_dup 3
2977          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2978   "
2979   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
2980     FAIL;
2981   "
2984 (define_expand "zero_extendqisi2"
2985   [(set (match_operand:SI 0 "s_register_operand" "")
2986         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
2987   "TARGET_EITHER"
2988   "
2989   if (GET_CODE (operands[1]) != MEM)
2990     {
2991       if (TARGET_ARM)
2992         {
2993           emit_insn (gen_andsi3 (operands[0],
2994                                  gen_lowpart (SImode, operands[1]),
2995                                  GEN_INT (255)));
2996         }
2997       else /* TARGET_THUMB */
2998         {
2999           rtx temp = gen_reg_rtx (SImode);
3000           rtx ops[3];
3001           
3002           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3003           operands[1] = gen_lowpart (SImode, operands[1]);
3005           ops[0] = temp;
3006           ops[1] = operands[1];
3007           ops[2] = GEN_INT (24);
3009           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3010                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3011           
3012           ops[0] = operands[0];
3013           ops[1] = temp;
3014           ops[2] = GEN_INT (24);
3016           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3017                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3018         }
3019       DONE;
3020     }
3021   "
3024 (define_insn "*thumb_zero_extendqisi2"
3025   [(set (match_operand:SI                 0 "register_operand" "=l")
3026         (zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3027   "TARGET_THUMB"
3028   "ldrb\\t%0, %1"
3029   [(set_attr "length" "2")
3030    (set_attr "type" "load")
3031    (set_attr "pool_range" "32")]
3034 (define_insn "*arm_zero_extendqisi2"
3035   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3036         (zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3037   "TARGET_ARM"
3038   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3039   [(set_attr "type" "load")
3040    (set_attr "predicable" "yes")
3041    (set_attr "pool_range" "4096")
3042    (set_attr "neg_pool_range" "4084")]
3045 (define_split
3046   [(set (match_operand:SI 0 "s_register_operand" "")
3047         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3048    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3049   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3050   [(set (match_dup 2) (match_dup 1))
3051    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3052   ""
3055 (define_insn "*compareqi_eq0"
3056   [(set (reg:CC_Z CC_REGNUM)
3057         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3058                          (const_int 0)))]
3059   "TARGET_ARM"
3060   "tst\\t%0, #255"
3061   [(set_attr "conds" "set")]
3064 (define_expand "extendhisi2"
3065   [(set (match_dup 2)
3066         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3067                    (const_int 16)))
3068    (set (match_operand:SI 0 "s_register_operand" "")
3069         (ashiftrt:SI (match_dup 2)
3070                      (const_int 16)))]
3071   "TARGET_EITHER"
3072   "
3073   {
3074     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3075       {
3076        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3077           here because the insn below will generate an LDRH instruction
3078           rather than an LDR instruction, so we cannot get an unaligned
3079           word access.  */
3080         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3081                    gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3082         DONE;
3083       }
3085     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3086       {
3087         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3088         DONE;
3089       }
3090     if (!s_register_operand (operands[1], HImode))
3091       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3092     operands[1] = gen_lowpart (SImode, operands[1]);
3093     operands[2] = gen_reg_rtx (SImode);
3095     if (TARGET_THUMB)
3096       {
3097         rtx ops[3];
3098         
3099         ops[0] = operands[2];
3100         ops[1] = operands[1];
3101         ops[2] = GEN_INT (16);
3102         
3103         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3104                                 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3105             
3106         ops[0] = operands[0];
3107         ops[1] = operands[2];
3108         ops[2] = GEN_INT (16);
3109         
3110         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3111                                 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3112         
3113         DONE;
3114       }
3115   }"
3118 (define_insn "*thumb_extendhisi2_insn"
3119   [(set (match_operand:SI                 0 "register_operand" "=l")
3120         (sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3121    (clobber (match_scratch:SI             2                   "=&l"))]
3122   "TARGET_THUMB"
3123   "*
3124   {
3125     rtx ops[4];
3126     rtx mem = XEXP (operands[1], 0);
3128     /* This code used to try to use 'V', and fix the address only if it was
3129        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3130        range of QImode offsets, and offsettable_address_p does a QImode
3131        address check.  */
3132        
3133     if (GET_CODE (mem) == CONST)
3134       mem = XEXP (mem, 0);
3135     
3136     if (GET_CODE (mem) == LABEL_REF)
3137       return \"ldr\\t%0, %1\";
3138     
3139     if (GET_CODE (mem) == PLUS)
3140       {
3141         rtx a = XEXP (mem, 0);
3142         rtx b = XEXP (mem, 1);
3144         if (GET_CODE (a) == LABEL_REF
3145             && GET_CODE (b) == CONST_INT)
3146           return \"ldr\\t%0, %1\";
3148         if (GET_CODE (b) == REG)
3149           return \"ldrsh\\t%0, %1\";
3150           
3151         ops[1] = a;
3152         ops[2] = b;
3153       }
3154     else
3155       {
3156         ops[1] = mem;
3157         ops[2] = const0_rtx;
3158       }
3159       
3160     if (GET_CODE (ops[1]) != REG)
3161       {
3162         debug_rtx (ops[1]);
3163         abort ();
3164       }
3166     ops[0] = operands[0];
3167     ops[3] = operands[2];
3168     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3169     return \"\";
3170   }"
3171   [(set_attr "length" "4")
3172    (set_attr "type" "load")
3173    (set_attr "pool_range" "1020")]
3176 (define_expand "extendhisi2_mem"
3177   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3178    (set (match_dup 3)
3179         (zero_extend:SI (match_dup 7)))
3180    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3181    (set (match_operand:SI 0 "" "")
3182         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3183   "TARGET_ARM"
3184   "
3185   {
3186     rtx mem1, mem2;
3187     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3189     mem1 = gen_rtx_MEM (QImode, addr);
3190     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3191     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3192     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3193     operands[0] = gen_lowpart (SImode, operands[0]);
3194     operands[1] = mem1;
3195     operands[2] = gen_reg_rtx (SImode);
3196     operands[3] = gen_reg_rtx (SImode);
3197     operands[6] = gen_reg_rtx (SImode);
3198     operands[7] = mem2;
3200     if (BYTES_BIG_ENDIAN)
3201       {
3202         operands[4] = operands[2];
3203         operands[5] = operands[3];
3204       }
3205     else
3206       {
3207         operands[4] = operands[3];
3208         operands[5] = operands[2];
3209       }
3210   }"
3213 (define_insn "*arm_extendhisi_insn"
3214   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3215         (sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3216   "TARGET_ARM && arm_arch4"
3217   "ldr%?sh\\t%0, %1"
3218   [(set_attr "type" "load")
3219    (set_attr "predicable" "yes")
3220    (set_attr "pool_range" "256")
3221    (set_attr "neg_pool_range" "244")]
3224 (define_split
3225   [(set (match_operand:SI                 0 "s_register_operand" "")
3226         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3227    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3228   "TARGET_ARM && (!arm_arch4)"
3229   [(set (match_dup 2) (match_dup 1))
3230    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3231   "
3232   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3233     FAIL;
3234   "
3237 (define_split
3238   [(set (match_operand:SI                   0 "s_register_operand" "")
3239         (match_operator:SI                  3 "shiftable_operator"
3240          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3241           (match_operand:SI                 4 "s_register_operand" "")]))
3242    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3243   "TARGET_ARM && (!arm_arch4)"
3244   [(set (match_dup 2) (match_dup 1))
3245    (set (match_dup 0)
3246         (match_op_dup 3
3247          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3248   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3249      FAIL;
3250   "
3253 (define_expand "extendqihi2"
3254   [(set (match_dup 2)
3255         (ashift:SI (match_operand:QI 1 "general_operand" "")
3256                    (const_int 24)))
3257    (set (match_operand:HI 0 "s_register_operand" "")
3258         (ashiftrt:SI (match_dup 2)
3259                      (const_int 24)))]
3260   "TARGET_ARM"
3261   "
3262   {
3263     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3264       {
3265         emit_insn (gen_rtx_SET (VOIDmode,
3266                                 operands[0],
3267                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3268         DONE;
3269       }
3270     if (!s_register_operand (operands[1], QImode))
3271       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3272     operands[0] = gen_lowpart (SImode, operands[0]);
3273     operands[1] = gen_lowpart (SImode, operands[1]);
3274     operands[2] = gen_reg_rtx (SImode);
3275   }"
3278 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3279 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3280 (define_insn "*extendqihi_insn"
3281   [(set (match_operand:HI                 0 "s_register_operand" "=r")
3282         (sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3283   "TARGET_ARM && arm_arch4"
3284   "*
3285   /* If the address is invalid, this will split the instruction into two. */
3286   if (bad_signed_byte_operand (operands[1], VOIDmode))
3287     return \"#\";
3288   return \"ldr%?sb\\t%0, %1\";
3289   "
3290   [(set_attr "type" "load")
3291    (set_attr "predicable" "yes")
3292    (set_attr "length" "8")
3293    (set_attr "pool_range" "256")
3294    (set_attr "neg_pool_range" "244")]
3297 (define_split
3298   [(set (match_operand:HI 0 "s_register_operand" "")
3299         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3300   "TARGET_ARM && arm_arch4 && reload_completed"
3301   [(set (match_dup 3) (match_dup 1))
3302    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3303   "
3304   {
3305     HOST_WIDE_INT offset;
3307     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3308     operands[2] = gen_rtx_MEM (QImode, operands[3]);
3309     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3310     operands[1] = XEXP (operands[1], 0);
3311     if (GET_CODE (operands[1]) == PLUS
3312         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3313         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3314              || const_ok_for_arm (-offset)))
3315       {
3316         HOST_WIDE_INT low = (offset > 0
3317                              ? (offset & 0xff) : -((-offset) & 0xff));
3318         XEXP (operands[2], 0) = plus_constant (operands[3], low);
3319         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3320       }
3321     /* Ensure the sum is in correct canonical form */
3322     else if (GET_CODE (operands[1]) == PLUS
3323              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3324              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3325       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3326                                            XEXP (operands[1], 1),
3327                                            XEXP (operands[1], 0));
3328   }"
3331 (define_expand "extendqisi2"
3332   [(set (match_dup 2)
3333         (ashift:SI (match_operand:QI 1 "general_operand" "")
3334                    (const_int 24)))
3335    (set (match_operand:SI 0 "s_register_operand" "")
3336         (ashiftrt:SI (match_dup 2)
3337                      (const_int 24)))]
3338   "TARGET_EITHER"
3339   "
3340   {
3341     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3342       {
3343         emit_insn (gen_rtx_SET (VOIDmode,
3344                                 operands[0],
3345                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3346         DONE;
3347       }
3348     if (!s_register_operand (operands[1], QImode))
3349       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3350     operands[1] = gen_lowpart (SImode, operands[1]);
3351     operands[2] = gen_reg_rtx (SImode);
3352     
3353     if (TARGET_THUMB)
3354       {
3355         rtx ops[3];
3356         
3357         ops[0] = operands[2];
3358         ops[1] = operands[1];
3359         ops[2] = GEN_INT (24);
3360         
3361         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3362                    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3364         ops[0] = operands[0];
3365         ops[1] = operands[2];
3366         ops[2] = GEN_INT (24);
3367         
3368         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3369                    gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3370         
3371         DONE;
3372       }
3373   }"
3376 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3377 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3378 (define_insn "*arm_extendqisi_insn"
3379   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3380         (sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3381   "TARGET_ARM && arm_arch4"
3382   "*
3383   /* If the address is invalid, this will split the instruction into two. */
3384   if (bad_signed_byte_operand (operands[1], VOIDmode))
3385     return \"#\";
3386   return \"ldr%?sb\\t%0, %1\";
3387   "
3388   [(set_attr "type" "load")
3389    (set_attr "predicable" "yes")
3390    (set_attr "length" "8")
3391    (set_attr "pool_range" "256")
3392    (set_attr "neg_pool_range" "244")]
3395 (define_split
3396   [(set (match_operand:SI 0 "s_register_operand" "")
3397         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3398   "TARGET_ARM && arm_arch4 && reload_completed"
3399   [(set (match_dup 0) (match_dup 1))
3400    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3401   "
3402   {
3403     HOST_WIDE_INT offset;
3405     operands[2] = gen_rtx_MEM (QImode, operands[0]);
3406     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3407     operands[1] = XEXP (operands[1], 0);
3408     if (GET_CODE (operands[1]) == PLUS
3409         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3410         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3411              || const_ok_for_arm (-offset)))
3412       {
3413         HOST_WIDE_INT low = (offset > 0
3414                              ? (offset & 0xff) : -((-offset) & 0xff));
3415         XEXP (operands[2], 0) = plus_constant (operands[0], low);
3416         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3417       }
3418     /* Ensure the sum is in correct canonical form */
3419     else if (GET_CODE (operands[1]) == PLUS
3420              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3421              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3422       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3423                                            XEXP (operands[1], 1),
3424                                            XEXP (operands[1], 0));
3425   }"
3428 (define_insn "*thumb_extendqisi2_insn"
3429   [(set (match_operand:SI                 0 "register_operand" "=l,l")
3430         (sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3431   "TARGET_THUMB"
3432   "*
3433   {
3434     rtx ops[3];
3435     rtx mem = XEXP (operands[1], 0);
3436     
3437     if (GET_CODE (mem) == CONST)
3438       mem = XEXP (mem, 0);
3439     
3440     if (GET_CODE (mem) == LABEL_REF)
3441       return \"ldr\\t%0, %1\";
3443     if (GET_CODE (mem) == PLUS
3444         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3445       return \"ldr\\t%0, %1\";
3446       
3447     if (which_alternative == 0)
3448       return \"ldrsb\\t%0, %1\";
3449       
3450     ops[0] = operands[0];
3451     
3452     if (GET_CODE (mem) == PLUS)
3453       {
3454         rtx a = XEXP (mem, 0);
3455         rtx b = XEXP (mem, 1);
3456         
3457         ops[1] = a;
3458         ops[2] = b;
3460         if (GET_CODE (a) == REG)
3461           {
3462             if (GET_CODE (b) == REG)
3463               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3464             else if (REGNO (a) == REGNO (ops[0]))
3465               {
3466                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3467                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3468                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3469               }
3470             else
3471               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3472           }
3473         else if (GET_CODE (b) != REG)
3474           abort ();
3475         else
3476           {
3477             if (REGNO (b) == REGNO (ops[0]))
3478               {
3479                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3480                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3481                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3482               }
3483             else
3484               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3485           }
3486       }
3487     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3488       {
3489         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3490         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3491         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3492       }
3493     else
3494       {
3495         ops[1] = mem;
3496         ops[2] = const0_rtx;
3497         
3498         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3499       }
3500     return \"\";
3501   }"
3502   [(set_attr "length" "2,6")
3503    (set_attr "type" "load,load")
3504    (set_attr "pool_range" "32,32")]
3507 (define_expand "extendsfdf2"
3508   [(set (match_operand:DF                  0 "s_register_operand" "")
3509         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "")))]
3510   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3511   ""
3514 ;; Move insns (including loads and stores)
3516 ;; XXX Just some ideas about movti.
3517 ;; I don't think these are a good idea on the arm, there just aren't enough
3518 ;; registers
3519 ;;(define_expand "loadti"
3520 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3521 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3522 ;;  "" "")
3524 ;;(define_expand "storeti"
3525 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3526 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3527 ;;  "" "")
3529 ;;(define_expand "movti"
3530 ;;  [(set (match_operand:TI 0 "general_operand" "")
3531 ;;      (match_operand:TI 1 "general_operand" ""))]
3532 ;;  ""
3533 ;;  "
3535 ;;  rtx insn;
3537 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3538 ;;    operands[1] = copy_to_reg (operands[1]);
3539 ;;  if (GET_CODE (operands[0]) == MEM)
3540 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3541 ;;  else if (GET_CODE (operands[1]) == MEM)
3542 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3543 ;;  else
3544 ;;    FAIL;
3546 ;;  emit_insn (insn);
3547 ;;  DONE;
3548 ;;}")
3550 ;; Recognize garbage generated above.
3552 ;;(define_insn ""
3553 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3554 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3555 ;;  ""
3556 ;;  "*
3557 ;;  {
3558 ;;    register mem = (which_alternative < 3);
3559 ;;    register const char *template;
3561 ;;    operands[mem] = XEXP (operands[mem], 0);
3562 ;;    switch (which_alternative)
3563 ;;      {
3564 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3565 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3566 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3567 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3568 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3569 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3570 ;;      }
3571 ;;    output_asm_insn (template, operands);
3572 ;;    return \"\";
3573 ;;  }")
3575 (define_expand "movdi"
3576   [(set (match_operand:DI 0 "general_operand" "")
3577         (match_operand:DI 1 "general_operand" ""))]
3578   "TARGET_EITHER"
3579   "
3580   if (TARGET_THUMB)
3581     {
3582       if (!no_new_pseudos)
3583         {
3584           if (GET_CODE (operands[0]) != REG)
3585             operands[1] = force_reg (DImode, operands[1]);
3586         }
3587     }
3588   "
3591 (define_insn "*arm_movdi"
3592   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3593         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3594   "TARGET_ARM && !TARGET_CIRRUS"
3595   "*
3596   return (output_move_double (operands));
3597   "
3598   [(set_attr "length" "8")
3599    (set_attr "type" "*,load,store2")
3600    (set_attr "pool_range" "*,1020,*")
3601    (set_attr "neg_pool_range" "*,1008,*")]
3604 ;;; ??? This should have alternatives for constants.
3605 ;;; ??? This was originally identical to the movdf_insn pattern.
3606 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3607 ;;; thumb_reorg with a memory reference.
3608 (define_insn "*thumb_movdi_insn"
3609   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3610         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3611   "TARGET_THUMB
3612    && !TARGET_CIRRUS
3613    && (   register_operand (operands[0], DImode)
3614        || register_operand (operands[1], DImode))"
3615   "*
3616   {
3617   switch (which_alternative)
3618     {
3619     default:
3620     case 0:
3621       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3622         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3623       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3624     case 1:
3625       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3626     case 2:
3627       operands[1] = GEN_INT (- INTVAL (operands[1]));
3628       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3629     case 3:
3630       return \"ldmia\\t%1, {%0, %H0}\";
3631     case 4:
3632       return \"stmia\\t%0, {%1, %H1}\";
3633     case 5:
3634       return thumb_load_double_from_address (operands);
3635     case 6:
3636       operands[2] = gen_rtx (MEM, SImode,
3637                              plus_constant (XEXP (operands[0], 0), 4));
3638       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3639       return \"\";
3640     case 7:
3641       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3642         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3643       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3644     }
3645   }"
3646   [(set_attr "length" "4,4,6,2,2,6,4,4")
3647    (set_attr "type" "*,*,*,load,store2,load,store2,*")
3648    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3651 (define_expand "movsi"
3652   [(set (match_operand:SI 0 "general_operand" "")
3653         (match_operand:SI 1 "general_operand" ""))]
3654   "TARGET_EITHER"
3655   "
3656   if (TARGET_ARM)
3657     {
3658       /* Everything except mem = const or mem = mem can be done easily */
3659       if (GET_CODE (operands[0]) == MEM)
3660         operands[1] = force_reg (SImode, operands[1]);
3661       if (GET_CODE (operands[1]) == CONST_INT
3662           && !(const_ok_for_arm (INTVAL (operands[1]))
3663                || const_ok_for_arm (~INTVAL (operands[1]))))
3664         {
3665            arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3666                               NULL_RTX,
3667                               (no_new_pseudos ? 0
3668                                : preserve_subexpressions_p ()));
3669           DONE;
3670         }
3671     }
3672   else /* TARGET_THUMB.... */
3673     {
3674       if (!no_new_pseudos)
3675         {
3676           if (GET_CODE (operands[0]) != REG)
3677             operands[1] = force_reg (SImode, operands[1]);
3678         }
3679     }
3680     
3681   if (flag_pic
3682       && (CONSTANT_P (operands[1])
3683          || symbol_mentioned_p (operands[1])
3684          || label_mentioned_p (operands[1])))
3685     operands[1] = legitimize_pic_address (operands[1], SImode,
3686                                           (no_new_pseudos ? operands[0] : 0));
3687   "
3690 (define_insn "*arm_movsi_insn"
3691   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3692         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
3693   "TARGET_ARM
3694    && (   register_operand (operands[0], SImode)
3695        || register_operand (operands[1], SImode))"
3696   "@
3697    mov%?\\t%0, %1
3698    mvn%?\\t%0, #%B1
3699    ldr%?\\t%0, %1
3700    str%?\\t%1, %0"
3701   [(set_attr "type" "*,*,load,store1")
3702    (set_attr "predicable" "yes")
3703    (set_attr "pool_range" "*,*,4096,*")
3704    (set_attr "neg_pool_range" "*,*,4084,*")]
3707 (define_split
3708   [(set (match_operand:SI 0 "s_register_operand" "")
3709         (match_operand:SI 1 "const_int_operand" ""))]
3710   "TARGET_ARM
3711   && (!(const_ok_for_arm (INTVAL (operands[1]))
3712         || const_ok_for_arm (~INTVAL (operands[1]))))"
3713   [(clobber (const_int 0))]
3714   "
3715   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3716                       NULL_RTX, 0);
3717   DONE;
3718   "
3721 (define_insn "*thumb_movsi_insn"
3722   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3723         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
3724   "TARGET_THUMB
3725    && (   register_operand (operands[0], SImode) 
3726        || register_operand (operands[1], SImode))"
3727   "@
3728    mov  %0, %1
3729    mov  %0, %1
3730    #
3731    #
3732    ldmia\\t%1, {%0}
3733    stmia\\t%0, {%1}
3734    ldr\\t%0, %1
3735    str\\t%1, %0
3736    mov\\t%0, %1"
3737   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3738    (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3739    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3742 (define_split 
3743   [(set (match_operand:SI 0 "register_operand" "")
3744         (match_operand:SI 1 "const_int_operand" ""))]
3745   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3746   [(set (match_dup 0) (match_dup 1))
3747    (set (match_dup 0) (neg:SI (match_dup 0)))]
3748   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3751 (define_split 
3752   [(set (match_operand:SI 0 "register_operand" "")
3753         (match_operand:SI 1 "const_int_operand" ""))]
3754   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3755   [(set (match_dup 0) (match_dup 1))
3756    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3757   "
3758   {
3759     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3760     unsigned HOST_WIDE_INT mask = 0xff;
3761     int i;
3762     
3763     for (i = 0; i < 25; i++)
3764       if ((val & (mask << i)) == val)
3765         break;
3767     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
3768     if (i == 0)
3769       FAIL;
3771     operands[1] = GEN_INT (val >> i);
3772     operands[2] = GEN_INT (i);
3773   }"
3776 ;; When generating pic, we need to load the symbol offset into a register.
3777 ;; So that the optimizer does not confuse this with a normal symbol load
3778 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
3779 ;; since that is the only type of relocation we can use.
3781 ;; The rather odd constraints on the following are to force reload to leave
3782 ;; the insn alone, and to force the minipool generation pass to then move
3783 ;; the GOT symbol to memory.
3785 (define_insn "pic_load_addr_arm"
3786   [(set (match_operand:SI 0 "s_register_operand" "=r")
3787         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3788   "TARGET_ARM && flag_pic"
3789   "ldr%?\\t%0, %1"
3790   [(set_attr "type" "load")
3791    (set (attr "pool_range")     (const_int 4096))
3792    (set (attr "neg_pool_range") (const_int 4084))]
3795 (define_insn "pic_load_addr_thumb"
3796   [(set (match_operand:SI 0 "s_register_operand" "=l")
3797         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3798   "TARGET_THUMB && flag_pic"
3799   "ldr\\t%0, %1"
3800   [(set_attr "type" "load")
3801    (set (attr "pool_range") (const_int 1024))]
3804 ;; This variant is used for AOF assembly, since it needs to mention the
3805 ;; pic register in the rtl.
3806 (define_expand "pic_load_addr_based"
3807   [(set (match_operand:SI 0 "s_register_operand" "")
3808         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
3809   "TARGET_ARM && flag_pic"
3810   "operands[2] = pic_offset_table_rtx;"
3813 (define_insn "*pic_load_addr_based_insn"
3814   [(set (match_operand:SI 0 "s_register_operand" "=r")
3815         (unspec:SI [(match_operand 1 "" "")
3816                     (match_operand 2 "s_register_operand" "r")]
3817                    UNSPEC_PIC_SYM))]
3818   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
3819   "*
3820 #ifdef AOF_ASSEMBLER
3821   operands[1] = aof_pic_entry (operands[1]);
3822 #endif
3823   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3824   return \"\";
3825   "
3826   [(set_attr "type" "load")
3827    (set (attr "pool_range")
3828         (if_then_else (eq_attr "is_thumb" "yes")
3829                       (const_int 1024)
3830                       (const_int 4096)))
3831    (set (attr "neg_pool_range")
3832         (if_then_else (eq_attr "is_thumb" "yes")
3833                       (const_int 0)
3834                       (const_int 4084)))]
3837 (define_insn "pic_add_dot_plus_four"
3838   [(set (match_operand:SI 0 "register_operand" "+r")
3839         (unspec:SI [(plus:SI (match_dup 0)
3840                              (const (plus:SI (pc) (const_int 4))))]
3841                    UNSPEC_PIC_BASE))
3842    (use (label_ref (match_operand 1 "" "")))]
3843   "TARGET_THUMB && flag_pic"
3844   "*
3845   (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3846                              CODE_LABEL_NUMBER (operands[1]));
3847   return \"add\\t%0, %|pc\";
3848   "
3849   [(set_attr "length" "2")]
3852 (define_insn "pic_add_dot_plus_eight"
3853   [(set (match_operand:SI 0 "register_operand" "+r")
3854         (unspec:SI [(plus:SI (match_dup 0)
3855                              (const (plus:SI (pc) (const_int 8))))]
3856                    UNSPEC_PIC_BASE))
3857    (use (label_ref (match_operand 1 "" "")))]
3858   "TARGET_ARM && flag_pic"
3859   "*
3860     (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3861                                CODE_LABEL_NUMBER (operands[1]));
3862     return \"add%?\\t%0, %|pc, %0\";
3863   "
3864   [(set_attr "predicable" "yes")]
3867 (define_expand "builtin_setjmp_receiver"
3868   [(label_ref (match_operand 0 "" ""))]
3869   "flag_pic"
3870   "
3872   arm_finalize_pic (0);
3873   DONE;
3876 ;; If copying one reg to another we can set the condition codes according to
3877 ;; its value.  Such a move is common after a return from subroutine and the
3878 ;; result is being tested against zero.
3880 (define_insn "*movsi_compare0"
3881   [(set (reg:CC CC_REGNUM)
3882         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
3883                     (const_int 0)))
3884    (set (match_operand:SI 0 "s_register_operand" "=r,r")
3885         (match_dup 1))]
3886   "TARGET_ARM"
3887   "@
3888    cmp%?\\t%0, #0
3889    sub%?s\\t%0, %1, #0"
3890   [(set_attr "conds" "set")]
3893 ;; Subroutine to store a half word from a register into memory.
3894 ;; Operand 0 is the source register (HImode)
3895 ;; Operand 1 is the destination address in a register (SImode)
3897 ;; In both this routine and the next, we must be careful not to spill
3898 ;; a memory address of reg+large_const into a separate PLUS insn, since this
3899 ;; can generate unrecognizable rtl.
3901 (define_expand "storehi"
3902   [;; store the low byte
3903    (set (match_operand 1 "" "") (match_dup 3))
3904    ;; extract the high byte
3905    (set (match_dup 2)
3906         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3907    ;; store the high byte
3908    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
3909   "TARGET_ARM"
3910   "
3911   {
3912     rtx op1 = operands[1];
3913     rtx addr = XEXP (op1, 0);
3914     enum rtx_code code = GET_CODE (addr);
3916     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3917         || code == MINUS)
3918       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
3920     operands[4] = adjust_address (op1, QImode, 1);
3921     operands[1] = adjust_address (operands[1], QImode, 0);
3922     operands[3] = gen_lowpart (QImode, operands[0]);
3923     operands[0] = gen_lowpart (SImode, operands[0]);
3924     operands[2] = gen_reg_rtx (SImode); 
3925   }"
3928 (define_expand "storehi_bigend"
3929   [(set (match_dup 4) (match_dup 3))
3930    (set (match_dup 2)
3931         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3932    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
3933   "TARGET_ARM"
3934   "
3935   {
3936     rtx op1 = operands[1];
3937     rtx addr = XEXP (op1, 0);
3938     enum rtx_code code = GET_CODE (addr);
3940     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3941         || code == MINUS)
3942       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
3944     operands[4] = adjust_address (op1, QImode, 1);
3945     operands[1] = adjust_address (operands[1], QImode, 0);
3946     operands[3] = gen_lowpart (QImode, operands[0]);
3947     operands[0] = gen_lowpart (SImode, operands[0]);
3948     operands[2] = gen_reg_rtx (SImode);
3949   }"
3952 ;; Subroutine to store a half word integer constant into memory.
3953 (define_expand "storeinthi"
3954   [(set (match_operand 0 "" "")
3955         (subreg:QI (match_operand 1 "" "") 0))
3956    (set (match_dup 3) (match_dup 2))]
3957   "TARGET_ARM"
3958   "
3959   {
3960     HOST_WIDE_INT value = INTVAL (operands[1]);
3961     rtx addr = XEXP (operands[0], 0);
3962     rtx op0 = operands[0];
3963     enum rtx_code code = GET_CODE (addr);
3965     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3966         || code == MINUS)
3967       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
3969     operands[1] = gen_reg_rtx (SImode);
3970     if (BYTES_BIG_ENDIAN)
3971       {
3972         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
3973         if ((value & 255) == ((value >> 8) & 255))
3974           operands[2] = operands[1];
3975         else
3976           {
3977             operands[2] = gen_reg_rtx (SImode);
3978             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
3979           }
3980       }
3981     else
3982       {
3983         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
3984         if ((value & 255) == ((value >> 8) & 255))
3985           operands[2] = operands[1];
3986         else
3987           {
3988             operands[2] = gen_reg_rtx (SImode);
3989             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
3990           }
3991       }
3993     operands[3] = adjust_address (op0, QImode, 1);
3994     operands[0] = adjust_address (operands[0], QImode, 0);
3995     operands[2] = gen_lowpart (QImode, operands[2]);
3996   }"
3999 (define_expand "storehi_single_op"
4000   [(set (match_operand:HI 0 "memory_operand" "")
4001         (match_operand:HI 1 "general_operand" ""))]
4002   "TARGET_ARM && arm_arch4"
4003   "
4004   if (!s_register_operand (operands[1], HImode))
4005     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4006   "
4009 (define_expand "movhi"
4010   [(set (match_operand:HI 0 "general_operand" "")
4011         (match_operand:HI 1 "general_operand" ""))]
4012   "TARGET_EITHER"
4013   "
4014   if (TARGET_ARM)
4015     {
4016       if (!no_new_pseudos)
4017         {
4018           if (GET_CODE (operands[0]) == MEM)
4019             {
4020               if (arm_arch4)
4021                 {
4022                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4023                   DONE;
4024                 }
4025               if (GET_CODE (operands[1]) == CONST_INT)
4026                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4027               else
4028                 {
4029                   if (GET_CODE (operands[1]) == MEM)
4030                     operands[1] = force_reg (HImode, operands[1]);
4031                   if (BYTES_BIG_ENDIAN)
4032                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4033                   else
4034                    emit_insn (gen_storehi (operands[1], operands[0]));
4035                 }
4036               DONE;
4037             }
4038           /* Sign extend a constant, and keep it in an SImode reg.  */
4039           else if (GET_CODE (operands[1]) == CONST_INT)
4040             {
4041               rtx reg = gen_reg_rtx (SImode);
4042               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4044               /* If the constant is already valid, leave it alone.  */
4045               if (!const_ok_for_arm (val))
4046                 {
4047                   /* If setting all the top bits will make the constant 
4048                      loadable in a single instruction, then set them.  
4049                      Otherwise, sign extend the number.  */
4051                   if (const_ok_for_arm (~(val | ~0xffff)))
4052                     val |= ~0xffff;
4053                   else if (val & 0x8000)
4054                     val |= ~0xffff;
4055                 }
4057               emit_insn (gen_movsi (reg, GEN_INT (val)));
4058               operands[1] = gen_lowpart (HImode, reg);
4059             }
4060           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4061                    && GET_CODE (operands[1]) == MEM)
4062             {
4063               rtx reg = gen_reg_rtx (SImode);
4065               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4066               operands[1] = gen_lowpart (HImode, reg);
4067             }
4068           else if (!arm_arch4)
4069             {
4070              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4071                 for v4 and up architectures because LDRH instructions will
4072                 be used to access the HI values, and these cannot generate
4073                 unaligned word access faults in the MMU.  */
4074               if (GET_CODE (operands[1]) == MEM)
4075                 {
4076                   if (TARGET_MMU_TRAPS)
4077                     {
4078                       rtx base;
4079                       rtx offset = const0_rtx;
4080                       rtx reg = gen_reg_rtx (SImode);
4082                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4083                            || (GET_CODE (base) == PLUS
4084                                && (GET_CODE (offset = XEXP (base, 1))
4085                                    == CONST_INT)
4086                                && ((INTVAL(offset) & 1) != 1)
4087                                && GET_CODE (base = XEXP (base, 0)) == REG))
4088                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4089                         {
4090                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4091                           rtx new;
4093                           new = gen_rtx_MEM (SImode,
4094                                              plus_constant (base, new_offset));
4095                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4096                           emit_insn (gen_movsi (reg, new));
4097                           if (((INTVAL (offset) & 2) != 0)
4098                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4099                             {
4100                               rtx reg2 = gen_reg_rtx (SImode);
4102                               emit_insn (gen_lshrsi3 (reg2, reg,
4103                                          GEN_INT (16)));
4104                               reg = reg2;
4105                             }
4106                         }
4107                       else
4108                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4110                       operands[1] = gen_lowpart (HImode, reg);
4111                     }
4112                   else if (BYTES_BIG_ENDIAN)
4113                     {
4114                       rtx base;
4115                       rtx offset = const0_rtx;
4117                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4118                            || (GET_CODE (base) == PLUS
4119                               && (GET_CODE (offset = XEXP (base, 1))
4120                                   == CONST_INT)
4121                               && GET_CODE (base = XEXP (base, 0)) == REG))
4122                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4123                         {
4124                           rtx reg = gen_reg_rtx (SImode);
4125                           rtx new;
4127                           if ((INTVAL (offset) & 2) == 2)
4128                             {
4129                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4130                               new = gen_rtx_MEM (SImode,
4131                                                  plus_constant (base,
4132                                                                 new_offset));
4133                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4134                               emit_insn (gen_movsi (reg, new));
4135                             }
4136                           else
4137                             {
4138                               new = gen_rtx_MEM (SImode,
4139                                                  XEXP (operands[1], 0));
4140                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4141                               emit_insn (gen_rotated_loadsi (reg, new));
4142                             }
4144                           operands[1] = gen_lowpart (HImode, reg);
4145                         }
4146                       else
4147                         {
4148                           emit_insn (gen_movhi_bigend (operands[0],
4149                                                        operands[1]));
4150                           DONE;
4151                         }
4152                     }
4153                }
4154            }
4155         }
4156       /* Handle loading a large integer during reload */
4157       else if (GET_CODE (operands[1]) == CONST_INT
4158                && !const_ok_for_arm (INTVAL (operands[1]))
4159                && !const_ok_for_arm (~INTVAL (operands[1])))
4160         {
4161           /* Writing a constant to memory needs a scratch, which should
4162              be handled with SECONDARY_RELOADs.  */
4163           if (GET_CODE (operands[0]) != REG)
4164             abort ();
4166           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4167           emit_insn (gen_movsi (operands[0], operands[1]));
4168           DONE;
4169        }
4170     }
4171   else /* TARGET_THUMB */
4172     {
4173       if (!no_new_pseudos)
4174         {
4175           if (GET_CODE (operands[0]) != REG)
4176             operands[1] = force_reg (HImode, operands[1]);
4178           /* ??? We shouldn't really get invalid addresses here, but this can
4179              happen if we are passed a SP (never OK for HImode/QImode) or 
4180              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4181              HImode/QImode) relative address.  */
4182           /* ??? This should perhaps be fixed elsewhere, for instance, in
4183              fixup_stack_1, by checking for other kinds of invalid addresses,
4184              e.g. a bare reference to a virtual register.  This may confuse the
4185              alpha though, which must handle this case differently.  */
4186           if (GET_CODE (operands[0]) == MEM
4187               && !memory_address_p (GET_MODE (operands[0]),
4188                                     XEXP (operands[0], 0)))
4189             operands[0]
4190               = replace_equiv_address (operands[0],
4191                                        copy_to_reg (XEXP (operands[0], 0)));
4192    
4193           if (GET_CODE (operands[1]) == MEM
4194               && !memory_address_p (GET_MODE (operands[1]),
4195                                     XEXP (operands[1], 0)))
4196             operands[1]
4197               = replace_equiv_address (operands[1],
4198                                        copy_to_reg (XEXP (operands[1], 0)));
4199         }
4200       /* Handle loading a large integer during reload */
4201       else if (GET_CODE (operands[1]) == CONST_INT
4202                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4203         {
4204           /* Writing a constant to memory needs a scratch, which should
4205              be handled with SECONDARY_RELOADs.  */
4206           if (GET_CODE (operands[0]) != REG)
4207             abort ();
4209           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4210           emit_insn (gen_movsi (operands[0], operands[1]));
4211           DONE;
4212         }
4213     }
4214   "
4217 (define_insn "*thumb_movhi_insn"
4218   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4219         (match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4220   "TARGET_THUMB
4221    && (   register_operand (operands[0], HImode)
4222        || register_operand (operands[1], HImode))"
4223   "*
4224   switch (which_alternative)
4225     {
4226     case 0: return \"add        %0, %1, #0\";
4227     case 2: return \"strh       %1, %0\";
4228     case 3: return \"mov        %0, %1\";
4229     case 4: return \"mov        %0, %1\";
4230     case 5: return \"mov        %0, %1\";
4231     default: abort ();
4232     case 1:
4233       /* The stack pointer can end up being taken as an index register.
4234           Catch this case here and deal with it.  */
4235       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4236           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4237           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4238         {
4239           rtx ops[2];
4240           ops[0] = operands[0];
4241           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4242       
4243           output_asm_insn (\"mov        %0, %1\", ops);
4245           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4246     
4247         }
4248       return \"ldrh     %0, %1\";
4249     }"
4250   [(set_attr "length" "2,4,2,2,2,2")
4251    (set_attr "type" "*,load,store1,*,*,*")
4252    (set_attr "pool_range" "*,64,*,*,*,*")]
4256 (define_insn "rotated_loadsi"
4257   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4258         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4259                    (const_int 16)))]
4260   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4261   "*
4262   {
4263     rtx ops[2];
4265     ops[0] = operands[0];
4266     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4267     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4268     return \"\";
4269   }"
4270   [(set_attr "type" "load")
4271    (set_attr "predicable" "yes")]
4274 (define_expand "movhi_bytes"
4275   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4276    (set (match_dup 3)
4277         (zero_extend:SI (match_dup 6)))
4278    (set (match_operand:SI 0 "" "")
4279          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4280   "TARGET_ARM"
4281   "
4282   {
4283     rtx mem1, mem2;
4284     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4286     mem1 = gen_rtx_MEM (QImode, addr);
4287     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4288     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4289     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4290     operands[0] = gen_lowpart (SImode, operands[0]);
4291     operands[1] = mem1;
4292     operands[2] = gen_reg_rtx (SImode);
4293     operands[3] = gen_reg_rtx (SImode);
4294     operands[6] = mem2;
4296     if (BYTES_BIG_ENDIAN)
4297       {
4298         operands[4] = operands[2];
4299         operands[5] = operands[3];
4300       }
4301     else
4302       {
4303         operands[4] = operands[3];
4304         operands[5] = operands[2];
4305       }
4306   }"
4309 (define_expand "movhi_bigend"
4310   [(set (match_dup 2)
4311         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4312                    (const_int 16)))
4313    (set (match_dup 3)
4314         (ashiftrt:SI (match_dup 2) (const_int 16)))
4315    (set (match_operand:HI 0 "s_register_operand" "")
4316         (subreg:HI (match_dup 3) 0))]
4317   "TARGET_ARM"
4318   "
4319   operands[2] = gen_reg_rtx (SImode);
4320   operands[3] = gen_reg_rtx (SImode);
4321   "
4324 ;; Pattern to recognize insn generated default case above
4325 (define_insn "*movhi_insn_arch4"
4326   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4327         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4328   "TARGET_ARM
4329    && arm_arch4
4330    && (GET_CODE (operands[1]) != CONST_INT
4331        || const_ok_for_arm (INTVAL (operands[1]))
4332        || const_ok_for_arm (~INTVAL (operands[1])))"
4333   "@
4334    mov%?\\t%0, %1\\t%@ movhi
4335    mvn%?\\t%0, #%B1\\t%@ movhi
4336    str%?h\\t%1, %0\\t%@ movhi 
4337    ldr%?h\\t%0, %1\\t%@ movhi"
4338   [(set_attr "type" "*,*,store1,load")
4339    (set_attr "predicable" "yes")
4340    (set_attr "pool_range" "*,*,*,256")
4341    (set_attr "neg_pool_range" "*,*,*,244")]
4344 (define_insn "*movhi_insn_littleend"
4345   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4346         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4347   "TARGET_ARM
4348    && !arm_arch4
4349    && !BYTES_BIG_ENDIAN
4350    && !TARGET_MMU_TRAPS
4351    && (GET_CODE (operands[1]) != CONST_INT
4352        || const_ok_for_arm (INTVAL (operands[1]))
4353        || const_ok_for_arm (~INTVAL (operands[1])))"
4354   "@
4355    mov%?\\t%0, %1\\t%@ movhi
4356    mvn%?\\t%0, #%B1\\t%@ movhi
4357    ldr%?\\t%0, %1\\t%@ movhi"
4358   [(set_attr "type" "*,*,load")
4359    (set_attr "predicable" "yes")
4360    (set_attr "pool_range" "4096")
4361    (set_attr "neg_pool_range" "4084")]
4364 (define_insn "*movhi_insn_bigend"
4365   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4366         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4367   "TARGET_ARM
4368    && !arm_arch4
4369    && BYTES_BIG_ENDIAN
4370    && !TARGET_MMU_TRAPS
4371    && (GET_CODE (operands[1]) != CONST_INT
4372        || const_ok_for_arm (INTVAL (operands[1]))
4373        || const_ok_for_arm (~INTVAL (operands[1])))"
4374   "@
4375    mov%?\\t%0, %1\\t%@ movhi
4376    mvn%?\\t%0, #%B1\\t%@ movhi
4377    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4378   [(set_attr "type" "*,*,load")
4379    (set_attr "predicable" "yes")
4380    (set_attr "length" "4,4,8")
4381    (set_attr "pool_range" "*,*,4092")
4382    (set_attr "neg_pool_range" "*,*,4084")]
4385 (define_insn "*loadhi_si_bigend"
4386   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4387         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4388                    (const_int 16)))]
4389   "TARGET_ARM
4390    && BYTES_BIG_ENDIAN
4391    && !TARGET_MMU_TRAPS"
4392   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4393   [(set_attr "type" "load")
4394    (set_attr "predicable" "yes")
4395    (set_attr "pool_range" "4096")
4396    (set_attr "neg_pool_range" "4084")]
4399 (define_insn "*movhi_bytes"
4400   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4401         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4402   "TARGET_ARM && TARGET_MMU_TRAPS"
4403   "@
4404    mov%?\\t%0, %1\\t%@ movhi
4405    mvn%?\\t%0, #%B1\\t%@ movhi"
4406   [(set_attr "predicable" "yes")]
4409 (define_insn "thumb_movhi_clobber"
4410   [(set (match_operand:HI     0 "memory_operand"   "=m")
4411         (match_operand:HI     1 "register_operand" "l"))
4412    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4413   "TARGET_THUMB"
4414   "*
4415   abort ();"
4417         
4418 ;; We use a DImode scratch because we may occasionally need an additional
4419 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4420 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4421 (define_expand "reload_outhi"
4422   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4423               (match_operand:HI 1 "s_register_operand"        "r")
4424               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4425   "TARGET_EITHER"
4426   "if (TARGET_ARM)
4427      arm_reload_out_hi (operands);
4428    else
4429      thumb_reload_out_hi (operands);
4430   DONE;
4431   "
4434 (define_expand "reload_inhi"
4435   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4436               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4437               (match_operand:DI 2 "s_register_operand" "=&r")])]
4438   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4439   "
4440   if (TARGET_ARM)
4441     arm_reload_in_hi (operands);
4442   else
4443     thumb_reload_out_hi (operands);
4444   DONE;
4447 (define_expand "movqi"
4448   [(set (match_operand:QI 0 "general_operand" "")
4449         (match_operand:QI 1 "general_operand" ""))]
4450   "TARGET_EITHER"
4451   "
4452   if (TARGET_ARM)
4453     {
4454       /* Everything except mem = const or mem = mem can be done easily */
4456       if (!no_new_pseudos)
4457         {
4458           if (GET_CODE (operands[1]) == CONST_INT)
4459             {
4460               rtx reg = gen_reg_rtx (SImode);
4462               emit_insn (gen_movsi (reg, operands[1]));
4463               operands[1] = gen_lowpart (QImode, reg);
4464             }
4465           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4466             {
4467               rtx reg = gen_reg_rtx (SImode);
4469               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4470               operands[1] = gen_lowpart (QImode, reg);
4471             }
4472           if (GET_CODE (operands[0]) == MEM)
4473             operands[1] = force_reg (QImode, operands[1]);
4474         }
4475     }
4476   else /* TARGET_THUMB */
4477     {
4478       if (!no_new_pseudos)
4479         {
4480           if (GET_CODE (operands[0]) != REG)
4481             operands[1] = force_reg (QImode, operands[1]);
4483           /* ??? We shouldn't really get invalid addresses here, but this can
4484              happen if we are passed a SP (never OK for HImode/QImode) or
4485              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4486              HImode/QImode) relative address.  */
4487           /* ??? This should perhaps be fixed elsewhere, for instance, in
4488              fixup_stack_1, by checking for other kinds of invalid addresses,
4489              e.g. a bare reference to a virtual register.  This may confuse the
4490              alpha though, which must handle this case differently.  */
4491           if (GET_CODE (operands[0]) == MEM
4492               && !memory_address_p (GET_MODE (operands[0]),
4493                                      XEXP (operands[0], 0)))
4494             operands[0]
4495               = replace_equiv_address (operands[0],
4496                                        copy_to_reg (XEXP (operands[0], 0)));
4497           if (GET_CODE (operands[1]) == MEM
4498               && !memory_address_p (GET_MODE (operands[1]),
4499                                     XEXP (operands[1], 0)))
4500              operands[1]
4501                = replace_equiv_address (operands[1],
4502                                         copy_to_reg (XEXP (operands[1], 0)));
4503         }
4504       /* Handle loading a large integer during reload */
4505       else if (GET_CODE (operands[1]) == CONST_INT
4506                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4507         {
4508           /* Writing a constant to memory needs a scratch, which should
4509              be handled with SECONDARY_RELOADs.  */
4510           if (GET_CODE (operands[0]) != REG)
4511             abort ();
4513           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4514           emit_insn (gen_movsi (operands[0], operands[1]));
4515           DONE;
4516        }
4517     }
4518   "
4522 (define_insn "*arm_movqi_insn"
4523   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4524         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4525   "TARGET_ARM
4526    && (   register_operand (operands[0], QImode)
4527        || register_operand (operands[1], QImode))"
4528   "@
4529    mov%?\\t%0, %1
4530    mvn%?\\t%0, #%B1
4531    ldr%?b\\t%0, %1
4532    str%?b\\t%1, %0"
4533   [(set_attr "type" "*,*,load,store1")
4534    (set_attr "predicable" "yes")]
4537 (define_insn "*thumb_movqi_insn"
4538   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4539         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4540   "TARGET_THUMB
4541    && (   register_operand (operands[0], QImode)
4542        || register_operand (operands[1], QImode))"
4543   "@
4544    add\\t%0, %1, #0
4545    ldrb\\t%0, %1
4546    strb\\t%1, %0
4547    mov\\t%0, %1
4548    mov\\t%0, %1
4549    mov\\t%0, %1"
4550   [(set_attr "length" "2")
4551    (set_attr "type" "*,load,store1,*,*,*")
4552    (set_attr "pool_range" "*,32,*,*,*,*")]
4555 (define_expand "movsf"
4556   [(set (match_operand:SF 0 "general_operand" "")
4557         (match_operand:SF 1 "general_operand" ""))]
4558   "TARGET_EITHER"
4559   "
4560   if (TARGET_ARM)
4561     {
4562       if (GET_CODE (operands[0]) == MEM)
4563         operands[1] = force_reg (SFmode, operands[1]);
4564     }
4565   else /* TARGET_THUMB */
4566     {
4567       if (!no_new_pseudos)
4568         {
4569            if (GET_CODE (operands[0]) != REG)
4570              operands[1] = force_reg (SFmode, operands[1]);
4571         }
4572     }
4573   "
4576 (define_split
4577   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4578         (match_operand:SF 1 "immediate_operand" ""))]
4579   "TARGET_ARM
4580    && !TARGET_HARD_FLOAT
4581    && reload_completed
4582    && GET_CODE (operands[1]) == CONST_DOUBLE"
4583   [(set (match_dup 2) (match_dup 3))]
4584   "
4585   operands[2] = gen_lowpart (SImode, operands[0]);
4586   operands[3] = gen_lowpart (SImode, operands[1]);
4587   if (operands[2] == 0 || operands[3] == 0)
4588     FAIL;
4589   "
4592 (define_insn "*arm_movsf_soft_insn"
4593   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4594         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4595   "TARGET_ARM
4596    && !TARGET_CIRRUS
4597    && TARGET_SOFT_FLOAT
4598    && (GET_CODE (operands[0]) != MEM
4599        || register_operand (operands[1], SFmode))"
4600   "@
4601    mov%?\\t%0, %1
4602    ldr%?\\t%0, %1\\t%@ float
4603    str%?\\t%1, %0\\t%@ float"
4604   [(set_attr "length" "4,4,4")
4605    (set_attr "predicable" "yes")
4606    (set_attr "type" "*,load,store1")
4607    (set_attr "pool_range" "*,4096,*")
4608    (set_attr "neg_pool_range" "*,4084,*")]
4611 ;;; ??? This should have alternatives for constants.
4612 (define_insn "*thumb_movsf_insn"
4613   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4614         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4615   "TARGET_THUMB
4616    && (   register_operand (operands[0], SFmode) 
4617        || register_operand (operands[1], SFmode))"
4618   "@
4619    add\\t%0, %1, #0
4620    ldmia\\t%1, {%0}
4621    stmia\\t%0, {%1}
4622    ldr\\t%0, %1
4623    str\\t%1, %0
4624    mov\\t%0, %1
4625    mov\\t%0, %1"
4626   [(set_attr "length" "2")
4627    (set_attr "type" "*,load,store1,load,store1,*,*")
4628    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4631 (define_expand "movdf"
4632   [(set (match_operand:DF 0 "general_operand" "")
4633         (match_operand:DF 1 "general_operand" ""))]
4634   "TARGET_EITHER"
4635   "
4636   if (TARGET_ARM)
4637     {
4638       if (GET_CODE (operands[0]) == MEM)
4639         operands[1] = force_reg (DFmode, operands[1]);
4640     }
4641   else /* TARGET_THUMB */
4642     {
4643       if (!no_new_pseudos)
4644         {
4645           if (GET_CODE (operands[0]) != REG)
4646             operands[1] = force_reg (DFmode, operands[1]);
4647         }
4648     }
4649   "
4652 ;; Reloading a df mode value stored in integer regs to memory can require a
4653 ;; scratch reg.
4654 (define_expand "reload_outdf"
4655   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4656    (match_operand:DF 1 "s_register_operand" "r")
4657    (match_operand:SI 2 "s_register_operand" "=&r")]
4658   "TARGET_ARM"
4659   "
4660   {
4661     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4663     if (code == REG)
4664       operands[2] = XEXP (operands[0], 0);
4665     else if (code == POST_INC || code == PRE_DEC)
4666       {
4667         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4668         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4669         emit_insn (gen_movdi (operands[0], operands[1]));
4670         DONE;
4671       }
4672     else if (code == PRE_INC)
4673       {
4674         rtx reg = XEXP (XEXP (operands[0], 0), 0);
4676         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4677         operands[2] = reg;
4678       }
4679     else if (code == POST_DEC)
4680       operands[2] = XEXP (XEXP (operands[0], 0), 0);
4681     else
4682       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4683                              XEXP (XEXP (operands[0], 0), 1)));
4685     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4686                             operands[1]));
4688     if (code == POST_DEC)
4689       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4691     DONE;
4692   }"
4695 (define_insn "*movdf_soft_insn"
4696   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4697         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4698   "TARGET_ARM && TARGET_SOFT_FLOAT
4699    && !TARGET_CIRRUS
4700   "
4701   "* return output_move_double (operands);"
4702   [(set_attr "length" "8,8,8")
4703    (set_attr "type" "*,load,store2")
4704    (set_attr "pool_range" "1020")
4705    (set_attr "neg_pool_range" "1008")]
4708 ;;; ??? This should have alternatives for constants.
4709 ;;; ??? This was originally identical to the movdi_insn pattern.
4710 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4711 ;;; thumb_reorg with a memory reference.
4712 (define_insn "*thumb_movdf_insn"
4713   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4714         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
4715   "TARGET_THUMB
4716    && (   register_operand (operands[0], DFmode)
4717        || register_operand (operands[1], DFmode))"
4718   "*
4719   switch (which_alternative)
4720     {
4721     default:
4722     case 0:
4723       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4724         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4725       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4726     case 1:
4727       return \"ldmia\\t%1, {%0, %H0}\";
4728     case 2:
4729       return \"stmia\\t%0, {%1, %H1}\";
4730     case 3:
4731       return thumb_load_double_from_address (operands);
4732     case 4:
4733       operands[2] = gen_rtx (MEM, SImode,
4734                              plus_constant (XEXP (operands[0], 0), 4));
4735       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4736       return \"\";
4737     case 5:
4738       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4739         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4740       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4741     }
4742   "
4743   [(set_attr "length" "4,2,2,6,4,4")
4744    (set_attr "type" "*,load,store2,load,store2,*")
4745    (set_attr "pool_range" "*,*,*,1020,*,*")]
4749 ;; load- and store-multiple insns
4750 ;; The arm can load/store any set of registers, provided that they are in
4751 ;; ascending order; but that is beyond GCC so stick with what it knows.
4753 (define_expand "load_multiple"
4754   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4755                           (match_operand:SI 1 "" ""))
4756                      (use (match_operand:SI 2 "" ""))])]
4757   "TARGET_ARM"
4758   "
4759   /* Support only fixed point registers.  */
4760   if (GET_CODE (operands[2]) != CONST_INT
4761       || INTVAL (operands[2]) > 14
4762       || INTVAL (operands[2]) < 2
4763       || GET_CODE (operands[1]) != MEM
4764       || GET_CODE (operands[0]) != REG
4765       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
4766       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4767     FAIL;
4769   operands[3]
4770     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
4771                              force_reg (SImode, XEXP (operands[1], 0)),
4772                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
4773                              MEM_IN_STRUCT_P(operands[1]),
4774                              MEM_SCALAR_P (operands[1]));
4775   "
4778 ;; Load multiple with write-back
4780 (define_insn "*ldmsi_postinc4"
4781   [(match_parallel 0 "load_multiple_operation"
4782     [(set (match_operand:SI 1 "s_register_operand" "=r")
4783           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4784                    (const_int 16)))
4785      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4786           (mem:SI (match_dup 2)))
4787      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4788           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4789      (set (match_operand:SI 5 "arm_hard_register_operand" "")
4790           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
4791      (set (match_operand:SI 6 "arm_hard_register_operand" "")
4792           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
4793   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4794   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
4795   [(set_attr "type" "load")
4796    (set_attr "predicable" "yes")]
4799 (define_insn "*ldmsi_postinc3"
4800   [(match_parallel 0 "load_multiple_operation"
4801     [(set (match_operand:SI 1 "s_register_operand" "=r")
4802           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4803                    (const_int 12)))
4804      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4805           (mem:SI (match_dup 2)))
4806      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4807           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4808      (set (match_operand:SI 5 "arm_hard_register_operand" "")
4809           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
4810   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4811   "ldm%?ia\\t%1!, {%3, %4, %5}"
4812   [(set_attr "type" "load")
4813    (set_attr "predicable" "yes")]
4816 (define_insn "*ldmsi_postinc2"
4817   [(match_parallel 0 "load_multiple_operation"
4818     [(set (match_operand:SI 1 "s_register_operand" "=r")
4819           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4820                    (const_int 8)))
4821      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4822           (mem:SI (match_dup 2)))
4823      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4824           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
4825   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4826   "ldm%?ia\\t%1!, {%3, %4}"
4827   [(set_attr "type" "load")
4828    (set_attr "predicable" "yes")]
4831 ;; Ordinary load multiple
4833 (define_insn "*ldmsi4"
4834   [(match_parallel 0 "load_multiple_operation"
4835     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4836           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4837      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4838           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4839      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4840           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4841      (set (match_operand:SI 5 "arm_hard_register_operand" "")
4842           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
4843   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4844   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
4845   [(set_attr "type" "load")
4846    (set_attr "predicable" "yes")]
4849 (define_insn "*ldmsi3"
4850   [(match_parallel 0 "load_multiple_operation"
4851     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4852           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4853      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4854           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4855      (set (match_operand:SI 4 "arm_hard_register_operand" "")
4856           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
4857   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4858   "ldm%?ia\\t%1, {%2, %3, %4}"
4859   [(set_attr "type" "load")
4860    (set_attr "predicable" "yes")]
4863 (define_insn "*ldmsi2"
4864   [(match_parallel 0 "load_multiple_operation"
4865     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4866           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4867      (set (match_operand:SI 3 "arm_hard_register_operand" "")
4868           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
4869   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4870   "ldm%?ia\\t%1, {%2, %3}"
4871   [(set_attr "type" "load")
4872    (set_attr "predicable" "yes")]
4875 (define_expand "store_multiple"
4876   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4877                           (match_operand:SI 1 "" ""))
4878                      (use (match_operand:SI 2 "" ""))])]
4879   "TARGET_ARM"
4880   "
4881   /* Support only fixed point registers */
4882   if (GET_CODE (operands[2]) != CONST_INT
4883       || INTVAL (operands[2]) > 14
4884       || INTVAL (operands[2]) < 2
4885       || GET_CODE (operands[1]) != REG
4886       || GET_CODE (operands[0]) != MEM
4887       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
4888       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4889     FAIL;
4891   operands[3]
4892     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
4893                               force_reg (SImode, XEXP (operands[0], 0)),
4894                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
4895                               MEM_IN_STRUCT_P(operands[0]), 
4896                               MEM_SCALAR_P (operands[0]));
4897   "
4900 ;; Store multiple with write-back
4902 (define_insn "*stmsi_postinc4"
4903   [(match_parallel 0 "store_multiple_operation"
4904     [(set (match_operand:SI 1 "s_register_operand" "=r")
4905           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4906                    (const_int 16)))
4907      (set (mem:SI (match_dup 2))
4908           (match_operand:SI 3 "arm_hard_register_operand" ""))
4909      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4910           (match_operand:SI 4 "arm_hard_register_operand" ""))
4911      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
4912           (match_operand:SI 5 "arm_hard_register_operand" ""))
4913      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
4914           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
4915   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4916   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
4917   [(set_attr "predicable" "yes")
4918    (set_attr "type" "store4")]
4921 (define_insn "*stmsi_postinc3"
4922   [(match_parallel 0 "store_multiple_operation"
4923     [(set (match_operand:SI 1 "s_register_operand" "=r")
4924           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4925                    (const_int 12)))
4926      (set (mem:SI (match_dup 2))
4927           (match_operand:SI 3 "arm_hard_register_operand" ""))
4928      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4929           (match_operand:SI 4 "arm_hard_register_operand" ""))
4930      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
4931           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
4932   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4933   "stm%?ia\\t%1!, {%3, %4, %5}"
4934   [(set_attr "predicable" "yes")
4935    (set_attr "type" "store3")]
4938 (define_insn "*stmsi_postinc2"
4939   [(match_parallel 0 "store_multiple_operation"
4940     [(set (match_operand:SI 1 "s_register_operand" "=r")
4941           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4942                    (const_int 8)))
4943      (set (mem:SI (match_dup 2))
4944           (match_operand:SI 3 "arm_hard_register_operand" ""))
4945      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4946           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
4947   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4948   "stm%?ia\\t%1!, {%3, %4}"
4949   [(set_attr "predicable" "yes")
4950    (set_attr "type" "store2")]
4953 ;; Ordinary store multiple
4955 (define_insn "*stmsi4"
4956   [(match_parallel 0 "store_multiple_operation"
4957     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4958           (match_operand:SI 2 "arm_hard_register_operand" ""))
4959      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4960           (match_operand:SI 3 "arm_hard_register_operand" ""))
4961      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
4962           (match_operand:SI 4 "arm_hard_register_operand" ""))
4963      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
4964           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
4965   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4966   "stm%?ia\\t%1, {%2, %3, %4, %5}"
4967   [(set_attr "predicable" "yes")
4968    (set_attr "type" "store4")]
4971 (define_insn "*stmsi3"
4972   [(match_parallel 0 "store_multiple_operation"
4973     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4974           (match_operand:SI 2 "arm_hard_register_operand" ""))
4975      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4976           (match_operand:SI 3 "arm_hard_register_operand" ""))
4977      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
4978           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
4979   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4980   "stm%?ia\\t%1, {%2, %3, %4}"
4981   [(set_attr "predicable" "yes")
4982    (set_attr "type" "store3")]
4985 (define_insn "*stmsi2"
4986   [(match_parallel 0 "store_multiple_operation"
4987     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4988           (match_operand:SI 2 "arm_hard_register_operand" ""))
4989      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4990           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
4991   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4992   "stm%?ia\\t%1, {%2, %3}"
4993   [(set_attr "predicable" "yes")
4994    (set_attr "type" "store2")]
4997 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
4998 ;; We could let this apply for blocks of less than this, but it clobbers so
4999 ;; many registers that there is then probably a better way.
5001 (define_expand "movstrqi"
5002   [(match_operand:BLK 0 "general_operand" "")
5003    (match_operand:BLK 1 "general_operand" "")
5004    (match_operand:SI 2 "const_int_operand" "")
5005    (match_operand:SI 3 "const_int_operand" "")]
5006   "TARGET_EITHER"
5007   "
5008   if (TARGET_ARM)
5009     {
5010       if (arm_gen_movstrqi (operands))
5011         DONE;
5012       FAIL;
5013     }
5014   else /* TARGET_THUMB */
5015     {
5016       if (   INTVAL (operands[3]) != 4
5017           || INTVAL (operands[2]) > 48)
5018         FAIL;
5020       thumb_expand_movstrqi (operands);
5021       DONE;
5022     }
5023   "
5026 ;; Thumb block-move insns
5028 (define_insn "movmem12b"
5029   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5030         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5031    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5032         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5033    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5034         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5035    (set (match_operand:SI 0 "register_operand" "=l")
5036         (plus:SI (match_dup 2) (const_int 12)))
5037    (set (match_operand:SI 1 "register_operand" "=l")
5038         (plus:SI (match_dup 3) (const_int 12)))
5039    (clobber (match_scratch:SI 4 "=&l"))
5040    (clobber (match_scratch:SI 5 "=&l"))
5041    (clobber (match_scratch:SI 6 "=&l"))]
5042   "TARGET_THUMB"
5043   "* return thumb_output_move_mem_multiple (3, operands);"
5044   [(set_attr "length" "4")
5045    ; This isn't entirely accurate...  It loads as well, but in terms of
5046    ; scheduling the following insn it is better to consider it as a store
5047    (set_attr "type" "store3")]
5050 (define_insn "movmem8b"
5051   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5052         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5053    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5054         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5055    (set (match_operand:SI 0 "register_operand" "=l")
5056         (plus:SI (match_dup 2) (const_int 8)))
5057    (set (match_operand:SI 1 "register_operand" "=l")
5058         (plus:SI (match_dup 3) (const_int 8)))
5059    (clobber (match_scratch:SI 4 "=&l"))
5060    (clobber (match_scratch:SI 5 "=&l"))]
5061   "TARGET_THUMB"
5062   "* return thumb_output_move_mem_multiple (2, operands);"
5063   [(set_attr "length" "4")
5064    ; This isn't entirely accurate...  It loads as well, but in terms of
5065    ; scheduling the following insn it is better to consider it as a store
5066    (set_attr "type" "store2")]
5071 ;; Compare & branch insns
5072 ;; The range calcualations are based as follows:
5073 ;; For forward branches, the address calculation returns the address of
5074 ;; the next instruction.  This is 2 beyond the branch instruction.
5075 ;; For backward branches, the address calculation returns the address of
5076 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5077 ;; instruction for the shortest sequence, and 4 before the branch instruction
5078 ;; if we have to jump around an unconditional branch.
5079 ;; To the basic branch range the PC offset must be added (this is +4).
5080 ;; So for forward branches we have 
5081 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5082 ;; And for backward branches we have 
5083 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5085 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5086 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5088 (define_insn "cbranchsi4"
5089   [(set (pc)
5090         (if_then_else
5091             (match_operator                    0 "arm_comparison_operator"
5092                             [(match_operand:SI 1 "register_operand"   "l,r")
5093                              (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5094             (label_ref       (match_operand    3 "" ""))
5095             (pc)))]
5096   "TARGET_THUMB"
5097   "*
5098   output_asm_insn (\"cmp\\t%1, %2\", operands);
5099   switch (get_attr_length (insn))
5100     {
5101     case 4:  return \"b%d0\\t%l3\";
5102     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5103     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5104     }
5105   "
5106   [(set (attr "far_jump")
5107         (if_then_else
5108             (eq_attr "length" "8")
5109             (const_string "yes")
5110             (const_string "no")))
5111    (set (attr "length") 
5112         (if_then_else
5113             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5114                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5115             (const_int 4)
5116             (if_then_else
5117                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5118                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5119                 (const_int 6)
5120                 (const_int 8))))]
5123 (define_insn "*negated_cbranchsi4"
5124   [(set (pc)
5125         (if_then_else
5126          (match_operator             0 "arm_comparison_operator"
5127           [(match_operand:SI         1 "register_operand"  "l")
5128            (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5129          (label_ref (match_operand   3 "" ""))
5130          (pc)))]
5131   "TARGET_THUMB"
5132   "*
5133   output_asm_insn (\"cmn\\t%1, %2\", operands);
5134   switch (get_attr_length (insn))
5135     {
5136     case 4:  return \"b%d0\\t%l3\";
5137     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5138     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5139     }
5140   "
5141   [(set (attr "far_jump")
5142         (if_then_else
5143             (eq_attr "length" "8")
5144             (const_string "yes")
5145             (const_string "no")))
5146    (set (attr "length") 
5147         (if_then_else
5148             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5149                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5150             (const_int 4)
5151             (if_then_else
5152                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5153                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5154                 (const_int 6)
5155                 (const_int 8))))]
5159 ;; Comparison and test insns
5161 (define_expand "cmpsi"
5162   [(match_operand:SI 0 "s_register_operand" "")
5163    (match_operand:SI 1 "arm_add_operand" "")]
5164   "TARGET_ARM"
5165   "{
5166     arm_compare_op0 = operands[0];
5167     arm_compare_op1 = operands[1];
5168     DONE;
5169   }"
5172 (define_expand "cmpsf"
5173   [(match_operand:SF 0 "s_register_operand" "")
5174    (match_operand:SF 1 "fpa_rhs_operand" "")]
5175   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5176   "
5177   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5178     operands[1] = force_reg (SFmode, operands[1]);
5180   arm_compare_op0 = operands[0];
5181   arm_compare_op1 = operands[1];
5182   DONE;
5183   "
5186 (define_expand "cmpdf"
5187   [(match_operand:DF 0 "s_register_operand" "")
5188    (match_operand:DF 1 "fpa_rhs_operand" "")]
5189   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5190   "
5191   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5192     operands[1] = force_reg (DFmode, operands[1]);
5194   arm_compare_op0 = operands[0];
5195   arm_compare_op1 = operands[1];
5196   DONE;
5197   "
5200 (define_insn "*arm_cmpsi_insn"
5201   [(set (reg:CC CC_REGNUM)
5202         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5203                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5204   "TARGET_ARM"
5205   "@
5206    cmp%?\\t%0, %1
5207    cmn%?\\t%0, #%n1"
5208   [(set_attr "conds" "set")]
5211 (define_insn "*cmpsi_shiftsi"
5212   [(set (reg:CC CC_REGNUM)
5213         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
5214                     (match_operator:SI  3 "shift_operator"
5215                      [(match_operand:SI 1 "s_register_operand" "r")
5216                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5217   "TARGET_ARM"
5218   "cmp%?\\t%0, %1%S3"
5219   [(set_attr "conds" "set")
5220    (set_attr "shift" "1")
5221    ]
5224 (define_insn "*cmpsi_shiftsi_swp"
5225   [(set (reg:CC_SWP CC_REGNUM)
5226         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5227                          [(match_operand:SI 1 "s_register_operand" "r")
5228                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
5229                         (match_operand:SI 0 "s_register_operand" "r")))]
5230   "TARGET_ARM"
5231   "cmp%?\\t%0, %1%S3"
5232   [(set_attr "conds" "set")
5233    (set_attr "shift" "1")
5234    ]
5237 (define_insn "*cmpsi_neg_shiftsi"
5238   [(set (reg:CC CC_REGNUM)
5239         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5240                     (neg:SI (match_operator:SI 3 "shift_operator"
5241                              [(match_operand:SI 1 "s_register_operand" "r")
5242                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5243   "TARGET_ARM"
5244   "cmn%?\\t%0, %1%S3"
5245   [(set_attr "conds" "set")
5246    (set_attr "shift" "1")
5247    ]
5250 ;; Cirrus SF compare instruction
5251 (define_insn "*cirrus_cmpsf"
5252   [(set (reg:CCFP CC_REGNUM)
5253         (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5254                       (match_operand:SF 1 "cirrus_fp_register" "v")))]
5255   "TARGET_ARM && TARGET_CIRRUS"
5256   "cfcmps%?\\tr15, %V0, %V1"
5257   [(set_attr "type"   "mav_farith")
5258    (set_attr "cirrus" "compare")]
5261 ;; Cirrus DF compare instruction
5262 (define_insn "*cirrus_cmpdf"
5263   [(set (reg:CCFP CC_REGNUM)
5264         (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5265                       (match_operand:DF 1 "cirrus_fp_register" "v")))]
5266   "TARGET_ARM && TARGET_CIRRUS"
5267   "cfcmpd%?\\tr15, %V0, %V1"
5268   [(set_attr "type"   "mav_farith")
5269    (set_attr "cirrus" "compare")]
5272 ;; Cirrus DI compare instruction
5273 (define_expand "cmpdi"
5274   [(match_operand:DI 0 "cirrus_fp_register" "")
5275    (match_operand:DI 1 "cirrus_fp_register" "")]
5276   "TARGET_ARM && TARGET_CIRRUS"
5277   "{
5278      arm_compare_op0 = operands[0];
5279      arm_compare_op1 = operands[1];
5280      DONE;
5281    }")
5283 (define_insn "*cirrus_cmpdi"
5284   [(set (reg:CC CC_REGNUM)
5285         (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5286                     (match_operand:DI 1 "cirrus_fp_register" "v")))]
5287   "TARGET_ARM && TARGET_CIRRUS"
5288   "cfcmp64%?\\tr15, %V0, %V1"
5289   [(set_attr "type"   "mav_farith")
5290    (set_attr "cirrus" "compare")]
5293 ; This insn allows redundant compares to be removed by cse, nothing should
5294 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5295 ; is deleted later on. The match_dup will match the mode here, so that
5296 ; mode changes of the condition codes aren't lost by this even though we don't
5297 ; specify what they are.
5299 (define_insn "*deleted_compare"
5300   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5301   "TARGET_ARM"
5302   "\\t%@ deleted compare"
5303   [(set_attr "conds" "set")
5304    (set_attr "length" "0")]
5308 ;; Conditional branch insns
5310 (define_expand "beq"
5311   [(set (pc)
5312         (if_then_else (eq (match_dup 1) (const_int 0))
5313                       (label_ref (match_operand 0 "" ""))
5314                       (pc)))]
5315   "TARGET_ARM"
5316   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5319 (define_expand "bne"
5320   [(set (pc)
5321         (if_then_else (ne (match_dup 1) (const_int 0))
5322                       (label_ref (match_operand 0 "" ""))
5323                       (pc)))]
5324   "TARGET_ARM"
5325   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5328 (define_expand "bgt"
5329   [(set (pc)
5330         (if_then_else (gt (match_dup 1) (const_int 0))
5331                       (label_ref (match_operand 0 "" ""))
5332                       (pc)))]
5333   "TARGET_ARM"
5334   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5337 (define_expand "ble"
5338   [(set (pc)
5339         (if_then_else (le (match_dup 1) (const_int 0))
5340                       (label_ref (match_operand 0 "" ""))
5341                       (pc)))]
5342   "TARGET_ARM"
5343   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5346 (define_expand "bge"
5347   [(set (pc)
5348         (if_then_else (ge (match_dup 1) (const_int 0))
5349                       (label_ref (match_operand 0 "" ""))
5350                       (pc)))]
5351   "TARGET_ARM"
5352   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5355 (define_expand "blt"
5356   [(set (pc)
5357         (if_then_else (lt (match_dup 1) (const_int 0))
5358                       (label_ref (match_operand 0 "" ""))
5359                       (pc)))]
5360   "TARGET_ARM"
5361   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5364 (define_expand "bgtu"
5365   [(set (pc)
5366         (if_then_else (gtu (match_dup 1) (const_int 0))
5367                       (label_ref (match_operand 0 "" ""))
5368                       (pc)))]
5369   "TARGET_ARM"
5370   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5373 (define_expand "bleu"
5374   [(set (pc)
5375         (if_then_else (leu (match_dup 1) (const_int 0))
5376                       (label_ref (match_operand 0 "" ""))
5377                       (pc)))]
5378   "TARGET_ARM"
5379   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5382 (define_expand "bgeu"
5383   [(set (pc)
5384         (if_then_else (geu (match_dup 1) (const_int 0))
5385                       (label_ref (match_operand 0 "" ""))
5386                       (pc)))]
5387   "TARGET_ARM"
5388   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5391 (define_expand "bltu"
5392   [(set (pc)
5393         (if_then_else (ltu (match_dup 1) (const_int 0))
5394                       (label_ref (match_operand 0 "" ""))
5395                       (pc)))]
5396   "TARGET_ARM"
5397   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5400 (define_expand "bunordered"
5401   [(set (pc)
5402         (if_then_else (unordered (match_dup 1) (const_int 0))
5403                       (label_ref (match_operand 0 "" ""))
5404                       (pc)))]
5405   "TARGET_ARM && TARGET_HARD_FLOAT"
5406   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5407                                       arm_compare_op1);"
5410 (define_expand "bordered"
5411   [(set (pc)
5412         (if_then_else (ordered (match_dup 1) (const_int 0))
5413                       (label_ref (match_operand 0 "" ""))
5414                       (pc)))]
5415   "TARGET_ARM && TARGET_HARD_FLOAT"
5416   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5417                                       arm_compare_op1);"
5420 (define_expand "bungt"
5421   [(set (pc)
5422         (if_then_else (ungt (match_dup 1) (const_int 0))
5423                       (label_ref (match_operand 0 "" ""))
5424                       (pc)))]
5425   "TARGET_ARM && TARGET_HARD_FLOAT"
5426   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5429 (define_expand "bunlt"
5430   [(set (pc)
5431         (if_then_else (unlt (match_dup 1) (const_int 0))
5432                       (label_ref (match_operand 0 "" ""))
5433                       (pc)))]
5434   "TARGET_ARM && TARGET_HARD_FLOAT"
5435   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5438 (define_expand "bunge"
5439   [(set (pc)
5440         (if_then_else (unge (match_dup 1) (const_int 0))
5441                       (label_ref (match_operand 0 "" ""))
5442                       (pc)))]
5443   "TARGET_ARM && TARGET_HARD_FLOAT"
5444   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5447 (define_expand "bunle"
5448   [(set (pc)
5449         (if_then_else (unle (match_dup 1) (const_int 0))
5450                       (label_ref (match_operand 0 "" ""))
5451                       (pc)))]
5452   "TARGET_ARM && TARGET_HARD_FLOAT"
5453   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5456 ;; The following two patterns need two branch instructions, since there is
5457 ;; no single instruction that will handle all cases.
5458 (define_expand "buneq"
5459   [(set (pc)
5460         (if_then_else (uneq (match_dup 1) (const_int 0))
5461                       (label_ref (match_operand 0 "" ""))
5462                       (pc)))]
5463   "TARGET_ARM && TARGET_HARD_FLOAT"
5464   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5467 (define_expand "bltgt"
5468   [(set (pc)
5469         (if_then_else (ltgt (match_dup 1) (const_int 0))
5470                       (label_ref (match_operand 0 "" ""))
5471                       (pc)))]
5472   "TARGET_ARM && TARGET_HARD_FLOAT"
5473   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5477 ;; Patterns to match conditional branch insns.
5480 ; Special pattern to match UNEQ.
5481 (define_insn "*arm_buneq"
5482   [(set (pc)
5483         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5484                       (label_ref (match_operand 0 "" ""))
5485                       (pc)))]
5486   "TARGET_ARM && TARGET_HARD_FLOAT"
5487   "*
5488   if (arm_ccfsm_state != 0)
5489     abort ();
5491   return \"bvs\\t%l0\;beq\\t%l0\";
5492   "
5493   [(set_attr "conds" "jump_clob")
5494    (set_attr "length" "8")]
5497 ; Special pattern to match LTGT.
5498 (define_insn "*arm_bltgt"
5499   [(set (pc)
5500         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5501                       (label_ref (match_operand 0 "" ""))
5502                       (pc)))]
5503   "TARGET_ARM && TARGET_HARD_FLOAT"
5504   "*
5505   if (arm_ccfsm_state != 0)
5506     abort ();
5508   return \"bmi\\t%l0\;bgt\\t%l0\";
5509   "
5510   [(set_attr "conds" "jump_clob")
5511    (set_attr "length" "8")]
5514 (define_insn "*arm_cond_branch"
5515   [(set (pc)
5516         (if_then_else (match_operator 1 "arm_comparison_operator"
5517                        [(match_operand 2 "cc_register" "") (const_int 0)])
5518                       (label_ref (match_operand 0 "" ""))
5519                       (pc)))]
5520   "TARGET_ARM"
5521   "*
5522   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5523     {
5524       arm_ccfsm_state += 2;
5525       return \"\";
5526     }
5527   return \"b%d1\\t%l0\";
5528   "
5529   [(set_attr "conds" "use")]
5532 ; Special pattern to match reversed UNEQ.
5533 (define_insn "*arm_buneq_reversed"
5534   [(set (pc)
5535         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5536                       (pc)
5537                       (label_ref (match_operand 0 "" ""))))]
5538   "TARGET_ARM && TARGET_HARD_FLOAT"
5539   "*
5540   if (arm_ccfsm_state != 0)
5541     abort ();
5543   return \"bmi\\t%l0\;bgt\\t%l0\";
5544   "
5545   [(set_attr "conds" "jump_clob")
5546    (set_attr "length" "8")]
5549 ; Special pattern to match reversed LTGT.
5550 (define_insn "*arm_bltgt_reversed"
5551   [(set (pc)
5552         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5553                       (pc)
5554                       (label_ref (match_operand 0 "" ""))))]
5555   "TARGET_ARM && TARGET_HARD_FLOAT"
5556   "*
5557   if (arm_ccfsm_state != 0)
5558     abort ();
5560   return \"bvs\\t%l0\;beq\\t%l0\";
5561   "
5562   [(set_attr "conds" "jump_clob")
5563    (set_attr "length" "8")]
5566 (define_insn "*arm_cond_branch_reversed"
5567   [(set (pc)
5568         (if_then_else (match_operator 1 "arm_comparison_operator"
5569                        [(match_operand 2 "cc_register" "") (const_int 0)])
5570                       (pc)
5571                       (label_ref (match_operand 0 "" ""))))]
5572   "TARGET_ARM"
5573   "*
5574   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5575     {
5576       arm_ccfsm_state += 2;
5577       return \"\";
5578     }
5579   return \"b%D1\\t%l0\";
5580   "
5581   [(set_attr "conds" "use")]
5586 ; scc insns
5588 (define_expand "seq"
5589   [(set (match_operand:SI 0 "s_register_operand" "")
5590         (eq:SI (match_dup 1) (const_int 0)))]
5591   "TARGET_ARM"
5592   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5595 (define_expand "sne"
5596   [(set (match_operand:SI 0 "s_register_operand" "")
5597         (ne:SI (match_dup 1) (const_int 0)))]
5598   "TARGET_ARM"
5599   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5602 (define_expand "sgt"
5603   [(set (match_operand:SI 0 "s_register_operand" "")
5604         (gt:SI (match_dup 1) (const_int 0)))]
5605   "TARGET_ARM"
5606   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5609 (define_expand "sle"
5610   [(set (match_operand:SI 0 "s_register_operand" "")
5611         (le:SI (match_dup 1) (const_int 0)))]
5612   "TARGET_ARM"
5613   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5616 (define_expand "sge"
5617   [(set (match_operand:SI 0 "s_register_operand" "")
5618         (ge:SI (match_dup 1) (const_int 0)))]
5619   "TARGET_ARM"
5620   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5623 (define_expand "slt"
5624   [(set (match_operand:SI 0 "s_register_operand" "")
5625         (lt:SI (match_dup 1) (const_int 0)))]
5626   "TARGET_ARM"
5627   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5630 (define_expand "sgtu"
5631   [(set (match_operand:SI 0 "s_register_operand" "")
5632         (gtu:SI (match_dup 1) (const_int 0)))]
5633   "TARGET_ARM"
5634   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5637 (define_expand "sleu"
5638   [(set (match_operand:SI 0 "s_register_operand" "")
5639         (leu:SI (match_dup 1) (const_int 0)))]
5640   "TARGET_ARM"
5641   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5644 (define_expand "sgeu"
5645   [(set (match_operand:SI 0 "s_register_operand" "")
5646         (geu:SI (match_dup 1) (const_int 0)))]
5647   "TARGET_ARM"
5648   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5651 (define_expand "sltu"
5652   [(set (match_operand:SI 0 "s_register_operand" "")
5653         (ltu:SI (match_dup 1) (const_int 0)))]
5654   "TARGET_ARM"
5655   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5658 (define_expand "sunordered"
5659   [(set (match_operand:SI 0 "s_register_operand" "")
5660         (unordered:SI (match_dup 1) (const_int 0)))]
5661   "TARGET_ARM && TARGET_HARD_FLOAT"
5662   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5663                                       arm_compare_op1);"
5666 (define_expand "sordered"
5667   [(set (match_operand:SI 0 "s_register_operand" "")
5668         (ordered:SI (match_dup 1) (const_int 0)))]
5669   "TARGET_ARM && TARGET_HARD_FLOAT"
5670   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5671                                       arm_compare_op1);"
5674 (define_expand "sungt"
5675   [(set (match_operand:SI 0 "s_register_operand" "")
5676         (ungt:SI (match_dup 1) (const_int 0)))]
5677   "TARGET_ARM && TARGET_HARD_FLOAT"
5678   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
5679                                       arm_compare_op1);"
5682 (define_expand "sunge"
5683   [(set (match_operand:SI 0 "s_register_operand" "")
5684         (unge:SI (match_dup 1) (const_int 0)))]
5685   "TARGET_ARM && TARGET_HARD_FLOAT"
5686   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
5687                                       arm_compare_op1);"
5690 (define_expand "sunlt"
5691   [(set (match_operand:SI 0 "s_register_operand" "")
5692         (unlt:SI (match_dup 1) (const_int 0)))]
5693   "TARGET_ARM && TARGET_HARD_FLOAT"
5694   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
5695                                       arm_compare_op1);"
5698 (define_expand "sunle"
5699   [(set (match_operand:SI 0 "s_register_operand" "")
5700         (unle:SI (match_dup 1) (const_int 0)))]
5701   "TARGET_ARM && TARGET_HARD_FLOAT"
5702   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
5703                                       arm_compare_op1);"
5706 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
5707 ;;; simple ARM instructions. 
5709 ; (define_expand "suneq"
5710 ;   [(set (match_operand:SI 0 "s_register_operand" "")
5711 ;       (uneq:SI (match_dup 1) (const_int 0)))]
5712 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
5713 ;   "abort ();"
5714 ; )
5716 ; (define_expand "sltgt"
5717 ;   [(set (match_operand:SI 0 "s_register_operand" "")
5718 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
5719 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
5720 ;   "abort ();"
5721 ; )
5723 (define_insn "*mov_scc"
5724   [(set (match_operand:SI 0 "s_register_operand" "=r")
5725         (match_operator:SI 1 "arm_comparison_operator"
5726          [(match_operand 2 "cc_register" "") (const_int 0)]))]
5727   "TARGET_ARM"
5728   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
5729   [(set_attr "conds" "use")
5730    (set_attr "length" "8")]
5733 (define_insn "*mov_negscc"
5734   [(set (match_operand:SI 0 "s_register_operand" "=r")
5735         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
5736                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
5737   "TARGET_ARM"
5738   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
5739   [(set_attr "conds" "use")
5740    (set_attr "length" "8")]
5743 (define_insn "*mov_notscc"
5744   [(set (match_operand:SI 0 "s_register_operand" "=r")
5745         (not:SI (match_operator:SI 1 "arm_comparison_operator"
5746                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
5747   "TARGET_ARM"
5748   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
5749   [(set_attr "conds" "use")
5750    (set_attr "length" "8")]
5754 ;; Conditional move insns
5756 (define_expand "movsicc"
5757   [(set (match_operand:SI 0 "s_register_operand" "")
5758         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
5759                          (match_operand:SI 2 "arm_not_operand" "")
5760                          (match_operand:SI 3 "arm_not_operand" "")))]
5761   "TARGET_ARM"
5762   "
5763   {
5764     enum rtx_code code = GET_CODE (operands[1]);
5765     rtx ccreg;
5767     if (code == UNEQ || code == LTGT)
5768       FAIL;
5770     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5771     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5772   }"
5775 (define_expand "movsfcc"
5776   [(set (match_operand:SF 0 "s_register_operand" "")
5777         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
5778                          (match_operand:SF 2 "s_register_operand" "")
5779                          (match_operand:SF 3 "nonmemory_operand" "")))]
5780   "TARGET_ARM"
5781   "
5782   {
5783     enum rtx_code code = GET_CODE (operands[1]);
5784     rtx ccreg;
5786     if (code == UNEQ || code == LTGT)
5787       FAIL;
5789     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
5790        Otherwise, ensure it is a valid FP add operand */
5791     if ((!TARGET_HARD_FLOAT)
5792         || (!fpa_add_operand (operands[3], SFmode)))
5793       operands[3] = force_reg (SFmode, operands[3]);
5795     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5796     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5797   }"
5800 (define_expand "movdfcc"
5801   [(set (match_operand:DF 0 "s_register_operand" "")
5802         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
5803                          (match_operand:DF 2 "s_register_operand" "")
5804                          (match_operand:DF 3 "fpa_add_operand" "")))]
5805   "TARGET_ARM && TARGET_HARD_FLOAT"
5806   "
5807   {
5808     enum rtx_code code = GET_CODE (operands[1]);
5809     rtx ccreg;
5811     if (code == UNEQ || code == LTGT)
5812       FAIL;
5814     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5815     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5816   }"
5819 (define_insn "*movsicc_insn"
5820   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
5821         (if_then_else:SI
5822          (match_operator 3 "arm_comparison_operator"
5823           [(match_operand 4 "cc_register" "") (const_int 0)])
5824          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
5825          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
5826   "TARGET_ARM"
5827   "@
5828    mov%D3\\t%0, %2
5829    mvn%D3\\t%0, #%B2
5830    mov%d3\\t%0, %1
5831    mvn%d3\\t%0, #%B1
5832    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
5833    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
5834    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
5835    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
5836   [(set_attr "length" "4,4,4,4,8,8,8,8")
5837    (set_attr "conds" "use")]
5840 (define_insn "*movsfcc_soft_insn"
5841   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
5842         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
5843                           [(match_operand 4 "cc_register" "") (const_int 0)])
5844                          (match_operand:SF 1 "s_register_operand" "0,r")
5845                          (match_operand:SF 2 "s_register_operand" "r,0")))]
5846   "TARGET_ARM && TARGET_SOFT_FLOAT"
5847   "@
5848    mov%D3\\t%0, %2
5849    mov%d3\\t%0, %1"
5850   [(set_attr "conds" "use")]
5854 ;; Jump and linkage insns
5856 (define_expand "jump"
5857   [(set (pc)
5858         (label_ref (match_operand 0 "" "")))]
5859   "TARGET_EITHER"
5860   ""
5863 (define_insn "*arm_jump"
5864   [(set (pc)
5865         (label_ref (match_operand 0 "" "")))]
5866   "TARGET_ARM"
5867   "*
5868   {
5869     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5870       {
5871         arm_ccfsm_state += 2;
5872         return \"\";
5873       }
5874     return \"b%?\\t%l0\";
5875   }
5876   "
5877   [(set_attr "predicable" "yes")]
5880 (define_insn "*thumb_jump"
5881   [(set (pc)
5882         (label_ref (match_operand 0 "" "")))]
5883   "TARGET_THUMB"
5884   "*
5885   if (get_attr_length (insn) == 2)
5886     return \"b\\t%l0\";
5887   return \"bl\\t%l0\\t%@ far jump\";
5888   "
5889   [(set (attr "far_jump")
5890         (if_then_else
5891             (eq_attr "length" "4")
5892             (const_string "yes")
5893             (const_string "no")))
5894    (set (attr "length") 
5895         (if_then_else
5896             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
5897                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
5898             (const_int 2)
5899             (const_int 4)))]
5902 (define_expand "call"
5903   [(parallel [(call (match_operand 0 "memory_operand" "")
5904                     (match_operand 1 "general_operand" ""))
5905               (use (match_operand 2 "" ""))
5906               (clobber (reg:SI LR_REGNUM))])]
5907   "TARGET_EITHER"
5908   "
5909   {
5910     rtx callee;
5911     
5912     /* In an untyped call, we can get NULL for operand 2.  */
5913     if (operands[2] == NULL_RTX)
5914       operands[2] = const0_rtx;
5915       
5916     /* This is to decide if we should generate indirect calls by loading the
5917        32 bit address of the callee into a register before performing the
5918        branch and link.  operand[2] encodes the long_call/short_call
5919        attribute of the function being called.  This attribute is set whenever
5920        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
5921        is used, and the short_call attribute can also be set if function is
5922        declared as static or if it has already been defined in the current
5923        compilation unit.  See arm.c and arm.h for info about this.  The third
5924        parameter to arm_is_longcall_p is used to tell it which pattern
5925        invoked it.  */
5926     callee  = XEXP (operands[0], 0);
5927     
5928     if (GET_CODE (callee) != REG
5929        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
5930       XEXP (operands[0], 0) = force_reg (Pmode, callee);
5931   }"
5934 (define_insn "*call_reg"
5935   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
5936          (match_operand 1 "" ""))
5937    (use (match_operand 2 "" ""))
5938    (clobber (reg:SI LR_REGNUM))]
5939   "TARGET_ARM"
5940   "*
5941   return output_call (operands);
5942   "
5943   ;; length is worst case, normally it is only two
5944   [(set_attr "length" "12")
5945    (set_attr "type" "call")]
5948 (define_insn "*call_mem"
5949   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
5950          (match_operand 1 "" ""))
5951    (use (match_operand 2 "" ""))
5952    (clobber (reg:SI LR_REGNUM))]
5953   "TARGET_ARM"
5954   "*
5955   return output_call_mem (operands);
5956   "
5957   [(set_attr "length" "12")
5958    (set_attr "type" "call")]
5961 (define_insn "*call_indirect"
5962   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
5963          (match_operand 1 "" ""))
5964    (use (match_operand 2 "" ""))
5965    (clobber (reg:SI LR_REGNUM))]
5966   "TARGET_THUMB"
5967   "*
5968   {
5969     if (TARGET_CALLER_INTERWORKING)
5970       return \"bl\\t%__interwork_call_via_%0\";
5971     else
5972       return \"bl\\t%__call_via_%0\";
5973   }"
5974   [(set_attr "type" "call")]
5977 (define_insn "*call_value_indirect"
5978   [(set (match_operand 0 "" "=l")
5979         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
5980               (match_operand 2 "" "")))
5981    (use (match_operand 3 "" ""))
5982    (clobber (reg:SI LR_REGNUM))]
5983   "TARGET_THUMB"
5984   "*
5985   {
5986     if (TARGET_CALLER_INTERWORKING)
5987       return \"bl\\t%__interwork_call_via_%1\";
5988     else
5989       return \"bl\\t%__call_via_%1\";
5990   }"
5991   [(set_attr "type" "call")]
5994 (define_expand "call_value"
5995   [(parallel [(set (match_operand       0 "" "")
5996                    (call (match_operand 1 "memory_operand" "")
5997                          (match_operand 2 "general_operand" "")))
5998               (use (match_operand 3 "" ""))
5999               (clobber (reg:SI LR_REGNUM))])]
6000   "TARGET_EITHER"
6001   "
6002   {
6003     rtx callee = XEXP (operands[1], 0);
6004     
6005     /* In an untyped call, we can get NULL for operand 2.  */
6006     if (operands[3] == 0)
6007       operands[3] = const0_rtx;
6008       
6009     /* See the comment in define_expand \"call\".  */
6010     if (GET_CODE (callee) != REG
6011         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6012       XEXP (operands[1], 0) = force_reg (Pmode, callee);
6013   }"
6016 (define_insn "*call_value_reg"
6017   [(set (match_operand 0 "" "=r,f,v")
6018         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
6019               (match_operand 2 "" "")))
6020    (use (match_operand 3 "" ""))
6021    (clobber (reg:SI LR_REGNUM))]
6022   "TARGET_ARM"
6023   "*
6024   return output_call (&operands[1]);
6025   "
6026   [(set_attr "length" "12")
6027    (set_attr "type" "call")]
6030 (define_insn "*call_value_mem"
6031   [(set (match_operand 0 "" "=r,f,v")
6032         (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
6033               (match_operand 2 "" "")))
6034    (use (match_operand 3 "" ""))
6035    (clobber (reg:SI LR_REGNUM))]
6036   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6037   "*
6038   return output_call_mem (&operands[1]);
6039   "
6040   [(set_attr "length" "12")
6041    (set_attr "type" "call")]
6044 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6045 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6047 (define_insn "*call_symbol"
6048   [(call (mem:SI (match_operand:SI 0 "" "X"))
6049          (match_operand 1 "" ""))
6050    (use (match_operand 2 "" ""))
6051    (clobber (reg:SI LR_REGNUM))]
6052   "TARGET_ARM
6053    && (GET_CODE (operands[0]) == SYMBOL_REF)
6054    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6055   "*
6056   {
6057     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6058   }"
6059   [(set_attr "type" "call")]
6062 (define_insn "*call_value_symbol"
6063   [(set (match_operand 0 "s_register_operand" "=r,f,v")
6064         (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6065         (match_operand:SI 2 "" "")))
6066    (use (match_operand 3 "" ""))
6067    (clobber (reg:SI LR_REGNUM))]
6068   "TARGET_ARM
6069    && (GET_CODE (operands[1]) == SYMBOL_REF)
6070    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6071   "*
6072   {
6073     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6074   }"
6075   [(set_attr "type" "call")]
6078 (define_insn "*call_insn"
6079   [(call (mem:SI (match_operand:SI 0 "" "X"))
6080          (match_operand:SI 1 "" ""))
6081    (use (match_operand 2 "" ""))
6082    (clobber (reg:SI LR_REGNUM))]
6083   "TARGET_THUMB
6084    && GET_CODE (operands[0]) == SYMBOL_REF
6085    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6086   "bl\\t%a0"
6087   [(set_attr "length" "4")
6088    (set_attr "type" "call")]
6091 (define_insn "*call_value_insn"
6092   [(set (match_operand 0 "register_operand" "=l")
6093         (call (mem:SI (match_operand 1 "" "X"))
6094               (match_operand 2 "" "")))
6095    (use (match_operand 3 "" ""))
6096    (clobber (reg:SI LR_REGNUM))]
6097   "TARGET_THUMB
6098    && GET_CODE (operands[1]) == SYMBOL_REF
6099    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6100   "bl\\t%a1"
6101   [(set_attr "length" "4")
6102    (set_attr "type" "call")]
6105 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6106 (define_expand "sibcall"
6107   [(parallel [(call (match_operand 0 "memory_operand" "")
6108                     (match_operand 1 "general_operand" ""))
6109               (return)
6110               (use (match_operand 2 "" ""))])]
6111   "TARGET_ARM"
6112   "
6113   {
6114     if (operands[2] == NULL_RTX)
6115       operands[2] = const0_rtx;
6116   }"
6119 (define_expand "sibcall_value"
6120   [(parallel [(set (match_operand 0 "register_operand" "")
6121                    (call (match_operand 1 "memory_operand" "")
6122                          (match_operand 2 "general_operand" "")))
6123               (return)
6124               (use (match_operand 3 "" ""))])]
6125   "TARGET_ARM"
6126   "
6127   {
6128     if (operands[3] == NULL_RTX)
6129       operands[3] = const0_rtx;
6130   }"
6133 (define_insn "*sibcall_insn"
6134  [(call (mem:SI (match_operand:SI 0 "" "X"))
6135         (match_operand 1 "" ""))
6136   (return)
6137   (use (match_operand 2 "" ""))]
6138   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6139   "*
6140   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6141   "
6142   [(set_attr "type" "call")]
6145 (define_insn "*sibcall_value_insn"
6146  [(set (match_operand 0 "s_register_operand" "=r,f,v")
6147        (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
6148              (match_operand 2 "" "")))
6149   (return)
6150   (use (match_operand 3 "" ""))]
6151   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6152   "*
6153   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6154   "
6155   [(set_attr "type" "call")]
6158 ;; Often the return insn will be the same as loading from memory, so set attr
6159 (define_insn "return"
6160   [(return)]
6161   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6162   "*
6163   {
6164     if (arm_ccfsm_state == 2)
6165       {
6166         arm_ccfsm_state += 2;
6167         return \"\";
6168       }
6169     return output_return_instruction (const_true_rtx, TRUE, FALSE);
6170   }"
6171   [(set_attr "type" "load")
6172    (set_attr "predicable" "yes")]
6175 (define_insn "*cond_return"
6176   [(set (pc)
6177         (if_then_else (match_operator 0 "arm_comparison_operator"
6178                        [(match_operand 1 "cc_register" "") (const_int 0)])
6179                       (return)
6180                       (pc)))]
6181   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6182   "*
6183   {
6184     if (arm_ccfsm_state == 2)
6185       {
6186         arm_ccfsm_state += 2;
6187         return \"\";
6188       }
6189     return output_return_instruction (operands[0], TRUE, FALSE);
6190   }"
6191   [(set_attr "conds" "use")
6192    (set_attr "type" "load")]
6195 (define_insn "*cond_return_inverted"
6196   [(set (pc)
6197         (if_then_else (match_operator 0 "arm_comparison_operator"
6198                        [(match_operand 1 "cc_register" "") (const_int 0)])
6199                       (pc)
6200                       (return)))]
6201   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6202   "*
6203   {
6204     if (arm_ccfsm_state == 2)
6205       {
6206         arm_ccfsm_state += 2;
6207         return \"\";
6208       }
6209     return output_return_instruction (operands[0], TRUE, TRUE);
6210   }"
6211   [(set_attr "conds" "use")
6212    (set_attr "type" "load")]
6215 ;; Generate a sequence of instructions to determine if the processor is
6216 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6217 ;; mask.
6219 (define_expand "return_addr_mask"
6220   [(set (match_dup 1)
6221       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6222                        (const_int 0)))
6223    (set (match_operand:SI 0 "s_register_operand" "")
6224       (if_then_else:SI (eq (match_dup 1) (const_int 0))
6225                        (const_int -1)
6226                        (const_int 67108860)))] ; 0x03fffffc
6227   "TARGET_ARM"
6228   "
6229   operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6230   ")
6232 (define_insn "*check_arch2"
6233   [(set (match_operand:CC_NOOV 0 "cc_register" "")
6234       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6235                        (const_int 0)))]
6236   "TARGET_ARM"
6237   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6238   [(set_attr "length" "8")
6239    (set_attr "conds" "set")]
6242 ;; Call subroutine returning any type.
6244 (define_expand "untyped_call"
6245   [(parallel [(call (match_operand 0 "" "")
6246                     (const_int 0))
6247               (match_operand 1 "" "")
6248               (match_operand 2 "" "")])]
6249   "TARGET_ARM"
6250   "
6251   {
6252     int i;
6254     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6256     for (i = 0; i < XVECLEN (operands[2], 0); i++)
6257       {
6258         rtx set = XVECEXP (operands[2], 0, i);
6260         emit_move_insn (SET_DEST (set), SET_SRC (set));
6261       }
6263     /* The optimizer does not know that the call sets the function value
6264        registers we stored in the result block.  We avoid problems by
6265        claiming that all hard registers are used and clobbered at this
6266        point.  */
6267     emit_insn (gen_blockage ());
6269     DONE;
6270   }"
6273 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6274 ;; all of memory.  This blocks insns from being moved across this point.
6276 (define_insn "blockage"
6277   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6278   "TARGET_EITHER"
6279   ""
6280   [(set_attr "length" "0")
6281    (set_attr "type" "block")]
6284 (define_expand "casesi"
6285   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6286    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
6287    (match_operand:SI 2 "const_int_operand" "")  ; total range
6288    (match_operand:SI 3 "" "")                   ; table label
6289    (match_operand:SI 4 "" "")]                  ; Out of range label
6290   "TARGET_ARM"
6291   "
6292   {
6293     rtx reg;
6294     if (operands[1] != const0_rtx)
6295       {
6296         reg = gen_reg_rtx (SImode);
6298         emit_insn (gen_addsi3 (reg, operands[0],
6299                                GEN_INT (-INTVAL (operands[1]))));
6300         operands[0] = reg;
6301       }
6303     if (!const_ok_for_arm (INTVAL (operands[2])))
6304       operands[2] = force_reg (SImode, operands[2]);
6306     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6307                                          operands[4]));
6308     DONE;
6309   }"
6312 ;; The USE in this pattern is needed to tell flow analysis that this is
6313 ;; a CASESI insn.  It has no other purpose.
6314 (define_insn "casesi_internal"
6315   [(parallel [(set (pc)
6316                (if_then_else
6317                 (leu (match_operand:SI 0 "s_register_operand" "r")
6318                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
6319                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6320                                  (label_ref (match_operand 2 "" ""))))
6321                 (label_ref (match_operand 3 "" ""))))
6322               (clobber (reg:CC CC_REGNUM))
6323               (use (label_ref (match_dup 2)))])]
6324   "TARGET_ARM"
6325   "*
6326     if (flag_pic)
6327       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6328     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6329   "
6330   [(set_attr "conds" "clob")
6331    (set_attr "length" "12")]
6334 (define_expand "indirect_jump"
6335   [(set (pc)
6336         (match_operand:SI 0 "s_register_operand" ""))]
6337   "TARGET_EITHER"
6338   ""
6341 (define_insn "*arm_indirect_jump"
6342   [(set (pc)
6343         (match_operand:SI 0 "s_register_operand" "r"))]
6344   "TARGET_ARM"
6345   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6346   [(set_attr "predicable" "yes")]
6349 ;; Although not supported by the define_expand above,
6350 ;; cse/combine may generate this form.
6351 (define_insn "*load_indirect_jump"
6352   [(set (pc)
6353         (match_operand:SI 0 "memory_operand" "m"))]
6354   "TARGET_ARM"
6355   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6356   [(set_attr "type" "load")
6357    (set_attr "pool_range" "4096")
6358    (set_attr "neg_pool_range" "4084")
6359    (set_attr "predicable" "yes")]
6362 (define_insn "*thumb_indirect_jump"
6363   [(set (pc)
6364         (match_operand:SI 0 "register_operand" "l*r"))]
6365   "TARGET_THUMB"
6366   "mov\\tpc, %0"
6367   [(set_attr "conds" "clob")
6368    (set_attr "length" "2")]
6372 ;; Misc insns
6374 (define_insn "nop"
6375   [(const_int 0)]
6376   "TARGET_EITHER"
6377   "*
6378   if (TARGET_ARM)
6379     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6380   return  \"mov\\tr8, r8\";
6381   "
6382   [(set (attr "length")
6383         (if_then_else (eq_attr "is_thumb" "yes")
6384                       (const_int 2)
6385                       (const_int 4)))]
6389 ;; Patterns to allow combination of arithmetic, cond code and shifts
6391 (define_insn "*arith_shiftsi"
6392   [(set (match_operand:SI 0 "s_register_operand" "=r")
6393         (match_operator:SI 1 "shiftable_operator"
6394           [(match_operator:SI 3 "shift_operator"
6395              [(match_operand:SI 4 "s_register_operand" "r")
6396               (match_operand:SI 5 "reg_or_int_operand" "rI")])
6397            (match_operand:SI 2 "s_register_operand" "r")]))]
6398   "TARGET_ARM"
6399   "%i1%?\\t%0, %2, %4%S3"
6400   [(set_attr "predicable" "yes")
6401    (set_attr "shift" "4")
6402    ]
6405 (define_insn "*arith_shiftsi_compare0"
6406   [(set (reg:CC_NOOV CC_REGNUM)
6407         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6408                           [(match_operator:SI 3 "shift_operator"
6409                             [(match_operand:SI 4 "s_register_operand" "r")
6410                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6411                            (match_operand:SI 2 "s_register_operand" "r")])
6412                          (const_int 0)))
6413    (set (match_operand:SI 0 "s_register_operand" "=r")
6414         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6415                          (match_dup 2)]))]
6416   "TARGET_ARM"
6417   "%i1%?s\\t%0, %2, %4%S3"
6418   [(set_attr "conds" "set")
6419    (set_attr "shift" "4")
6420    ]
6423 (define_insn "*arith_shiftsi_compare0_scratch"
6424   [(set (reg:CC_NOOV CC_REGNUM)
6425         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6426                           [(match_operator:SI 3 "shift_operator"
6427                             [(match_operand:SI 4 "s_register_operand" "r")
6428                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6429                            (match_operand:SI 2 "s_register_operand" "r")])
6430                          (const_int 0)))
6431    (clobber (match_scratch:SI 0 "=r"))]
6432   "TARGET_ARM"
6433   "%i1%?s\\t%0, %2, %4%S3"
6434   [(set_attr "conds" "set")
6435    (set_attr "shift" "4")
6436    ]
6439 (define_insn "*sub_shiftsi"
6440   [(set (match_operand:SI 0 "s_register_operand" "=r")
6441         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6442                   (match_operator:SI 2 "shift_operator"
6443                    [(match_operand:SI 3 "s_register_operand" "r")
6444                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6445   "TARGET_ARM"
6446   "sub%?\\t%0, %1, %3%S2"
6447   [(set_attr "predicable" "yes")
6448    (set_attr "shift" "3")
6449    ]
6452 (define_insn "*sub_shiftsi_compare0"
6453   [(set (reg:CC_NOOV CC_REGNUM)
6454         (compare:CC_NOOV
6455          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6456                    (match_operator:SI 2 "shift_operator"
6457                     [(match_operand:SI 3 "s_register_operand" "r")
6458                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6459          (const_int 0)))
6460    (set (match_operand:SI 0 "s_register_operand" "=r")
6461         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6462                                                  (match_dup 4)])))]
6463   "TARGET_ARM"
6464   "sub%?s\\t%0, %1, %3%S2"
6465   [(set_attr "conds" "set")
6466    (set_attr "shift" "3") 
6467    ]
6470 (define_insn "*sub_shiftsi_compare0_scratch"
6471   [(set (reg:CC_NOOV CC_REGNUM)
6472         (compare:CC_NOOV
6473          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6474                    (match_operator:SI 2 "shift_operator"
6475                     [(match_operand:SI 3 "s_register_operand" "r")
6476                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6477          (const_int 0)))
6478    (clobber (match_scratch:SI 0 "=r"))]
6479   "TARGET_ARM"
6480   "sub%?s\\t%0, %1, %3%S2"
6481   [(set_attr "conds" "set")
6482    (set_attr "shift" "3") 
6483    ]
6488 (define_insn "*and_scc"
6489   [(set (match_operand:SI 0 "s_register_operand" "=r")
6490         (and:SI (match_operator:SI 1 "arm_comparison_operator"
6491                  [(match_operand 3 "cc_register" "") (const_int 0)])
6492                 (match_operand:SI 2 "s_register_operand" "r")))]
6493   "TARGET_ARM"
6494   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6495   [(set_attr "conds" "use")
6496    (set_attr "length" "8")]
6499 (define_insn "*ior_scc"
6500   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6501         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6502                  [(match_operand 3 "cc_register" "") (const_int 0)])
6503                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6504   "TARGET_ARM"
6505   "@
6506    orr%d2\\t%0, %1, #1
6507    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6508   [(set_attr "conds" "use")
6509    (set_attr "length" "4,8")]
6512 (define_insn "*compare_scc"
6513   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6514         (match_operator:SI 1 "arm_comparison_operator"
6515          [(match_operand:SI 2 "s_register_operand" "r,r")
6516           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6517    (clobber (reg:CC CC_REGNUM))]
6518   "TARGET_ARM"
6519   "*
6520     if (operands[3] == const0_rtx)
6521       {
6522         if (GET_CODE (operands[1]) == LT)
6523           return \"mov\\t%0, %2, lsr #31\";
6525         if (GET_CODE (operands[1]) == GE)
6526           return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6528         if (GET_CODE (operands[1]) == EQ)
6529           return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
6530       }
6532     if (GET_CODE (operands[1]) == NE)
6533       {
6534         if (which_alternative == 1)
6535           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
6536         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
6537       }
6538     if (which_alternative == 1)
6539       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6540     else
6541       output_asm_insn (\"cmp\\t%2, %3\", operands);
6542     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
6543   "
6544   [(set_attr "conds" "clob")
6545    (set_attr "length" "12")]
6548 (define_insn "*cond_move"
6549   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6550         (if_then_else:SI (match_operator 3 "equality_operator"
6551                           [(match_operator 4 "arm_comparison_operator"
6552                             [(match_operand 5 "cc_register" "") (const_int 0)])
6553                            (const_int 0)])
6554                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6555                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
6556   "TARGET_ARM"
6557   "*
6558     if (GET_CODE (operands[3]) == NE)
6559       {
6560         if (which_alternative != 1)
6561           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
6562         if (which_alternative != 0)
6563           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6564         return \"\";
6565       }
6566     if (which_alternative != 0)
6567       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6568     if (which_alternative != 1)
6569       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
6570     return \"\";
6571   "
6572   [(set_attr "conds" "use")
6573    (set_attr "length" "4,4,8")]
6576 (define_insn "*cond_arith"
6577   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6578         (match_operator:SI 5 "shiftable_operator" 
6579          [(match_operator:SI 4 "arm_comparison_operator"
6580            [(match_operand:SI 2 "s_register_operand" "r,r")
6581             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
6582           (match_operand:SI 1 "s_register_operand" "0,?r")]))
6583    (clobber (reg:CC CC_REGNUM))]
6584   "TARGET_ARM"
6585   "*
6586     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
6587       return \"%i5\\t%0, %1, %2, lsr #31\";
6589     output_asm_insn (\"cmp\\t%2, %3\", operands);
6590     if (GET_CODE (operands[5]) == AND)
6591       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
6592     else if (GET_CODE (operands[5]) == MINUS)
6593       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
6594     else if (which_alternative != 0)
6595       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6596     return \"%i5%d4\\t%0, %1, #1\";
6597   "
6598   [(set_attr "conds" "clob")
6599    (set_attr "length" "12")]
6602 (define_insn "*cond_sub"
6603   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6604         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
6605                   (match_operator:SI 4 "arm_comparison_operator"
6606                    [(match_operand:SI 2 "s_register_operand" "r,r")
6607                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
6608    (clobber (reg:CC CC_REGNUM))]
6609   "TARGET_ARM"
6610   "*
6611     output_asm_insn (\"cmp\\t%2, %3\", operands);
6612     if (which_alternative != 0)
6613       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6614     return \"sub%d4\\t%0, %1, #1\";
6615   "
6616   [(set_attr "conds" "clob")
6617    (set_attr "length" "8,12")]
6620 (define_insn "*cmp_ite0"
6621   [(set (match_operand 6 "dominant_cc_register" "")
6622         (compare
6623          (if_then_else:SI
6624           (match_operator 4 "arm_comparison_operator"
6625            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6626             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6627           (match_operator:SI 5 "arm_comparison_operator"
6628            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6629             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6630           (const_int 0))
6631          (const_int 0)))]
6632   "TARGET_ARM"
6633   "*
6634   {
6635     static const char * const opcodes[4][2] =
6636     {
6637       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6638        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6639       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6640        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6641       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6642        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6643       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6644        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6645     };
6646     int swap =
6647       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6649     return opcodes[which_alternative][swap];
6650   }"
6651   [(set_attr "conds" "set")
6652    (set_attr "length" "8")]
6655 (define_insn "*cmp_ite1"
6656   [(set (match_operand 6 "dominant_cc_register" "")
6657         (compare
6658          (if_then_else:SI
6659           (match_operator 4 "arm_comparison_operator"
6660            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6661             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6662           (match_operator:SI 5 "arm_comparison_operator"
6663            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6664             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6665           (const_int 1))
6666          (const_int 0)))]
6667   "TARGET_ARM"
6668   "*
6669   {
6670     static const char * const opcodes[4][2] =
6671     {
6672       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
6673        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6674       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
6675        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6676       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
6677        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6678       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
6679        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6680     };
6681     int swap =
6682       comparison_dominates_p (GET_CODE (operands[5]),
6683                               reverse_condition (GET_CODE (operands[4])));
6685     return opcodes[which_alternative][swap];
6686   }"
6687   [(set_attr "conds" "set")
6688    (set_attr "length" "8")]
6691 (define_insn "*cmp_and"
6692   [(set (match_operand 6 "dominant_cc_register" "")
6693         (compare
6694          (and:SI
6695           (match_operator 4 "arm_comparison_operator"
6696            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6697             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6698           (match_operator:SI 5 "arm_comparison_operator"
6699            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6700             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6701          (const_int 0)))]
6702   "TARGET_ARM"
6703   "*
6704   {
6705     static const char *const opcodes[4][2] =
6706     {
6707       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6708        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6709       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6710        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6711       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6712        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6713       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6714        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6715     };
6716     int swap =
6717       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6719     return opcodes[which_alternative][swap];
6720   }"
6721   [(set_attr "conds" "set")
6722    (set_attr "predicable" "no")
6723    (set_attr "length" "8")]
6726 (define_insn "*cmp_ior"
6727   [(set (match_operand 6 "dominant_cc_register" "")
6728         (compare
6729          (ior:SI
6730           (match_operator 4 "arm_comparison_operator"
6731            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6732             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6733           (match_operator:SI 5 "arm_comparison_operator"
6734            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6735             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6736          (const_int 0)))]
6737   "TARGET_ARM"
6738   "*
6740   static const char *const opcodes[4][2] =
6741   {
6742     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
6743      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6744     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
6745      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6746     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
6747      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6748     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
6749      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6750   };
6751   int swap =
6752     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6754   return opcodes[which_alternative][swap];
6757   [(set_attr "conds" "set")
6758    (set_attr "length" "8")]
6761 (define_insn_and_split "*ior_scc_scc"
6762   [(set (match_operand:SI 0 "s_register_operand" "=r")
6763         (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6764                  [(match_operand:SI 1 "s_register_operand" "r")
6765                   (match_operand:SI 2 "arm_add_operand" "rIL")])
6766                 (match_operator:SI 6 "arm_comparison_operator"
6767                  [(match_operand:SI 4 "s_register_operand" "r")
6768                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
6769    (clobber (reg:CC CC_REGNUM))]
6770   "TARGET_ARM
6771    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
6772        != CCmode)"
6773   "#"
6774   "TARGET_ARM && reload_completed"
6775   [(set (match_dup 7)
6776         (compare
6777          (ior:SI
6778           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6779           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6780          (const_int 0)))
6781    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
6782   "operands[7]
6783      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
6784                                                   DOM_CC_X_OR_Y),
6785                     CC_REGNUM);"
6786   [(set_attr "conds" "clob")
6787    (set_attr "length" "16")])
6789 ; If the above pattern is followed by a CMP insn, then the compare is 
6790 ; redundant, since we can rework the conditional instruction that follows.
6791 (define_insn_and_split "*ior_scc_scc_cmp"
6792   [(set (match_operand 0 "dominant_cc_register" "")
6793         (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6794                           [(match_operand:SI 1 "s_register_operand" "r")
6795                            (match_operand:SI 2 "arm_add_operand" "rIL")])
6796                          (match_operator:SI 6 "arm_comparison_operator"
6797                           [(match_operand:SI 4 "s_register_operand" "r")
6798                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
6799                  (const_int 0)))
6800    (set (match_operand:SI 7 "s_register_operand" "=r")
6801         (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6802                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
6803   "TARGET_ARM"
6804   "#"
6805   "TARGET_ARM && reload_completed"
6806   [(set (match_dup 0)
6807         (compare
6808          (ior:SI
6809           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6810           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6811          (const_int 0)))
6812    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
6813   ""
6814   [(set_attr "conds" "set")
6815    (set_attr "length" "16")])
6817 (define_insn_and_split "*and_scc_scc"
6818   [(set (match_operand:SI 0 "s_register_operand" "=r")
6819         (and:SI (match_operator:SI 3 "arm_comparison_operator"
6820                  [(match_operand:SI 1 "s_register_operand" "r")
6821                   (match_operand:SI 2 "arm_add_operand" "rIL")])
6822                 (match_operator:SI 6 "arm_comparison_operator"
6823                  [(match_operand:SI 4 "s_register_operand" "r")
6824                   (match_operand:SI 5 "arm_add_operand" "rIL")])))
6825    (clobber (reg:CC CC_REGNUM))]
6826   "TARGET_ARM
6827    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6828        != CCmode)"
6829   "#"
6830   "TARGET_ARM && reload_completed
6831    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6832        != CCmode)"
6833   [(set (match_dup 7)
6834         (compare
6835          (and:SI
6836           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6837           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6838          (const_int 0)))
6839    (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
6840   "operands[7]
6841      = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
6842                                                   DOM_CC_X_AND_Y),
6843                     CC_REGNUM);"
6844   [(set_attr "conds" "clob")
6845    (set_attr "length" "16")])
6847 ; If the above pattern is followed by a CMP insn, then the compare is 
6848 ; redundant, since we can rework the conditional instruction that follows.
6849 (define_insn_and_split "*and_scc_scc_cmp"
6850   [(set (match_operand 0 "dominant_cc_register" "")
6851         (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
6852                           [(match_operand:SI 1 "s_register_operand" "r")
6853                            (match_operand:SI 2 "arm_add_operand" "rIL")])
6854                          (match_operator:SI 6 "arm_comparison_operator"
6855                           [(match_operand:SI 4 "s_register_operand" "r")
6856                            (match_operand:SI 5 "arm_add_operand" "rIL")]))
6857                  (const_int 0)))
6858    (set (match_operand:SI 7 "s_register_operand" "=r")
6859         (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6860                 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
6861   "TARGET_ARM"
6862   "#"
6863   "TARGET_ARM && reload_completed"
6864   [(set (match_dup 0)
6865         (compare
6866          (and:SI
6867           (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6868           (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6869          (const_int 0)))
6870    (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
6871   ""
6872   [(set_attr "conds" "set")
6873    (set_attr "length" "16")])
6875 ;; If there is no dominance in the comparison, then we can still save an
6876 ;; instruction in the AND case, since we can know that the second compare
6877 ;; need only zero the value if false (if true, then the value is already
6878 ;; correct).
6879 (define_insn_and_split "*and_scc_scc_nodom"
6880   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
6881         (and:SI (match_operator:SI 3 "arm_comparison_operator"
6882                  [(match_operand:SI 1 "s_register_operand" "r,r,0")
6883                   (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
6884                 (match_operator:SI 6 "arm_comparison_operator"
6885                  [(match_operand:SI 4 "s_register_operand" "r,r,r")
6886                   (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
6887    (clobber (reg:CC CC_REGNUM))]
6888   "TARGET_ARM
6889    && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6890        == CCmode)"
6891   "#"
6892   "TARGET_ARM && reload_completed"
6893   [(parallel [(set (match_dup 0)
6894                    (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
6895               (clobber (reg:CC CC_REGNUM))])
6896    (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
6897    (set (match_dup 0)
6898         (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
6899                          (match_dup 0)
6900                          (const_int 0)))]
6901   "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
6902                                               operands[4], operands[5]),
6903                               CC_REGNUM);
6904    operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
6905                                   operands[5]);"
6906   [(set_attr "conds" "clob")
6907    (set_attr "length" "20")])
6909 (define_insn "*negscc"
6910   [(set (match_operand:SI 0 "s_register_operand" "=r")
6911         (neg:SI (match_operator 3 "arm_comparison_operator"
6912                  [(match_operand:SI 1 "s_register_operand" "r")
6913                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
6914    (clobber (reg:CC CC_REGNUM))]
6915   "TARGET_ARM"
6916   "*
6917   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
6918     return \"mov\\t%0, %1, asr #31\";
6920   if (GET_CODE (operands[3]) == NE)
6921     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
6923   if (GET_CODE (operands[3]) == GT)
6924     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
6926   output_asm_insn (\"cmp\\t%1, %2\", operands);
6927   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
6928   return \"mvn%d3\\t%0, #0\";
6929   "
6930   [(set_attr "conds" "clob")
6931    (set_attr "length" "12")]
6934 (define_insn "movcond"
6935   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6936         (if_then_else:SI
6937          (match_operator 5 "arm_comparison_operator"
6938           [(match_operand:SI 3 "s_register_operand" "r,r,r")
6939            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
6940          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6941          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
6942    (clobber (reg:CC CC_REGNUM))]
6943   "TARGET_ARM"
6944   "*
6945   if (GET_CODE (operands[5]) == LT
6946       && (operands[4] == const0_rtx))
6947     {
6948       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6949         {
6950           if (operands[2] == const0_rtx)
6951             return \"and\\t%0, %1, %3, asr #31\";
6952           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
6953         }
6954       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6955         {
6956           if (operands[1] == const0_rtx)
6957             return \"bic\\t%0, %2, %3, asr #31\";
6958           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
6959         }
6960       /* The only case that falls through to here is when both ops 1 & 2
6961          are constants */
6962     }
6964   if (GET_CODE (operands[5]) == GE
6965       && (operands[4] == const0_rtx))
6966     {
6967       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6968         {
6969           if (operands[2] == const0_rtx)
6970             return \"bic\\t%0, %1, %3, asr #31\";
6971           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
6972         }
6973       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6974         {
6975           if (operands[1] == const0_rtx)
6976             return \"and\\t%0, %2, %3, asr #31\";
6977           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
6978         }
6979       /* The only case that falls through to here is when both ops 1 & 2
6980          are constants */
6981     }
6982   if (GET_CODE (operands[4]) == CONST_INT
6983       && !const_ok_for_arm (INTVAL (operands[4])))
6984     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
6985   else
6986     output_asm_insn (\"cmp\\t%3, %4\", operands);
6987   if (which_alternative != 0)
6988     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
6989   if (which_alternative != 1)
6990     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
6991   return \"\";
6992   "
6993   [(set_attr "conds" "clob")
6994    (set_attr "length" "8,8,12")]
6997 (define_insn "*ifcompare_plus_move"
6998   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6999         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7000                           [(match_operand:SI 4 "s_register_operand" "r,r")
7001                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7002                          (plus:SI
7003                           (match_operand:SI 2 "s_register_operand" "r,r")
7004                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7005                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7006    (clobber (reg:CC CC_REGNUM))]
7007   "TARGET_ARM"
7008   "#"
7009   [(set_attr "conds" "clob")
7010    (set_attr "length" "8,12")]
7013 (define_insn "*if_plus_move"
7014   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7015         (if_then_else:SI
7016          (match_operator 4 "arm_comparison_operator"
7017           [(match_operand 5 "cc_register" "") (const_int 0)])
7018          (plus:SI
7019           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7020           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7021          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7022   "TARGET_ARM"
7023   "@
7024    add%d4\\t%0, %2, %3
7025    sub%d4\\t%0, %2, #%n3
7026    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7027    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7028   [(set_attr "conds" "use")
7029    (set_attr "length" "4,4,8,8")
7030    (set_attr "type" "*,*,*,*")]
7033 (define_insn "*ifcompare_move_plus"
7034   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7035         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7036                           [(match_operand:SI 4 "s_register_operand" "r,r")
7037                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7038                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7039                          (plus:SI
7040                           (match_operand:SI 2 "s_register_operand" "r,r")
7041                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7042    (clobber (reg:CC CC_REGNUM))]
7043   "TARGET_ARM"
7044   "#"
7045   [(set_attr "conds" "clob")
7046    (set_attr "length" "8,12")]
7049 (define_insn "*if_move_plus"
7050   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7051         (if_then_else:SI
7052          (match_operator 4 "arm_comparison_operator"
7053           [(match_operand 5 "cc_register" "") (const_int 0)])
7054          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7055          (plus:SI
7056           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7057           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7058   "TARGET_ARM"
7059   "@
7060    add%D4\\t%0, %2, %3
7061    sub%D4\\t%0, %2, #%n3
7062    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7063    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7064   [(set_attr "conds" "use")
7065    (set_attr "length" "4,4,8,8")
7066    (set_attr "type" "*,*,*,*")]
7069 (define_insn "*ifcompare_arith_arith"
7070   [(set (match_operand:SI 0 "s_register_operand" "=r")
7071         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7072                           [(match_operand:SI 5 "s_register_operand" "r")
7073                            (match_operand:SI 6 "arm_add_operand" "rIL")])
7074                          (match_operator:SI 8 "shiftable_operator"
7075                           [(match_operand:SI 1 "s_register_operand" "r")
7076                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7077                          (match_operator:SI 7 "shiftable_operator"
7078                           [(match_operand:SI 3 "s_register_operand" "r")
7079                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7080    (clobber (reg:CC CC_REGNUM))]
7081   "TARGET_ARM"
7082   "#"
7083   [(set_attr "conds" "clob")
7084    (set_attr "length" "12")]
7087 (define_insn "*if_arith_arith"
7088   [(set (match_operand:SI 0 "s_register_operand" "=r")
7089         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7090                           [(match_operand 8 "cc_register" "") (const_int 0)])
7091                          (match_operator:SI 6 "shiftable_operator"
7092                           [(match_operand:SI 1 "s_register_operand" "r")
7093                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7094                          (match_operator:SI 7 "shiftable_operator"
7095                           [(match_operand:SI 3 "s_register_operand" "r")
7096                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7097   "TARGET_ARM"
7098   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7099   [(set_attr "conds" "use")
7100    (set_attr "length" "8")]
7103 (define_insn "*ifcompare_arith_move"
7104   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7105         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7106                           [(match_operand:SI 2 "s_register_operand" "r,r")
7107                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7108                          (match_operator:SI 7 "shiftable_operator"
7109                           [(match_operand:SI 4 "s_register_operand" "r,r")
7110                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7111                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7112    (clobber (reg:CC CC_REGNUM))]
7113   "TARGET_ARM"
7114   "*
7115   /* If we have an operation where (op x 0) is the identity operation and
7116      the conditional operator is LT or GE and we are comparing against zero and
7117      everything is in registers then we can do this in two instructions */
7118   if (operands[3] == const0_rtx
7119       && GET_CODE (operands[7]) != AND
7120       && GET_CODE (operands[5]) == REG
7121       && GET_CODE (operands[1]) == REG 
7122       && REGNO (operands[1]) == REGNO (operands[4])
7123       && REGNO (operands[4]) != REGNO (operands[0]))
7124     {
7125       if (GET_CODE (operands[6]) == LT)
7126         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7127       else if (GET_CODE (operands[6]) == GE)
7128         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7129     }
7130   if (GET_CODE (operands[3]) == CONST_INT
7131       && !const_ok_for_arm (INTVAL (operands[3])))
7132     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7133   else
7134     output_asm_insn (\"cmp\\t%2, %3\", operands);
7135   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7136   if (which_alternative != 0)
7137     return \"mov%D6\\t%0, %1\";
7138   return \"\";
7139   "
7140   [(set_attr "conds" "clob")
7141    (set_attr "length" "8,12")]
7144 (define_insn "*if_arith_move"
7145   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7146         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7147                           [(match_operand 6 "cc_register" "") (const_int 0)])
7148                          (match_operator:SI 5 "shiftable_operator"
7149                           [(match_operand:SI 2 "s_register_operand" "r,r")
7150                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7151                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7152   "TARGET_ARM"
7153   "@
7154    %I5%d4\\t%0, %2, %3
7155    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7156   [(set_attr "conds" "use")
7157    (set_attr "length" "4,8")
7158    (set_attr "type" "*,*")]
7161 (define_insn "*ifcompare_move_arith"
7162   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7163         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7164                           [(match_operand:SI 4 "s_register_operand" "r,r")
7165                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7166                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7167                          (match_operator:SI 7 "shiftable_operator"
7168                           [(match_operand:SI 2 "s_register_operand" "r,r")
7169                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7170    (clobber (reg:CC CC_REGNUM))]
7171   "TARGET_ARM"
7172   "*
7173   /* If we have an operation where (op x 0) is the identity operation and
7174      the conditional operator is LT or GE and we are comparing against zero and
7175      everything is in registers then we can do this in two instructions */
7176   if (operands[5] == const0_rtx
7177       && GET_CODE (operands[7]) != AND
7178       && GET_CODE (operands[3]) == REG
7179       && GET_CODE (operands[1]) == REG 
7180       && REGNO (operands[1]) == REGNO (operands[2])
7181       && REGNO (operands[2]) != REGNO (operands[0]))
7182     {
7183       if (GET_CODE (operands[6]) == GE)
7184         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7185       else if (GET_CODE (operands[6]) == LT)
7186         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7187     }
7189   if (GET_CODE (operands[5]) == CONST_INT
7190       && !const_ok_for_arm (INTVAL (operands[5])))
7191     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7192   else
7193     output_asm_insn (\"cmp\\t%4, %5\", operands);
7195   if (which_alternative != 0)
7196     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7197   return \"%I7%D6\\t%0, %2, %3\";
7198   "
7199   [(set_attr "conds" "clob")
7200    (set_attr "length" "8,12")]
7203 (define_insn "*if_move_arith"
7204   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7205         (if_then_else:SI
7206          (match_operator 4 "arm_comparison_operator"
7207           [(match_operand 6 "cc_register" "") (const_int 0)])
7208          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7209          (match_operator:SI 5 "shiftable_operator"
7210           [(match_operand:SI 2 "s_register_operand" "r,r")
7211            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7212   "TARGET_ARM"
7213   "@
7214    %I5%D4\\t%0, %2, %3
7215    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7216   [(set_attr "conds" "use")
7217    (set_attr "length" "4,8")
7218    (set_attr "type" "*,*")]
7221 (define_insn "*ifcompare_move_not"
7222   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7223         (if_then_else:SI
7224          (match_operator 5 "arm_comparison_operator"
7225           [(match_operand:SI 3 "s_register_operand" "r,r")
7226            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7227          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7228          (not:SI
7229           (match_operand:SI 2 "s_register_operand" "r,r"))))
7230    (clobber (reg:CC CC_REGNUM))]
7231   "TARGET_ARM"
7232   "#"
7233   [(set_attr "conds" "clob")
7234    (set_attr "length" "8,12")]
7237 (define_insn "*if_move_not"
7238   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7239         (if_then_else:SI
7240          (match_operator 4 "arm_comparison_operator"
7241           [(match_operand 3 "cc_register" "") (const_int 0)])
7242          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7243          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7244   "TARGET_ARM"
7245   "@
7246    mvn%D4\\t%0, %2
7247    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7248    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7249   [(set_attr "conds" "use")
7250    (set_attr "length" "4,8,8")]
7253 (define_insn "*ifcompare_not_move"
7254   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7255         (if_then_else:SI 
7256          (match_operator 5 "arm_comparison_operator"
7257           [(match_operand:SI 3 "s_register_operand" "r,r")
7258            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7259          (not:SI
7260           (match_operand:SI 2 "s_register_operand" "r,r"))
7261          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7262    (clobber (reg:CC CC_REGNUM))]
7263   "TARGET_ARM"
7264   "#"
7265   [(set_attr "conds" "clob")
7266    (set_attr "length" "8,12")]
7269 (define_insn "*if_not_move"
7270   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7271         (if_then_else:SI
7272          (match_operator 4 "arm_comparison_operator"
7273           [(match_operand 3 "cc_register" "") (const_int 0)])
7274          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7275          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7276   "TARGET_ARM"
7277   "@
7278    mvn%d4\\t%0, %2
7279    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7280    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7281   [(set_attr "conds" "use")
7282    (set_attr "length" "4,8,8")]
7285 (define_insn "*ifcompare_shift_move"
7286   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7287         (if_then_else:SI
7288          (match_operator 6 "arm_comparison_operator"
7289           [(match_operand:SI 4 "s_register_operand" "r,r")
7290            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7291          (match_operator:SI 7 "shift_operator"
7292           [(match_operand:SI 2 "s_register_operand" "r,r")
7293            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7294          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7295    (clobber (reg:CC CC_REGNUM))]
7296   "TARGET_ARM"
7297   "#"
7298   [(set_attr "conds" "clob")
7299    (set_attr "length" "8,12")]
7302 (define_insn "*if_shift_move"
7303   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7304         (if_then_else:SI
7305          (match_operator 5 "arm_comparison_operator"
7306           [(match_operand 6 "cc_register" "") (const_int 0)])
7307          (match_operator:SI 4 "shift_operator"
7308           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7309            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7310          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7311   "TARGET_ARM"
7312   "@
7313    mov%d5\\t%0, %2%S4
7314    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7315    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7316   [(set_attr "conds" "use")
7317    (set_attr "shift" "2")
7318    (set_attr "length" "4,8,8")]
7321 (define_insn "*ifcompare_move_shift"
7322   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7323         (if_then_else:SI
7324          (match_operator 6 "arm_comparison_operator"
7325           [(match_operand:SI 4 "s_register_operand" "r,r")
7326            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7327          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7328          (match_operator:SI 7 "shift_operator"
7329           [(match_operand:SI 2 "s_register_operand" "r,r")
7330            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7331    (clobber (reg:CC CC_REGNUM))]
7332   "TARGET_ARM"
7333   "#"
7334   [(set_attr "conds" "clob")
7335    (set_attr "length" "8,12")]
7338 (define_insn "*if_move_shift"
7339   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7340         (if_then_else:SI
7341          (match_operator 5 "arm_comparison_operator"
7342           [(match_operand 6 "cc_register" "") (const_int 0)])
7343          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7344          (match_operator:SI 4 "shift_operator"
7345           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7346            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7347   "TARGET_ARM"
7348   "@
7349    mov%D5\\t%0, %2%S4
7350    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7351    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7352   [(set_attr "conds" "use")
7353    (set_attr "shift" "2")
7354    (set_attr "length" "4,8,8")]
7357 (define_insn "*ifcompare_shift_shift"
7358   [(set (match_operand:SI 0 "s_register_operand" "=r")
7359         (if_then_else:SI
7360          (match_operator 7 "arm_comparison_operator"
7361           [(match_operand:SI 5 "s_register_operand" "r")
7362            (match_operand:SI 6 "arm_add_operand" "rIL")])
7363          (match_operator:SI 8 "shift_operator"
7364           [(match_operand:SI 1 "s_register_operand" "r")
7365            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7366          (match_operator:SI 9 "shift_operator"
7367           [(match_operand:SI 3 "s_register_operand" "r")
7368            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7369    (clobber (reg:CC CC_REGNUM))]
7370   "TARGET_ARM"
7371   "#"
7372   [(set_attr "conds" "clob")
7373    (set_attr "length" "12")]
7376 (define_insn "*if_shift_shift"
7377   [(set (match_operand:SI 0 "s_register_operand" "=r")
7378         (if_then_else:SI
7379          (match_operator 5 "arm_comparison_operator"
7380           [(match_operand 8 "cc_register" "") (const_int 0)])
7381          (match_operator:SI 6 "shift_operator"
7382           [(match_operand:SI 1 "s_register_operand" "r")
7383            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7384          (match_operator:SI 7 "shift_operator"
7385           [(match_operand:SI 3 "s_register_operand" "r")
7386            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7387   "TARGET_ARM"
7388   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7389   [(set_attr "conds" "use")
7390    (set_attr "shift" "1")
7391    (set_attr "length" "8")]
7394 (define_insn "*ifcompare_not_arith"
7395   [(set (match_operand:SI 0 "s_register_operand" "=r")
7396         (if_then_else:SI
7397          (match_operator 6 "arm_comparison_operator"
7398           [(match_operand:SI 4 "s_register_operand" "r")
7399            (match_operand:SI 5 "arm_add_operand" "rIL")])
7400          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7401          (match_operator:SI 7 "shiftable_operator"
7402           [(match_operand:SI 2 "s_register_operand" "r")
7403            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7404    (clobber (reg:CC CC_REGNUM))]
7405   "TARGET_ARM"
7406   "#"
7407   [(set_attr "conds" "clob")
7408    (set_attr "length" "12")]
7411 (define_insn "*if_not_arith"
7412   [(set (match_operand:SI 0 "s_register_operand" "=r")
7413         (if_then_else:SI
7414          (match_operator 5 "arm_comparison_operator"
7415           [(match_operand 4 "cc_register" "") (const_int 0)])
7416          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7417          (match_operator:SI 6 "shiftable_operator"
7418           [(match_operand:SI 2 "s_register_operand" "r")
7419            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7420   "TARGET_ARM"
7421   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7422   [(set_attr "conds" "use")
7423    (set_attr "length" "8")]
7426 (define_insn "*ifcompare_arith_not"
7427   [(set (match_operand:SI 0 "s_register_operand" "=r")
7428         (if_then_else:SI
7429          (match_operator 6 "arm_comparison_operator"
7430           [(match_operand:SI 4 "s_register_operand" "r")
7431            (match_operand:SI 5 "arm_add_operand" "rIL")])
7432          (match_operator:SI 7 "shiftable_operator"
7433           [(match_operand:SI 2 "s_register_operand" "r")
7434            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7435          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7436    (clobber (reg:CC CC_REGNUM))]
7437   "TARGET_ARM"
7438   "#"
7439   [(set_attr "conds" "clob")
7440    (set_attr "length" "12")]
7443 (define_insn "*if_arith_not"
7444   [(set (match_operand:SI 0 "s_register_operand" "=r")
7445         (if_then_else:SI
7446          (match_operator 5 "arm_comparison_operator"
7447           [(match_operand 4 "cc_register" "") (const_int 0)])
7448          (match_operator:SI 6 "shiftable_operator"
7449           [(match_operand:SI 2 "s_register_operand" "r")
7450            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7451          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7452   "TARGET_ARM"
7453   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7454   [(set_attr "conds" "use")
7455    (set_attr "length" "8")]
7458 (define_insn "*ifcompare_neg_move"
7459   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7460         (if_then_else:SI
7461          (match_operator 5 "arm_comparison_operator"
7462           [(match_operand:SI 3 "s_register_operand" "r,r")
7463            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7464          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7465          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7466    (clobber (reg:CC CC_REGNUM))]
7467   "TARGET_ARM"
7468   "#"
7469   [(set_attr "conds" "clob")
7470    (set_attr "length" "8,12")]
7473 (define_insn "*if_neg_move"
7474   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7475         (if_then_else:SI
7476          (match_operator 4 "arm_comparison_operator"
7477           [(match_operand 3 "cc_register" "") (const_int 0)])
7478          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7479          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7480   "TARGET_ARM"
7481   "@
7482    rsb%d4\\t%0, %2, #0
7483    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7484    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7485   [(set_attr "conds" "use")
7486    (set_attr "length" "4,8,8")]
7489 (define_insn "*ifcompare_move_neg"
7490   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7491         (if_then_else:SI
7492          (match_operator 5 "arm_comparison_operator"
7493           [(match_operand:SI 3 "s_register_operand" "r,r")
7494            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7495          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7496          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7497    (clobber (reg:CC CC_REGNUM))]
7498   "TARGET_ARM"
7499   "#"
7500   [(set_attr "conds" "clob")
7501    (set_attr "length" "8,12")]
7504 (define_insn "*if_move_neg"
7505   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7506         (if_then_else:SI
7507          (match_operator 4 "arm_comparison_operator"
7508           [(match_operand 3 "cc_register" "") (const_int 0)])
7509          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7510          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7511   "TARGET_ARM"
7512   "@
7513    rsb%D4\\t%0, %2, #0
7514    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7515    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7516   [(set_attr "conds" "use")
7517    (set_attr "length" "4,8,8")]
7520 (define_insn "*arith_adjacentmem"
7521   [(set (match_operand:SI 0 "s_register_operand" "=r")
7522         (match_operator:SI 1 "shiftable_operator"
7523          [(match_operand:SI 2 "memory_operand" "m")
7524           (match_operand:SI 3 "memory_operand" "m")]))
7525    (clobber (match_scratch:SI 4 "=r"))]
7526   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7527   "*
7528   {
7529     rtx ldm[3];
7530     rtx arith[4];
7531     int val1 = 0, val2 = 0;
7533     if (REGNO (operands[0]) > REGNO (operands[4]))
7534       {
7535         ldm[1] = operands[4];
7536         ldm[2] = operands[0];
7537       }
7538     else
7539       {
7540         ldm[1] = operands[0];
7541         ldm[2] = operands[4];
7542       }
7543     if (GET_CODE (XEXP (operands[2], 0)) != REG)
7544       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7545     if (GET_CODE (XEXP (operands[3], 0)) != REG)
7546       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7547     arith[0] = operands[0];
7548     arith[3] = operands[1];
7549     if (val1 < val2)
7550       {
7551         arith[1] = ldm[1];
7552         arith[2] = ldm[2];
7553       }
7554     else
7555       {
7556         arith[1] = ldm[2];
7557         arith[2] = ldm[1];
7558       }
7559    if (val1 && val2)
7560       {
7561         rtx ops[3];
7562         ldm[0] = ops[0] = operands[4];
7563         ops[1] = XEXP (XEXP (operands[2], 0), 0);
7564         ops[2] = XEXP (XEXP (operands[2], 0), 1);
7565         output_add_immediate (ops);
7566         if (val1 < val2)
7567           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7568         else
7569           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7570       }
7571     else if (val1)
7572       {
7573         ldm[0] = XEXP (operands[3], 0);
7574         if (val1 < val2)
7575           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7576         else
7577           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7578       }
7579     else
7580       {
7581         ldm[0] = XEXP (operands[2], 0);
7582         if (val1 < val2)
7583           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7584         else
7585           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7586       }
7587     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7588     return \"\";
7589   }"
7590   [(set_attr "length" "12")
7591    (set_attr "predicable" "yes")
7592    (set_attr "type" "load")]
7595 ;; the arm can support extended pre-inc instructions
7597 ;; In all these cases, we use operands 0 and 1 for the register being
7598 ;; incremented because those are the operands that local-alloc will
7599 ;; tie and these are the pair most likely to be tieable (and the ones
7600 ;; that will benefit the most).
7602 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7603 ;; elimination will cause too many headaches.
7605 (define_insn "*strqi_preinc"
7606   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7607                          (match_operand:SI 2 "index_operand" "rJ")))
7608         (match_operand:QI 3 "s_register_operand" "r"))
7609    (set (match_operand:SI 0 "s_register_operand" "=r")
7610         (plus:SI (match_dup 1) (match_dup 2)))]
7611   "TARGET_ARM
7612    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7613    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7614    && (GET_CODE (operands[2]) != REG
7615        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7616   "str%?b\\t%3, [%0, %2]!"
7617   [(set_attr "type" "store1")
7618    (set_attr "predicable" "yes")]
7621 (define_insn "*strqi_predec"
7622   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7623                           (match_operand:SI 2 "s_register_operand" "r")))
7624         (match_operand:QI 3 "s_register_operand" "r"))
7625    (set (match_operand:SI 0 "s_register_operand" "=r")
7626         (minus:SI (match_dup 1) (match_dup 2)))]
7627   "TARGET_ARM
7628    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7629    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7630    && (GET_CODE (operands[2]) != REG
7631        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7632   "str%?b\\t%3, [%0, -%2]!"
7633   [(set_attr "type" "store1")
7634    (set_attr "predicable" "yes")]
7637 (define_insn "*loadqi_preinc"
7638   [(set (match_operand:QI 3 "s_register_operand" "=r")
7639         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7640                          (match_operand:SI 2 "index_operand" "rJ"))))
7641    (set (match_operand:SI 0 "s_register_operand" "=r")
7642         (plus:SI (match_dup 1) (match_dup 2)))]
7643   "TARGET_ARM
7644    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7645    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7646    && (GET_CODE (operands[2]) != REG
7647        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7648   "ldr%?b\\t%3, [%0, %2]!"
7649   [(set_attr "type" "load")
7650    (set_attr "predicable" "yes")]
7653 (define_insn "*loadqi_predec"
7654   [(set (match_operand:QI 3 "s_register_operand" "=r")
7655         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7656                           (match_operand:SI 2 "s_register_operand" "r"))))
7657    (set (match_operand:SI 0 "s_register_operand" "=r")
7658         (minus:SI (match_dup 1) (match_dup 2)))]
7659   "TARGET_ARM
7660    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7661    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7662    && (GET_CODE (operands[2]) != REG
7663        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7664   "ldr%?b\\t%3, [%0, -%2]!"
7665   [(set_attr "type" "load")
7666    (set_attr "predicable" "yes")]
7669 (define_insn "*loadqisi_preinc"
7670   [(set (match_operand:SI 3 "s_register_operand" "=r")
7671         (zero_extend:SI
7672          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7673                           (match_operand:SI 2 "index_operand" "rJ")))))
7674    (set (match_operand:SI 0 "s_register_operand" "=r")
7675         (plus:SI (match_dup 1) (match_dup 2)))]
7676   "TARGET_ARM
7677    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7678    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7679    && (GET_CODE (operands[2]) != REG
7680        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7681   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
7682   [(set_attr "type" "load")
7683    (set_attr "predicable" "yes")]
7686 (define_insn "*loadqisi_predec"
7687   [(set (match_operand:SI 3 "s_register_operand" "=r")
7688         (zero_extend:SI
7689          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7690                            (match_operand:SI 2 "s_register_operand" "r")))))
7691    (set (match_operand:SI 0 "s_register_operand" "=r")
7692         (minus:SI (match_dup 1) (match_dup 2)))]
7693   "TARGET_ARM
7694    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7695    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7696    && (GET_CODE (operands[2]) != REG
7697        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7698   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
7699   [(set_attr "type" "load")
7700    (set_attr "predicable" "yes")]
7703 (define_insn "*strsi_preinc"
7704   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7705                          (match_operand:SI 2 "index_operand" "rJ")))
7706         (match_operand:SI 3 "s_register_operand" "r"))
7707    (set (match_operand:SI 0 "s_register_operand" "=r")
7708         (plus:SI (match_dup 1) (match_dup 2)))]
7709   "TARGET_ARM
7710    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7711    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7712    && (GET_CODE (operands[2]) != REG
7713        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7714   "str%?\\t%3, [%0, %2]!"
7715   [(set_attr "type" "store1")
7716    (set_attr "predicable" "yes")]
7719 (define_insn "*strsi_predec"
7720   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7721                           (match_operand:SI 2 "s_register_operand" "r")))
7722         (match_operand:SI 3 "s_register_operand" "r"))
7723    (set (match_operand:SI 0 "s_register_operand" "=r")
7724         (minus:SI (match_dup 1) (match_dup 2)))]
7725   "TARGET_ARM
7726    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7727    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7728    && (GET_CODE (operands[2]) != REG
7729        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7730   "str%?\\t%3, [%0, -%2]!"
7731   [(set_attr "type" "store1")
7732    (set_attr "predicable" "yes")]
7735 (define_insn "*loadsi_preinc"
7736   [(set (match_operand:SI 3 "s_register_operand" "=r")
7737         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7738                          (match_operand:SI 2 "index_operand" "rJ"))))
7739    (set (match_operand:SI 0 "s_register_operand" "=r")
7740         (plus:SI (match_dup 1) (match_dup 2)))]
7741   "TARGET_ARM
7742    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7743    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7744    && (GET_CODE (operands[2]) != REG
7745        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7746   "ldr%?\\t%3, [%0, %2]!"
7747   [(set_attr "type" "load")
7748    (set_attr "predicable" "yes")]
7751 (define_insn "*loadsi_predec"
7752   [(set (match_operand:SI 3 "s_register_operand" "=r")
7753         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7754                           (match_operand:SI 2 "s_register_operand" "r"))))
7755    (set (match_operand:SI 0 "s_register_operand" "=r")
7756         (minus:SI (match_dup 1) (match_dup 2)))]
7757   "TARGET_ARM
7758    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7759    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7760    && (GET_CODE (operands[2]) != REG
7761        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7762   "ldr%?\\t%3, [%0, -%2]!"
7763   [(set_attr "type" "load")
7764    (set_attr "predicable" "yes")]
7767 (define_insn "*loadhi_preinc"
7768   [(set (match_operand:HI 3 "s_register_operand" "=r")
7769         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7770                          (match_operand:SI 2 "index_operand" "rJ"))))
7771    (set (match_operand:SI 0 "s_register_operand" "=r")
7772         (plus:SI (match_dup 1) (match_dup 2)))]
7773   "TARGET_ARM
7774    && !BYTES_BIG_ENDIAN
7775    && !TARGET_MMU_TRAPS
7776    && !arm_arch4
7777    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7778    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7779    && (GET_CODE (operands[2]) != REG
7780        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7781   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
7782   [(set_attr "type" "load")
7783    (set_attr "predicable" "yes")]
7786 (define_insn "*loadhi_predec"
7787   [(set (match_operand:HI 3 "s_register_operand" "=r")
7788         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7789                           (match_operand:SI 2 "s_register_operand" "r"))))
7790    (set (match_operand:SI 0 "s_register_operand" "=r")
7791         (minus:SI (match_dup 1) (match_dup 2)))]
7792   "TARGET_ARM
7793    && !BYTES_BIG_ENDIAN
7794    && !TARGET_MMU_TRAPS
7795    && !arm_arch4
7796    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7797    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7798    && (GET_CODE (operands[2]) != REG
7799        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7800   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
7801   [(set_attr "type" "load")
7802    (set_attr "predicable" "yes")]
7805 (define_insn "*strqi_shiftpreinc"
7806   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7807                           [(match_operand:SI 3 "s_register_operand" "r")
7808                            (match_operand:SI 4 "const_shift_operand" "n")])
7809                          (match_operand:SI 1 "s_register_operand" "0")))
7810         (match_operand:QI 5 "s_register_operand" "r"))
7811    (set (match_operand:SI 0 "s_register_operand" "=r")
7812         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7813                  (match_dup 1)))]
7814   "TARGET_ARM
7815    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7816    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7817    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7818   "str%?b\\t%5, [%0, %3%S2]!"
7819   [(set_attr "type" "store1")
7820    (set_attr "predicable" "yes")]
7823 (define_insn "*strqi_shiftpredec"
7824   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7825                           (match_operator:SI 2 "shift_operator"
7826                            [(match_operand:SI 3 "s_register_operand" "r")
7827                             (match_operand:SI 4 "const_shift_operand" "n")])))
7828         (match_operand:QI 5 "s_register_operand" "r"))
7829    (set (match_operand:SI 0 "s_register_operand" "=r")
7830         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7831                                                  (match_dup 4)])))]
7832   "TARGET_ARM
7833    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7834    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7835    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7836   "str%?b\\t%5, [%0, -%3%S2]!"
7837   [(set_attr "type" "store1")
7838    (set_attr "predicable" "yes")]
7841 (define_insn "*loadqi_shiftpreinc"
7842   [(set (match_operand:QI 5 "s_register_operand" "=r")
7843         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7844                           [(match_operand:SI 3 "s_register_operand" "r")
7845                            (match_operand:SI 4 "const_shift_operand" "n")])
7846                          (match_operand:SI 1 "s_register_operand" "0"))))
7847    (set (match_operand:SI 0 "s_register_operand" "=r")
7848         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7849                  (match_dup 1)))]
7850   "TARGET_ARM
7851    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7852    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7853    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7854   "ldr%?b\\t%5, [%0, %3%S2]!"
7855   [(set_attr "type" "load")
7856    (set_attr "predicable" "yes")]
7859 (define_insn "*loadqi_shiftpredec"
7860   [(set (match_operand:QI 5 "s_register_operand" "=r")
7861         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7862                           (match_operator:SI 2 "shift_operator"
7863                            [(match_operand:SI 3 "s_register_operand" "r")
7864                             (match_operand:SI 4 "const_shift_operand" "n")]))))
7865    (set (match_operand:SI 0 "s_register_operand" "=r")
7866         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7867                                                  (match_dup 4)])))]
7868   "TARGET_ARM
7869    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7870    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7871    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7872   "ldr%?b\\t%5, [%0, -%3%S2]!"
7873   [(set_attr "type" "load")
7874    (set_attr "predicable" "yes")]
7877 (define_insn "*strsi_shiftpreinc"
7878   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7879                           [(match_operand:SI 3 "s_register_operand" "r")
7880                            (match_operand:SI 4 "const_shift_operand" "n")])
7881                          (match_operand:SI 1 "s_register_operand" "0")))
7882         (match_operand:SI 5 "s_register_operand" "r"))
7883    (set (match_operand:SI 0 "s_register_operand" "=r")
7884         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7885                  (match_dup 1)))]
7886   "TARGET_ARM
7887    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7888    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7889    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7890   "str%?\\t%5, [%0, %3%S2]!"
7891   [(set_attr "type" "store1")
7892    (set_attr "predicable" "yes")]
7895 (define_insn "*strsi_shiftpredec"
7896   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7897                           (match_operator:SI 2 "shift_operator"
7898                            [(match_operand:SI 3 "s_register_operand" "r")
7899                             (match_operand:SI 4 "const_shift_operand" "n")])))
7900         (match_operand:SI 5 "s_register_operand" "r"))
7901    (set (match_operand:SI 0 "s_register_operand" "=r")
7902         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7903                                                  (match_dup 4)])))]
7904   "TARGET_ARM
7905    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7906    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7907    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7908   "str%?\\t%5, [%0, -%3%S2]!"
7909   [(set_attr "type" "store1")
7910    (set_attr "predicable" "yes")]
7913 (define_insn "*loadsi_shiftpreinc"
7914   [(set (match_operand:SI 5 "s_register_operand" "=r")
7915         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7916                           [(match_operand:SI 3 "s_register_operand" "r")
7917                            (match_operand:SI 4 "const_shift_operand" "n")])
7918                          (match_operand:SI 1 "s_register_operand" "0"))))
7919    (set (match_operand:SI 0 "s_register_operand" "=r")
7920         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7921                  (match_dup 1)))]
7922   "TARGET_ARM
7923    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7924    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7925    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7926   "ldr%?\\t%5, [%0, %3%S2]!"
7927   [(set_attr "type" "load")
7928    (set_attr "predicable" "yes")]
7931 (define_insn "*loadsi_shiftpredec"
7932   [(set (match_operand:SI 5 "s_register_operand" "=r")
7933         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7934                           (match_operator:SI 2 "shift_operator"
7935                            [(match_operand:SI 3 "s_register_operand" "r")
7936                             (match_operand:SI 4 "const_shift_operand" "n")]))))
7937    (set (match_operand:SI 0 "s_register_operand" "=r")
7938         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7939                                                  (match_dup 4)])))]
7940   "TARGET_ARM
7941    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7942    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7943    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7944   "ldr%?\\t%5, [%0, -%3%S2]!"
7945   [(set_attr "type" "load")
7946    (set_attr "predicable" "yes")])
7948 (define_insn "*loadhi_shiftpreinc"
7949   [(set (match_operand:HI 5 "s_register_operand" "=r")
7950         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
7951                           [(match_operand:SI 3 "s_register_operand" "r")
7952                            (match_operand:SI 4 "const_shift_operand" "n")])
7953                          (match_operand:SI 1 "s_register_operand" "0"))))
7954    (set (match_operand:SI 0 "s_register_operand" "=r")
7955         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7956                  (match_dup 1)))]
7957   "TARGET_ARM
7958    && !BYTES_BIG_ENDIAN
7959    && !TARGET_MMU_TRAPS
7960    && !arm_arch4
7961    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7962    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7963    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7964   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
7965   [(set_attr "type" "load")
7966    (set_attr "predicable" "yes")]
7969 (define_insn "*loadhi_shiftpredec"
7970   [(set (match_operand:HI 5 "s_register_operand" "=r")
7971         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7972                           (match_operator:SI 2 "shift_operator"
7973                            [(match_operand:SI 3 "s_register_operand" "r")
7974                             (match_operand:SI 4 "const_shift_operand" "n")]))))
7975    (set (match_operand:SI 0 "s_register_operand" "=r")
7976         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7977                                                  (match_dup 4)])))]
7978   "TARGET_ARM
7979    && !BYTES_BIG_ENDIAN
7980    && !TARGET_MMU_TRAPS
7981    && !arm_arch4
7982    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7983    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7984    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7985   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
7986   [(set_attr "type" "load")
7987    (set_attr "predicable" "yes")]
7990 ; It can also support extended post-inc expressions, but combine doesn't
7991 ; try these....
7992 ; It doesn't seem worth adding peepholes for anything but the most common
7993 ; cases since, unlike combine, the increment must immediately follow the load
7994 ; for this pattern to match.
7995 ; We must watch to see that the source/destination register isn't also the
7996 ; same as the base address register, and that if the index is a register,
7997 ; that it is not the same as the base address register.  In such cases the
7998 ; instruction that we would generate would have UNPREDICTABLE behavior so 
7999 ; we cannot use it.
8001 (define_peephole
8002   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8003         (match_operand:QI 2 "s_register_operand" "r"))
8004    (set (match_dup 0)
8005         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8006   "TARGET_ARM
8007    && (REGNO (operands[2]) != REGNO (operands[0]))
8008    && (GET_CODE (operands[1]) != REG
8009        || (REGNO (operands[1]) != REGNO (operands[0])))"
8010   "str%?b\\t%2, [%0], %1"
8013 (define_peephole
8014   [(set (match_operand:QI 0 "s_register_operand" "=r")
8015         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8016    (set (match_dup 1)
8017         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8018   "TARGET_ARM
8019    && REGNO (operands[0]) != REGNO(operands[1])
8020    && (GET_CODE (operands[2]) != REG
8021        || REGNO(operands[0]) != REGNO (operands[2]))"
8022   "ldr%?b\\t%0, [%1], %2"
8025 (define_peephole
8026   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8027         (match_operand:SI 2 "s_register_operand" "r"))
8028    (set (match_dup 0)
8029         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8030   "TARGET_ARM
8031    && (REGNO (operands[2]) != REGNO (operands[0]))
8032    && (GET_CODE (operands[1]) != REG
8033        || (REGNO (operands[1]) != REGNO (operands[0])))"
8034   "str%?\\t%2, [%0], %1"
8037 (define_peephole
8038   [(set (match_operand:HI 0 "s_register_operand" "=r")
8039         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8040    (set (match_dup 1)
8041         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8042   "TARGET_ARM
8043    && !BYTES_BIG_ENDIAN
8044    && !TARGET_MMU_TRAPS
8045    && !arm_arch4
8046    && REGNO (operands[0]) != REGNO(operands[1])
8047    && (GET_CODE (operands[2]) != REG
8048        || REGNO(operands[0]) != REGNO (operands[2]))"
8049   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8052 (define_peephole
8053   [(set (match_operand:SI 0 "s_register_operand" "=r")
8054         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8055    (set (match_dup 1)
8056         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8057   "TARGET_ARM
8058    && REGNO (operands[0]) != REGNO(operands[1])
8059    && (GET_CODE (operands[2]) != REG
8060        || REGNO(operands[0]) != REGNO (operands[2]))"
8061   "ldr%?\\t%0, [%1], %2"
8064 (define_peephole
8065   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8066                          (match_operand:SI 1 "index_operand" "rJ")))
8067         (match_operand:QI 2 "s_register_operand" "r"))
8068    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8069   "TARGET_ARM
8070    && (REGNO (operands[2]) != REGNO (operands[0]))
8071    && (GET_CODE (operands[1]) != REG
8072        || (REGNO (operands[1]) != REGNO (operands[0])))"
8073   "str%?b\\t%2, [%0, %1]!"
8076 (define_peephole
8077   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8078                           [(match_operand:SI 0 "s_register_operand" "r")
8079                            (match_operand:SI 1 "const_int_operand" "n")])
8080                          (match_operand:SI 2 "s_register_operand" "+r")))
8081         (match_operand:QI 3 "s_register_operand" "r"))
8082    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8083                                (match_dup 2)))]
8084   "TARGET_ARM
8085    && (REGNO (operands[3]) != REGNO (operands[2]))
8086    && (REGNO (operands[0]) != REGNO (operands[2]))"
8087   "str%?b\\t%3, [%2, %0%S4]!"
8090 ; This pattern is never tried by combine, so do it as a peephole
8092 (define_peephole2
8093   [(set (match_operand:SI 0 "s_register_operand" "")
8094         (match_operand:SI 1 "s_register_operand" ""))
8095    (set (reg:CC CC_REGNUM)
8096         (compare:CC (match_dup 1) (const_int 0)))]
8097   "TARGET_ARM
8098    && (!TARGET_CIRRUS
8099        || (!cirrus_fp_register (operands[0], SImode)
8100            && !cirrus_fp_register (operands[1], SImode)))
8101   "
8102   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8103               (set (match_dup 0) (match_dup 1))])]
8104   ""
8107 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8108 ; reversed, check that the memory references aren't volatile.
8110 (define_peephole
8111   [(set (match_operand:SI 0 "s_register_operand" "=r")
8112         (match_operand:SI 4 "memory_operand" "m"))
8113    (set (match_operand:SI 1 "s_register_operand" "=r")
8114         (match_operand:SI 5 "memory_operand" "m"))
8115    (set (match_operand:SI 2 "s_register_operand" "=r")
8116         (match_operand:SI 6 "memory_operand" "m"))
8117    (set (match_operand:SI 3 "s_register_operand" "=r")
8118         (match_operand:SI 7 "memory_operand" "m"))]
8119   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8120   "*
8121   return emit_ldm_seq (operands, 4);
8122   "
8125 (define_peephole
8126   [(set (match_operand:SI 0 "s_register_operand" "=r")
8127         (match_operand:SI 3 "memory_operand" "m"))
8128    (set (match_operand:SI 1 "s_register_operand" "=r")
8129         (match_operand:SI 4 "memory_operand" "m"))
8130    (set (match_operand:SI 2 "s_register_operand" "=r")
8131         (match_operand:SI 5 "memory_operand" "m"))]
8132   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8133   "*
8134   return emit_ldm_seq (operands, 3);
8135   "
8138 (define_peephole
8139   [(set (match_operand:SI 0 "s_register_operand" "=r")
8140         (match_operand:SI 2 "memory_operand" "m"))
8141    (set (match_operand:SI 1 "s_register_operand" "=r")
8142         (match_operand:SI 3 "memory_operand" "m"))]
8143   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8144   "*
8145   return emit_ldm_seq (operands, 2);
8146   "
8149 (define_peephole
8150   [(set (match_operand:SI 4 "memory_operand" "=m")
8151         (match_operand:SI 0 "s_register_operand" "r"))
8152    (set (match_operand:SI 5 "memory_operand" "=m")
8153         (match_operand:SI 1 "s_register_operand" "r"))
8154    (set (match_operand:SI 6 "memory_operand" "=m")
8155         (match_operand:SI 2 "s_register_operand" "r"))
8156    (set (match_operand:SI 7 "memory_operand" "=m")
8157         (match_operand:SI 3 "s_register_operand" "r"))]
8158   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8159   "*
8160   return emit_stm_seq (operands, 4);
8161   "
8164 (define_peephole
8165   [(set (match_operand:SI 3 "memory_operand" "=m")
8166         (match_operand:SI 0 "s_register_operand" "r"))
8167    (set (match_operand:SI 4 "memory_operand" "=m")
8168         (match_operand:SI 1 "s_register_operand" "r"))
8169    (set (match_operand:SI 5 "memory_operand" "=m")
8170         (match_operand:SI 2 "s_register_operand" "r"))]
8171   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8172   "*
8173   return emit_stm_seq (operands, 3);
8174   "
8177 (define_peephole
8178   [(set (match_operand:SI 2 "memory_operand" "=m")
8179         (match_operand:SI 0 "s_register_operand" "r"))
8180    (set (match_operand:SI 3 "memory_operand" "=m")
8181         (match_operand:SI 1 "s_register_operand" "r"))]
8182   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8183   "*
8184   return emit_stm_seq (operands, 2);
8185   "
8188 (define_split
8189   [(set (match_operand:SI 0 "s_register_operand" "")
8190         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8191                        (const_int 0))
8192                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8193                          [(match_operand:SI 3 "s_register_operand" "")
8194                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
8195    (clobber (match_operand:SI 5 "s_register_operand" ""))]
8196   "TARGET_ARM"
8197   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8198    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8199                               (match_dup 5)))]
8200   ""
8203 ;; This split can be used because CC_Z mode implies that the following
8204 ;; branch will be an equality, or an unsigned inequality, so the sign
8205 ;; extension is not needed.
8207 (define_split
8208   [(set (reg:CC_Z CC_REGNUM)
8209         (compare:CC_Z
8210          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8211                     (const_int 24))
8212          (match_operand 1 "const_int_operand" "")))
8213    (clobber (match_scratch:SI 2 ""))]
8214   "TARGET_ARM
8215    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8216        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8217   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8218    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8219   "
8220   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8221   "
8224 (define_expand "prologue"
8225   [(clobber (const_int 0))]
8226   "TARGET_EITHER"
8227   "if (TARGET_ARM)
8228      arm_expand_prologue ();
8229    else
8230      thumb_expand_prologue ();
8231   DONE;
8232   "
8235 (define_expand "epilogue"
8236   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8237   "TARGET_EITHER"
8238   "
8239   if (TARGET_THUMB)
8240     thumb_expand_epilogue ();
8241   else if (USE_RETURN_INSN (FALSE))
8242     {
8243       emit_jump_insn (gen_return ());
8244       DONE;
8245     }
8246   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8247         gen_rtvec (1,
8248                 gen_rtx_RETURN (VOIDmode)),
8249         VUNSPEC_EPILOGUE));
8250   DONE;
8251   "
8254 ;; Note - although unspec_volatile's USE all hard registers,
8255 ;; USEs are ignored after relaod has completed.  Thus we need
8256 ;; to add an unspec of the link register to ensure that flow
8257 ;; does not think that it is unused by the sibcall branch that
8258 ;; will replace the standard function epilogue.
8259 (define_insn "sibcall_epilogue"
8260   [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8261               (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8262   "TARGET_ARM"
8263   "*
8264   if (USE_RETURN_INSN (FALSE))
8265     return output_return_instruction (const_true_rtx, FALSE, FALSE);
8266   return arm_output_epilogue (FALSE);
8267   "
8268 ;; Length is absolute worst case
8269   [(set_attr "length" "44")
8270    (set_attr "type" "block")
8271    ;; We don't clobber the conditions, but the potential length of this
8272    ;; operation is sufficient to make conditionalizing the sequence 
8273    ;; unlikely to be profitable.
8274    (set_attr "conds" "clob")]
8277 (define_insn "*epilogue_insns"
8278   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8279   "TARGET_EITHER"
8280   "*
8281   if (TARGET_ARM)
8282     return arm_output_epilogue (TRUE);
8283   else /* TARGET_THUMB */
8284     return thumb_unexpanded_epilogue ();
8285   "
8286   ; Length is absolute worst case
8287   [(set_attr "length" "44")
8288    (set_attr "type" "block")
8289    ;; We don't clobber the conditions, but the potential length of this
8290    ;; operation is sufficient to make conditionalizing the sequence 
8291    ;; unlikely to be profitable.
8292    (set_attr "conds" "clob")]
8295 (define_expand "eh_epilogue"
8296   [(use (match_operand:SI 0 "register_operand" ""))
8297    (use (match_operand:SI 1 "register_operand" ""))
8298    (use (match_operand:SI 2 "register_operand" ""))]
8299   "TARGET_EITHER"
8300   "
8301   {
8302     cfun->machine->eh_epilogue_sp_ofs = operands[1];
8303     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8304       {
8305         rtx ra = gen_rtx_REG (Pmode, 2);
8307         emit_move_insn (ra, operands[2]);
8308         operands[2] = ra;
8309       }
8310     /* This is a hack -- we may have crystalized the function type too
8311        early.  */
8312     cfun->machine->func_type = 0;
8313   }"
8316 ;; This split is only used during output to reduce the number of patterns
8317 ;; that need assembler instructions adding to them.  We allowed the setting
8318 ;; of the conditions to be implicit during rtl generation so that
8319 ;; the conditional compare patterns would work.  However this conflicts to
8320 ;; some extent with the conditional data operations, so we have to split them
8321 ;; up again here.
8323 (define_split
8324   [(set (match_operand:SI 0 "s_register_operand" "")
8325         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8326                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8327                          (match_dup 0)
8328                          (match_operand 4 "" "")))
8329    (clobber (reg:CC CC_REGNUM))]
8330   "TARGET_ARM && reload_completed"
8331   [(set (match_dup 5) (match_dup 6))
8332    (cond_exec (match_dup 7)
8333               (set (match_dup 0) (match_dup 4)))]
8334   "
8335   {
8336     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8337                                              operands[2], operands[3]);
8338     enum rtx_code rc = GET_CODE (operands[1]);
8340     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8341     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8342     if (mode == CCFPmode || mode == CCFPEmode)
8343       rc = reverse_condition_maybe_unordered (rc);
8344     else
8345       rc = reverse_condition (rc);
8347     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8348   }"
8351 (define_split
8352   [(set (match_operand:SI 0 "s_register_operand" "")
8353         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8354                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8355                          (match_operand 4 "" "")
8356                          (match_dup 0)))
8357    (clobber (reg:CC CC_REGNUM))]
8358   "TARGET_ARM && reload_completed"
8359   [(set (match_dup 5) (match_dup 6))
8360    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8361               (set (match_dup 0) (match_dup 4)))]
8362   "
8363   {
8364     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8365                                              operands[2], operands[3]);
8367     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8368     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8369   }"
8372 (define_split
8373   [(set (match_operand:SI 0 "s_register_operand" "")
8374         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8375                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8376                          (match_operand 4 "" "")
8377                          (match_operand 5 "" "")))
8378    (clobber (reg:CC CC_REGNUM))]
8379   "TARGET_ARM && reload_completed"
8380   [(set (match_dup 6) (match_dup 7))
8381    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8382               (set (match_dup 0) (match_dup 4)))
8383    (cond_exec (match_dup 8)
8384               (set (match_dup 0) (match_dup 5)))]
8385   "
8386   {
8387     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8388                                              operands[2], operands[3]);
8389     enum rtx_code rc = GET_CODE (operands[1]);
8391     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8392     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8393     if (mode == CCFPmode || mode == CCFPEmode)
8394       rc = reverse_condition_maybe_unordered (rc);
8395     else
8396       rc = reverse_condition (rc);
8398     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8399   }"
8402 (define_split
8403   [(set (match_operand:SI 0 "s_register_operand" "")
8404         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8405                           [(match_operand:SI 2 "s_register_operand" "")
8406                            (match_operand:SI 3 "arm_add_operand" "")])
8407                          (match_operand:SI 4 "arm_rhs_operand" "")
8408                          (not:SI
8409                           (match_operand:SI 5 "s_register_operand" ""))))
8410    (clobber (reg:CC CC_REGNUM))]
8411   "TARGET_ARM && reload_completed"
8412   [(set (match_dup 6) (match_dup 7))
8413    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8414               (set (match_dup 0) (match_dup 4)))
8415    (cond_exec (match_dup 8)
8416               (set (match_dup 0) (not:SI (match_dup 5))))]
8417   "
8418   {
8419     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8420                                              operands[2], operands[3]);
8421     enum rtx_code rc = GET_CODE (operands[1]);
8423     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8424     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8425     if (mode == CCFPmode || mode == CCFPEmode)
8426       rc = reverse_condition_maybe_unordered (rc);
8427     else
8428       rc = reverse_condition (rc);
8430     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8431   }"
8434 (define_insn "*cond_move_not"
8435   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8436         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8437                           [(match_operand 3 "cc_register" "") (const_int 0)])
8438                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8439                          (not:SI
8440                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
8441   "TARGET_ARM"
8442   "@
8443    mvn%D4\\t%0, %2
8444    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8445   [(set_attr "conds" "use")
8446    (set_attr "length" "4,8")]
8449 ;; The next two patterns occur when an AND operation is followed by a
8450 ;; scc insn sequence 
8452 (define_insn "*sign_extract_onebit"
8453   [(set (match_operand:SI 0 "s_register_operand" "=r")
8454         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8455                          (const_int 1)
8456                          (match_operand:SI 2 "const_int_operand" "n")))
8457     (clobber (reg:CC CC_REGNUM))]
8458   "TARGET_ARM"
8459   "*
8460     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8461     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8462     return \"mvnne\\t%0, #0\";
8463   "
8464   [(set_attr "conds" "clob")
8465    (set_attr "length" "8")]
8468 (define_insn "*not_signextract_onebit"
8469   [(set (match_operand:SI 0 "s_register_operand" "=r")
8470         (not:SI
8471          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8472                           (const_int 1)
8473                           (match_operand:SI 2 "const_int_operand" "n"))))
8474    (clobber (reg:CC CC_REGNUM))]
8475   "TARGET_ARM"
8476   "*
8477     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8478     output_asm_insn (\"tst\\t%1, %2\", operands);
8479     output_asm_insn (\"mvneq\\t%0, #0\", operands);
8480     return \"movne\\t%0, #0\";
8481   "
8482   [(set_attr "conds" "clob")
8483    (set_attr "length" "12")]
8486 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8487 ;; expressions.  For simplicity, the first register is also in the unspec
8488 ;; part.
8489 (define_insn "*push_multi"
8490   [(match_parallel 2 "multi_register_push"
8491     [(set (match_operand:BLK 0 "memory_operand" "=m")
8492           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8493                       UNSPEC_PUSH_MULT))])]
8494   "TARGET_ARM"
8495   "*
8496   {
8497     int num_saves = XVECLEN (operands[2], 0);
8498      
8499     /* For the StrongARM at least it is faster to
8500        use STR to store only a single register.  */
8501     if (num_saves == 1)
8502       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8503     else
8504       {
8505         int i;
8506         char pattern[100];
8508         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8510         for (i = 1; i < num_saves; i++)
8511           {
8512             strcat (pattern, \", %|\");
8513             strcat (pattern,
8514                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8515           }
8517         strcat (pattern, \"}\");
8518         output_asm_insn (pattern, operands);
8519       }
8521     return \"\";
8522   }"
8523   [(set_attr "type" "store4")]
8526 (define_insn "stack_tie"
8527   [(set (mem:BLK (scratch))
8528         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8529                      (match_operand:SI 1 "s_register_operand" "r")]
8530                     UNSPEC_PRLG_STK))]
8531   ""
8532   ""
8533   [(set_attr "length" "0")]
8536 ;; Similarly for the floating point registers
8537 (define_insn "*push_fp_multi"
8538   [(match_parallel 2 "multi_register_push"
8539     [(set (match_operand:BLK 0 "memory_operand" "=m")
8540           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8541                       UNSPEC_PUSH_MULT))])]
8542   "TARGET_ARM"
8543   "*
8544   {
8545     char pattern[100];
8547     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8548     output_asm_insn (pattern, operands);
8549     return \"\";
8550   }"
8551   [(set_attr "type" "f_store")]
8554 ;; Special patterns for dealing with the constant pool
8556 (define_insn "align_4"
8557   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8558   "TARGET_EITHER"
8559   "*
8560   assemble_align (32);
8561   return \"\";
8562   "
8565 (define_insn "consttable_end"
8566   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8567   "TARGET_EITHER"
8568   "*
8569   making_const_table = FALSE;
8570   return \"\";
8571   "
8574 (define_insn "consttable_1"
8575   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8576   "TARGET_THUMB"
8577   "*
8578   making_const_table = TRUE;
8579   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8580   assemble_zeros (3);
8581   return \"\";
8582   "
8583   [(set_attr "length" "4")]
8586 (define_insn "consttable_2"
8587   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8588   "TARGET_THUMB"
8589   "*
8590   making_const_table = TRUE;
8591   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8592   assemble_zeros (2);
8593   return \"\";
8594   "
8595   [(set_attr "length" "4")]
8598 (define_insn "consttable_4"
8599   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8600   "TARGET_EITHER"
8601   "*
8602   {
8603     making_const_table = TRUE;
8604     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8605       {
8606       case MODE_FLOAT:
8607       {
8608         REAL_VALUE_TYPE r;
8609         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8610         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8611         break;
8612       }
8613       default:
8614         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8615         break;
8616       }
8617     return \"\";
8618   }"
8619   [(set_attr "length" "4")]
8622 (define_insn "consttable_8"
8623   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8624   "TARGET_EITHER"
8625   "*
8626   {
8627     making_const_table = TRUE;
8628     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8629       {
8630        case MODE_FLOAT:
8631         {
8632           REAL_VALUE_TYPE r;
8633           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8634           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8635           break;
8636         }
8637       default:
8638         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8639         break;
8640       }
8641     return \"\";
8642   }"
8643   [(set_attr "length" "8")]
8646 ;; Miscellaneous Thumb patterns
8648 (define_expand "tablejump"
8649   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
8650               (use (label_ref (match_operand 1 "" "")))])]
8651   "TARGET_THUMB"
8652   "
8653   if (flag_pic)
8654     {
8655       /* Hopefully, CSE will eliminate this copy.  */
8656       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8657       rtx reg2 = gen_reg_rtx (SImode);
8659       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8660       operands[0] = reg2;
8661     }
8662   "
8665 (define_insn "*thumb_tablejump"
8666   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8667    (use (label_ref (match_operand 1 "" "")))]
8668   "TARGET_THUMB"
8669   "mov\\t%|pc, %0"
8670   [(set_attr "length" "2")]
8673 ;; V5 Instructions,
8675 (define_insn "clzsi2"
8676   [(set (match_operand:SI 0 "s_register_operand" "=r")
8677         (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8678   "TARGET_ARM && arm_arch5"
8679   "clz%?\\t%0, %1"
8680   [(set_attr "predicable" "yes")])
8682 (define_expand "ffssi2"
8683   [(set (match_operand:SI 0 "s_register_operand" "")
8684         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
8685   "TARGET_ARM && arm_arch5"
8686   "
8687   {
8688     rtx t1, t2, t3;
8690     t1 = gen_reg_rtx (SImode);
8691     t2 = gen_reg_rtx (SImode);
8692     t3 = gen_reg_rtx (SImode);
8694     emit_insn (gen_negsi2 (t1, operands[1]));
8695     emit_insn (gen_andsi3 (t2, operands[1], t1));
8696     emit_insn (gen_clzsi2 (t3, t2));
8697     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
8698     DONE;
8699   }"
8702 (define_expand "ctzsi2"
8703   [(set (match_operand:SI 0 "s_register_operand" "")
8704         (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
8705   "TARGET_ARM && arm_arch5"
8706   "
8707   {
8708     rtx t1, t2, t3;
8710     t1 = gen_reg_rtx (SImode);
8711     t2 = gen_reg_rtx (SImode);
8712     t3 = gen_reg_rtx (SImode);
8714     emit_insn (gen_negsi2 (t1, operands[1]));
8715     emit_insn (gen_andsi3 (t2, operands[1], t1));
8716     emit_insn (gen_clzsi2 (t3, t2));
8717     emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
8718     DONE;
8719   }"
8722 ;; V5E instructions.
8724 (define_insn "prefetch"
8725   [(prefetch (match_operand:SI 0 "address_operand" "p")
8726              (match_operand:SI 1 "" "")
8727              (match_operand:SI 2 "" ""))]
8728   "TARGET_ARM && arm_arch5e"
8729   "pld\\t%a0")
8731 ;; General predication pattern
8733 (define_cond_exec
8734   [(match_operator 0 "arm_comparison_operator"
8735     [(match_operand 1 "cc_register" "")
8736      (const_int 0)])]
8737   "TARGET_ARM"
8738   ""
8741 (define_insn "prologue_use"
8742   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
8743   ""
8744   "%@ %0 needed for prologue"
8747 ;; Load the FPA co-processor patterns
8748 (include "fpa.md")
8749 ;; Load the Maverick co-processor patterns
8750 (include "cirrus.md")