Fix bogons from XScale contribution
[official-gcc.git] / gcc / config / arm / arm.md
blob5e5262563c2d7d8d191ce00f4d4e32bf8aece9f4
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000
3 ;;  Free Software Foundation, Inc.
4 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;;  and Martin Simmons (@harleqn.co.uk).
6 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GNU CC.
10 ;; GNU CC is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
15 ;; GNU CC is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU CC; see the file COPYING.  If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
27 ;; There are patterns in this file to support XFmode arithmetic.
28 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
29 ;; (See arm.h)
31 ;; UNSPEC Usage:
32 ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
33 ;;   the mode is MODE_FLOAT
34 ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
35 ;;   the mode is MODE_FLOAT
36 ;; 2 `push multiple' operation: operand 0 is the first register.  Subsequent
37 ;;   registers are in parallel (use...) expressions.
38 ;; 3 A symbol that has been treated properly for pic usage, that is, we
39 ;;   will add the pic_register value to it before trying to dereference it.
40 ;; Note: sin and cos are no-longer used.
42 ;; UNSPEC_VOLATILE Usage:
43 ;; 0 `blockage' insn to prevent scheduling across an insn in the code.
44 ;; 1 `epilogue' insn, used to represent any part of the instruction epilogue
45 ;;   sequence that isn't expanded into normal RTL.  Used for both normal
46 ;;   and sibcall epilogues.
47 ;; 2 `align' insn.  Used at the head of a minipool table for inlined 
48 ;;   constants.
49 ;; 3 `end-of-table'.  Used to mark the end of a minipool table.
50 ;; 4 `pool-entry(1)'.  An entry in the constant pool for an 8-bit object.
51 ;; 5 `pool-entry(2)'.  An entry in the constant pool for a 16-bit object.
52 ;; 6 `pool-entry(4)'.  An entry in the constant pool for a 32-bit object.
53 ;; 7 `pool-entry(8)'.  An entry in the constant pool for a 64-bit object.
56 ;; Attributes
58 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
59 ; generating ARM code.  This is used to control the length of some insn
60 ; patterns that share the same RTL in both ARM and Thumb code.
61 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
63 ; PROG_MODE attribute is used to determine whether condition codes are
64 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
65 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
66 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
68 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
69 ; scheduling decisions for the load unit and the multiplier.
70 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
72 ;; Operand number of an input operand that is shifted.  Zero if the
73 ;; given instruction does not shift one of its input operands.
74 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
75 (define_attr "shift" "" (const_int 0))
77 ; Floating Point Unit.  If we only have floating point emulation, then there
78 ; is no point in scheduling the floating point insns.  (Well, for best
79 ; performance we should try and group them together).
80 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
82 ; LENGTH of an instruction (in bytes)
83 (define_attr "length" "" (const_int 4))
85 ; POOL_RANGE is how far away from a constant pool entry that this insn
86 ; can be placed.  If the distance is zero, then this insn will never
87 ; reference the pool.
88 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
89 ; before its address.
90 (define_attr "pool_range" "" (const_int 0))
91 (define_attr "neg_pool_range" "" (const_int 0))
93 ; An assembler sequence may clobber the condition codes without us knowing.
94 (define_asm_attributes
95  [(set_attr "conds" "clob")])
97 ; TYPE attribute is used to detect floating point instructions which, if
98 ; running on a co-processor can run in parallel with other, basic instructions
99 ; If write-buffer scheduling is enabled then it can also be used in the
100 ; scheduling of writes.
102 ; Classification of each insn
103 ; normal        any data instruction that doesn't hit memory or fp regs
104 ; mult          a multiply instruction
105 ; block         blockage insn, this blocks all functional units
106 ; float         a floating point arithmetic operation (subject to expansion)
107 ; fdivx         XFmode floating point division
108 ; fdivd         DFmode floating point division
109 ; fdivs         SFmode floating point division
110 ; fmul          Floating point multiply
111 ; ffmul         Fast floating point multiply
112 ; farith        Floating point arithmetic (4 cycle)
113 ; ffarith       Fast floating point arithmetic (2 cycle)
114 ; float_em      a floating point arithmetic operation that is normally emulated
115 ;               even on a machine with an fpa.
116 ; f_load        a floating point load from memory
117 ; f_store       a floating point store to memory
118 ; f_mem_r       a transfer of a floating point register to a real reg via mem
119 ; r_mem_f       the reverse of f_mem_r
120 ; f_2_r         fast transfer float to arm (no memory needed)
121 ; r_2_f         fast transfer arm to float
122 ; call          a subroutine call
123 ; load          any load from memory
124 ; store1        store 1 word to memory from arm registers
125 ; store2        store 2 words
126 ; store3        store 3 words
127 ; store4        store 4 words
129 (define_attr "type"
130         "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" 
131         (const_string "normal"))
133 ; Load scheduling, set from the arm_ld_sched variable
134 ; initialised by arm_override_options() 
135 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
137 ; condition codes: this one is used by final_prescan_insn to speed up
138 ; conditionalizing instructions.  It saves having to scan the rtl to see if
139 ; it uses or alters the condition codes.
141 ; USE means that the condition codes are used by the insn in the process of
142 ;   outputting code, this means (at present) that we can't use the insn in
143 ;   inlined branches
145 ; SET means that the purpose of the insn is to set the condition codes in a
146 ;   well defined manner.
148 ; CLOB means that the condition codes are altered in an undefined manner, if
149 ;   they are altered at all
151 ; JUMP_CLOB is used when the condition cannot be represented by a single
152 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
154 ; NOCOND means that the condition codes are neither altered nor affect the
155 ;   output of this insn
157 (define_attr "conds" "use,set,clob,jump_clob,nocond"
158         (if_then_else (eq_attr "type" "call")
159          (if_then_else (eq_attr "prog_mode" "prog32")
160           (const_string "clob") (const_string "nocond"))
161          (const_string "nocond")))
163 ; Predicable means that the insn can be conditionally executed based on
164 ; an automatically added predicate (additional patterns are generated by 
165 ; gen...).  We default to 'no' because no Thumb patterns match this rule
166 ; and not all ARM patterns do.
167 (define_attr "predicable" "no,yes" (const_string "no"))
169 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
170 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
171 ; suffer blockages enough to warrent modelling this (and it can adversely
172 ; affect the schedule).
173 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
175 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
176 ; to stall the processor.  Used with model_wbuf above.
177 (define_attr "write_conflict" "no,yes"
178   (if_then_else (eq_attr "type"
179                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
180                 (const_string "yes")
181                 (const_string "no")))
183 ; Classify the insns into those that take one cycle and those that take more
184 ; than one on the main cpu execution unit.
185 (define_attr "core_cycles" "single,multi"
186   (if_then_else (eq_attr "type"
187                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
188                 (const_string "single")
189                 (const_string "multi")))
191 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
192 ;; distant label.  Only applicable to Thumb code.
193 (define_attr "far_jump" "yes,no" (const_string "no"))
195 ;; (define_function_unit {name} {num-units} {n-users} {test}
196 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
198 ;;--------------------------------------------------------------------
199 ;; Floating point unit (FPA)
200 ;;--------------------------------------------------------------------
201 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
202                                      (eq_attr "type" "fdivx")) 71 69)
204 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
205                                      (eq_attr "type" "fdivd")) 59 57)
207 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
208                                      (eq_attr "type" "fdivs")) 31 29)
210 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
211                                      (eq_attr "type" "fmul")) 9 7)
213 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
214                                      (eq_attr "type" "ffmul")) 6 4)
216 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
217                                      (eq_attr "type" "farith")) 4 2)
219 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
220                                      (eq_attr "type" "ffarith")) 2 2)
222 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
223                                      (eq_attr "type" "r_2_f")) 5 3)
225 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
226                                      (eq_attr "type" "f_2_r")) 1 2)
228 ; The fpa10 doesn't really have a memory read unit, but it can start to
229 ; speculatively execute the instruction in the pipeline, provided the data
230 ; is already loaded, so pretend reads have a delay of 2 (and that the
231 ; pipeline is infinite).
233 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
234                                          (eq_attr "type" "f_load")) 3 1)
236 ;;--------------------------------------------------------------------
237 ;; Write buffer
238 ;;--------------------------------------------------------------------
239 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
241 ; The write buffer on some of the arm6 processors is hard to model exactly.
242 ; There is room in the buffer for up to two addresses and up to eight words
243 ; of memory, but the two needn't be split evenly.  When writing the two
244 ; addresses are fully pipelined.  However, a read from memory that is not
245 ; currently in the cache will block until the writes have completed.
246 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
247 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
248 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
249 ; cycle to add as well.
251 (define_function_unit "write_buf" 1 2
252   (and (eq_attr "model_wbuf" "yes")
253        (eq_attr "type" "store1,r_mem_f")) 5 3)
254 (define_function_unit "write_buf" 1 2 
255   (and (eq_attr "model_wbuf" "yes")
256        (eq_attr "type" "store2")) 7 4)
257 (define_function_unit "write_buf" 1 2
258   (and (eq_attr "model_wbuf" "yes")
259        (eq_attr "type" "store3")) 9 5)
260 (define_function_unit "write_buf" 1 2
261   (and (eq_attr "model_wbuf" "yes")
262        (eq_attr "type" "store4")) 11 6)
264 ;;--------------------------------------------------------------------
265 ;; Write blockage unit
266 ;;--------------------------------------------------------------------
267 ; The write_blockage unit models (partially), the fact that reads will stall
268 ; until the write buffer empties.
269 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
270 ; so we don't model them here
271 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
272                                                 (eq_attr "type" "store1")) 5 5
273         [(eq_attr "write_conflict" "yes")])
274 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
275                                                 (eq_attr "type" "store2")) 7 7
276         [(eq_attr "write_conflict" "yes")])
277 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
278                                                 (eq_attr "type" "store3")) 9 9
279         [(eq_attr "write_conflict" "yes")])
280 (define_function_unit "write_blockage" 1 0
281         (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
282         [(eq_attr "write_conflict" "yes")])
283 (define_function_unit "write_blockage" 1 0
284         (and (eq_attr "model_wbuf" "yes")
285              (eq_attr "write_conflict" "yes")) 1 1)
287 ;;--------------------------------------------------------------------
288 ;; Core unit
289 ;;--------------------------------------------------------------------
290 ; Everything must spend at least one cycle in the core unit
291 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
293 (define_function_unit "core" 1 0
294   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
296 (define_function_unit "core" 1 0
297   (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
299 ;; We do not need to conditionalize the define_function_unit immediately
300 ;; above.  This one will be ignored for anything other than xscale
301 ;; compiles and for xscale compiles it provides a larger delay
302 ;; and the scheduler will DTRT.
303 ;; FIXME: this test needs to be revamped to not depend on this feature 
304 ;; of the scheduler.
306 (define_function_unit "core" 1 0
307   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
308        (eq_attr "is_xscale" "yes"))
309    3 1)
311 (define_function_unit "core" 1 0
312   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
314 (define_function_unit "core" 1 0
315   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
317 (define_function_unit "core" 1 0
318   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
320 (define_function_unit "core" 1 0
321   (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
323 (define_function_unit "core" 1 0
324   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
326 (define_function_unit "core" 1 0
327   (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
329 (define_function_unit "core" 1 0
330   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
331        (eq_attr "type" "mult")) 4 4)
333 (define_function_unit "core" 1 0
334   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
335        (eq_attr "type" "mult")) 3 2)
337 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
339 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
341 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
343 (define_function_unit "core" 1 0
344   (and (eq_attr "core_cycles" "multi")
345        (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
347 ;;---------------------------------------------------------------------------
348 ;; Make code more maintainable by using names for fixed registers.
350 (define_constants
351   [(LR_REGNUM       14)
352    (LAST_ARM_REGNUM 15)
353    (CC_REGNUM       24)]
356 ;; Addition insns.
358 ;; Note: For DImode insns, there is normally no reason why operands should
359 ;; not be in the same register, what we don't want is for something being
360 ;; written to partially overlap something that is an input.
362 (define_expand "adddi3"
363  [(parallel
364    [(set (match_operand:DI           0 "s_register_operand" "")
365           (plus:DI (match_operand:DI 1 "s_register_operand" "")
366                    (match_operand:DI 2 "s_register_operand" "")))
367     (clobber (reg:CC CC_REGNUM))])]
368   "TARGET_EITHER"
369   "
370   if (TARGET_THUMB)
371     {
372       if (GET_CODE (operands[1]) != REG)
373         operands[1] = force_reg (SImode, operands[1]);
374       if (GET_CODE (operands[2]) != REG)
375         operands[2] = force_reg (SImode, operands[2]);
376      }
377   "
380 (define_insn "*thumb_adddi3"
381   [(set (match_operand:DI          0 "register_operand" "=l")
382         (plus:DI (match_operand:DI 1 "register_operand" "%0")
383                  (match_operand:DI 2 "register_operand" "l")))
384    (clobber (reg:CC CC_REGNUM))
385   ]
386   "TARGET_THUMB"
387   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
388   [(set_attr "length" "4")]
391 (define_insn_and_split "*arm_adddi3"
392   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
393         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
394                  (match_operand:DI 2 "s_register_operand" "r,  0")))
395    (clobber (reg:CC CC_REGNUM))]
396   "TARGET_ARM"
397   "#"
398   "TARGET_ARM && reload_completed"
399   [(parallel [(set (reg:CC_C CC_REGNUM)
400                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
401                                  (match_dup 1)))
402               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
403    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
404                                (plus:SI (match_dup 4) (match_dup 5))))]
405   "
406   {
407     operands[3] = gen_highpart (SImode, operands[0]);
408     operands[0] = gen_lowpart (SImode, operands[0]);
409     operands[4] = gen_highpart (SImode, operands[1]);
410     operands[1] = gen_lowpart (SImode, operands[1]);
411     operands[5] = gen_highpart (SImode, operands[2]);
412     operands[2] = gen_lowpart (SImode, operands[2]);
413   }"
414   [(set_attr "conds" "clob")
415    (set_attr "length" "8")]
418 (define_insn_and_split "*adddi_sesidi_di"
419   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
420         (plus:DI (sign_extend:DI
421                   (match_operand:SI 2 "s_register_operand" "r,r"))
422                  (match_operand:DI 1 "s_register_operand" "r,0")))
423    (clobber (reg:CC CC_REGNUM))]
424   "TARGET_ARM"
425   "#"
426   "TARGET_ARM && reload_completed"
427   [(parallel [(set (reg:CC_C CC_REGNUM)
428                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
429                                  (match_dup 1)))
430               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
431    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
432                                (plus:SI (ashiftrt:SI (match_dup 2)
433                                                      (const_int 31))
434                                         (match_dup 4))))]
435   "
436   {
437     operands[3] = gen_highpart (SImode, operands[0]);
438     operands[0] = gen_lowpart (SImode, operands[0]);
439     operands[4] = gen_highpart (SImode, operands[1]);
440     operands[1] = gen_lowpart (SImode, operands[1]);
441     operands[2] = gen_lowpart (SImode, operands[2]);
442   }"
443   [(set_attr "conds" "clob")
444    (set_attr "length" "8")]
447 (define_insn_and_split "*adddi_zesidi_di"
448   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
449         (plus:DI (zero_extend:DI
450                   (match_operand:SI 2 "s_register_operand" "r,r"))
451                  (match_operand:DI 1 "s_register_operand" "r,0")))
452    (clobber (reg:CC CC_REGNUM))]
453   "TARGET_ARM"
454   "#"
455   "TARGET_ARM && reload_completed"
456   [(parallel [(set (reg:CC_C CC_REGNUM)
457                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
458                                  (match_dup 1)))
459               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
460    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
461                                (plus:SI (match_dup 4) (const_int 0))))]
462   "
463   {
464     operands[3] = gen_highpart (SImode, operands[0]);
465     operands[0] = gen_lowpart (SImode, operands[0]);
466     operands[4] = gen_highpart (SImode, operands[1]);
467     operands[1] = gen_lowpart (SImode, operands[1]);
468     operands[2] = gen_lowpart (SImode, operands[2]);
469   }"
470   [(set_attr "conds" "clob")
471    (set_attr "length" "8")]
474 (define_expand "addsi3"
475   [(set (match_operand:SI          0 "s_register_operand" "")
476         (plus:SI (match_operand:SI 1 "s_register_operand" "")
477                  (match_operand:SI 2 "reg_or_int_operand" "")))]
478   "TARGET_EITHER"
479   "
480   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
481     {
482       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
483                           operands[1],
484                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
485       DONE;
486     }
487   "
490 ; If there is a scratch available, this will be faster than synthesising the
491 ; addition.
492 (define_peephole2
493   [(match_scratch:SI 3 "r")
494    (set (match_operand:SI          0 "s_register_operand" "")
495         (plus:SI (match_operand:SI 1 "s_register_operand" "")
496                  (match_operand:SI 2 "const_int_operand"  "")))]
497   "TARGET_ARM &&
498    !(const_ok_for_arm (INTVAL (operands[2]))
499      || const_ok_for_arm (-INTVAL (operands[2])))
500     && const_ok_for_arm (~INTVAL (operands[2]))"
501   [(set (match_dup 3) (match_dup 2))
502    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
503   ""
506 (define_insn_and_split "*arm_addsi3"
507   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
508         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
509                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
510   "TARGET_ARM"
511   "@
512    add%?\\t%0, %1, %2
513    sub%?\\t%0, %1, #%n2
514    #"
515   "TARGET_ARM &&
516    GET_CODE (operands[2]) == CONST_INT
517    && !(const_ok_for_arm (INTVAL (operands[2]))
518         || const_ok_for_arm (-INTVAL (operands[2])))"
519   [(clobber (const_int 0))]
520   "
521   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
522                       operands[1], 0);
523   DONE;
524   "
525   [(set_attr "length" "4,4,16")
526    (set_attr "predicable" "yes")]
529 ;; Register group 'k' is a single register group containing only the stack
530 ;; register.  Trying to reload it will always fail catastrophically,
531 ;; so never allow those alternatives to match if reloading is needed.
533 (define_insn "*thumb_addsi3"
534   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
535         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
536                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
537   "TARGET_THUMB"
538   "*
539    static const char * const asms[] = 
540    {
541      \"add\\t%0, %0, %2\",
542      \"sub\\t%0, %0, #%n2\",
543      \"add\\t%0, %1, %2\",
544      \"add\\t%0, %0, %2\",
545      \"add\\t%0, %0, %2\",
546      \"add\\t%0, %1, %2\",
547      \"add\\t%0, %1, %2\"
548    };
549    if ((which_alternative == 2 || which_alternative == 6)
550        && GET_CODE (operands[2]) == CONST_INT
551        && INTVAL (operands[2]) < 0)
552      return \"sub\\t%0, %1, #%n2\";
553    return asms[which_alternative];
554   "
555   [(set_attr "length" "2")]
558 ;; Reloading and elimination of the frame pointer can
559 ;; sometimes cause this optimization to be missed.
560 (define_peephole2
561   [(set (match_operand:SI 0 "register_operand" "=l")
562         (match_operand:SI 1 "const_int_operand" "M"))
563    (set (match_dup 0)
564         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
565   "TARGET_THUMB
566    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
567    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
568    && (INTVAL (operands[1]) & 3) == 0"
569   [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
570   ""
573 (define_insn "*addsi3_compare0"
574   [(set (reg:CC_NOOV CC_REGNUM)
575         (compare:CC_NOOV
576          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
577                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
578          (const_int 0)))
579    (set (match_operand:SI 0 "s_register_operand" "=r,r")
580         (plus:SI (match_dup 1) (match_dup 2)))]
581   "TARGET_ARM"
582   "@
583    add%?s\\t%0, %1, %2
584    sub%?s\\t%0, %1, #%n2"
585   [(set_attr "conds" "set")]
588 (define_insn "*addsi3_compare0_scratch"
589   [(set (reg:CC_NOOV CC_REGNUM)
590         (compare:CC_NOOV
591          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
592                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
593          (const_int 0)))]
594   "TARGET_ARM"
595   "@
596    cmn%?\\t%0, %1
597    cmp%?\\t%0, #%n1"
598   [(set_attr "conds" "set")]
601 ;; These patterns are the same ones as the two regular addsi3_compare0
602 ;; patterns, except we write them slightly different - the combiner
603 ;; tends to generate them this way.
604 (define_insn "*addsi3_compare0_for_combiner"
605   [(set (reg:CC CC_REGNUM)
606         (compare:CC
607          (match_operand:SI 1 "s_register_operand" "r,r")
608          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
609    (set (match_operand:SI 0 "s_register_operand" "=r,r")
610         (plus:SI (match_dup 1) (match_dup 2)))]
611   "TARGET_ARM"
612   "@
613    add%?s\\t%0, %1, %2
614    sub%?s\\t%0, %1, #%n2"
615   [(set_attr "conds" "set")]
618 (define_insn "*addsi3_compare0_scratch_for_combiner"
619   [(set (reg:CC CC_REGNUM)
620         (compare:CC
621          (match_operand:SI 0 "s_register_operand" "r,r")
622          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
623   "TARGET_ARM"
624   "@
625    cmn%?\\t%0, %1
626    cmp%?\\t%0, #%n1"
627   [(set_attr "conds" "set")]
630 ;; The next four insns work because they compare the result with one of
631 ;; the operands, and we know that the use of the condition code is
632 ;; either GEU or LTU, so we can use the carry flag from the addition
633 ;; instead of doing the compare a second time.
634 (define_insn "*addsi3_compare_op1"
635   [(set (reg:CC_C CC_REGNUM)
636         (compare:CC_C
637          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
638                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
639          (match_dup 1)))
640    (set (match_operand:SI 0 "s_register_operand" "=r,r")
641         (plus:SI (match_dup 1) (match_dup 2)))]
642   "TARGET_ARM"
643   "@
644    add%?s\\t%0, %1, %2
645    sub%?s\\t%0, %1, #%n2"
646   [(set_attr "conds" "set")]
649 (define_insn "*addsi3_compare_op2"
650   [(set (reg:CC_C CC_REGNUM)
651         (compare:CC_C
652          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
653                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
654          (match_dup 2)))
655    (set (match_operand:SI 0 "s_register_operand" "=r,r")
656         (plus:SI (match_dup 1) (match_dup 2)))]
657   "TARGET_ARM"
658   "@
659    add%?s\\t%0, %1, %2
660    sub%?s\\t%0, %1, #%n2"
661   [(set_attr "conds" "set")]
664 (define_insn "*compare_addsi2_op0"
665   [(set (reg:CC_C CC_REGNUM)
666         (compare:CC_C
667          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
668                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
669          (match_dup 0)))]
670   "TARGET_ARM"
671   "@
672    cmn%?\\t%0, %1
673    cmp%?\\t%0, #%n1"
674   [(set_attr "conds" "set")]
677 (define_insn "*compare_addsi2_op1"
678   [(set (reg:CC_C CC_REGNUM)
679         (compare:CC_C
680          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
681                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
682          (match_dup 1)))]
683   "TARGET_ARM"
684   "@
685    cmn%?\\t%0, %1
686    cmp%?\\t%0, #%n1"
687   [(set_attr "conds" "set")]
690 (define_insn "*addsi3_carryin"
691   [(set (match_operand:SI 0 "s_register_operand" "=r")
692         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
693                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
694                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
695   "TARGET_ARM"
696   "adc%?\\t%0, %1, %2"
697   [(set_attr "conds" "use")]
700 (define_insn "*addsi3_carryin_shift"
701   [(set (match_operand:SI 0 "s_register_operand" "")
702         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
703                  (plus:SI
704                    (match_operator:SI 2 "shift_operator"
705                       [(match_operand:SI 3 "s_register_operand" "")
706                        (match_operand:SI 4 "reg_or_int_operand" "")])
707                     (match_operand:SI 1 "s_register_operand" ""))))]
708   "TARGET_ARM"
709   "adc%?\\t%0, %1, %3%S2"
710   [(set_attr "conds" "use")]
713 (define_insn "*addsi3_carryin_alt1"
714   [(set (match_operand:SI 0 "s_register_operand" "=r")
715         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
716                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
717                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
718   "TARGET_ARM"
719   "adc%?\\t%0, %1, %2"
720   [(set_attr "conds" "use")]
723 (define_insn "*addsi3_carryin_alt2"
724   [(set (match_operand:SI 0 "s_register_operand" "=r")
725         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
726                           (match_operand:SI 1 "s_register_operand" "r"))
727                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
728   "TARGET_ARM"
729   "adc%?\\t%0, %1, %2"
730   [(set_attr "conds" "use")]
733 (define_insn "*addsi3_carryin_alt3"
734   [(set (match_operand:SI 0 "s_register_operand" "=r")
735         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
736                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
737                  (match_operand:SI 1 "s_register_operand" "r")))]
738   "TARGET_ARM"
739   "adc%?\\t%0, %1, %2"
740   [(set_attr "conds" "use")]
743 (define_insn "incscc"
744   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
745         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
746                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
747                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
748   "TARGET_ARM"
749   "@
750   add%d2\\t%0, %1, #1
751   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
752   [(set_attr "conds" "use")
753    (set_attr "length" "4,8")]
756 (define_insn "addsf3"
757   [(set (match_operand:SF          0 "s_register_operand" "=f,f")
758         (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
759                  (match_operand:SF 2 "fpu_add_operand"    "fG,H")))]
760   "TARGET_ARM && TARGET_HARD_FLOAT"
761   "@
762    adf%?s\\t%0, %1, %2
763    suf%?s\\t%0, %1, #%N2"
764   [(set_attr "type" "farith")
765    (set_attr "predicable" "yes")]
768 (define_insn "adddf3"
769   [(set (match_operand:DF          0 "s_register_operand" "=f,f")
770         (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
771                  (match_operand:DF 2 "fpu_add_operand"    "fG,H")))]
772   "TARGET_ARM && TARGET_HARD_FLOAT"
773   "@
774    adf%?d\\t%0, %1, %2
775    suf%?d\\t%0, %1, #%N2"
776   [(set_attr "type" "farith")
777    (set_attr "predicable" "yes")]
780 (define_insn "*adddf_esfdf_df"
781   [(set (match_operand:DF           0 "s_register_operand" "=f,f")
782         (plus:DF (float_extend:DF
783                   (match_operand:SF 1 "s_register_operand"  "f,f"))
784                  (match_operand:DF  2 "fpu_add_operand"    "fG,H")))]
785   "TARGET_ARM && TARGET_HARD_FLOAT"
786   "@
787    adf%?d\\t%0, %1, %2
788    suf%?d\\t%0, %1, #%N2"
789   [(set_attr "type" "farith")
790    (set_attr "predicable" "yes")]
793 (define_insn "*adddf_df_esfdf"
794   [(set (match_operand:DF           0 "s_register_operand" "=f")
795         (plus:DF (match_operand:DF  1 "s_register_operand"  "f")
796                  (float_extend:DF
797                   (match_operand:SF 2 "s_register_operand"  "f"))))]
798   "TARGET_ARM && TARGET_HARD_FLOAT"
799   "adf%?d\\t%0, %1, %2"
800   [(set_attr "type" "farith")
801    (set_attr "predicable" "yes")]
804 (define_insn "*adddf_esfdf_esfdf"
805   [(set (match_operand:DF           0 "s_register_operand" "=f")
806         (plus:DF (float_extend:DF 
807                   (match_operand:SF 1 "s_register_operand" "f"))
808                  (float_extend:DF
809                   (match_operand:SF 2 "s_register_operand" "f"))))]
810   "TARGET_ARM && TARGET_HARD_FLOAT"
811   "adf%?d\\t%0, %1, %2"
812   [(set_attr "type" "farith")
813    (set_attr "predicable" "yes")]
816 (define_insn "addxf3"
817   [(set (match_operand:XF          0 "s_register_operand" "=f,f")
818         (plus:XF (match_operand:XF 1 "s_register_operand"  "f,f")
819                  (match_operand:XF 2 "fpu_add_operand"    "fG,H")))]
820   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
821   "@
822    adf%?e\\t%0, %1, %2
823    suf%?e\\t%0, %1, #%N2"
824   [(set_attr "type" "farith")
825    (set_attr "predicable" "yes")]
828 (define_expand "subdi3"
829  [(parallel
830    [(set (match_operand:DI            0 "s_register_operand" "")
831           (minus:DI (match_operand:DI 1 "s_register_operand" "")
832                     (match_operand:DI 2 "s_register_operand" "")))
833     (clobber (reg:CC CC_REGNUM))])]
834   "TARGET_EITHER"
835   "
836   if (TARGET_THUMB)
837     {
838       if (GET_CODE (operands[1]) != REG)
839         operands[1] = force_reg (SImode, operands[1]);
840       if (GET_CODE (operands[2]) != REG)
841         operands[2] = force_reg (SImode, operands[2]);
842      }  
843   "
846 (define_insn "*arm_subdi3"
847   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
848         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
849                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
850    (clobber (reg:CC CC_REGNUM))]
851   "TARGET_ARM"
852   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
853   [(set_attr "conds" "clob")
854    (set_attr "length" "8")]
857 (define_insn "*thumb_subdi3"
858   [(set (match_operand:DI           0 "register_operand" "=l")
859         (minus:DI (match_operand:DI 1 "register_operand"  "0")
860                   (match_operand:DI 2 "register_operand"  "l")))
861    (clobber (reg:CC CC_REGNUM))]
862   "TARGET_THUMB"
863   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
864   [(set_attr "length" "4")]
867 (define_insn "*subdi_di_zesidi"
868   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
869         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
870                   (zero_extend:DI
871                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
872    (clobber (reg:CC CC_REGNUM))]
873   "TARGET_ARM"
874   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
875   [(set_attr "conds" "clob")
876    (set_attr "length" "8")]
879 (define_insn "*subdi_di_sesidi"
880   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
881         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
882                   (sign_extend:DI
883                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
884    (clobber (reg:CC CC_REGNUM))]
885   "TARGET_ARM"
886   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
887   [(set_attr "conds" "clob")
888    (set_attr "length" "8")]
891 (define_insn "*subdi_zesidi_di"
892   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
893         (minus:DI (zero_extend:DI
894                    (match_operand:SI 2 "s_register_operand"  "r,r"))
895                   (match_operand:DI  1 "s_register_operand" "?r,0")))
896    (clobber (reg:CC CC_REGNUM))]
897   "TARGET_ARM"
898   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
899   [(set_attr "conds" "clob")
900    (set_attr "length" "8")]
903 (define_insn "*subdi_sesidi_di"
904   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
905         (minus:DI (sign_extend:DI
906                    (match_operand:SI 2 "s_register_operand"   "r,r"))
907                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
908    (clobber (reg:CC CC_REGNUM))]
909   "TARGET_ARM"
910   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
911   [(set_attr "conds" "clob")
912    (set_attr "length" "8")]
915 (define_insn "*subdi_zesidi_zesidi"
916   [(set (match_operand:DI            0 "s_register_operand" "=r")
917         (minus:DI (zero_extend:DI
918                    (match_operand:SI 1 "s_register_operand"  "r"))
919                   (zero_extend:DI
920                    (match_operand:SI 2 "s_register_operand"  "r"))))
921    (clobber (reg:CC CC_REGNUM))]
922   "TARGET_ARM"
923   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
924   [(set_attr "conds" "clob")
925    (set_attr "length" "8")]
928 (define_expand "subsi3"
929   [(set (match_operand:SI           0 "s_register_operand" "")
930         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
931                   (match_operand:SI 2 "s_register_operand" "")))]
932   "TARGET_EITHER"
933   "
934   if (GET_CODE (operands[1]) == CONST_INT)
935     {
936       if (TARGET_ARM)
937         {
938           arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
939                               operands[2],
940                               (no_new_pseudos ? 0
941                                :  preserve_subexpressions_p ()));
942           DONE;
943         }
944       else /* TARGET_THUMB */
945         operands[1] = force_reg (SImode, operands[1]);
946     }
947   "
950 (define_insn "*thumb_subsi3_insn"
951   [(set (match_operand:SI           0 "register_operand" "=l")
952         (minus:SI (match_operand:SI 1 "register_operand" "l")
953                   (match_operand:SI 2 "register_operand" "l")))]
954   "TARGET_THUMB"
955   "sub\\t%0, %1, %2"
956   [(set_attr "length" "2")]
959 (define_insn_and_split "*arm_subsi3_insn"
960   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
961         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
962                   (match_operand:SI 2 "s_register_operand" "r,r")))]
963   "TARGET_ARM"
964   "@
965    rsb%?\\t%0, %2, %1
966    #"
967   "TARGET_ARM
968    && GET_CODE (operands[1]) == CONST_INT
969    && !const_ok_for_arm (INTVAL (operands[1]))"
970   [(clobber (const_int 0))]
971   "
972   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
973                       operands[2], 0);
974   DONE;
975   "
976   [(set_attr "length" "4,16")
977    (set_attr "predicable" "yes")]
980 (define_peephole2
981   [(match_scratch:SI 3 "r")
982    (set (match_operand:SI           0 "s_register_operand" "")
983         (minus:SI (match_operand:SI 1 "const_int_operand" "")
984                   (match_operand:SI 2 "s_register_operand" "")))]
985   "TARGET_ARM
986    && !const_ok_for_arm (INTVAL (operands[1]))
987    && const_ok_for_arm (~INTVAL (operands[1]))"
988   [(set (match_dup 3) (match_dup 1))
989    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
990   ""
993 (define_insn "*subsi3_compare0"
994   [(set (reg:CC_NOOV CC_REGNUM)
995         (compare:CC_NOOV
996          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
997                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
998          (const_int 0)))
999    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1000         (minus:SI (match_dup 1) (match_dup 2)))]
1001   "TARGET_ARM"
1002   "@
1003    sub%?s\\t%0, %1, %2
1004    rsb%?s\\t%0, %2, %1"
1005   [(set_attr "conds" "set")]
1008 (define_insn "decscc"
1009   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1010         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1011                   (match_operator:SI 2 "arm_comparison_operator"
1012                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1013   "TARGET_ARM"
1014   "@
1015    sub%d2\\t%0, %1, #1
1016    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1017   [(set_attr "conds" "use")
1018    (set_attr "length" "*,8")]
1021 (define_insn "subsf3"
1022   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1023         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1024                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1025   "TARGET_ARM && TARGET_HARD_FLOAT"
1026   "@
1027    suf%?s\\t%0, %1, %2
1028    rsf%?s\\t%0, %2, %1"
1029   [(set_attr "type" "farith")]
1032 (define_insn "subdf3"
1033   [(set (match_operand:DF           0 "s_register_operand" "=f,f")
1034         (minus:DF (match_operand:DF 1 "fpu_rhs_operand"     "f,G")
1035                   (match_operand:DF 2 "fpu_rhs_operand"    "fG,f")))]
1036   "TARGET_ARM && TARGET_HARD_FLOAT"
1037   "@
1038    suf%?d\\t%0, %1, %2
1039    rsf%?d\\t%0, %2, %1"
1040   [(set_attr "type" "farith")
1041    (set_attr "predicable" "yes")]
1044 (define_insn "*subdf_esfdf_df"
1045   [(set (match_operand:DF            0 "s_register_operand" "=f")
1046         (minus:DF (float_extend:DF
1047                    (match_operand:SF 1 "s_register_operand"  "f"))
1048                   (match_operand:DF  2 "fpu_rhs_operand"    "fG")))]
1049   "TARGET_ARM && TARGET_HARD_FLOAT"
1050   "suf%?d\\t%0, %1, %2"
1051   [(set_attr "type" "farith")
1052    (set_attr "predicable" "yes")]
1055 (define_insn "*subdf_df_esfdf"
1056   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1057         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1058                   (float_extend:DF
1059                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
1060   "TARGET_ARM && TARGET_HARD_FLOAT"
1061   "@
1062    suf%?d\\t%0, %1, %2
1063    rsf%?d\\t%0, %2, %1"
1064   [(set_attr "type" "farith")
1065    (set_attr "predicable" "yes")]
1068 (define_insn "*subdf_esfdf_esfdf"
1069   [(set (match_operand:DF 0 "s_register_operand" "=f")
1070         (minus:DF (float_extend:DF
1071                    (match_operand:SF 1 "s_register_operand" "f"))
1072                   (float_extend:DF
1073                    (match_operand:SF 2 "s_register_operand" "f"))))]
1074   "TARGET_ARM && TARGET_HARD_FLOAT"
1075   "suf%?d\\t%0, %1, %2"
1076   [(set_attr "type" "farith")
1077    (set_attr "predicable" "yes")]
1080 (define_insn "subxf3"
1081   [(set (match_operand:XF           0 "s_register_operand" "=f,f")
1082         (minus:XF (match_operand:XF 1 "fpu_rhs_operand"     "f,G")
1083                   (match_operand:XF 2 "fpu_rhs_operand"    "fG,f")))]
1084   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1085   "@
1086    suf%?e\\t%0, %1, %2
1087    rsf%?e\\t%0, %2, %1"
1088   [(set_attr "type" "farith")
1089    (set_attr "predicable" "yes")]
1092 ;; Multiplication insns
1094 (define_expand "mulsi3"
1095   [(set (match_operand:SI          0 "s_register_operand" "")
1096         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1097                  (match_operand:SI 1 "s_register_operand" "")))]
1098   "TARGET_EITHER"
1099   ""
1102 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1103 (define_insn "*arm_mulsi3"
1104   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1105         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1106                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1107   "TARGET_ARM"
1108   "mul%?\\t%0, %2, %1"
1109   [(set_attr "type" "mult")
1110    (set_attr "predicable" "yes")]
1113 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1114 ; 1 and 2; are the same, because reload will make operand 0 match 
1115 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1116 ; this by adding another alternative to match this case, and then `reload' 
1117 ; it ourselves.  This alternative must come first.
1118 (define_insn "*thumb_mulsi3"
1119   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1120         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1121                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1122   "TARGET_THUMB"
1123   "*
1124   if (which_alternative < 2)
1125     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1126   else
1127     return \"mul\\t%0, %0, %2\";
1128   "
1129   [(set_attr "length" "4,4,2")
1130    (set_attr "type" "mult")]
1133 (define_insn "*mulsi3_compare0"
1134   [(set (reg:CC_NOOV CC_REGNUM)
1135         (compare:CC_NOOV (mult:SI
1136                           (match_operand:SI 2 "s_register_operand" "r,r")
1137                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1138                          (const_int 0)))
1139    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1140         (mult:SI (match_dup 2) (match_dup 1)))]
1141   "TARGET_ARM && !arm_is_xscale"
1142   "mul%?s\\t%0, %2, %1"
1143   [(set_attr "conds" "set")
1144    (set_attr "type" "mult")]
1147 (define_insn "*mulsi_compare0_scratch"
1148   [(set (reg:CC_NOOV CC_REGNUM)
1149         (compare:CC_NOOV (mult:SI
1150                           (match_operand:SI 2 "s_register_operand" "r,r")
1151                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1152                          (const_int 0)))
1153    (clobber (match_scratch:SI 0 "=&r,&r"))]
1154   "TARGET_ARM && !arm_is_xscale"
1155   "mul%?s\\t%0, %2, %1"
1156   [(set_attr "conds" "set")
1157    (set_attr "type" "mult")]
1160 ;; Unnamed templates to match MLA instruction.
1162 (define_insn "*mulsi3addsi"
1163   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1164         (plus:SI
1165           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1166                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1167           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1168   "TARGET_ARM"
1169   "mla%?\\t%0, %2, %1, %3"
1170   [(set_attr "type" "mult")
1171    (set_attr "predicable" "yes")]
1174 (define_insn "*mulsi3addsi_compare0"
1175   [(set (reg:CC_NOOV CC_REGNUM)
1176         (compare:CC_NOOV
1177          (plus:SI (mult:SI
1178                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1179                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1180                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1181          (const_int 0)))
1182    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1183         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1184                  (match_dup 3)))]
1185   "TARGET_ARM && !arm_is_xscale"
1186   "mla%?s\\t%0, %2, %1, %3"
1187   [(set_attr "conds" "set")
1188    (set_attr "type" "mult")]
1191 (define_insn "*mulsi3addsi_compare0_scratch"
1192   [(set (reg:CC_NOOV CC_REGNUM)
1193         (compare:CC_NOOV
1194          (plus:SI (mult:SI
1195                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1196                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1197                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1198          (const_int 0)))
1199    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1200   "TARGET_ARM && !arm_is_xscale"
1201   "mla%?s\\t%0, %2, %1, %3"
1202   [(set_attr "conds" "set")
1203    (set_attr "type" "mult")]
1206 ;; Unnamed template to match long long multiply-accumlate (smlal)
1208 (define_insn "*mulsidi3adddi"
1209   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1210         (plus:DI
1211          (mult:DI
1212           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1213           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1214          (match_operand:DI 1 "s_register_operand" "0")))]
1215   "TARGET_ARM && arm_fast_multiply"
1216   "smlal%?\\t%Q0, %R0, %3, %2"
1217   [(set_attr "type" "mult")
1218    (set_attr "predicable" "yes")]
1221 (define_insn "mulsidi3"
1222   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1223         (mult:DI
1224          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1225          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1226   "TARGET_ARM && arm_fast_multiply"
1227   "smull%?\\t%Q0, %R0, %1, %2"
1228   [(set_attr "type" "mult")
1229    (set_attr "predicable" "yes")]
1232 (define_insn "umulsidi3"
1233   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1234         (mult:DI
1235          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1236          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1237   "TARGET_ARM && arm_fast_multiply"
1238   "umull%?\\t%Q0, %R0, %1, %2"
1239   [(set_attr "type" "mult")
1240    (set_attr "predicable" "yes")]
1243 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1245 (define_insn "*umulsidi3adddi"
1246   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1247         (plus:DI
1248          (mult:DI
1249           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1250           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1251          (match_operand:DI 1 "s_register_operand" "0")))]
1252   "TARGET_ARM && arm_fast_multiply"
1253   "umlal%?\\t%Q0, %R0, %3, %2"
1254   [(set_attr "type" "mult")
1255    (set_attr "predicable" "yes")]
1258 (define_insn "smulsi3_highpart"
1259   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1260         (truncate:SI
1261          (lshiftrt:DI
1262           (mult:DI
1263            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1264            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1265           (const_int 32))))
1266    (clobber (match_scratch:SI 3 "=&r,&r"))]
1267   "TARGET_ARM && arm_fast_multiply"
1268   "smull%?\\t%3, %0, %2, %1"
1269   [(set_attr "type" "mult")
1270    (set_attr "predicable" "yes")]
1273 (define_insn "umulsi3_highpart"
1274   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1275         (truncate:SI
1276          (lshiftrt:DI
1277           (mult:DI
1278            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1279            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1280           (const_int 32))))
1281    (clobber (match_scratch:SI 3 "=&r,&r"))]
1282   "TARGET_ARM && arm_fast_multiply"
1283   "umull%?\\t%3, %0, %2, %1"
1284   [(set_attr "type" "mult")
1285    (set_attr "predicable" "yes")]
1288 (define_insn "mulhisi3"
1289   [(set (match_operand:SI 0 "s_register_operand" "=r")
1290         (mult:SI (sign_extend:SI
1291                   (match_operand:HI 1 "s_register_operand" "%r"))
1292                  (sign_extend:SI
1293                   (match_operand:HI 2 "s_register_operand" "r"))))]
1294   "TARGET_ARM && arm_is_xscale"
1295   "smulbb%?\\t%0,%1,%2"
1296   [(set_attr "type" "mult")]
1299 (define_insn "*mulhisi3addsi"
1300   [(set (match_operand:SI 0 "s_register_operand" "=r")
1301         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1302                  (mult:SI (sign_extend:SI
1303                            (match_operand:HI 2 "s_register_operand" "%r"))
1304                           (sign_extend:SI
1305                            (match_operand:HI 3 "s_register_operand" "r")))))]
1306   "TARGET_ARM && arm_is_xscale"
1307   "smlabb%?\\t%0,%2,%3,%1"
1308   [(set_attr "type" "mult")]
1311 (define_insn "*mulhidi3adddi"
1312   [(set (match_operand:DI 0 "s_register_operand" "=r")
1313         (plus:DI
1314           (match_operand:DI 1 "s_register_operand" "0")
1315           (mult:DI (sign_extend:DI
1316                     (match_operand:HI 2 "s_register_operand" "%r"))
1317                    (sign_extend:DI
1318                     (match_operand:HI 3 "s_register_operand" "r")))))]
1319   "TARGET_ARM && arm_is_xscale"
1320   "smlalbb%?\\t%Q0, %R0, %2, %3"
1321 [(set_attr "type" "mult")])
1323 (define_insn "mulsf3"
1324   [(set (match_operand:SF 0 "s_register_operand" "=f")
1325         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1326                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1327   "TARGET_ARM && TARGET_HARD_FLOAT"
1328   "fml%?s\\t%0, %1, %2"
1329   [(set_attr "type" "ffmul")
1330    (set_attr "predicable" "yes")]
1333 (define_insn "muldf3"
1334   [(set (match_operand:DF 0 "s_register_operand" "=f")
1335         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1336                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1337   "TARGET_ARM && TARGET_HARD_FLOAT"
1338   "muf%?d\\t%0, %1, %2"
1339   [(set_attr "type" "fmul")
1340    (set_attr "predicable" "yes")]
1343 (define_insn "*muldf_esfdf_df"
1344   [(set (match_operand:DF 0 "s_register_operand" "=f")
1345         (mult:DF (float_extend:DF
1346                   (match_operand:SF 1 "s_register_operand" "f"))
1347                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1348   "TARGET_ARM && TARGET_HARD_FLOAT"
1349   "muf%?d\\t%0, %1, %2"
1350   [(set_attr "type" "fmul")
1351    (set_attr "predicable" "yes")]
1354 (define_insn "*muldf_df_esfdf"
1355   [(set (match_operand:DF 0 "s_register_operand" "=f")
1356         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1357                  (float_extend:DF
1358                   (match_operand:SF 2 "s_register_operand" "f"))))]
1359   "TARGET_ARM && TARGET_HARD_FLOAT"
1360   "muf%?d\\t%0, %1, %2"
1361   [(set_attr "type" "fmul")
1362    (set_attr "predicable" "yes")]
1365 (define_insn "*muldf_esfdf_esfdf"
1366   [(set (match_operand:DF 0 "s_register_operand" "=f")
1367         (mult:DF
1368          (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1369          (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1370   "TARGET_ARM && TARGET_HARD_FLOAT"
1371   "muf%?d\\t%0, %1, %2"
1372   [(set_attr "type" "fmul")
1373    (set_attr "predicable" "yes")]
1376 (define_insn "mulxf3"
1377   [(set (match_operand:XF 0 "s_register_operand" "=f")
1378         (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1379                  (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1380   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1381   "muf%?e\\t%0, %1, %2"
1382   [(set_attr "type" "fmul")
1383    (set_attr "predicable" "yes")]
1386 ;; Division insns
1388 (define_insn "divsf3"
1389   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1390         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1391                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1392   "TARGET_ARM && TARGET_HARD_FLOAT"
1393   "@
1394    fdv%?s\\t%0, %1, %2
1395    frd%?s\\t%0, %2, %1"
1396   [(set_attr "type" "fdivs")
1397    (set_attr "predicable" "yes")]
1400 (define_insn "divdf3"
1401   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1402         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1403                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1404   "TARGET_ARM && TARGET_HARD_FLOAT"
1405   "@
1406    dvf%?d\\t%0, %1, %2
1407    rdf%?d\\t%0, %2, %1"
1408   [(set_attr "type" "fdivd")
1409    (set_attr "predicable" "yes")]
1412 (define_insn "*divdf_esfdf_df"
1413   [(set (match_operand:DF 0 "s_register_operand" "=f")
1414         (div:DF (float_extend:DF
1415                  (match_operand:SF 1 "s_register_operand" "f"))
1416                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1417   "TARGET_ARM && TARGET_HARD_FLOAT"
1418   "dvf%?d\\t%0, %1, %2"
1419   [(set_attr "type" "fdivd")
1420    (set_attr "predicable" "yes")]
1423 (define_insn "*divdf_df_esfdf"
1424   [(set (match_operand:DF 0 "s_register_operand" "=f")
1425         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1426                 (float_extend:DF
1427                  (match_operand:SF 2 "s_register_operand" "f"))))]
1428   "TARGET_ARM && TARGET_HARD_FLOAT"
1429   "rdf%?d\\t%0, %2, %1"
1430   [(set_attr "type" "fdivd")
1431    (set_attr "predicable" "yes")]
1434 (define_insn "*divdf_esfdf_esfdf"
1435   [(set (match_operand:DF 0 "s_register_operand" "=f")
1436         (div:DF (float_extend:DF
1437                  (match_operand:SF 1 "s_register_operand" "f"))
1438                 (float_extend:DF
1439                  (match_operand:SF 2 "s_register_operand" "f"))))]
1440   "TARGET_ARM && TARGET_HARD_FLOAT"
1441   "dvf%?d\\t%0, %1, %2"
1442   [(set_attr "type" "fdivd")
1443    (set_attr "predicable" "yes")]
1446 (define_insn "divxf3"
1447   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1448         (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1449                 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1450   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1451   "@
1452    dvf%?e\\t%0, %1, %2
1453    rdf%?e\\t%0, %2, %1"
1454   [(set_attr "type" "fdivx")
1455    (set_attr "predicable" "yes")]
1458 ;; Modulo insns
1460 (define_insn "modsf3"
1461   [(set (match_operand:SF 0 "s_register_operand" "=f")
1462         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1463                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1464   "TARGET_ARM && TARGET_HARD_FLOAT"
1465   "rmf%?s\\t%0, %1, %2"
1466   [(set_attr "type" "fdivs")
1467    (set_attr "predicable" "yes")]
1470 (define_insn "moddf3"
1471   [(set (match_operand:DF 0 "s_register_operand" "=f")
1472         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1473                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1474   "TARGET_ARM && TARGET_HARD_FLOAT"
1475   "rmf%?d\\t%0, %1, %2"
1476   [(set_attr "type" "fdivd")
1477    (set_attr "predicable" "yes")]
1480 (define_insn "*moddf_esfdf_df"
1481   [(set (match_operand:DF 0 "s_register_operand" "=f")
1482         (mod:DF (float_extend:DF
1483                  (match_operand:SF 1 "s_register_operand" "f"))
1484                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1485   "TARGET_ARM && TARGET_HARD_FLOAT"
1486   "rmf%?d\\t%0, %1, %2"
1487   [(set_attr "type" "fdivd")
1488    (set_attr "predicable" "yes")]
1491 (define_insn "*moddf_df_esfdf"
1492   [(set (match_operand:DF 0 "s_register_operand" "=f")
1493         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1494                 (float_extend:DF
1495                  (match_operand:SF 2 "s_register_operand" "f"))))]
1496   "TARGET_ARM && TARGET_HARD_FLOAT"
1497   "rmf%?d\\t%0, %1, %2"
1498   [(set_attr "type" "fdivd")
1499    (set_attr "predicable" "yes")]
1502 (define_insn "*moddf_esfdf_esfdf"
1503   [(set (match_operand:DF 0 "s_register_operand" "=f")
1504         (mod:DF (float_extend:DF
1505                  (match_operand:SF 1 "s_register_operand" "f"))
1506                 (float_extend:DF
1507                  (match_operand:SF 2 "s_register_operand" "f"))))]
1508   "TARGET_ARM && TARGET_HARD_FLOAT"
1509   "rmf%?d\\t%0, %1, %2"
1510   [(set_attr "type" "fdivd")
1511    (set_attr "predicable" "yes")]
1514 (define_insn "modxf3"
1515   [(set (match_operand:XF 0 "s_register_operand" "=f")
1516         (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1517                 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1518   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1519   "rmf%?e\\t%0, %1, %2"
1520   [(set_attr "type" "fdivx")
1521    (set_attr "predicable" "yes")]
1524 ;; Boolean and,ior,xor insns
1526 ;; Split up double word logical operations
1528 ;; Split up simple DImode logical operations.  Simply perform the logical
1529 ;; operation on the upper and lower halves of the registers.
1530 (define_split
1531   [(set (match_operand:DI 0 "s_register_operand" "")
1532         (match_operator:DI 6 "logical_binary_operator"
1533           [(match_operand:DI 1 "s_register_operand" "")
1534            (match_operand:DI 2 "s_register_operand" "")]))]
1535   "TARGET_ARM && reload_completed"
1536   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1537    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1538   "
1539   {
1540     operands[3] = gen_highpart (SImode, operands[0]);
1541     operands[0] = gen_lowpart (SImode, operands[0]);
1542     operands[4] = gen_highpart (SImode, operands[1]);
1543     operands[1] = gen_lowpart (SImode, operands[1]);
1544     operands[5] = gen_highpart (SImode, operands[2]);
1545     operands[2] = gen_lowpart (SImode, operands[2]);
1546   }"
1549 (define_split
1550   [(set (match_operand:DI 0 "s_register_operand" "")
1551         (match_operator:DI 6 "logical_binary_operator"
1552           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1553            (match_operand:DI 1 "s_register_operand" "")]))]
1554   "TARGET_ARM && reload_completed"
1555   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1556    (set (match_dup 3) (match_op_dup:SI 6
1557                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1558                          (match_dup 4)]))]
1559   "
1560   {
1561     operands[3] = gen_highpart (SImode, operands[0]);
1562     operands[0] = gen_lowpart (SImode, operands[0]);
1563     operands[4] = gen_highpart (SImode, operands[1]);
1564     operands[1] = gen_lowpart (SImode, operands[1]);
1565     operands[5] = gen_highpart (SImode, operands[2]);
1566     operands[2] = gen_lowpart (SImode, operands[2]);
1567   }"
1570 ;; The zero extend of operand 2 means we can just copy the high part of
1571 ;; operand1 into operand0.
1572 (define_split
1573   [(set (match_operand:DI 0 "s_register_operand" "")
1574         (ior:DI
1575           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1576           (match_operand:DI 1 "s_register_operand" "")))]
1577   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1578   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1579    (set (match_dup 3) (match_dup 4))]
1580   "
1581   {
1582     operands[4] = gen_highpart (SImode, operands[1]);
1583     operands[3] = gen_highpart (SImode, operands[0]);
1584     operands[0] = gen_lowpart (SImode, operands[0]);
1585     operands[1] = gen_lowpart (SImode, operands[1]);
1586   }"
1589 ;; The zero extend of operand 2 means we can just copy the high part of
1590 ;; operand1 into operand0.
1591 (define_split
1592   [(set (match_operand:DI 0 "s_register_operand" "")
1593         (xor:DI
1594           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1595           (match_operand:DI 1 "s_register_operand" "")))]
1596   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1597   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1598    (set (match_dup 3) (match_dup 4))]
1599   "
1600   {
1601     operands[4] = gen_highpart (SImode, operands[1]);
1602     operands[3] = gen_highpart (SImode, operands[0]);
1603     operands[0] = gen_lowpart (SImode, operands[0]);
1604     operands[1] = gen_lowpart (SImode, operands[1]);
1605   }"
1608 (define_insn "anddi3"
1609   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1610         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1611                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1612   "TARGET_ARM"
1613   "#"
1614   [(set_attr "length" "8")]
1617 (define_insn_and_split "*anddi_zesidi_di"
1618   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1619         (and:DI (zero_extend:DI
1620                  (match_operand:SI 2 "s_register_operand" "r,r"))
1621                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1622   "TARGET_ARM"
1623   "#"
1624   "TARGET_ARM && reload_completed"
1625   ; The zero extend of operand 2 clears the high word of the output
1626   ; operand.
1627   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1628    (set (match_dup 3) (const_int 0))]
1629   "
1630   {
1631     operands[3] = gen_highpart (SImode, operands[0]);
1632     operands[0] = gen_lowpart (SImode, operands[0]);
1633     operands[1] = gen_lowpart (SImode, operands[1]);
1634   }"
1635   [(set_attr "length" "8")]
1638 (define_insn "*anddi_sesdi_di"
1639   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1640         (and:DI (sign_extend:DI
1641                  (match_operand:SI 2 "s_register_operand" "r,r"))
1642                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1643   "TARGET_ARM"
1644   "#"
1645   [(set_attr "length" "8")]
1648 (define_expand "andsi3"
1649   [(set (match_operand:SI         0 "s_register_operand" "")
1650         (and:SI (match_operand:SI 1 "s_register_operand" "")
1651                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1652   "TARGET_EITHER"
1653   "
1654   if (TARGET_ARM)
1655     {
1656       if (GET_CODE (operands[2]) == CONST_INT)
1657         {
1658           arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1659                               operands[1],
1660                               (no_new_pseudos
1661                                ? 0 : preserve_subexpressions_p ()));
1662           DONE;
1663         }
1664     }
1665   else /* TARGET_THUMB */
1666     {
1667       if (GET_CODE (operands[2]) != CONST_INT)
1668         operands[2] = force_reg (SImode, operands[2]);
1669       else
1670         {
1671           int i;
1672           
1673           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1674             {
1675               operands[2] = force_reg (SImode,
1676                                        GEN_INT (~INTVAL (operands[2])));
1677               
1678               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1679               
1680               DONE;
1681             }
1683           for (i = 9; i <= 31; i++)
1684             {
1685               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1686                 {
1687                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1688                                         const0_rtx));
1689                   DONE;
1690                 }
1691               else if ((((HOST_WIDE_INT) 1) << i) - 1
1692                        == ~INTVAL (operands[2]))
1693                 {
1694                   rtx shift = GEN_INT (i);
1695                   rtx reg = gen_reg_rtx (SImode);
1696                 
1697                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1698                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1699                   
1700                   DONE;
1701                 }
1702             }
1704           operands[2] = force_reg (SImode, operands[2]);
1705         }
1706     }
1707   "
1710 (define_insn_and_split "*arm_andsi3_insn"
1711   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1712         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1713                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1714   "TARGET_ARM"
1715   "@
1716    and%?\\t%0, %1, %2
1717    bic%?\\t%0, %1, #%B2
1718    #"
1719   "TARGET_ARM
1720    && GET_CODE (operands[2]) == CONST_INT
1721    && !(const_ok_for_arm (INTVAL (operands[2]))
1722         || const_ok_for_arm (~INTVAL (operands[2])))"
1723   [(clobber (const_int 0))]
1724   "
1725   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1726                        operands[1], 0);
1727   DONE;
1728   "
1729   [(set_attr "length" "4,4,16")
1730    (set_attr "predicable" "yes")]
1733 (define_insn "*thumb_andsi3_insn"
1734   [(set (match_operand:SI         0 "register_operand" "=l")
1735         (and:SI (match_operand:SI 1 "register_operand" "%0")
1736                 (match_operand:SI 2 "register_operand" "l")))]
1737   "TARGET_THUMB"
1738   "and\\t%0, %0, %2"
1739   [(set_attr "length" "2")]
1742 (define_insn "*andsi3_compare0"
1743   [(set (reg:CC_NOOV CC_REGNUM)
1744         (compare:CC_NOOV
1745          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1746                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1747          (const_int 0)))
1748    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1749         (and:SI (match_dup 1) (match_dup 2)))]
1750   "TARGET_ARM"
1751   "@
1752    and%?s\\t%0, %1, %2
1753    bic%?s\\t%0, %1, #%B2"
1754   [(set_attr "conds" "set")]
1757 (define_insn "*andsi3_compare0_scratch"
1758   [(set (reg:CC_NOOV CC_REGNUM)
1759         (compare:CC_NOOV
1760          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1761                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1762          (const_int 0)))
1763    (clobber (match_scratch:SI 2 "=X,r"))]
1764   "TARGET_ARM"
1765   "@
1766    tst%?\\t%0, %1
1767    bic%?s\\t%2, %0, #%B1"
1768   [(set_attr "conds" "set")]
1771 (define_insn "*zeroextractsi_compare0_scratch"
1772   [(set (reg:CC_NOOV CC_REGNUM)
1773         (compare:CC_NOOV (zero_extract:SI
1774                           (match_operand:SI 0 "s_register_operand" "r")
1775                           (match_operand 1 "const_int_operand" "n")
1776                           (match_operand 2 "const_int_operand" "n"))
1777                          (const_int 0)))]
1778   "TARGET_ARM
1779   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1780       && INTVAL (operands[1]) > 0 
1781       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1782       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1783   "*
1784   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1785                          << INTVAL (operands[2]));
1786   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1787   return \"\";
1788   "
1789   [(set_attr "conds" "set")]
1792 (define_insn "*ne_zeroextractsi"
1793   [(set (match_operand:SI 0 "s_register_operand" "=r")
1794         (ne:SI (zero_extract:SI
1795                 (match_operand:SI 1 "s_register_operand" "r")
1796                 (match_operand:SI 2 "const_int_operand" "n")
1797                 (match_operand:SI 3 "const_int_operand" "n"))
1798                (const_int 0)))]
1799   "TARGET_ARM
1800    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1801        && INTVAL (operands[2]) > 0 
1802        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1803        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1804   "*
1805   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1806                          << INTVAL (operands[3]));
1807   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1808   return \"movne\\t%0, #1\";
1809   "
1810   [(set_attr "conds" "clob")
1811    (set_attr "length" "8")]
1814 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1815 ;;; represented by the bitfield, then this will produce incorrect results.
1816 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1817 ;;; which have a real bitfield insert instruction, the truncation happens
1818 ;;; in the bitfield insert instruction itself.  Since arm does not have a
1819 ;;; bitfield insert instruction, we would have to emit code here to truncate
1820 ;;; the value before we insert.  This loses some of the advantage of having
1821 ;;; this insv pattern, so this pattern needs to be reevalutated.
1823 (define_expand "insv"
1824   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1825                          (match_operand:SI 1 "general_operand" "")
1826                          (match_operand:SI 2 "general_operand" ""))
1827         (match_operand:SI 3 "nonmemory_operand" ""))]
1828   "TARGET_ARM"
1829   "
1830   {
1831     int start_bit = INTVAL (operands[2]);
1832     int width = INTVAL (operands[1]);
1833     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1834     rtx target, subtarget;
1836     target = operands[0];
1837     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1838        subreg as the final target.  */
1839     if (GET_CODE (target) == SUBREG)
1840       {
1841         subtarget = gen_reg_rtx (SImode);
1842         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1843             < GET_MODE_SIZE (SImode))
1844           target = SUBREG_REG (target);
1845       }
1846     else
1847       subtarget = target;    
1849     if (GET_CODE (operands[3]) == CONST_INT)
1850       {
1851         /* Since we are inserting a known constant, we may be able to
1852            reduce the number of bits that we have to clear so that
1853            the mask becomes simple.  */
1854         /* ??? This code does not check to see if the new mask is actually
1855            simpler.  It may not be.  */
1856         rtx op1 = gen_reg_rtx (SImode);
1857         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1858            start of this pattern.  */
1859         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1860         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1862         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1863         emit_insn (gen_iorsi3 (subtarget, op1,
1864                                GEN_INT (op3_value << start_bit)));
1865       }
1866     else if (start_bit == 0
1867              && !(const_ok_for_arm (mask)
1868                   || const_ok_for_arm (~mask)))
1869       {
1870         /* A Trick, since we are setting the bottom bits in the word,
1871            we can shift operand[3] up, operand[0] down, OR them together
1872            and rotate the result back again.  This takes 3 insns, and
1873            the third might be mergable into another op.  */
1874         /* The shift up copes with the possibility that operand[3] is
1875            wider than the bitfield.  */
1876         rtx op0 = gen_reg_rtx (SImode);
1877         rtx op1 = gen_reg_rtx (SImode);
1879         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1880         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1881         emit_insn (gen_iorsi3  (op1, op1, op0));
1882         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1883       }
1884     else if ((width + start_bit == 32)
1885              && !(const_ok_for_arm (mask)
1886                   || const_ok_for_arm (~mask)))
1887       {
1888         /* Similar trick, but slightly less efficient.  */
1890         rtx op0 = gen_reg_rtx (SImode);
1891         rtx op1 = gen_reg_rtx (SImode);
1893         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1894         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1895         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1896         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1897       }
1898     else
1899       {
1900         rtx op0 = GEN_INT (mask);
1901         rtx op1 = gen_reg_rtx (SImode);
1902         rtx op2 = gen_reg_rtx (SImode);
1904         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1905           {
1906             rtx tmp = gen_reg_rtx (SImode);
1908             emit_insn (gen_movsi (tmp, op0));
1909             op0 = tmp;
1910           }
1912         /* Mask out any bits in operand[3] that are not needed.  */
1913            emit_insn (gen_andsi3 (op1, operands[3], op0));
1915         if (GET_CODE (op0) == CONST_INT
1916             && (const_ok_for_arm (mask << start_bit)
1917                 || const_ok_for_arm (~(mask << start_bit))))
1918           {
1919             op0 = GEN_INT (~(mask << start_bit));
1920             emit_insn (gen_andsi3 (op2, operands[0], op0));
1921           }
1922         else
1923           {
1924             if (GET_CODE (op0) == CONST_INT)
1925               {
1926                 rtx tmp = gen_reg_rtx (SImode);
1928                 emit_insn (gen_movsi (tmp, op0));
1929                 op0 = tmp;
1930               }
1932             if (start_bit != 0)
1933               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1934             
1935             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1936           }
1938         if (start_bit != 0)
1939           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1941         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1942       }
1944     if (subtarget != target)
1945       {
1946         /* If TARGET is still a SUBREG, then it must be wider than a word,
1947            so we must be careful only to set the subword we were asked to.  */
1948         if (GET_CODE (target) == SUBREG)
1949           emit_move_insn (target, subtarget);
1950         else
1951           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1952       }
1954     DONE;
1955   }"
1958 ; constants for op 2 will never be given to these patterns.
1959 (define_insn_and_split "*anddi_notdi_di"
1960   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1961         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1962                 (match_operand:DI 2 "s_register_operand" "0,r")))]
1963   "TARGET_ARM"
1964   "#"
1965   "TARGET_ARM && reload_completed"
1966   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1967    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1968   "
1969   {
1970     operands[3] = gen_highpart (SImode, operands[0]);
1971     operands[0] = gen_lowpart (SImode, operands[0]);
1972     operands[4] = gen_highpart (SImode, operands[1]);
1973     operands[1] = gen_lowpart (SImode, operands[1]);
1974     operands[5] = gen_highpart (SImode, operands[2]);
1975     operands[2] = gen_lowpart (SImode, operands[2]);
1976   }"
1977   [(set_attr "length" "8")
1978    (set_attr "predicable" "yes")]
1980   
1981 (define_insn_and_split "*anddi_notzesidi_di"
1982   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1983         (and:DI (not:DI (zero_extend:DI
1984                          (match_operand:SI 2 "s_register_operand" "r,r")))
1985                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1986   "TARGET_ARM"
1987   "@
1988    bic%?\\t%Q0, %Q1, %2
1989    #"
1990   ; (not (zero_extend ...)) allows us to just copy the high word from
1991   ; operand1 to operand0.
1992   "TARGET_ARM
1993    && reload_completed
1994    && operands[0] != operands[1]"
1995   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1996    (set (match_dup 3) (match_dup 4))]
1997   "
1998   {
1999     operands[3] = gen_highpart (SImode, operands[0]);
2000     operands[0] = gen_lowpart (SImode, operands[0]);
2001     operands[4] = gen_highpart (SImode, operands[1]);
2002     operands[1] = gen_lowpart (SImode, operands[1]);
2003   }"
2004   [(set_attr "length" "4,8")
2005    (set_attr "predicable" "yes")]
2007   
2008 (define_insn_and_split "*anddi_notsesidi_di"
2009   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2010         (and:DI (not:DI (sign_extend:DI
2011                          (match_operand:SI 2 "s_register_operand" "r,r")))
2012                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2013   "TARGET_ARM"
2014   "#"
2015   "TARGET_ARM && reload_completed"
2016   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2017    (set (match_dup 3) (and:SI (not:SI
2018                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2019                                (match_dup 4)))]
2020   "
2021   {
2022     operands[3] = gen_highpart (SImode, operands[0]);
2023     operands[0] = gen_lowpart (SImode, operands[0]);
2024     operands[4] = gen_highpart (SImode, operands[1]);
2025     operands[1] = gen_lowpart (SImode, operands[1]);
2026   }"
2027   [(set_attr "length" "8")
2028    (set_attr "predicable" "yes")]
2030   
2031 (define_insn "andsi_notsi_si"
2032   [(set (match_operand:SI 0 "s_register_operand" "=r")
2033         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2034                 (match_operand:SI 1 "s_register_operand" "r")))]
2035   "TARGET_ARM"
2036   "bic%?\\t%0, %1, %2"
2037   [(set_attr "predicable" "yes")]
2040 (define_insn "bicsi3"
2041   [(set (match_operand:SI                 0 "register_operand" "=l")
2042         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2043                 (match_operand:SI         2 "register_operand" "0")))]
2044   "TARGET_THUMB"
2045   "bic\\t%0, %0, %1"
2046   [(set_attr "length" "2")]
2049 (define_insn "andsi_not_shiftsi_si"
2050   [(set (match_operand:SI                   0 "s_register_operand" "=r")
2051         (and:SI (not:SI (match_operator:SI  4 "shift_operator"
2052                          [(match_operand:SI 2 "s_register_operand"  "r")
2053                           (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
2054                 (match_operand:SI           1 "s_register_operand"  "r")))]
2055   "TARGET_ARM"
2056   "bic%?\\t%0, %1, %2%S4"
2057   [(set_attr "predicable" "yes")
2058    (set_attr "shift" "2")
2059    ]
2062 (define_insn "*andsi_notsi_si_compare0"
2063   [(set (reg:CC_NOOV CC_REGNUM)
2064         (compare:CC_NOOV
2065          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2066                  (match_operand:SI 1 "s_register_operand" "r"))
2067          (const_int 0)))
2068    (set (match_operand:SI 0 "s_register_operand" "=r")
2069         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2070   "TARGET_ARM"
2071   "bic%?s\\t%0, %1, %2"
2072   [(set_attr "conds" "set")]
2075 (define_insn "*andsi_notsi_si_compare0_scratch"
2076   [(set (reg:CC_NOOV CC_REGNUM)
2077         (compare:CC_NOOV
2078          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2079                  (match_operand:SI 1 "s_register_operand" "r"))
2080          (const_int 0)))
2081    (clobber (match_scratch:SI 0 "=r"))]
2082   "TARGET_ARM"
2083   "bic%?s\\t%0, %1, %2"
2084   [(set_attr "conds" "set")]
2087 (define_insn "iordi3"
2088   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2089         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2090                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2091   "TARGET_ARM"
2092   "#"
2093   [(set_attr "length" "8")
2094    (set_attr "predicable" "yes")]
2097 (define_insn "*iordi_zesidi_di"
2098   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2099         (ior:DI (zero_extend:DI
2100                  (match_operand:SI 2 "s_register_operand" "r,r"))
2101                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2102   "TARGET_ARM"
2103   "@
2104    orr%?\\t%Q0, %Q1, %2
2105    #"
2106   [(set_attr "length" "4,8")
2107    (set_attr "predicable" "yes")]
2110 (define_insn "*iordi_sesidi_di"
2111   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2112         (ior:DI (sign_extend:DI
2113                  (match_operand:SI 2 "s_register_operand" "r,r"))
2114                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2115   "TARGET_ARM"
2116   "#"
2117   [(set_attr "length" "8")
2118    (set_attr "predicable" "yes")]
2121 (define_expand "iorsi3"
2122   [(set (match_operand:SI         0 "s_register_operand" "")
2123         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2124                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2125   "TARGET_EITHER"
2126   "
2127   if (GET_CODE (operands[2]) == CONST_INT)
2128     {
2129       if (TARGET_ARM)
2130         {
2131           arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2132                               operands[1],
2133                               (no_new_pseudos
2134                               ? 0 : preserve_subexpressions_p ()));
2135           DONE;
2136         }
2137       else /* TARGET_THUMB */
2138         operands [2] = force_reg (SImode, operands [2]);
2139     }
2140   "
2143 (define_insn_and_split "*arm_iorsi3"
2144   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2145         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2146                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2147   "TARGET_ARM"
2148   "@
2149    orr%?\\t%0, %1, %2
2150    #"
2151   "TARGET_ARM
2152    && GET_CODE (operands[2]) == CONST_INT
2153    && !const_ok_for_arm (INTVAL (operands[2]))"
2154   [(clobber (const_int 0))]
2155   "
2156   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2157                       operands[1], 0);
2158   DONE;
2159   "
2160   [(set_attr "length" "4,16")
2161    (set_attr "predicable" "yes")]
2164 (define_insn "*thumb_iorsi3"
2165   [(set (match_operand:SI         0 "register_operand" "=l")
2166         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2167                 (match_operand:SI 2 "register_operand" "l")))]
2168   "TARGET_THUMB"
2169   "orr\\t%0, %0, %2"
2170   [(set_attr "length" "2")]
2173 (define_peephole2
2174   [(match_scratch:SI 3 "r")
2175    (set (match_operand:SI         0 "s_register_operand" "")
2176         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2177                 (match_operand:SI 2 "const_int_operand" "")))]
2178   "TARGET_ARM
2179    && !const_ok_for_arm (INTVAL (operands[2]))
2180    && const_ok_for_arm (~INTVAL (operands[2]))"
2181   [(set (match_dup 3) (match_dup 2))
2182    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2183   ""
2186 (define_insn "*iorsi3_compare0"
2187   [(set (reg:CC_NOOV CC_REGNUM)
2188         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2189                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2190                          (const_int 0)))
2191    (set (match_operand:SI 0 "s_register_operand" "=r")
2192         (ior:SI (match_dup 1) (match_dup 2)))]
2193   "TARGET_ARM"
2194   "orr%?s\\t%0, %1, %2"
2195   [(set_attr "conds" "set")]
2198 (define_insn "*iorsi3_compare0_scratch"
2199   [(set (reg:CC_NOOV CC_REGNUM)
2200         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2201                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2202                          (const_int 0)))
2203    (clobber (match_scratch:SI 0 "=r"))]
2204   "TARGET_ARM"
2205   "orr%?s\\t%0, %1, %2"
2206   [(set_attr "conds" "set")]
2209 (define_insn "xordi3"
2210   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2211         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2212                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2213   "TARGET_ARM"
2214   "#"
2215   [(set_attr "length" "8")
2216    (set_attr "predicable" "yes")]
2219 (define_insn "*xordi_zesidi_di"
2220   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2221         (xor:DI (zero_extend:DI
2222                  (match_operand:SI 2 "s_register_operand" "r,r"))
2223                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2224   "TARGET_ARM"
2225   "@
2226    eor%?\\t%Q0, %Q1, %2
2227    #"
2228   [(set_attr "length" "4,8")
2229    (set_attr "predicable" "yes")]
2232 (define_insn "*xordi_sesidi_di"
2233   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2234         (xor:DI (sign_extend:DI
2235                  (match_operand:SI 2 "s_register_operand" "r,r"))
2236                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2237   "TARGET_ARM"
2238   "#"
2239   [(set_attr "length" "8")
2240    (set_attr "predicable" "yes")]
2243 (define_expand "xorsi3"
2244   [(set (match_operand:SI         0 "s_register_operand" "")
2245         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2246                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2247   "TARGET_EITHER"
2248   "if (TARGET_THUMB)
2249      if (GET_CODE (operands[2]) == CONST_INT)
2250        operands[2] = force_reg (SImode, operands[2]);
2251   "
2254 (define_insn "*arm_xorsi3"
2255   [(set (match_operand:SI         0 "s_register_operand" "=r")
2256         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2257                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2258   "TARGET_ARM"
2259   "eor%?\\t%0, %1, %2"
2260   [(set_attr "predicable" "yes")]
2263 (define_insn "*thumb_xorsi3"
2264   [(set (match_operand:SI         0 "register_operand" "=l")
2265         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2266                 (match_operand:SI 2 "register_operand" "l")))]
2267   "TARGET_THUMB"
2268   "eor\\t%0, %0, %2"
2269   [(set_attr "length" "2")]
2272 (define_insn "*xorsi3_compare0"
2273   [(set (reg:CC_NOOV CC_REGNUM)
2274         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2275                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2276                          (const_int 0)))
2277    (set (match_operand:SI 0 "s_register_operand" "=r")
2278         (xor:SI (match_dup 1) (match_dup 2)))]
2279   "TARGET_ARM"
2280   "eor%?s\\t%0, %1, %2"
2281   [(set_attr "conds" "set")]
2284 (define_insn "*xorsi3_compare0_scratch"
2285   [(set (reg:CC_NOOV CC_REGNUM)
2286         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2287                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2288                          (const_int 0)))]
2289   "TARGET_ARM"
2290   "teq%?\\t%0, %1"
2291   [(set_attr "conds" "set")]
2294 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2295 ; (NOT D) we can sometimes merge the final NOT into one of the following
2296 ; insns.
2298 (define_split
2299   [(set (match_operand:SI 0 "s_register_operand" "=r")
2300         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2301                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
2302                 (match_operand:SI 3 "arm_rhs_operand" "rI")))
2303    (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
2304   "TARGET_ARM"
2305   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2306                               (not:SI (match_dup 3))))
2307    (set (match_dup 0) (not:SI (match_dup 4)))]
2308   ""
2311 (define_insn "*andsi_iorsi3_notsi"
2312   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2313         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2314                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2315                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2316   "TARGET_ARM"
2317   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2318   [(set_attr "length" "8")
2319    (set_attr "predicable" "yes")]
2324 ;; Minimum and maximum insns
2326 (define_insn "smaxsi3"
2327   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2328         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2329                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2330    (clobber (reg:CC CC_REGNUM))]
2331   "TARGET_ARM"
2332   "@
2333    cmp\\t%1, %2\;movlt\\t%0, %2
2334    cmp\\t%1, %2\;movge\\t%0, %1
2335    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2336   [(set_attr "conds" "clob")
2337    (set_attr "length" "8,8,12")]
2340 (define_insn "sminsi3"
2341   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2342         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2343                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2344    (clobber (reg:CC CC_REGNUM))]
2345   "TARGET_ARM"
2346   "@
2347    cmp\\t%1, %2\;movge\\t%0, %2
2348    cmp\\t%1, %2\;movlt\\t%0, %1
2349    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2350   [(set_attr "conds" "clob")
2351    (set_attr "length" "8,8,12")]
2354 (define_insn "umaxsi3"
2355   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2356         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2357                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2358    (clobber (reg:CC CC_REGNUM))]
2359   "TARGET_ARM"
2360   "@
2361    cmp\\t%1, %2\;movcc\\t%0, %2
2362    cmp\\t%1, %2\;movcs\\t%0, %1
2363    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2364   [(set_attr "conds" "clob")
2365    (set_attr "length" "8,8,12")]
2368 (define_insn "uminsi3"
2369   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2370         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2371                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2372    (clobber (reg:CC CC_REGNUM))]
2373   "TARGET_ARM"
2374   "@
2375    cmp\\t%1, %2\;movcs\\t%0, %2
2376    cmp\\t%1, %2\;movcc\\t%0, %1
2377    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2378   [(set_attr "conds" "clob")
2379    (set_attr "length" "8,8,12")]
2382 (define_insn "*store_minmaxsi"
2383   [(set (match_operand:SI 0 "memory_operand" "=m")
2384         (match_operator:SI 3 "minmax_operator"
2385          [(match_operand:SI 1 "s_register_operand" "r")
2386           (match_operand:SI 2 "s_register_operand" "r")]))
2387    (clobber (reg:CC CC_REGNUM))]
2388   "TARGET_ARM"
2389   "*
2390   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2391                          operands[2]);
2392   output_asm_insn (\"cmp\\t%1, %2\", operands);
2393   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2394   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2395   return \"\";
2396   "
2397   [(set_attr "conds" "clob")
2398    (set_attr "length" "12")
2399    (set_attr "type" "store1")]
2402 ; Reject the frame pointer in operand[1], since reloading this after
2403 ; it has been eliminated can cause carnage.
2404 (define_insn "*minmax_arithsi"
2405   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2406         (match_operator:SI 4 "shiftable_operator"
2407          [(match_operator:SI 5 "minmax_operator"
2408            [(match_operand:SI 2 "s_register_operand" "r,r")
2409             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2410           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2411    (clobber (reg:CC CC_REGNUM))]
2412   "TARGET_ARM
2413    && (GET_CODE (operands[1]) != REG
2414        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2415            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2416   "*
2417   {
2418     enum rtx_code code = GET_CODE (operands[4]);
2420     operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2421                            operands[3]);
2422     output_asm_insn (\"cmp\\t%2, %3\", operands);
2423     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2424     if (which_alternative != 0 || operands[3] != const0_rtx
2425         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2426       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2427     return \"\";
2428   }"
2429   [(set_attr "conds" "clob")
2430    (set_attr "length" "12")]
2434 ;; Shift and rotation insns
2436 (define_expand "ashlsi3"
2437   [(set (match_operand:SI            0 "s_register_operand" "")
2438         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2439                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2440   "TARGET_EITHER"
2441   "
2442   if (GET_CODE (operands[2]) == CONST_INT
2443       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2444     {
2445       emit_insn (gen_movsi (operands[0], const0_rtx));
2446       DONE;
2447     }
2448   "
2451 (define_insn "*thumb_ashlsi3"
2452   [(set (match_operand:SI            0 "register_operand" "=l,l")
2453         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2454                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2455   "TARGET_THUMB"
2456   "lsl\\t%0, %1, %2"
2457   [(set_attr "length" "2")]
2460 (define_expand "ashrsi3"
2461   [(set (match_operand:SI              0 "s_register_operand" "")
2462         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2463                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2464   "TARGET_EITHER"
2465   "
2466   if (GET_CODE (operands[2]) == CONST_INT
2467       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2468     operands[2] = GEN_INT (31);
2469   "
2472 (define_insn "*thumb_ashrsi3"
2473   [(set (match_operand:SI              0 "register_operand" "=l,l")
2474         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2475                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2476   "TARGET_THUMB"
2477   "asr\\t%0, %1, %2"
2478   [(set_attr "length" "2")]
2481 (define_expand "lshrsi3"
2482   [(set (match_operand:SI              0 "s_register_operand" "")
2483         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2484                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2485   "TARGET_EITHER"
2486   "
2487   if (GET_CODE (operands[2]) == CONST_INT
2488       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2489     {
2490       emit_insn (gen_movsi (operands[0], const0_rtx));
2491       DONE;
2492     }
2493   "
2496 (define_insn "*thumb_lshrsi3"
2497   [(set (match_operand:SI              0 "register_operand" "=l,l")
2498         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2499                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2500   "TARGET_THUMB"
2501   "lsr\\t%0, %1, %2"
2502   [(set_attr "length" "2")]
2505 (define_expand "rotlsi3"
2506   [(set (match_operand:SI              0 "s_register_operand" "")
2507         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2508                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2509   "TARGET_ARM"
2510   "
2511   if (GET_CODE (operands[2]) == CONST_INT)
2512     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2513   else
2514     {
2515       rtx reg = gen_reg_rtx (SImode);
2516       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2517       operands[2] = reg;
2518     }
2519   "
2522 (define_expand "rotrsi3"
2523   [(set (match_operand:SI              0 "s_register_operand" "")
2524         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2525                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2526   "TARGET_EITHER"
2527   "
2528   if (TARGET_ARM)
2529     {
2530       if (GET_CODE (operands[2]) == CONST_INT
2531           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2532         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2533     }
2534   else /* TARGET_THUMB */
2535     {
2536       if (GET_CODE (operands [2]) == CONST_INT)
2537         operands [2] = force_reg (SImode, operands[2]);
2538     }
2539   "
2542 (define_insn "*thumb_rotrsi3"
2543   [(set (match_operand:SI              0 "register_operand" "=l")
2544         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2545                      (match_operand:SI 2 "register_operand" "l")))]
2546   "TARGET_THUMB"
2547   "ror\\t%0, %0, %2"
2548   [(set_attr "length" "2")]
2551 (define_insn "*arm_shiftsi3"
2552   [(set (match_operand:SI   0 "s_register_operand" "=r")
2553         (match_operator:SI  3 "shift_operator"
2554          [(match_operand:SI 1 "s_register_operand"  "r")
2555           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2556   "TARGET_ARM"
2557   "mov%?\\t%0, %1%S3"
2558   [(set_attr "predicable" "yes")
2559    (set_attr "shift" "1")
2560    ]
2563 (define_insn "*shiftsi3_compare0"
2564   [(set (reg:CC_NOOV CC_REGNUM)
2565         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2566                           [(match_operand:SI 1 "s_register_operand" "r")
2567                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2568                          (const_int 0)))
2569    (set (match_operand:SI 0 "s_register_operand" "=r")
2570         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2571   "TARGET_ARM"
2572   "mov%?s\\t%0, %1%S3"
2573   [(set_attr "conds" "set")
2574    (set_attr "shift" "1")
2575    ]
2578 (define_insn "*shiftsi3_compare0_scratch"
2579   [(set (reg:CC_NOOV CC_REGNUM)
2580         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2581                           [(match_operand:SI 1 "s_register_operand" "r")
2582                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2583                          (const_int 0)))
2584    (clobber (match_scratch:SI 0 "=r"))]
2585   "TARGET_ARM"
2586   "mov%?s\\t%0, %1%S3"
2587   [(set_attr "conds" "set")
2588    (set_attr "shift" "1")
2589    ]
2592 (define_insn "*notsi_shiftsi"
2593   [(set (match_operand:SI 0 "s_register_operand" "=r")
2594         (not:SI (match_operator:SI 3 "shift_operator"
2595                  [(match_operand:SI 1 "s_register_operand" "r")
2596                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2597   "TARGET_ARM"
2598   "mvn%?\\t%0, %1%S3"
2599   [(set_attr "predicable" "yes")
2600    (set_attr "shift" "1")
2601    ]
2604 (define_insn "*notsi_shiftsi_compare0"
2605   [(set (reg:CC_NOOV CC_REGNUM)
2606         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2607                           [(match_operand:SI 1 "s_register_operand" "r")
2608                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2609                          (const_int 0)))
2610    (set (match_operand:SI 0 "s_register_operand" "=r")
2611         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2612   "TARGET_ARM"
2613   "mvn%?s\\t%0, %1%S3"
2614   [(set_attr "conds" "set")
2615    (set_attr "shift" "1")
2616    ]
2619 (define_insn "*not_shiftsi_compare0_scratch"
2620   [(set (reg:CC_NOOV CC_REGNUM)
2621         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2622                           [(match_operand:SI 1 "s_register_operand" "r")
2623                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2624                          (const_int 0)))
2625    (clobber (match_scratch:SI 0 "=r"))]
2626   "TARGET_ARM"
2627   "mvn%?s\\t%0, %1%S3"
2628   [(set_attr "conds" "set")
2629    (set_attr "shift" "1")
2630   ]
2633 ;; We don't really have extzv, but defining this using shifts helps
2634 ;; to reduce register pressure later on.
2636 (define_expand "extzv"
2637   [(set (match_dup 4)
2638         (ashift:SI (match_operand:SI   1 "register_operand" "")
2639                    (match_operand:SI   2 "const_int_operand" "")))
2640    (set (match_operand:SI              0 "register_operand" "")
2641         (lshiftrt:SI (match_dup 4)
2642                      (match_operand:SI 3 "const_int_operand" "")))]
2643   "TARGET_THUMB"
2644   "
2645   {
2646     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2647     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2648     
2649     operands[3] = GEN_INT (rshift);
2650     
2651     if (lshift == 0)
2652       {
2653         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2654         DONE;
2655       }
2656       
2657     operands[2] = GEN_INT (lshift);
2658     operands[4] = gen_reg_rtx (SImode);
2659   }"
2663 ;; Unary arithmetic insns
2665 (define_expand "negdi2"
2666  [(parallel
2667    [(set (match_operand:DI          0 "s_register_operand" "")
2668           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2669     (clobber (reg:CC CC_REGNUM))])]
2670   "TARGET_EITHER"
2671   "
2672   if (TARGET_THUMB)
2673     {
2674       if (GET_CODE (operands[1]) != REG)
2675         operands[1] = force_reg (SImode, operands[1]);
2676      }
2677   "
2680 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2681 ;; The second alternative is to allow the common case of a *full* overlap.
2682 (define_insn "*arm_negdi2"
2683   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2684         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2685    (clobber (reg:CC CC_REGNUM))]
2686   "TARGET_ARM"
2687   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2688   [(set_attr "conds" "clob")
2689    (set_attr "length" "8")]
2692 (define_insn "*thumb_negdi2"
2693   [(set (match_operand:DI         0 "register_operand" "=&l")
2694         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2695    (clobber (reg:CC CC_REGNUM))]
2696   "TARGET_THUMB"
2697   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2698   [(set_attr "length" "6")]
2701 (define_expand "negsi2"
2702   [(set (match_operand:SI         0 "s_register_operand" "")
2703         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2704   "TARGET_EITHER"
2705   ""
2708 (define_insn "*arm_negsi2"
2709   [(set (match_operand:SI         0 "s_register_operand" "=r")
2710         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2711   "TARGET_ARM"
2712   "rsb%?\\t%0, %1, #0"
2713   [(set_attr "predicable" "yes")]
2716 (define_insn "*thumb_negsi2"
2717   [(set (match_operand:SI         0 "register_operand" "=l")
2718         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2719   "TARGET_THUMB"
2720   "neg\\t%0, %1"
2721   [(set_attr "length" "2")]
2724 (define_insn "negsf2"
2725   [(set (match_operand:SF 0 "s_register_operand" "=f")
2726         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2727   "TARGET_ARM && TARGET_HARD_FLOAT"
2728   "mnf%?s\\t%0, %1"
2729   [(set_attr "type" "ffarith")
2730    (set_attr "predicable" "yes")]
2733 (define_insn "negdf2"
2734   [(set (match_operand:DF 0 "s_register_operand" "=f")
2735         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2736   "TARGET_ARM && TARGET_HARD_FLOAT"
2737   "mnf%?d\\t%0, %1"
2738   [(set_attr "type" "ffarith")
2739    (set_attr "predicable" "yes")]
2742 (define_insn "*negdf_esfdf"
2743   [(set (match_operand:DF 0 "s_register_operand" "=f")
2744         (neg:DF (float_extend:DF
2745                  (match_operand:SF 1 "s_register_operand" "f"))))]
2746   "TARGET_ARM && TARGET_HARD_FLOAT"
2747   "mnf%?d\\t%0, %1"
2748   [(set_attr "type" "ffarith")
2749    (set_attr "predicable" "yes")]
2752 (define_insn "negxf2"
2753   [(set (match_operand:XF 0 "s_register_operand" "=f")
2754         (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2755   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2756   "mnf%?e\\t%0, %1"
2757   [(set_attr "type" "ffarith")
2758    (set_attr "predicable" "yes")]
2761 ;; abssi2 doesn't really clobber the condition codes if a different register
2762 ;; is being set.  To keep things simple, assume during rtl manipulations that
2763 ;; it does, but tell the final scan operator the truth.  Similarly for
2764 ;; (neg (abs...))
2766 (define_insn "abssi2"
2767   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2768         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2769    (clobber (reg:CC CC_REGNUM))]
2770   "TARGET_ARM"
2771   "@
2772    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2773    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2774   [(set_attr "conds" "clob,*")
2775    (set_attr "shift" "1")
2776    ;; predicable can't be set based on the variant, so left as no
2777    (set_attr "length" "8")]
2780 (define_insn "*neg_abssi2"
2781   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2782         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2783    (clobber (reg:CC CC_REGNUM))]
2784   "TARGET_ARM"
2785   "@
2786    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2787    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2788   [(set_attr "conds" "clob,*")
2789    (set_attr "shift" "1")
2790    ;; predicable can't be set based on the variant, so left as no
2791    (set_attr "length" "8")]
2794 (define_insn "abssf2"
2795   [(set (match_operand:SF 0 "s_register_operand" "=f")
2796          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2797   "TARGET_ARM && TARGET_HARD_FLOAT"
2798   "abs%?s\\t%0, %1"
2799   [(set_attr "type" "ffarith")
2800    (set_attr "predicable" "yes")]
2803 (define_insn "absdf2"
2804   [(set (match_operand:DF 0 "s_register_operand" "=f")
2805         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2806   "TARGET_ARM && TARGET_HARD_FLOAT"
2807   "abs%?d\\t%0, %1"
2808   [(set_attr "type" "ffarith")
2809    (set_attr "predicable" "yes")]
2812 (define_insn "*absdf_esfdf"
2813   [(set (match_operand:DF 0 "s_register_operand" "=f")
2814         (abs:DF (float_extend:DF
2815                  (match_operand:SF 1 "s_register_operand" "f"))))]
2816   "TARGET_ARM && TARGET_HARD_FLOAT"
2817   "abs%?d\\t%0, %1"
2818   [(set_attr "type" "ffarith")
2819    (set_attr "predicable" "yes")]
2822 (define_insn "absxf2"
2823   [(set (match_operand:XF 0 "s_register_operand" "=f")
2824         (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2825   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2826   "abs%?e\\t%0, %1"
2827   [(set_attr "type" "ffarith")
2828    (set_attr "predicable" "yes")]
2831 (define_insn "sqrtsf2"
2832   [(set (match_operand:SF 0 "s_register_operand" "=f")
2833         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2834   "TARGET_ARM && TARGET_HARD_FLOAT"
2835   "sqt%?s\\t%0, %1"
2836   [(set_attr "type" "float_em")
2837    (set_attr "predicable" "yes")]
2840 (define_insn "sqrtdf2"
2841   [(set (match_operand:DF 0 "s_register_operand" "=f")
2842         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2843   "TARGET_ARM && TARGET_HARD_FLOAT"
2844   "sqt%?d\\t%0, %1"
2845   [(set_attr "type" "float_em")
2846    (set_attr "predicable" "yes")]
2849 (define_insn "*sqrtdf_esfdf"
2850   [(set (match_operand:DF 0 "s_register_operand" "=f")
2851         (sqrt:DF (float_extend:DF
2852                   (match_operand:SF 1 "s_register_operand" "f"))))]
2853   "TARGET_ARM && TARGET_HARD_FLOAT"
2854   "sqt%?d\\t%0, %1"
2855   [(set_attr "type" "float_em")
2856    (set_attr "predicable" "yes")]
2859 (define_insn "sqrtxf2"
2860   [(set (match_operand:XF 0 "s_register_operand" "=f")
2861         (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2862   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2863   "sqt%?e\\t%0, %1"
2864   [(set_attr "type" "float_em")
2865    (set_attr "predicable" "yes")]
2868 ;; SIN COS TAN and family are always emulated, so it's probably better
2869 ;; to always call a library function.
2870 ;(define_insn "sinsf2"
2871 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2872 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
2873 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2874 ;  "sin%?s\\t%0, %1"
2875 ;[(set_attr "type" "float_em")])
2877 ;(define_insn "sindf2"
2878 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2879 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
2880 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2881 ;  "sin%?d\\t%0, %1"
2882 ;[(set_attr "type" "float_em")])
2884 ;(define_insn "*sindf_esfdf"
2885 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2886 ;       (unspec:DF [(float_extend:DF
2887 ;                    (match_operand:SF 1 "s_register_operand" "f"))] 0))]
2888 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2889 ;  "sin%?d\\t%0, %1"
2890 ;[(set_attr "type" "float_em")])
2892 ;(define_insn "sinxf2"
2893 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2894 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
2895 ;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2896 ;  "sin%?e\\t%0, %1"
2897 ;[(set_attr "type" "float_em")])
2899 ;(define_insn "cossf2"
2900 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2901 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
2902 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2903 ;  "cos%?s\\t%0, %1"
2904 ;[(set_attr "type" "float_em")])
2906 ;(define_insn "cosdf2"
2907 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2908 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
2909 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2910 ;  "cos%?d\\t%0, %1"
2911 ;[(set_attr "type" "float_em")])
2913 ;(define_insn "*cosdf_esfdf"
2914 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2915 ;       (unspec:DF [(float_extend:DF
2916 ;                    (match_operand:SF 1 "s_register_operand" "f"))] 1))]
2917 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2918 ;  "cos%?d\\t%0, %1"
2919 ;[(set_attr "type" "float_em")])
2921 ;(define_insn "cosxf2"
2922 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2923 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
2924 ;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2925 ;  "cos%?e\\t%0, %1"
2926 ;[(set_attr "type" "float_em")])
2928 (define_insn_and_split "one_cmpldi2"
2929   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2930         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2931   "TARGET_ARM"
2932   "#"
2933   "TARGET_ARM && reload_completed"
2934   [(set (match_dup 0) (not:SI (match_dup 1)))
2935    (set (match_dup 2) (not:SI (match_dup 3)))]
2936   "
2937   {
2938     operands[2] = gen_highpart (SImode, operands[0]);
2939     operands[0] = gen_lowpart (SImode, operands[0]);
2940     operands[3] = gen_highpart (SImode, operands[1]);
2941     operands[1] = gen_lowpart (SImode, operands[1]);
2942   }"
2943   [(set_attr "length" "8")
2944    (set_attr "predicable" "yes")]
2947 (define_expand "one_cmplsi2"
2948   [(set (match_operand:SI         0 "s_register_operand" "")
2949         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2950   "TARGET_EITHER"
2951   ""
2954 (define_insn "*arm_one_cmplsi2"
2955   [(set (match_operand:SI         0 "s_register_operand" "=r")
2956         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2957   "TARGET_ARM"
2958   "mvn%?\\t%0, %1"
2959   [(set_attr "predicable" "yes")]
2962 (define_insn "*thumb_one_cmplsi2"
2963   [(set (match_operand:SI         0 "register_operand" "=l")
2964         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
2965   "TARGET_THUMB"
2966   "mvn\\t%0, %1"
2967   [(set_attr "length" "2")]
2970 (define_insn "*notsi_compare0"
2971   [(set (reg:CC_NOOV CC_REGNUM)
2972         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2973                          (const_int 0)))
2974    (set (match_operand:SI 0 "s_register_operand" "=r")
2975         (not:SI (match_dup 1)))]
2976   "TARGET_ARM"
2977   "mvn%?s\\t%0, %1"
2978   [(set_attr "conds" "set")]
2981 (define_insn "*notsi_compare0_scratch"
2982   [(set (reg:CC_NOOV CC_REGNUM)
2983         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2984                          (const_int 0)))
2985    (clobber (match_scratch:SI 0 "=r"))]
2986   "TARGET_ARM"
2987   "mvn%?s\\t%0, %1"
2988   [(set_attr "conds" "set")]
2991 ;; Fixed <--> Floating conversion insns
2993 (define_insn "floatsisf2"
2994   [(set (match_operand:SF 0 "s_register_operand" "=f")
2995         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2996   "TARGET_ARM && TARGET_HARD_FLOAT"
2997   "flt%?s\\t%0, %1"
2998   [(set_attr "type" "r_2_f")
2999    (set_attr "predicable" "yes")]
3002 (define_insn "floatsidf2"
3003   [(set (match_operand:DF 0 "s_register_operand" "=f")
3004         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3005   "TARGET_ARM && TARGET_HARD_FLOAT"
3006   "flt%?d\\t%0, %1"
3007   [(set_attr "type" "r_2_f")
3008    (set_attr "predicable" "yes")]
3011 (define_insn "floatsixf2"
3012   [(set (match_operand:XF 0 "s_register_operand" "=f")
3013         (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3014   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3015   "flt%?e\\t%0, %1"
3016   [(set_attr "type" "r_2_f")
3017    (set_attr "predicable" "yes")]
3020 (define_insn "fix_truncsfsi2"
3021   [(set (match_operand:SI 0 "s_register_operand" "=r")
3022         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3023   "TARGET_ARM && TARGET_HARD_FLOAT"
3024   "fix%?z\\t%0, %1"
3025   [(set_attr "type" "f_2_r")
3026    (set_attr "predicable" "yes")]
3029 (define_insn "fix_truncdfsi2"
3030   [(set (match_operand:SI 0 "s_register_operand" "=r")
3031         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3032   "TARGET_ARM && TARGET_HARD_FLOAT"
3033   "fix%?z\\t%0, %1"
3034   [(set_attr "type" "f_2_r")
3035    (set_attr "predicable" "yes")]
3038 (define_insn "fix_truncxfsi2"
3039   [(set (match_operand:SI 0 "s_register_operand" "=r")
3040         (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3041   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3042   "fix%?z\\t%0, %1"
3043   [(set_attr "type" "f_2_r")
3044    (set_attr "predicable" "yes")]
3047 ;; Truncation insns
3049 (define_insn "truncdfsf2"
3050   [(set (match_operand:SF 0 "s_register_operand" "=f")
3051         (float_truncate:SF
3052          (match_operand:DF 1 "s_register_operand" "f")))]
3053   "TARGET_ARM && TARGET_HARD_FLOAT"
3054   "mvf%?s\\t%0, %1"
3055   [(set_attr "type" "ffarith")
3056    (set_attr "predicable" "yes")]
3059 (define_insn "truncxfsf2"
3060   [(set (match_operand:SF 0 "s_register_operand" "=f")
3061         (float_truncate:SF
3062          (match_operand:XF 1 "s_register_operand" "f")))]
3063   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3064   "mvf%?s\\t%0, %1"
3065   [(set_attr "type" "ffarith")
3066    (set_attr "predicable" "yes")]
3069 (define_insn "truncxfdf2"
3070   [(set (match_operand:DF 0 "s_register_operand" "=f")
3071         (float_truncate:DF
3072          (match_operand:XF 1 "s_register_operand" "f")))]
3073   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3074   "mvf%?d\\t%0, %1"
3075   [(set_attr "type" "ffarith")
3076    (set_attr "predicable" "yes")]
3079 ;; Zero and sign extension instructions.
3081 (define_insn "zero_extendsidi2"
3082   [(set (match_operand:DI 0 "s_register_operand" "=r")
3083         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3084   "TARGET_ARM"
3085   "*
3086     if (REGNO (operands[1])
3087         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3088       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3089     return \"mov%?\\t%R0, #0\";
3090   "
3091   [(set_attr "length" "8")
3092    (set_attr "predicable" "yes")]
3095 (define_insn "zero_extendqidi2"
3096   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3097         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3098   "TARGET_ARM"
3099   "@
3100    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3101    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3102   [(set_attr "length" "8")
3103    (set_attr "predicable" "yes")
3104    (set_attr "type" "*,load")
3105    (set_attr "pool_range" "*,4092")
3106    (set_attr "neg_pool_range" "*,4084")]
3109 (define_insn "extendsidi2"
3110   [(set (match_operand:DI 0 "s_register_operand" "=r")
3111         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3112   "TARGET_ARM"
3113   "*
3114     if (REGNO (operands[1])
3115         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3116       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3117     return \"mov%?\\t%R0, %Q0, asr #31\";
3118   "
3119   [(set_attr "length" "8")
3120    (set_attr "shift" "1")
3121    (set_attr "predicable" "yes")]
3124 (define_expand "zero_extendhisi2"
3125   [(set (match_dup 2)
3126         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3127                    (const_int 16)))
3128    (set (match_operand:SI 0 "s_register_operand" "")
3129         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3130   "TARGET_EITHER"
3131   "
3132   {
3133     if (TARGET_ARM)
3134       {
3135         if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3136           {
3137            /* Note: We do not have to worry about TARGET_MMU_TRAPS
3138               here because the insn below will generate an LDRH instruction
3139               rather than an LDR instruction, so we cannot get an unaligned
3140               word access.  */
3141             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3142                                     gen_rtx_ZERO_EXTEND (SImode,
3143                                                          operands[1])));
3144             DONE;
3145           }
3146         if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3147           {
3148             emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3149             DONE;
3150           }
3151         if (!s_register_operand (operands[1], HImode))
3152           operands[1] = copy_to_mode_reg (HImode, operands[1]);
3153         operands[1] = gen_lowpart (SImode, operands[1]);
3154         operands[2] = gen_reg_rtx (SImode);
3155       }
3156     else /* TARGET_THUMB */
3157       {
3158         if (GET_CODE (operands[1]) == MEM)
3159           {
3160             rtx tmp;
3162             tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3163             tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3164             emit_insn (tmp);
3165           }
3166         else
3167           {
3168             rtx ops[3];
3169             
3170             if (!s_register_operand (operands[1], HImode))
3171               operands[1] = copy_to_mode_reg (HImode, operands[1]);
3172             operands[1] = gen_lowpart (SImode, operands[1]);
3173             operands[2] = gen_reg_rtx (SImode);
3174             
3175             ops[0] = operands[2];
3176             ops[1] = operands[1];
3177             ops[2] = GEN_INT (16);
3178             
3179             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3180                                     gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3182             ops[0] = operands[0];
3183             ops[1] = operands[2];
3184             ops[2] = GEN_INT (16);
3186             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3187                                     gen_rtx_LSHIFTRT (SImode, ops[1],
3188                                                       ops[2])));
3189           }
3190         DONE; 
3191       }
3192   }"
3195 (define_insn "*thumb_zero_extendhisi2"
3196   [(set (match_operand:SI                 0 "register_operand" "=l")
3197         (zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3198   "TARGET_THUMB"
3199   "*
3200   rtx mem = XEXP (operands[1], 0);
3202   if (GET_CODE (mem) == CONST)
3203     mem = XEXP (mem, 0);
3204     
3205   if (GET_CODE (mem) == LABEL_REF)
3206     return \"ldr\\t%0, %1\";
3207     
3208   if (GET_CODE (mem) == PLUS)
3209     {
3210       rtx a = XEXP (mem, 0);
3211       rtx b = XEXP (mem, 1);
3213       /* This can happen due to bugs in reload.  */
3214       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3215         {
3216           rtx ops[2];
3217           ops[0] = operands[0];
3218           ops[1] = a;
3219       
3220           output_asm_insn (\"mov        %0, %1\", ops);
3222           XEXP (mem, 0) = operands[0];
3223        }
3225       else if (   GET_CODE (a) == LABEL_REF
3226                && GET_CODE (b) == CONST_INT)
3227         return \"ldr\\t%0, %1\";
3228     }
3229     
3230   return \"ldrh\\t%0, %1\";
3231   "
3232   [(set_attr "length" "4")
3233    (set_attr "type" "load")
3234    (set_attr "pool_range" "60")]
3237 (define_insn "*arm_zero_extendhisi2"
3238   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3239         (zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3240   "TARGET_ARM && arm_arch4"
3241   "ldr%?h\\t%0, %1"
3242   [(set_attr "type" "load")
3243    (set_attr "predicable" "yes")
3244    (set_attr "pool_range" "256")
3245    (set_attr "neg_pool_range" "244")]
3248 (define_split
3249   [(set (match_operand:SI 0 "s_register_operand" "")
3250         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3251    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3252   "TARGET_ARM && (!arm_arch4)"
3253   [(set (match_dup 2) (match_dup 1))
3254    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3255   "
3256   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3257     FAIL;
3258   "
3261 (define_split
3262   [(set (match_operand:SI 0 "s_register_operand" "")
3263         (match_operator:SI 3 "shiftable_operator"
3264          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3265           (match_operand:SI 4 "s_register_operand" "")]))
3266    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3267   "TARGET_ARM && (!arm_arch4)"
3268   [(set (match_dup 2) (match_dup 1))
3269    (set (match_dup 0)
3270         (match_op_dup 3
3271          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3272   "
3273   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3274     FAIL;
3275   "
3278 (define_expand "zero_extendqisi2"
3279   [(set (match_operand:SI 0 "s_register_operand" "")
3280         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3281   "TARGET_EITHER"
3282   "
3283   if (GET_CODE (operands[1]) != MEM)
3284     {
3285       if (TARGET_ARM)
3286         {
3287           emit_insn (gen_andsi3 (operands[0],
3288                                  gen_lowpart (SImode, operands[1]),
3289                                  GEN_INT (255)));
3290         }
3291       else /* TARGET_THUMB */
3292         {
3293           rtx temp = gen_reg_rtx (SImode);
3294           rtx ops[3];
3295           
3296           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3297           operands[1] = gen_lowpart (SImode, operands[1]);
3299           ops[0] = temp;
3300           ops[1] = operands[1];
3301           ops[2] = GEN_INT (24);
3303           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3304                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3305           
3306           ops[0] = operands[0];
3307           ops[1] = temp;
3308           ops[2] = GEN_INT (24);
3310           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3311                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3312         }
3313       DONE;
3314     }
3315   "
3318 (define_insn "*thumb_zero_extendqisi2"
3319   [(set (match_operand:SI                 0 "register_operand" "=l")
3320         (zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3321   "TARGET_THUMB"
3322   "ldrb\\t%0, %1"
3323   [(set_attr "length" "2")
3324    (set_attr "type" "load")
3325    (set_attr "pool_range" "32")]
3328 (define_insn "*arm_zero_extendqisi2"
3329   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3330         (zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3331   "TARGET_ARM"
3332   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3333   [(set_attr "type" "load")
3334    (set_attr "predicable" "yes")
3335    (set_attr "pool_range" "4096")
3336    (set_attr "neg_pool_range" "4084")]
3339 (define_split
3340   [(set (match_operand:SI 0 "s_register_operand" "")
3341         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3342    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3343   "TARGET_ARM && (GET_CODE (operands[1]) != MEM)"
3344   [(set (match_dup 2) (match_dup 1))
3345    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3346   ""
3349 (define_insn "*compareqi_eq0"
3350   [(set (reg:CC_Z CC_REGNUM)
3351         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3352                          (const_int 0)))]
3353   "TARGET_ARM"
3354   "tst\\t%0, #255"
3355   [(set_attr "conds" "set")]
3358 (define_expand "extendhisi2"
3359   [(set (match_dup 2)
3360         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3361                    (const_int 16)))
3362    (set (match_operand:SI 0 "s_register_operand" "")
3363         (ashiftrt:SI (match_dup 2)
3364                      (const_int 16)))]
3365   "TARGET_EITHER"
3366   "
3367   {
3368     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3369       {
3370        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3371           here because the insn below will generate an LDRH instruction
3372           rather than an LDR instruction, so we cannot get an unaligned
3373           word access.  */
3374         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3375                    gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3376         DONE;
3377       }
3379     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3380       {
3381         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3382         DONE;
3383       }
3384     if (!s_register_operand (operands[1], HImode))
3385       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3386     operands[1] = gen_lowpart (SImode, operands[1]);
3387     operands[2] = gen_reg_rtx (SImode);
3389     if (TARGET_THUMB)
3390       {
3391         rtx ops[3];
3392         
3393         ops[0] = operands[2];
3394         ops[1] = operands[1];
3395         ops[2] = GEN_INT (16);
3396         
3397         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3398                                 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3399             
3400         ops[0] = operands[0];
3401         ops[1] = operands[2];
3402         ops[2] = GEN_INT (16);
3403         
3404         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3405                                 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3406         
3407         DONE;
3408       }
3409   }"
3412 (define_insn "*thumb_extendhisi2_insn"
3413   [(set (match_operand:SI                 0 "register_operand" "=l")
3414         (sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3415    (clobber (match_scratch:SI             2                   "=&l"))]
3416   "TARGET_THUMB"
3417   "*
3418   {
3419     rtx ops[4];
3420     rtx mem = XEXP (operands[1], 0);
3422     /* This code used to try to use 'V', and fix the address only if it was
3423        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3424        range of QImode offsets, and offsettable_address_p does a QImode
3425        address check.  */
3426        
3427     if (GET_CODE (mem) == CONST)
3428       mem = XEXP (mem, 0);
3429     
3430     if (GET_CODE (mem) == LABEL_REF)
3431       return \"ldr\\t%0, %1\";
3432     
3433     if (GET_CODE (mem) == PLUS)
3434       {
3435         rtx a = XEXP (mem, 0);
3436         rtx b = XEXP (mem, 1);
3438         if (GET_CODE (a) == LABEL_REF
3439             && GET_CODE (b) == CONST_INT)
3440           return \"ldr\\t%0, %1\";
3442         if (GET_CODE (b) == REG)
3443           return \"ldrsh\\t%0, %1\";
3444           
3445         ops[1] = a;
3446         ops[2] = b;
3447       }
3448     else
3449       {
3450         ops[1] = mem;
3451         ops[2] = const0_rtx;
3452       }
3453       
3454     if (GET_CODE (ops[1]) != REG)
3455       {
3456         debug_rtx (ops[1]);
3457         abort ();
3458       }
3460     ops[0] = operands[0];
3461     ops[3] = operands[2];
3462     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3463     return \"\";
3464   }"
3465   [(set_attr "length" "4")
3466    (set_attr "type" "load")
3467    (set_attr "pool_range" "1020")]
3470 (define_expand "extendhisi2_mem"
3471   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3472    (set (match_dup 3)
3473         (zero_extend:SI (match_dup 7)))
3474    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3475    (set (match_operand:SI 0 "" "")
3476         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3477   "TARGET_ARM"
3478   "
3479   {
3480     rtx mem1, mem2;
3481     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3483     mem1 = gen_rtx_MEM (QImode, addr);
3484     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3485     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3486     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3487     operands[0] = gen_lowpart (SImode, operands[0]);
3488     operands[1] = mem1;
3489     operands[2] = gen_reg_rtx (SImode);
3490     operands[3] = gen_reg_rtx (SImode);
3491     operands[6] = gen_reg_rtx (SImode);
3492     operands[7] = mem2;
3494     if (BYTES_BIG_ENDIAN)
3495       {
3496         operands[4] = operands[2];
3497         operands[5] = operands[3];
3498       }
3499     else
3500       {
3501         operands[4] = operands[3];
3502         operands[5] = operands[2];
3503       }
3504   }"
3507 (define_insn "*arm_extendhisi_insn"
3508   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3509         (sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3510   "TARGET_ARM && arm_arch4"
3511   "ldr%?sh\\t%0, %1"
3512   [(set_attr "type" "load")
3513    (set_attr "predicable" "yes")
3514    (set_attr "pool_range" "256")
3515    (set_attr "neg_pool_range" "244")]
3518 (define_split
3519   [(set (match_operand:SI                 0 "s_register_operand" "")
3520         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3521    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3522   "TARGET_ARM && (!arm_arch4)"
3523   [(set (match_dup 2) (match_dup 1))
3524    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3525   "
3526   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3527     FAIL;
3528   "
3531 (define_split
3532   [(set (match_operand:SI                   0 "s_register_operand" "")
3533         (match_operator:SI                  3 "shiftable_operator"
3534          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3535           (match_operand:SI                 4 "s_register_operand" "")]))
3536    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3537   "TARGET_ARM && (!arm_arch4)"
3538   [(set (match_dup 2) (match_dup 1))
3539    (set (match_dup 0)
3540         (match_op_dup 3
3541          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3542   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3543      FAIL;
3544   "
3547 (define_expand "extendqihi2"
3548   [(set (match_dup 2)
3549         (ashift:SI (match_operand:QI 1 "general_operand" "")
3550                    (const_int 24)))
3551    (set (match_operand:HI 0 "s_register_operand" "")
3552         (ashiftrt:SI (match_dup 2)
3553                      (const_int 24)))]
3554   "TARGET_ARM"
3555   "
3556   {
3557     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3558       {
3559         emit_insn (gen_rtx_SET (VOIDmode,
3560                                 operands[0],
3561                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3562         DONE;
3563       }
3564     if (!s_register_operand (operands[1], QImode))
3565       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3566     operands[0] = gen_lowpart (SImode, operands[0]);
3567     operands[1] = gen_lowpart (SImode, operands[1]);
3568     operands[2] = gen_reg_rtx (SImode);
3569   }"
3572 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3573 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3574 (define_insn "*extendqihi_insn"
3575   [(set (match_operand:HI                 0 "s_register_operand" "=r")
3576         (sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3577   "TARGET_ARM && arm_arch4"
3578   "*
3579   /* If the address is invalid, this will split the instruction into two. */
3580   if (bad_signed_byte_operand (operands[1], VOIDmode))
3581     return \"#\";
3582   return \"ldr%?sb\\t%0, %1\";
3583   "
3584   [(set_attr "type" "load")
3585    (set_attr "predicable" "yes")
3586    (set_attr "length" "8")
3587    (set_attr "pool_range" "256")
3588    (set_attr "neg_pool_range" "244")]
3591 (define_split
3592   [(set (match_operand:HI 0 "s_register_operand" "")
3593         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3594   "TARGET_ARM && arm_arch4 && reload_completed"
3595   [(set (match_dup 3) (match_dup 1))
3596    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3597   "
3598   {
3599     HOST_WIDE_INT offset;
3601     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3602     operands[2] = gen_rtx_MEM (QImode, operands[3]);
3603     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3604     operands[1] = XEXP (operands[1], 0);
3605     if (GET_CODE (operands[1]) == PLUS
3606         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3607         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3608              || const_ok_for_arm (-offset)))
3609       {
3610         HOST_WIDE_INT low = (offset > 0
3611                              ? (offset & 0xff) : -((-offset) & 0xff));
3612         XEXP (operands[2], 0) = plus_constant (operands[3], low);
3613         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3614       }
3615     /* Ensure the sum is in correct canonical form */
3616     else if (GET_CODE (operands[1]) == PLUS
3617              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3618              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3619       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3620                                            XEXP (operands[1], 1),
3621                                            XEXP (operands[1], 0));
3622   }"
3625 (define_expand "extendqisi2"
3626   [(set (match_dup 2)
3627         (ashift:SI (match_operand:QI 1 "general_operand" "")
3628                    (const_int 24)))
3629    (set (match_operand:SI 0 "s_register_operand" "")
3630         (ashiftrt:SI (match_dup 2)
3631                      (const_int 24)))]
3632   "TARGET_EITHER"
3633   "
3634   {
3635     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3636       {
3637         emit_insn (gen_rtx_SET (VOIDmode,
3638                                 operands[0],
3639                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3640         DONE;
3641       }
3642     if (!s_register_operand (operands[1], QImode))
3643       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3644     operands[1] = gen_lowpart (SImode, operands[1]);
3645     operands[2] = gen_reg_rtx (SImode);
3646     
3647     if (TARGET_THUMB)
3648       {
3649         rtx ops[3];
3650         
3651         ops[0] = operands[2];
3652         ops[1] = operands[1];
3653         ops[2] = GEN_INT (24);
3654         
3655         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3656                    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3658         ops[0] = operands[0];
3659         ops[1] = operands[2];
3660         ops[2] = GEN_INT (24);
3661         
3662         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3663                    gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3664         
3665         DONE;
3666       }
3667   }"
3670 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3671 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3672 (define_insn "*arm_extendqisi_insn"
3673   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3674         (sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3675   "TARGET_ARM && arm_arch4"
3676   "*
3677   /* If the address is invalid, this will split the instruction into two. */
3678   if (bad_signed_byte_operand (operands[1], VOIDmode))
3679     return \"#\";
3680   return \"ldr%?sb\\t%0, %1\";
3681   "
3682   [(set_attr "type" "load")
3683    (set_attr "predicable" "yes")
3684    (set_attr "length" "8")
3685    (set_attr "pool_range" "256")
3686    (set_attr "neg_pool_range" "244")]
3689 (define_split
3690   [(set (match_operand:SI 0 "s_register_operand" "")
3691         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3692   "TARGET_ARM && arm_arch4 && reload_completed"
3693   [(set (match_dup 0) (match_dup 1))
3694    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3695   "
3696   {
3697     HOST_WIDE_INT offset;
3699     operands[2] = gen_rtx_MEM (QImode, operands[0]);
3700     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3701     operands[1] = XEXP (operands[1], 0);
3702     if (GET_CODE (operands[1]) == PLUS
3703         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3704         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3705              || const_ok_for_arm (-offset)))
3706       {
3707         HOST_WIDE_INT low = (offset > 0
3708                              ? (offset & 0xff) : -((-offset) & 0xff));
3709         XEXP (operands[2], 0) = plus_constant (operands[0], low);
3710         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3711       }
3712     /* Ensure the sum is in correct canonical form */
3713     else if (GET_CODE (operands[1]) == PLUS
3714              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3715              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3716       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3717                                            XEXP (operands[1], 1),
3718                                            XEXP (operands[1], 0));
3719   }"
3722 (define_insn "*thumb_extendqisi2_insn"
3723   [(set (match_operand:SI                 0 "register_operand" "=l,l")
3724         (sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3725   "TARGET_THUMB"
3726   "*
3727   {
3728     rtx ops[3];
3729     rtx mem = XEXP (operands[1], 0);
3730     
3731     if (GET_CODE (mem) == CONST)
3732       mem = XEXP (mem, 0);
3733     
3734     if (GET_CODE (mem) == LABEL_REF)
3735       return \"ldr\\t%0, %1\";
3737     if (GET_CODE (mem) == PLUS
3738         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3739       return \"ldr\\t%0, %1\";
3740       
3741     if (which_alternative == 0)
3742       return \"ldrsb\\t%0, %1\";
3743       
3744     ops[0] = operands[0];
3745     
3746     if (GET_CODE (mem) == PLUS)
3747       {
3748         rtx a = XEXP (mem, 0);
3749         rtx b = XEXP (mem, 1);
3750         
3751         ops[1] = a;
3752         ops[2] = b;
3754         if (GET_CODE (a) == REG)
3755           {
3756             if (GET_CODE (b) == REG)
3757               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3758             else if (REGNO (a) == REGNO (ops[0]))
3759               {
3760                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3761                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3762                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3763               }
3764             else
3765               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3766           }
3767         else if (GET_CODE (b) != REG)
3768           abort ();
3769         else
3770           {
3771             if (REGNO (b) == REGNO (ops[0]))
3772               {
3773                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3774                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3775                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3776               }
3777             else
3778               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3779           }
3780       }
3781     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3782       {
3783         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3784         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3785         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3786       }
3787     else
3788       {
3789         ops[1] = mem;
3790         ops[2] = const0_rtx;
3791         
3792         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3793       }
3794     return \"\";
3795   }"
3796   [(set_attr "length" "2,6")
3797    (set_attr "type" "load,load")
3798    (set_attr "pool_range" "32,32")]
3801 (define_insn "extendsfdf2"
3802   [(set (match_operand:DF                  0 "s_register_operand" "=f")
3803         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "f")))]
3804   "TARGET_ARM && TARGET_HARD_FLOAT"
3805   "mvf%?d\\t%0, %1"
3806   [(set_attr "type" "ffarith")
3807    (set_attr "predicable" "yes")]
3810 (define_insn "extendsfxf2"
3811   [(set (match_operand:XF 0 "s_register_operand" "=f")
3812         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3813   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3814   "mvf%?e\\t%0, %1"
3815   [(set_attr "type" "ffarith")
3816    (set_attr "predicable" "yes")]
3819 (define_insn "extenddfxf2"
3820   [(set (match_operand:XF 0 "s_register_operand" "=f")
3821         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3822   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3823   "mvf%?e\\t%0, %1"
3824   [(set_attr "type" "ffarith")
3825    (set_attr "predicable" "yes")]
3829 ;; Move insns (including loads and stores)
3831 ;; XXX Just some ideas about movti.
3832 ;; I don't think these are a good idea on the arm, there just aren't enough
3833 ;; registers
3834 ;;(define_expand "loadti"
3835 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3836 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3837 ;;  "" "")
3839 ;;(define_expand "storeti"
3840 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3841 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3842 ;;  "" "")
3844 ;;(define_expand "movti"
3845 ;;  [(set (match_operand:TI 0 "general_operand" "")
3846 ;;      (match_operand:TI 1 "general_operand" ""))]
3847 ;;  ""
3848 ;;  "
3850 ;;  rtx insn;
3852 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3853 ;;    operands[1] = copy_to_reg (operands[1]);
3854 ;;  if (GET_CODE (operands[0]) == MEM)
3855 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3856 ;;  else if (GET_CODE (operands[1]) == MEM)
3857 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3858 ;;  else
3859 ;;    FAIL;
3861 ;;  emit_insn (insn);
3862 ;;  DONE;
3863 ;;}")
3865 ;; Recognise garbage generated above.
3867 ;;(define_insn ""
3868 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3869 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3870 ;;  ""
3871 ;;  "*
3872 ;;  {
3873 ;;    register mem = (which_alternative < 3);
3874 ;;    register const char *template;
3876 ;;    operands[mem] = XEXP (operands[mem], 0);
3877 ;;    switch (which_alternative)
3878 ;;      {
3879 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3880 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3881 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3882 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3883 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3884 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3885 ;;      }
3886 ;;    output_asm_insn (template, operands);
3887 ;;    return \"\";
3888 ;;  }")
3890 (define_expand "movdi"
3891   [(set (match_operand:DI 0 "general_operand" "")
3892         (match_operand:DI 1 "general_operand" ""))]
3893   "TARGET_EITHER"
3894   "
3895   if (TARGET_THUMB)
3896     {
3897       if (!no_new_pseudos)
3898         {
3899           if (GET_CODE (operands[0]) != REG)
3900             operands[1] = force_reg (DImode, operands[1]);
3901         }
3902     }
3903   "
3906 (define_insn "*arm_movdi"
3907   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3908         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3909   "TARGET_ARM
3910   "
3911   "*
3912   return (output_move_double (operands));
3913   "
3914   [(set_attr "length" "8")
3915    (set_attr "type" "*,load,store2")
3916    (set_attr "pool_range" "*,1020,*")
3917    (set_attr "neg_pool_range" "*,1012,*")]
3920 ;;; ??? This should have alternatives for constants.
3921 ;;; ??? This was originally identical to the movdf_insn pattern.
3922 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3923 ;;; thumb_reorg with a memory reference.
3924 (define_insn "*thumb_movdi_insn"
3925   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3926         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3927   "TARGET_THUMB
3928    && (   register_operand (operands[0], DImode)
3929        || register_operand (operands[1], DImode))"
3930   "*
3931   {
3932   switch (which_alternative)
3933     {
3934     default:
3935     case 0:
3936       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3937         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3938       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3939     case 1:
3940       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3941     case 2:
3942       operands[1] = GEN_INT (- INTVAL (operands[1]));
3943       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3944     case 3:
3945       return \"ldmia\\t%1, {%0, %H0}\";
3946     case 4:
3947       return \"stmia\\t%0, {%1, %H1}\";
3948     case 5:
3949       return thumb_load_double_from_address (operands);
3950     case 6:
3951       operands[2] = gen_rtx (MEM, SImode,
3952                              plus_constant (XEXP (operands[0], 0), 4));
3953       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3954       return \"\";
3955     case 7:
3956       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3957         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3958       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3959     }
3960   }"
3961   [(set_attr "length" "4,4,6,2,2,6,4,4")
3962    (set_attr "type" "*,*,*,load,store2,load,store2,*")
3963    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3966 (define_expand "movsi"
3967   [(set (match_operand:SI 0 "general_operand" "")
3968         (match_operand:SI 1 "general_operand" ""))]
3969   "TARGET_EITHER"
3970   "
3971   if (TARGET_ARM)
3972     {
3973       /* Everything except mem = const or mem = mem can be done easily */
3974       if (GET_CODE (operands[0]) == MEM)
3975         operands[1] = force_reg (SImode, operands[1]);
3976       if (GET_CODE (operands[1]) == CONST_INT
3977           && !(const_ok_for_arm (INTVAL (operands[1]))
3978                || const_ok_for_arm (~INTVAL (operands[1]))))
3979         {
3980            arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3981                               NULL_RTX,
3982                               (no_new_pseudos ? 0
3983                                : preserve_subexpressions_p ()));
3984           DONE;
3985         }
3986     }
3987   else /* TARGET_THUMB.... */
3988     {
3989       if (!no_new_pseudos)
3990         {
3991           if (GET_CODE (operands[0]) != REG)
3992             operands[1] = force_reg (SImode, operands[1]);
3993         }
3994     }
3995     
3996   if (flag_pic
3997       && (CONSTANT_P (operands[1])
3998          || symbol_mentioned_p (operands[1])
3999          || label_mentioned_p (operands[1])))
4000     operands[1] = legitimize_pic_address (operands[1], SImode,
4001                                           (no_new_pseudos ? operands[0] : 0));
4002   "
4005 (define_insn "*arm_movsi_insn"
4006   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4007         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4008   "TARGET_ARM
4009    && (   register_operand (operands[0], SImode)
4010        || register_operand (operands[1], SImode))"
4011   "@
4012    mov%?\\t%0, %1
4013    mvn%?\\t%0, #%B1
4014    ldr%?\\t%0, %1
4015    str%?\\t%1, %0"
4016   [(set_attr "type" "*,*,load,store1")
4017    (set_attr "predicable" "yes")
4018    (set_attr "pool_range" "*,*,4096,*")
4019    (set_attr "neg_pool_range" "*,*,4084,*")]
4022 (define_split
4023   [(set (match_operand:SI 0 "s_register_operand" "")
4024         (match_operand:SI 1 "const_int_operand" ""))]
4025   "TARGET_ARM
4026   && (!(const_ok_for_arm (INTVAL (operands[1]))
4027         || const_ok_for_arm (~INTVAL (operands[1]))))"
4028   [(clobber (const_int 0))]
4029   "
4030   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4031                       NULL_RTX, 0);
4032   DONE;
4033   "
4036 (define_insn "*thumb_movsi_insn"
4037   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4038         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4039   "TARGET_THUMB
4040    && (   register_operand (operands[0], SImode) 
4041        || register_operand (operands[1], SImode))"
4042   "@
4043    mov  %0, %1
4044    mov  %0, %1
4045    #
4046    #
4047    ldmia\\t%1, {%0}
4048    stmia\\t%0, {%1}
4049    ldr\\t%0, %1
4050    str\\t%1, %0
4051    mov\\t%0, %1"
4052   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4053    (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4054    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4057 (define_split 
4058   [(set (match_operand:SI 0 "register_operand" "")
4059         (match_operand:SI 1 "const_int_operand" ""))]
4060   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4061   [(set (match_dup 0) (match_dup 1))
4062    (set (match_dup 0) (neg:SI (match_dup 0)))]
4063   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4066 (define_split 
4067   [(set (match_operand:SI 0 "register_operand" "")
4068         (match_operand:SI 1 "const_int_operand" ""))]
4069   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4070   [(set (match_dup 0) (match_dup 1))
4071    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4072   "
4073   {
4074     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4075     unsigned HOST_WIDE_INT mask = 0xff;
4076     int i;
4077     
4078     for (i = 0; i < 25; i++)
4079       if ((val & (mask << i)) == val)
4080         break;
4082     if (i == 0)
4083       FAIL;
4085     operands[1] = GEN_INT (val >> i);
4086     operands[2] = GEN_INT (i);
4087   }"
4090 (define_expand "movaddr"
4091   [(set (match_operand:SI 0 "s_register_operand" "")
4092         (match_operand:DI 1 "address_operand" ""))]
4093   "TARGET_ARM"
4094   ""
4097 (define_insn "*movaddr_insn"
4098   [(set (match_operand:SI 0 "s_register_operand" "=r")
4099         (match_operand:DI 1 "address_operand" "p"))]
4100   "TARGET_ARM
4101    && reload_completed
4102    && (GET_CODE (operands[1]) == LABEL_REF
4103        || (GET_CODE (operands[1]) == CONST
4104            && GET_CODE (XEXP (operands[1], 0)) == PLUS
4105            && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
4106            && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
4107   "adr%?\\t%0, %a1"
4108   [(set_attr "predicable" "yes")]
4111 ;; When generating pic, we need to load the symbol offset into a register.
4112 ;; So that the optimizer does not confuse this with a normal symbol load
4113 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4114 ;; since that is the only type of relocation we can use.
4116 ;; The rather odd constraints on the following are to force reload to leave
4117 ;; the insn alone, and to force the minipool generation pass to then move
4118 ;; the GOT symbol to memory.
4120 (define_insn "pic_load_addr_arm"
4121   [(set (match_operand:SI 0 "s_register_operand" "=r")
4122         (unspec:SI [(match_operand:SI 1 "" "mX")] 3))]
4123   "TARGET_ARM && flag_pic"
4124   "ldr%?\\t%0, %1"
4125   [(set_attr "type" "load")
4126    (set (attr "pool_range")     (const_int 4096))
4127    (set (attr "neg_pool_range") (const_int 4084))]
4130 (define_insn "pic_load_addr_thumb"
4131   [(set (match_operand:SI 0 "s_register_operand" "=l")
4132         (unspec:SI [(match_operand:SI 1 "" "mX")] 3))]
4133   "TARGET_THUMB && flag_pic"
4134   "ldr\\t%0, %1"
4135   [(set_attr "type" "load")
4136    (set (attr "pool_range") (const_int 1024))]
4139 ;; This variant is used for AOF assembly, since it needs to mention the
4140 ;; pic register in the rtl.
4141 (define_expand "pic_load_addr_based"
4142   [(set (match_operand:SI 0 "s_register_operand" "=r")
4143         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
4144   "TARGET_ARM && flag_pic"
4145   "operands[2] = pic_offset_table_rtx;"
4148 (define_insn "*pic_load_addr_based_insn"
4149   [(set (match_operand:SI 0 "s_register_operand" "=r")
4150         (unspec:SI [(match_operand 1 "" "")
4151                     (match_operand 2 "s_register_operand" "r")] 3))]
4152   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4153   "*
4154 #ifdef AOF_ASSEMBLER
4155   operands[1] = aof_pic_entry (operands[1]);
4156 #endif
4157   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4158   return \"\";
4159   "
4160   [(set_attr "type" "load")
4161    (set (attr "pool_range")
4162         (if_then_else (eq_attr "is_thumb" "yes")
4163                       (const_int 1024)
4164                       (const_int 4096)))
4165    (set (attr "neg_pool_range")
4166         (if_then_else (eq_attr "is_thumb" "yes")
4167                       (const_int 0)
4168                       (const_int 4084)))]
4171 (define_insn "pic_add_dot_plus_four"
4172   [(set (match_operand:SI 0 "register_operand" "+r")
4173         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4174    (use (label_ref (match_operand 1 "" "")))]
4175   "TARGET_THUMB && flag_pic"
4176   "*
4177   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4178                              CODE_LABEL_NUMBER (operands[1]));
4179   return \"add\\t%0, %|pc\";
4180   "
4181   [(set_attr "length" "2")]
4184 (define_insn "pic_add_dot_plus_eight"
4185   [(set (match_operand:SI 0 "register_operand" "+r")
4186         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4187    (use (label_ref (match_operand 1 "" "")))]
4188   "TARGET_ARM && flag_pic"
4189   "*
4190     ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4191                                CODE_LABEL_NUMBER (operands[1]));
4192     return \"add%?\\t%0, %|pc, %0\";
4193   "
4194   [(set_attr "predicable" "yes")]
4197 ;; If copying one reg to another we can set the condition codes according to
4198 ;; its value.  Such a move is common after a return from subroutine and the
4199 ;; result is being tested against zero.
4201 (define_insn "*movsi_compare0"
4202   [(set (reg:CC CC_REGNUM)
4203         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4204                     (const_int 0)))
4205    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4206         (match_dup 1))]
4207   "TARGET_ARM"
4208   "@
4209    cmp%?\\t%0, #0
4210    sub%?s\\t%0, %1, #0"
4211   [(set_attr "conds" "set")]
4214 ;; Subroutine to store a half word from a register into memory.
4215 ;; Operand 0 is the source register (HImode)
4216 ;; Operand 1 is the destination address in a register (SImode)
4218 ;; In both this routine and the next, we must be careful not to spill
4219 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4220 ;; can generate unrecognizable rtl.
4222 (define_expand "storehi"
4223   [;; store the low byte
4224    (set (match_operand 1 "" "") (match_dup 3))
4225    ;; extract the high byte
4226    (set (match_dup 2)
4227         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4228    ;; store the high byte
4229    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
4230   "TARGET_ARM"
4231   "
4232   {
4233     rtx addr = XEXP (operands[1], 0);
4234     enum rtx_code code = GET_CODE (addr);
4236     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4237         || code == MINUS)
4238       addr = force_reg (SImode, addr);
4240     operands[4] = change_address (operands[1], QImode,
4241                                   plus_constant (addr, 1));
4242     operands[1] = change_address (operands[1], QImode, NULL_RTX);
4243     operands[3] = gen_lowpart (QImode, operands[0]);
4244     operands[0] = gen_lowpart (SImode, operands[0]);
4245     operands[2] = gen_reg_rtx (SImode); 
4246   }"
4249 (define_expand "storehi_bigend"
4250   [(set (match_dup 4) (match_dup 3))
4251    (set (match_dup 2)
4252         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4253    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
4254   "TARGET_ARM"
4255   "
4256   {
4257     rtx addr = XEXP (operands[1], 0);
4258     enum rtx_code code = GET_CODE (addr);
4260     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4261         || code == MINUS)
4262       addr = force_reg (SImode, addr);
4264     operands[4] = change_address (operands[1], QImode,
4265                                   plus_constant (addr, 1));
4266     operands[1] = change_address (operands[1], QImode, NULL_RTX);
4267     operands[3] = gen_lowpart (QImode, operands[0]);
4268     operands[0] = gen_lowpart (SImode, operands[0]);
4269     operands[2] = gen_reg_rtx (SImode);
4270   }"
4273 ;; Subroutine to store a half word integer constant into memory.
4274 (define_expand "storeinthi"
4275   [(set (match_operand 0 "" "")
4276         (subreg:QI (match_operand 1 "" "") 0))
4277    (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
4278   "TARGET_ARM"
4279   "
4280   {
4281     HOST_WIDE_INT value = INTVAL (operands[1]);
4282     rtx addr = XEXP (operands[0], 0);
4283     enum rtx_code code = GET_CODE (addr);
4285     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4286         || code == MINUS)
4287       addr = force_reg (SImode, addr);
4289     operands[1] = gen_reg_rtx (SImode);
4290     if (BYTES_BIG_ENDIAN)
4291       {
4292         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4293         if ((value & 255) == ((value >> 8) & 255))
4294           operands[2] = operands[1];
4295         else
4296           {
4297             operands[2] = gen_reg_rtx (SImode);
4298             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4299           }
4300       }
4301     else
4302       {
4303         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4304         if ((value & 255) == ((value >> 8) & 255))
4305           operands[2] = operands[1];
4306         else
4307           {
4308             operands[2] = gen_reg_rtx (SImode);
4309             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4310           }
4311       }
4313     operands[3] = change_address (operands[0], QImode,
4314                                   plus_constant (addr, 1));
4315     operands[0] = change_address (operands[0], QImode, NULL_RTX);
4316   }"
4319 (define_expand "storehi_single_op"
4320   [(set (match_operand:HI 0 "memory_operand" "")
4321         (match_operand:HI 1 "general_operand" ""))]
4322   "TARGET_ARM && arm_arch4"
4323   "
4324   if (!s_register_operand (operands[1], HImode))
4325     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4326   "
4329 (define_expand "movhi"
4330   [(set (match_operand:HI 0 "general_operand" "")
4331         (match_operand:HI 1 "general_operand" ""))]
4332   "TARGET_EITHER"
4333   "
4334   if (TARGET_ARM)
4335     {
4336       if (!no_new_pseudos)
4337         {
4338           if (GET_CODE (operands[0]) == MEM)
4339             {
4340               if (arm_arch4)
4341                 {
4342                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4343                   DONE;
4344                 }
4345               if (GET_CODE (operands[1]) == CONST_INT)
4346                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4347               else
4348                 {
4349                   if (GET_CODE (operands[1]) == MEM)
4350                     operands[1] = force_reg (HImode, operands[1]);
4351                   if (BYTES_BIG_ENDIAN)
4352                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4353                   else
4354                    emit_insn (gen_storehi (operands[1], operands[0]));
4355                 }
4356               DONE;
4357             }
4358           /* Sign extend a constant, and keep it in an SImode reg.  */
4359           else if (GET_CODE (operands[1]) == CONST_INT)
4360             {
4361               rtx reg = gen_reg_rtx (SImode);
4362               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4364               /* If the constant is already valid, leave it alone.  */
4365               if (!const_ok_for_arm (val))
4366                 {
4367                   /* If setting all the top bits will make the constant 
4368                      loadable in a single instruction, then set them.  
4369                      Otherwise, sign extend the number.  */
4371                   if (const_ok_for_arm (~(val | ~0xffff)))
4372                     val |= ~0xffff;
4373                   else if (val & 0x8000)
4374                     val |= ~0xffff;
4375                 }
4377               emit_insn (gen_movsi (reg, GEN_INT (val)));
4378               operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
4379             }
4380           else if (!arm_arch4)
4381             {
4382              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4383                 for v4 and up architectures because LDRH instructions will
4384                 be used to access the HI values, and these cannot generate
4385                 unaligned word access faults in the MMU.  */
4386               if (GET_CODE (operands[1]) == MEM)
4387                 {
4388                   if (TARGET_MMU_TRAPS)
4389                     {
4390                       rtx base;
4391                       rtx offset = const0_rtx;
4392                       rtx reg = gen_reg_rtx (SImode);
4394                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4395                            || (GET_CODE (base) == PLUS
4396                                && (GET_CODE (offset = XEXP (base, 1))
4397                                    == CONST_INT)
4398                                && ((INTVAL(offset) & 1) != 1)
4399                                && GET_CODE (base = XEXP (base, 0)) == REG))
4400                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4401                         {
4402                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4403                           rtx new;
4405                           new = gen_rtx_MEM (SImode,
4406                                              plus_constant (base, new_offset));
4407                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4408                           emit_insn (gen_movsi (reg, new));
4409                           if (((INTVAL (offset) & 2) != 0)
4410                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4411                             {
4412                               rtx reg2 = gen_reg_rtx (SImode);
4414                               emit_insn (gen_lshrsi3 (reg2, reg,
4415                                          GEN_INT (16)));
4416                               reg = reg2;
4417                             }
4418                         }
4419                       else
4420                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4422                       operands[1] = gen_lowpart (HImode, reg);
4423                     }
4424                   else if (BYTES_BIG_ENDIAN)
4425                     {
4426                       rtx base;
4427                       rtx offset = const0_rtx;
4429                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4430                            || (GET_CODE (base) == PLUS
4431                               && (GET_CODE (offset = XEXP (base, 1))
4432                                   == CONST_INT)
4433                               && GET_CODE (base = XEXP (base, 0)) == REG))
4434                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4435                         {
4436                           rtx reg = gen_reg_rtx (SImode);
4437                           rtx new;
4439                           if ((INTVAL (offset) & 2) == 2)
4440                             {
4441                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4442                               new = gen_rtx_MEM (SImode,
4443                                                  plus_constant (base,
4444                                                                 new_offset));
4445                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4446                               emit_insn (gen_movsi (reg, new));
4447                             }
4448                           else
4449                             {
4450                               new = gen_rtx_MEM (SImode,
4451                                                  XEXP (operands[1], 0));
4452                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4453                               emit_insn (gen_rotated_loadsi (reg, new));
4454                             }
4456                           operands[1] = gen_lowpart (HImode, reg);
4457                         }
4458                       else
4459                         {
4460                           emit_insn (gen_movhi_bigend (operands[0],
4461                                                        operands[1]));
4462                           DONE;
4463                         }
4464                     }
4465                }
4466            }
4467         }
4468       /* Handle loading a large integer during reload */
4469       else if (GET_CODE (operands[1]) == CONST_INT
4470                && !const_ok_for_arm (INTVAL (operands[1]))
4471                && !const_ok_for_arm (~INTVAL (operands[1])))
4472         {
4473           /* Writing a constant to memory needs a scratch, which should
4474              be handled with SECONDARY_RELOADs.  */
4475           if (GET_CODE (operands[0]) != REG)
4476             abort ();
4478           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4479           emit_insn (gen_movsi (operands[0], operands[1]));
4480           DONE;
4481        }
4482     }
4483   else /* TARGET_THUMB */
4484     {
4485       if (!no_new_pseudos)
4486         {
4487           if (GET_CODE (operands[0]) != REG)
4488             operands[1] = force_reg (HImode, operands[1]);
4490           /* ??? We shouldn't really get invalid addresses here, but this can
4491              happen if we are passed a SP (never OK for HImode/QImode) or 
4492              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4493              HImode/QImode) relative address.  */
4494           /* ??? This should perhaps be fixed elsewhere, for instance, in
4495              fixup_stack_1, by checking for other kinds of invalid addresses,
4496              e.g. a bare reference to a virtual register.  This may confuse the
4497              alpha though, which must handle this case differently.  */
4498           if (GET_CODE (operands[0]) == MEM
4499               && !memory_address_p (GET_MODE (operands[0]),
4500                                     XEXP (operands[0], 0)))
4501             {
4502               rtx temp = copy_to_reg (XEXP (operands[0], 0));
4503               operands[0] = change_address (operands[0], VOIDmode, temp);
4504             }
4505    
4506           if (GET_CODE (operands[1]) == MEM
4507               && !memory_address_p (GET_MODE (operands[1]),
4508                                     XEXP (operands[1], 0)))
4509             {
4510               rtx temp = copy_to_reg (XEXP (operands[1], 0));
4511               operands[1] = change_address (operands[1], VOIDmode, temp);
4512             }
4513         }
4514       /* Handle loading a large integer during reload */
4515       else if (GET_CODE (operands[1]) == CONST_INT
4516                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4517         {
4518           /* Writing a constant to memory needs a scratch, which should
4519              be handled with SECONDARY_RELOADs.  */
4520           if (GET_CODE (operands[0]) != REG)
4521             abort ();
4523           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4524           emit_insn (gen_movsi (operands[0], operands[1]));
4525           DONE;
4526         }
4527     }
4528   "
4531 (define_insn "*thumb_movhi_insn"
4532   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4533         (match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4534   "TARGET_THUMB
4535    && (   register_operand (operands[0], HImode)
4536        || register_operand (operands[1], HImode))"
4537   "*
4538   switch (which_alternative)
4539     {
4540     case 0: return \"add        %0, %1, #0\";
4541     case 2: return \"strh       %1, %0\";
4542     case 3: return \"mov        %0, %1\";
4543     case 4: return \"mov        %0, %1\";
4544     case 5: return \"mov        %0, %1\";
4545     default: abort ();
4546     case 1:
4547       /* The stack pointer can end up being taken as an index register.
4548           Catch this case here and deal with it.  */
4549       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4550           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4551           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4552         {
4553           rtx ops[2];
4554           ops[0] = operands[0];
4555           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4556       
4557           output_asm_insn (\"mov        %0, %1\", ops);
4559           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4560     
4561         }
4562       return \"ldrh     %0, %1\";
4563     }"
4564   [(set_attr "length" "2,4,2,2,2,2")
4565    (set_attr "type" "*,load,store1,*,*,*")
4566    (set_attr "pool_range" "*,64,*,*,*,*")]
4570 (define_insn "rotated_loadsi"
4571   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4572         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4573                    (const_int 16)))]
4574   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4575   "*
4576   {
4577     rtx ops[2];
4579     ops[0] = operands[0];
4580     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4581     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4582     return \"\";
4583   }"
4584   [(set_attr "type" "load")
4585    (set_attr "predicable" "yes")]
4588 (define_expand "movhi_bytes"
4589   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4590    (set (match_dup 3)
4591         (zero_extend:SI (match_dup 6)))
4592    (set (match_operand:SI 0 "" "")
4593          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4594   "TARGET_ARM"
4595   "
4596   {
4597     rtx mem1, mem2;
4598     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4600     mem1 = gen_rtx_MEM (QImode, addr);
4601     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4602     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4603     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4604     operands[0] = gen_lowpart (SImode, operands[0]);
4605     operands[1] = mem1;
4606     operands[2] = gen_reg_rtx (SImode);
4607     operands[3] = gen_reg_rtx (SImode);
4608     operands[6] = mem2;
4610     if (BYTES_BIG_ENDIAN)
4611       {
4612         operands[4] = operands[2];
4613         operands[5] = operands[3];
4614       }
4615     else
4616       {
4617         operands[4] = operands[3];
4618         operands[5] = operands[2];
4619       }
4620   }"
4623 (define_expand "movhi_bigend"
4624   [(set (match_dup 2)
4625         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4626                    (const_int 16)))
4627    (set (match_dup 3)
4628         (ashiftrt:SI (match_dup 2) (const_int 16)))
4629    (set (match_operand:HI 0 "s_register_operand" "")
4630         (subreg:HI (match_dup 3) 0))]
4631   "TARGET_ARM"
4632   "
4633   operands[2] = gen_reg_rtx (SImode);
4634   operands[3] = gen_reg_rtx (SImode);
4635   "
4638 ;; Pattern to recognise insn generated default case above
4639 (define_insn "*movhi_insn_arch4"
4640   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4641         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4642   "TARGET_ARM
4643    && arm_arch4
4644    && (GET_CODE (operands[1]) != CONST_INT
4645        || const_ok_for_arm (INTVAL (operands[1]))
4646        || const_ok_for_arm (~INTVAL (operands[1])))"
4647   "@
4648    mov%?\\t%0, %1\\t%@ movhi
4649    mvn%?\\t%0, #%B1\\t%@ movhi
4650    str%?h\\t%1, %0\\t%@ movhi 
4651    ldr%?h\\t%0, %1\\t%@ movhi"
4652   [(set_attr "type" "*,*,store1,load")
4653    (set_attr "predicable" "yes")
4654    (set_attr "pool_range" "*,*,*,256")
4655    (set_attr "neg_pool_range" "*,*,*,244")]
4658 (define_insn "*movhi_insn_littleend"
4659   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4660         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4661   "TARGET_ARM
4662    && !arm_arch4
4663    && !BYTES_BIG_ENDIAN
4664    && !TARGET_MMU_TRAPS
4665    && (GET_CODE (operands[1]) != CONST_INT
4666        || const_ok_for_arm (INTVAL (operands[1]))
4667        || const_ok_for_arm (~INTVAL (operands[1])))"
4668   "@
4669    mov%?\\t%0, %1\\t%@ movhi
4670    mvn%?\\t%0, #%B1\\t%@ movhi
4671    ldr%?\\t%0, %1\\t%@ movhi"
4672   [(set_attr "type" "*,*,load")
4673    (set_attr "predicable" "yes")
4674    (set_attr "pool_range" "4096")
4675    (set_attr "neg_pool_range" "4084")]
4678 (define_insn "*movhi_insn_bigend"
4679   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4680         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4681   "TARGET_ARM
4682    && !arm_arch4
4683    && BYTES_BIG_ENDIAN
4684    && !TARGET_MMU_TRAPS
4685    && (GET_CODE (operands[1]) != CONST_INT
4686        || const_ok_for_arm (INTVAL (operands[1]))
4687        || const_ok_for_arm (~INTVAL (operands[1])))"
4688   "@
4689    mov%?\\t%0, %1\\t%@ movhi
4690    mvn%?\\t%0, #%B1\\t%@ movhi
4691    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4692   [(set_attr "type" "*,*,load")
4693    (set_attr "predicable" "yes")
4694    (set_attr "length" "4,4,8")
4695    (set_attr "pool_range" "*,*,4092")
4696    (set_attr "neg_pool_range" "*,*,4084")]
4699 (define_insn "*loadhi_si_bigend"
4700   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4701         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4702                    (const_int 16)))]
4703   "TARGET_ARM
4704    && BYTES_BIG_ENDIAN
4705    && !TARGET_MMU_TRAPS"
4706   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4707   [(set_attr "type" "load")
4708    (set_attr "predicable" "yes")
4709    (set_attr "pool_range" "4096")
4710    (set_attr "neg_pool_range" "4084")]
4713 (define_insn "*movhi_bytes"
4714   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4715         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4716   "TARGET_ARM && TARGET_MMU_TRAPS"
4717   "@
4718    mov%?\\t%0, %1\\t%@ movhi
4719    mvn%?\\t%0, #%B1\\t%@ movhi"
4720   [(set_attr "predicable" "yes")]
4723 (define_insn "thumb_movhi_clobber"
4724   [(set (match_operand:HI     0 "memory_operand"   "=m")
4725         (match_operand:HI     1 "register_operand" "l"))
4726    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4727   "TARGET_THUMB"
4728   "*
4729   abort ();"
4731         
4732 ;; We use a DImode scratch because we may occasionally need an additional
4733 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4734 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4735 (define_expand "reload_outhi"
4736   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4737               (match_operand:HI 1 "s_register_operand"        "r")
4738               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4739   "TARGET_EITHER"
4740   "if (TARGET_ARM)
4741      arm_reload_out_hi (operands);
4742    else
4743      thumb_reload_out_hi (operands);
4744   DONE;
4745   "
4748 (define_expand "reload_inhi"
4749   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4750               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4751               (match_operand:DI 2 "s_register_operand" "=&r")])]
4752   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4753   "
4754   if (TARGET_ARM)
4755     arm_reload_in_hi (operands);
4756   else
4757     thumb_reload_out_hi (operands);
4758   DONE;
4761 (define_expand "movqi"
4762   [(set (match_operand:QI 0 "general_operand" "")
4763         (match_operand:QI 1 "general_operand" ""))]
4764   "TARGET_EITHER"
4765   "
4766   if (TARGET_ARM)
4767     {
4768       /* Everything except mem = const or mem = mem can be done easily */
4770       if (!no_new_pseudos)
4771         {
4772           if (GET_CODE (operands[1]) == CONST_INT)
4773             {
4774               rtx reg = gen_reg_rtx (SImode);
4776               emit_insn (gen_movsi (reg, operands[1]));
4777               operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
4778             }
4779          if (GET_CODE (operands[0]) == MEM)
4780            operands[1] = force_reg (QImode, operands[1]);
4781        }
4782     }
4783   else /* TARGET_THUMB */
4784     {
4785       if (!no_new_pseudos)
4786         {
4787           if (GET_CODE (operands[0]) != REG)
4788             operands[1] = force_reg (QImode, operands[1]);
4790           /* ??? We shouldn't really get invalid addresses here, but this can
4791              happen if we are passed a SP (never OK for HImode/QImode) or
4792              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4793              HImode/QImode) relative address.  */
4794           /* ??? This should perhaps be fixed elsewhere, for instance, in
4795              fixup_stack_1, by checking for other kinds of invalid addresses,
4796              e.g. a bare reference to a virtual register.  This may confuse the
4797              alpha though, which must handle this case differently.  */
4798           if (GET_CODE (operands[0]) == MEM
4799               && !memory_address_p (GET_MODE (operands[0]),
4800                                      XEXP (operands[0], 0)))
4801             {
4802               rtx temp = copy_to_reg (XEXP (operands[0], 0));
4803               operands[0] = change_address (operands[0], VOIDmode, temp);
4804             }
4805           if (GET_CODE (operands[1]) == MEM
4806               && !memory_address_p (GET_MODE (operands[1]),
4807                                     XEXP (operands[1], 0)))
4808             {
4809                rtx temp = copy_to_reg (XEXP (operands[1], 0));
4810                operands[1] = change_address (operands[1], VOIDmode, temp);
4811             }
4812         }
4813       /* Handle loading a large integer during reload */
4814       else if (GET_CODE (operands[1]) == CONST_INT
4815                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4816         {
4817           /* Writing a constant to memory needs a scratch, which should
4818              be handled with SECONDARY_RELOADs.  */
4819           if (GET_CODE (operands[0]) != REG)
4820             abort ();
4822           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4823           emit_insn (gen_movsi (operands[0], operands[1]));
4824           DONE;
4825        }
4826     }
4827   "
4831 (define_insn "*arm_movqi_insn"
4832   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4833         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4834   "TARGET_ARM
4835    && (   register_operand (operands[0], QImode)
4836        || register_operand (operands[1], QImode))"
4837   "@
4838    mov%?\\t%0, %1
4839    mvn%?\\t%0, #%B1
4840    ldr%?b\\t%0, %1
4841    str%?b\\t%1, %0"
4842   [(set_attr "type" "*,*,load,store1")
4843    (set_attr "predicable" "yes")]
4846 (define_insn "*thumb_movqi_insn"
4847   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4848         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4849   "TARGET_THUMB
4850    && (   register_operand (operands[0], QImode)
4851        || register_operand (operands[1], QImode))"
4852   "@
4853    add\\t%0, %1, #0
4854    ldrb\\t%0, %1
4855    strb\\t%1, %0
4856    mov\\t%0, %1
4857    mov\\t%0, %1
4858    mov\\t%0, %1"
4859   [(set_attr "length" "2")
4860    (set_attr "type" "*,load,store1,*,*,*")
4861    (set_attr "pool_range" "*,32,*,*,*,*")]
4864 (define_expand "movsf"
4865   [(set (match_operand:SF 0 "general_operand" "")
4866         (match_operand:SF 1 "general_operand" ""))]
4867   "TARGET_EITHER"
4868   "
4869   if (TARGET_ARM)
4870     {
4871       if (GET_CODE (operands[0]) == MEM)
4872         operands[1] = force_reg (SFmode, operands[1]);
4873     }
4874   else /* TARGET_THUMB */
4875     {
4876       if (!no_new_pseudos)
4877         {
4878            if (GET_CODE (operands[0]) != REG)
4879              operands[1] = force_reg (SFmode, operands[1]);
4880         }
4881     }
4882   "
4885 (define_split
4886   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4887         (match_operand:SF 1 "immediate_operand" ""))]
4888   "TARGET_ARM
4889    && !TARGET_HARD_FLOAT
4890    && reload_completed
4891    && GET_CODE (operands[1]) == CONST_DOUBLE"
4892   [(set (match_dup 2) (match_dup 3))]
4893   "
4894   operands[2] = gen_lowpart (SImode, operands[0]);
4895   operands[3] = gen_lowpart (SImode, operands[1]);
4896   if (operands[2] == 0 || operands[3] == 0)
4897     FAIL;
4898   "
4901 (define_insn "*arm_movsf_hard_insn"
4902   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4903         (match_operand:SF 1 "general_operand"      "fG,H,mE,f,r,f,r,mE,r"))]
4904   "TARGET_ARM
4905    && TARGET_HARD_FLOAT
4906    && (GET_CODE (operands[0]) != MEM
4907        || register_operand (operands[1], SFmode))"
4908   "@
4909    mvf%?s\\t%0, %1
4910    mnf%?s\\t%0, #%N1
4911    ldf%?s\\t%0, %1
4912    stf%?s\\t%1, %0
4913    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4914    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4915    mov%?\\t%0, %1
4916    ldr%?\\t%0, %1\\t%@ float
4917    str%?\\t%1, %0\\t%@ float"
4918   [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4919    (set_attr "predicable" "yes")
4920    (set_attr "type"
4921          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4922    (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4923    (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4926 ;; Exactly the same as above, except that all `f' cases are deleted.
4927 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4928 ;; when -msoft-float.
4930 (define_insn "*arm_movsf_soft_insn"
4931   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4932         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4933   "TARGET_ARM
4934    && TARGET_SOFT_FLOAT
4935    && (GET_CODE (operands[0]) != MEM
4936        || register_operand (operands[1], SFmode))"
4937   "@
4938    mov%?\\t%0, %1
4939    ldr%?\\t%0, %1\\t%@ float
4940    str%?\\t%1, %0\\t%@ float"
4941   [(set_attr "length" "4,4,4")
4942    (set_attr "predicable" "yes")
4943    (set_attr "type" "*,load,store1")
4944    (set_attr "pool_range" "*,4096,*")
4945    (set_attr "neg_pool_range" "*,4084,*")]
4948 ;;; ??? This should have alternatives for constants.
4949 (define_insn "*thumb_movsf_insn"
4950   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4951         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
4952   "TARGET_THUMB
4953    && (   register_operand (operands[0], SFmode) 
4954        || register_operand (operands[1], SFmode))"
4955   "@
4956    add\\t%0, %1, #0
4957    ldmia\\t%1, {%0}
4958    stmia\\t%0, {%1}
4959    ldr\\t%0, %1
4960    str\\t%1, %0
4961    mov\\t%0, %1
4962    mov\\t%0, %1"
4963   [(set_attr "length" "2")
4964    (set_attr "type" "*,load,store1,load,store1,*,*")
4965    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4968 (define_expand "movdf"
4969   [(set (match_operand:DF 0 "general_operand" "")
4970         (match_operand:DF 1 "general_operand" ""))]
4971   "TARGET_EITHER"
4972   "
4973   if (TARGET_ARM)
4974     {
4975       if (GET_CODE (operands[0]) == MEM)
4976         operands[1] = force_reg (DFmode, operands[1]);
4977     }
4978   else /* TARGET_THUMB */
4979     {
4980       if (!no_new_pseudos)
4981         {
4982           if (GET_CODE (operands[0]) != REG)
4983             operands[1] = force_reg (DFmode, operands[1]);
4984         }
4985     }
4986   "
4989 ;; Reloading a df mode value stored in integer regs to memory can require a
4990 ;; scratch reg.
4991 (define_expand "reload_outdf"
4992   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4993    (match_operand:DF 1 "s_register_operand" "r")
4994    (match_operand:SI 2 "s_register_operand" "=&r")]
4995   "TARGET_ARM"
4996   "
4997   {
4998     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5000     if (code == REG)
5001       operands[2] = XEXP (operands[0], 0);
5002     else if (code == POST_INC || code == PRE_DEC)
5003       {
5004         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5005         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5006         emit_insn (gen_movdi (operands[0], operands[1]));
5007         DONE;
5008       }
5009     else if (code == PRE_INC)
5010       {
5011         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5013         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5014         operands[2] = reg;
5015       }
5016     else if (code == POST_DEC)
5017       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5018     else
5019       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5020                              XEXP (XEXP (operands[0], 0), 1)));
5022     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5023                             operands[1]));
5025     if (code == POST_DEC)
5026       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5028     DONE;
5029   }"
5032 (define_insn "*movdf_hard_insn"
5033   [(set (match_operand:DF 0 "nonimmediate_operand"
5034                                                 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5035         (match_operand:DF 1 "general_operand"
5036                                                 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5037   "TARGET_ARM
5038    && TARGET_HARD_FLOAT
5039    && (GET_CODE (operands[0]) != MEM
5040        || register_operand (operands[1], DFmode))"
5041   "*
5042   {
5043   switch (which_alternative)
5044     {
5045     default:
5046     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5047     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5048     case 2: case 3: case 4: return output_move_double (operands);
5049     case 5: return \"mvf%?d\\t%0, %1\";
5050     case 6: return \"mnf%?d\\t%0, #%N1\";
5051     case 7: return \"ldf%?d\\t%0, %1\";
5052     case 8: return \"stf%?d\\t%1, %0\";
5053     case 9: return output_mov_double_fpu_from_arm (operands);
5054     case 10: return output_mov_double_arm_from_fpu (operands);
5055     }
5056   }
5057   "
5058   [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5059    (set_attr "predicable" "yes")
5060    (set_attr "type"
5061     "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5062    (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")
5063    (set_attr "neg_pool_range" "*,*,*,*,244,*,*,1012,*,*,*")]
5066 ;; Software floating point version.  This is essentially the same as movdi.
5067 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5068 ;; an `f' reg.
5070 (define_insn "*movdf_soft_insn"
5071   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5072         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5073   "TARGET_ARM && TARGET_SOFT_FLOAT
5074   "
5075   "* return output_move_double (operands);"
5076   [(set_attr "length" "8,8,8")
5077    (set_attr "type" "*,load,store2")
5078    (set_attr "pool_range" "252")
5079    (set_attr "neg_pool_range" "244")]
5082 ;;; ??? This should have alternatives for constants.
5083 ;;; ??? This was originally identical to the movdi_insn pattern.
5084 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5085 ;;; thumb_reorg with a memory reference.
5086 (define_insn "*thumb_movdf_insn"
5087   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5088         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5089   "TARGET_THUMB
5090    && (   register_operand (operands[0], DFmode)
5091        || register_operand (operands[1], DFmode))"
5092   "*
5093   switch (which_alternative)
5094     {
5095     default:
5096     case 0:
5097       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5098         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5099       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5100     case 1:
5101       return \"ldmia\\t%1, {%0, %H0}\";
5102     case 2:
5103       return \"stmia\\t%0, {%1, %H1}\";
5104     case 3:
5105       return thumb_load_double_from_address (operands);
5106     case 4:
5107       operands[2] = gen_rtx (MEM, SImode,
5108                              plus_constant (XEXP (operands[0], 0), 4));
5109       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5110       return \"\";
5111     case 5:
5112       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5113         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5114       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5115     }
5116   "
5117   [(set_attr "length" "4,2,2,6,4,4")
5118    (set_attr "type" "*,load,store2,load,store2,*")
5119    (set_attr "pool_range" "*,*,*,1020,*,*")]
5123 (define_expand "movxf"
5124   [(set (match_operand:XF 0 "general_operand" "")
5125         (match_operand:XF 1 "general_operand" ""))]
5126   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5127   "")
5129 ;; Even when the XFmode patterns aren't enabled, we enable this after
5130 ;; reloading so that we can push floating point registers in the prologue.
5132 (define_insn "*movxf_hard_insn"
5133   [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5134         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5135   "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5136   "*
5137   switch (which_alternative)
5138     {
5139     default:
5140     case 0: return \"mvf%?e\\t%0, %1\";
5141     case 1: return \"mnf%?e\\t%0, #%N1\";
5142     case 2: return \"ldf%?e\\t%0, %1\";
5143     case 3: return \"stf%?e\\t%1, %0\";
5144     case 4: return output_mov_long_double_fpu_from_arm (operands);
5145     case 5: return output_mov_long_double_arm_from_fpu (operands);
5146     case 6: return output_mov_long_double_arm_from_arm (operands);
5147     }
5148   "
5149   [(set_attr "length" "4,4,4,4,8,8,12")
5150    (set_attr "predicable" "yes")
5151    (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5152    (set_attr "pool_range" "*,*,1024,*,*,*,*")
5153    (set_attr "neg_pool_range" "*,*,1012,*,*,*,*")]
5157 ;; load- and store-multiple insns
5158 ;; The arm can load/store any set of registers, provided that they are in
5159 ;; ascending order; but that is beyond GCC so stick with what it knows.
5161 (define_expand "load_multiple"
5162   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5163                           (match_operand:SI 1 "" ""))
5164                      (use (match_operand:SI 2 "" ""))])]
5165   "TARGET_ARM"
5166   "
5167   /* Support only fixed point registers.  */
5168   if (GET_CODE (operands[2]) != CONST_INT
5169       || INTVAL (operands[2]) > 14
5170       || INTVAL (operands[2]) < 2
5171       || GET_CODE (operands[1]) != MEM
5172       || GET_CODE (operands[0]) != REG
5173       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5174       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5175     FAIL;
5177   operands[3]
5178     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5179                              force_reg (SImode, XEXP (operands[1], 0)),
5180                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5181                              MEM_IN_STRUCT_P(operands[1]),
5182                              MEM_SCALAR_P (operands[1]));
5183   "
5186 ;; Load multiple with write-back
5188 (define_insn "*ldmsi_postinc"
5189   [(match_parallel 0 "load_multiple_operation"
5190     [(set (match_operand:SI 1 "s_register_operand" "+r")
5191           (plus:SI (match_dup 1)
5192                    (match_operand:SI 2 "const_int_operand" "n")))
5193      (set (match_operand:SI 3 "s_register_operand" "=r")
5194           (mem:SI (match_dup 1)))])]
5195   "TARGET_ARM && (INTVAL (operands[2])  == 4 * (XVECLEN (operands[0], 0) - 1))"
5196   "*
5197   {
5198     rtx ops[3];
5199     int count = XVECLEN (operands[0], 0);
5201     ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
5202     ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
5203     ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
5205     output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
5206     return \"\";
5207   }
5208   "
5209   [(set_attr "type" "load")
5210    (set_attr "predicable" "yes")]
5213 ;; Ordinary load multiple
5215 (define_insn "*ldmsi"
5216   [(match_parallel 0 "load_multiple_operation"
5217     [(set (match_operand:SI 1 "s_register_operand" "=r")
5218           (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
5219   "TARGET_ARM"
5220   "*
5221   {
5222     rtx ops[3];
5223     int count = XVECLEN (operands[0], 0);
5225     ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
5226     ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
5227     ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
5229     output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
5230     return \"\";
5231   }
5232   "
5233   [(set_attr "type" "load")
5234    (set_attr "predicable" "yes")]
5237 (define_expand "store_multiple"
5238   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5239                           (match_operand:SI 1 "" ""))
5240                      (use (match_operand:SI 2 "" ""))])]
5241   "TARGET_ARM"
5242   "
5243   /* Support only fixed point registers */
5244   if (GET_CODE (operands[2]) != CONST_INT
5245       || INTVAL (operands[2]) > 14
5246       || INTVAL (operands[2]) < 2
5247       || GET_CODE (operands[1]) != REG
5248       || GET_CODE (operands[0]) != MEM
5249       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5250       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5251     FAIL;
5253   operands[3]
5254     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5255                               force_reg (SImode, XEXP (operands[0], 0)),
5256                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5257                               MEM_IN_STRUCT_P(operands[0]), 
5258                               MEM_SCALAR_P (operands[0]));
5259   "
5262 ;; Store multiple with write-back
5264 (define_insn "*stmsi_postinc"
5265   [(match_parallel 0 "store_multiple_operation"
5266     [(set (match_operand:SI 1 "s_register_operand" "+r")
5267           (plus:SI (match_dup 1)
5268                    (match_operand:SI 2 "const_int_operand" "n")))
5269      (set (mem:SI (match_dup 1))
5270           (match_operand:SI 3 "s_register_operand" "r"))])]
5271   "TARGET_ARM && (INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 1))"
5272   "*
5273   {
5274     rtx ops[3];
5275     int count = XVECLEN (operands[0], 0);
5277     ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
5278     ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
5279     ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
5281     output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
5282     return \"\";
5283   }
5284   "
5285   [(set_attr "predicable" "yes")
5286    (set (attr "type")
5287         (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
5288                    (const_string "store2")
5289                (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
5290                    (const_string "store3")]
5291                (const_string "store4")))]
5294 ;; Ordinary store multiple
5296 (define_insn "*stmsi"
5297   [(match_parallel 0 "store_multiple_operation"
5298     [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
5299           (match_operand:SI 1 "s_register_operand" "r"))])]
5300   "TARGET_ARM"
5301   "*
5302   {
5303     rtx ops[3];
5304     int count = XVECLEN (operands[0], 0);
5306     ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
5307     ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
5308     ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
5310     output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
5311     return \"\";
5312   }
5313   "
5314   [(set_attr "predicable" "yes")
5315    (set (attr "type")
5316         (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
5317                    (const_string "store2")
5318                (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
5319                    (const_string "store3")]
5320                (const_string "store4")))]
5323 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5324 ;; We could let this apply for blocks of less than this, but it clobbers so
5325 ;; many registers that there is then probably a better way.
5327 (define_expand "movstrqi"
5328   [(match_operand:BLK 0 "general_operand" "")
5329    (match_operand:BLK 1 "general_operand" "")
5330    (match_operand:SI 2 "const_int_operand" "")
5331    (match_operand:SI 3 "const_int_operand" "")]
5332   "TARGET_EITHER"
5333   "
5334   if (TARGET_ARM)
5335     {
5336       if (arm_gen_movstrqi (operands))
5337         DONE;
5338       FAIL;
5339     }
5340   else /* TARGET_THUMB */
5341     {
5342       if (   INTVAL (operands[3]) != 4
5343           || INTVAL (operands[2]) > 48)
5344         FAIL;
5346       thumb_expand_movstrqi (operands);
5347       DONE;
5348     }
5349   "
5352 ;; Block-move insns
5354 (define_insn "movmem12b"
5355   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5356         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5357    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5358         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5359    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5360         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5361    (set (match_operand:SI 0 "register_operand" "=l")
5362         (plus:SI (match_dup 2) (const_int 12)))
5363    (set (match_operand:SI 1 "register_operand" "=l")
5364         (plus:SI (match_dup 3) (const_int 12)))
5365    (clobber (match_scratch:SI 4 "=&l"))
5366    (clobber (match_scratch:SI 5 "=&l"))
5367    (clobber (match_scratch:SI 6 "=&l"))]
5368   "TARGET_THUMB"
5369   "* return thumb_output_move_mem_multiple (3, operands);"
5370   [(set_attr "length" "4")
5371    ; This isn't entirely accurate...  It loads as well, but in terms of
5372    ; scheduling the following insn it is better to consider it as a store
5373    (set_attr "type" "store3")]
5376 (define_insn "movmem8b"
5377   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5378         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5379    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5380         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5381    (set (match_operand:SI 0 "register_operand" "=l")
5382         (plus:SI (match_dup 2) (const_int 8)))
5383    (set (match_operand:SI 1 "register_operand" "=l")
5384         (plus:SI (match_dup 3) (const_int 8)))
5385    (clobber (match_scratch:SI 4 "=&l"))
5386    (clobber (match_scratch:SI 5 "=&l"))]
5387   "TARGET_THUMB"
5388   "* return thumb_output_move_mem_multiple (2, operands);"
5389   [(set_attr "length" "4")
5390    ; This isn't entirely accurate...  It loads as well, but in terms of
5391    ; scheduling the following insn it is better to consider it as a store
5392    (set_attr "type" "store2")]
5397 ;; Comapre & branch insns
5399 (define_insn "cbranchsi4"
5400   [(set (pc)
5401         (if_then_else
5402             (match_operator                    0 "arm_comparison_operator"
5403                             [(match_operand:SI 1 "register_operand"   "l,r")
5404                              (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5405             (label_ref       (match_operand    3 "" ""))
5406             (pc)))]
5407   "TARGET_THUMB"
5408   "*
5409   output_asm_insn (\"cmp\\t%1, %2\", operands);
5410   switch (get_attr_length (insn))
5411     {
5412     case 4:  return \"b%d0\\t%l3\";
5413     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5414     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5415     }
5416   "
5417   [(set (attr "far_jump")
5418         (if_then_else
5419             (eq_attr "length" "8")
5420             (const_string "yes")
5421             (const_string "no")))
5422    (set (attr "length") 
5423         (if_then_else
5424             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5425                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5426             (const_int 4)
5427             (if_then_else
5428                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5429                      (le (minus (match_dup 3) (pc)) (const_int 2054)))
5430                 (const_int 6)
5431                 (const_int 8))))]
5434 (define_insn "*negated_cbranchsi4"
5435   [(set (pc)
5436         (if_then_else
5437          (match_operator             0 "arm_comparison_operator"
5438           [(match_operand:SI         1 "register_operand"  "l")
5439            (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5440          (label_ref (match_operand   3 "" ""))
5441          (pc)))]
5442   "TARGET_THUMB"
5443   "*
5444   output_asm_insn (\"cmn\\t%1, %2\", operands);
5445   switch (get_attr_length (insn))
5446     {
5447     case 4:  return \"b%d0\\t%l3\";
5448     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5449     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5450     }
5451   "
5452   [(set (attr "far_jump")
5453         (if_then_else
5454             (eq_attr "length" "8")
5455             (const_string "yes")
5456             (const_string "no")))
5457    (set (attr "length") 
5458         (if_then_else
5459             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5460                  (le (minus (match_dup 3) (pc)) (const_int 254)))
5461             (const_int 4)
5462             (if_then_else
5463                 (and (ge (minus (match_dup 3) (pc)) (const_int -2044))
5464                      (le (minus (match_dup 3) (pc)) (const_int 2044)))
5465                 (const_int 6)
5466                 (const_int 8))))]
5470 ;; Comparison and test insns
5472 (define_expand "cmpsi"
5473   [(match_operand:SI 0 "s_register_operand" "")
5474    (match_operand:SI 1 "arm_add_operand" "")]
5475   "TARGET_ARM"
5476   "{
5477     arm_compare_op0 = operands[0];
5478     arm_compare_op1 = operands[1];
5479     DONE;
5480   }"
5483 (define_expand "cmpsf"
5484   [(match_operand:SF 0 "s_register_operand" "")
5485    (match_operand:SF 1 "fpu_rhs_operand" "")]
5486   "TARGET_ARM && TARGET_HARD_FLOAT"
5487   "
5488   arm_compare_op0 = operands[0];
5489   arm_compare_op1 = operands[1];
5490   DONE;
5491   "
5494 (define_expand "cmpdf"
5495   [(match_operand:DF 0 "s_register_operand" "")
5496    (match_operand:DF 1 "fpu_rhs_operand" "")]
5497   "TARGET_ARM && TARGET_HARD_FLOAT"
5498   "
5499   arm_compare_op0 = operands[0];
5500   arm_compare_op1 = operands[1];
5501   DONE;
5502   "
5505 (define_expand "cmpxf"
5506   [(match_operand:XF 0 "s_register_operand" "")
5507    (match_operand:XF 1 "fpu_rhs_operand" "")]
5508   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5509   "
5510   arm_compare_op0 = operands[0];
5511   arm_compare_op1 = operands[1];
5512   DONE;
5513   "
5516 (define_insn "*arm_cmpsi_insn"
5517   [(set (reg:CC CC_REGNUM)
5518         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5519                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5520   "TARGET_ARM"
5521   "@
5522    cmp%?\\t%0, %1
5523    cmn%?\\t%0, #%n1"
5524   [(set_attr "conds" "set")]
5527 (define_insn "*cmpsi_shiftsi"
5528   [(set (reg:CC CC_REGNUM)
5529         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
5530                     (match_operator:SI  3 "shift_operator"
5531                      [(match_operand:SI 1 "s_register_operand" "r")
5532                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5533   "TARGET_ARM"
5534   "cmp%?\\t%0, %1%S3"
5535   [(set_attr "conds" "set")
5536    (set_attr "shift" "1")
5537    ]
5540 (define_insn "*cmpsi_shiftsi_swp"
5541   [(set (reg:CC_SWP CC_REGNUM)
5542         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5543                          [(match_operand:SI 1 "s_register_operand" "r")
5544                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
5545                         (match_operand:SI 0 "s_register_operand" "r")))]
5546   "TARGET_ARM"
5547   "cmp%?\\t%0, %1%S3"
5548   [(set_attr "conds" "set")
5549    (set_attr "shift" "1")
5550    ]
5553 (define_insn "*cmpsi_neg_shiftsi"
5554   [(set (reg:CC CC_REGNUM)
5555         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5556                     (neg:SI (match_operator:SI 3 "shift_operator"
5557                              [(match_operand:SI 1 "s_register_operand" "r")
5558                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5559   "TARGET_ARM"
5560   "cmn%?\\t%0, %1%S3"
5561   [(set_attr "conds" "set")
5562    (set_attr "shift" "1")
5563    ]
5566 (define_insn "*cmpsf_insn"
5567   [(set (reg:CCFP CC_REGNUM)
5568         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5569                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5570   "TARGET_ARM && TARGET_HARD_FLOAT"
5571   "@
5572    cmf%?\\t%0, %1
5573    cnf%?\\t%0, #%N1"
5574   [(set_attr "conds" "set")
5575    (set_attr "type" "f_2_r")]
5578 (define_insn "*cmpdf_insn"
5579   [(set (reg:CCFP CC_REGNUM)
5580         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5581                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5582   "TARGET_ARM && TARGET_HARD_FLOAT"
5583   "@
5584    cmf%?\\t%0, %1
5585    cnf%?\\t%0, #%N1"
5586   [(set_attr "conds" "set")
5587    (set_attr "type" "f_2_r")]
5590 (define_insn "*cmpesfdf_df"
5591   [(set (reg:CCFP CC_REGNUM)
5592         (compare:CCFP (float_extend:DF
5593                        (match_operand:SF 0 "s_register_operand" "f,f"))
5594                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5595   "TARGET_ARM && TARGET_HARD_FLOAT"
5596   "@
5597    cmf%?\\t%0, %1
5598    cnf%?\\t%0, #%N1"
5599   [(set_attr "conds" "set")
5600    (set_attr "type" "f_2_r")]
5603 (define_insn "*cmpdf_esfdf"
5604   [(set (reg:CCFP CC_REGNUM)
5605         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5606                       (float_extend:DF
5607                        (match_operand:SF 1 "s_register_operand" "f"))))]
5608   "TARGET_ARM && TARGET_HARD_FLOAT"
5609   "cmf%?\\t%0, %1"
5610   [(set_attr "conds" "set")
5611    (set_attr "type" "f_2_r")]
5614 (define_insn "*cmpxf_insn"
5615   [(set (reg:CCFP CC_REGNUM)
5616         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5617                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5618   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5619   "@
5620    cmf%?\\t%0, %1
5621    cnf%?\\t%0, #%N1"
5622   [(set_attr "conds" "set")
5623    (set_attr "type" "f_2_r")]
5626 (define_insn "*cmpsf_trap"
5627   [(set (reg:CCFPE CC_REGNUM)
5628         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5629                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5630   "TARGET_ARM && TARGET_HARD_FLOAT"
5631   "@
5632    cmf%?e\\t%0, %1
5633    cnf%?e\\t%0, #%N1"
5634   [(set_attr "conds" "set")
5635    (set_attr "type" "f_2_r")]
5638 (define_insn "*cmpdf_trap"
5639   [(set (reg:CCFPE CC_REGNUM)
5640         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5641                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5642   "TARGET_ARM && TARGET_HARD_FLOAT"
5643   "@
5644    cmf%?e\\t%0, %1
5645    cnf%?e\\t%0, #%N1"
5646   [(set_attr "conds" "set")
5647    (set_attr "type" "f_2_r")]
5650 (define_insn "*cmp_esfdf_df_trap"
5651   [(set (reg:CCFPE CC_REGNUM)
5652         (compare:CCFPE (float_extend:DF
5653                         (match_operand:SF 0 "s_register_operand" "f,f"))
5654                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5655   "TARGET_ARM && TARGET_HARD_FLOAT"
5656   "@
5657    cmf%?e\\t%0, %1
5658    cnf%?e\\t%0, #%N1"
5659   [(set_attr "conds" "set")
5660    (set_attr "type" "f_2_r")]
5663 (define_insn "*cmp_df_esfdf_trap"
5664   [(set (reg:CCFPE CC_REGNUM)
5665         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5666                        (float_extend:DF
5667                         (match_operand:SF 1 "s_register_operand" "f"))))]
5668   "TARGET_ARM && TARGET_HARD_FLOAT"
5669   "cmf%?e\\t%0, %1"
5670   [(set_attr "conds" "set")
5671    (set_attr "type" "f_2_r")]
5674 (define_insn "*cmpxf_trap"
5675   [(set (reg:CCFPE CC_REGNUM)
5676         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5677                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5678   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5679   "@
5680    cmf%?e\\t%0, %1
5681    cnf%?e\\t%0, #%N1"
5682   [(set_attr "conds" "set")
5683    (set_attr "type" "f_2_r")]
5686 ; This insn allows redundant compares to be removed by cse, nothing should
5687 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5688 ; is deleted later on. The match_dup will match the mode here, so that
5689 ; mode changes of the condition codes aren't lost by this even though we don't
5690 ; specify what they are.
5692 (define_insn "*deleted_compare"
5693   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5694   "TARGET_ARM"
5695   "\\t%@ deleted compare"
5696   [(set_attr "conds" "set")
5697    (set_attr "length" "0")]
5701 ;; Conditional branch insns
5703 (define_expand "beq"
5704   [(set (pc)
5705         (if_then_else (eq (match_dup 1) (const_int 0))
5706                       (label_ref (match_operand 0 "" ""))
5707                       (pc)))]
5708   "TARGET_ARM"
5709   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5712 (define_expand "bne"
5713   [(set (pc)
5714         (if_then_else (ne (match_dup 1) (const_int 0))
5715                       (label_ref (match_operand 0 "" ""))
5716                       (pc)))]
5717   "TARGET_ARM"
5718   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5721 (define_expand "bgt"
5722   [(set (pc)
5723         (if_then_else (gt (match_dup 1) (const_int 0))
5724                       (label_ref (match_operand 0 "" ""))
5725                       (pc)))]
5726   "TARGET_ARM"
5727   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5730 (define_expand "ble"
5731   [(set (pc)
5732         (if_then_else (le (match_dup 1) (const_int 0))
5733                       (label_ref (match_operand 0 "" ""))
5734                       (pc)))]
5735   "TARGET_ARM"
5736   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5739 (define_expand "bge"
5740   [(set (pc)
5741         (if_then_else (ge (match_dup 1) (const_int 0))
5742                       (label_ref (match_operand 0 "" ""))
5743                       (pc)))]
5744   "TARGET_ARM"
5745   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5748 (define_expand "blt"
5749   [(set (pc)
5750         (if_then_else (lt (match_dup 1) (const_int 0))
5751                       (label_ref (match_operand 0 "" ""))
5752                       (pc)))]
5753   "TARGET_ARM"
5754   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5757 (define_expand "bgtu"
5758   [(set (pc)
5759         (if_then_else (gtu (match_dup 1) (const_int 0))
5760                       (label_ref (match_operand 0 "" ""))
5761                       (pc)))]
5762   "TARGET_ARM"
5763   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5766 (define_expand "bleu"
5767   [(set (pc)
5768         (if_then_else (leu (match_dup 1) (const_int 0))
5769                       (label_ref (match_operand 0 "" ""))
5770                       (pc)))]
5771   "TARGET_ARM"
5772   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5775 (define_expand "bgeu"
5776   [(set (pc)
5777         (if_then_else (geu (match_dup 1) (const_int 0))
5778                       (label_ref (match_operand 0 "" ""))
5779                       (pc)))]
5780   "TARGET_ARM"
5781   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5784 (define_expand "bltu"
5785   [(set (pc)
5786         (if_then_else (ltu (match_dup 1) (const_int 0))
5787                       (label_ref (match_operand 0 "" ""))
5788                       (pc)))]
5789   "TARGET_ARM"
5790   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5793 (define_expand "bunordered"
5794   [(set (pc)
5795         (if_then_else (unordered (match_dup 1) (const_int 0))
5796                       (label_ref (match_operand 0 "" ""))
5797                       (pc)))]
5798   "TARGET_ARM && TARGET_HARD_FLOAT"
5799   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5800                                       arm_compare_op1);"
5803 (define_expand "bordered"
5804   [(set (pc)
5805         (if_then_else (ordered (match_dup 1) (const_int 0))
5806                       (label_ref (match_operand 0 "" ""))
5807                       (pc)))]
5808   "TARGET_ARM && TARGET_HARD_FLOAT"
5809   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5810                                       arm_compare_op1);"
5813 (define_expand "bungt"
5814   [(set (pc)
5815         (if_then_else (ungt (match_dup 1) (const_int 0))
5816                       (label_ref (match_operand 0 "" ""))
5817                       (pc)))]
5818   "TARGET_ARM && TARGET_HARD_FLOAT"
5819   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5822 (define_expand "bunlt"
5823   [(set (pc)
5824         (if_then_else (unlt (match_dup 1) (const_int 0))
5825                       (label_ref (match_operand 0 "" ""))
5826                       (pc)))]
5827   "TARGET_ARM && TARGET_HARD_FLOAT"
5828   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5831 (define_expand "bunge"
5832   [(set (pc)
5833         (if_then_else (unge (match_dup 1) (const_int 0))
5834                       (label_ref (match_operand 0 "" ""))
5835                       (pc)))]
5836   "TARGET_ARM && TARGET_HARD_FLOAT"
5837   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5840 (define_expand "bunle"
5841   [(set (pc)
5842         (if_then_else (unle (match_dup 1) (const_int 0))
5843                       (label_ref (match_operand 0 "" ""))
5844                       (pc)))]
5845   "TARGET_ARM && TARGET_HARD_FLOAT"
5846   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5849 ;; The following two patterns need two branch instructions, since there is
5850 ;; no single instruction that will handle all cases.
5851 (define_expand "buneq"
5852   [(set (pc)
5853         (if_then_else (uneq (match_dup 1) (const_int 0))
5854                       (label_ref (match_operand 0 "" ""))
5855                       (pc)))]
5856   "TARGET_ARM && TARGET_HARD_FLOAT"
5857   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5860 (define_expand "bltgt"
5861   [(set (pc)
5862         (if_then_else (ltgt (match_dup 1) (const_int 0))
5863                       (label_ref (match_operand 0 "" ""))
5864                       (pc)))]
5865   "TARGET_ARM && TARGET_HARD_FLOAT"
5866   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5870 ;; Patterns to match conditional branch insns.
5873 ; Special pattern to match UNEQ.
5874 (define_insn "*arm_buneq"
5875   [(set (pc)
5876         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5877                       (label_ref (match_operand 0 "" ""))
5878                       (pc)))]
5879   "TARGET_ARM && TARGET_HARD_FLOAT"
5880   "*
5881   if (arm_ccfsm_state != 0)
5882     abort ();
5884   return \"bvs\\t%l0;beq\\t%l0\";
5885   "
5886   [(set_attr "conds" "jump_clob")
5887    (set_attr "length" "8")]
5890 ; Special pattern to match LTGT.
5891 (define_insn "*arm_bltgt"
5892   [(set (pc)
5893         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5894                       (label_ref (match_operand 0 "" ""))
5895                       (pc)))]
5896   "TARGET_ARM && TARGET_HARD_FLOAT"
5897   "*
5898   if (arm_ccfsm_state != 0)
5899     abort ();
5901   return \"bmi\\t%l0;bgt\\t%l0\";
5902   "
5903   [(set_attr "conds" "jump_clob")
5904    (set_attr "length" "8")]
5907 (define_insn "*arm_cond_branch"
5908   [(set (pc)
5909         (if_then_else (match_operator 1 "arm_comparison_operator"
5910                        [(match_operand 2 "cc_register" "") (const_int 0)])
5911                       (label_ref (match_operand 0 "" ""))
5912                       (pc)))]
5913   "TARGET_ARM"
5914   "*
5915   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5916     {
5917       arm_ccfsm_state += 2;
5918       return \"\";
5919     }
5920   return \"b%d1\\t%l0\";
5921   "
5922   [(set_attr "conds" "use")]
5925 ; Special pattern to match reversed UNEQ.
5926 (define_insn "*arm_buneq_reversed"
5927   [(set (pc)
5928         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5929                       (pc)
5930                       (label_ref (match_operand 0 "" ""))))]
5931   "TARGET_ARM && TARGET_HARD_FLOAT"
5932   "*
5933   if (arm_ccfsm_state != 0)
5934     abort ();
5936   return \"bmi\\t%l0;bgt\\t%l0\";
5937   "
5938   [(set_attr "conds" "jump_clob")
5939    (set_attr "length" "8")]
5942 ; Special pattern to match reversed LTGT.
5943 (define_insn "*arm_bltgt_reversed"
5944   [(set (pc)
5945         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5946                       (pc)
5947                       (label_ref (match_operand 0 "" ""))))]
5948   "TARGET_ARM && TARGET_HARD_FLOAT"
5949   "*
5950   if (arm_ccfsm_state != 0)
5951     abort ();
5953   return \"bvs\\t%l0;beq\\t%l0\";
5954   "
5955   [(set_attr "conds" "jump_clob")
5956    (set_attr "length" "8")]
5959 (define_insn "*arm_cond_branch_reversed"
5960   [(set (pc)
5961         (if_then_else (match_operator 1 "arm_comparison_operator"
5962                        [(match_operand 2 "cc_register" "") (const_int 0)])
5963                       (pc)
5964                       (label_ref (match_operand 0 "" ""))))]
5965   "TARGET_ARM"
5966   "*
5967   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5968     {
5969       arm_ccfsm_state += 2;
5970       return \"\";
5971     }
5972   return \"b%D1\\t%l0\";
5973   "
5974   [(set_attr "conds" "use")]
5979 ; scc insns
5981 (define_expand "seq"
5982   [(set (match_operand:SI 0 "s_register_operand" "=r")
5983         (eq:SI (match_dup 1) (const_int 0)))]
5984   "TARGET_ARM"
5985   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5988 (define_expand "sne"
5989   [(set (match_operand:SI 0 "s_register_operand" "=r")
5990         (ne:SI (match_dup 1) (const_int 0)))]
5991   "TARGET_ARM"
5992   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5995 (define_expand "sgt"
5996   [(set (match_operand:SI 0 "s_register_operand" "=r")
5997         (gt:SI (match_dup 1) (const_int 0)))]
5998   "TARGET_ARM"
5999   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6002 (define_expand "sle"
6003   [(set (match_operand:SI 0 "s_register_operand" "=r")
6004         (le:SI (match_dup 1) (const_int 0)))]
6005   "TARGET_ARM"
6006   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6009 (define_expand "sge"
6010   [(set (match_operand:SI 0 "s_register_operand" "=r")
6011         (ge:SI (match_dup 1) (const_int 0)))]
6012   "TARGET_ARM"
6013   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6016 (define_expand "slt"
6017   [(set (match_operand:SI 0 "s_register_operand" "=r")
6018         (lt:SI (match_dup 1) (const_int 0)))]
6019   "TARGET_ARM"
6020   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6023 (define_expand "sgtu"
6024   [(set (match_operand:SI 0 "s_register_operand" "=r")
6025         (gtu:SI (match_dup 1) (const_int 0)))]
6026   "TARGET_ARM"
6027   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6030 (define_expand "sleu"
6031   [(set (match_operand:SI 0 "s_register_operand" "=r")
6032         (leu:SI (match_dup 1) (const_int 0)))]
6033   "TARGET_ARM"
6034   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6037 (define_expand "sgeu"
6038   [(set (match_operand:SI 0 "s_register_operand" "=r")
6039         (geu:SI (match_dup 1) (const_int 0)))]
6040   "TARGET_ARM"
6041   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6044 (define_expand "sltu"
6045   [(set (match_operand:SI 0 "s_register_operand" "=r")
6046         (ltu:SI (match_dup 1) (const_int 0)))]
6047   "TARGET_ARM"
6048   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6051 (define_expand "sunordered"
6052   [(set (match_operand:SI 0 "s_register_operand" "=r")
6053         (unordered:SI (match_dup 1) (const_int 0)))]
6054   "TARGET_ARM && TARGET_HARD_FLOAT"
6055   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6056                                       arm_compare_op1);"
6059 (define_expand "sordered"
6060   [(set (match_operand:SI 0 "s_register_operand" "=r")
6061         (ordered:SI (match_dup 1) (const_int 0)))]
6062   "TARGET_ARM && TARGET_HARD_FLOAT"
6063   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6064                                       arm_compare_op1);"
6067 (define_expand "sungt"
6068   [(set (match_operand:SI 0 "s_register_operand" "=r")
6069         (ungt:SI (match_dup 1) (const_int 0)))]
6070   "TARGET_ARM && TARGET_HARD_FLOAT"
6071   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6072                                       arm_compare_op1);"
6075 (define_expand "sunge"
6076   [(set (match_operand:SI 0 "s_register_operand" "=r")
6077         (unge:SI (match_dup 1) (const_int 0)))]
6078   "TARGET_ARM && TARGET_HARD_FLOAT"
6079   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6080                                       arm_compare_op1);"
6083 (define_expand "sunlt"
6084   [(set (match_operand:SI 0 "s_register_operand" "=r")
6085         (unlt:SI (match_dup 1) (const_int 0)))]
6086   "TARGET_ARM && TARGET_HARD_FLOAT"
6087   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6088                                       arm_compare_op1);"
6091 (define_expand "sunle"
6092   [(set (match_operand:SI 0 "s_register_operand" "=r")
6093         (unle:SI (match_dup 1) (const_int 0)))]
6094   "TARGET_ARM && TARGET_HARD_FLOAT"
6095   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6096                                       arm_compare_op1);"
6099 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6100 ;;; simple ARM instructions. 
6102 ; (define_expand "suneq"
6103 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6104 ;       (uneq:SI (match_dup 1) (const_int 0)))]
6105 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6106 ;   "abort ();"
6107 ; )
6109 ; (define_expand "sltgt"
6110 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6111 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
6112 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6113 ;   "abort ();"
6114 ; )
6116 (define_insn "*mov_scc"
6117   [(set (match_operand:SI 0 "s_register_operand" "=r")
6118         (match_operator:SI 1 "arm_comparison_operator"
6119          [(match_operand 2 "cc_register" "") (const_int 0)]))]
6120   "TARGET_ARM"
6121   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6122   [(set_attr "conds" "use")
6123    (set_attr "length" "8")]
6126 (define_insn "*mov_negscc"
6127   [(set (match_operand:SI 0 "s_register_operand" "=r")
6128         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6129                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6130   "TARGET_ARM"
6131   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6132   [(set_attr "conds" "use")
6133    (set_attr "length" "8")]
6136 (define_insn "*mov_notscc"
6137   [(set (match_operand:SI 0 "s_register_operand" "=r")
6138         (not:SI (match_operator:SI 1 "arm_comparison_operator"
6139                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6140   "TARGET_ARM"
6141   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6142   [(set_attr "conds" "use")
6143    (set_attr "length" "8")]
6147 ;; Conditional move insns
6149 (define_expand "movsicc"
6150   [(set (match_operand:SI 0 "s_register_operand" "")
6151         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6152                          (match_operand:SI 2 "arm_not_operand" "")
6153                          (match_operand:SI 3 "arm_not_operand" "")))]
6154   "TARGET_ARM"
6155   "
6156   {
6157     enum rtx_code code = GET_CODE (operands[1]);
6158     rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6160     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6161   }"
6164 (define_expand "movsfcc"
6165   [(set (match_operand:SF 0 "s_register_operand" "")
6166         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6167                          (match_operand:SF 2 "s_register_operand" "")
6168                          (match_operand:SF 3 "nonmemory_operand" "")))]
6169   "TARGET_ARM"
6170   "
6171   {
6172     enum rtx_code code = GET_CODE (operands[1]);
6173     rtx ccreg;
6175     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
6176        Otherwise, ensure it is a valid FP add operand */
6177     if ((!TARGET_HARD_FLOAT)
6178         || (!fpu_add_operand (operands[3], SFmode)))
6179       operands[3] = force_reg (SFmode, operands[3]);
6181     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6182     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6183   }"
6186 (define_expand "movdfcc"
6187   [(set (match_operand:DF 0 "s_register_operand" "")
6188         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6189                          (match_operand:DF 2 "s_register_operand" "")
6190                          (match_operand:DF 3 "fpu_add_operand" "")))]
6191   "TARGET_ARM && TARGET_HARD_FLOAT"
6192   "
6193   {
6194     enum rtx_code code = GET_CODE (operands[1]);
6195     rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6197     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6198   }"
6201 (define_insn "*movsicc_insn"
6202   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6203         (if_then_else:SI
6204          (match_operator 3 "arm_comparison_operator"
6205           [(match_operand 4 "cc_register" "") (const_int 0)])
6206          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6207          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6208   "TARGET_ARM"
6209   "@
6210    mov%D3\\t%0, %2
6211    mvn%D3\\t%0, #%B2
6212    mov%d3\\t%0, %1
6213    mvn%d3\\t%0, #%B1
6214    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6215    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6216    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6217    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6218   [(set_attr "length" "4,4,4,4,8,8,8,8")
6219    (set_attr "conds" "use")]
6222 (define_insn "*movsfcc_hard_insn"
6223   [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6224         (if_then_else:SF
6225          (match_operator 3 "arm_comparison_operator" 
6226           [(match_operand 4 "cc_register" "") (const_int 0)])
6227          (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6228          (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6229   "TARGET_ARM && TARGET_HARD_FLOAT"
6230   "@
6231    mvf%D3s\\t%0, %2
6232    mnf%D3s\\t%0, #%N2
6233    mvf%d3s\\t%0, %1
6234    mnf%d3s\\t%0, #%N1
6235    mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6236    mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6237    mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6238    mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6239   [(set_attr "length" "4,4,4,4,8,8,8,8")
6240    (set_attr "type" "ffarith")
6241    (set_attr "conds" "use")]
6244 (define_insn "*movsfcc_soft_insn"
6245   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6246         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6247                           [(match_operand 4 "cc_register" "") (const_int 0)])
6248                          (match_operand:SF 1 "s_register_operand" "0,r")
6249                          (match_operand:SF 2 "s_register_operand" "r,0")))]
6250   "TARGET_ARM && TARGET_SOFT_FLOAT"
6251   "@
6252    mov%D3\\t%0, %2
6253    mov%d3\\t%0, %1"
6254   [(set_attr "conds" "use")]
6257 (define_insn "*movdfcc_insn"
6258   [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6259         (if_then_else:DF
6260          (match_operator 3 "arm_comparison_operator"
6261           [(match_operand 4 "cc_register" "") (const_int 0)])
6262          (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6263          (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6264   "TARGET_ARM && TARGET_HARD_FLOAT"
6265   "@
6266    mvf%D3d\\t%0, %2
6267    mnf%D3d\\t%0, #%N2
6268    mvf%d3d\\t%0, %1
6269    mnf%d3d\\t%0, #%N1
6270    mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6271    mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6272    mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6273    mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6274   [(set_attr "length" "4,4,4,4,8,8,8,8")
6275    (set_attr "type" "ffarith")
6276    (set_attr "conds" "use")]
6280 ;; Jump and linkage insns
6282 (define_expand "jump"
6283   [(set (pc)
6284         (label_ref (match_operand 0 "" "")))]
6285   "TARGET_EITHER"
6286   ""
6289 (define_insn "*arm_jump"
6290   [(set (pc)
6291         (label_ref (match_operand 0 "" "")))]
6292   "TARGET_ARM"
6293   "*
6294   {
6295     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6296       {
6297         arm_ccfsm_state += 2;
6298         return \"\";
6299       }
6300     return \"b%?\\t%l0\";
6301   }
6302   "
6303   [(set_attr "predicable" "yes")]
6306 (define_insn "*thumb_jump"
6307   [(set (pc)
6308         (label_ref (match_operand 0 "" "")))]
6309   "TARGET_THUMB"
6310   "*
6311   if (get_attr_length (insn) == 2)
6312     return \"b\\t%l0\";
6313   return \"bl\\t%l0\\t%@ far jump\";
6314   "
6315   [(set (attr "far_jump")
6316         (if_then_else
6317             (eq_attr "length" "4")
6318             (const_string "yes")
6319             (const_string "no")))
6320    (set (attr "length") 
6321         (if_then_else
6322             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6323                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
6324             (const_int 2)
6325             (const_int 4)))]
6328 (define_expand "call"
6329   [(parallel [(call (match_operand 0 "memory_operand" "")
6330                     (match_operand 1 "general_operand" ""))
6331               (use (match_operand 2 "" ""))
6332               (clobber (reg:SI LR_REGNUM))])]
6333   "TARGET_EITHER"
6334   "
6335   {
6336     rtx callee;
6337     
6338     /* In an untyped call, we can get NULL for operand 2.  */
6339     if (operands[2] == NULL_RTX)
6340       operands[2] = const0_rtx;
6341       
6342     /* This is to decide if we should generate indirect calls by loading the
6343        32 bit address of the callee into a register before performing the
6344        branch and link.  operand[2] encodes the long_call/short_call
6345        attribute of the function being called.  This attribute is set whenever
6346        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6347        is used, and the short_call attribute can also be set if function is
6348        declared as static or if it has already been defined in the current
6349        compilation unit.  See arm.c and arm.h for info about this.  The third
6350        parameter to arm_is_longcall_p is used to tell it which pattern
6351        invoked it.  */
6352     callee  = XEXP (operands[0], 0);
6353     
6354     if (GET_CODE (callee) != REG
6355        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6356       XEXP (operands[0], 0) = force_reg (Pmode, callee);
6357   }"
6360 (define_insn "*call_reg"
6361   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6362          (match_operand 1 "" ""))
6363    (use (match_operand 2 "" ""))
6364    (clobber (reg:SI LR_REGNUM))]
6365   "TARGET_ARM"
6366   "*
6367   return output_call (operands);
6368   "
6369   ;; length is worst case, normally it is only two
6370   [(set_attr "length" "12")
6371    (set_attr "type" "call")]
6374 (define_insn "*call_mem"
6375   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6376          (match_operand 1 "" ""))
6377    (use (match_operand 2 "" ""))
6378    (clobber (reg:SI LR_REGNUM))]
6379   "TARGET_ARM"
6380   "*
6381   return output_call_mem (operands);
6382   "
6383   [(set_attr "length" "12")
6384    (set_attr "type" "call")]
6387 (define_insn "*call_indirect"
6388   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6389          (match_operand 1 "" ""))
6390    (use (match_operand 2 "" ""))
6391    (clobber (reg:SI LR_REGNUM))]
6392   "TARGET_THUMB"
6393   "*
6394   {
6395     if (TARGET_CALLER_INTERWORKING)
6396       return \"bl\\t%__interwork_call_via_%0\";
6397     else
6398       return \"bl\\t%__call_via_%0\";
6399   }"
6400   [(set_attr "type" "call")]
6403 (define_insn "*call_value_indirect"
6404   [(set (match_operand 0 "" "=l")
6405         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6406               (match_operand 2 "" "")))
6407    (use (match_operand 3 "" ""))
6408    (clobber (reg:SI LR_REGNUM))]
6409   "TARGET_THUMB"
6410   "*
6411   {
6412     if (TARGET_CALLER_INTERWORKING)
6413       return \"bl\\t%__interwork_call_via_%1\";
6414     else
6415       return \"bl\\t%__call_via_%1\";
6416   }"
6417   [(set_attr "type" "call")]
6420 (define_expand "call_value"
6421   [(parallel [(set (match_operand       0 "" "")
6422                    (call (match_operand 1 "memory_operand" "")
6423                          (match_operand 2 "general_operand" "")))
6424               (use (match_operand 3 "" ""))
6425               (clobber (reg:SI LR_REGNUM))])]
6426   "TARGET_EITHER"
6427   "
6428   {
6429     rtx callee = XEXP (operands[1], 0);
6430     
6431     /* In an untyped call, we can get NULL for operand 2.  */
6432     if (operands[3] == 0)
6433       operands[3] = const0_rtx;
6434       
6435     /* See the comment in define_expand \"call\".  */
6436     if (GET_CODE (callee) != REG
6437         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6438       XEXP (operands[1], 0) = force_reg (Pmode, callee);
6439   }"
6442 (define_insn "*call_value_reg"
6443   [(set (match_operand 0 "" "=r,f")
6444         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6445               (match_operand 2 "" "")))
6446    (use (match_operand 3 "" ""))
6447    (clobber (reg:SI LR_REGNUM))]
6448   "TARGET_ARM"
6449   "*
6450   return output_call (&operands[1]);
6451   "
6452   [(set_attr "length" "12")
6453    (set_attr "type" "call")]
6456 (define_insn "*call_value_mem"
6457   [(set (match_operand 0 "" "=r,f")
6458         (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6459               (match_operand 2 "" "")))
6460    (use (match_operand 3 "" ""))
6461    (clobber (reg:SI LR_REGNUM))]
6462   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6463   "*
6464   return output_call_mem (&operands[1]);
6465   "
6466   [(set_attr "length" "12")
6467    (set_attr "type" "call")]
6470 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6471 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6473 (define_insn "*call_symbol"
6474   [(call (mem:SI (match_operand:SI 0 "" "X"))
6475          (match_operand 1 "" ""))
6476    (use (match_operand 2 "" ""))
6477    (clobber (reg:SI LR_REGNUM))]
6478   "TARGET_ARM
6479    && (GET_CODE (operands[0]) == SYMBOL_REF)
6480    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6481   "*
6482   {
6483     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6484   }"
6485   [(set_attr "type" "call")]
6488 (define_insn "*call_value_symbol"
6489   [(set (match_operand 0 "s_register_operand" "=r,f")
6490         (call (mem:SI (match_operand:SI 1 "" "X,X"))
6491         (match_operand:SI 2 "" "")))
6492    (use (match_operand 3 "" ""))
6493    (clobber (reg:SI LR_REGNUM))]
6494   "TARGET_ARM
6495    && (GET_CODE (operands[1]) == SYMBOL_REF)
6496    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6497   "*
6498   {
6499     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6500   }"
6501   [(set_attr "type" "call")]
6504 (define_insn "*call_insn"
6505   [(call (mem:SI (match_operand:SI 0 "" "X"))
6506          (match_operand:SI 1 "" ""))
6507    (use (match_operand 2 "" ""))
6508    (clobber (reg:SI LR_REGNUM))]
6509   "TARGET_THUMB
6510    && operands[2] == const0_rtx && (GET_CODE (operands[0]) == SYMBOL_REF)"
6511   "bl\\t%a0"
6512   [(set_attr "length" "4")
6513    (set_attr "type" "call")]
6516 (define_insn "*call_value_insn"
6517   [(set (match_operand 0 "register_operand" "=l")
6518         (call (mem:SI (match_operand 1 "" "X"))
6519               (match_operand 2 "" "")))
6520    (use (match_operand 3 "" ""))
6521    (clobber (reg:SI LR_REGNUM))]
6522   "TARGET_THUMB
6523    && operands[3] == const0_rtx && (GET_CODE (operands[1]) == SYMBOL_REF)"
6524   "bl\\t%a1"
6525   [(set_attr "length" "4")
6526    (set_attr "type" "call")]
6529 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6530 (define_expand "sibcall"
6531   [(parallel [(call (match_operand 0 "memory_operand" "")
6532                     (match_operand 1 "general_operand" ""))
6533               (use (match_operand 2 "" ""))
6534               (use (reg:SI LR_REGNUM))])]
6535   "TARGET_ARM"
6536   "
6537   {
6538     if (operands[2] == NULL_RTX)
6539       operands[2] = const0_rtx;
6540   }"
6543 (define_expand "sibcall_value"
6544   [(parallel [(set (match_operand 0 "register_operand" "")
6545                    (call (match_operand 1 "memory_operand" "")
6546                          (match_operand 2 "general_operand" "")))
6547               (use (match_operand 3 "" ""))
6548               (use (reg:SI LR_REGNUM))])]
6549   "TARGET_ARM"
6550   "
6551   {
6552     if (operands[3] == NULL_RTX)
6553       operands[3] = const0_rtx;
6554   }"
6557 (define_insn "*sibcall_insn"
6558  [(call (mem:SI (match_operand:SI 0 "" "X"))
6559         (match_operand 1 "" ""))
6560   (use (match_operand 2 "" ""))
6561   (use (reg:SI LR_REGNUM))]
6562   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6563   "*
6564   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6565   "
6566   [(set_attr "type" "call")]
6569 (define_insn "*sibcall_value_insn"
6570  [(set (match_operand 0 "s_register_operand" "=r,f")
6571        (call (mem:SI (match_operand:SI 1 "" "X,X"))
6572              (match_operand 2 "" "")))
6573   (use (match_operand 3 "" ""))
6574   (use (reg:SI LR_REGNUM))]
6575   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6576   "*
6577   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6578   "
6579   [(set_attr "type" "call")]
6582 ;; Often the return insn will be the same as loading from memory, so set attr
6583 (define_insn "return"
6584   [(return)]
6585   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6586   "*
6587   {
6588     if (arm_ccfsm_state == 2)
6589       {
6590         arm_ccfsm_state += 2;
6591         return \"\";
6592       }
6593     return output_return_instruction (NULL, TRUE, FALSE);
6594   }"
6595   [(set_attr "type" "load")
6596    (set_attr "predicable" "yes")]
6599 (define_insn "*cond_return"
6600   [(set (pc)
6601         (if_then_else (match_operator 0 "arm_comparison_operator"
6602                        [(match_operand 1 "cc_register" "") (const_int 0)])
6603                       (return)
6604                       (pc)))]
6605   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6606   "*
6607   {
6608     if (arm_ccfsm_state == 2)
6609       {
6610         arm_ccfsm_state += 2;
6611         return \"\";
6612       }
6613     return output_return_instruction (operands[0], TRUE, FALSE);
6614   }"
6615   [(set_attr "conds" "use")
6616    (set_attr "type" "load")]
6619 (define_insn "*cond_return_inverted"
6620   [(set (pc)
6621         (if_then_else (match_operator 0 "arm_comparison_operator"
6622                        [(match_operand 1 "cc_register" "") (const_int 0)])
6623                       (pc)
6624                       (return)))]
6625   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6626   "*
6627   {
6628     if (arm_ccfsm_state == 2)
6629       {
6630         arm_ccfsm_state += 2;
6631         return \"\";
6632       }
6633     return output_return_instruction (operands[0], TRUE, TRUE);
6634   }"
6635   [(set_attr "conds" "use")
6636    (set_attr "type" "load")]
6639 ;; Call subroutine returning any type.
6641 (define_expand "untyped_call"
6642   [(parallel [(call (match_operand 0 "" "")
6643                     (const_int 0))
6644               (match_operand 1 "" "")
6645               (match_operand 2 "" "")])]
6646   "TARGET_ARM"
6647   "
6648   {
6649     int i;
6651     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6653     for (i = 0; i < XVECLEN (operands[2], 0); i++)
6654       {
6655         rtx set = XVECEXP (operands[2], 0, i);
6657         emit_move_insn (SET_DEST (set), SET_SRC (set));
6658       }
6660     /* The optimizer does not know that the call sets the function value
6661        registers we stored in the result block.  We avoid problems by
6662        claiming that all hard registers are used and clobbered at this
6663        point.  */
6664     emit_insn (gen_blockage ());
6666     DONE;
6667   }"
6670 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6671 ;; all of memory.  This blocks insns from being moved across this point.
6673 (define_insn "blockage"
6674   [(unspec_volatile [(const_int 0)] 0)]
6675   "TARGET_EITHER"
6676   ""
6677   [(set_attr "length" "0")
6678    (set_attr "type" "block")]
6681 (define_expand "casesi"
6682   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6683    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
6684    (match_operand:SI 2 "const_int_operand" "")  ; total range
6685    (match_operand:SI 3 "" "")                   ; table label
6686    (match_operand:SI 4 "" "")]                  ; Out of range label
6687   "TARGET_ARM"
6688   "
6689   {
6690     rtx reg;
6691     if (operands[1] != const0_rtx)
6692       {
6693         reg = gen_reg_rtx (SImode);
6695         emit_insn (gen_addsi3 (reg, operands[0],
6696                                GEN_INT (-INTVAL (operands[1]))));
6697         operands[0] = reg;
6698       }
6700     if (!const_ok_for_arm (INTVAL (operands[2])))
6701       operands[2] = force_reg (SImode, operands[2]);
6703     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6704                                          operands[4]));
6705     DONE;
6706   }"
6709 ;; The USE in this pattern is needed to tell flow analysis that this is
6710 ;; a CASESI insn.  It has no other purpose.
6711 (define_insn "casesi_internal"
6712   [(parallel [(set (pc)
6713                (if_then_else
6714                 (leu (match_operand:SI 0 "s_register_operand" "r")
6715                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
6716                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6717                                  (label_ref (match_operand 2 "" ""))))
6718                 (label_ref (match_operand 3 "" ""))))
6719               (clobber (reg:CC CC_REGNUM))
6720               (use (label_ref (match_dup 2)))])]
6721   "TARGET_ARM"
6722   "*
6723     if (flag_pic)
6724       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6725     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6726   "
6727   [(set_attr "conds" "clob")
6728    (set_attr "length" "12")]
6731 (define_expand "indirect_jump"
6732   [(set (pc)
6733         (match_operand:SI 0 "s_register_operand" ""))]
6734   "TARGET_EITHER"
6735   ""
6738 (define_insn "*arm_indirect_jump"
6739   [(set (pc)
6740         (match_operand:SI 0 "s_register_operand" "r"))]
6741   "TARGET_ARM"
6742   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6743   [(set_attr "predicable" "yes")]
6746 ;; Although not supported by the define_expand above,
6747 ;; cse/combine may generate this form.
6748 (define_insn "*load_indirect_jump"
6749   [(set (pc)
6750         (match_operand:SI 0 "memory_operand" "m"))]
6751   "TARGET_ARM"
6752   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6753   [(set_attr "type" "load")
6754    (set_attr "predicable" "yes")]
6757 (define_insn "*thumb_indirect_jump"
6758   [(set (pc)
6759         (match_operand:SI 0 "register_operand" "l*r"))]
6760   "TARGET_THUMB"
6761   "mov\\tpc, %0"
6762   [(set_attr "conds" "clob")
6763    (set_attr "length" "2")]
6767 ;; Misc insns
6769 (define_insn "nop"
6770   [(const_int 0)]
6771   "TARGET_EITHER"
6772   "*
6773   if (TARGET_ARM)
6774     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6775   return  \"mov\\tr8, r8\";
6776   "
6777   [(set (attr "length")
6778         (if_then_else (eq_attr "is_thumb" "yes")
6779                       (const_int 2)
6780                       (const_int 4)))]
6784 ;; Patterns to allow combination of arithmetic, cond code and shifts
6786 (define_insn "*arith_shiftsi"
6787   [(set (match_operand:SI 0 "s_register_operand" "=r")
6788         (match_operator:SI 1 "shiftable_operator"
6789           [(match_operator:SI 3 "shift_operator"
6790              [(match_operand:SI 4 "s_register_operand" "r")
6791               (match_operand:SI 5 "reg_or_int_operand" "rI")])
6792            (match_operand:SI 2 "s_register_operand" "r")]))]
6793   "TARGET_ARM"
6794   "%i1%?\\t%0, %2, %4%S3"
6795   [(set_attr "predicable" "yes")
6796    (set_attr "shift" "4")
6797    ]
6800 (define_insn "*arith_shiftsi_compare0"
6801   [(set (reg:CC_NOOV CC_REGNUM)
6802         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6803                           [(match_operator:SI 3 "shift_operator"
6804                             [(match_operand:SI 4 "s_register_operand" "r")
6805                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6806                            (match_operand:SI 2 "s_register_operand" "r")])
6807                          (const_int 0)))
6808    (set (match_operand:SI 0 "s_register_operand" "=r")
6809         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6810                          (match_dup 2)]))]
6811   "TARGET_ARM"
6812   "%i1%?s\\t%0, %2, %4%S3"
6813   [(set_attr "conds" "set")
6814    (set_attr "shift" "4")
6815    ]
6818 (define_insn "*arith_shiftsi_compare0_scratch"
6819   [(set (reg:CC_NOOV CC_REGNUM)
6820         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6821                           [(match_operator:SI 3 "shift_operator"
6822                             [(match_operand:SI 4 "s_register_operand" "r")
6823                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6824                            (match_operand:SI 2 "s_register_operand" "r")])
6825                          (const_int 0)))
6826    (clobber (match_scratch:SI 0 "=r"))]
6827   "TARGET_ARM"
6828   "%i1%?s\\t%0, %2, %4%S3"
6829   [(set_attr "conds" "set")
6830    (set_attr "shift" "4")
6831    ]
6834 (define_insn "*sub_shiftsi"
6835   [(set (match_operand:SI 0 "s_register_operand" "=r")
6836         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6837                   (match_operator:SI 2 "shift_operator"
6838                    [(match_operand:SI 3 "s_register_operand" "r")
6839                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6840   "TARGET_ARM"
6841   "sub%?\\t%0, %1, %3%S2"
6842   [(set_attr "predicable" "yes")
6843    (set_attr "shift" "3")
6844    ]
6847 (define_insn "*sub_shiftsi_compare0"
6848   [(set (reg:CC_NOOV CC_REGNUM)
6849         (compare:CC_NOOV
6850          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6851                    (match_operator:SI 2 "shift_operator"
6852                     [(match_operand:SI 3 "s_register_operand" "r")
6853                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6854          (const_int 0)))
6855    (set (match_operand:SI 0 "s_register_operand" "=r")
6856         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6857                                                  (match_dup 4)])))]
6858   "TARGET_ARM"
6859   "sub%?s\\t%0, %1, %3%S2"
6860   [(set_attr "conds" "set")
6861    (set_attr "shift" "3") 
6862    ]
6865 (define_insn "*sub_shiftsi_compare0_scratch"
6866   [(set (reg:CC_NOOV CC_REGNUM)
6867         (compare:CC_NOOV
6868          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6869                    (match_operator:SI 2 "shift_operator"
6870                     [(match_operand:SI 3 "s_register_operand" "r")
6871                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6872          (const_int 0)))
6873    (clobber (match_scratch:SI 0 "=r"))]
6874   "TARGET_ARM"
6875   "sub%?s\\t%0, %1, %3%S2"
6876   [(set_attr "conds" "set")
6877    (set_attr "shift" "3") 
6878    ]
6881 ;; These variants of the above insns can occur if the first operand is the
6882 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
6883 ;; seem to be a way around it.  Most of the predicates have to be null
6884 ;; because the format can be generated part way through reload, so
6885 ;; if we don't match it as soon as it becomes available, reload doesn't know
6886 ;; how to reload pseudos that haven't got hard registers; the constraints will
6887 ;; sort everything out.
6889 (define_insn "*reload_mulsi3"
6890   [(set (match_operand:SI 0 "" "=&r")
6891         (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
6892                            [(match_operand:SI 3 "" "r")
6893                             (match_operand:SI 4 "" "rM")])
6894                           (match_operand:SI 2 "" "r"))
6895                  (match_operand:SI 1 "const_int_operand" "n")))]
6896   "TARGET_ARM && reload_in_progress"
6897   "*
6898   output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
6899   operands[2] = operands[1];
6900   operands[1] = operands[0];
6901   return output_add_immediate (operands);
6902   "
6903   [
6904    ; we have no idea how long the add_immediate is, it could be up to 4.
6905    (set_attr "length" "20")]
6908 (define_insn "*reload_mulsi_compare0"
6909   [(set (reg:CC_NOOV CC_REGNUM)
6910         (compare:CC_NOOV (plus:SI
6911                           (plus:SI 
6912                            (match_operator:SI 5 "shift_operator"
6913                             [(match_operand:SI 3 "" "r")
6914                              (match_operand:SI 4 "" "rM")])
6915                            (match_operand:SI 1 "" "r"))
6916                           (match_operand:SI 2 "const_int_operand" "n"))
6917                          (const_int 0)))
6918    (set (match_operand:SI 0 "" "=&r")
6919         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
6920                           (match_dup 1))
6921                  (match_dup 2)))]
6922   "TARGET_ARM && reload_in_progress && !arm_is_xscale"
6923   "*
6924     output_add_immediate (operands);
6925     return \"add%?s\\t%0, %0, %3%S5\";
6926   "
6927   [(set_attr "conds" "set")
6928    (set_attr "shift" "3")
6929    (set_attr "length" "20")]
6932 (define_insn "*reload_mulsi_compare0_scratch"
6933   [(set (reg:CC_NOOV CC_REGNUM)
6934         (compare:CC_NOOV (plus:SI
6935                           (plus:SI 
6936                            (match_operator:SI 5 "shift_operator"
6937                             [(match_operand:SI 3 "" "r")
6938                              (match_operand:SI 4 "" "rM")])
6939                            (match_operand:SI 1 "" "r"))
6940                           (match_operand:SI 2 "const_int_operand" "n"))
6941                          (const_int 0)))
6942    (clobber (match_scratch:SI 0 "=&r"))]
6943   "TARGET_ARM && reload_in_progress && !arm_is_xscale"
6944   "*
6945     output_add_immediate (operands);
6946     return \"add%?s\\t%0, %0, %3%S5\";
6947   "
6948   [(set_attr "conds" "set")
6949    (set_attr "shift" "3")
6950    (set_attr "length" "20")]
6953 ;; These are similar, but are needed when the mla pattern contains the
6954 ;; eliminated register as operand 3.
6956 (define_insn "*reload_muladdsi"
6957   [(set (match_operand:SI 0 "" "=&r,&r")
6958         (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
6959                                    (match_operand:SI 2 "" "r,r"))
6960                           (match_operand:SI 3 "" "r,r"))
6961                  (match_operand:SI 4 "const_int_operand" "n,n")))]
6962   "TARGET_ARM && reload_in_progress"
6963   "*
6964   output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
6965   operands[2] = operands[4];
6966   operands[1] = operands[0];
6967   return output_add_immediate (operands);
6968   "
6969   [(set_attr "length" "20")
6970    (set_attr "type" "mult")]
6973 (define_insn "*reload_muladdsi_compare0"
6974   [(set (reg:CC_NOOV CC_REGNUM)
6975         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
6976                                             (match_operand:SI 3 "" "r")
6977                                             (match_operand:SI 4 "" "r"))
6978                                            (match_operand:SI 1 "" "r"))
6979                                   (match_operand:SI 2 "const_int_operand" "n"))
6980                          (const_int 0)))
6981    (set (match_operand:SI 0 "" "=&r")
6982         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
6983                  (match_dup 2)))]
6984   "TARGET_ARM && reload_in_progress && !arm_is_xscale"
6985   "*
6986     output_add_immediate (operands);
6987     output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
6988     return \"\";
6989   "
6990   [(set_attr "length" "20")
6991    (set_attr "conds" "set")
6992    (set_attr "type" "mult")]
6995 (define_insn "*reload_muladdsi_compare0_scratch"
6996   [(set (reg:CC_NOOV CC_REGNUM)
6997         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
6998                                             (match_operand:SI 3 "" "r")
6999                                             (match_operand:SI 4 "" "r"))
7000                                            (match_operand:SI 1 "" "r"))
7001                                   (match_operand:SI 2 "const_int_operand" "n"))
7002                          (const_int 0)))
7003    (clobber (match_scratch:SI 0 "=&r"))]
7004   "TARGET_ARM && reload_in_progress"
7005   "*
7006     output_add_immediate (operands);
7007     return \"mla%?s\\t%0, %3, %4, %0\";
7008   "
7009   [(set_attr "length" "20")
7010    (set_attr "conds" "set")
7011    (set_attr "type" "mult")]
7016 (define_insn "*and_scc"
7017   [(set (match_operand:SI 0 "s_register_operand" "=r")
7018         (and:SI (match_operator:SI 1 "arm_comparison_operator"
7019                  [(match_operand 3 "cc_register" "") (const_int 0)])
7020                 (match_operand:SI 2 "s_register_operand" "r")))]
7021   "TARGET_ARM"
7022   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7023   [(set_attr "conds" "use")
7024    (set_attr "length" "8")]
7027 (define_insn "*ior_scc"
7028   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7029         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7030                  [(match_operand 3 "cc_register" "") (const_int 0)])
7031                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7032   "TARGET_ARM"
7033   "@
7034    orr%d2\\t%0, %1, #1
7035    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7036   [(set_attr "conds" "use")
7037    (set_attr "length" "4,8")]
7040 (define_insn "*compare_scc"
7041   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7042         (match_operator:SI 1 "arm_comparison_operator"
7043          [(match_operand:SI 2 "s_register_operand" "r,r")
7044           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7045    (clobber (reg:CC CC_REGNUM))]
7046   "TARGET_ARM"
7047   "*
7048     if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7049       return \"mov\\t%0, %2, lsr #31\";
7051     if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7052       return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7054     if (GET_CODE (operands[1]) == NE)
7055       {
7056         if (which_alternative == 1)
7057           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7058         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7059       }
7060     if (which_alternative == 1)
7061       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7062     else
7063       output_asm_insn (\"cmp\\t%2, %3\", operands);
7064     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7065   "
7066   [(set_attr "conds" "clob")
7067    (set_attr "length" "12")]
7070 (define_insn "*cond_move"
7071   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7072         (if_then_else:SI (match_operator 3 "equality_operator"
7073                           [(match_operator 4 "arm_comparison_operator"
7074                             [(match_operand 5 "cc_register" "") (const_int 0)])
7075                            (const_int 0)])
7076                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7077                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7078   "TARGET_ARM"
7079   "*
7080     if (GET_CODE (operands[3]) == NE)
7081       {
7082         if (which_alternative != 1)
7083           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7084         if (which_alternative != 0)
7085           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7086         return \"\";
7087       }
7088     if (which_alternative != 0)
7089       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7090     if (which_alternative != 1)
7091       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7092     return \"\";
7093   "
7094   [(set_attr "conds" "use")
7095    (set_attr "length" "4,4,8")]
7098 (define_insn "*cond_arith"
7099   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7100         (match_operator:SI 5 "shiftable_operator" 
7101          [(match_operator:SI 4 "arm_comparison_operator"
7102            [(match_operand:SI 2 "s_register_operand" "r,r")
7103             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7104           (match_operand:SI 1 "s_register_operand" "0,?r")]))
7105    (clobber (reg:CC CC_REGNUM))]
7106   "TARGET_ARM"
7107   "*
7108     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7109       return \"%i5\\t%0, %1, %2, lsr #31\";
7111     output_asm_insn (\"cmp\\t%2, %3\", operands);
7112     if (GET_CODE (operands[5]) == AND)
7113       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7114     else if (GET_CODE (operands[5]) == MINUS)
7115       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7116     else if (which_alternative != 0)
7117       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7118     return \"%i5%d4\\t%0, %1, #1\";
7119   "
7120   [(set_attr "conds" "clob")
7121    (set_attr "length" "12")]
7124 (define_insn "*cond_sub"
7125   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7126         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7127                   (match_operator:SI 4 "arm_comparison_operator"
7128                    [(match_operand:SI 2 "s_register_operand" "r,r")
7129                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7130    (clobber (reg:CC CC_REGNUM))]
7131   "TARGET_ARM"
7132   "*
7133     output_asm_insn (\"cmp\\t%2, %3\", operands);
7134     if (which_alternative != 0)
7135       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7136     return \"sub%d4\\t%0, %1, #1\";
7137   "
7138   [(set_attr "conds" "clob")
7139    (set_attr "length" "8,12")]
7142 (define_insn "*cmp_ite0"
7143   [(set (match_operand 6 "dominant_cc_register" "")
7144         (compare
7145          (if_then_else:SI
7146           (match_operator 4 "arm_comparison_operator"
7147            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7148             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7149           (match_operator:SI 5 "arm_comparison_operator"
7150            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7151             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7152           (const_int 0))
7153          (const_int 0)))]
7154   "TARGET_ARM"
7155   "*
7156   {
7157     static const char * const opcodes[4][2] =
7158     {
7159       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7160        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7161       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7162        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7163       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7164        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7165       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7166        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7167     };
7168     int swap =
7169       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7171     return opcodes[which_alternative][swap];
7172   }"
7173   [(set_attr "conds" "set")
7174    (set_attr "length" "8")]
7177 (define_insn "*cmp_ite1"
7178   [(set (match_operand 6 "dominant_cc_register" "")
7179         (compare
7180          (if_then_else:SI
7181           (match_operator 4 "arm_comparison_operator"
7182            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7183             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7184           (match_operator:SI 5 "arm_comparison_operator"
7185            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7186             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7187           (const_int 1))
7188          (const_int 0)))]
7189   "TARGET_ARM"
7190   "*
7191   {
7192     static const char * const opcodes[4][2] =
7193     {
7194       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7195        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7196       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7197        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7198       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7199        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7200       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7201        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7202     };
7203     int swap =
7204       comparison_dominates_p (GET_CODE (operands[5]),
7205                               reverse_condition (GET_CODE (operands[4])));
7207     return opcodes[which_alternative][swap];
7208   }"
7209   [(set_attr "conds" "set")
7210    (set_attr "length" "8")]
7213 (define_insn "*cmp_and"
7214   [(set (match_operand 6 "dominant_cc_register" "")
7215         (compare
7216          (and:SI
7217           (match_operator 4 "arm_comparison_operator"
7218            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7219             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7220           (match_operator:SI 5 "arm_comparison_operator"
7221            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7222             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7223          (const_int 0)))]
7224   "TARGET_ARM"
7225   "*
7226   {
7227     const char * opcodes[4][2] =
7228     {
7229       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7230        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7231       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7232        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7233       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7234        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7235       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7236        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7237     };
7238     int swap =
7239       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7241     return opcodes[which_alternative][swap];
7242   }"
7243   [(set_attr "conds" "set")
7244    (set_attr "predicable" "no")
7245    (set_attr "length" "8")]
7248 (define_insn "*cmp_ior"
7249   [(set (match_operand 6 "dominant_cc_register" "")
7250         (compare
7251          (ior:SI
7252           (match_operator 4 "arm_comparison_operator"
7253            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7254             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7255           (match_operator:SI 5 "arm_comparison_operator"
7256            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7257             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7258          (const_int 0)))]
7259   "TARGET_ARM"
7260   "*
7262   const char * opcodes[4][2] =
7263   {
7264     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7265      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7266     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7267      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7268     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7269      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7270     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7271      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7272   };
7273   int swap =
7274     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7276   return opcodes[which_alternative][swap];
7279   [(set_attr "conds" "set")
7280    (set_attr "length" "8")]
7283 (define_insn "*negscc"
7284   [(set (match_operand:SI 0 "s_register_operand" "=r")
7285         (neg:SI (match_operator 3 "arm_comparison_operator"
7286                  [(match_operand:SI 1 "s_register_operand" "r")
7287                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7288    (clobber (reg:CC CC_REGNUM))]
7289   "TARGET_ARM"
7290   "*
7291   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7292     return \"mov\\t%0, %1, asr #31\";
7294   if (GET_CODE (operands[3]) == NE)
7295     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7297   if (GET_CODE (operands[3]) == GT)
7298     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7300   output_asm_insn (\"cmp\\t%1, %2\", operands);
7301   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7302   return \"mvn%d3\\t%0, #0\";
7303   "
7304   [(set_attr "conds" "clob")
7305    (set_attr "length" "12")]
7308 (define_insn "movcond"
7309   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7310         (if_then_else:SI
7311          (match_operator 5 "arm_comparison_operator"
7312           [(match_operand:SI 3 "s_register_operand" "r,r,r")
7313            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7314          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7315          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7316    (clobber (reg:CC CC_REGNUM))]
7317   "TARGET_ARM"
7318   "*
7319   if (GET_CODE (operands[5]) == LT
7320       && (operands[4] == const0_rtx))
7321     {
7322       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7323         {
7324           if (operands[2] == const0_rtx)
7325             return \"and\\t%0, %1, %3, asr #31\";
7326           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7327         }
7328       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7329         {
7330           if (operands[1] == const0_rtx)
7331             return \"bic\\t%0, %2, %3, asr #31\";
7332           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7333         }
7334       /* The only case that falls through to here is when both ops 1 & 2
7335          are constants */
7336     }
7338   if (GET_CODE (operands[5]) == GE
7339       && (operands[4] == const0_rtx))
7340     {
7341       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7342         {
7343           if (operands[2] == const0_rtx)
7344             return \"bic\\t%0, %1, %3, asr #31\";
7345           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7346         }
7347       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7348         {
7349           if (operands[1] == const0_rtx)
7350             return \"and\\t%0, %2, %3, asr #31\";
7351           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7352         }
7353       /* The only case that falls through to here is when both ops 1 & 2
7354          are constants */
7355     }
7356   if (GET_CODE (operands[4]) == CONST_INT
7357       && !const_ok_for_arm (INTVAL (operands[4])))
7358     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7359   else
7360     output_asm_insn (\"cmp\\t%3, %4\", operands);
7361   if (which_alternative != 0)
7362     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7363   if (which_alternative != 1)
7364     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7365   return \"\";
7366   "
7367   [(set_attr "conds" "clob")
7368    (set_attr "length" "8,8,12")]
7371 (define_insn "*ifcompare_plus_move"
7372   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7373         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7374                           [(match_operand:SI 4 "s_register_operand" "r,r")
7375                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7376                          (plus:SI
7377                           (match_operand:SI 2 "s_register_operand" "r,r")
7378                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7379                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7380    (clobber (reg:CC CC_REGNUM))]
7381   "TARGET_ARM"
7382   "#"
7383   [(set_attr "conds" "clob")
7384    (set_attr "length" "8,12")]
7387 (define_insn "*if_plus_move"
7388   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7389         (if_then_else:SI
7390          (match_operator 4 "arm_comparison_operator"
7391           [(match_operand 5 "cc_register" "") (const_int 0)])
7392          (plus:SI
7393           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7394           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7395          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7396   "TARGET_ARM"
7397   "@
7398    add%d4\\t%0, %2, %3
7399    sub%d4\\t%0, %2, #%n3
7400    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7401    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7402   [(set_attr "conds" "use")
7403    (set_attr "length" "4,4,8,8")
7404    (set_attr "type" "*,*,*,*")]
7407 (define_insn "*ifcompare_move_plus"
7408   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7409         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7410                           [(match_operand:SI 4 "s_register_operand" "r,r")
7411                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7412                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7413                          (plus:SI
7414                           (match_operand:SI 2 "s_register_operand" "r,r")
7415                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7416    (clobber (reg:CC CC_REGNUM))]
7417   "TARGET_ARM"
7418   "#"
7419   [(set_attr "conds" "clob")
7420    (set_attr "length" "8,12")]
7423 (define_insn "*if_move_plus"
7424   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7425         (if_then_else:SI
7426          (match_operator 4 "arm_comparison_operator"
7427           [(match_operand 5 "cc_register" "") (const_int 0)])
7428          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7429          (plus:SI
7430           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7431           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7432   "TARGET_ARM"
7433   "@
7434    add%D4\\t%0, %2, %3
7435    sub%D4\\t%0, %2, #%n3
7436    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7437    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7438   [(set_attr "conds" "use")
7439    (set_attr "length" "4,4,8,8")
7440    (set_attr "type" "*,*,*,*")]
7443 (define_insn "*ifcompare_arith_arith"
7444   [(set (match_operand:SI 0 "s_register_operand" "=r")
7445         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7446                           [(match_operand:SI 5 "s_register_operand" "r")
7447                            (match_operand:SI 6 "arm_add_operand" "rIL")])
7448                          (match_operator:SI 8 "shiftable_operator"
7449                           [(match_operand:SI 1 "s_register_operand" "r")
7450                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7451                          (match_operator:SI 7 "shiftable_operator"
7452                           [(match_operand:SI 3 "s_register_operand" "r")
7453                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7454    (clobber (reg:CC CC_REGNUM))]
7455   "TARGET_ARM"
7456   "#"
7457   [(set_attr "conds" "clob")
7458    (set_attr "length" "12")]
7461 (define_insn "*if_arith_arith"
7462   [(set (match_operand:SI 0 "s_register_operand" "=r")
7463         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7464                           [(match_operand 8 "cc_register" "") (const_int 0)])
7465                          (match_operator:SI 6 "shiftable_operator"
7466                           [(match_operand:SI 1 "s_register_operand" "r")
7467                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7468                          (match_operator:SI 7 "shiftable_operator"
7469                           [(match_operand:SI 3 "s_register_operand" "r")
7470                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7471   "TARGET_ARM"
7472   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7473   [(set_attr "conds" "use")
7474    (set_attr "length" "8")]
7477 (define_insn "*ifcompare_arith_move"
7478   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7479         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7480                           [(match_operand:SI 2 "s_register_operand" "r,r")
7481                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7482                          (match_operator:SI 7 "shiftable_operator"
7483                           [(match_operand:SI 4 "s_register_operand" "r,r")
7484                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7485                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7486    (clobber (reg:CC CC_REGNUM))]
7487   "TARGET_ARM"
7488   "*
7489   /* If we have an operation where (op x 0) is the identity operation and
7490      the conditional operator is LT or GE and we are comparing against zero and
7491      everything is in registers then we can do this in two instructions */
7492   if (operands[3] == const0_rtx
7493       && GET_CODE (operands[7]) != AND
7494       && GET_CODE (operands[5]) == REG
7495       && GET_CODE (operands[1]) == REG 
7496       && REGNO (operands[1]) == REGNO (operands[4])
7497       && REGNO (operands[4]) != REGNO (operands[0]))
7498     {
7499       if (GET_CODE (operands[6]) == LT)
7500         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7501       else if (GET_CODE (operands[6]) == GE)
7502         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7503     }
7504   if (GET_CODE (operands[3]) == CONST_INT
7505       && !const_ok_for_arm (INTVAL (operands[3])))
7506     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7507   else
7508     output_asm_insn (\"cmp\\t%2, %3\", operands);
7509   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7510   if (which_alternative != 0)
7511     return \"mov%D6\\t%0, %1\";
7512   return \"\";
7513   "
7514   [(set_attr "conds" "clob")
7515    (set_attr "length" "8,12")]
7518 (define_insn "*if_arith_move"
7519   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7520         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7521                           [(match_operand 6 "cc_register" "") (const_int 0)])
7522                          (match_operator:SI 5 "shiftable_operator"
7523                           [(match_operand:SI 2 "s_register_operand" "r,r")
7524                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7525                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7526   "TARGET_ARM"
7527   "@
7528    %I5%d4\\t%0, %2, %3
7529    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7530   [(set_attr "conds" "use")
7531    (set_attr "length" "4,8")
7532    (set_attr "type" "*,*")]
7535 (define_insn "*ifcompare_move_arith"
7536   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7537         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7538                           [(match_operand:SI 4 "s_register_operand" "r,r")
7539                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7540                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7541                          (match_operator:SI 7 "shiftable_operator"
7542                           [(match_operand:SI 2 "s_register_operand" "r,r")
7543                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7544    (clobber (reg:CC CC_REGNUM))]
7545   "TARGET_ARM"
7546   "*
7547   /* If we have an operation where (op x 0) is the identity operation and
7548      the conditional operator is LT or GE and we are comparing against zero and
7549      everything is in registers then we can do this in two instructions */
7550   if (operands[5] == const0_rtx
7551       && GET_CODE (operands[7]) != AND
7552       && GET_CODE (operands[3]) == REG
7553       && GET_CODE (operands[1]) == REG 
7554       && REGNO (operands[1]) == REGNO (operands[2])
7555       && REGNO (operands[2]) != REGNO (operands[0]))
7556     {
7557       if (GET_CODE (operands[6]) == GE)
7558         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7559       else if (GET_CODE (operands[6]) == LT)
7560         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7561     }
7563   if (GET_CODE (operands[5]) == CONST_INT
7564       && !const_ok_for_arm (INTVAL (operands[5])))
7565     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7566   else
7567     output_asm_insn (\"cmp\\t%4, %5\", operands);
7569   if (which_alternative != 0)
7570     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7571   return \"%I7%D6\\t%0, %2, %3\";
7572   "
7573   [(set_attr "conds" "clob")
7574    (set_attr "length" "8,12")]
7577 (define_insn "*if_move_arith"
7578   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7579         (if_then_else:SI
7580          (match_operator 4 "arm_comparison_operator"
7581           [(match_operand 6 "cc_register" "") (const_int 0)])
7582          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7583          (match_operator:SI 5 "shiftable_operator"
7584           [(match_operand:SI 2 "s_register_operand" "r,r")
7585            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7586   "TARGET_ARM"
7587   "@
7588    %I5%D4\\t%0, %2, %3
7589    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7590   [(set_attr "conds" "use")
7591    (set_attr "length" "4,8")
7592    (set_attr "type" "*,*")]
7595 (define_insn "*ifcompare_move_not"
7596   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7597         (if_then_else:SI
7598          (match_operator 5 "arm_comparison_operator"
7599           [(match_operand:SI 3 "s_register_operand" "r,r")
7600            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7601          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7602          (not:SI
7603           (match_operand:SI 2 "s_register_operand" "r,r"))))
7604    (clobber (reg:CC CC_REGNUM))]
7605   "TARGET_ARM"
7606   "#"
7607   [(set_attr "conds" "clob")
7608    (set_attr "length" "8,12")]
7611 (define_insn "*if_move_not"
7612   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7613         (if_then_else:SI
7614          (match_operator 4 "arm_comparison_operator"
7615           [(match_operand 3 "cc_register" "") (const_int 0)])
7616          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7617          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7618   "TARGET_ARM"
7619   "@
7620    mvn%D4\\t%0, %2
7621    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7622    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7623   [(set_attr "conds" "use")
7624    (set_attr "length" "4,8,8")]
7627 (define_insn "*ifcompare_not_move"
7628   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7629         (if_then_else:SI 
7630          (match_operator 5 "arm_comparison_operator"
7631           [(match_operand:SI 3 "s_register_operand" "r,r")
7632            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7633          (not:SI
7634           (match_operand:SI 2 "s_register_operand" "r,r"))
7635          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7636    (clobber (reg:CC CC_REGNUM))]
7637   "TARGET_ARM"
7638   "#"
7639   [(set_attr "conds" "clob")
7640    (set_attr "length" "8,12")]
7643 (define_insn "*if_not_move"
7644   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7645         (if_then_else:SI
7646          (match_operator 4 "arm_comparison_operator"
7647           [(match_operand 3 "cc_register" "") (const_int 0)])
7648          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7649          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7650   "TARGET_ARM"
7651   "@
7652    mvn%d4\\t%0, %2
7653    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7654    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7655   [(set_attr "conds" "use")
7656    (set_attr "length" "4,8,8")]
7659 (define_insn "*ifcompare_shift_move"
7660   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7661         (if_then_else:SI
7662          (match_operator 6 "arm_comparison_operator"
7663           [(match_operand:SI 4 "s_register_operand" "r,r")
7664            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7665          (match_operator:SI 7 "shift_operator"
7666           [(match_operand:SI 2 "s_register_operand" "r,r")
7667            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7668          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7669    (clobber (reg:CC CC_REGNUM))]
7670   "TARGET_ARM"
7671   "#"
7672   [(set_attr "conds" "clob")
7673    (set_attr "length" "8,12")]
7676 (define_insn "*if_shift_move"
7677   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7678         (if_then_else:SI
7679          (match_operator 5 "arm_comparison_operator"
7680           [(match_operand 6 "cc_register" "") (const_int 0)])
7681          (match_operator:SI 4 "shift_operator"
7682           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7683            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7684          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7685   "TARGET_ARM"
7686   "@
7687    mov%d5\\t%0, %2%S4
7688    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7689    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7690   [(set_attr "conds" "use")
7691    (set_attr "shift" "2")
7692    (set_attr "length" "4,8,8")]
7695 (define_insn "*ifcompare_move_shift"
7696   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7697         (if_then_else:SI
7698          (match_operator 6 "arm_comparison_operator"
7699           [(match_operand:SI 4 "s_register_operand" "r,r")
7700            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7701          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7702          (match_operator:SI 7 "shift_operator"
7703           [(match_operand:SI 2 "s_register_operand" "r,r")
7704            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7705    (clobber (reg:CC CC_REGNUM))]
7706   "TARGET_ARM"
7707   "#"
7708   [(set_attr "conds" "clob")
7709    (set_attr "length" "8,12")]
7712 (define_insn "*if_move_shift"
7713   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7714         (if_then_else:SI
7715          (match_operator 5 "arm_comparison_operator"
7716           [(match_operand 6 "cc_register" "") (const_int 0)])
7717          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7718          (match_operator:SI 4 "shift_operator"
7719           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7720            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7721   "TARGET_ARM"
7722   "@
7723    mov%D5\\t%0, %2%S4
7724    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7725    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7726   [(set_attr "conds" "use")
7727    (set_attr "shift" "2")
7728    (set_attr "length" "4,8,8")]
7731 (define_insn "*ifcompare_shift_shift"
7732   [(set (match_operand:SI 0 "s_register_operand" "=r")
7733         (if_then_else:SI
7734          (match_operator 7 "arm_comparison_operator"
7735           [(match_operand:SI 5 "s_register_operand" "r")
7736            (match_operand:SI 6 "arm_add_operand" "rIL")])
7737          (match_operator:SI 8 "shift_operator"
7738           [(match_operand:SI 1 "s_register_operand" "r")
7739            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7740          (match_operator:SI 9 "shift_operator"
7741           [(match_operand:SI 3 "s_register_operand" "r")
7742            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7743    (clobber (reg:CC CC_REGNUM))]
7744   "TARGET_ARM"
7745   "#"
7746   [(set_attr "conds" "clob")
7747    (set_attr "length" "12")]
7750 (define_insn "*if_shift_shift"
7751   [(set (match_operand:SI 0 "s_register_operand" "=r")
7752         (if_then_else:SI
7753          (match_operator 5 "arm_comparison_operator"
7754           [(match_operand 8 "cc_register" "") (const_int 0)])
7755          (match_operator:SI 6 "shift_operator"
7756           [(match_operand:SI 1 "s_register_operand" "r")
7757            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7758          (match_operator:SI 7 "shift_operator"
7759           [(match_operand:SI 3 "s_register_operand" "r")
7760            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7761   "TARGET_ARM"
7762   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7763   [(set_attr "conds" "use")
7764    (set_attr "shift" "1")
7765    (set_attr "length" "8")]
7768 (define_insn "*ifcompare_not_arith"
7769   [(set (match_operand:SI 0 "s_register_operand" "=r")
7770         (if_then_else:SI
7771          (match_operator 6 "arm_comparison_operator"
7772           [(match_operand:SI 4 "s_register_operand" "r")
7773            (match_operand:SI 5 "arm_add_operand" "rIL")])
7774          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7775          (match_operator:SI 7 "shiftable_operator"
7776           [(match_operand:SI 2 "s_register_operand" "r")
7777            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7778    (clobber (reg:CC CC_REGNUM))]
7779   "TARGET_ARM"
7780   "#"
7781   [(set_attr "conds" "clob")
7782    (set_attr "length" "12")]
7785 (define_insn "*if_not_arith"
7786   [(set (match_operand:SI 0 "s_register_operand" "=r")
7787         (if_then_else:SI
7788          (match_operator 5 "arm_comparison_operator"
7789           [(match_operand 4 "cc_register" "") (const_int 0)])
7790          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7791          (match_operator:SI 6 "shiftable_operator"
7792           [(match_operand:SI 2 "s_register_operand" "r")
7793            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7794   "TARGET_ARM"
7795   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7796   [(set_attr "conds" "use")
7797    (set_attr "length" "8")]
7800 (define_insn "*ifcompare_arith_not"
7801   [(set (match_operand:SI 0 "s_register_operand" "=r")
7802         (if_then_else:SI
7803          (match_operator 6 "arm_comparison_operator"
7804           [(match_operand:SI 4 "s_register_operand" "r")
7805            (match_operand:SI 5 "arm_add_operand" "rIL")])
7806          (match_operator:SI 7 "shiftable_operator"
7807           [(match_operand:SI 2 "s_register_operand" "r")
7808            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7809          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7810    (clobber (reg:CC CC_REGNUM))]
7811   "TARGET_ARM"
7812   "#"
7813   [(set_attr "conds" "clob")
7814    (set_attr "length" "12")]
7817 (define_insn "*if_arith_not"
7818   [(set (match_operand:SI 0 "s_register_operand" "=r")
7819         (if_then_else:SI
7820          (match_operator 5 "arm_comparison_operator"
7821           [(match_operand 4 "cc_register" "") (const_int 0)])
7822          (match_operator:SI 6 "shiftable_operator"
7823           [(match_operand:SI 2 "s_register_operand" "r")
7824            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7825          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7826   "TARGET_ARM"
7827   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7828   [(set_attr "conds" "use")
7829    (set_attr "length" "8")]
7832 (define_insn "*ifcompare_neg_move"
7833   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7834         (if_then_else:SI
7835          (match_operator 5 "arm_comparison_operator"
7836           [(match_operand:SI 3 "s_register_operand" "r,r")
7837            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7838          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7839          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7840    (clobber (reg:CC CC_REGNUM))]
7841   "TARGET_ARM"
7842   "#"
7843   [(set_attr "conds" "clob")
7844    (set_attr "length" "8,12")]
7847 (define_insn "*if_neg_move"
7848   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7849         (if_then_else:SI
7850          (match_operator 4 "arm_comparison_operator"
7851           [(match_operand 3 "cc_register" "") (const_int 0)])
7852          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7853          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7854   "TARGET_ARM"
7855   "@
7856    rsb%d4\\t%0, %2, #0
7857    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7858    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7859   [(set_attr "conds" "use")
7860    (set_attr "length" "4,8,8")]
7863 (define_insn "*ifcompare_move_neg"
7864   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7865         (if_then_else:SI
7866          (match_operator 5 "arm_comparison_operator"
7867           [(match_operand:SI 3 "s_register_operand" "r,r")
7868            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7869          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7870          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7871    (clobber (reg:CC CC_REGNUM))]
7872   "TARGET_ARM"
7873   "#"
7874   [(set_attr "conds" "clob")
7875    (set_attr "length" "8,12")]
7878 (define_insn "*if_move_neg"
7879   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7880         (if_then_else:SI
7881          (match_operator 4 "arm_comparison_operator"
7882           [(match_operand 3 "cc_register" "") (const_int 0)])
7883          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7884          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7885   "TARGET_ARM"
7886   "@
7887    rsb%D4\\t%0, %2, #0
7888    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7889    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7890   [(set_attr "conds" "use")
7891    (set_attr "length" "4,8,8")]
7894 (define_insn "*arith_adjacentmem"
7895   [(set (match_operand:SI 0 "s_register_operand" "=r")
7896         (match_operator:SI 1 "shiftable_operator"
7897          [(match_operand:SI 2 "memory_operand" "m")
7898           (match_operand:SI 3 "memory_operand" "m")]))
7899    (clobber (match_scratch:SI 4 "=r"))]
7900   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7901   "*
7902   {
7903     rtx ldm[3];
7904     rtx arith[4];
7905     int val1 = 0, val2 = 0;
7907     if (REGNO (operands[0]) > REGNO (operands[4]))
7908       {
7909         ldm[1] = operands[4];
7910         ldm[2] = operands[0];
7911       }
7912     else
7913       {
7914         ldm[1] = operands[0];
7915         ldm[2] = operands[4];
7916       }
7917     if (GET_CODE (XEXP (operands[2], 0)) != REG)
7918       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7919     if (GET_CODE (XEXP (operands[3], 0)) != REG)
7920       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7921     arith[0] = operands[0];
7922     arith[3] = operands[1];
7923     if (val1 < val2)
7924       {
7925         arith[1] = ldm[1];
7926         arith[2] = ldm[2];
7927       }
7928     else
7929       {
7930         arith[1] = ldm[2];
7931         arith[2] = ldm[1];
7932       }
7933    if (val1 && val2)
7934       {
7935         rtx ops[3];
7936         ldm[0] = ops[0] = operands[4];
7937         ops[1] = XEXP (XEXP (operands[2], 0), 0);
7938         ops[2] = XEXP (XEXP (operands[2], 0), 1);
7939         output_add_immediate (ops);
7940         if (val1 < val2)
7941           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7942         else
7943           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7944       }
7945     else if (val1)
7946       {
7947         ldm[0] = XEXP (operands[3], 0);
7948         if (val1 < val2)
7949           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7950         else
7951           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7952       }
7953     else
7954       {
7955         ldm[0] = XEXP (operands[2], 0);
7956         if (val1 < val2)
7957           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7958         else
7959           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7960       }
7961     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7962     return \"\";
7963   }"
7964   [(set_attr "length" "12")
7965    (set_attr "predicable" "yes")
7966    (set_attr "type" "load")]
7969 ;; the arm can support extended pre-inc instructions
7971 ;; In all these cases, we use operands 0 and 1 for the register being
7972 ;; incremented because those are the operands that local-alloc will
7973 ;; tie and these are the pair most likely to be tieable (and the ones
7974 ;; that will benefit the most).
7976 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7977 ;; elimination will cause too many headaches.
7979 (define_insn "*strqi_preinc"
7980   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7981                          (match_operand:SI 2 "index_operand" "rJ")))
7982         (match_operand:QI 3 "s_register_operand" "r"))
7983    (set (match_operand:SI 0 "s_register_operand" "=r")
7984         (plus:SI (match_dup 1) (match_dup 2)))]
7985   "TARGET_ARM
7986    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7987    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7988    && (GET_CODE (operands[2]) != REG
7989        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7990   "str%?b\\t%3, [%0, %2]!"
7991   [(set_attr "type" "store1")
7992    (set_attr "predicable" "yes")]
7995 (define_insn "*strqi_predec"
7996   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7997                           (match_operand:SI 2 "s_register_operand" "r")))
7998         (match_operand:QI 3 "s_register_operand" "r"))
7999    (set (match_operand:SI 0 "s_register_operand" "=r")
8000         (minus:SI (match_dup 1) (match_dup 2)))]
8001   "TARGET_ARM
8002    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8003    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8004    && (GET_CODE (operands[2]) != REG
8005        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8006   "str%?b\\t%3, [%0, -%2]!"
8007   [(set_attr "type" "store1")
8008    (set_attr "predicable" "yes")]
8011 (define_insn "*loadqi_preinc"
8012   [(set (match_operand:QI 3 "s_register_operand" "=r")
8013         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8014                          (match_operand:SI 2 "index_operand" "rJ"))))
8015    (set (match_operand:SI 0 "s_register_operand" "=r")
8016         (plus:SI (match_dup 1) (match_dup 2)))]
8017   "TARGET_ARM
8018    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8019    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8020    && (GET_CODE (operands[2]) != REG
8021        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8022   "ldr%?b\\t%3, [%0, %2]!"
8023   [(set_attr "type" "load")
8024    (set_attr "predicable" "yes")]
8027 (define_insn "*loadqi_predec"
8028   [(set (match_operand:QI 3 "s_register_operand" "=r")
8029         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8030                           (match_operand:SI 2 "s_register_operand" "r"))))
8031    (set (match_operand:SI 0 "s_register_operand" "=r")
8032         (minus:SI (match_dup 1) (match_dup 2)))]
8033   "TARGET_ARM
8034    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8035    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8036    && (GET_CODE (operands[2]) != REG
8037        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8038   "ldr%?b\\t%3, [%0, -%2]!"
8039   [(set_attr "type" "load")
8040    (set_attr "predicable" "yes")]
8043 (define_insn "*loadqisi_preinc"
8044   [(set (match_operand:SI 3 "s_register_operand" "=r")
8045         (zero_extend:SI
8046          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8047                           (match_operand:SI 2 "index_operand" "rJ")))))
8048    (set (match_operand:SI 0 "s_register_operand" "=r")
8049         (plus:SI (match_dup 1) (match_dup 2)))]
8050   "TARGET_ARM
8051    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8052    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8053    && (GET_CODE (operands[2]) != REG
8054        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8055   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8056   [(set_attr "type" "load")
8057    (set_attr "predicable" "yes")]
8060 (define_insn "*loadqisi_predec"
8061   [(set (match_operand:SI 3 "s_register_operand" "=r")
8062         (zero_extend:SI
8063          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8064                            (match_operand:SI 2 "s_register_operand" "r")))))
8065    (set (match_operand:SI 0 "s_register_operand" "=r")
8066         (minus:SI (match_dup 1) (match_dup 2)))]
8067   "TARGET_ARM
8068    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8069    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8070    && (GET_CODE (operands[2]) != REG
8071        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8072   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8073   [(set_attr "type" "load")
8074    (set_attr "predicable" "yes")]
8077 (define_insn "*strsi_preinc"
8078   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8079                          (match_operand:SI 2 "index_operand" "rJ")))
8080         (match_operand:SI 3 "s_register_operand" "r"))
8081    (set (match_operand:SI 0 "s_register_operand" "=r")
8082         (plus:SI (match_dup 1) (match_dup 2)))]
8083   "TARGET_ARM
8084    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8085    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8086    && (GET_CODE (operands[2]) != REG
8087        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8088   "str%?\\t%3, [%0, %2]!"
8089   [(set_attr "type" "store1")
8090    (set_attr "predicable" "yes")]
8093 (define_insn "*strsi_predec"
8094   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8095                           (match_operand:SI 2 "s_register_operand" "r")))
8096         (match_operand:SI 3 "s_register_operand" "r"))
8097    (set (match_operand:SI 0 "s_register_operand" "=r")
8098         (minus:SI (match_dup 1) (match_dup 2)))]
8099   "TARGET_ARM
8100    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8101    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8102    && (GET_CODE (operands[2]) != REG
8103        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8104   "str%?\\t%3, [%0, -%2]!"
8105   [(set_attr "type" "store1")
8106    (set_attr "predicable" "yes")]
8109 (define_insn "*loadsi_preinc"
8110   [(set (match_operand:SI 3 "s_register_operand" "=r")
8111         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8112                          (match_operand:SI 2 "index_operand" "rJ"))))
8113    (set (match_operand:SI 0 "s_register_operand" "=r")
8114         (plus:SI (match_dup 1) (match_dup 2)))]
8115   "TARGET_ARM
8116    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8117    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8118    && (GET_CODE (operands[2]) != REG
8119        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8120   "ldr%?\\t%3, [%0, %2]!"
8121   [(set_attr "type" "load")
8122    (set_attr "predicable" "yes")]
8125 (define_insn "*loadsi_predec"
8126   [(set (match_operand:SI 3 "s_register_operand" "=r")
8127         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8128                           (match_operand:SI 2 "s_register_operand" "r"))))
8129    (set (match_operand:SI 0 "s_register_operand" "=r")
8130         (minus:SI (match_dup 1) (match_dup 2)))]
8131   "TARGET_ARM
8132    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8133    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8134    && (GET_CODE (operands[2]) != REG
8135        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8136   "ldr%?\\t%3, [%0, -%2]!"
8137   [(set_attr "type" "load")
8138    (set_attr "predicable" "yes")]
8141 (define_insn "*loadhi_preinc"
8142   [(set (match_operand:HI 3 "s_register_operand" "=r")
8143         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8144                          (match_operand:SI 2 "index_operand" "rJ"))))
8145    (set (match_operand:SI 0 "s_register_operand" "=r")
8146         (plus:SI (match_dup 1) (match_dup 2)))]
8147   "TARGET_ARM
8148    && !BYTES_BIG_ENDIAN
8149    && !TARGET_MMU_TRAPS
8150    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8151    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8152    && (GET_CODE (operands[2]) != REG
8153        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8154   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8155   [(set_attr "type" "load")
8156    (set_attr "predicable" "yes")]
8159 (define_insn "*loadhi_predec"
8160   [(set (match_operand:HI 3 "s_register_operand" "=r")
8161         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8162                           (match_operand:SI 2 "s_register_operand" "r"))))
8163    (set (match_operand:SI 0 "s_register_operand" "=r")
8164         (minus:SI (match_dup 1) (match_dup 2)))]
8165   "TARGET_ARM
8166    && !BYTES_BIG_ENDIAN
8167    && !TARGET_MMU_TRAPS
8168    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8169    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8170    && (GET_CODE (operands[2]) != REG
8171        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8172   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8173   [(set_attr "type" "load")
8174    (set_attr "predicable" "yes")]
8177 (define_insn "*strqi_shiftpreinc"
8178   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8179                           [(match_operand:SI 3 "s_register_operand" "r")
8180                            (match_operand:SI 4 "const_shift_operand" "n")])
8181                          (match_operand:SI 1 "s_register_operand" "0")))
8182         (match_operand:QI 5 "s_register_operand" "r"))
8183    (set (match_operand:SI 0 "s_register_operand" "=r")
8184         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8185                  (match_dup 1)))]
8186   "TARGET_ARM
8187    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8188    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8189    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8190   "str%?b\\t%5, [%0, %3%S2]!"
8191   [(set_attr "type" "store1")
8192    (set_attr "predicable" "yes")]
8195 (define_insn "*strqi_shiftpredec"
8196   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8197                           (match_operator:SI 2 "shift_operator"
8198                            [(match_operand:SI 3 "s_register_operand" "r")
8199                             (match_operand:SI 4 "const_shift_operand" "n")])))
8200         (match_operand:QI 5 "s_register_operand" "r"))
8201    (set (match_operand:SI 0 "s_register_operand" "=r")
8202         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8203                                                  (match_dup 4)])))]
8204   "TARGET_ARM
8205    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8206    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8207    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8208   "str%?b\\t%5, [%0, -%3%S2]!"
8209   [(set_attr "type" "store1")
8210    (set_attr "predicable" "yes")]
8213 (define_insn "*loadqi_shiftpreinc"
8214   [(set (match_operand:QI 5 "s_register_operand" "=r")
8215         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8216                           [(match_operand:SI 3 "s_register_operand" "r")
8217                            (match_operand:SI 4 "const_shift_operand" "n")])
8218                          (match_operand:SI 1 "s_register_operand" "0"))))
8219    (set (match_operand:SI 0 "s_register_operand" "=r")
8220         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8221                  (match_dup 1)))]
8222   "TARGET_ARM
8223    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8224    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8225    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8226   "ldr%?b\\t%5, [%0, %3%S2]!"
8227   [(set_attr "type" "load")
8228    (set_attr "predicable" "yes")]
8231 (define_insn "*loadqi_shiftpredec"
8232   [(set (match_operand:QI 5 "s_register_operand" "=r")
8233         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8234                           (match_operator:SI 2 "shift_operator"
8235                            [(match_operand:SI 3 "s_register_operand" "r")
8236                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8237    (set (match_operand:SI 0 "s_register_operand" "=r")
8238         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8239                                                  (match_dup 4)])))]
8240   "TARGET_ARM
8241    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8242    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8243    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8244   "ldr%?b\\t%5, [%0, -%3%S2]!"
8245   [(set_attr "type" "load")
8246    (set_attr "predicable" "yes")]
8249 (define_insn "*strsi_shiftpreinc"
8250   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8251                           [(match_operand:SI 3 "s_register_operand" "r")
8252                            (match_operand:SI 4 "const_shift_operand" "n")])
8253                          (match_operand:SI 1 "s_register_operand" "0")))
8254         (match_operand:SI 5 "s_register_operand" "r"))
8255    (set (match_operand:SI 0 "s_register_operand" "=r")
8256         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8257                  (match_dup 1)))]
8258   "TARGET_ARM
8259    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8260    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8261    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8262   "str%?\\t%5, [%0, %3%S2]!"
8263   [(set_attr "type" "store1")
8264    (set_attr "predicable" "yes")]
8267 (define_insn "*strsi_shiftpredec"
8268   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8269                           (match_operator:SI 2 "shift_operator"
8270                            [(match_operand:SI 3 "s_register_operand" "r")
8271                             (match_operand:SI 4 "const_shift_operand" "n")])))
8272         (match_operand:SI 5 "s_register_operand" "r"))
8273    (set (match_operand:SI 0 "s_register_operand" "=r")
8274         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8275                                                  (match_dup 4)])))]
8276   "TARGET_ARM
8277    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8278    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8279    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8280   "str%?\\t%5, [%0, -%3%S2]!"
8281   [(set_attr "type" "store1")
8282    (set_attr "predicable" "yes")]
8285 (define_insn "*loadsi_shiftpreinc"
8286   [(set (match_operand:SI 5 "s_register_operand" "=r")
8287         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8288                           [(match_operand:SI 3 "s_register_operand" "r")
8289                            (match_operand:SI 4 "const_shift_operand" "n")])
8290                          (match_operand:SI 1 "s_register_operand" "0"))))
8291    (set (match_operand:SI 0 "s_register_operand" "=r")
8292         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8293                  (match_dup 1)))]
8294   "TARGET_ARM
8295    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8296    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8297    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8298   "ldr%?\\t%5, [%0, %3%S2]!"
8299   [(set_attr "type" "load")
8300    (set_attr "predicable" "yes")]
8303 (define_insn "*loadsi_shiftpredec"
8304   [(set (match_operand:SI 5 "s_register_operand" "=r")
8305         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8306                           (match_operator:SI 2 "shift_operator"
8307                            [(match_operand:SI 3 "s_register_operand" "r")
8308                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8309    (set (match_operand:SI 0 "s_register_operand" "=r")
8310         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8311                                                  (match_dup 4)])))]
8312   "TARGET_ARM
8313    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8314    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8315    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8316   "ldr%?\\t%5, [%0, -%3%S2]!"
8317   [(set_attr "type" "load")
8318    (set_attr "predicable" "yes")])
8320 (define_insn "*loadhi_shiftpreinc"
8321   [(set (match_operand:HI 5 "s_register_operand" "=r")
8322         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8323                           [(match_operand:SI 3 "s_register_operand" "r")
8324                            (match_operand:SI 4 "const_shift_operand" "n")])
8325                          (match_operand:SI 1 "s_register_operand" "0"))))
8326    (set (match_operand:SI 0 "s_register_operand" "=r")
8327         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8328                  (match_dup 1)))]
8329   "TARGET_ARM
8330    && !BYTES_BIG_ENDIAN
8331    && !TARGET_MMU_TRAPS
8332    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8333    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8334    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8335   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8336   [(set_attr "type" "load")
8337    (set_attr "predicable" "yes")]
8340 (define_insn "*loadhi_shiftpredec"
8341   [(set (match_operand:HI 5 "s_register_operand" "=r")
8342         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8343                           (match_operator:SI 2 "shift_operator"
8344                            [(match_operand:SI 3 "s_register_operand" "r")
8345                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8346    (set (match_operand:SI 0 "s_register_operand" "=r")
8347         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8348                                                  (match_dup 4)])))]
8349   "TARGET_ARM
8350    && !BYTES_BIG_ENDIAN
8351    && !TARGET_MMU_TRAPS
8352    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8353    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8354    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8355   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8356   [(set_attr "type" "load")
8357    (set_attr "predicable" "yes")]
8360 ; It can also support extended post-inc expressions, but combine doesn't
8361 ; try these....
8362 ; It doesn't seem worth adding peepholes for anything but the most common
8363 ; cases since, unlike combine, the increment must immediately follow the load
8364 ; for this pattern to match.
8365 ; We must watch to see that the source/destination register isn't also the
8366 ; same as the base address register, and that if the index is a register,
8367 ; that it is not the same as the base address register.  In such cases the
8368 ; instruction that we would generate would have UNPREDICTABLE behaviour so 
8369 ; we cannot use it.
8371 (define_peephole
8372   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8373         (match_operand:QI 2 "s_register_operand" "r"))
8374    (set (match_dup 0)
8375         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8376   "TARGET_ARM
8377    && (REGNO (operands[2]) != REGNO (operands[0]))
8378    && (GET_CODE (operands[1]) != REG
8379        || (REGNO (operands[1]) != REGNO (operands[0])))"
8380   "str%?b\\t%2, [%0], %1"
8383 (define_peephole
8384   [(set (match_operand:QI 0 "s_register_operand" "=r")
8385         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8386    (set (match_dup 1)
8387         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8388   "TARGET_ARM
8389    && REGNO (operands[0]) != REGNO(operands[1])
8390    && (GET_CODE (operands[2]) != REG
8391        || REGNO(operands[0]) != REGNO (operands[2]))"
8392   "ldr%?b\\t%0, [%1], %2"
8395 (define_peephole
8396   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8397         (match_operand:SI 2 "s_register_operand" "r"))
8398    (set (match_dup 0)
8399         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8400   "TARGET_ARM
8401    && (REGNO (operands[2]) != REGNO (operands[0]))
8402    && (GET_CODE (operands[1]) != REG
8403        || (REGNO (operands[1]) != REGNO (operands[0])))"
8404   "str%?\\t%2, [%0], %1"
8407 (define_peephole
8408   [(set (match_operand:HI 0 "s_register_operand" "=r")
8409         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8410    (set (match_dup 1)
8411         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8412   "TARGET_ARM
8413    && !BYTES_BIG_ENDIAN
8414    && !TARGET_MMU_TRAPS
8415    && REGNO (operands[0]) != REGNO(operands[1])
8416    && (GET_CODE (operands[2]) != REG
8417        || REGNO(operands[0]) != REGNO (operands[2]))"
8418   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8421 (define_peephole
8422   [(set (match_operand:SI 0 "s_register_operand" "=r")
8423         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8424    (set (match_dup 1)
8425         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8426   "TARGET_ARM
8427    && REGNO (operands[0]) != REGNO(operands[1])
8428    && (GET_CODE (operands[2]) != REG
8429        || REGNO(operands[0]) != REGNO (operands[2]))"
8430   "ldr%?\\t%0, [%1], %2"
8433 (define_peephole
8434   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8435                          (match_operand:SI 1 "index_operand" "rJ")))
8436         (match_operand:QI 2 "s_register_operand" "r"))
8437    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8438   "TARGET_ARM
8439    && (REGNO (operands[2]) != REGNO (operands[0]))
8440    && (GET_CODE (operands[1]) != REG
8441        || (REGNO (operands[1]) != REGNO (operands[0])))"
8442   "str%?b\\t%2, [%0, %1]!"
8445 (define_peephole
8446   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8447                           [(match_operand:SI 0 "s_register_operand" "r")
8448                            (match_operand:SI 1 "const_int_operand" "n")])
8449                          (match_operand:SI 2 "s_register_operand" "+r")))
8450         (match_operand:QI 3 "s_register_operand" "r"))
8451    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8452                                (match_dup 2)))]
8453   "TARGET_ARM
8454    && (REGNO (operands[3]) != REGNO (operands[2]))
8455    && (REGNO (operands[0]) != REGNO (operands[2]))"
8456   "str%?b\\t%3, [%2, %0%S4]!"
8459 ; This pattern is never tried by combine, so do it as a peephole
8461 (define_peephole2
8462   [(set (match_operand:SI 0 "s_register_operand" "")
8463         (match_operand:SI 1 "s_register_operand" ""))
8464    (set (reg:CC CC_REGNUM)
8465         (compare:CC (match_dup 1) (const_int 0)))]
8466   "TARGET_ARM"
8467   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8468               (set (match_dup 0) (match_dup 1))])]
8469   ""
8472 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8473 ; reversed, check that the memory references aren't volatile.
8475 (define_peephole
8476   [(set (match_operand:SI 0 "s_register_operand" "=r")
8477         (match_operand:SI 4 "memory_operand" "m"))
8478    (set (match_operand:SI 1 "s_register_operand" "=r")
8479         (match_operand:SI 5 "memory_operand" "m"))
8480    (set (match_operand:SI 2 "s_register_operand" "=r")
8481         (match_operand:SI 6 "memory_operand" "m"))
8482    (set (match_operand:SI 3 "s_register_operand" "=r")
8483         (match_operand:SI 7 "memory_operand" "m"))]
8484   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8485   "*
8486   return emit_ldm_seq (operands, 4);
8487   "
8490 (define_peephole
8491   [(set (match_operand:SI 0 "s_register_operand" "=r")
8492         (match_operand:SI 3 "memory_operand" "m"))
8493    (set (match_operand:SI 1 "s_register_operand" "=r")
8494         (match_operand:SI 4 "memory_operand" "m"))
8495    (set (match_operand:SI 2 "s_register_operand" "=r")
8496         (match_operand:SI 5 "memory_operand" "m"))]
8497   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8498   "*
8499   return emit_ldm_seq (operands, 3);
8500   "
8503 (define_peephole
8504   [(set (match_operand:SI 0 "s_register_operand" "=r")
8505         (match_operand:SI 2 "memory_operand" "m"))
8506    (set (match_operand:SI 1 "s_register_operand" "=r")
8507         (match_operand:SI 3 "memory_operand" "m"))]
8508   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8509   "*
8510   return emit_ldm_seq (operands, 2);
8511   "
8514 (define_peephole
8515   [(set (match_operand:SI 4 "memory_operand" "=m")
8516         (match_operand:SI 0 "s_register_operand" "r"))
8517    (set (match_operand:SI 5 "memory_operand" "=m")
8518         (match_operand:SI 1 "s_register_operand" "r"))
8519    (set (match_operand:SI 6 "memory_operand" "=m")
8520         (match_operand:SI 2 "s_register_operand" "r"))
8521    (set (match_operand:SI 7 "memory_operand" "=m")
8522         (match_operand:SI 3 "s_register_operand" "r"))]
8523   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8524   "*
8525   return emit_stm_seq (operands, 4);
8526   "
8529 (define_peephole
8530   [(set (match_operand:SI 3 "memory_operand" "=m")
8531         (match_operand:SI 0 "s_register_operand" "r"))
8532    (set (match_operand:SI 4 "memory_operand" "=m")
8533         (match_operand:SI 1 "s_register_operand" "r"))
8534    (set (match_operand:SI 5 "memory_operand" "=m")
8535         (match_operand:SI 2 "s_register_operand" "r"))]
8536   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8537   "*
8538   return emit_stm_seq (operands, 3);
8539   "
8542 (define_peephole
8543   [(set (match_operand:SI 2 "memory_operand" "=m")
8544         (match_operand:SI 0 "s_register_operand" "r"))
8545    (set (match_operand:SI 3 "memory_operand" "=m")
8546         (match_operand:SI 1 "s_register_operand" "r"))]
8547   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8548   "*
8549   return emit_stm_seq (operands, 2);
8550   "
8553 (define_split
8554   [(set (match_operand:SI 0 "s_register_operand" "")
8555         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8556                        (const_int 0))
8557                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8558                          [(match_operand:SI 3 "s_register_operand" "")
8559                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
8560    (clobber (match_operand:SI 5 "s_register_operand" ""))]
8561   "TARGET_ARM"
8562   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8563    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8564                               (match_dup 5)))]
8565   ""
8568 ;; This split can be used because CC_Z mode implies that the following
8569 ;; branch will be an equality, or an unsigned inequality, so the sign
8570 ;; extension is not needed.
8572 (define_split
8573   [(set (reg:CC_Z CC_REGNUM)
8574         (compare:CC_Z
8575          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8576                     (const_int 24))
8577          (match_operand 1 "const_int_operand" "")))
8578    (clobber (match_scratch:SI 2 ""))]
8579   "TARGET_ARM
8580    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8581        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8582   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8583    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8584   "
8585   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8586   "
8589 (define_expand "prologue"
8590   [(clobber (const_int 0))]
8591   "TARGET_EITHER"
8592   "if (TARGET_ARM)
8593      arm_expand_prologue ();
8594    else
8595      thumb_expand_prologue ();
8596   DONE;
8597   "
8600 (define_expand "epilogue"
8601   [(unspec_volatile [(return)] 1)]
8602   "TARGET_EITHER"
8603   "
8604   if (TARGET_THUMB)
8605     thumb_expand_epilogue ();
8606   else if (USE_RETURN_INSN (FALSE))
8607     {
8608       emit_jump_insn (gen_return ());
8609       DONE;
8610     }
8611   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8612         gen_rtvec (1,
8613                 gen_rtx_RETURN (VOIDmode)),
8614         1));
8615   DONE;
8616   "
8619 (define_insn "sibcall_epilogue"
8620   [(unspec_volatile [(const_int 0)] 1)]
8621   "TARGET_ARM"
8622   "*
8623   output_asm_insn (\"%@ Sibcall epilogue\", operands);
8624   if (USE_RETURN_INSN (FALSE))
8625     return output_return_instruction (NULL, FALSE, FALSE);
8626   return arm_output_epilogue (FALSE);
8627   "
8628 ;; Length is absolute worst case
8629   [(set_attr "length" "44")
8630    (set_attr "type" "block")]
8633 (define_insn "*epilogue_insns"
8634   [(unspec_volatile [(return)] 1)]
8635   "TARGET_EITHER"
8636   "*
8637   if (TARGET_ARM)
8638     return arm_output_epilogue (TRUE);
8639   else /* TARGET_THUMB */
8640     return thumb_unexpanded_epilogue ();
8641   "
8642   ; Length is absolute worst case
8643   [(set_attr "length" "44")
8644    (set_attr "type" "block")]
8647 (define_expand "eh_epilogue"
8648   [(use (match_operand:SI 0 "register_operand" "r"))
8649    (use (match_operand:SI 1 "register_operand" "r"))
8650    (use (match_operand:SI 2 "register_operand" "r"))]
8651   "TARGET_EITHER"
8652   "
8653   {
8654     cfun->machine->eh_epilogue_sp_ofs = operands[1];
8655     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8656       {
8657         rtx ra = gen_rtx_REG (Pmode, 2);
8659         emit_move_insn (ra, operands[2]);
8660         operands[2] = ra;
8661       }
8662   }"
8665 ;; This split is only used during output to reduce the number of patterns
8666 ;; that need assembler instructions adding to them.  We allowed the setting
8667 ;; of the conditions to be implicit during rtl generation so that
8668 ;; the conditional compare patterns would work.  However this conflicts to
8669 ;; some extent with the conditional data operations, so we have to split them
8670 ;; up again here.
8672 (define_split
8673   [(set (match_operand:SI 0 "s_register_operand" "")
8674         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8675                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8676                          (match_dup 0)
8677                          (match_operand 4 "" "")))
8678    (clobber (reg:CC CC_REGNUM))]
8679   "TARGET_ARM && reload_completed"
8680   [(set (match_dup 5) (match_dup 6))
8681    (cond_exec (match_dup 7)
8682               (set (match_dup 0) (match_dup 4)))]
8683   "
8684   {
8685     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8686                                              operands[2], operands[3]);
8687     enum rtx_code rc = GET_CODE (operands[1]);
8689     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8690     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8691     if (mode == CCFPmode || mode == CCFPEmode)
8692       rc = reverse_condition_maybe_unordered (rc);
8693     else
8694       rc = reverse_condition (rc);
8696     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8697   }"
8700 (define_split
8701   [(set (match_operand:SI 0 "s_register_operand" "")
8702         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8703                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8704                          (match_operand 4 "" "")
8705                          (match_dup 0)))
8706    (clobber (reg:CC CC_REGNUM))]
8707   "TARGET_ARM && reload_completed"
8708   [(set (match_dup 5) (match_dup 6))
8709    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8710               (set (match_dup 0) (match_dup 4)))]
8711   "
8712   {
8713     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8714                                              operands[2], operands[3]);
8716     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8717     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8718   }"
8721 (define_split
8722   [(set (match_operand:SI 0 "s_register_operand" "")
8723         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8724                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8725                          (match_operand 4 "" "")
8726                          (match_operand 5 "" "")))
8727    (clobber (reg:CC CC_REGNUM))]
8728   "TARGET_ARM && reload_completed"
8729   [(set (match_dup 6) (match_dup 7))
8730    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8731               (set (match_dup 0) (match_dup 4)))
8732    (cond_exec (match_dup 8)
8733               (set (match_dup 0) (match_dup 5)))]
8734   "
8735   {
8736     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8737                                              operands[2], operands[3]);
8738     enum rtx_code rc = GET_CODE (operands[1]);
8740     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8741     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8742     if (mode == CCFPmode || mode == CCFPEmode)
8743       rc = reverse_condition_maybe_unordered (rc);
8744     else
8745       rc = reverse_condition (rc);
8747     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8748   }"
8751 (define_split
8752   [(set (match_operand:SI 0 "s_register_operand" "")
8753         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8754                           [(match_operand:SI 2 "s_register_operand" "")
8755                            (match_operand:SI 3 "arm_add_operand" "")])
8756                          (match_operand:SI 4 "arm_rhs_operand" "")
8757                          (not:SI
8758                           (match_operand:SI 5 "s_register_operand" ""))))
8759    (clobber (reg:CC CC_REGNUM))]
8760   "TARGET_ARM && reload_completed"
8761   [(set (match_dup 6) (match_dup 7))
8762    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8763               (set (match_dup 0) (match_dup 4)))
8764    (cond_exec (match_dup 8)
8765               (set (match_dup 0) (not:SI (match_dup 5))))]
8766   "
8767   {
8768     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8769                                              operands[2], operands[3]);
8770     enum rtx_code rc = GET_CODE (operands[1]);
8772     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8773     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8774     if (mode == CCFPmode || mode == CCFPEmode)
8775       rc = reverse_condition_maybe_unordered (rc);
8776     else
8777       rc = reverse_condition (rc);
8779     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8780   }"
8783 (define_insn "*cond_move_not"
8784   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8785         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8786                           [(match_operand 3 "cc_register" "") (const_int 0)])
8787                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8788                          (not:SI
8789                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
8790   "TARGET_ARM"
8791   "@
8792    mvn%D4\\t%0, %2
8793    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8794   [(set_attr "conds" "use")
8795    (set_attr "length" "4,8")]
8798 ;; The next two patterns occur when an AND operation is followed by a
8799 ;; scc insn sequence 
8801 (define_insn "*sign_extract_onebit"
8802   [(set (match_operand:SI 0 "s_register_operand" "=r")
8803         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8804                          (const_int 1)
8805                          (match_operand:SI 2 "const_int_operand" "n")))]
8806   "TARGET_ARM"
8807   "*
8808     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8809     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8810     return \"mvnne\\t%0, #0\";
8811   "
8812   [(set_attr "conds" "clob")
8813    (set_attr "length" "8")]
8816 (define_insn "*not_signextract_onebit"
8817   [(set (match_operand:SI 0 "s_register_operand" "=r")
8818         (not:SI
8819          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8820                           (const_int 1)
8821                           (match_operand:SI 2 "const_int_operand" "n"))))]
8822   "TARGET_ARM"
8823   "*
8824     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8825     output_asm_insn (\"tst\\t%1, %2\", operands);
8826     output_asm_insn (\"mvneq\\t%0, #0\", operands);
8827     return \"movne\\t%0, #0\";
8828   "
8829   [(set_attr "conds" "clob")
8830    (set_attr "length" "12")]
8833 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8834 ;; expressions.  For simplicity, the first register is also in the unspec
8835 ;; part.
8836 (define_insn "*push_multi"
8837   [(match_parallel 2 "multi_register_push"
8838     [(set (match_operand:BLK 0 "memory_operand" "=m")
8839           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
8840   "TARGET_ARM"
8841   "*
8842   {
8843     int num_saves = XVECLEN (operands[2], 0);
8844      
8845     /* For the StrongARM at least it is faster to
8846        use STR to store only a single register.  */
8847     if (num_saves == 1)
8848       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8849     else
8850       {
8851         int i;
8852         char pattern[100];
8854         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8856         for (i = 1; i < num_saves; i++)
8857           {
8858             strcat (pattern, \", %|\");
8859             strcat (pattern,
8860                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8861           }
8863         strcat (pattern, \"}\");
8864         output_asm_insn (pattern, operands);
8865       }
8867     return \"\";
8868   }"
8869   [(set_attr "type" "store4")]
8872 ;; Similarly for the floating point registers
8873 (define_insn "*push_fp_multi"
8874   [(match_parallel 2 "multi_register_push"
8875     [(set (match_operand:BLK 0 "memory_operand" "=m")
8876           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
8877   "TARGET_ARM"
8878   "*
8879   {
8880     char pattern[100];
8882     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8883     output_asm_insn (pattern, operands);
8884     return \"\";
8885   }"
8886   [(set_attr "type" "f_store")]
8889 ;; Special patterns for dealing with the constant pool
8891 (define_insn "align_4"
8892   [(unspec_volatile [(const_int 0)] 2)]
8893   "TARGET_EITHER"
8894   "*
8895   assemble_align (32);
8896   return \"\";
8897   "
8900 (define_insn "consttable_end"
8901   [(unspec_volatile [(const_int 0)] 3)]
8902   "TARGET_EITHER"
8903   "*
8904   making_const_table = FALSE;
8905   return \"\";
8906   "
8909 (define_insn "consttable_1"
8910   [(unspec_volatile [(match_operand 0 "" "")] 4)]
8911   "TARGET_THUMB"
8912   "*
8913   making_const_table = TRUE;
8914   assemble_integer (operands[0], 1, 1);
8915   assemble_zeros (3);
8916   return \"\";
8917   "
8918   [(set_attr "length" "4")]
8921 (define_insn "consttable_2"
8922   [(unspec_volatile [(match_operand 0 "" "")] 5)]
8923   "TARGET_THUMB"
8924   "*
8925   making_const_table = TRUE;
8926   assemble_integer (operands[0], 2, 1);
8927   assemble_zeros (2);
8928   return \"\";
8929   "
8930   [(set_attr "length" "4")]
8933 (define_insn "consttable_4"
8934   [(unspec_volatile [(match_operand 0 "" "")] 6)]
8935   "TARGET_EITHER"
8936   "*
8937   {
8938     making_const_table = TRUE;
8939     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8940       {
8941       case MODE_FLOAT:
8942       {
8943         union real_extract u;
8944         memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
8945         assemble_real (u.d, GET_MODE (operands[0]));
8946         break;
8947       }
8948       default:
8949         assemble_integer (operands[0], 4, 1);
8950         break;
8951       }
8952     return \"\";
8953   }"
8954   [(set_attr "length" "4")]
8957 (define_insn "consttable_8"
8958   [(unspec_volatile [(match_operand 0 "" "")] 7)]
8959   "TARGET_EITHER"
8960   "*
8961   {
8962     making_const_table = TRUE;
8963     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8964       {
8965        case MODE_FLOAT:
8966         {
8967           union real_extract u;
8968           memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
8969           assemble_real (u.d, GET_MODE (operands[0]));
8970           break;
8971         }
8972       default:
8973         assemble_integer (operands[0], 8, 1);
8974         break;
8975       }
8976     return \"\";
8977   }"
8978   [(set_attr "length" "8")]
8981 ;; Miscellaneous Thumb patterns
8983 (define_insn "tablejump"
8984   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8985    (use (label_ref (match_operand 1 "" "")))]
8986   "TARGET_THUMB"
8987   "mov  pc, %0"
8988   [(set_attr "length" "2")]
8991 ;; V5 Instructions,
8993 (define_insn "clz"
8994   [(set (match_operand:SI             0 "s_register_operand" "=r")
8995         (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")] 128))]
8996   "TARGET_ARM"
8997   "clz\\t%0,%1")
8999 ;; XScale instructions.
9001 (define_insn "prefetch"
9002   [(unspec_volatile
9003     [(match_operand:SI 0 "offsettable_memory_operand" "o")] 129)]
9004   "TARGET_ARM"
9005   "pld\\t%0")
9007 ;; General predication pattern
9009 (define_cond_exec
9010   [(match_operator 0 "arm_comparison_operator"
9011     [(match_operand 1 "cc_register" "")
9012      (const_int 0)])]
9013   "TARGET_ARM"
9014   ""