* ChangeLog: Follow spelling conventions.
[official-gcc.git] / gcc / config / arm / arm.md
blob8d58b529d1c48e707e43bcfa8b3550192704d0b6
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;;  2001, 2002  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 ;;---------------------------------------------------------------------------
32 ;; Constants
34 ;; Register numbers
35 (define_constants
36   [(IP_REGNUM       12)         ; Scratch register
37    (SP_REGNUM       13)         ; Stack pointer
38    (LR_REGNUM       14)         ; Return address register
39    (PC_REGNUM       15)         ; Program counter
40    (CC_REGNUM       24)         ; Condition code pseudo register
41    (LAST_ARM_REGNUM 15)
42   ]
45 ;; UNSPEC Usage:
46 ;; Note: sin and cos are no-longer used.
48 (define_constants
49   [(UNSPEC_SIN       0) ; `sin' operation (MODE_FLOAT):
50                         ;   operand 0 is the result,
51                         ;   operand 1 the parameter.
52    (UNPSEC_COS       1) ; `cos' operation (MODE_FLOAT):
53                         ;   operand 0 is the result,
54                         ;   operand 1 the parameter.
55    (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
56                         ;   operand 0 is the first register,
57                         ;   subsequent registers are in parallel (use ...)
58                         ;   expressions.
59    (UNSPEC_PIC_SYM   3) ; A symbol that has been treated properly for pic
60                         ;   usage, that is, we will add the pic_register
61                         ;   value to it before trying to dereference it.
62    (UNSPEC_PRLG_STK  4) ; A special barrier that prevents frame accesses 
63                         ;   being scheduled before the stack adjustment insn.
64    (UNSPEC_CLZ       5) ; `clz' instruction, count leading zeros (SImode):
65                         ;   operand 0 is the result,
66                         ;   operand 1 is the parameter.
67    (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
68                         ; this unspec is used to prevent the deletion of
69                         ; instructions setting registers for EH handling
70                         ; and stack frame generation.  Operand 0 is the
71                         ; register to "use".
72    (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
73   ]
76 ;; UNSPEC_VOLATILE Usage:
78 (define_constants
79   [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
80                         ;   insn in the code.
81    (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
82                         ;   instruction epilogue sequence that isn't expanded
83                         ;   into normal RTL.  Used for both normal and sibcall
84                         ;   epilogues.
85    (VUNSPEC_ALIGN    2) ; `align' insn.  Used at the head of a minipool table 
86                         ;   for inlined constants.
87    (VUNSPEC_POOL_END 3) ; `end-of-table'.  Used to mark the end of a minipool
88                         ;   table.
89    (VUNSPEC_POOL_1   4) ; `pool-entry(1)'.  An entry in the constant pool for
90                         ;   an 8-bit object.
91    (VUNSPEC_POOL_2   5) ; `pool-entry(2)'.  An entry in the constant pool for
92                         ;   a 16-bit object.
93    (VUNSPEC_POOL_4   6) ; `pool-entry(4)'.  An entry in the constant pool for
94                         ;   a 32-bit object.
95    (VUNSPEC_POOL_8   7) ; `pool-entry(8)'.  An entry in the constant pool for
96                         ;   a 64-bit object.
97   ]
100 ;;---------------------------------------------------------------------------
101 ;; Attributes
103 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
104 ; generating ARM code.  This is used to control the length of some insn
105 ; patterns that share the same RTL in both ARM and Thumb code.
106 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
108 ; PROG_MODE attribute is used to determine whether condition codes are
109 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
110 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
111 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
113 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
114 ; scheduling decisions for the load unit and the multiplier.
115 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
117 ;; Operand number of an input operand that is shifted.  Zero if the
118 ;; given instruction does not shift one of its input operands.
119 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
120 (define_attr "shift" "" (const_int 0))
122 ; Floating Point Unit.  If we only have floating point emulation, then there
123 ; is no point in scheduling the floating point insns.  (Well, for best
124 ; performance we should try and group them together).
125 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
127 ; LENGTH of an instruction (in bytes)
128 (define_attr "length" "" (const_int 4))
130 ; POOL_RANGE is how far away from a constant pool entry that this insn
131 ; can be placed.  If the distance is zero, then this insn will never
132 ; reference the pool.
133 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
134 ; before its address.
135 (define_attr "pool_range" "" (const_int 0))
136 (define_attr "neg_pool_range" "" (const_int 0))
138 ; An assembler sequence may clobber the condition codes without us knowing.
139 ; If such an insn references the pool, then we have no way of knowing how,
140 ; so use the most conservative value for pool_range.
141 (define_asm_attributes
142  [(set_attr "conds" "clob")
143   (set_attr "length" "4")
144   (set_attr "pool_range" "250")])
146 ; TYPE attribute is used to detect floating point instructions which, if
147 ; running on a co-processor can run in parallel with other, basic instructions
148 ; If write-buffer scheduling is enabled then it can also be used in the
149 ; scheduling of writes.
151 ; Classification of each insn
152 ; normal        any data instruction that doesn't hit memory or fp regs
153 ; mult          a multiply instruction
154 ; block         blockage insn, this blocks all functional units
155 ; float         a floating point arithmetic operation (subject to expansion)
156 ; fdivx         XFmode floating point division
157 ; fdivd         DFmode floating point division
158 ; fdivs         SFmode floating point division
159 ; fmul          Floating point multiply
160 ; ffmul         Fast floating point multiply
161 ; farith        Floating point arithmetic (4 cycle)
162 ; ffarith       Fast floating point arithmetic (2 cycle)
163 ; float_em      a floating point arithmetic operation that is normally emulated
164 ;               even on a machine with an fpa.
165 ; f_load        a floating point load from memory
166 ; f_store       a floating point store to memory
167 ; f_mem_r       a transfer of a floating point register to a real reg via mem
168 ; r_mem_f       the reverse of f_mem_r
169 ; f_2_r         fast transfer float to arm (no memory needed)
170 ; r_2_f         fast transfer arm to float
171 ; call          a subroutine call
172 ; load          any load from memory
173 ; store1        store 1 word to memory from arm registers
174 ; store2        store 2 words
175 ; store3        store 3 words
176 ; store4        store 4 words
178 (define_attr "type"
179         "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" 
180         (const_string "normal"))
182 ; Load scheduling, set from the arm_ld_sched variable
183 ; initialized by arm_override_options() 
184 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
186 ; condition codes: this one is used by final_prescan_insn to speed up
187 ; conditionalizing instructions.  It saves having to scan the rtl to see if
188 ; it uses or alters the condition codes.
190 ; USE means that the condition codes are used by the insn in the process of
191 ;   outputting code, this means (at present) that we can't use the insn in
192 ;   inlined branches
194 ; SET means that the purpose of the insn is to set the condition codes in a
195 ;   well defined manner.
197 ; CLOB means that the condition codes are altered in an undefined manner, if
198 ;   they are altered at all
200 ; JUMP_CLOB is used when the condition cannot be represented by a single
201 ;   instruction (UNEQ and LTGT).  These cannot be predicated.
203 ; NOCOND means that the condition codes are neither altered nor affect the
204 ;   output of this insn
206 (define_attr "conds" "use,set,clob,jump_clob,nocond"
207         (if_then_else (eq_attr "type" "call")
208          (if_then_else (eq_attr "prog_mode" "prog32")
209           (const_string "clob") (const_string "nocond"))
210          (const_string "nocond")))
212 ; Predicable means that the insn can be conditionally executed based on
213 ; an automatically added predicate (additional patterns are generated by 
214 ; gen...).  We default to 'no' because no Thumb patterns match this rule
215 ; and not all ARM patterns do.
216 (define_attr "predicable" "no,yes" (const_string "no"))
218 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
219 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
220 ; suffer blockages enough to warrent modelling this (and it can adversely
221 ; affect the schedule).
222 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
224 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
225 ; to stall the processor.  Used with model_wbuf above.
226 (define_attr "write_conflict" "no,yes"
227   (if_then_else (eq_attr "type"
228                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
229                 (const_string "yes")
230                 (const_string "no")))
232 ; Classify the insns into those that take one cycle and those that take more
233 ; than one on the main cpu execution unit.
234 (define_attr "core_cycles" "single,multi"
235   (if_then_else (eq_attr "type"
236                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
237                 (const_string "single")
238                 (const_string "multi")))
240 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
241 ;; distant label.  Only applicable to Thumb code.
242 (define_attr "far_jump" "yes,no" (const_string "no"))
244 ;; (define_function_unit {name} {num-units} {n-users} {test}
245 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
247 ;;--------------------------------------------------------------------
248 ;; Floating point unit (FPA)
249 ;;--------------------------------------------------------------------
250 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
251                                      (eq_attr "type" "fdivx")) 71 69)
253 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
254                                      (eq_attr "type" "fdivd")) 59 57)
256 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
257                                      (eq_attr "type" "fdivs")) 31 29)
259 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
260                                      (eq_attr "type" "fmul")) 9 7)
262 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
263                                      (eq_attr "type" "ffmul")) 6 4)
265 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
266                                      (eq_attr "type" "farith")) 4 2)
268 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
269                                      (eq_attr "type" "ffarith")) 2 2)
271 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
272                                      (eq_attr "type" "r_2_f")) 5 3)
274 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
275                                      (eq_attr "type" "f_2_r")) 1 2)
277 ; The fpa10 doesn't really have a memory read unit, but it can start to
278 ; speculatively execute the instruction in the pipeline, provided the data
279 ; is already loaded, so pretend reads have a delay of 2 (and that the
280 ; pipeline is infinite).
282 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
283                                          (eq_attr "type" "f_load")) 3 1)
285 ;;--------------------------------------------------------------------
286 ;; Write buffer
287 ;;--------------------------------------------------------------------
288 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
290 ; The write buffer on some of the arm6 processors is hard to model exactly.
291 ; There is room in the buffer for up to two addresses and up to eight words
292 ; of memory, but the two needn't be split evenly.  When writing the two
293 ; addresses are fully pipelined.  However, a read from memory that is not
294 ; currently in the cache will block until the writes have completed.
295 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
296 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
297 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
298 ; cycle to add as well.
300 (define_function_unit "write_buf" 1 2
301   (and (eq_attr "model_wbuf" "yes")
302        (eq_attr "type" "store1,r_mem_f")) 5 3)
303 (define_function_unit "write_buf" 1 2 
304   (and (eq_attr "model_wbuf" "yes")
305        (eq_attr "type" "store2")) 7 4)
306 (define_function_unit "write_buf" 1 2
307   (and (eq_attr "model_wbuf" "yes")
308        (eq_attr "type" "store3")) 9 5)
309 (define_function_unit "write_buf" 1 2
310   (and (eq_attr "model_wbuf" "yes")
311        (eq_attr "type" "store4")) 11 6)
313 ;;--------------------------------------------------------------------
314 ;; Write blockage unit
315 ;;--------------------------------------------------------------------
316 ; The write_blockage unit models (partially), the fact that reads will stall
317 ; until the write buffer empties.
318 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
319 ; so we don't model them here
320 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
321                                                 (eq_attr "type" "store1")) 5 5
322         [(eq_attr "write_conflict" "yes")])
323 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
324                                                 (eq_attr "type" "store2")) 7 7
325         [(eq_attr "write_conflict" "yes")])
326 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
327                                                 (eq_attr "type" "store3")) 9 9
328         [(eq_attr "write_conflict" "yes")])
329 (define_function_unit "write_blockage" 1 0
330         (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
331         [(eq_attr "write_conflict" "yes")])
332 (define_function_unit "write_blockage" 1 0
333         (and (eq_attr "model_wbuf" "yes")
334              (eq_attr "write_conflict" "yes")) 1 1)
336 ;;--------------------------------------------------------------------
337 ;; Core unit
338 ;;--------------------------------------------------------------------
339 ; Everything must spend at least one cycle in the core unit
340 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
342 (define_function_unit "core" 1 0
343   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
345 (define_function_unit "core" 1 0
346   (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
348 ;; We do not need to conditionalize the define_function_unit immediately
349 ;; above.  This one will be ignored for anything other than xscale
350 ;; compiles and for xscale compiles it provides a larger delay
351 ;; and the scheduler will DTRT.
352 ;; FIXME: this test needs to be revamped to not depend on this feature 
353 ;; of the scheduler.
355 (define_function_unit "core" 1 0
356   (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
357        (eq_attr "is_xscale" "yes"))
358    3 1)
360 (define_function_unit "core" 1 0
361   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
363 (define_function_unit "core" 1 0
364   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
366 (define_function_unit "core" 1 0
367   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
369 (define_function_unit "core" 1 0
370   (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
372 (define_function_unit "core" 1 0
373   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
375 (define_function_unit "core" 1 0
376   (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
378 (define_function_unit "core" 1 0
379   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
380        (eq_attr "type" "mult")) 4 4)
382 (define_function_unit "core" 1 0
383   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
384        (eq_attr "type" "mult")) 3 2)
386 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
388 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
390 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
392 (define_function_unit "core" 1 0
393   (and (eq_attr "core_cycles" "multi")
394        (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
396 ;;---------------------------------------------------------------------------
397 ;; Insn patterns
399 ;; Addition insns.
401 ;; Note: For DImode insns, there is normally no reason why operands should
402 ;; not be in the same register, what we don't want is for something being
403 ;; written to partially overlap something that is an input.
405 (define_expand "adddi3"
406  [(parallel
407    [(set (match_operand:DI           0 "s_register_operand" "")
408           (plus:DI (match_operand:DI 1 "s_register_operand" "")
409                    (match_operand:DI 2 "s_register_operand" "")))
410     (clobber (reg:CC CC_REGNUM))])]
411   "TARGET_EITHER"
412   "
413   if (TARGET_THUMB)
414     {
415       if (GET_CODE (operands[1]) != REG)
416         operands[1] = force_reg (SImode, operands[1]);
417       if (GET_CODE (operands[2]) != REG)
418         operands[2] = force_reg (SImode, operands[2]);
419      }
420   "
423 (define_insn "*thumb_adddi3"
424   [(set (match_operand:DI          0 "register_operand" "=l")
425         (plus:DI (match_operand:DI 1 "register_operand" "%0")
426                  (match_operand:DI 2 "register_operand" "l")))
427    (clobber (reg:CC CC_REGNUM))
428   ]
429   "TARGET_THUMB"
430   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
431   [(set_attr "length" "4")]
434 (define_insn_and_split "*arm_adddi3"
435   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
436         (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
437                  (match_operand:DI 2 "s_register_operand" "r,  0")))
438    (clobber (reg:CC CC_REGNUM))]
439   "TARGET_ARM"
440   "#"
441   "TARGET_ARM && reload_completed"
442   [(parallel [(set (reg:CC_C CC_REGNUM)
443                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
444                                  (match_dup 1)))
445               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
446    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
447                                (plus:SI (match_dup 4) (match_dup 5))))]
448   "
449   {
450     operands[3] = gen_highpart (SImode, operands[0]);
451     operands[0] = gen_lowpart (SImode, operands[0]);
452     operands[4] = gen_highpart (SImode, operands[1]);
453     operands[1] = gen_lowpart (SImode, operands[1]);
454     operands[5] = gen_highpart (SImode, operands[2]);
455     operands[2] = gen_lowpart (SImode, operands[2]);
456   }"
457   [(set_attr "conds" "clob")
458    (set_attr "length" "8")]
461 (define_insn_and_split "*adddi_sesidi_di"
462   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
463         (plus:DI (sign_extend:DI
464                   (match_operand:SI 2 "s_register_operand" "r,r"))
465                  (match_operand:DI 1 "s_register_operand" "r,0")))
466    (clobber (reg:CC CC_REGNUM))]
467   "TARGET_ARM"
468   "#"
469   "TARGET_ARM && reload_completed"
470   [(parallel [(set (reg:CC_C CC_REGNUM)
471                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
472                                  (match_dup 1)))
473               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
474    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
475                                (plus:SI (ashiftrt:SI (match_dup 2)
476                                                      (const_int 31))
477                                         (match_dup 4))))]
478   "
479   {
480     operands[3] = gen_highpart (SImode, operands[0]);
481     operands[0] = gen_lowpart (SImode, operands[0]);
482     operands[4] = gen_highpart (SImode, operands[1]);
483     operands[1] = gen_lowpart (SImode, operands[1]);
484     operands[2] = gen_lowpart (SImode, operands[2]);
485   }"
486   [(set_attr "conds" "clob")
487    (set_attr "length" "8")]
490 (define_insn_and_split "*adddi_zesidi_di"
491   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
492         (plus:DI (zero_extend:DI
493                   (match_operand:SI 2 "s_register_operand" "r,r"))
494                  (match_operand:DI 1 "s_register_operand" "r,0")))
495    (clobber (reg:CC CC_REGNUM))]
496   "TARGET_ARM"
497   "#"
498   "TARGET_ARM && reload_completed"
499   [(parallel [(set (reg:CC_C CC_REGNUM)
500                    (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
501                                  (match_dup 1)))
502               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
503    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
504                                (plus:SI (match_dup 4) (const_int 0))))]
505   "
506   {
507     operands[3] = gen_highpart (SImode, operands[0]);
508     operands[0] = gen_lowpart (SImode, operands[0]);
509     operands[4] = gen_highpart (SImode, operands[1]);
510     operands[1] = gen_lowpart (SImode, operands[1]);
511     operands[2] = gen_lowpart (SImode, operands[2]);
512   }"
513   [(set_attr "conds" "clob")
514    (set_attr "length" "8")]
517 (define_expand "addsi3"
518   [(set (match_operand:SI          0 "s_register_operand" "")
519         (plus:SI (match_operand:SI 1 "s_register_operand" "")
520                  (match_operand:SI 2 "reg_or_int_operand" "")))]
521   "TARGET_EITHER"
522   "
523   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
524     {
525       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
526                           operands[1],
527                           (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
528       DONE;
529     }
530   "
533 ; If there is a scratch available, this will be faster than synthesising the
534 ; addition.
535 (define_peephole2
536   [(match_scratch:SI 3 "r")
537    (set (match_operand:SI          0 "s_register_operand" "")
538         (plus:SI (match_operand:SI 1 "s_register_operand" "")
539                  (match_operand:SI 2 "const_int_operand"  "")))]
540   "TARGET_ARM &&
541    !(const_ok_for_arm (INTVAL (operands[2]))
542      || const_ok_for_arm (-INTVAL (operands[2])))
543     && const_ok_for_arm (~INTVAL (operands[2]))"
544   [(set (match_dup 3) (match_dup 2))
545    (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
546   ""
549 (define_insn_and_split "*arm_addsi3"
550   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
551         (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
552                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
553   "TARGET_ARM"
554   "@
555    add%?\\t%0, %1, %2
556    sub%?\\t%0, %1, #%n2
557    #"
558   "TARGET_ARM &&
559    GET_CODE (operands[2]) == CONST_INT
560    && !(const_ok_for_arm (INTVAL (operands[2]))
561         || const_ok_for_arm (-INTVAL (operands[2])))"
562   [(clobber (const_int 0))]
563   "
564   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
565                       operands[1], 0);
566   DONE;
567   "
568   [(set_attr "length" "4,4,16")
569    (set_attr "predicable" "yes")]
572 ;; Register group 'k' is a single register group containing only the stack
573 ;; register.  Trying to reload it will always fail catastrophically,
574 ;; so never allow those alternatives to match if reloading is needed.
576 (define_insn "*thumb_addsi3"
577   [(set (match_operand:SI          0 "register_operand" "=l,l,l,*r,*h,l,!k")
578         (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
579                  (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
580   "TARGET_THUMB"
581   "*
582    static const char * const asms[] = 
583    {
584      \"add\\t%0, %0, %2\",
585      \"sub\\t%0, %0, #%n2\",
586      \"add\\t%0, %1, %2\",
587      \"add\\t%0, %0, %2\",
588      \"add\\t%0, %0, %2\",
589      \"add\\t%0, %1, %2\",
590      \"add\\t%0, %1, %2\"
591    };
592    if ((which_alternative == 2 || which_alternative == 6)
593        && GET_CODE (operands[2]) == CONST_INT
594        && INTVAL (operands[2]) < 0)
595      return \"sub\\t%0, %1, #%n2\";
596    return asms[which_alternative];
597   "
598   [(set_attr "length" "2")]
601 ;; Reloading and elimination of the frame pointer can
602 ;; sometimes cause this optimization to be missed.
603 (define_peephole2
604   [(set (match_operand:SI 0 "register_operand" "")
605         (match_operand:SI 1 "const_int_operand" ""))
606    (set (match_dup 0)
607         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
608   "TARGET_THUMB
609    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
610    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
611    && (INTVAL (operands[1]) & 3) == 0"
612   [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
613   ""
616 (define_insn "*addsi3_compare0"
617   [(set (reg:CC_NOOV CC_REGNUM)
618         (compare:CC_NOOV
619          (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
620                   (match_operand:SI 2 "arm_add_operand"    "rI,L"))
621          (const_int 0)))
622    (set (match_operand:SI 0 "s_register_operand" "=r,r")
623         (plus:SI (match_dup 1) (match_dup 2)))]
624   "TARGET_ARM"
625   "@
626    add%?s\\t%0, %1, %2
627    sub%?s\\t%0, %1, #%n2"
628   [(set_attr "conds" "set")]
631 (define_insn "*addsi3_compare0_scratch"
632   [(set (reg:CC_NOOV CC_REGNUM)
633         (compare:CC_NOOV
634          (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
635                   (match_operand:SI 1 "arm_add_operand"    "rI,L"))
636          (const_int 0)))]
637   "TARGET_ARM"
638   "@
639    cmn%?\\t%0, %1
640    cmp%?\\t%0, #%n1"
641   [(set_attr "conds" "set")]
644 ;; These patterns are the same ones as the two regular addsi3_compare0
645 ;; patterns, except we write them slightly different - the combiner
646 ;; tends to generate them this way.
647 (define_insn "*addsi3_compare0_for_combiner"
648   [(set (reg:CC CC_REGNUM)
649         (compare:CC
650          (match_operand:SI 1 "s_register_operand" "r,r")
651          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
652    (set (match_operand:SI 0 "s_register_operand" "=r,r")
653         (plus:SI (match_dup 1) (match_dup 2)))]
654   "TARGET_ARM"
655   "@
656    add%?s\\t%0, %1, %2
657    sub%?s\\t%0, %1, #%n2"
658   [(set_attr "conds" "set")]
661 (define_insn "*addsi3_compare0_scratch_for_combiner"
662   [(set (reg:CC CC_REGNUM)
663         (compare:CC
664          (match_operand:SI 0 "s_register_operand" "r,r")
665          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
666   "TARGET_ARM"
667   "@
668    cmn%?\\t%0, %1
669    cmp%?\\t%0, #%n1"
670   [(set_attr "conds" "set")]
673 ;; The next four insns work because they compare the result with one of
674 ;; the operands, and we know that the use of the condition code is
675 ;; either GEU or LTU, so we can use the carry flag from the addition
676 ;; instead of doing the compare a second time.
677 (define_insn "*addsi3_compare_op1"
678   [(set (reg:CC_C CC_REGNUM)
679         (compare:CC_C
680          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
681                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
682          (match_dup 1)))
683    (set (match_operand:SI 0 "s_register_operand" "=r,r")
684         (plus:SI (match_dup 1) (match_dup 2)))]
685   "TARGET_ARM"
686   "@
687    add%?s\\t%0, %1, %2
688    sub%?s\\t%0, %1, #%n2"
689   [(set_attr "conds" "set")]
692 (define_insn "*addsi3_compare_op2"
693   [(set (reg:CC_C CC_REGNUM)
694         (compare:CC_C
695          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
696                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
697          (match_dup 2)))
698    (set (match_operand:SI 0 "s_register_operand" "=r,r")
699         (plus:SI (match_dup 1) (match_dup 2)))]
700   "TARGET_ARM"
701   "@
702    add%?s\\t%0, %1, %2
703    sub%?s\\t%0, %1, #%n2"
704   [(set_attr "conds" "set")]
707 (define_insn "*compare_addsi2_op0"
708   [(set (reg:CC_C CC_REGNUM)
709         (compare:CC_C
710          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
711                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
712          (match_dup 0)))]
713   "TARGET_ARM"
714   "@
715    cmn%?\\t%0, %1
716    cmp%?\\t%0, #%n1"
717   [(set_attr "conds" "set")]
720 (define_insn "*compare_addsi2_op1"
721   [(set (reg:CC_C CC_REGNUM)
722         (compare:CC_C
723          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
724                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
725          (match_dup 1)))]
726   "TARGET_ARM"
727   "@
728    cmn%?\\t%0, %1
729    cmp%?\\t%0, #%n1"
730   [(set_attr "conds" "set")]
733 (define_insn "*addsi3_carryin"
734   [(set (match_operand:SI 0 "s_register_operand" "=r")
735         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
736                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
737                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
738   "TARGET_ARM"
739   "adc%?\\t%0, %1, %2"
740   [(set_attr "conds" "use")]
743 (define_insn "*addsi3_carryin_shift"
744   [(set (match_operand:SI 0 "s_register_operand" "")
745         (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
746                  (plus:SI
747                    (match_operator:SI 2 "shift_operator"
748                       [(match_operand:SI 3 "s_register_operand" "")
749                        (match_operand:SI 4 "reg_or_int_operand" "")])
750                     (match_operand:SI 1 "s_register_operand" ""))))]
751   "TARGET_ARM"
752   "adc%?\\t%0, %1, %3%S2"
753   [(set_attr "conds" "use")]
756 (define_insn "*addsi3_carryin_alt1"
757   [(set (match_operand:SI 0 "s_register_operand" "=r")
758         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
759                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
760                  (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
761   "TARGET_ARM"
762   "adc%?\\t%0, %1, %2"
763   [(set_attr "conds" "use")]
766 (define_insn "*addsi3_carryin_alt2"
767   [(set (match_operand:SI 0 "s_register_operand" "=r")
768         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
769                           (match_operand:SI 1 "s_register_operand" "r"))
770                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
771   "TARGET_ARM"
772   "adc%?\\t%0, %1, %2"
773   [(set_attr "conds" "use")]
776 (define_insn "*addsi3_carryin_alt3"
777   [(set (match_operand:SI 0 "s_register_operand" "=r")
778         (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
779                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
780                  (match_operand:SI 1 "s_register_operand" "r")))]
781   "TARGET_ARM"
782   "adc%?\\t%0, %1, %2"
783   [(set_attr "conds" "use")]
786 (define_insn "incscc"
787   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
788         (plus:SI (match_operator:SI 2 "arm_comparison_operator"
789                     [(match_operand:CC 3 "cc_register" "") (const_int 0)])
790                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
791   "TARGET_ARM"
792   "@
793   add%d2\\t%0, %1, #1
794   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
795   [(set_attr "conds" "use")
796    (set_attr "length" "4,8")]
799 (define_insn "addsf3"
800   [(set (match_operand:SF          0 "s_register_operand" "=f,f")
801         (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
802                  (match_operand:SF 2 "fpu_add_operand"    "fG,H")))]
803   "TARGET_ARM && TARGET_HARD_FLOAT"
804   "@
805    adf%?s\\t%0, %1, %2
806    suf%?s\\t%0, %1, #%N2"
807   [(set_attr "type" "farith")
808    (set_attr "predicable" "yes")]
811 (define_insn "adddf3"
812   [(set (match_operand:DF          0 "s_register_operand" "=f,f")
813         (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
814                  (match_operand:DF 2 "fpu_add_operand"    "fG,H")))]
815   "TARGET_ARM && TARGET_HARD_FLOAT"
816   "@
817    adf%?d\\t%0, %1, %2
818    suf%?d\\t%0, %1, #%N2"
819   [(set_attr "type" "farith")
820    (set_attr "predicable" "yes")]
823 (define_insn "*adddf_esfdf_df"
824   [(set (match_operand:DF           0 "s_register_operand" "=f,f")
825         (plus:DF (float_extend:DF
826                   (match_operand:SF 1 "s_register_operand"  "f,f"))
827                  (match_operand:DF  2 "fpu_add_operand"    "fG,H")))]
828   "TARGET_ARM && TARGET_HARD_FLOAT"
829   "@
830    adf%?d\\t%0, %1, %2
831    suf%?d\\t%0, %1, #%N2"
832   [(set_attr "type" "farith")
833    (set_attr "predicable" "yes")]
836 (define_insn "*adddf_df_esfdf"
837   [(set (match_operand:DF           0 "s_register_operand" "=f")
838         (plus:DF (match_operand:DF  1 "s_register_operand"  "f")
839                  (float_extend:DF
840                   (match_operand:SF 2 "s_register_operand"  "f"))))]
841   "TARGET_ARM && TARGET_HARD_FLOAT"
842   "adf%?d\\t%0, %1, %2"
843   [(set_attr "type" "farith")
844    (set_attr "predicable" "yes")]
847 (define_insn "*adddf_esfdf_esfdf"
848   [(set (match_operand:DF           0 "s_register_operand" "=f")
849         (plus:DF (float_extend:DF 
850                   (match_operand:SF 1 "s_register_operand" "f"))
851                  (float_extend:DF
852                   (match_operand:SF 2 "s_register_operand" "f"))))]
853   "TARGET_ARM && TARGET_HARD_FLOAT"
854   "adf%?d\\t%0, %1, %2"
855   [(set_attr "type" "farith")
856    (set_attr "predicable" "yes")]
859 (define_insn "addxf3"
860   [(set (match_operand:XF          0 "s_register_operand" "=f,f")
861         (plus:XF (match_operand:XF 1 "s_register_operand"  "f,f")
862                  (match_operand:XF 2 "fpu_add_operand"    "fG,H")))]
863   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
864   "@
865    adf%?e\\t%0, %1, %2
866    suf%?e\\t%0, %1, #%N2"
867   [(set_attr "type" "farith")
868    (set_attr "predicable" "yes")]
871 (define_expand "subdi3"
872  [(parallel
873    [(set (match_operand:DI            0 "s_register_operand" "")
874           (minus:DI (match_operand:DI 1 "s_register_operand" "")
875                     (match_operand:DI 2 "s_register_operand" "")))
876     (clobber (reg:CC CC_REGNUM))])]
877   "TARGET_EITHER"
878   "
879   if (TARGET_THUMB)
880     {
881       if (GET_CODE (operands[1]) != REG)
882         operands[1] = force_reg (SImode, operands[1]);
883       if (GET_CODE (operands[2]) != REG)
884         operands[2] = force_reg (SImode, operands[2]);
885      }  
886   "
889 (define_insn "*arm_subdi3"
890   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r,&r")
891         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
892                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
893    (clobber (reg:CC CC_REGNUM))]
894   "TARGET_ARM"
895   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
896   [(set_attr "conds" "clob")
897    (set_attr "length" "8")]
900 (define_insn "*thumb_subdi3"
901   [(set (match_operand:DI           0 "register_operand" "=l")
902         (minus:DI (match_operand:DI 1 "register_operand"  "0")
903                   (match_operand:DI 2 "register_operand"  "l")))
904    (clobber (reg:CC CC_REGNUM))]
905   "TARGET_THUMB"
906   "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
907   [(set_attr "length" "4")]
910 (define_insn "*subdi_di_zesidi"
911   [(set (match_operand:DI           0 "s_register_operand" "=&r,&r")
912         (minus:DI (match_operand:DI 1 "s_register_operand"  "?r,0")
913                   (zero_extend:DI
914                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
915    (clobber (reg:CC CC_REGNUM))]
916   "TARGET_ARM"
917   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
918   [(set_attr "conds" "clob")
919    (set_attr "length" "8")]
922 (define_insn "*subdi_di_sesidi"
923   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
924         (minus:DI (match_operand:DI  1 "s_register_operand"  "r,0")
925                   (sign_extend:DI
926                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
927    (clobber (reg:CC CC_REGNUM))]
928   "TARGET_ARM"
929   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
930   [(set_attr "conds" "clob")
931    (set_attr "length" "8")]
934 (define_insn "*subdi_zesidi_di"
935   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
936         (minus:DI (zero_extend:DI
937                    (match_operand:SI 2 "s_register_operand"  "r,r"))
938                   (match_operand:DI  1 "s_register_operand" "?r,0")))
939    (clobber (reg:CC CC_REGNUM))]
940   "TARGET_ARM"
941   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
942   [(set_attr "conds" "clob")
943    (set_attr "length" "8")]
946 (define_insn "*subdi_sesidi_di"
947   [(set (match_operand:DI            0 "s_register_operand" "=&r,&r")
948         (minus:DI (sign_extend:DI
949                    (match_operand:SI 2 "s_register_operand"   "r,r"))
950                   (match_operand:DI  1 "s_register_operand"  "?r,0")))
951    (clobber (reg:CC CC_REGNUM))]
952   "TARGET_ARM"
953   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
954   [(set_attr "conds" "clob")
955    (set_attr "length" "8")]
958 (define_insn "*subdi_zesidi_zesidi"
959   [(set (match_operand:DI            0 "s_register_operand" "=r")
960         (minus:DI (zero_extend:DI
961                    (match_operand:SI 1 "s_register_operand"  "r"))
962                   (zero_extend:DI
963                    (match_operand:SI 2 "s_register_operand"  "r"))))
964    (clobber (reg:CC CC_REGNUM))]
965   "TARGET_ARM"
966   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
967   [(set_attr "conds" "clob")
968    (set_attr "length" "8")]
971 (define_expand "subsi3"
972   [(set (match_operand:SI           0 "s_register_operand" "")
973         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
974                   (match_operand:SI 2 "s_register_operand" "")))]
975   "TARGET_EITHER"
976   "
977   if (GET_CODE (operands[1]) == CONST_INT)
978     {
979       if (TARGET_ARM)
980         {
981           arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
982                               operands[2],
983                               (no_new_pseudos ? 0
984                                :  preserve_subexpressions_p ()));
985           DONE;
986         }
987       else /* TARGET_THUMB */
988         operands[1] = force_reg (SImode, operands[1]);
989     }
990   "
993 (define_insn "*thumb_subsi3_insn"
994   [(set (match_operand:SI           0 "register_operand" "=l")
995         (minus:SI (match_operand:SI 1 "register_operand" "l")
996                   (match_operand:SI 2 "register_operand" "l")))]
997   "TARGET_THUMB"
998   "sub\\t%0, %1, %2"
999   [(set_attr "length" "2")]
1002 (define_insn_and_split "*arm_subsi3_insn"
1003   [(set (match_operand:SI           0 "s_register_operand" "=r,r")
1004         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1005                   (match_operand:SI 2 "s_register_operand" "r,r")))]
1006   "TARGET_ARM"
1007   "@
1008    rsb%?\\t%0, %2, %1
1009    #"
1010   "TARGET_ARM
1011    && GET_CODE (operands[1]) == CONST_INT
1012    && !const_ok_for_arm (INTVAL (operands[1]))"
1013   [(clobber (const_int 0))]
1014   "
1015   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1016                       operands[2], 0);
1017   DONE;
1018   "
1019   [(set_attr "length" "4,16")
1020    (set_attr "predicable" "yes")]
1023 (define_peephole2
1024   [(match_scratch:SI 3 "r")
1025    (set (match_operand:SI           0 "s_register_operand" "")
1026         (minus:SI (match_operand:SI 1 "const_int_operand" "")
1027                   (match_operand:SI 2 "s_register_operand" "")))]
1028   "TARGET_ARM
1029    && !const_ok_for_arm (INTVAL (operands[1]))
1030    && const_ok_for_arm (~INTVAL (operands[1]))"
1031   [(set (match_dup 3) (match_dup 1))
1032    (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1033   ""
1036 (define_insn "*subsi3_compare0"
1037   [(set (reg:CC_NOOV CC_REGNUM)
1038         (compare:CC_NOOV
1039          (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1040                    (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1041          (const_int 0)))
1042    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1043         (minus:SI (match_dup 1) (match_dup 2)))]
1044   "TARGET_ARM"
1045   "@
1046    sub%?s\\t%0, %1, %2
1047    rsb%?s\\t%0, %2, %1"
1048   [(set_attr "conds" "set")]
1051 (define_insn "decscc"
1052   [(set (match_operand:SI            0 "s_register_operand" "=r,r")
1053         (minus:SI (match_operand:SI  1 "s_register_operand" "0,?r")
1054                   (match_operator:SI 2 "arm_comparison_operator"
1055                    [(match_operand   3 "cc_register" "") (const_int 0)])))]
1056   "TARGET_ARM"
1057   "@
1058    sub%d2\\t%0, %1, #1
1059    mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1060   [(set_attr "conds" "use")
1061    (set_attr "length" "*,8")]
1064 (define_insn "subsf3"
1065   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1066         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1067                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1068   "TARGET_ARM && TARGET_HARD_FLOAT"
1069   "@
1070    suf%?s\\t%0, %1, %2
1071    rsf%?s\\t%0, %2, %1"
1072   [(set_attr "type" "farith")]
1075 (define_insn "subdf3"
1076   [(set (match_operand:DF           0 "s_register_operand" "=f,f")
1077         (minus:DF (match_operand:DF 1 "fpu_rhs_operand"     "f,G")
1078                   (match_operand:DF 2 "fpu_rhs_operand"    "fG,f")))]
1079   "TARGET_ARM && TARGET_HARD_FLOAT"
1080   "@
1081    suf%?d\\t%0, %1, %2
1082    rsf%?d\\t%0, %2, %1"
1083   [(set_attr "type" "farith")
1084    (set_attr "predicable" "yes")]
1087 (define_insn "*subdf_esfdf_df"
1088   [(set (match_operand:DF            0 "s_register_operand" "=f")
1089         (minus:DF (float_extend:DF
1090                    (match_operand:SF 1 "s_register_operand"  "f"))
1091                   (match_operand:DF  2 "fpu_rhs_operand"    "fG")))]
1092   "TARGET_ARM && TARGET_HARD_FLOAT"
1093   "suf%?d\\t%0, %1, %2"
1094   [(set_attr "type" "farith")
1095    (set_attr "predicable" "yes")]
1098 (define_insn "*subdf_df_esfdf"
1099   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1100         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1101                   (float_extend:DF
1102                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
1103   "TARGET_ARM && TARGET_HARD_FLOAT"
1104   "@
1105    suf%?d\\t%0, %1, %2
1106    rsf%?d\\t%0, %2, %1"
1107   [(set_attr "type" "farith")
1108    (set_attr "predicable" "yes")]
1111 (define_insn "*subdf_esfdf_esfdf"
1112   [(set (match_operand:DF 0 "s_register_operand" "=f")
1113         (minus:DF (float_extend:DF
1114                    (match_operand:SF 1 "s_register_operand" "f"))
1115                   (float_extend:DF
1116                    (match_operand:SF 2 "s_register_operand" "f"))))]
1117   "TARGET_ARM && TARGET_HARD_FLOAT"
1118   "suf%?d\\t%0, %1, %2"
1119   [(set_attr "type" "farith")
1120    (set_attr "predicable" "yes")]
1123 (define_insn "subxf3"
1124   [(set (match_operand:XF           0 "s_register_operand" "=f,f")
1125         (minus:XF (match_operand:XF 1 "fpu_rhs_operand"     "f,G")
1126                   (match_operand:XF 2 "fpu_rhs_operand"    "fG,f")))]
1127   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1128   "@
1129    suf%?e\\t%0, %1, %2
1130    rsf%?e\\t%0, %2, %1"
1131   [(set_attr "type" "farith")
1132    (set_attr "predicable" "yes")]
1135 ;; Multiplication insns
1137 (define_expand "mulsi3"
1138   [(set (match_operand:SI          0 "s_register_operand" "")
1139         (mult:SI (match_operand:SI 2 "s_register_operand" "")
1140                  (match_operand:SI 1 "s_register_operand" "")))]
1141   "TARGET_EITHER"
1142   ""
1145 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1146 (define_insn "*arm_mulsi3"
1147   [(set (match_operand:SI          0 "s_register_operand" "=&r,&r")
1148         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1149                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1150   "TARGET_ARM"
1151   "mul%?\\t%0, %2, %1"
1152   [(set_attr "type" "mult")
1153    (set_attr "predicable" "yes")]
1156 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 
1157 ; 1 and 2; are the same, because reload will make operand 0 match 
1158 ; operand 1 without realizing that this conflicts with operand 2.  We fix 
1159 ; this by adding another alternative to match this case, and then `reload' 
1160 ; it ourselves.  This alternative must come first.
1161 (define_insn "*thumb_mulsi3"
1162   [(set (match_operand:SI          0 "register_operand" "=&l,&l,&l")
1163         (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1164                  (match_operand:SI 2 "register_operand" "l,l,l")))]
1165   "TARGET_THUMB"
1166   "*
1167   if (which_alternative < 2)
1168     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1169   else
1170     return \"mul\\t%0, %0, %2\";
1171   "
1172   [(set_attr "length" "4,4,2")
1173    (set_attr "type" "mult")]
1176 (define_insn "*mulsi3_compare0"
1177   [(set (reg:CC_NOOV CC_REGNUM)
1178         (compare:CC_NOOV (mult:SI
1179                           (match_operand:SI 2 "s_register_operand" "r,r")
1180                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1181                          (const_int 0)))
1182    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1183         (mult:SI (match_dup 2) (match_dup 1)))]
1184   "TARGET_ARM && !arm_is_xscale"
1185   "mul%?s\\t%0, %2, %1"
1186   [(set_attr "conds" "set")
1187    (set_attr "type" "mult")]
1190 (define_insn "*mulsi_compare0_scratch"
1191   [(set (reg:CC_NOOV CC_REGNUM)
1192         (compare:CC_NOOV (mult:SI
1193                           (match_operand:SI 2 "s_register_operand" "r,r")
1194                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
1195                          (const_int 0)))
1196    (clobber (match_scratch:SI 0 "=&r,&r"))]
1197   "TARGET_ARM && !arm_is_xscale"
1198   "mul%?s\\t%0, %2, %1"
1199   [(set_attr "conds" "set")
1200    (set_attr "type" "mult")]
1203 ;; Unnamed templates to match MLA instruction.
1205 (define_insn "*mulsi3addsi"
1206   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1207         (plus:SI
1208           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1209                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1210           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1211   "TARGET_ARM"
1212   "mla%?\\t%0, %2, %1, %3"
1213   [(set_attr "type" "mult")
1214    (set_attr "predicable" "yes")]
1217 (define_insn "*mulsi3addsi_compare0"
1218   [(set (reg:CC_NOOV CC_REGNUM)
1219         (compare:CC_NOOV
1220          (plus:SI (mult:SI
1221                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1222                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1223                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1224          (const_int 0)))
1225    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1226         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1227                  (match_dup 3)))]
1228   "TARGET_ARM && !arm_is_xscale"
1229   "mla%?s\\t%0, %2, %1, %3"
1230   [(set_attr "conds" "set")
1231    (set_attr "type" "mult")]
1234 (define_insn "*mulsi3addsi_compare0_scratch"
1235   [(set (reg:CC_NOOV CC_REGNUM)
1236         (compare:CC_NOOV
1237          (plus:SI (mult:SI
1238                    (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1239                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1240                   (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1241          (const_int 0)))
1242    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1243   "TARGET_ARM && !arm_is_xscale"
1244   "mla%?s\\t%0, %2, %1, %3"
1245   [(set_attr "conds" "set")
1246    (set_attr "type" "mult")]
1249 ;; Unnamed template to match long long multiply-accumlate (smlal)
1251 (define_insn "*mulsidi3adddi"
1252   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1253         (plus:DI
1254          (mult:DI
1255           (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1256           (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1257          (match_operand:DI 1 "s_register_operand" "0")))]
1258   "TARGET_ARM && arm_fast_multiply"
1259   "smlal%?\\t%Q0, %R0, %3, %2"
1260   [(set_attr "type" "mult")
1261    (set_attr "predicable" "yes")]
1264 (define_insn "mulsidi3"
1265   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1266         (mult:DI
1267          (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1268          (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1269   "TARGET_ARM && arm_fast_multiply"
1270   "smull%?\\t%Q0, %R0, %1, %2"
1271   [(set_attr "type" "mult")
1272    (set_attr "predicable" "yes")]
1275 (define_insn "umulsidi3"
1276   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1277         (mult:DI
1278          (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1279          (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1280   "TARGET_ARM && arm_fast_multiply"
1281   "umull%?\\t%Q0, %R0, %1, %2"
1282   [(set_attr "type" "mult")
1283    (set_attr "predicable" "yes")]
1286 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1288 (define_insn "*umulsidi3adddi"
1289   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1290         (plus:DI
1291          (mult:DI
1292           (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1293           (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1294          (match_operand:DI 1 "s_register_operand" "0")))]
1295   "TARGET_ARM && arm_fast_multiply"
1296   "umlal%?\\t%Q0, %R0, %3, %2"
1297   [(set_attr "type" "mult")
1298    (set_attr "predicable" "yes")]
1301 (define_insn "smulsi3_highpart"
1302   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1303         (truncate:SI
1304          (lshiftrt:DI
1305           (mult:DI
1306            (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1307            (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1308           (const_int 32))))
1309    (clobber (match_scratch:SI 3 "=&r,&r"))]
1310   "TARGET_ARM && arm_fast_multiply"
1311   "smull%?\\t%3, %0, %2, %1"
1312   [(set_attr "type" "mult")
1313    (set_attr "predicable" "yes")]
1316 (define_insn "umulsi3_highpart"
1317   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1318         (truncate:SI
1319          (lshiftrt:DI
1320           (mult:DI
1321            (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1322            (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1323           (const_int 32))))
1324    (clobber (match_scratch:SI 3 "=&r,&r"))]
1325   "TARGET_ARM && arm_fast_multiply"
1326   "umull%?\\t%3, %0, %2, %1"
1327   [(set_attr "type" "mult")
1328    (set_attr "predicable" "yes")]
1331 (define_insn "mulhisi3"
1332   [(set (match_operand:SI 0 "s_register_operand" "=r")
1333         (mult:SI (sign_extend:SI
1334                   (match_operand:HI 1 "s_register_operand" "%r"))
1335                  (sign_extend:SI
1336                   (match_operand:HI 2 "s_register_operand" "r"))))]
1337   "TARGET_ARM && arm_is_xscale"
1338   "smulbb%?\\t%0, %1, %2"
1339   [(set_attr "type" "mult")]
1342 (define_insn "*mulhisi3addsi"
1343   [(set (match_operand:SI 0 "s_register_operand" "=r")
1344         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1345                  (mult:SI (sign_extend:SI
1346                            (match_operand:HI 2 "s_register_operand" "%r"))
1347                           (sign_extend:SI
1348                            (match_operand:HI 3 "s_register_operand" "r")))))]
1349   "TARGET_ARM && arm_is_xscale"
1350   "smlabb%?\\t%0, %2, %3, %1"
1351   [(set_attr "type" "mult")]
1354 (define_insn "*mulhidi3adddi"
1355   [(set (match_operand:DI 0 "s_register_operand" "=r")
1356         (plus:DI
1357           (match_operand:DI 1 "s_register_operand" "0")
1358           (mult:DI (sign_extend:DI
1359                     (match_operand:HI 2 "s_register_operand" "%r"))
1360                    (sign_extend:DI
1361                     (match_operand:HI 3 "s_register_operand" "r")))))]
1362   "TARGET_ARM && arm_is_xscale"
1363   "smlalbb%?\\t%Q0, %R0, %2, %3"
1364 [(set_attr "type" "mult")])
1366 (define_insn "mulsf3"
1367   [(set (match_operand:SF 0 "s_register_operand" "=f")
1368         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1369                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1370   "TARGET_ARM && TARGET_HARD_FLOAT"
1371   "fml%?s\\t%0, %1, %2"
1372   [(set_attr "type" "ffmul")
1373    (set_attr "predicable" "yes")]
1376 (define_insn "muldf3"
1377   [(set (match_operand:DF 0 "s_register_operand" "=f")
1378         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1379                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1380   "TARGET_ARM && TARGET_HARD_FLOAT"
1381   "muf%?d\\t%0, %1, %2"
1382   [(set_attr "type" "fmul")
1383    (set_attr "predicable" "yes")]
1386 (define_insn "*muldf_esfdf_df"
1387   [(set (match_operand:DF 0 "s_register_operand" "=f")
1388         (mult:DF (float_extend:DF
1389                   (match_operand:SF 1 "s_register_operand" "f"))
1390                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1391   "TARGET_ARM && TARGET_HARD_FLOAT"
1392   "muf%?d\\t%0, %1, %2"
1393   [(set_attr "type" "fmul")
1394    (set_attr "predicable" "yes")]
1397 (define_insn "*muldf_df_esfdf"
1398   [(set (match_operand:DF 0 "s_register_operand" "=f")
1399         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1400                  (float_extend:DF
1401                   (match_operand:SF 2 "s_register_operand" "f"))))]
1402   "TARGET_ARM && TARGET_HARD_FLOAT"
1403   "muf%?d\\t%0, %1, %2"
1404   [(set_attr "type" "fmul")
1405    (set_attr "predicable" "yes")]
1408 (define_insn "*muldf_esfdf_esfdf"
1409   [(set (match_operand:DF 0 "s_register_operand" "=f")
1410         (mult:DF
1411          (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1412          (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1413   "TARGET_ARM && TARGET_HARD_FLOAT"
1414   "muf%?d\\t%0, %1, %2"
1415   [(set_attr "type" "fmul")
1416    (set_attr "predicable" "yes")]
1419 (define_insn "mulxf3"
1420   [(set (match_operand:XF 0 "s_register_operand" "=f")
1421         (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1422                  (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1423   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1424   "muf%?e\\t%0, %1, %2"
1425   [(set_attr "type" "fmul")
1426    (set_attr "predicable" "yes")]
1429 ;; Division insns
1431 (define_insn "divsf3"
1432   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1433         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1434                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1435   "TARGET_ARM && TARGET_HARD_FLOAT"
1436   "@
1437    fdv%?s\\t%0, %1, %2
1438    frd%?s\\t%0, %2, %1"
1439   [(set_attr "type" "fdivs")
1440    (set_attr "predicable" "yes")]
1443 (define_insn "divdf3"
1444   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1445         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1446                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1447   "TARGET_ARM && TARGET_HARD_FLOAT"
1448   "@
1449    dvf%?d\\t%0, %1, %2
1450    rdf%?d\\t%0, %2, %1"
1451   [(set_attr "type" "fdivd")
1452    (set_attr "predicable" "yes")]
1455 (define_insn "*divdf_esfdf_df"
1456   [(set (match_operand:DF 0 "s_register_operand" "=f")
1457         (div:DF (float_extend:DF
1458                  (match_operand:SF 1 "s_register_operand" "f"))
1459                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1460   "TARGET_ARM && TARGET_HARD_FLOAT"
1461   "dvf%?d\\t%0, %1, %2"
1462   [(set_attr "type" "fdivd")
1463    (set_attr "predicable" "yes")]
1466 (define_insn "*divdf_df_esfdf"
1467   [(set (match_operand:DF 0 "s_register_operand" "=f")
1468         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1469                 (float_extend:DF
1470                  (match_operand:SF 2 "s_register_operand" "f"))))]
1471   "TARGET_ARM && TARGET_HARD_FLOAT"
1472   "rdf%?d\\t%0, %2, %1"
1473   [(set_attr "type" "fdivd")
1474    (set_attr "predicable" "yes")]
1477 (define_insn "*divdf_esfdf_esfdf"
1478   [(set (match_operand:DF 0 "s_register_operand" "=f")
1479         (div:DF (float_extend:DF
1480                  (match_operand:SF 1 "s_register_operand" "f"))
1481                 (float_extend:DF
1482                  (match_operand:SF 2 "s_register_operand" "f"))))]
1483   "TARGET_ARM && TARGET_HARD_FLOAT"
1484   "dvf%?d\\t%0, %1, %2"
1485   [(set_attr "type" "fdivd")
1486    (set_attr "predicable" "yes")]
1489 (define_insn "divxf3"
1490   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1491         (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1492                 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1493   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1494   "@
1495    dvf%?e\\t%0, %1, %2
1496    rdf%?e\\t%0, %2, %1"
1497   [(set_attr "type" "fdivx")
1498    (set_attr "predicable" "yes")]
1501 ;; Modulo insns
1503 (define_insn "modsf3"
1504   [(set (match_operand:SF 0 "s_register_operand" "=f")
1505         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1506                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1507   "TARGET_ARM && TARGET_HARD_FLOAT"
1508   "rmf%?s\\t%0, %1, %2"
1509   [(set_attr "type" "fdivs")
1510    (set_attr "predicable" "yes")]
1513 (define_insn "moddf3"
1514   [(set (match_operand:DF 0 "s_register_operand" "=f")
1515         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1516                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1517   "TARGET_ARM && TARGET_HARD_FLOAT"
1518   "rmf%?d\\t%0, %1, %2"
1519   [(set_attr "type" "fdivd")
1520    (set_attr "predicable" "yes")]
1523 (define_insn "*moddf_esfdf_df"
1524   [(set (match_operand:DF 0 "s_register_operand" "=f")
1525         (mod:DF (float_extend:DF
1526                  (match_operand:SF 1 "s_register_operand" "f"))
1527                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1528   "TARGET_ARM && TARGET_HARD_FLOAT"
1529   "rmf%?d\\t%0, %1, %2"
1530   [(set_attr "type" "fdivd")
1531    (set_attr "predicable" "yes")]
1534 (define_insn "*moddf_df_esfdf"
1535   [(set (match_operand:DF 0 "s_register_operand" "=f")
1536         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1537                 (float_extend:DF
1538                  (match_operand:SF 2 "s_register_operand" "f"))))]
1539   "TARGET_ARM && TARGET_HARD_FLOAT"
1540   "rmf%?d\\t%0, %1, %2"
1541   [(set_attr "type" "fdivd")
1542    (set_attr "predicable" "yes")]
1545 (define_insn "*moddf_esfdf_esfdf"
1546   [(set (match_operand:DF 0 "s_register_operand" "=f")
1547         (mod:DF (float_extend:DF
1548                  (match_operand:SF 1 "s_register_operand" "f"))
1549                 (float_extend:DF
1550                  (match_operand:SF 2 "s_register_operand" "f"))))]
1551   "TARGET_ARM && TARGET_HARD_FLOAT"
1552   "rmf%?d\\t%0, %1, %2"
1553   [(set_attr "type" "fdivd")
1554    (set_attr "predicable" "yes")]
1557 (define_insn "modxf3"
1558   [(set (match_operand:XF 0 "s_register_operand" "=f")
1559         (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1560                 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1561   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1562   "rmf%?e\\t%0, %1, %2"
1563   [(set_attr "type" "fdivx")
1564    (set_attr "predicable" "yes")]
1567 ;; Boolean and,ior,xor insns
1569 ;; Split up double word logical operations
1571 ;; Split up simple DImode logical operations.  Simply perform the logical
1572 ;; operation on the upper and lower halves of the registers.
1573 (define_split
1574   [(set (match_operand:DI 0 "s_register_operand" "")
1575         (match_operator:DI 6 "logical_binary_operator"
1576           [(match_operand:DI 1 "s_register_operand" "")
1577            (match_operand:DI 2 "s_register_operand" "")]))]
1578   "TARGET_ARM && reload_completed"
1579   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1580    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1581   "
1582   {
1583     operands[3] = gen_highpart (SImode, operands[0]);
1584     operands[0] = gen_lowpart (SImode, operands[0]);
1585     operands[4] = gen_highpart (SImode, operands[1]);
1586     operands[1] = gen_lowpart (SImode, operands[1]);
1587     operands[5] = gen_highpart (SImode, operands[2]);
1588     operands[2] = gen_lowpart (SImode, operands[2]);
1589   }"
1592 (define_split
1593   [(set (match_operand:DI 0 "s_register_operand" "")
1594         (match_operator:DI 6 "logical_binary_operator"
1595           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1596            (match_operand:DI 1 "s_register_operand" "")]))]
1597   "TARGET_ARM && reload_completed"
1598   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1599    (set (match_dup 3) (match_op_dup:SI 6
1600                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1601                          (match_dup 4)]))]
1602   "
1603   {
1604     operands[3] = gen_highpart (SImode, operands[0]);
1605     operands[0] = gen_lowpart (SImode, operands[0]);
1606     operands[4] = gen_highpart (SImode, operands[1]);
1607     operands[1] = gen_lowpart (SImode, operands[1]);
1608     operands[5] = gen_highpart (SImode, operands[2]);
1609     operands[2] = gen_lowpart (SImode, operands[2]);
1610   }"
1613 ;; The zero extend of operand 2 means we can just copy the high part of
1614 ;; operand1 into operand0.
1615 (define_split
1616   [(set (match_operand:DI 0 "s_register_operand" "")
1617         (ior:DI
1618           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1619           (match_operand:DI 1 "s_register_operand" "")))]
1620   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1621   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1622    (set (match_dup 3) (match_dup 4))]
1623   "
1624   {
1625     operands[4] = gen_highpart (SImode, operands[1]);
1626     operands[3] = gen_highpart (SImode, operands[0]);
1627     operands[0] = gen_lowpart (SImode, operands[0]);
1628     operands[1] = gen_lowpart (SImode, operands[1]);
1629   }"
1632 ;; The zero extend of operand 2 means we can just copy the high part of
1633 ;; operand1 into operand0.
1634 (define_split
1635   [(set (match_operand:DI 0 "s_register_operand" "")
1636         (xor:DI
1637           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1638           (match_operand:DI 1 "s_register_operand" "")))]
1639   "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1640   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1641    (set (match_dup 3) (match_dup 4))]
1642   "
1643   {
1644     operands[4] = gen_highpart (SImode, operands[1]);
1645     operands[3] = gen_highpart (SImode, operands[0]);
1646     operands[0] = gen_lowpart (SImode, operands[0]);
1647     operands[1] = gen_lowpart (SImode, operands[1]);
1648   }"
1651 (define_insn "anddi3"
1652   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
1653         (and:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
1654                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
1655   "TARGET_ARM"
1656   "#"
1657   [(set_attr "length" "8")]
1660 (define_insn_and_split "*anddi_zesidi_di"
1661   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1662         (and:DI (zero_extend:DI
1663                  (match_operand:SI 2 "s_register_operand" "r,r"))
1664                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1665   "TARGET_ARM"
1666   "#"
1667   "TARGET_ARM && reload_completed"
1668   ; The zero extend of operand 2 clears the high word of the output
1669   ; operand.
1670   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1671    (set (match_dup 3) (const_int 0))]
1672   "
1673   {
1674     operands[3] = gen_highpart (SImode, operands[0]);
1675     operands[0] = gen_lowpart (SImode, operands[0]);
1676     operands[1] = gen_lowpart (SImode, operands[1]);
1677   }"
1678   [(set_attr "length" "8")]
1681 (define_insn "*anddi_sesdi_di"
1682   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
1683         (and:DI (sign_extend:DI
1684                  (match_operand:SI 2 "s_register_operand" "r,r"))
1685                 (match_operand:DI  1 "s_register_operand" "?r,0")))]
1686   "TARGET_ARM"
1687   "#"
1688   [(set_attr "length" "8")]
1691 (define_expand "andsi3"
1692   [(set (match_operand:SI         0 "s_register_operand" "")
1693         (and:SI (match_operand:SI 1 "s_register_operand" "")
1694                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1695   "TARGET_EITHER"
1696   "
1697   if (TARGET_ARM)
1698     {
1699       if (GET_CODE (operands[2]) == CONST_INT)
1700         {
1701           arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1702                               operands[1],
1703                               (no_new_pseudos
1704                                ? 0 : preserve_subexpressions_p ()));
1705           DONE;
1706         }
1707     }
1708   else /* TARGET_THUMB */
1709     {
1710       if (GET_CODE (operands[2]) != CONST_INT)
1711         operands[2] = force_reg (SImode, operands[2]);
1712       else
1713         {
1714           int i;
1715           
1716           if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1717             {
1718               operands[2] = force_reg (SImode,
1719                                        GEN_INT (~INTVAL (operands[2])));
1720               
1721               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1722               
1723               DONE;
1724             }
1726           for (i = 9; i <= 31; i++)
1727             {
1728               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1729                 {
1730                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1731                                         const0_rtx));
1732                   DONE;
1733                 }
1734               else if ((((HOST_WIDE_INT) 1) << i) - 1
1735                        == ~INTVAL (operands[2]))
1736                 {
1737                   rtx shift = GEN_INT (i);
1738                   rtx reg = gen_reg_rtx (SImode);
1739                 
1740                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1741                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1742                   
1743                   DONE;
1744                 }
1745             }
1747           operands[2] = force_reg (SImode, operands[2]);
1748         }
1749     }
1750   "
1753 (define_insn_and_split "*arm_andsi3_insn"
1754   [(set (match_operand:SI         0 "s_register_operand" "=r,r,r")
1755         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1756                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1757   "TARGET_ARM"
1758   "@
1759    and%?\\t%0, %1, %2
1760    bic%?\\t%0, %1, #%B2
1761    #"
1762   "TARGET_ARM
1763    && GET_CODE (operands[2]) == CONST_INT
1764    && !(const_ok_for_arm (INTVAL (operands[2]))
1765         || const_ok_for_arm (~INTVAL (operands[2])))"
1766   [(clobber (const_int 0))]
1767   "
1768   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1769                        operands[1], 0);
1770   DONE;
1771   "
1772   [(set_attr "length" "4,4,16")
1773    (set_attr "predicable" "yes")]
1776 (define_insn "*thumb_andsi3_insn"
1777   [(set (match_operand:SI         0 "register_operand" "=l")
1778         (and:SI (match_operand:SI 1 "register_operand" "%0")
1779                 (match_operand:SI 2 "register_operand" "l")))]
1780   "TARGET_THUMB"
1781   "and\\t%0, %0, %2"
1782   [(set_attr "length" "2")]
1785 (define_insn "*andsi3_compare0"
1786   [(set (reg:CC_NOOV CC_REGNUM)
1787         (compare:CC_NOOV
1788          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1789                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1790          (const_int 0)))
1791    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1792         (and:SI (match_dup 1) (match_dup 2)))]
1793   "TARGET_ARM"
1794   "@
1795    and%?s\\t%0, %1, %2
1796    bic%?s\\t%0, %1, #%B2"
1797   [(set_attr "conds" "set")]
1800 (define_insn "*andsi3_compare0_scratch"
1801   [(set (reg:CC_NOOV CC_REGNUM)
1802         (compare:CC_NOOV
1803          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1804                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1805          (const_int 0)))
1806    (clobber (match_scratch:SI 2 "=X,r"))]
1807   "TARGET_ARM"
1808   "@
1809    tst%?\\t%0, %1
1810    bic%?s\\t%2, %0, #%B1"
1811   [(set_attr "conds" "set")]
1814 (define_insn "*zeroextractsi_compare0_scratch"
1815   [(set (reg:CC_NOOV CC_REGNUM)
1816         (compare:CC_NOOV (zero_extract:SI
1817                           (match_operand:SI 0 "s_register_operand" "r")
1818                           (match_operand 1 "const_int_operand" "n")
1819                           (match_operand 2 "const_int_operand" "n"))
1820                          (const_int 0)))]
1821   "TARGET_ARM
1822   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1823       && INTVAL (operands[1]) > 0 
1824       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1825       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1826   "*
1827   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1828                          << INTVAL (operands[2]));
1829   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1830   return \"\";
1831   "
1832   [(set_attr "conds" "set")]
1835 (define_insn "*ne_zeroextractsi"
1836   [(set (match_operand:SI 0 "s_register_operand" "=r")
1837         (ne:SI (zero_extract:SI
1838                 (match_operand:SI 1 "s_register_operand" "r")
1839                 (match_operand:SI 2 "const_int_operand" "n")
1840                 (match_operand:SI 3 "const_int_operand" "n"))
1841                (const_int 0)))]
1842   "TARGET_ARM
1843    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1844        && INTVAL (operands[2]) > 0 
1845        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1846        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1847   "*
1848   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1849                          << INTVAL (operands[3]));
1850   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1851   return \"movne\\t%0, #1\";
1852   "
1853   [(set_attr "conds" "clob")
1854    (set_attr "length" "8")]
1857 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1858 ;;; represented by the bitfield, then this will produce incorrect results.
1859 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1860 ;;; which have a real bitfield insert instruction, the truncation happens
1861 ;;; in the bitfield insert instruction itself.  Since arm does not have a
1862 ;;; bitfield insert instruction, we would have to emit code here to truncate
1863 ;;; the value before we insert.  This loses some of the advantage of having
1864 ;;; this insv pattern, so this pattern needs to be reevalutated.
1866 (define_expand "insv"
1867   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1868                          (match_operand:SI 1 "general_operand" "")
1869                          (match_operand:SI 2 "general_operand" ""))
1870         (match_operand:SI 3 "reg_or_int_operand" ""))]
1871   "TARGET_ARM"
1872   "
1873   {
1874     int start_bit = INTVAL (operands[2]);
1875     int width = INTVAL (operands[1]);
1876     HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1877     rtx target, subtarget;
1879     target = operands[0];
1880     /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1881        subreg as the final target.  */
1882     if (GET_CODE (target) == SUBREG)
1883       {
1884         subtarget = gen_reg_rtx (SImode);
1885         if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1886             < GET_MODE_SIZE (SImode))
1887           target = SUBREG_REG (target);
1888       }
1889     else
1890       subtarget = target;    
1892     if (GET_CODE (operands[3]) == CONST_INT)
1893       {
1894         /* Since we are inserting a known constant, we may be able to
1895            reduce the number of bits that we have to clear so that
1896            the mask becomes simple.  */
1897         /* ??? This code does not check to see if the new mask is actually
1898            simpler.  It may not be.  */
1899         rtx op1 = gen_reg_rtx (SImode);
1900         /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1901            start of this pattern.  */
1902         HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1903         HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1905         emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1906         emit_insn (gen_iorsi3 (subtarget, op1,
1907                                GEN_INT (op3_value << start_bit)));
1908       }
1909     else if (start_bit == 0
1910              && !(const_ok_for_arm (mask)
1911                   || const_ok_for_arm (~mask)))
1912       {
1913         /* A Trick, since we are setting the bottom bits in the word,
1914            we can shift operand[3] up, operand[0] down, OR them together
1915            and rotate the result back again.  This takes 3 insns, and
1916            the third might be mergable into another op.  */
1917         /* The shift up copes with the possibility that operand[3] is
1918            wider than the bitfield.  */
1919         rtx op0 = gen_reg_rtx (SImode);
1920         rtx op1 = gen_reg_rtx (SImode);
1922         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1923         emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1924         emit_insn (gen_iorsi3  (op1, op1, op0));
1925         emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1926       }
1927     else if ((width + start_bit == 32)
1928              && !(const_ok_for_arm (mask)
1929                   || const_ok_for_arm (~mask)))
1930       {
1931         /* Similar trick, but slightly less efficient.  */
1933         rtx op0 = gen_reg_rtx (SImode);
1934         rtx op1 = gen_reg_rtx (SImode);
1936         emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1937         emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1938         emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1939         emit_insn (gen_iorsi3 (subtarget, op1, op0));
1940       }
1941     else
1942       {
1943         rtx op0 = GEN_INT (mask);
1944         rtx op1 = gen_reg_rtx (SImode);
1945         rtx op2 = gen_reg_rtx (SImode);
1947         if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1948           {
1949             rtx tmp = gen_reg_rtx (SImode);
1951             emit_insn (gen_movsi (tmp, op0));
1952             op0 = tmp;
1953           }
1955         /* Mask out any bits in operand[3] that are not needed.  */
1956            emit_insn (gen_andsi3 (op1, operands[3], op0));
1958         if (GET_CODE (op0) == CONST_INT
1959             && (const_ok_for_arm (mask << start_bit)
1960                 || const_ok_for_arm (~(mask << start_bit))))
1961           {
1962             op0 = GEN_INT (~(mask << start_bit));
1963             emit_insn (gen_andsi3 (op2, operands[0], op0));
1964           }
1965         else
1966           {
1967             if (GET_CODE (op0) == CONST_INT)
1968               {
1969                 rtx tmp = gen_reg_rtx (SImode);
1971                 emit_insn (gen_movsi (tmp, op0));
1972                 op0 = tmp;
1973               }
1975             if (start_bit != 0)
1976               emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1977             
1978             emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1979           }
1981         if (start_bit != 0)
1982           emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1984         emit_insn (gen_iorsi3 (subtarget, op1, op2));
1985       }
1987     if (subtarget != target)
1988       {
1989         /* If TARGET is still a SUBREG, then it must be wider than a word,
1990            so we must be careful only to set the subword we were asked to.  */
1991         if (GET_CODE (target) == SUBREG)
1992           emit_move_insn (target, subtarget);
1993         else
1994           emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1995       }
1997     DONE;
1998   }"
2001 ; constants for op 2 will never be given to these patterns.
2002 (define_insn_and_split "*anddi_notdi_di"
2003   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2004         (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
2005                 (match_operand:DI 2 "s_register_operand" "0,r")))]
2006   "TARGET_ARM"
2007   "#"
2008   "TARGET_ARM && reload_completed"
2009   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2010    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2011   "
2012   {
2013     operands[3] = gen_highpart (SImode, operands[0]);
2014     operands[0] = gen_lowpart (SImode, operands[0]);
2015     operands[4] = gen_highpart (SImode, operands[1]);
2016     operands[1] = gen_lowpart (SImode, operands[1]);
2017     operands[5] = gen_highpart (SImode, operands[2]);
2018     operands[2] = gen_lowpart (SImode, operands[2]);
2019   }"
2020   [(set_attr "length" "8")
2021    (set_attr "predicable" "yes")]
2023   
2024 (define_insn_and_split "*anddi_notzesidi_di"
2025   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2026         (and:DI (not:DI (zero_extend:DI
2027                          (match_operand:SI 2 "s_register_operand" "r,r")))
2028                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2029   "TARGET_ARM"
2030   "@
2031    bic%?\\t%Q0, %Q1, %2
2032    #"
2033   ; (not (zero_extend ...)) allows us to just copy the high word from
2034   ; operand1 to operand0.
2035   "TARGET_ARM
2036    && reload_completed
2037    && operands[0] != operands[1]"
2038   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2039    (set (match_dup 3) (match_dup 4))]
2040   "
2041   {
2042     operands[3] = gen_highpart (SImode, operands[0]);
2043     operands[0] = gen_lowpart (SImode, operands[0]);
2044     operands[4] = gen_highpart (SImode, operands[1]);
2045     operands[1] = gen_lowpart (SImode, operands[1]);
2046   }"
2047   [(set_attr "length" "4,8")
2048    (set_attr "predicable" "yes")]
2050   
2051 (define_insn_and_split "*anddi_notsesidi_di"
2052   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2053         (and:DI (not:DI (sign_extend:DI
2054                          (match_operand:SI 2 "s_register_operand" "r,r")))
2055                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2056   "TARGET_ARM"
2057   "#"
2058   "TARGET_ARM && reload_completed"
2059   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2060    (set (match_dup 3) (and:SI (not:SI
2061                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
2062                                (match_dup 4)))]
2063   "
2064   {
2065     operands[3] = gen_highpart (SImode, operands[0]);
2066     operands[0] = gen_lowpart (SImode, operands[0]);
2067     operands[4] = gen_highpart (SImode, operands[1]);
2068     operands[1] = gen_lowpart (SImode, operands[1]);
2069   }"
2070   [(set_attr "length" "8")
2071    (set_attr "predicable" "yes")]
2073   
2074 (define_insn "andsi_notsi_si"
2075   [(set (match_operand:SI 0 "s_register_operand" "=r")
2076         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2077                 (match_operand:SI 1 "s_register_operand" "r")))]
2078   "TARGET_ARM"
2079   "bic%?\\t%0, %1, %2"
2080   [(set_attr "predicable" "yes")]
2083 (define_insn "bicsi3"
2084   [(set (match_operand:SI                 0 "register_operand" "=l")
2085         (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2086                 (match_operand:SI         2 "register_operand" "0")))]
2087   "TARGET_THUMB"
2088   "bic\\t%0, %0, %1"
2089   [(set_attr "length" "2")]
2092 (define_insn "andsi_not_shiftsi_si"
2093   [(set (match_operand:SI                   0 "s_register_operand" "=r")
2094         (and:SI (not:SI (match_operator:SI  4 "shift_operator"
2095                          [(match_operand:SI 2 "s_register_operand"  "r")
2096                           (match_operand:SI 3 "arm_rhs_operand"     "rM")]))
2097                 (match_operand:SI           1 "s_register_operand"  "r")))]
2098   "TARGET_ARM"
2099   "bic%?\\t%0, %1, %2%S4"
2100   [(set_attr "predicable" "yes")
2101    (set_attr "shift" "2")
2102    ]
2105 (define_insn "*andsi_notsi_si_compare0"
2106   [(set (reg:CC_NOOV CC_REGNUM)
2107         (compare:CC_NOOV
2108          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2109                  (match_operand:SI 1 "s_register_operand" "r"))
2110          (const_int 0)))
2111    (set (match_operand:SI 0 "s_register_operand" "=r")
2112         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2113   "TARGET_ARM"
2114   "bic%?s\\t%0, %1, %2"
2115   [(set_attr "conds" "set")]
2118 (define_insn "*andsi_notsi_si_compare0_scratch"
2119   [(set (reg:CC_NOOV CC_REGNUM)
2120         (compare:CC_NOOV
2121          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2122                  (match_operand:SI 1 "s_register_operand" "r"))
2123          (const_int 0)))
2124    (clobber (match_scratch:SI 0 "=r"))]
2125   "TARGET_ARM"
2126   "bic%?s\\t%0, %1, %2"
2127   [(set_attr "conds" "set")]
2130 (define_insn "iordi3"
2131   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2132         (ior:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2133                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2134   "TARGET_ARM"
2135   "#"
2136   [(set_attr "length" "8")
2137    (set_attr "predicable" "yes")]
2140 (define_insn "*iordi_zesidi_di"
2141   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2142         (ior:DI (zero_extend:DI
2143                  (match_operand:SI 2 "s_register_operand" "r,r"))
2144                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2145   "TARGET_ARM"
2146   "@
2147    orr%?\\t%Q0, %Q1, %2
2148    #"
2149   [(set_attr "length" "4,8")
2150    (set_attr "predicable" "yes")]
2153 (define_insn "*iordi_sesidi_di"
2154   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2155         (ior:DI (sign_extend:DI
2156                  (match_operand:SI 2 "s_register_operand" "r,r"))
2157                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2158   "TARGET_ARM"
2159   "#"
2160   [(set_attr "length" "8")
2161    (set_attr "predicable" "yes")]
2164 (define_expand "iorsi3"
2165   [(set (match_operand:SI         0 "s_register_operand" "")
2166         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2167                 (match_operand:SI 2 "reg_or_int_operand" "")))]
2168   "TARGET_EITHER"
2169   "
2170   if (GET_CODE (operands[2]) == CONST_INT)
2171     {
2172       if (TARGET_ARM)
2173         {
2174           arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2175                               operands[1],
2176                               (no_new_pseudos
2177                               ? 0 : preserve_subexpressions_p ()));
2178           DONE;
2179         }
2180       else /* TARGET_THUMB */
2181         operands [2] = force_reg (SImode, operands [2]);
2182     }
2183   "
2186 (define_insn_and_split "*arm_iorsi3"
2187   [(set (match_operand:SI         0 "s_register_operand" "=r,r")
2188         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2189                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2190   "TARGET_ARM"
2191   "@
2192    orr%?\\t%0, %1, %2
2193    #"
2194   "TARGET_ARM
2195    && GET_CODE (operands[2]) == CONST_INT
2196    && !const_ok_for_arm (INTVAL (operands[2]))"
2197   [(clobber (const_int 0))]
2198   "
2199   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2200                       operands[1], 0);
2201   DONE;
2202   "
2203   [(set_attr "length" "4,16")
2204    (set_attr "predicable" "yes")]
2207 (define_insn "*thumb_iorsi3"
2208   [(set (match_operand:SI         0 "register_operand" "=l")
2209         (ior:SI (match_operand:SI 1 "register_operand" "%0")
2210                 (match_operand:SI 2 "register_operand" "l")))]
2211   "TARGET_THUMB"
2212   "orr\\t%0, %0, %2"
2213   [(set_attr "length" "2")]
2216 (define_peephole2
2217   [(match_scratch:SI 3 "r")
2218    (set (match_operand:SI         0 "s_register_operand" "")
2219         (ior:SI (match_operand:SI 1 "s_register_operand" "")
2220                 (match_operand:SI 2 "const_int_operand" "")))]
2221   "TARGET_ARM
2222    && !const_ok_for_arm (INTVAL (operands[2]))
2223    && const_ok_for_arm (~INTVAL (operands[2]))"
2224   [(set (match_dup 3) (match_dup 2))
2225    (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2226   ""
2229 (define_insn "*iorsi3_compare0"
2230   [(set (reg:CC_NOOV CC_REGNUM)
2231         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2232                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2233                          (const_int 0)))
2234    (set (match_operand:SI 0 "s_register_operand" "=r")
2235         (ior:SI (match_dup 1) (match_dup 2)))]
2236   "TARGET_ARM"
2237   "orr%?s\\t%0, %1, %2"
2238   [(set_attr "conds" "set")]
2241 (define_insn "*iorsi3_compare0_scratch"
2242   [(set (reg:CC_NOOV CC_REGNUM)
2243         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2244                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2245                          (const_int 0)))
2246    (clobber (match_scratch:SI 0 "=r"))]
2247   "TARGET_ARM"
2248   "orr%?s\\t%0, %1, %2"
2249   [(set_attr "conds" "set")]
2252 (define_insn "xordi3"
2253   [(set (match_operand:DI         0 "s_register_operand" "=&r,&r")
2254         (xor:DI (match_operand:DI 1 "s_register_operand"  "%0,r")
2255                 (match_operand:DI 2 "s_register_operand"   "r,r")))]
2256   "TARGET_ARM"
2257   "#"
2258   [(set_attr "length" "8")
2259    (set_attr "predicable" "yes")]
2262 (define_insn "*xordi_zesidi_di"
2263   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2264         (xor:DI (zero_extend:DI
2265                  (match_operand:SI 2 "s_register_operand" "r,r"))
2266                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2267   "TARGET_ARM"
2268   "@
2269    eor%?\\t%Q0, %Q1, %2
2270    #"
2271   [(set_attr "length" "4,8")
2272    (set_attr "predicable" "yes")]
2275 (define_insn "*xordi_sesidi_di"
2276   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2277         (xor:DI (sign_extend:DI
2278                  (match_operand:SI 2 "s_register_operand" "r,r"))
2279                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2280   "TARGET_ARM"
2281   "#"
2282   [(set_attr "length" "8")
2283    (set_attr "predicable" "yes")]
2286 (define_expand "xorsi3"
2287   [(set (match_operand:SI         0 "s_register_operand" "")
2288         (xor:SI (match_operand:SI 1 "s_register_operand" "")
2289                 (match_operand:SI 2 "arm_rhs_operand"  "")))]
2290   "TARGET_EITHER"
2291   "if (TARGET_THUMB)
2292      if (GET_CODE (operands[2]) == CONST_INT)
2293        operands[2] = force_reg (SImode, operands[2]);
2294   "
2297 (define_insn "*arm_xorsi3"
2298   [(set (match_operand:SI         0 "s_register_operand" "=r")
2299         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2300                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2301   "TARGET_ARM"
2302   "eor%?\\t%0, %1, %2"
2303   [(set_attr "predicable" "yes")]
2306 (define_insn "*thumb_xorsi3"
2307   [(set (match_operand:SI         0 "register_operand" "=l")
2308         (xor:SI (match_operand:SI 1 "register_operand" "%0")
2309                 (match_operand:SI 2 "register_operand" "l")))]
2310   "TARGET_THUMB"
2311   "eor\\t%0, %0, %2"
2312   [(set_attr "length" "2")]
2315 (define_insn "*xorsi3_compare0"
2316   [(set (reg:CC_NOOV CC_REGNUM)
2317         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2318                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
2319                          (const_int 0)))
2320    (set (match_operand:SI 0 "s_register_operand" "=r")
2321         (xor:SI (match_dup 1) (match_dup 2)))]
2322   "TARGET_ARM"
2323   "eor%?s\\t%0, %1, %2"
2324   [(set_attr "conds" "set")]
2327 (define_insn "*xorsi3_compare0_scratch"
2328   [(set (reg:CC_NOOV CC_REGNUM)
2329         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2330                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
2331                          (const_int 0)))]
2332   "TARGET_ARM"
2333   "teq%?\\t%0, %1"
2334   [(set_attr "conds" "set")]
2337 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
2338 ; (NOT D) we can sometimes merge the final NOT into one of the following
2339 ; insns.
2341 (define_split
2342   [(set (match_operand:SI 0 "s_register_operand" "")
2343         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2344                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2345                 (match_operand:SI 3 "arm_rhs_operand" "")))
2346    (clobber (match_operand:SI 4 "s_register_operand" ""))]
2347   "TARGET_ARM"
2348   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2349                               (not:SI (match_dup 3))))
2350    (set (match_dup 0) (not:SI (match_dup 4)))]
2351   ""
2354 (define_insn "*andsi_iorsi3_notsi"
2355   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2356         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2357                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2358                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2359   "TARGET_ARM"
2360   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2361   [(set_attr "length" "8")
2362    (set_attr "predicable" "yes")]
2367 ;; Minimum and maximum insns
2369 (define_insn "smaxsi3"
2370   [(set (match_operand:SI          0 "s_register_operand" "=r,r,r")
2371         (smax:SI (match_operand:SI 1 "s_register_operand"  "0,r,?r")
2372                  (match_operand:SI 2 "arm_rhs_operand"    "rI,0,rI")))
2373    (clobber (reg:CC CC_REGNUM))]
2374   "TARGET_ARM"
2375   "@
2376    cmp\\t%1, %2\;movlt\\t%0, %2
2377    cmp\\t%1, %2\;movge\\t%0, %1
2378    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2379   [(set_attr "conds" "clob")
2380    (set_attr "length" "8,8,12")]
2383 (define_insn "sminsi3"
2384   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2385         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2386                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2387    (clobber (reg:CC CC_REGNUM))]
2388   "TARGET_ARM"
2389   "@
2390    cmp\\t%1, %2\;movge\\t%0, %2
2391    cmp\\t%1, %2\;movlt\\t%0, %1
2392    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2393   [(set_attr "conds" "clob")
2394    (set_attr "length" "8,8,12")]
2397 (define_insn "umaxsi3"
2398   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2399         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2400                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2401    (clobber (reg:CC CC_REGNUM))]
2402   "TARGET_ARM"
2403   "@
2404    cmp\\t%1, %2\;movcc\\t%0, %2
2405    cmp\\t%1, %2\;movcs\\t%0, %1
2406    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2407   [(set_attr "conds" "clob")
2408    (set_attr "length" "8,8,12")]
2411 (define_insn "uminsi3"
2412   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2413         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2414                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2415    (clobber (reg:CC CC_REGNUM))]
2416   "TARGET_ARM"
2417   "@
2418    cmp\\t%1, %2\;movcs\\t%0, %2
2419    cmp\\t%1, %2\;movcc\\t%0, %1
2420    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2421   [(set_attr "conds" "clob")
2422    (set_attr "length" "8,8,12")]
2425 (define_insn "*store_minmaxsi"
2426   [(set (match_operand:SI 0 "memory_operand" "=m")
2427         (match_operator:SI 3 "minmax_operator"
2428          [(match_operand:SI 1 "s_register_operand" "r")
2429           (match_operand:SI 2 "s_register_operand" "r")]))
2430    (clobber (reg:CC CC_REGNUM))]
2431   "TARGET_ARM"
2432   "*
2433   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2434                          operands[2]);
2435   output_asm_insn (\"cmp\\t%1, %2\", operands);
2436   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2437   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2438   return \"\";
2439   "
2440   [(set_attr "conds" "clob")
2441    (set_attr "length" "12")
2442    (set_attr "type" "store1")]
2445 ; Reject the frame pointer in operand[1], since reloading this after
2446 ; it has been eliminated can cause carnage.
2447 (define_insn "*minmax_arithsi"
2448   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2449         (match_operator:SI 4 "shiftable_operator"
2450          [(match_operator:SI 5 "minmax_operator"
2451            [(match_operand:SI 2 "s_register_operand" "r,r")
2452             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2453           (match_operand:SI 1 "s_register_operand" "0,?r")]))
2454    (clobber (reg:CC CC_REGNUM))]
2455   "TARGET_ARM
2456    && (GET_CODE (operands[1]) != REG
2457        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2458            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2459   "*
2460   {
2461     enum rtx_code code = GET_CODE (operands[4]);
2463     operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2464                            operands[3]);
2465     output_asm_insn (\"cmp\\t%2, %3\", operands);
2466     output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2467     if (which_alternative != 0 || operands[3] != const0_rtx
2468         || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2469       output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2470     return \"\";
2471   }"
2472   [(set_attr "conds" "clob")
2473    (set_attr "length" "12")]
2477 ;; Shift and rotation insns
2479 (define_expand "ashlsi3"
2480   [(set (match_operand:SI            0 "s_register_operand" "")
2481         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2482                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2483   "TARGET_EITHER"
2484   "
2485   if (GET_CODE (operands[2]) == CONST_INT
2486       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2487     {
2488       emit_insn (gen_movsi (operands[0], const0_rtx));
2489       DONE;
2490     }
2491   "
2494 (define_insn "*thumb_ashlsi3"
2495   [(set (match_operand:SI            0 "register_operand" "=l,l")
2496         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2497                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2498   "TARGET_THUMB"
2499   "lsl\\t%0, %1, %2"
2500   [(set_attr "length" "2")]
2503 (define_expand "ashrsi3"
2504   [(set (match_operand:SI              0 "s_register_operand" "")
2505         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2506                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2507   "TARGET_EITHER"
2508   "
2509   if (GET_CODE (operands[2]) == CONST_INT
2510       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2511     operands[2] = GEN_INT (31);
2512   "
2515 (define_insn "*thumb_ashrsi3"
2516   [(set (match_operand:SI              0 "register_operand" "=l,l")
2517         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2518                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2519   "TARGET_THUMB"
2520   "asr\\t%0, %1, %2"
2521   [(set_attr "length" "2")]
2524 (define_expand "lshrsi3"
2525   [(set (match_operand:SI              0 "s_register_operand" "")
2526         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2527                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2528   "TARGET_EITHER"
2529   "
2530   if (GET_CODE (operands[2]) == CONST_INT
2531       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2532     {
2533       emit_insn (gen_movsi (operands[0], const0_rtx));
2534       DONE;
2535     }
2536   "
2539 (define_insn "*thumb_lshrsi3"
2540   [(set (match_operand:SI              0 "register_operand" "=l,l")
2541         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2542                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2543   "TARGET_THUMB"
2544   "lsr\\t%0, %1, %2"
2545   [(set_attr "length" "2")]
2548 (define_expand "rotlsi3"
2549   [(set (match_operand:SI              0 "s_register_operand" "")
2550         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2551                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2552   "TARGET_ARM"
2553   "
2554   if (GET_CODE (operands[2]) == CONST_INT)
2555     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2556   else
2557     {
2558       rtx reg = gen_reg_rtx (SImode);
2559       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2560       operands[2] = reg;
2561     }
2562   "
2565 (define_expand "rotrsi3"
2566   [(set (match_operand:SI              0 "s_register_operand" "")
2567         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2568                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2569   "TARGET_EITHER"
2570   "
2571   if (TARGET_ARM)
2572     {
2573       if (GET_CODE (operands[2]) == CONST_INT
2574           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2575         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2576     }
2577   else /* TARGET_THUMB */
2578     {
2579       if (GET_CODE (operands [2]) == CONST_INT)
2580         operands [2] = force_reg (SImode, operands[2]);
2581     }
2582   "
2585 (define_insn "*thumb_rotrsi3"
2586   [(set (match_operand:SI              0 "register_operand" "=l")
2587         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2588                      (match_operand:SI 2 "register_operand" "l")))]
2589   "TARGET_THUMB"
2590   "ror\\t%0, %0, %2"
2591   [(set_attr "length" "2")]
2594 (define_insn "*arm_shiftsi3"
2595   [(set (match_operand:SI   0 "s_register_operand" "=r")
2596         (match_operator:SI  3 "shift_operator"
2597          [(match_operand:SI 1 "s_register_operand"  "r")
2598           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2599   "TARGET_ARM"
2600   "mov%?\\t%0, %1%S3"
2601   [(set_attr "predicable" "yes")
2602    (set_attr "shift" "1")
2603    ]
2606 (define_insn "*shiftsi3_compare0"
2607   [(set (reg:CC_NOOV CC_REGNUM)
2608         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2609                           [(match_operand:SI 1 "s_register_operand" "r")
2610                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2611                          (const_int 0)))
2612    (set (match_operand:SI 0 "s_register_operand" "=r")
2613         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2614   "TARGET_ARM"
2615   "mov%?s\\t%0, %1%S3"
2616   [(set_attr "conds" "set")
2617    (set_attr "shift" "1")
2618    ]
2621 (define_insn "*shiftsi3_compare0_scratch"
2622   [(set (reg:CC_NOOV CC_REGNUM)
2623         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2624                           [(match_operand:SI 1 "s_register_operand" "r")
2625                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2626                          (const_int 0)))
2627    (clobber (match_scratch:SI 0 "=r"))]
2628   "TARGET_ARM"
2629   "mov%?s\\t%0, %1%S3"
2630   [(set_attr "conds" "set")
2631    (set_attr "shift" "1")
2632    ]
2635 (define_insn "*notsi_shiftsi"
2636   [(set (match_operand:SI 0 "s_register_operand" "=r")
2637         (not:SI (match_operator:SI 3 "shift_operator"
2638                  [(match_operand:SI 1 "s_register_operand" "r")
2639                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2640   "TARGET_ARM"
2641   "mvn%?\\t%0, %1%S3"
2642   [(set_attr "predicable" "yes")
2643    (set_attr "shift" "1")
2644    ]
2647 (define_insn "*notsi_shiftsi_compare0"
2648   [(set (reg:CC_NOOV CC_REGNUM)
2649         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2650                           [(match_operand:SI 1 "s_register_operand" "r")
2651                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2652                          (const_int 0)))
2653    (set (match_operand:SI 0 "s_register_operand" "=r")
2654         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2655   "TARGET_ARM"
2656   "mvn%?s\\t%0, %1%S3"
2657   [(set_attr "conds" "set")
2658    (set_attr "shift" "1")
2659    ]
2662 (define_insn "*not_shiftsi_compare0_scratch"
2663   [(set (reg:CC_NOOV CC_REGNUM)
2664         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2665                           [(match_operand:SI 1 "s_register_operand" "r")
2666                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2667                          (const_int 0)))
2668    (clobber (match_scratch:SI 0 "=r"))]
2669   "TARGET_ARM"
2670   "mvn%?s\\t%0, %1%S3"
2671   [(set_attr "conds" "set")
2672    (set_attr "shift" "1")
2673   ]
2676 ;; We don't really have extzv, but defining this using shifts helps
2677 ;; to reduce register pressure later on.
2679 (define_expand "extzv"
2680   [(set (match_dup 4)
2681         (ashift:SI (match_operand:SI   1 "register_operand" "")
2682                    (match_operand:SI   2 "const_int_operand" "")))
2683    (set (match_operand:SI              0 "register_operand" "")
2684         (lshiftrt:SI (match_dup 4)
2685                      (match_operand:SI 3 "const_int_operand" "")))]
2686   "TARGET_THUMB"
2687   "
2688   {
2689     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2690     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2691     
2692     operands[3] = GEN_INT (rshift);
2693     
2694     if (lshift == 0)
2695       {
2696         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2697         DONE;
2698       }
2699       
2700     operands[2] = GEN_INT (lshift);
2701     operands[4] = gen_reg_rtx (SImode);
2702   }"
2706 ;; Unary arithmetic insns
2708 (define_expand "negdi2"
2709  [(parallel
2710    [(set (match_operand:DI          0 "s_register_operand" "")
2711           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2712     (clobber (reg:CC CC_REGNUM))])]
2713   "TARGET_EITHER"
2714   "
2715   if (TARGET_THUMB)
2716     {
2717       if (GET_CODE (operands[1]) != REG)
2718         operands[1] = force_reg (SImode, operands[1]);
2719      }
2720   "
2723 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2724 ;; The second alternative is to allow the common case of a *full* overlap.
2725 (define_insn "*arm_negdi2"
2726   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2727         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2728    (clobber (reg:CC CC_REGNUM))]
2729   "TARGET_ARM"
2730   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2731   [(set_attr "conds" "clob")
2732    (set_attr "length" "8")]
2735 (define_insn "*thumb_negdi2"
2736   [(set (match_operand:DI         0 "register_operand" "=&l")
2737         (neg:DI (match_operand:DI 1 "register_operand"   "l")))
2738    (clobber (reg:CC CC_REGNUM))]
2739   "TARGET_THUMB"
2740   "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2741   [(set_attr "length" "6")]
2744 (define_expand "negsi2"
2745   [(set (match_operand:SI         0 "s_register_operand" "")
2746         (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2747   "TARGET_EITHER"
2748   ""
2751 (define_insn "*arm_negsi2"
2752   [(set (match_operand:SI         0 "s_register_operand" "=r")
2753         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2754   "TARGET_ARM"
2755   "rsb%?\\t%0, %1, #0"
2756   [(set_attr "predicable" "yes")]
2759 (define_insn "*thumb_negsi2"
2760   [(set (match_operand:SI         0 "register_operand" "=l")
2761         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2762   "TARGET_THUMB"
2763   "neg\\t%0, %1"
2764   [(set_attr "length" "2")]
2767 (define_insn "negsf2"
2768   [(set (match_operand:SF         0 "s_register_operand" "=f")
2769         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2770   "TARGET_ARM && TARGET_HARD_FLOAT"
2771   "mnf%?s\\t%0, %1"
2772   [(set_attr "type" "ffarith")
2773    (set_attr "predicable" "yes")]
2776 (define_insn "negdf2"
2777   [(set (match_operand:DF         0 "s_register_operand" "=f")
2778         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2779   "TARGET_ARM && TARGET_HARD_FLOAT"
2780   "mnf%?d\\t%0, %1"
2781   [(set_attr "type" "ffarith")
2782    (set_attr "predicable" "yes")]
2785 (define_insn "*negdf_esfdf"
2786   [(set (match_operand:DF 0 "s_register_operand" "=f")
2787         (neg:DF (float_extend:DF
2788                  (match_operand:SF 1 "s_register_operand" "f"))))]
2789   "TARGET_ARM && TARGET_HARD_FLOAT"
2790   "mnf%?d\\t%0, %1"
2791   [(set_attr "type" "ffarith")
2792    (set_attr "predicable" "yes")]
2795 (define_insn "negxf2"
2796   [(set (match_operand:XF 0 "s_register_operand" "=f")
2797         (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2798   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2799   "mnf%?e\\t%0, %1"
2800   [(set_attr "type" "ffarith")
2801    (set_attr "predicable" "yes")]
2804 ;; abssi2 doesn't really clobber the condition codes if a different register
2805 ;; is being set.  To keep things simple, assume during rtl manipulations that
2806 ;; it does, but tell the final scan operator the truth.  Similarly for
2807 ;; (neg (abs...))
2809 (define_insn "abssi2"
2810   [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
2811         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2812    (clobber (reg:CC CC_REGNUM))]
2813   "TARGET_ARM"
2814   "@
2815    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2816    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2817   [(set_attr "conds" "clob,*")
2818    (set_attr "shift" "1")
2819    ;; predicable can't be set based on the variant, so left as no
2820    (set_attr "length" "8")]
2823 (define_insn "*neg_abssi2"
2824   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2825         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2826    (clobber (reg:CC CC_REGNUM))]
2827   "TARGET_ARM"
2828   "@
2829    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2830    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2831   [(set_attr "conds" "clob,*")
2832    (set_attr "shift" "1")
2833    ;; predicable can't be set based on the variant, so left as no
2834    (set_attr "length" "8")]
2837 (define_insn "abssf2"
2838   [(set (match_operand:SF          0 "s_register_operand" "=f")
2839          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2840   "TARGET_ARM && TARGET_HARD_FLOAT"
2841   "abs%?s\\t%0, %1"
2842   [(set_attr "type" "ffarith")
2843    (set_attr "predicable" "yes")]
2846 (define_insn "absdf2"
2847   [(set (match_operand:DF         0 "s_register_operand" "=f")
2848         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2849   "TARGET_ARM && TARGET_HARD_FLOAT"
2850   "abs%?d\\t%0, %1"
2851   [(set_attr "type" "ffarith")
2852    (set_attr "predicable" "yes")]
2855 (define_insn "*absdf_esfdf"
2856   [(set (match_operand:DF 0 "s_register_operand" "=f")
2857         (abs:DF (float_extend:DF
2858                  (match_operand:SF 1 "s_register_operand" "f"))))]
2859   "TARGET_ARM && TARGET_HARD_FLOAT"
2860   "abs%?d\\t%0, %1"
2861   [(set_attr "type" "ffarith")
2862    (set_attr "predicable" "yes")]
2865 (define_insn "absxf2"
2866   [(set (match_operand:XF 0 "s_register_operand" "=f")
2867         (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2868   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2869   "abs%?e\\t%0, %1"
2870   [(set_attr "type" "ffarith")
2871    (set_attr "predicable" "yes")]
2874 (define_insn "sqrtsf2"
2875   [(set (match_operand:SF 0 "s_register_operand" "=f")
2876         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2877   "TARGET_ARM && TARGET_HARD_FLOAT"
2878   "sqt%?s\\t%0, %1"
2879   [(set_attr "type" "float_em")
2880    (set_attr "predicable" "yes")]
2883 (define_insn "sqrtdf2"
2884   [(set (match_operand:DF 0 "s_register_operand" "=f")
2885         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2886   "TARGET_ARM && TARGET_HARD_FLOAT"
2887   "sqt%?d\\t%0, %1"
2888   [(set_attr "type" "float_em")
2889    (set_attr "predicable" "yes")]
2892 (define_insn "*sqrtdf_esfdf"
2893   [(set (match_operand:DF 0 "s_register_operand" "=f")
2894         (sqrt:DF (float_extend:DF
2895                   (match_operand:SF 1 "s_register_operand" "f"))))]
2896   "TARGET_ARM && TARGET_HARD_FLOAT"
2897   "sqt%?d\\t%0, %1"
2898   [(set_attr "type" "float_em")
2899    (set_attr "predicable" "yes")]
2902 (define_insn "sqrtxf2"
2903   [(set (match_operand:XF 0 "s_register_operand" "=f")
2904         (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2905   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2906   "sqt%?e\\t%0, %1"
2907   [(set_attr "type" "float_em")
2908    (set_attr "predicable" "yes")]
2911 ;; SIN COS TAN and family are always emulated, so it's probably better
2912 ;; to always call a library function.
2913 ;(define_insn "sinsf2"
2914 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2915 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2916 ;                   UNSPEC_SIN))]
2917 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2918 ;  "sin%?s\\t%0, %1"
2919 ;[(set_attr "type" "float_em")])
2921 ;(define_insn "sindf2"
2922 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2923 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2924 ;                   UNSPEC_SIN))]
2925 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2926 ;  "sin%?d\\t%0, %1"
2927 ;[(set_attr "type" "float_em")])
2929 ;(define_insn "*sindf_esfdf"
2930 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2931 ;       (unspec:DF [(float_extend:DF
2932 ;                    (match_operand:SF 1 "s_register_operand" "f"))]
2933 ;                   UNSPEC_SIN))]
2934 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2935 ;  "sin%?d\\t%0, %1"
2936 ;[(set_attr "type" "float_em")])
2938 ;(define_insn "sinxf2"
2939 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2940 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2941 ;                  UNSPEC_SIN))]
2942 ;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2943 ;  "sin%?e\\t%0, %1"
2944 ;[(set_attr "type" "float_em")])
2946 ;(define_insn "cossf2"
2947 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2948 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2949 ;                  UNSPEC_COS))]
2950 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2951 ;  "cos%?s\\t%0, %1"
2952 ;[(set_attr "type" "float_em")])
2954 ;(define_insn "cosdf2"
2955 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2956 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2957 ;                  UNSPEC_COS))]
2958 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2959 ;  "cos%?d\\t%0, %1"
2960 ;[(set_attr "type" "float_em")])
2962 ;(define_insn "*cosdf_esfdf"
2963 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2964 ;       (unspec:DF [(float_extend:DF
2965 ;                    (match_operand:SF 1 "s_register_operand" "f"))]
2966 ;                  UNSPEC_COS))]
2967 ;  "TARGET_ARM && TARGET_HARD_FLOAT"
2968 ;  "cos%?d\\t%0, %1"
2969 ;[(set_attr "type" "float_em")])
2971 ;(define_insn "cosxf2"
2972 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2973 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2974 ;                  UNSEPC_COS))]
2975 ;  "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2976 ;  "cos%?e\\t%0, %1"
2977 ;[(set_attr "type" "float_em")])
2979 (define_insn_and_split "one_cmpldi2"
2980   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2981         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2982   "TARGET_ARM"
2983   "#"
2984   "TARGET_ARM && reload_completed"
2985   [(set (match_dup 0) (not:SI (match_dup 1)))
2986    (set (match_dup 2) (not:SI (match_dup 3)))]
2987   "
2988   {
2989     operands[2] = gen_highpart (SImode, operands[0]);
2990     operands[0] = gen_lowpart (SImode, operands[0]);
2991     operands[3] = gen_highpart (SImode, operands[1]);
2992     operands[1] = gen_lowpart (SImode, operands[1]);
2993   }"
2994   [(set_attr "length" "8")
2995    (set_attr "predicable" "yes")]
2998 (define_expand "one_cmplsi2"
2999   [(set (match_operand:SI         0 "s_register_operand" "")
3000         (not:SI (match_operand:SI 1 "s_register_operand" "")))]
3001   "TARGET_EITHER"
3002   ""
3005 (define_insn "*arm_one_cmplsi2"
3006   [(set (match_operand:SI         0 "s_register_operand" "=r")
3007         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
3008   "TARGET_ARM"
3009   "mvn%?\\t%0, %1"
3010   [(set_attr "predicable" "yes")]
3013 (define_insn "*thumb_one_cmplsi2"
3014   [(set (match_operand:SI         0 "register_operand" "=l")
3015         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
3016   "TARGET_THUMB"
3017   "mvn\\t%0, %1"
3018   [(set_attr "length" "2")]
3021 (define_insn "*notsi_compare0"
3022   [(set (reg:CC_NOOV CC_REGNUM)
3023         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3024                          (const_int 0)))
3025    (set (match_operand:SI 0 "s_register_operand" "=r")
3026         (not:SI (match_dup 1)))]
3027   "TARGET_ARM"
3028   "mvn%?s\\t%0, %1"
3029   [(set_attr "conds" "set")]
3032 (define_insn "*notsi_compare0_scratch"
3033   [(set (reg:CC_NOOV CC_REGNUM)
3034         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3035                          (const_int 0)))
3036    (clobber (match_scratch:SI 0 "=r"))]
3037   "TARGET_ARM"
3038   "mvn%?s\\t%0, %1"
3039   [(set_attr "conds" "set")]
3042 ;; Fixed <--> Floating conversion insns
3044 (define_insn "floatsisf2"
3045   [(set (match_operand:SF           0 "s_register_operand" "=f")
3046         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3047   "TARGET_ARM && TARGET_HARD_FLOAT"
3048   "flt%?s\\t%0, %1"
3049   [(set_attr "type" "r_2_f")
3050    (set_attr "predicable" "yes")]
3053 (define_insn "floatsidf2"
3054   [(set (match_operand:DF           0 "s_register_operand" "=f")
3055         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3056   "TARGET_ARM && TARGET_HARD_FLOAT"
3057   "flt%?d\\t%0, %1"
3058   [(set_attr "type" "r_2_f")
3059    (set_attr "predicable" "yes")]
3062 (define_insn "floatsixf2"
3063   [(set (match_operand:XF 0 "s_register_operand" "=f")
3064         (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3065   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3066   "flt%?e\\t%0, %1"
3067   [(set_attr "type" "r_2_f")
3068    (set_attr "predicable" "yes")]
3071 (define_insn "fix_truncsfsi2"
3072   [(set (match_operand:SI         0 "s_register_operand" "=r")
3073         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3074   "TARGET_ARM && TARGET_HARD_FLOAT"
3075   "fix%?z\\t%0, %1"
3076   [(set_attr "type" "f_2_r")
3077    (set_attr "predicable" "yes")]
3080 (define_insn "fix_truncdfsi2"
3081   [(set (match_operand:SI         0 "s_register_operand" "=r")
3082         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3083   "TARGET_ARM && TARGET_HARD_FLOAT"
3084   "fix%?z\\t%0, %1"
3085   [(set_attr "type" "f_2_r")
3086    (set_attr "predicable" "yes")]
3089 (define_insn "fix_truncxfsi2"
3090   [(set (match_operand:SI 0 "s_register_operand" "=r")
3091         (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3092   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3093   "fix%?z\\t%0, %1"
3094   [(set_attr "type" "f_2_r")
3095    (set_attr "predicable" "yes")]
3098 ;; Truncation insns
3100 (define_insn "truncdfsf2"
3101   [(set (match_operand:SF 0 "s_register_operand" "=f")
3102         (float_truncate:SF
3103          (match_operand:DF 1 "s_register_operand" "f")))]
3104   "TARGET_ARM && TARGET_HARD_FLOAT"
3105   "mvf%?s\\t%0, %1"
3106   [(set_attr "type" "ffarith")
3107    (set_attr "predicable" "yes")]
3110 (define_insn "truncxfsf2"
3111   [(set (match_operand:SF 0 "s_register_operand" "=f")
3112         (float_truncate:SF
3113          (match_operand:XF 1 "s_register_operand" "f")))]
3114   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3115   "mvf%?s\\t%0, %1"
3116   [(set_attr "type" "ffarith")
3117    (set_attr "predicable" "yes")]
3120 (define_insn "truncxfdf2"
3121   [(set (match_operand:DF 0 "s_register_operand" "=f")
3122         (float_truncate:DF
3123          (match_operand:XF 1 "s_register_operand" "f")))]
3124   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3125   "mvf%?d\\t%0, %1"
3126   [(set_attr "type" "ffarith")
3127    (set_attr "predicable" "yes")]
3130 ;; Zero and sign extension instructions.
3132 (define_insn "zero_extendsidi2"
3133   [(set (match_operand:DI 0 "s_register_operand" "=r")
3134         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3135   "TARGET_ARM"
3136   "*
3137     if (REGNO (operands[1])
3138         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3139       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3140     return \"mov%?\\t%R0, #0\";
3141   "
3142   [(set_attr "length" "8")
3143    (set_attr "predicable" "yes")]
3146 (define_insn "zero_extendqidi2"
3147   [(set (match_operand:DI                 0 "s_register_operand"  "=r,r")
3148         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3149   "TARGET_ARM"
3150   "@
3151    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3152    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3153   [(set_attr "length" "8")
3154    (set_attr "predicable" "yes")
3155    (set_attr "type" "*,load")
3156    (set_attr "pool_range" "*,4092")
3157    (set_attr "neg_pool_range" "*,4084")]
3160 (define_insn "extendsidi2"
3161   [(set (match_operand:DI 0 "s_register_operand" "=r")
3162         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3163   "TARGET_ARM"
3164   "*
3165     if (REGNO (operands[1])
3166         != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3167       output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3168     return \"mov%?\\t%R0, %Q0, asr #31\";
3169   "
3170   [(set_attr "length" "8")
3171    (set_attr "shift" "1")
3172    (set_attr "predicable" "yes")]
3175 (define_expand "zero_extendhisi2"
3176   [(set (match_dup 2)
3177         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3178                    (const_int 16)))
3179    (set (match_operand:SI 0 "s_register_operand" "")
3180         (lshiftrt:SI (match_dup 2) (const_int 16)))]
3181   "TARGET_EITHER"
3182   "
3183   {
3184     if (TARGET_ARM)
3185       {
3186         if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3187           {
3188            /* Note: We do not have to worry about TARGET_MMU_TRAPS
3189               here because the insn below will generate an LDRH instruction
3190               rather than an LDR instruction, so we cannot get an unaligned
3191               word access.  */
3192             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3193                                     gen_rtx_ZERO_EXTEND (SImode,
3194                                                          operands[1])));
3195             DONE;
3196           }
3197         if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3198           {
3199             emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3200             DONE;
3201           }
3202         if (!s_register_operand (operands[1], HImode))
3203           operands[1] = copy_to_mode_reg (HImode, operands[1]);
3204         operands[1] = gen_lowpart (SImode, operands[1]);
3205         operands[2] = gen_reg_rtx (SImode);
3206       }
3207     else /* TARGET_THUMB */
3208       {
3209         if (GET_CODE (operands[1]) == MEM)
3210           {
3211             rtx tmp;
3213             tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3214             tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3215             emit_insn (tmp);
3216           }
3217         else
3218           {
3219             rtx ops[3];
3220             
3221             if (!s_register_operand (operands[1], HImode))
3222               operands[1] = copy_to_mode_reg (HImode, operands[1]);
3223             operands[1] = gen_lowpart (SImode, operands[1]);
3224             operands[2] = gen_reg_rtx (SImode);
3225             
3226             ops[0] = operands[2];
3227             ops[1] = operands[1];
3228             ops[2] = GEN_INT (16);
3229             
3230             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3231                                     gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3233             ops[0] = operands[0];
3234             ops[1] = operands[2];
3235             ops[2] = GEN_INT (16);
3237             emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3238                                     gen_rtx_LSHIFTRT (SImode, ops[1],
3239                                                       ops[2])));
3240           }
3241         DONE; 
3242       }
3243   }"
3246 (define_insn "*thumb_zero_extendhisi2"
3247   [(set (match_operand:SI                 0 "register_operand" "=l")
3248         (zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3249   "TARGET_THUMB"
3250   "*
3251   rtx mem = XEXP (operands[1], 0);
3253   if (GET_CODE (mem) == CONST)
3254     mem = XEXP (mem, 0);
3255     
3256   if (GET_CODE (mem) == LABEL_REF)
3257     return \"ldr\\t%0, %1\";
3258     
3259   if (GET_CODE (mem) == PLUS)
3260     {
3261       rtx a = XEXP (mem, 0);
3262       rtx b = XEXP (mem, 1);
3264       /* This can happen due to bugs in reload.  */
3265       if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3266         {
3267           rtx ops[2];
3268           ops[0] = operands[0];
3269           ops[1] = a;
3270       
3271           output_asm_insn (\"mov        %0, %1\", ops);
3273           XEXP (mem, 0) = operands[0];
3274        }
3276       else if (   GET_CODE (a) == LABEL_REF
3277                && GET_CODE (b) == CONST_INT)
3278         return \"ldr\\t%0, %1\";
3279     }
3280     
3281   return \"ldrh\\t%0, %1\";
3282   "
3283   [(set_attr "length" "4")
3284    (set_attr "type" "load")
3285    (set_attr "pool_range" "60")]
3288 (define_insn "*arm_zero_extendhisi2"
3289   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3290         (zero_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3291   "TARGET_ARM && arm_arch4"
3292   "ldr%?h\\t%0, %1"
3293   [(set_attr "type" "load")
3294    (set_attr "predicable" "yes")
3295    (set_attr "pool_range" "256")
3296    (set_attr "neg_pool_range" "244")]
3299 (define_split
3300   [(set (match_operand:SI 0 "s_register_operand" "")
3301         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3302    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3303   "TARGET_ARM && (!arm_arch4)"
3304   [(set (match_dup 2) (match_dup 1))
3305    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3306   "
3307   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3308     FAIL;
3309   "
3312 (define_split
3313   [(set (match_operand:SI 0 "s_register_operand" "")
3314         (match_operator:SI 3 "shiftable_operator"
3315          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3316           (match_operand:SI 4 "s_register_operand" "")]))
3317    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3318   "TARGET_ARM && (!arm_arch4)"
3319   [(set (match_dup 2) (match_dup 1))
3320    (set (match_dup 0)
3321         (match_op_dup 3
3322          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3323   "
3324   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3325     FAIL;
3326   "
3329 (define_expand "zero_extendqisi2"
3330   [(set (match_operand:SI 0 "s_register_operand" "")
3331         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3332   "TARGET_EITHER"
3333   "
3334   if (GET_CODE (operands[1]) != MEM)
3335     {
3336       if (TARGET_ARM)
3337         {
3338           emit_insn (gen_andsi3 (operands[0],
3339                                  gen_lowpart (SImode, operands[1]),
3340                                  GEN_INT (255)));
3341         }
3342       else /* TARGET_THUMB */
3343         {
3344           rtx temp = gen_reg_rtx (SImode);
3345           rtx ops[3];
3346           
3347           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3348           operands[1] = gen_lowpart (SImode, operands[1]);
3350           ops[0] = temp;
3351           ops[1] = operands[1];
3352           ops[2] = GEN_INT (24);
3354           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3355                                   gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3356           
3357           ops[0] = operands[0];
3358           ops[1] = temp;
3359           ops[2] = GEN_INT (24);
3361           emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3362                                   gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3363         }
3364       DONE;
3365     }
3366   "
3369 (define_insn "*thumb_zero_extendqisi2"
3370   [(set (match_operand:SI                 0 "register_operand" "=l")
3371         (zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3372   "TARGET_THUMB"
3373   "ldrb\\t%0, %1"
3374   [(set_attr "length" "2")
3375    (set_attr "type" "load")
3376    (set_attr "pool_range" "32")]
3379 (define_insn "*arm_zero_extendqisi2"
3380   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3381         (zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3382   "TARGET_ARM"
3383   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3384   [(set_attr "type" "load")
3385    (set_attr "predicable" "yes")
3386    (set_attr "pool_range" "4096")
3387    (set_attr "neg_pool_range" "4084")]
3390 (define_split
3391   [(set (match_operand:SI 0 "s_register_operand" "")
3392         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3393    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3394   "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3395   [(set (match_dup 2) (match_dup 1))
3396    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3397   ""
3400 (define_insn "*compareqi_eq0"
3401   [(set (reg:CC_Z CC_REGNUM)
3402         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3403                          (const_int 0)))]
3404   "TARGET_ARM"
3405   "tst\\t%0, #255"
3406   [(set_attr "conds" "set")]
3409 (define_expand "extendhisi2"
3410   [(set (match_dup 2)
3411         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3412                    (const_int 16)))
3413    (set (match_operand:SI 0 "s_register_operand" "")
3414         (ashiftrt:SI (match_dup 2)
3415                      (const_int 16)))]
3416   "TARGET_EITHER"
3417   "
3418   {
3419     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3420       {
3421        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3422           here because the insn below will generate an LDRH instruction
3423           rather than an LDR instruction, so we cannot get an unaligned
3424           word access.  */
3425         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3426                    gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3427         DONE;
3428       }
3430     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3431       {
3432         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3433         DONE;
3434       }
3435     if (!s_register_operand (operands[1], HImode))
3436       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3437     operands[1] = gen_lowpart (SImode, operands[1]);
3438     operands[2] = gen_reg_rtx (SImode);
3440     if (TARGET_THUMB)
3441       {
3442         rtx ops[3];
3443         
3444         ops[0] = operands[2];
3445         ops[1] = operands[1];
3446         ops[2] = GEN_INT (16);
3447         
3448         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3449                                 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3450             
3451         ops[0] = operands[0];
3452         ops[1] = operands[2];
3453         ops[2] = GEN_INT (16);
3454         
3455         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3456                                 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3457         
3458         DONE;
3459       }
3460   }"
3463 (define_insn "*thumb_extendhisi2_insn"
3464   [(set (match_operand:SI                 0 "register_operand" "=l")
3465         (sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3466    (clobber (match_scratch:SI             2                   "=&l"))]
3467   "TARGET_THUMB"
3468   "*
3469   {
3470     rtx ops[4];
3471     rtx mem = XEXP (operands[1], 0);
3473     /* This code used to try to use 'V', and fix the address only if it was
3474        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3475        range of QImode offsets, and offsettable_address_p does a QImode
3476        address check.  */
3477        
3478     if (GET_CODE (mem) == CONST)
3479       mem = XEXP (mem, 0);
3480     
3481     if (GET_CODE (mem) == LABEL_REF)
3482       return \"ldr\\t%0, %1\";
3483     
3484     if (GET_CODE (mem) == PLUS)
3485       {
3486         rtx a = XEXP (mem, 0);
3487         rtx b = XEXP (mem, 1);
3489         if (GET_CODE (a) == LABEL_REF
3490             && GET_CODE (b) == CONST_INT)
3491           return \"ldr\\t%0, %1\";
3493         if (GET_CODE (b) == REG)
3494           return \"ldrsh\\t%0, %1\";
3495           
3496         ops[1] = a;
3497         ops[2] = b;
3498       }
3499     else
3500       {
3501         ops[1] = mem;
3502         ops[2] = const0_rtx;
3503       }
3504       
3505     if (GET_CODE (ops[1]) != REG)
3506       {
3507         debug_rtx (ops[1]);
3508         abort ();
3509       }
3511     ops[0] = operands[0];
3512     ops[3] = operands[2];
3513     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3514     return \"\";
3515   }"
3516   [(set_attr "length" "4")
3517    (set_attr "type" "load")
3518    (set_attr "pool_range" "1020")]
3521 (define_expand "extendhisi2_mem"
3522   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3523    (set (match_dup 3)
3524         (zero_extend:SI (match_dup 7)))
3525    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3526    (set (match_operand:SI 0 "" "")
3527         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3528   "TARGET_ARM"
3529   "
3530   {
3531     rtx mem1, mem2;
3532     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3534     mem1 = gen_rtx_MEM (QImode, addr);
3535     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3536     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3537     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3538     operands[0] = gen_lowpart (SImode, operands[0]);
3539     operands[1] = mem1;
3540     operands[2] = gen_reg_rtx (SImode);
3541     operands[3] = gen_reg_rtx (SImode);
3542     operands[6] = gen_reg_rtx (SImode);
3543     operands[7] = mem2;
3545     if (BYTES_BIG_ENDIAN)
3546       {
3547         operands[4] = operands[2];
3548         operands[5] = operands[3];
3549       }
3550     else
3551       {
3552         operands[4] = operands[3];
3553         operands[5] = operands[2];
3554       }
3555   }"
3558 (define_insn "*arm_extendhisi_insn"
3559   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3560         (sign_extend:SI (match_operand:HI 1 "memory_operand"      "m")))]
3561   "TARGET_ARM && arm_arch4"
3562   "ldr%?sh\\t%0, %1"
3563   [(set_attr "type" "load")
3564    (set_attr "predicable" "yes")
3565    (set_attr "pool_range" "256")
3566    (set_attr "neg_pool_range" "244")]
3569 (define_split
3570   [(set (match_operand:SI                 0 "s_register_operand" "")
3571         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3572    (clobber (match_operand:SI             2 "s_register_operand" ""))]
3573   "TARGET_ARM && (!arm_arch4)"
3574   [(set (match_dup 2) (match_dup 1))
3575    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3576   "
3577   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3578     FAIL;
3579   "
3582 (define_split
3583   [(set (match_operand:SI                   0 "s_register_operand" "")
3584         (match_operator:SI                  3 "shiftable_operator"
3585          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3586           (match_operand:SI                 4 "s_register_operand" "")]))
3587    (clobber (match_operand:SI               2 "s_register_operand" ""))]
3588   "TARGET_ARM && (!arm_arch4)"
3589   [(set (match_dup 2) (match_dup 1))
3590    (set (match_dup 0)
3591         (match_op_dup 3
3592          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3593   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3594      FAIL;
3595   "
3598 (define_expand "extendqihi2"
3599   [(set (match_dup 2)
3600         (ashift:SI (match_operand:QI 1 "general_operand" "")
3601                    (const_int 24)))
3602    (set (match_operand:HI 0 "s_register_operand" "")
3603         (ashiftrt:SI (match_dup 2)
3604                      (const_int 24)))]
3605   "TARGET_ARM"
3606   "
3607   {
3608     if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3609       {
3610         emit_insn (gen_rtx_SET (VOIDmode,
3611                                 operands[0],
3612                                 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3613         DONE;
3614       }
3615     if (!s_register_operand (operands[1], QImode))
3616       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3617     operands[0] = gen_lowpart (SImode, operands[0]);
3618     operands[1] = gen_lowpart (SImode, operands[1]);
3619     operands[2] = gen_reg_rtx (SImode);
3620   }"
3623 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3624 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3625 (define_insn "*extendqihi_insn"
3626   [(set (match_operand:HI                 0 "s_register_operand" "=r")
3627         (sign_extend:HI (match_operand:QI 1 "memory_operand"      "m")))]
3628   "TARGET_ARM && arm_arch4"
3629   "*
3630   /* If the address is invalid, this will split the instruction into two. */
3631   if (bad_signed_byte_operand (operands[1], VOIDmode))
3632     return \"#\";
3633   return \"ldr%?sb\\t%0, %1\";
3634   "
3635   [(set_attr "type" "load")
3636    (set_attr "predicable" "yes")
3637    (set_attr "length" "8")
3638    (set_attr "pool_range" "256")
3639    (set_attr "neg_pool_range" "244")]
3642 (define_split
3643   [(set (match_operand:HI 0 "s_register_operand" "")
3644         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3645   "TARGET_ARM && arm_arch4 && reload_completed"
3646   [(set (match_dup 3) (match_dup 1))
3647    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3648   "
3649   {
3650     HOST_WIDE_INT offset;
3652     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3653     operands[2] = gen_rtx_MEM (QImode, operands[3]);
3654     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3655     operands[1] = XEXP (operands[1], 0);
3656     if (GET_CODE (operands[1]) == PLUS
3657         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3658         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3659              || const_ok_for_arm (-offset)))
3660       {
3661         HOST_WIDE_INT low = (offset > 0
3662                              ? (offset & 0xff) : -((-offset) & 0xff));
3663         XEXP (operands[2], 0) = plus_constant (operands[3], low);
3664         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3665       }
3666     /* Ensure the sum is in correct canonical form */
3667     else if (GET_CODE (operands[1]) == PLUS
3668              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3669              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3670       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3671                                            XEXP (operands[1], 1),
3672                                            XEXP (operands[1], 0));
3673   }"
3676 (define_expand "extendqisi2"
3677   [(set (match_dup 2)
3678         (ashift:SI (match_operand:QI 1 "general_operand" "")
3679                    (const_int 24)))
3680    (set (match_operand:SI 0 "s_register_operand" "")
3681         (ashiftrt:SI (match_dup 2)
3682                      (const_int 24)))]
3683   "TARGET_EITHER"
3684   "
3685   {
3686     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3687       {
3688         emit_insn (gen_rtx_SET (VOIDmode,
3689                                 operands[0],
3690                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3691         DONE;
3692       }
3693     if (!s_register_operand (operands[1], QImode))
3694       operands[1] = copy_to_mode_reg (QImode, operands[1]);
3695     operands[1] = gen_lowpart (SImode, operands[1]);
3696     operands[2] = gen_reg_rtx (SImode);
3697     
3698     if (TARGET_THUMB)
3699       {
3700         rtx ops[3];
3701         
3702         ops[0] = operands[2];
3703         ops[1] = operands[1];
3704         ops[2] = GEN_INT (24);
3705         
3706         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3707                    gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3709         ops[0] = operands[0];
3710         ops[1] = operands[2];
3711         ops[2] = GEN_INT (24);
3712         
3713         emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3714                    gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3715         
3716         DONE;
3717       }
3718   }"
3721 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3722 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3723 (define_insn "*arm_extendqisi_insn"
3724   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3725         (sign_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3726   "TARGET_ARM && arm_arch4"
3727   "*
3728   /* If the address is invalid, this will split the instruction into two. */
3729   if (bad_signed_byte_operand (operands[1], VOIDmode))
3730     return \"#\";
3731   return \"ldr%?sb\\t%0, %1\";
3732   "
3733   [(set_attr "type" "load")
3734    (set_attr "predicable" "yes")
3735    (set_attr "length" "8")
3736    (set_attr "pool_range" "256")
3737    (set_attr "neg_pool_range" "244")]
3740 (define_split
3741   [(set (match_operand:SI 0 "s_register_operand" "")
3742         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3743   "TARGET_ARM && arm_arch4 && reload_completed"
3744   [(set (match_dup 0) (match_dup 1))
3745    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3746   "
3747   {
3748     HOST_WIDE_INT offset;
3750     operands[2] = gen_rtx_MEM (QImode, operands[0]);
3751     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3752     operands[1] = XEXP (operands[1], 0);
3753     if (GET_CODE (operands[1]) == PLUS
3754         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3755         && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3756              || const_ok_for_arm (-offset)))
3757       {
3758         HOST_WIDE_INT low = (offset > 0
3759                              ? (offset & 0xff) : -((-offset) & 0xff));
3760         XEXP (operands[2], 0) = plus_constant (operands[0], low);
3761         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3762       }
3763     /* Ensure the sum is in correct canonical form */
3764     else if (GET_CODE (operands[1]) == PLUS
3765              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3766              && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3767       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3768                                            XEXP (operands[1], 1),
3769                                            XEXP (operands[1], 0));
3770   }"
3773 (define_insn "*thumb_extendqisi2_insn"
3774   [(set (match_operand:SI                 0 "register_operand" "=l,l")
3775         (sign_extend:SI (match_operand:QI 1 "memory_operand"    "V,m")))]
3776   "TARGET_THUMB"
3777   "*
3778   {
3779     rtx ops[3];
3780     rtx mem = XEXP (operands[1], 0);
3781     
3782     if (GET_CODE (mem) == CONST)
3783       mem = XEXP (mem, 0);
3784     
3785     if (GET_CODE (mem) == LABEL_REF)
3786       return \"ldr\\t%0, %1\";
3788     if (GET_CODE (mem) == PLUS
3789         && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3790       return \"ldr\\t%0, %1\";
3791       
3792     if (which_alternative == 0)
3793       return \"ldrsb\\t%0, %1\";
3794       
3795     ops[0] = operands[0];
3796     
3797     if (GET_CODE (mem) == PLUS)
3798       {
3799         rtx a = XEXP (mem, 0);
3800         rtx b = XEXP (mem, 1);
3801         
3802         ops[1] = a;
3803         ops[2] = b;
3805         if (GET_CODE (a) == REG)
3806           {
3807             if (GET_CODE (b) == REG)
3808               output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3809             else if (REGNO (a) == REGNO (ops[0]))
3810               {
3811                 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3812                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3813                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3814               }
3815             else
3816               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3817           }
3818         else if (GET_CODE (b) != REG)
3819           abort ();
3820         else
3821           {
3822             if (REGNO (b) == REGNO (ops[0]))
3823               {
3824                 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3825                 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3826                 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3827               }
3828             else
3829               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3830           }
3831       }
3832     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3833       {
3834         output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3835         output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3836         output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3837       }
3838     else
3839       {
3840         ops[1] = mem;
3841         ops[2] = const0_rtx;
3842         
3843         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3844       }
3845     return \"\";
3846   }"
3847   [(set_attr "length" "2,6")
3848    (set_attr "type" "load,load")
3849    (set_attr "pool_range" "32,32")]
3852 (define_insn "extendsfdf2"
3853   [(set (match_operand:DF                  0 "s_register_operand" "=f")
3854         (float_extend:DF (match_operand:SF 1 "s_register_operand"  "f")))]
3855   "TARGET_ARM && TARGET_HARD_FLOAT"
3856   "mvf%?d\\t%0, %1"
3857   [(set_attr "type" "ffarith")
3858    (set_attr "predicable" "yes")]
3861 (define_insn "extendsfxf2"
3862   [(set (match_operand:XF 0 "s_register_operand" "=f")
3863         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3864   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3865   "mvf%?e\\t%0, %1"
3866   [(set_attr "type" "ffarith")
3867    (set_attr "predicable" "yes")]
3870 (define_insn "extenddfxf2"
3871   [(set (match_operand:XF 0 "s_register_operand" "=f")
3872         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3873   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3874   "mvf%?e\\t%0, %1"
3875   [(set_attr "type" "ffarith")
3876    (set_attr "predicable" "yes")]
3880 ;; Move insns (including loads and stores)
3882 ;; XXX Just some ideas about movti.
3883 ;; I don't think these are a good idea on the arm, there just aren't enough
3884 ;; registers
3885 ;;(define_expand "loadti"
3886 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3887 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3888 ;;  "" "")
3890 ;;(define_expand "storeti"
3891 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3892 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3893 ;;  "" "")
3895 ;;(define_expand "movti"
3896 ;;  [(set (match_operand:TI 0 "general_operand" "")
3897 ;;      (match_operand:TI 1 "general_operand" ""))]
3898 ;;  ""
3899 ;;  "
3901 ;;  rtx insn;
3903 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3904 ;;    operands[1] = copy_to_reg (operands[1]);
3905 ;;  if (GET_CODE (operands[0]) == MEM)
3906 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3907 ;;  else if (GET_CODE (operands[1]) == MEM)
3908 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3909 ;;  else
3910 ;;    FAIL;
3912 ;;  emit_insn (insn);
3913 ;;  DONE;
3914 ;;}")
3916 ;; Recognise garbage generated above.
3918 ;;(define_insn ""
3919 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3920 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3921 ;;  ""
3922 ;;  "*
3923 ;;  {
3924 ;;    register mem = (which_alternative < 3);
3925 ;;    register const char *template;
3927 ;;    operands[mem] = XEXP (operands[mem], 0);
3928 ;;    switch (which_alternative)
3929 ;;      {
3930 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3931 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
3932 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
3933 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
3934 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
3935 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
3936 ;;      }
3937 ;;    output_asm_insn (template, operands);
3938 ;;    return \"\";
3939 ;;  }")
3941 (define_expand "movdi"
3942   [(set (match_operand:DI 0 "general_operand" "")
3943         (match_operand:DI 1 "general_operand" ""))]
3944   "TARGET_EITHER"
3945   "
3946   if (TARGET_THUMB)
3947     {
3948       if (!no_new_pseudos)
3949         {
3950           if (GET_CODE (operands[0]) != REG)
3951             operands[1] = force_reg (DImode, operands[1]);
3952         }
3953     }
3954   "
3957 (define_insn "*arm_movdi"
3958   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3959         (match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
3960   "TARGET_ARM"
3961   "*
3962   return (output_move_double (operands));
3963   "
3964   [(set_attr "length" "8")
3965    (set_attr "type" "*,load,store2")
3966    (set_attr "pool_range" "*,1020,*")
3967    (set_attr "neg_pool_range" "*,1008,*")]
3970 ;;; ??? This should have alternatives for constants.
3971 ;;; ??? This was originally identical to the movdf_insn pattern.
3972 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3973 ;;; thumb_reorg with a memory reference.
3974 (define_insn "*thumb_movdi_insn"
3975   [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3976         (match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
3977   "TARGET_THUMB
3978    && (   register_operand (operands[0], DImode)
3979        || register_operand (operands[1], DImode))"
3980   "*
3981   {
3982   switch (which_alternative)
3983     {
3984     default:
3985     case 0:
3986       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3987         return \"add\\t%0,  %1,  #0\;add\\t%H0, %H1, #0\";
3988       return   \"add\\t%H0, %H1, #0\;add\\t%0,  %1,  #0\";
3989     case 1:
3990       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3991     case 2:
3992       operands[1] = GEN_INT (- INTVAL (operands[1]));
3993       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3994     case 3:
3995       return \"ldmia\\t%1, {%0, %H0}\";
3996     case 4:
3997       return \"stmia\\t%0, {%1, %H1}\";
3998     case 5:
3999       return thumb_load_double_from_address (operands);
4000     case 6:
4001       operands[2] = gen_rtx (MEM, SImode,
4002                              plus_constant (XEXP (operands[0], 0), 4));
4003       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4004       return \"\";
4005     case 7:
4006       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4007         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4008       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4009     }
4010   }"
4011   [(set_attr "length" "4,4,6,2,2,6,4,4")
4012    (set_attr "type" "*,*,*,load,store2,load,store2,*")
4013    (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4016 (define_expand "movsi"
4017   [(set (match_operand:SI 0 "general_operand" "")
4018         (match_operand:SI 1 "general_operand" ""))]
4019   "TARGET_EITHER"
4020   "
4021   if (TARGET_ARM)
4022     {
4023       /* Everything except mem = const or mem = mem can be done easily */
4024       if (GET_CODE (operands[0]) == MEM)
4025         operands[1] = force_reg (SImode, operands[1]);
4026       if (GET_CODE (operands[1]) == CONST_INT
4027           && !(const_ok_for_arm (INTVAL (operands[1]))
4028                || const_ok_for_arm (~INTVAL (operands[1]))))
4029         {
4030            arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4031                               NULL_RTX,
4032                               (no_new_pseudos ? 0
4033                                : preserve_subexpressions_p ()));
4034           DONE;
4035         }
4036     }
4037   else /* TARGET_THUMB.... */
4038     {
4039       if (!no_new_pseudos)
4040         {
4041           if (GET_CODE (operands[0]) != REG)
4042             operands[1] = force_reg (SImode, operands[1]);
4043         }
4044     }
4045     
4046   if (flag_pic
4047       && (CONSTANT_P (operands[1])
4048          || symbol_mentioned_p (operands[1])
4049          || label_mentioned_p (operands[1])))
4050     operands[1] = legitimize_pic_address (operands[1], SImode,
4051                                           (no_new_pseudos ? operands[0] : 0));
4052   "
4055 (define_insn "*arm_movsi_insn"
4056   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4057         (match_operand:SI 1 "general_operand"      "rI,K,mi,r"))]
4058   "TARGET_ARM
4059    && (   register_operand (operands[0], SImode)
4060        || register_operand (operands[1], SImode))"
4061   "@
4062    mov%?\\t%0, %1
4063    mvn%?\\t%0, #%B1
4064    ldr%?\\t%0, %1
4065    str%?\\t%1, %0"
4066   [(set_attr "type" "*,*,load,store1")
4067    (set_attr "predicable" "yes")
4068    (set_attr "pool_range" "*,*,4096,*")
4069    (set_attr "neg_pool_range" "*,*,4084,*")]
4072 (define_split
4073   [(set (match_operand:SI 0 "s_register_operand" "")
4074         (match_operand:SI 1 "const_int_operand" ""))]
4075   "TARGET_ARM
4076   && (!(const_ok_for_arm (INTVAL (operands[1]))
4077         || const_ok_for_arm (~INTVAL (operands[1]))))"
4078   [(clobber (const_int 0))]
4079   "
4080   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4081                       NULL_RTX, 0);
4082   DONE;
4083   "
4086 (define_insn "*thumb_movsi_insn"
4087   [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4088         (match_operand:SI 1 "general_operand"      "l, I,J,K,>,l,mi,l,*lh"))]
4089   "TARGET_THUMB
4090    && (   register_operand (operands[0], SImode) 
4091        || register_operand (operands[1], SImode))"
4092   "@
4093    mov  %0, %1
4094    mov  %0, %1
4095    #
4096    #
4097    ldmia\\t%1, {%0}
4098    stmia\\t%0, {%1}
4099    ldr\\t%0, %1
4100    str\\t%1, %0
4101    mov\\t%0, %1"
4102   [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4103    (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4104    (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4107 (define_split 
4108   [(set (match_operand:SI 0 "register_operand" "")
4109         (match_operand:SI 1 "const_int_operand" ""))]
4110   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4111   [(set (match_dup 0) (match_dup 1))
4112    (set (match_dup 0) (neg:SI (match_dup 0)))]
4113   "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4116 (define_split 
4117   [(set (match_operand:SI 0 "register_operand" "")
4118         (match_operand:SI 1 "const_int_operand" ""))]
4119   "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4120   [(set (match_dup 0) (match_dup 1))
4121    (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4122   "
4123   {
4124     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4125     unsigned HOST_WIDE_INT mask = 0xff;
4126     int i;
4127     
4128     for (i = 0; i < 25; i++)
4129       if ((val & (mask << i)) == val)
4130         break;
4132     /* Shouldn't happen, but we don't want to split if the shift is zero.  */
4133     if (i == 0)
4134       FAIL;
4136     operands[1] = GEN_INT (val >> i);
4137     operands[2] = GEN_INT (i);
4138   }"
4141 ;; When generating pic, we need to load the symbol offset into a register.
4142 ;; So that the optimizer does not confuse this with a normal symbol load
4143 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
4144 ;; since that is the only type of relocation we can use.
4146 ;; The rather odd constraints on the following are to force reload to leave
4147 ;; the insn alone, and to force the minipool generation pass to then move
4148 ;; the GOT symbol to memory.
4150 (define_insn "pic_load_addr_arm"
4151   [(set (match_operand:SI 0 "s_register_operand" "=r")
4152         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4153   "TARGET_ARM && flag_pic"
4154   "ldr%?\\t%0, %1"
4155   [(set_attr "type" "load")
4156    (set (attr "pool_range")     (const_int 4096))
4157    (set (attr "neg_pool_range") (const_int 4084))]
4160 (define_insn "pic_load_addr_thumb"
4161   [(set (match_operand:SI 0 "s_register_operand" "=l")
4162         (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4163   "TARGET_THUMB && flag_pic"
4164   "ldr\\t%0, %1"
4165   [(set_attr "type" "load")
4166    (set (attr "pool_range") (const_int 1024))]
4169 ;; This variant is used for AOF assembly, since it needs to mention the
4170 ;; pic register in the rtl.
4171 (define_expand "pic_load_addr_based"
4172   [(set (match_operand:SI 0 "s_register_operand" "=r")
4173         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4174   "TARGET_ARM && flag_pic"
4175   "operands[2] = pic_offset_table_rtx;"
4178 (define_insn "*pic_load_addr_based_insn"
4179   [(set (match_operand:SI 0 "s_register_operand" "=r")
4180         (unspec:SI [(match_operand 1 "" "")
4181                     (match_operand 2 "s_register_operand" "r")]
4182                    UNSPEC_PIC_SYM))]
4183   "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4184   "*
4185 #ifdef AOF_ASSEMBLER
4186   operands[1] = aof_pic_entry (operands[1]);
4187 #endif
4188   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4189   return \"\";
4190   "
4191   [(set_attr "type" "load")
4192    (set (attr "pool_range")
4193         (if_then_else (eq_attr "is_thumb" "yes")
4194                       (const_int 1024)
4195                       (const_int 4096)))
4196    (set (attr "neg_pool_range")
4197         (if_then_else (eq_attr "is_thumb" "yes")
4198                       (const_int 0)
4199                       (const_int 4084)))]
4202 (define_insn "pic_add_dot_plus_four"
4203   [(set (match_operand:SI 0 "register_operand" "+r")
4204         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4205    (use (label_ref (match_operand 1 "" "")))]
4206   "TARGET_THUMB && flag_pic"
4207   "*
4208   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4209                              CODE_LABEL_NUMBER (operands[1]));
4210   return \"add\\t%0, %|pc\";
4211   "
4212   [(set_attr "length" "2")]
4215 (define_insn "pic_add_dot_plus_eight"
4216   [(set (match_operand:SI 0 "register_operand" "+r")
4217         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4218    (use (label_ref (match_operand 1 "" "")))]
4219   "TARGET_ARM && flag_pic"
4220   "*
4221     ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4222                                CODE_LABEL_NUMBER (operands[1]));
4223     return \"add%?\\t%0, %|pc, %0\";
4224   "
4225   [(set_attr "predicable" "yes")]
4228 (define_expand "builtin_setjmp_receiver"
4229   [(label_ref (match_operand 0 "" ""))]
4230   "flag_pic"
4231   "
4233   arm_finalize_pic (0);
4234   DONE;
4237 ;; If copying one reg to another we can set the condition codes according to
4238 ;; its value.  Such a move is common after a return from subroutine and the
4239 ;; result is being tested against zero.
4241 (define_insn "*movsi_compare0"
4242   [(set (reg:CC CC_REGNUM)
4243         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4244                     (const_int 0)))
4245    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4246         (match_dup 1))]
4247   "TARGET_ARM"
4248   "@
4249    cmp%?\\t%0, #0
4250    sub%?s\\t%0, %1, #0"
4251   [(set_attr "conds" "set")]
4254 ;; Subroutine to store a half word from a register into memory.
4255 ;; Operand 0 is the source register (HImode)
4256 ;; Operand 1 is the destination address in a register (SImode)
4258 ;; In both this routine and the next, we must be careful not to spill
4259 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4260 ;; can generate unrecognizable rtl.
4262 (define_expand "storehi"
4263   [;; store the low byte
4264    (set (match_operand 1 "" "") (match_dup 3))
4265    ;; extract the high byte
4266    (set (match_dup 2)
4267         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4268    ;; store the high byte
4269    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
4270   "TARGET_ARM"
4271   "
4272   {
4273     rtx op1 = operands[1];
4274     rtx addr = XEXP (op1, 0);
4275     enum rtx_code code = GET_CODE (addr);
4277     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4278         || code == MINUS)
4279       op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4281     operands[4] = adjust_address (op1, QImode, 1);
4282     operands[1] = adjust_address (operands[1], QImode, 0);
4283     operands[3] = gen_lowpart (QImode, operands[0]);
4284     operands[0] = gen_lowpart (SImode, operands[0]);
4285     operands[2] = gen_reg_rtx (SImode); 
4286   }"
4289 (define_expand "storehi_bigend"
4290   [(set (match_dup 4) (match_dup 3))
4291    (set (match_dup 2)
4292         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4293    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4294   "TARGET_ARM"
4295   "
4296   {
4297     rtx op1 = operands[1];
4298     rtx addr = XEXP (op1, 0);
4299     enum rtx_code code = GET_CODE (addr);
4301     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4302         || code == MINUS)
4303       op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4305     operands[4] = adjust_address (op1, QImode, 1);
4306     operands[1] = adjust_address (operands[1], QImode, 0);
4307     operands[3] = gen_lowpart (QImode, operands[0]);
4308     operands[0] = gen_lowpart (SImode, operands[0]);
4309     operands[2] = gen_reg_rtx (SImode);
4310   }"
4313 ;; Subroutine to store a half word integer constant into memory.
4314 (define_expand "storeinthi"
4315   [(set (match_operand 0 "" "")
4316         (subreg:QI (match_operand 1 "" "") 0))
4317    (set (match_dup 3) (match_dup 2))]
4318   "TARGET_ARM"
4319   "
4320   {
4321     HOST_WIDE_INT value = INTVAL (operands[1]);
4322     rtx addr = XEXP (operands[0], 0);
4323     rtx op0 = operands[0];
4324     enum rtx_code code = GET_CODE (addr);
4326     if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4327         || code == MINUS)
4328       op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4330     operands[1] = gen_reg_rtx (SImode);
4331     if (BYTES_BIG_ENDIAN)
4332       {
4333         emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4334         if ((value & 255) == ((value >> 8) & 255))
4335           operands[2] = operands[1];
4336         else
4337           {
4338             operands[2] = gen_reg_rtx (SImode);
4339             emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4340           }
4341       }
4342     else
4343       {
4344         emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4345         if ((value & 255) == ((value >> 8) & 255))
4346           operands[2] = operands[1];
4347         else
4348           {
4349             operands[2] = gen_reg_rtx (SImode);
4350             emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4351           }
4352       }
4354     operands[3] = adjust_address (op0, QImode, 1);
4355     operands[0] = adjust_address (operands[0], QImode, 0);
4356     operands[2] = gen_lowpart (QImode, operands[2]);
4357   }"
4360 (define_expand "storehi_single_op"
4361   [(set (match_operand:HI 0 "memory_operand" "")
4362         (match_operand:HI 1 "general_operand" ""))]
4363   "TARGET_ARM && arm_arch4"
4364   "
4365   if (!s_register_operand (operands[1], HImode))
4366     operands[1] = copy_to_mode_reg (HImode, operands[1]);
4367   "
4370 (define_expand "movhi"
4371   [(set (match_operand:HI 0 "general_operand" "")
4372         (match_operand:HI 1 "general_operand" ""))]
4373   "TARGET_EITHER"
4374   "
4375   if (TARGET_ARM)
4376     {
4377       if (!no_new_pseudos)
4378         {
4379           if (GET_CODE (operands[0]) == MEM)
4380             {
4381               if (arm_arch4)
4382                 {
4383                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4384                   DONE;
4385                 }
4386               if (GET_CODE (operands[1]) == CONST_INT)
4387                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4388               else
4389                 {
4390                   if (GET_CODE (operands[1]) == MEM)
4391                     operands[1] = force_reg (HImode, operands[1]);
4392                   if (BYTES_BIG_ENDIAN)
4393                     emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4394                   else
4395                    emit_insn (gen_storehi (operands[1], operands[0]));
4396                 }
4397               DONE;
4398             }
4399           /* Sign extend a constant, and keep it in an SImode reg.  */
4400           else if (GET_CODE (operands[1]) == CONST_INT)
4401             {
4402               rtx reg = gen_reg_rtx (SImode);
4403               HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4405               /* If the constant is already valid, leave it alone.  */
4406               if (!const_ok_for_arm (val))
4407                 {
4408                   /* If setting all the top bits will make the constant 
4409                      loadable in a single instruction, then set them.  
4410                      Otherwise, sign extend the number.  */
4412                   if (const_ok_for_arm (~(val | ~0xffff)))
4413                     val |= ~0xffff;
4414                   else if (val & 0x8000)
4415                     val |= ~0xffff;
4416                 }
4418               emit_insn (gen_movsi (reg, GEN_INT (val)));
4419               operands[1] = gen_lowpart (HImode, reg);
4420             }
4421           else if (arm_arch4 && !no_new_pseudos && optimize > 0
4422                    && GET_CODE (operands[1]) == MEM)
4423             {
4424               rtx reg = gen_reg_rtx (SImode);
4426               emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4427               operands[1] = gen_lowpart (HImode, reg);
4428             }
4429           else if (!arm_arch4)
4430             {
4431              /* Note: We do not have to worry about TARGET_MMU_TRAPS
4432                 for v4 and up architectures because LDRH instructions will
4433                 be used to access the HI values, and these cannot generate
4434                 unaligned word access faults in the MMU.  */
4435               if (GET_CODE (operands[1]) == MEM)
4436                 {
4437                   if (TARGET_MMU_TRAPS)
4438                     {
4439                       rtx base;
4440                       rtx offset = const0_rtx;
4441                       rtx reg = gen_reg_rtx (SImode);
4443                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4444                            || (GET_CODE (base) == PLUS
4445                                && (GET_CODE (offset = XEXP (base, 1))
4446                                    == CONST_INT)
4447                                && ((INTVAL(offset) & 1) != 1)
4448                                && GET_CODE (base = XEXP (base, 0)) == REG))
4449                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4450                         {
4451                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4452                           rtx new;
4454                           new = gen_rtx_MEM (SImode,
4455                                              plus_constant (base, new_offset));
4456                           MEM_COPY_ATTRIBUTES (new, operands[1]);
4457                           emit_insn (gen_movsi (reg, new));
4458                           if (((INTVAL (offset) & 2) != 0)
4459                               ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4460                             {
4461                               rtx reg2 = gen_reg_rtx (SImode);
4463                               emit_insn (gen_lshrsi3 (reg2, reg,
4464                                          GEN_INT (16)));
4465                               reg = reg2;
4466                             }
4467                         }
4468                       else
4469                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4471                       operands[1] = gen_lowpart (HImode, reg);
4472                     }
4473                   else if (BYTES_BIG_ENDIAN)
4474                     {
4475                       rtx base;
4476                       rtx offset = const0_rtx;
4478                       if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4479                            || (GET_CODE (base) == PLUS
4480                               && (GET_CODE (offset = XEXP (base, 1))
4481                                   == CONST_INT)
4482                               && GET_CODE (base = XEXP (base, 0)) == REG))
4483                           && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4484                         {
4485                           rtx reg = gen_reg_rtx (SImode);
4486                           rtx new;
4488                           if ((INTVAL (offset) & 2) == 2)
4489                             {
4490                               HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4491                               new = gen_rtx_MEM (SImode,
4492                                                  plus_constant (base,
4493                                                                 new_offset));
4494                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4495                               emit_insn (gen_movsi (reg, new));
4496                             }
4497                           else
4498                             {
4499                               new = gen_rtx_MEM (SImode,
4500                                                  XEXP (operands[1], 0));
4501                               MEM_COPY_ATTRIBUTES (new, operands[1]);
4502                               emit_insn (gen_rotated_loadsi (reg, new));
4503                             }
4505                           operands[1] = gen_lowpart (HImode, reg);
4506                         }
4507                       else
4508                         {
4509                           emit_insn (gen_movhi_bigend (operands[0],
4510                                                        operands[1]));
4511                           DONE;
4512                         }
4513                     }
4514                }
4515            }
4516         }
4517       /* Handle loading a large integer during reload */
4518       else if (GET_CODE (operands[1]) == CONST_INT
4519                && !const_ok_for_arm (INTVAL (operands[1]))
4520                && !const_ok_for_arm (~INTVAL (operands[1])))
4521         {
4522           /* Writing a constant to memory needs a scratch, which should
4523              be handled with SECONDARY_RELOADs.  */
4524           if (GET_CODE (operands[0]) != REG)
4525             abort ();
4527           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4528           emit_insn (gen_movsi (operands[0], operands[1]));
4529           DONE;
4530        }
4531     }
4532   else /* TARGET_THUMB */
4533     {
4534       if (!no_new_pseudos)
4535         {
4536           if (GET_CODE (operands[0]) != REG)
4537             operands[1] = force_reg (HImode, operands[1]);
4539           /* ??? We shouldn't really get invalid addresses here, but this can
4540              happen if we are passed a SP (never OK for HImode/QImode) or 
4541              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for 
4542              HImode/QImode) relative address.  */
4543           /* ??? This should perhaps be fixed elsewhere, for instance, in
4544              fixup_stack_1, by checking for other kinds of invalid addresses,
4545              e.g. a bare reference to a virtual register.  This may confuse the
4546              alpha though, which must handle this case differently.  */
4547           if (GET_CODE (operands[0]) == MEM
4548               && !memory_address_p (GET_MODE (operands[0]),
4549                                     XEXP (operands[0], 0)))
4550             operands[0]
4551               = replace_equiv_address (operands[0],
4552                                        copy_to_reg (XEXP (operands[0], 0)));
4553    
4554           if (GET_CODE (operands[1]) == MEM
4555               && !memory_address_p (GET_MODE (operands[1]),
4556                                     XEXP (operands[1], 0)))
4557             operands[1]
4558               = replace_equiv_address (operands[1],
4559                                        copy_to_reg (XEXP (operands[1], 0)));
4560         }
4561       /* Handle loading a large integer during reload */
4562       else if (GET_CODE (operands[1]) == CONST_INT
4563                 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4564         {
4565           /* Writing a constant to memory needs a scratch, which should
4566              be handled with SECONDARY_RELOADs.  */
4567           if (GET_CODE (operands[0]) != REG)
4568             abort ();
4570           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4571           emit_insn (gen_movsi (operands[0], operands[1]));
4572           DONE;
4573         }
4574     }
4575   "
4578 (define_insn "*thumb_movhi_insn"
4579   [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4580         (match_operand:HI 1 "general_operand"       "l,mn,l,*h,*r,I"))]
4581   "TARGET_THUMB
4582    && (   register_operand (operands[0], HImode)
4583        || register_operand (operands[1], HImode))"
4584   "*
4585   switch (which_alternative)
4586     {
4587     case 0: return \"add        %0, %1, #0\";
4588     case 2: return \"strh       %1, %0\";
4589     case 3: return \"mov        %0, %1\";
4590     case 4: return \"mov        %0, %1\";
4591     case 5: return \"mov        %0, %1\";
4592     default: abort ();
4593     case 1:
4594       /* The stack pointer can end up being taken as an index register.
4595           Catch this case here and deal with it.  */
4596       if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4597           && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4598           && REGNO    (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4599         {
4600           rtx ops[2];
4601           ops[0] = operands[0];
4602           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4603       
4604           output_asm_insn (\"mov        %0, %1\", ops);
4606           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4607     
4608         }
4609       return \"ldrh     %0, %1\";
4610     }"
4611   [(set_attr "length" "2,4,2,2,2,2")
4612    (set_attr "type" "*,load,store1,*,*,*")
4613    (set_attr "pool_range" "*,64,*,*,*,*")]
4617 (define_insn "rotated_loadsi"
4618   [(set (match_operand:SI            0 "s_register_operand"        "=r")
4619         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4620                    (const_int 16)))]
4621   "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4622   "*
4623   {
4624     rtx ops[2];
4626     ops[0] = operands[0];
4627     ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4628     output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4629     return \"\";
4630   }"
4631   [(set_attr "type" "load")
4632    (set_attr "predicable" "yes")]
4635 (define_expand "movhi_bytes"
4636   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4637    (set (match_dup 3)
4638         (zero_extend:SI (match_dup 6)))
4639    (set (match_operand:SI 0 "" "")
4640          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4641   "TARGET_ARM"
4642   "
4643   {
4644     rtx mem1, mem2;
4645     rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4647     mem1 = gen_rtx_MEM (QImode, addr);
4648     MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4649     mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4650     MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4651     operands[0] = gen_lowpart (SImode, operands[0]);
4652     operands[1] = mem1;
4653     operands[2] = gen_reg_rtx (SImode);
4654     operands[3] = gen_reg_rtx (SImode);
4655     operands[6] = mem2;
4657     if (BYTES_BIG_ENDIAN)
4658       {
4659         operands[4] = operands[2];
4660         operands[5] = operands[3];
4661       }
4662     else
4663       {
4664         operands[4] = operands[3];
4665         operands[5] = operands[2];
4666       }
4667   }"
4670 (define_expand "movhi_bigend"
4671   [(set (match_dup 2)
4672         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4673                    (const_int 16)))
4674    (set (match_dup 3)
4675         (ashiftrt:SI (match_dup 2) (const_int 16)))
4676    (set (match_operand:HI 0 "s_register_operand" "")
4677         (subreg:HI (match_dup 3) 0))]
4678   "TARGET_ARM"
4679   "
4680   operands[2] = gen_reg_rtx (SImode);
4681   operands[3] = gen_reg_rtx (SImode);
4682   "
4685 ;; Pattern to recognise insn generated default case above
4686 (define_insn "*movhi_insn_arch4"
4687   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")    
4688         (match_operand:HI 1 "general_operand"      "rI,K,r,m"))]
4689   "TARGET_ARM
4690    && arm_arch4
4691    && (GET_CODE (operands[1]) != CONST_INT
4692        || const_ok_for_arm (INTVAL (operands[1]))
4693        || const_ok_for_arm (~INTVAL (operands[1])))"
4694   "@
4695    mov%?\\t%0, %1\\t%@ movhi
4696    mvn%?\\t%0, #%B1\\t%@ movhi
4697    str%?h\\t%1, %0\\t%@ movhi 
4698    ldr%?h\\t%0, %1\\t%@ movhi"
4699   [(set_attr "type" "*,*,store1,load")
4700    (set_attr "predicable" "yes")
4701    (set_attr "pool_range" "*,*,*,256")
4702    (set_attr "neg_pool_range" "*,*,*,244")]
4705 (define_insn "*movhi_insn_littleend"
4706   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4707         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
4708   "TARGET_ARM
4709    && !arm_arch4
4710    && !BYTES_BIG_ENDIAN
4711    && !TARGET_MMU_TRAPS
4712    && (GET_CODE (operands[1]) != CONST_INT
4713        || const_ok_for_arm (INTVAL (operands[1]))
4714        || const_ok_for_arm (~INTVAL (operands[1])))"
4715   "@
4716    mov%?\\t%0, %1\\t%@ movhi
4717    mvn%?\\t%0, #%B1\\t%@ movhi
4718    ldr%?\\t%0, %1\\t%@ movhi"
4719   [(set_attr "type" "*,*,load")
4720    (set_attr "predicable" "yes")
4721    (set_attr "pool_range" "4096")
4722    (set_attr "neg_pool_range" "4084")]
4725 (define_insn "*movhi_insn_bigend"
4726   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4727         (match_operand:HI 1 "general_operand"    "rI,K,m"))]
4728   "TARGET_ARM
4729    && !arm_arch4
4730    && BYTES_BIG_ENDIAN
4731    && !TARGET_MMU_TRAPS
4732    && (GET_CODE (operands[1]) != CONST_INT
4733        || const_ok_for_arm (INTVAL (operands[1]))
4734        || const_ok_for_arm (~INTVAL (operands[1])))"
4735   "@
4736    mov%?\\t%0, %1\\t%@ movhi
4737    mvn%?\\t%0, #%B1\\t%@ movhi
4738    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4739   [(set_attr "type" "*,*,load")
4740    (set_attr "predicable" "yes")
4741    (set_attr "length" "4,4,8")
4742    (set_attr "pool_range" "*,*,4092")
4743    (set_attr "neg_pool_range" "*,*,4084")]
4746 (define_insn "*loadhi_si_bigend"
4747   [(set (match_operand:SI                       0 "s_register_operand" "=r")
4748         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand"      "m") 0)
4749                    (const_int 16)))]
4750   "TARGET_ARM
4751    && BYTES_BIG_ENDIAN
4752    && !TARGET_MMU_TRAPS"
4753   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4754   [(set_attr "type" "load")
4755    (set_attr "predicable" "yes")
4756    (set_attr "pool_range" "4096")
4757    (set_attr "neg_pool_range" "4084")]
4760 (define_insn "*movhi_bytes"
4761   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4762         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
4763   "TARGET_ARM && TARGET_MMU_TRAPS"
4764   "@
4765    mov%?\\t%0, %1\\t%@ movhi
4766    mvn%?\\t%0, #%B1\\t%@ movhi"
4767   [(set_attr "predicable" "yes")]
4770 (define_insn "thumb_movhi_clobber"
4771   [(set (match_operand:HI     0 "memory_operand"   "=m")
4772         (match_operand:HI     1 "register_operand" "l"))
4773    (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4774   "TARGET_THUMB"
4775   "*
4776   abort ();"
4778         
4779 ;; We use a DImode scratch because we may occasionally need an additional
4780 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4781 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4782 (define_expand "reload_outhi"
4783   [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4784               (match_operand:HI 1 "s_register_operand"        "r")
4785               (match_operand:DI 2 "s_register_operand"        "=&l")])]
4786   "TARGET_EITHER"
4787   "if (TARGET_ARM)
4788      arm_reload_out_hi (operands);
4789    else
4790      thumb_reload_out_hi (operands);
4791   DONE;
4792   "
4795 (define_expand "reload_inhi"
4796   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4797               (match_operand:HI 1 "arm_reload_memory_operand" "o")
4798               (match_operand:DI 2 "s_register_operand" "=&r")])]
4799   "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4800   "
4801   if (TARGET_ARM)
4802     arm_reload_in_hi (operands);
4803   else
4804     thumb_reload_out_hi (operands);
4805   DONE;
4808 (define_expand "movqi"
4809   [(set (match_operand:QI 0 "general_operand" "")
4810         (match_operand:QI 1 "general_operand" ""))]
4811   "TARGET_EITHER"
4812   "
4813   if (TARGET_ARM)
4814     {
4815       /* Everything except mem = const or mem = mem can be done easily */
4817       if (!no_new_pseudos)
4818         {
4819           if (GET_CODE (operands[1]) == CONST_INT)
4820             {
4821               rtx reg = gen_reg_rtx (SImode);
4823               emit_insn (gen_movsi (reg, operands[1]));
4824               operands[1] = gen_lowpart (QImode, reg);
4825             }
4826           if (GET_CODE (operands[1]) == MEM && optimize > 0)
4827             {
4828               rtx reg = gen_reg_rtx (SImode);
4830               emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4831               operands[1] = gen_lowpart (QImode, reg);
4832             }
4833           if (GET_CODE (operands[0]) == MEM)
4834             operands[1] = force_reg (QImode, operands[1]);
4835         }
4836     }
4837   else /* TARGET_THUMB */
4838     {
4839       if (!no_new_pseudos)
4840         {
4841           if (GET_CODE (operands[0]) != REG)
4842             operands[1] = force_reg (QImode, operands[1]);
4844           /* ??? We shouldn't really get invalid addresses here, but this can
4845              happen if we are passed a SP (never OK for HImode/QImode) or
4846              virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4847              HImode/QImode) relative address.  */
4848           /* ??? This should perhaps be fixed elsewhere, for instance, in
4849              fixup_stack_1, by checking for other kinds of invalid addresses,
4850              e.g. a bare reference to a virtual register.  This may confuse the
4851              alpha though, which must handle this case differently.  */
4852           if (GET_CODE (operands[0]) == MEM
4853               && !memory_address_p (GET_MODE (operands[0]),
4854                                      XEXP (operands[0], 0)))
4855             operands[0]
4856               = replace_equiv_address (operands[0],
4857                                        copy_to_reg (XEXP (operands[0], 0)));
4858           if (GET_CODE (operands[1]) == MEM
4859               && !memory_address_p (GET_MODE (operands[1]),
4860                                     XEXP (operands[1], 0)))
4861              operands[1]
4862                = replace_equiv_address (operands[1],
4863                                         copy_to_reg (XEXP (operands[1], 0)));
4864         }
4865       /* Handle loading a large integer during reload */
4866       else if (GET_CODE (operands[1]) == CONST_INT
4867                && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4868         {
4869           /* Writing a constant to memory needs a scratch, which should
4870              be handled with SECONDARY_RELOADs.  */
4871           if (GET_CODE (operands[0]) != REG)
4872             abort ();
4874           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4875           emit_insn (gen_movsi (operands[0], operands[1]));
4876           DONE;
4877        }
4878     }
4879   "
4883 (define_insn "*arm_movqi_insn"
4884   [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4885         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4886   "TARGET_ARM
4887    && (   register_operand (operands[0], QImode)
4888        || register_operand (operands[1], QImode))"
4889   "@
4890    mov%?\\t%0, %1
4891    mvn%?\\t%0, #%B1
4892    ldr%?b\\t%0, %1
4893    str%?b\\t%1, %0"
4894   [(set_attr "type" "*,*,load,store1")
4895    (set_attr "predicable" "yes")]
4898 (define_insn "*thumb_movqi_insn"
4899   [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4900         (match_operand:QI 1 "general_operand"      "l, m,l,*h,*r,I"))]
4901   "TARGET_THUMB
4902    && (   register_operand (operands[0], QImode)
4903        || register_operand (operands[1], QImode))"
4904   "@
4905    add\\t%0, %1, #0
4906    ldrb\\t%0, %1
4907    strb\\t%1, %0
4908    mov\\t%0, %1
4909    mov\\t%0, %1
4910    mov\\t%0, %1"
4911   [(set_attr "length" "2")
4912    (set_attr "type" "*,load,store1,*,*,*")
4913    (set_attr "pool_range" "*,32,*,*,*,*")]
4916 (define_expand "movsf"
4917   [(set (match_operand:SF 0 "general_operand" "")
4918         (match_operand:SF 1 "general_operand" ""))]
4919   "TARGET_EITHER"
4920   "
4921   if (TARGET_ARM)
4922     {
4923       if (GET_CODE (operands[0]) == MEM)
4924         operands[1] = force_reg (SFmode, operands[1]);
4925     }
4926   else /* TARGET_THUMB */
4927     {
4928       if (!no_new_pseudos)
4929         {
4930            if (GET_CODE (operands[0]) != REG)
4931              operands[1] = force_reg (SFmode, operands[1]);
4932         }
4933     }
4934   "
4937 (define_split
4938   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4939         (match_operand:SF 1 "immediate_operand" ""))]
4940   "TARGET_ARM
4941    && !TARGET_HARD_FLOAT
4942    && reload_completed
4943    && GET_CODE (operands[1]) == CONST_DOUBLE"
4944   [(set (match_dup 2) (match_dup 3))]
4945   "
4946   operands[2] = gen_lowpart (SImode, operands[0]);
4947   operands[3] = gen_lowpart (SImode, operands[1]);
4948   if (operands[2] == 0 || operands[3] == 0)
4949     FAIL;
4950   "
4953 (define_insn "*arm_movsf_hard_insn"
4954   [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4955         (match_operand:SF 1 "general_operand"      "fG,H,mE,f,r,f,r,mE,r"))]
4956   "TARGET_ARM
4957    && TARGET_HARD_FLOAT
4958    && (GET_CODE (operands[0]) != MEM
4959        || register_operand (operands[1], SFmode))"
4960   "@
4961    mvf%?s\\t%0, %1
4962    mnf%?s\\t%0, #%N1
4963    ldf%?s\\t%0, %1
4964    stf%?s\\t%1, %0
4965    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4966    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4967    mov%?\\t%0, %1
4968    ldr%?\\t%0, %1\\t%@ float
4969    str%?\\t%1, %0\\t%@ float"
4970   [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4971    (set_attr "predicable" "yes")
4972    (set_attr "type"
4973          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4974    (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4975    (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4978 ;; Exactly the same as above, except that all `f' cases are deleted.
4979 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4980 ;; when -msoft-float.
4982 (define_insn "*arm_movsf_soft_insn"
4983   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4984         (match_operand:SF 1 "general_operand"  "r,mE,r"))]
4985   "TARGET_ARM
4986    && TARGET_SOFT_FLOAT
4987    && (GET_CODE (operands[0]) != MEM
4988        || register_operand (operands[1], SFmode))"
4989   "@
4990    mov%?\\t%0, %1
4991    ldr%?\\t%0, %1\\t%@ float
4992    str%?\\t%1, %0\\t%@ float"
4993   [(set_attr "length" "4,4,4")
4994    (set_attr "predicable" "yes")
4995    (set_attr "type" "*,load,store1")
4996    (set_attr "pool_range" "*,4096,*")
4997    (set_attr "neg_pool_range" "*,4084,*")]
5000 ;;; ??? This should have alternatives for constants.
5001 (define_insn "*thumb_movsf_insn"
5002   [(set (match_operand:SF     0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5003         (match_operand:SF     1 "general_operand"      "l, >,l,mF,l,*h,*r"))]
5004   "TARGET_THUMB
5005    && (   register_operand (operands[0], SFmode) 
5006        || register_operand (operands[1], SFmode))"
5007   "@
5008    add\\t%0, %1, #0
5009    ldmia\\t%1, {%0}
5010    stmia\\t%0, {%1}
5011    ldr\\t%0, %1
5012    str\\t%1, %0
5013    mov\\t%0, %1
5014    mov\\t%0, %1"
5015   [(set_attr "length" "2")
5016    (set_attr "type" "*,load,store1,load,store1,*,*")
5017    (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5020 (define_expand "movdf"
5021   [(set (match_operand:DF 0 "general_operand" "")
5022         (match_operand:DF 1 "general_operand" ""))]
5023   "TARGET_EITHER"
5024   "
5025   if (TARGET_ARM)
5026     {
5027       if (GET_CODE (operands[0]) == MEM)
5028         operands[1] = force_reg (DFmode, operands[1]);
5029     }
5030   else /* TARGET_THUMB */
5031     {
5032       if (!no_new_pseudos)
5033         {
5034           if (GET_CODE (operands[0]) != REG)
5035             operands[1] = force_reg (DFmode, operands[1]);
5036         }
5037     }
5038   "
5041 ;; Reloading a df mode value stored in integer regs to memory can require a
5042 ;; scratch reg.
5043 (define_expand "reload_outdf"
5044   [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5045    (match_operand:DF 1 "s_register_operand" "r")
5046    (match_operand:SI 2 "s_register_operand" "=&r")]
5047   "TARGET_ARM"
5048   "
5049   {
5050     enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5052     if (code == REG)
5053       operands[2] = XEXP (operands[0], 0);
5054     else if (code == POST_INC || code == PRE_DEC)
5055       {
5056         operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5057         operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5058         emit_insn (gen_movdi (operands[0], operands[1]));
5059         DONE;
5060       }
5061     else if (code == PRE_INC)
5062       {
5063         rtx reg = XEXP (XEXP (operands[0], 0), 0);
5065         emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5066         operands[2] = reg;
5067       }
5068     else if (code == POST_DEC)
5069       operands[2] = XEXP (XEXP (operands[0], 0), 0);
5070     else
5071       emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5072                              XEXP (XEXP (operands[0], 0), 1)));
5074     emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5075                             operands[1]));
5077     if (code == POST_DEC)
5078       emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5080     DONE;
5081   }"
5084 (define_insn "*movdf_hard_insn"
5085   [(set (match_operand:DF 0 "nonimmediate_operand"
5086                                                 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5087         (match_operand:DF 1 "general_operand"
5088                                                 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5089   "TARGET_ARM
5090    && TARGET_HARD_FLOAT
5091    && (GET_CODE (operands[0]) != MEM
5092        || register_operand (operands[1], DFmode))"
5093   "*
5094   {
5095   switch (which_alternative)
5096     {
5097     default:
5098     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5099     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5100     case 2: case 3: case 4: return output_move_double (operands);
5101     case 5: return \"mvf%?d\\t%0, %1\";
5102     case 6: return \"mnf%?d\\t%0, #%N1\";
5103     case 7: return \"ldf%?d\\t%0, %1\";
5104     case 8: return \"stf%?d\\t%1, %0\";
5105     case 9: return output_mov_double_fpu_from_arm (operands);
5106     case 10: return output_mov_double_arm_from_fpu (operands);
5107     }
5108   }
5109   "
5110   [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5111    (set_attr "predicable" "yes")
5112    (set_attr "type"
5113     "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5114    (set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
5115    (set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
5118 ;; Software floating point version.  This is essentially the same as movdi.
5119 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5120 ;; an `f' reg.
5122 (define_insn "*movdf_soft_insn"
5123   [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5124         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5125   "TARGET_ARM && TARGET_SOFT_FLOAT
5126   "
5127   "* return output_move_double (operands);"
5128   [(set_attr "length" "8,8,8")
5129    (set_attr "type" "*,load,store2")
5130    (set_attr "pool_range" "1020")
5131    (set_attr "neg_pool_range" "1008")]
5134 ;;; ??? This should have alternatives for constants.
5135 ;;; ??? This was originally identical to the movdi_insn pattern.
5136 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5137 ;;; thumb_reorg with a memory reference.
5138 (define_insn "*thumb_movdf_insn"
5139   [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5140         (match_operand:DF 1 "general_operand"      "l, >,l,mF,l,*r"))]
5141   "TARGET_THUMB
5142    && (   register_operand (operands[0], DFmode)
5143        || register_operand (operands[1], DFmode))"
5144   "*
5145   switch (which_alternative)
5146     {
5147     default:
5148     case 0:
5149       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5150         return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5151       return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5152     case 1:
5153       return \"ldmia\\t%1, {%0, %H0}\";
5154     case 2:
5155       return \"stmia\\t%0, {%1, %H1}\";
5156     case 3:
5157       return thumb_load_double_from_address (operands);
5158     case 4:
5159       operands[2] = gen_rtx (MEM, SImode,
5160                              plus_constant (XEXP (operands[0], 0), 4));
5161       output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5162       return \"\";
5163     case 5:
5164       if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5165         return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5166       return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5167     }
5168   "
5169   [(set_attr "length" "4,2,2,6,4,4")
5170    (set_attr "type" "*,load,store2,load,store2,*")
5171    (set_attr "pool_range" "*,*,*,1020,*,*")]
5175 (define_expand "movxf"
5176   [(set (match_operand:XF 0 "general_operand" "")
5177         (match_operand:XF 1 "general_operand" ""))]
5178   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5179   "")
5181 ;; Even when the XFmode patterns aren't enabled, we enable this after
5182 ;; reloading so that we can push floating point registers in the prologue.
5184 (define_insn "*movxf_hard_insn"
5185   [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5186         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5187   "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5188   "*
5189   switch (which_alternative)
5190     {
5191     default:
5192     case 0: return \"mvf%?e\\t%0, %1\";
5193     case 1: return \"mnf%?e\\t%0, #%N1\";
5194     case 2: return \"ldf%?e\\t%0, %1\";
5195     case 3: return \"stf%?e\\t%1, %0\";
5196     case 4: return output_mov_long_double_fpu_from_arm (operands);
5197     case 5: return output_mov_long_double_arm_from_fpu (operands);
5198     case 6: return output_mov_long_double_arm_from_arm (operands);
5199     }
5200   "
5201   [(set_attr "length" "4,4,4,4,8,8,12")
5202    (set_attr "predicable" "yes")
5203    (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5204    (set_attr "pool_range" "*,*,1024,*,*,*,*")
5205    (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
5209 ;; load- and store-multiple insns
5210 ;; The arm can load/store any set of registers, provided that they are in
5211 ;; ascending order; but that is beyond GCC so stick with what it knows.
5213 (define_expand "load_multiple"
5214   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5215                           (match_operand:SI 1 "" ""))
5216                      (use (match_operand:SI 2 "" ""))])]
5217   "TARGET_ARM"
5218   "
5219   /* Support only fixed point registers.  */
5220   if (GET_CODE (operands[2]) != CONST_INT
5221       || INTVAL (operands[2]) > 14
5222       || INTVAL (operands[2]) < 2
5223       || GET_CODE (operands[1]) != MEM
5224       || GET_CODE (operands[0]) != REG
5225       || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5226       || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5227     FAIL;
5229   operands[3]
5230     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5231                              force_reg (SImode, XEXP (operands[1], 0)),
5232                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5233                              MEM_IN_STRUCT_P(operands[1]),
5234                              MEM_SCALAR_P (operands[1]));
5235   "
5238 ;; Load multiple with write-back
5240 (define_insn "*ldmsi_postinc4"
5241   [(match_parallel 0 "load_multiple_operation"
5242     [(set (match_operand:SI 1 "s_register_operand" "=r")
5243           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5244                    (const_int 16)))
5245      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5246           (mem:SI (match_dup 2)))
5247      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5248           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5249      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5250           (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5251      (set (match_operand:SI 6 "arm_hard_register_operand" "")
5252           (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5253   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5254   "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5255   [(set_attr "type" "load")
5256    (set_attr "predicable" "yes")]
5259 (define_insn "*ldmsi_postinc3"
5260   [(match_parallel 0 "load_multiple_operation"
5261     [(set (match_operand:SI 1 "s_register_operand" "=r")
5262           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5263                    (const_int 12)))
5264      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5265           (mem:SI (match_dup 2)))
5266      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5267           (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5268      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5269           (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5270   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5271   "ldm%?ia\\t%1!, {%3, %4, %5}"
5272   [(set_attr "type" "load")
5273    (set_attr "predicable" "yes")]
5276 (define_insn "*ldmsi_postinc2"
5277   [(match_parallel 0 "load_multiple_operation"
5278     [(set (match_operand:SI 1 "s_register_operand" "=r")
5279           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5280                    (const_int 8)))
5281      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5282           (mem:SI (match_dup 2)))
5283      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5284           (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5285   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5286   "ldm%?ia\\t%1!, {%3, %4}"
5287   [(set_attr "type" "load")
5288    (set_attr "predicable" "yes")]
5291 ;; Ordinary load multiple
5293 (define_insn "*ldmsi4"
5294   [(match_parallel 0 "load_multiple_operation"
5295     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5296           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5297      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5298           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5299      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5300           (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5301      (set (match_operand:SI 5 "arm_hard_register_operand" "")
5302           (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5303   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5304   "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5305   [(set_attr "type" "load")
5306    (set_attr "predicable" "yes")]
5309 (define_insn "*ldmsi3"
5310   [(match_parallel 0 "load_multiple_operation"
5311     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5312           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5313      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5314           (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5315      (set (match_operand:SI 4 "arm_hard_register_operand" "")
5316           (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5317   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5318   "ldm%?ia\\t%1, {%2, %3, %4}"
5319   [(set_attr "type" "load")
5320    (set_attr "predicable" "yes")]
5323 (define_insn "*ldmsi2"
5324   [(match_parallel 0 "load_multiple_operation"
5325     [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5326           (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5327      (set (match_operand:SI 3 "arm_hard_register_operand" "")
5328           (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5329   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5330   "ldm%?ia\\t%1, {%2, %3}"
5331   [(set_attr "type" "load")
5332    (set_attr "predicable" "yes")]
5335 (define_expand "store_multiple"
5336   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5337                           (match_operand:SI 1 "" ""))
5338                      (use (match_operand:SI 2 "" ""))])]
5339   "TARGET_ARM"
5340   "
5341   /* Support only fixed point registers */
5342   if (GET_CODE (operands[2]) != CONST_INT
5343       || INTVAL (operands[2]) > 14
5344       || INTVAL (operands[2]) < 2
5345       || GET_CODE (operands[1]) != REG
5346       || GET_CODE (operands[0]) != MEM
5347       || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5348       || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5349     FAIL;
5351   operands[3]
5352     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5353                               force_reg (SImode, XEXP (operands[0], 0)),
5354                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5355                               MEM_IN_STRUCT_P(operands[0]), 
5356                               MEM_SCALAR_P (operands[0]));
5357   "
5360 ;; Store multiple with write-back
5362 (define_insn "*stmsi_postinc4"
5363   [(match_parallel 0 "store_multiple_operation"
5364     [(set (match_operand:SI 1 "s_register_operand" "=r")
5365           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5366                    (const_int 16)))
5367      (set (mem:SI (match_dup 2))
5368           (match_operand:SI 3 "arm_hard_register_operand" ""))
5369      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5370           (match_operand:SI 4 "arm_hard_register_operand" ""))
5371      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5372           (match_operand:SI 5 "arm_hard_register_operand" ""))
5373      (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5374           (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5375   "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5376   "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5377   [(set_attr "predicable" "yes")
5378    (set_attr "type" "store4")]
5381 (define_insn "*stmsi_postinc3"
5382   [(match_parallel 0 "store_multiple_operation"
5383     [(set (match_operand:SI 1 "s_register_operand" "=r")
5384           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5385                    (const_int 12)))
5386      (set (mem:SI (match_dup 2))
5387           (match_operand:SI 3 "arm_hard_register_operand" ""))
5388      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5389           (match_operand:SI 4 "arm_hard_register_operand" ""))
5390      (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5391           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5392   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5393   "stm%?ia\\t%1!, {%3, %4, %5}"
5394   [(set_attr "predicable" "yes")
5395    (set_attr "type" "store3")]
5398 (define_insn "*stmsi_postinc2"
5399   [(match_parallel 0 "store_multiple_operation"
5400     [(set (match_operand:SI 1 "s_register_operand" "=r")
5401           (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5402                    (const_int 8)))
5403      (set (mem:SI (match_dup 2))
5404           (match_operand:SI 3 "arm_hard_register_operand" ""))
5405      (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5406           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5407   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5408   "stm%?ia\\t%1!, {%3, %4}"
5409   [(set_attr "predicable" "yes")
5410    (set_attr "type" "store2")]
5413 ;; Ordinary store multiple
5415 (define_insn "*stmsi4"
5416   [(match_parallel 0 "store_multiple_operation"
5417     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5418           (match_operand:SI 2 "arm_hard_register_operand" ""))
5419      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5420           (match_operand:SI 3 "arm_hard_register_operand" ""))
5421      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5422           (match_operand:SI 4 "arm_hard_register_operand" ""))
5423      (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5424           (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5425   "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5426   "stm%?ia\\t%1, {%2, %3, %4, %5}"
5427   [(set_attr "predicable" "yes")
5428    (set_attr "type" "store4")]
5431 (define_insn "*stmsi3"
5432   [(match_parallel 0 "store_multiple_operation"
5433     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5434           (match_operand:SI 2 "arm_hard_register_operand" ""))
5435      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5436           (match_operand:SI 3 "arm_hard_register_operand" ""))
5437      (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5438           (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5439   "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5440   "stm%?ia\\t%1, {%2, %3, %4}"
5441   [(set_attr "predicable" "yes")
5442    (set_attr "type" "store3")]
5445 (define_insn "*stmsi2"
5446   [(match_parallel 0 "store_multiple_operation"
5447     [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5448           (match_operand:SI 2 "arm_hard_register_operand" ""))
5449      (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5450           (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5451   "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5452   "stm%?ia\\t%1, {%2, %3}"
5453   [(set_attr "predicable" "yes")
5454    (set_attr "type" "store2")]
5457 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5458 ;; We could let this apply for blocks of less than this, but it clobbers so
5459 ;; many registers that there is then probably a better way.
5461 (define_expand "movstrqi"
5462   [(match_operand:BLK 0 "general_operand" "")
5463    (match_operand:BLK 1 "general_operand" "")
5464    (match_operand:SI 2 "const_int_operand" "")
5465    (match_operand:SI 3 "const_int_operand" "")]
5466   "TARGET_EITHER"
5467   "
5468   if (TARGET_ARM)
5469     {
5470       if (arm_gen_movstrqi (operands))
5471         DONE;
5472       FAIL;
5473     }
5474   else /* TARGET_THUMB */
5475     {
5476       if (   INTVAL (operands[3]) != 4
5477           || INTVAL (operands[2]) > 48)
5478         FAIL;
5480       thumb_expand_movstrqi (operands);
5481       DONE;
5482     }
5483   "
5486 ;; Thumb block-move insns
5488 (define_insn "movmem12b"
5489   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5490         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5491    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5492         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5493    (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5494         (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5495    (set (match_operand:SI 0 "register_operand" "=l")
5496         (plus:SI (match_dup 2) (const_int 12)))
5497    (set (match_operand:SI 1 "register_operand" "=l")
5498         (plus:SI (match_dup 3) (const_int 12)))
5499    (clobber (match_scratch:SI 4 "=&l"))
5500    (clobber (match_scratch:SI 5 "=&l"))
5501    (clobber (match_scratch:SI 6 "=&l"))]
5502   "TARGET_THUMB"
5503   "* return thumb_output_move_mem_multiple (3, operands);"
5504   [(set_attr "length" "4")
5505    ; This isn't entirely accurate...  It loads as well, but in terms of
5506    ; scheduling the following insn it is better to consider it as a store
5507    (set_attr "type" "store3")]
5510 (define_insn "movmem8b"
5511   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5512         (mem:SI (match_operand:SI 3 "register_operand" "1")))
5513    (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5514         (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5515    (set (match_operand:SI 0 "register_operand" "=l")
5516         (plus:SI (match_dup 2) (const_int 8)))
5517    (set (match_operand:SI 1 "register_operand" "=l")
5518         (plus:SI (match_dup 3) (const_int 8)))
5519    (clobber (match_scratch:SI 4 "=&l"))
5520    (clobber (match_scratch:SI 5 "=&l"))]
5521   "TARGET_THUMB"
5522   "* return thumb_output_move_mem_multiple (2, operands);"
5523   [(set_attr "length" "4")
5524    ; This isn't entirely accurate...  It loads as well, but in terms of
5525    ; scheduling the following insn it is better to consider it as a store
5526    (set_attr "type" "store2")]
5531 ;; Compare & branch insns
5532 ;; The range calcualations are based as follows:
5533 ;; For forward branches, the address calculation returns the address of
5534 ;; the next instruction.  This is 2 beyond the branch instruction.
5535 ;; For backward branches, the address calculation returns the address of
5536 ;; the first instruction in this pattern (cmp).  This is 2 before the branch
5537 ;; instruction for the shortest sequence, and 4 before the branch instruction
5538 ;; if we have to jump around an unconditional branch.
5539 ;; To the basic branch range the PC offset must be added (this is +4).
5540 ;; So for forward branches we have 
5541 ;;   (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5542 ;; And for backward branches we have 
5543 ;;   (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5545 ;; For a 'b'       pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5546 ;; For a 'b<cond>' pos_range = 254,  neg_range = -256  giving (-250 ->256).
5548 (define_insn "cbranchsi4"
5549   [(set (pc)
5550         (if_then_else
5551             (match_operator                    0 "arm_comparison_operator"
5552                             [(match_operand:SI 1 "register_operand"   "l,r")
5553                              (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5554             (label_ref       (match_operand    3 "" ""))
5555             (pc)))]
5556   "TARGET_THUMB"
5557   "*
5558   output_asm_insn (\"cmp\\t%1, %2\", operands);
5559   switch (get_attr_length (insn))
5560     {
5561     case 4:  return \"b%d0\\t%l3\";
5562     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5563     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5564     }
5565   "
5566   [(set (attr "far_jump")
5567         (if_then_else
5568             (eq_attr "length" "8")
5569             (const_string "yes")
5570             (const_string "no")))
5571    (set (attr "length") 
5572         (if_then_else
5573             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5574                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5575             (const_int 4)
5576             (if_then_else
5577                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5578                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5579                 (const_int 6)
5580                 (const_int 8))))]
5583 (define_insn "*negated_cbranchsi4"
5584   [(set (pc)
5585         (if_then_else
5586          (match_operator             0 "arm_comparison_operator"
5587           [(match_operand:SI         1 "register_operand"  "l")
5588            (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5589          (label_ref (match_operand   3 "" ""))
5590          (pc)))]
5591   "TARGET_THUMB"
5592   "*
5593   output_asm_insn (\"cmn\\t%1, %2\", operands);
5594   switch (get_attr_length (insn))
5595     {
5596     case 4:  return \"b%d0\\t%l3\";
5597     case 6:  return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5598     default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5599     }
5600   "
5601   [(set (attr "far_jump")
5602         (if_then_else
5603             (eq_attr "length" "8")
5604             (const_string "yes")
5605             (const_string "no")))
5606    (set (attr "length") 
5607         (if_then_else
5608             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5609                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5610             (const_int 4)
5611             (if_then_else
5612                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5613                      (le (minus (match_dup 3) (pc)) (const_int 2048)))
5614                 (const_int 6)
5615                 (const_int 8))))]
5619 ;; Comparison and test insns
5621 (define_expand "cmpsi"
5622   [(match_operand:SI 0 "s_register_operand" "")
5623    (match_operand:SI 1 "arm_add_operand" "")]
5624   "TARGET_ARM"
5625   "{
5626     arm_compare_op0 = operands[0];
5627     arm_compare_op1 = operands[1];
5628     DONE;
5629   }"
5632 (define_expand "cmpsf"
5633   [(match_operand:SF 0 "s_register_operand" "")
5634    (match_operand:SF 1 "fpu_rhs_operand" "")]
5635   "TARGET_ARM && TARGET_HARD_FLOAT"
5636   "
5637   arm_compare_op0 = operands[0];
5638   arm_compare_op1 = operands[1];
5639   DONE;
5640   "
5643 (define_expand "cmpdf"
5644   [(match_operand:DF 0 "s_register_operand" "")
5645    (match_operand:DF 1 "fpu_rhs_operand" "")]
5646   "TARGET_ARM && TARGET_HARD_FLOAT"
5647   "
5648   arm_compare_op0 = operands[0];
5649   arm_compare_op1 = operands[1];
5650   DONE;
5651   "
5654 (define_expand "cmpxf"
5655   [(match_operand:XF 0 "s_register_operand" "")
5656    (match_operand:XF 1 "fpu_rhs_operand" "")]
5657   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5658   "
5659   arm_compare_op0 = operands[0];
5660   arm_compare_op1 = operands[1];
5661   DONE;
5662   "
5665 (define_insn "*arm_cmpsi_insn"
5666   [(set (reg:CC CC_REGNUM)
5667         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5668                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5669   "TARGET_ARM"
5670   "@
5671    cmp%?\\t%0, %1
5672    cmn%?\\t%0, #%n1"
5673   [(set_attr "conds" "set")]
5676 (define_insn "*cmpsi_shiftsi"
5677   [(set (reg:CC CC_REGNUM)
5678         (compare:CC (match_operand:SI   0 "s_register_operand" "r")
5679                     (match_operator:SI  3 "shift_operator"
5680                      [(match_operand:SI 1 "s_register_operand" "r")
5681                       (match_operand:SI 2 "arm_rhs_operand"    "rM")])))]
5682   "TARGET_ARM"
5683   "cmp%?\\t%0, %1%S3"
5684   [(set_attr "conds" "set")
5685    (set_attr "shift" "1")
5686    ]
5689 (define_insn "*cmpsi_shiftsi_swp"
5690   [(set (reg:CC_SWP CC_REGNUM)
5691         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5692                          [(match_operand:SI 1 "s_register_operand" "r")
5693                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
5694                         (match_operand:SI 0 "s_register_operand" "r")))]
5695   "TARGET_ARM"
5696   "cmp%?\\t%0, %1%S3"
5697   [(set_attr "conds" "set")
5698    (set_attr "shift" "1")
5699    ]
5702 (define_insn "*cmpsi_neg_shiftsi"
5703   [(set (reg:CC CC_REGNUM)
5704         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5705                     (neg:SI (match_operator:SI 3 "shift_operator"
5706                              [(match_operand:SI 1 "s_register_operand" "r")
5707                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5708   "TARGET_ARM"
5709   "cmn%?\\t%0, %1%S3"
5710   [(set_attr "conds" "set")
5711    (set_attr "shift" "1")
5712    ]
5715 (define_insn "*cmpsf_insn"
5716   [(set (reg:CCFP CC_REGNUM)
5717         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5718                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5719   "TARGET_ARM && TARGET_HARD_FLOAT"
5720   "@
5721    cmf%?\\t%0, %1
5722    cnf%?\\t%0, #%N1"
5723   [(set_attr "conds" "set")
5724    (set_attr "type" "f_2_r")]
5727 (define_insn "*cmpdf_insn"
5728   [(set (reg:CCFP CC_REGNUM)
5729         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5730                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5731   "TARGET_ARM && TARGET_HARD_FLOAT"
5732   "@
5733    cmf%?\\t%0, %1
5734    cnf%?\\t%0, #%N1"
5735   [(set_attr "conds" "set")
5736    (set_attr "type" "f_2_r")]
5739 (define_insn "*cmpesfdf_df"
5740   [(set (reg:CCFP CC_REGNUM)
5741         (compare:CCFP (float_extend:DF
5742                        (match_operand:SF 0 "s_register_operand" "f,f"))
5743                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5744   "TARGET_ARM && TARGET_HARD_FLOAT"
5745   "@
5746    cmf%?\\t%0, %1
5747    cnf%?\\t%0, #%N1"
5748   [(set_attr "conds" "set")
5749    (set_attr "type" "f_2_r")]
5752 (define_insn "*cmpdf_esfdf"
5753   [(set (reg:CCFP CC_REGNUM)
5754         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5755                       (float_extend:DF
5756                        (match_operand:SF 1 "s_register_operand" "f"))))]
5757   "TARGET_ARM && TARGET_HARD_FLOAT"
5758   "cmf%?\\t%0, %1"
5759   [(set_attr "conds" "set")
5760    (set_attr "type" "f_2_r")]
5763 (define_insn "*cmpxf_insn"
5764   [(set (reg:CCFP CC_REGNUM)
5765         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5766                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5767   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5768   "@
5769    cmf%?\\t%0, %1
5770    cnf%?\\t%0, #%N1"
5771   [(set_attr "conds" "set")
5772    (set_attr "type" "f_2_r")]
5775 (define_insn "*cmpsf_trap"
5776   [(set (reg:CCFPE CC_REGNUM)
5777         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5778                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5779   "TARGET_ARM && TARGET_HARD_FLOAT"
5780   "@
5781    cmf%?e\\t%0, %1
5782    cnf%?e\\t%0, #%N1"
5783   [(set_attr "conds" "set")
5784    (set_attr "type" "f_2_r")]
5787 (define_insn "*cmpdf_trap"
5788   [(set (reg:CCFPE CC_REGNUM)
5789         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5790                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5791   "TARGET_ARM && TARGET_HARD_FLOAT"
5792   "@
5793    cmf%?e\\t%0, %1
5794    cnf%?e\\t%0, #%N1"
5795   [(set_attr "conds" "set")
5796    (set_attr "type" "f_2_r")]
5799 (define_insn "*cmp_esfdf_df_trap"
5800   [(set (reg:CCFPE CC_REGNUM)
5801         (compare:CCFPE (float_extend:DF
5802                         (match_operand:SF 0 "s_register_operand" "f,f"))
5803                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5804   "TARGET_ARM && TARGET_HARD_FLOAT"
5805   "@
5806    cmf%?e\\t%0, %1
5807    cnf%?e\\t%0, #%N1"
5808   [(set_attr "conds" "set")
5809    (set_attr "type" "f_2_r")]
5812 (define_insn "*cmp_df_esfdf_trap"
5813   [(set (reg:CCFPE CC_REGNUM)
5814         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5815                        (float_extend:DF
5816                         (match_operand:SF 1 "s_register_operand" "f"))))]
5817   "TARGET_ARM && TARGET_HARD_FLOAT"
5818   "cmf%?e\\t%0, %1"
5819   [(set_attr "conds" "set")
5820    (set_attr "type" "f_2_r")]
5823 (define_insn "*cmpxf_trap"
5824   [(set (reg:CCFPE CC_REGNUM)
5825         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5826                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5827   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5828   "@
5829    cmf%?e\\t%0, %1
5830    cnf%?e\\t%0, #%N1"
5831   [(set_attr "conds" "set")
5832    (set_attr "type" "f_2_r")]
5835 ; This insn allows redundant compares to be removed by cse, nothing should
5836 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5837 ; is deleted later on. The match_dup will match the mode here, so that
5838 ; mode changes of the condition codes aren't lost by this even though we don't
5839 ; specify what they are.
5841 (define_insn "*deleted_compare"
5842   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5843   "TARGET_ARM"
5844   "\\t%@ deleted compare"
5845   [(set_attr "conds" "set")
5846    (set_attr "length" "0")]
5850 ;; Conditional branch insns
5852 (define_expand "beq"
5853   [(set (pc)
5854         (if_then_else (eq (match_dup 1) (const_int 0))
5855                       (label_ref (match_operand 0 "" ""))
5856                       (pc)))]
5857   "TARGET_ARM"
5858   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5861 (define_expand "bne"
5862   [(set (pc)
5863         (if_then_else (ne (match_dup 1) (const_int 0))
5864                       (label_ref (match_operand 0 "" ""))
5865                       (pc)))]
5866   "TARGET_ARM"
5867   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5870 (define_expand "bgt"
5871   [(set (pc)
5872         (if_then_else (gt (match_dup 1) (const_int 0))
5873                       (label_ref (match_operand 0 "" ""))
5874                       (pc)))]
5875   "TARGET_ARM"
5876   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5879 (define_expand "ble"
5880   [(set (pc)
5881         (if_then_else (le (match_dup 1) (const_int 0))
5882                       (label_ref (match_operand 0 "" ""))
5883                       (pc)))]
5884   "TARGET_ARM"
5885   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5888 (define_expand "bge"
5889   [(set (pc)
5890         (if_then_else (ge (match_dup 1) (const_int 0))
5891                       (label_ref (match_operand 0 "" ""))
5892                       (pc)))]
5893   "TARGET_ARM"
5894   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5897 (define_expand "blt"
5898   [(set (pc)
5899         (if_then_else (lt (match_dup 1) (const_int 0))
5900                       (label_ref (match_operand 0 "" ""))
5901                       (pc)))]
5902   "TARGET_ARM"
5903   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5906 (define_expand "bgtu"
5907   [(set (pc)
5908         (if_then_else (gtu (match_dup 1) (const_int 0))
5909                       (label_ref (match_operand 0 "" ""))
5910                       (pc)))]
5911   "TARGET_ARM"
5912   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5915 (define_expand "bleu"
5916   [(set (pc)
5917         (if_then_else (leu (match_dup 1) (const_int 0))
5918                       (label_ref (match_operand 0 "" ""))
5919                       (pc)))]
5920   "TARGET_ARM"
5921   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5924 (define_expand "bgeu"
5925   [(set (pc)
5926         (if_then_else (geu (match_dup 1) (const_int 0))
5927                       (label_ref (match_operand 0 "" ""))
5928                       (pc)))]
5929   "TARGET_ARM"
5930   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5933 (define_expand "bltu"
5934   [(set (pc)
5935         (if_then_else (ltu (match_dup 1) (const_int 0))
5936                       (label_ref (match_operand 0 "" ""))
5937                       (pc)))]
5938   "TARGET_ARM"
5939   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5942 (define_expand "bunordered"
5943   [(set (pc)
5944         (if_then_else (unordered (match_dup 1) (const_int 0))
5945                       (label_ref (match_operand 0 "" ""))
5946                       (pc)))]
5947   "TARGET_ARM && TARGET_HARD_FLOAT"
5948   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5949                                       arm_compare_op1);"
5952 (define_expand "bordered"
5953   [(set (pc)
5954         (if_then_else (ordered (match_dup 1) (const_int 0))
5955                       (label_ref (match_operand 0 "" ""))
5956                       (pc)))]
5957   "TARGET_ARM && TARGET_HARD_FLOAT"
5958   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5959                                       arm_compare_op1);"
5962 (define_expand "bungt"
5963   [(set (pc)
5964         (if_then_else (ungt (match_dup 1) (const_int 0))
5965                       (label_ref (match_operand 0 "" ""))
5966                       (pc)))]
5967   "TARGET_ARM && TARGET_HARD_FLOAT"
5968   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5971 (define_expand "bunlt"
5972   [(set (pc)
5973         (if_then_else (unlt (match_dup 1) (const_int 0))
5974                       (label_ref (match_operand 0 "" ""))
5975                       (pc)))]
5976   "TARGET_ARM && TARGET_HARD_FLOAT"
5977   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5980 (define_expand "bunge"
5981   [(set (pc)
5982         (if_then_else (unge (match_dup 1) (const_int 0))
5983                       (label_ref (match_operand 0 "" ""))
5984                       (pc)))]
5985   "TARGET_ARM && TARGET_HARD_FLOAT"
5986   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5989 (define_expand "bunle"
5990   [(set (pc)
5991         (if_then_else (unle (match_dup 1) (const_int 0))
5992                       (label_ref (match_operand 0 "" ""))
5993                       (pc)))]
5994   "TARGET_ARM && TARGET_HARD_FLOAT"
5995   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5998 ;; The following two patterns need two branch instructions, since there is
5999 ;; no single instruction that will handle all cases.
6000 (define_expand "buneq"
6001   [(set (pc)
6002         (if_then_else (uneq (match_dup 1) (const_int 0))
6003                       (label_ref (match_operand 0 "" ""))
6004                       (pc)))]
6005   "TARGET_ARM && TARGET_HARD_FLOAT"
6006   "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6009 (define_expand "bltgt"
6010   [(set (pc)
6011         (if_then_else (ltgt (match_dup 1) (const_int 0))
6012                       (label_ref (match_operand 0 "" ""))
6013                       (pc)))]
6014   "TARGET_ARM && TARGET_HARD_FLOAT"
6015   "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6019 ;; Patterns to match conditional branch insns.
6022 ; Special pattern to match UNEQ.
6023 (define_insn "*arm_buneq"
6024   [(set (pc)
6025         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6026                       (label_ref (match_operand 0 "" ""))
6027                       (pc)))]
6028   "TARGET_ARM && TARGET_HARD_FLOAT"
6029   "*
6030   if (arm_ccfsm_state != 0)
6031     abort ();
6033   return \"bvs\\t%l0\;beq\\t%l0\";
6034   "
6035   [(set_attr "conds" "jump_clob")
6036    (set_attr "length" "8")]
6039 ; Special pattern to match LTGT.
6040 (define_insn "*arm_bltgt"
6041   [(set (pc)
6042         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6043                       (label_ref (match_operand 0 "" ""))
6044                       (pc)))]
6045   "TARGET_ARM && TARGET_HARD_FLOAT"
6046   "*
6047   if (arm_ccfsm_state != 0)
6048     abort ();
6050   return \"bmi\\t%l0\;bgt\\t%l0\";
6051   "
6052   [(set_attr "conds" "jump_clob")
6053    (set_attr "length" "8")]
6056 (define_insn "*arm_cond_branch"
6057   [(set (pc)
6058         (if_then_else (match_operator 1 "arm_comparison_operator"
6059                        [(match_operand 2 "cc_register" "") (const_int 0)])
6060                       (label_ref (match_operand 0 "" ""))
6061                       (pc)))]
6062   "TARGET_ARM"
6063   "*
6064   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6065     {
6066       arm_ccfsm_state += 2;
6067       return \"\";
6068     }
6069   return \"b%d1\\t%l0\";
6070   "
6071   [(set_attr "conds" "use")]
6074 ; Special pattern to match reversed UNEQ.
6075 (define_insn "*arm_buneq_reversed"
6076   [(set (pc)
6077         (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6078                       (pc)
6079                       (label_ref (match_operand 0 "" ""))))]
6080   "TARGET_ARM && TARGET_HARD_FLOAT"
6081   "*
6082   if (arm_ccfsm_state != 0)
6083     abort ();
6085   return \"bmi\\t%l0\;bgt\\t%l0\";
6086   "
6087   [(set_attr "conds" "jump_clob")
6088    (set_attr "length" "8")]
6091 ; Special pattern to match reversed LTGT.
6092 (define_insn "*arm_bltgt_reversed"
6093   [(set (pc)
6094         (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6095                       (pc)
6096                       (label_ref (match_operand 0 "" ""))))]
6097   "TARGET_ARM && TARGET_HARD_FLOAT"
6098   "*
6099   if (arm_ccfsm_state != 0)
6100     abort ();
6102   return \"bvs\\t%l0\;beq\\t%l0\";
6103   "
6104   [(set_attr "conds" "jump_clob")
6105    (set_attr "length" "8")]
6108 (define_insn "*arm_cond_branch_reversed"
6109   [(set (pc)
6110         (if_then_else (match_operator 1 "arm_comparison_operator"
6111                        [(match_operand 2 "cc_register" "") (const_int 0)])
6112                       (pc)
6113                       (label_ref (match_operand 0 "" ""))))]
6114   "TARGET_ARM"
6115   "*
6116   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6117     {
6118       arm_ccfsm_state += 2;
6119       return \"\";
6120     }
6121   return \"b%D1\\t%l0\";
6122   "
6123   [(set_attr "conds" "use")]
6128 ; scc insns
6130 (define_expand "seq"
6131   [(set (match_operand:SI 0 "s_register_operand" "=r")
6132         (eq:SI (match_dup 1) (const_int 0)))]
6133   "TARGET_ARM"
6134   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6137 (define_expand "sne"
6138   [(set (match_operand:SI 0 "s_register_operand" "=r")
6139         (ne:SI (match_dup 1) (const_int 0)))]
6140   "TARGET_ARM"
6141   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6144 (define_expand "sgt"
6145   [(set (match_operand:SI 0 "s_register_operand" "=r")
6146         (gt:SI (match_dup 1) (const_int 0)))]
6147   "TARGET_ARM"
6148   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6151 (define_expand "sle"
6152   [(set (match_operand:SI 0 "s_register_operand" "=r")
6153         (le:SI (match_dup 1) (const_int 0)))]
6154   "TARGET_ARM"
6155   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6158 (define_expand "sge"
6159   [(set (match_operand:SI 0 "s_register_operand" "=r")
6160         (ge:SI (match_dup 1) (const_int 0)))]
6161   "TARGET_ARM"
6162   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6165 (define_expand "slt"
6166   [(set (match_operand:SI 0 "s_register_operand" "=r")
6167         (lt:SI (match_dup 1) (const_int 0)))]
6168   "TARGET_ARM"
6169   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6172 (define_expand "sgtu"
6173   [(set (match_operand:SI 0 "s_register_operand" "=r")
6174         (gtu:SI (match_dup 1) (const_int 0)))]
6175   "TARGET_ARM"
6176   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6179 (define_expand "sleu"
6180   [(set (match_operand:SI 0 "s_register_operand" "=r")
6181         (leu:SI (match_dup 1) (const_int 0)))]
6182   "TARGET_ARM"
6183   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6186 (define_expand "sgeu"
6187   [(set (match_operand:SI 0 "s_register_operand" "=r")
6188         (geu:SI (match_dup 1) (const_int 0)))]
6189   "TARGET_ARM"
6190   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6193 (define_expand "sltu"
6194   [(set (match_operand:SI 0 "s_register_operand" "=r")
6195         (ltu:SI (match_dup 1) (const_int 0)))]
6196   "TARGET_ARM"
6197   "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6200 (define_expand "sunordered"
6201   [(set (match_operand:SI 0 "s_register_operand" "=r")
6202         (unordered:SI (match_dup 1) (const_int 0)))]
6203   "TARGET_ARM && TARGET_HARD_FLOAT"
6204   "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6205                                       arm_compare_op1);"
6208 (define_expand "sordered"
6209   [(set (match_operand:SI 0 "s_register_operand" "=r")
6210         (ordered:SI (match_dup 1) (const_int 0)))]
6211   "TARGET_ARM && TARGET_HARD_FLOAT"
6212   "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6213                                       arm_compare_op1);"
6216 (define_expand "sungt"
6217   [(set (match_operand:SI 0 "s_register_operand" "=r")
6218         (ungt:SI (match_dup 1) (const_int 0)))]
6219   "TARGET_ARM && TARGET_HARD_FLOAT"
6220   "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6221                                       arm_compare_op1);"
6224 (define_expand "sunge"
6225   [(set (match_operand:SI 0 "s_register_operand" "=r")
6226         (unge:SI (match_dup 1) (const_int 0)))]
6227   "TARGET_ARM && TARGET_HARD_FLOAT"
6228   "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6229                                       arm_compare_op1);"
6232 (define_expand "sunlt"
6233   [(set (match_operand:SI 0 "s_register_operand" "=r")
6234         (unlt:SI (match_dup 1) (const_int 0)))]
6235   "TARGET_ARM && TARGET_HARD_FLOAT"
6236   "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6237                                       arm_compare_op1);"
6240 (define_expand "sunle"
6241   [(set (match_operand:SI 0 "s_register_operand" "=r")
6242         (unle:SI (match_dup 1) (const_int 0)))]
6243   "TARGET_ARM && TARGET_HARD_FLOAT"
6244   "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6245                                       arm_compare_op1);"
6248 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6249 ;;; simple ARM instructions. 
6251 ; (define_expand "suneq"
6252 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6253 ;       (uneq:SI (match_dup 1) (const_int 0)))]
6254 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6255 ;   "abort ();"
6256 ; )
6258 ; (define_expand "sltgt"
6259 ;   [(set (match_operand:SI 0 "s_register_operand" "=r")
6260 ;       (ltgt:SI (match_dup 1) (const_int 0)))]
6261 ;   "TARGET_ARM && TARGET_HARD_FLOAT"
6262 ;   "abort ();"
6263 ; )
6265 (define_insn "*mov_scc"
6266   [(set (match_operand:SI 0 "s_register_operand" "=r")
6267         (match_operator:SI 1 "arm_comparison_operator"
6268          [(match_operand 2 "cc_register" "") (const_int 0)]))]
6269   "TARGET_ARM"
6270   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6271   [(set_attr "conds" "use")
6272    (set_attr "length" "8")]
6275 (define_insn "*mov_negscc"
6276   [(set (match_operand:SI 0 "s_register_operand" "=r")
6277         (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6278                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6279   "TARGET_ARM"
6280   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6281   [(set_attr "conds" "use")
6282    (set_attr "length" "8")]
6285 (define_insn "*mov_notscc"
6286   [(set (match_operand:SI 0 "s_register_operand" "=r")
6287         (not:SI (match_operator:SI 1 "arm_comparison_operator"
6288                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
6289   "TARGET_ARM"
6290   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6291   [(set_attr "conds" "use")
6292    (set_attr "length" "8")]
6296 ;; Conditional move insns
6298 (define_expand "movsicc"
6299   [(set (match_operand:SI 0 "s_register_operand" "")
6300         (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6301                          (match_operand:SI 2 "arm_not_operand" "")
6302                          (match_operand:SI 3 "arm_not_operand" "")))]
6303   "TARGET_ARM"
6304   "
6305   {
6306     enum rtx_code code = GET_CODE (operands[1]);
6307     rtx ccreg;
6309     if (code == UNEQ || code == LTGT)
6310       FAIL;
6312     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6313     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6314   }"
6317 (define_expand "movsfcc"
6318   [(set (match_operand:SF 0 "s_register_operand" "")
6319         (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6320                          (match_operand:SF 2 "s_register_operand" "")
6321                          (match_operand:SF 3 "nonmemory_operand" "")))]
6322   "TARGET_ARM"
6323   "
6324   {
6325     enum rtx_code code = GET_CODE (operands[1]);
6326     rtx ccreg;
6328     if (code == UNEQ || code == LTGT)
6329       FAIL;
6331     /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
6332        Otherwise, ensure it is a valid FP add operand */
6333     if ((!TARGET_HARD_FLOAT)
6334         || (!fpu_add_operand (operands[3], SFmode)))
6335       operands[3] = force_reg (SFmode, operands[3]);
6337     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6338     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6339   }"
6342 (define_expand "movdfcc"
6343   [(set (match_operand:DF 0 "s_register_operand" "")
6344         (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6345                          (match_operand:DF 2 "s_register_operand" "")
6346                          (match_operand:DF 3 "fpu_add_operand" "")))]
6347   "TARGET_ARM && TARGET_HARD_FLOAT"
6348   "
6349   {
6350     enum rtx_code code = GET_CODE (operands[1]);
6351     rtx ccreg;
6353     if (code == UNEQ || code == LTGT)
6354       FAIL;
6356     ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6357     operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6358   }"
6361 (define_insn "*movsicc_insn"
6362   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6363         (if_then_else:SI
6364          (match_operator 3 "arm_comparison_operator"
6365           [(match_operand 4 "cc_register" "") (const_int 0)])
6366          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6367          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6368   "TARGET_ARM"
6369   "@
6370    mov%D3\\t%0, %2
6371    mvn%D3\\t%0, #%B2
6372    mov%d3\\t%0, %1
6373    mvn%d3\\t%0, #%B1
6374    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6375    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6376    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6377    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6378   [(set_attr "length" "4,4,4,4,8,8,8,8")
6379    (set_attr "conds" "use")]
6382 (define_insn "*movsfcc_hard_insn"
6383   [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6384         (if_then_else:SF
6385          (match_operator 3 "arm_comparison_operator" 
6386           [(match_operand 4 "cc_register" "") (const_int 0)])
6387          (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6388          (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6389   "TARGET_ARM && TARGET_HARD_FLOAT"
6390   "@
6391    mvf%D3s\\t%0, %2
6392    mnf%D3s\\t%0, #%N2
6393    mvf%d3s\\t%0, %1
6394    mnf%d3s\\t%0, #%N1
6395    mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6396    mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6397    mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6398    mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6399   [(set_attr "length" "4,4,4,4,8,8,8,8")
6400    (set_attr "type" "ffarith")
6401    (set_attr "conds" "use")]
6404 (define_insn "*movsfcc_soft_insn"
6405   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6406         (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6407                           [(match_operand 4 "cc_register" "") (const_int 0)])
6408                          (match_operand:SF 1 "s_register_operand" "0,r")
6409                          (match_operand:SF 2 "s_register_operand" "r,0")))]
6410   "TARGET_ARM && TARGET_SOFT_FLOAT"
6411   "@
6412    mov%D3\\t%0, %2
6413    mov%d3\\t%0, %1"
6414   [(set_attr "conds" "use")]
6417 (define_insn "*movdfcc_insn"
6418   [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6419         (if_then_else:DF
6420          (match_operator 3 "arm_comparison_operator"
6421           [(match_operand 4 "cc_register" "") (const_int 0)])
6422          (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6423          (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6424   "TARGET_ARM && TARGET_HARD_FLOAT"
6425   "@
6426    mvf%D3d\\t%0, %2
6427    mnf%D3d\\t%0, #%N2
6428    mvf%d3d\\t%0, %1
6429    mnf%d3d\\t%0, #%N1
6430    mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6431    mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6432    mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6433    mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6434   [(set_attr "length" "4,4,4,4,8,8,8,8")
6435    (set_attr "type" "ffarith")
6436    (set_attr "conds" "use")]
6440 ;; Jump and linkage insns
6442 (define_expand "jump"
6443   [(set (pc)
6444         (label_ref (match_operand 0 "" "")))]
6445   "TARGET_EITHER"
6446   ""
6449 (define_insn "*arm_jump"
6450   [(set (pc)
6451         (label_ref (match_operand 0 "" "")))]
6452   "TARGET_ARM"
6453   "*
6454   {
6455     if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6456       {
6457         arm_ccfsm_state += 2;
6458         return \"\";
6459       }
6460     return \"b%?\\t%l0\";
6461   }
6462   "
6463   [(set_attr "predicable" "yes")]
6466 (define_insn "*thumb_jump"
6467   [(set (pc)
6468         (label_ref (match_operand 0 "" "")))]
6469   "TARGET_THUMB"
6470   "*
6471   if (get_attr_length (insn) == 2)
6472     return \"b\\t%l0\";
6473   return \"bl\\t%l0\\t%@ far jump\";
6474   "
6475   [(set (attr "far_jump")
6476         (if_then_else
6477             (eq_attr "length" "4")
6478             (const_string "yes")
6479             (const_string "no")))
6480    (set (attr "length") 
6481         (if_then_else
6482             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6483                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
6484             (const_int 2)
6485             (const_int 4)))]
6488 (define_expand "call"
6489   [(parallel [(call (match_operand 0 "memory_operand" "")
6490                     (match_operand 1 "general_operand" ""))
6491               (use (match_operand 2 "" ""))
6492               (clobber (reg:SI LR_REGNUM))])]
6493   "TARGET_EITHER"
6494   "
6495   {
6496     rtx callee;
6497     
6498     /* In an untyped call, we can get NULL for operand 2.  */
6499     if (operands[2] == NULL_RTX)
6500       operands[2] = const0_rtx;
6501       
6502     /* This is to decide if we should generate indirect calls by loading the
6503        32 bit address of the callee into a register before performing the
6504        branch and link.  operand[2] encodes the long_call/short_call
6505        attribute of the function being called.  This attribute is set whenever
6506        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6507        is used, and the short_call attribute can also be set if function is
6508        declared as static or if it has already been defined in the current
6509        compilation unit.  See arm.c and arm.h for info about this.  The third
6510        parameter to arm_is_longcall_p is used to tell it which pattern
6511        invoked it.  */
6512     callee  = XEXP (operands[0], 0);
6513     
6514     if (GET_CODE (callee) != REG
6515        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6516       XEXP (operands[0], 0) = force_reg (Pmode, callee);
6517   }"
6520 (define_insn "*call_reg"
6521   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6522          (match_operand 1 "" ""))
6523    (use (match_operand 2 "" ""))
6524    (clobber (reg:SI LR_REGNUM))]
6525   "TARGET_ARM"
6526   "*
6527   return output_call (operands);
6528   "
6529   ;; length is worst case, normally it is only two
6530   [(set_attr "length" "12")
6531    (set_attr "type" "call")]
6534 (define_insn "*call_mem"
6535   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6536          (match_operand 1 "" ""))
6537    (use (match_operand 2 "" ""))
6538    (clobber (reg:SI LR_REGNUM))]
6539   "TARGET_ARM"
6540   "*
6541   return output_call_mem (operands);
6542   "
6543   [(set_attr "length" "12")
6544    (set_attr "type" "call")]
6547 (define_insn "*call_indirect"
6548   [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6549          (match_operand 1 "" ""))
6550    (use (match_operand 2 "" ""))
6551    (clobber (reg:SI LR_REGNUM))]
6552   "TARGET_THUMB"
6553   "*
6554   {
6555     if (TARGET_CALLER_INTERWORKING)
6556       return \"bl\\t%__interwork_call_via_%0\";
6557     else
6558       return \"bl\\t%__call_via_%0\";
6559   }"
6560   [(set_attr "type" "call")]
6563 (define_insn "*call_value_indirect"
6564   [(set (match_operand 0 "" "=l")
6565         (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6566               (match_operand 2 "" "")))
6567    (use (match_operand 3 "" ""))
6568    (clobber (reg:SI LR_REGNUM))]
6569   "TARGET_THUMB"
6570   "*
6571   {
6572     if (TARGET_CALLER_INTERWORKING)
6573       return \"bl\\t%__interwork_call_via_%1\";
6574     else
6575       return \"bl\\t%__call_via_%1\";
6576   }"
6577   [(set_attr "type" "call")]
6580 (define_expand "call_value"
6581   [(parallel [(set (match_operand       0 "" "")
6582                    (call (match_operand 1 "memory_operand" "")
6583                          (match_operand 2 "general_operand" "")))
6584               (use (match_operand 3 "" ""))
6585               (clobber (reg:SI LR_REGNUM))])]
6586   "TARGET_EITHER"
6587   "
6588   {
6589     rtx callee = XEXP (operands[1], 0);
6590     
6591     /* In an untyped call, we can get NULL for operand 2.  */
6592     if (operands[3] == 0)
6593       operands[3] = const0_rtx;
6594       
6595     /* See the comment in define_expand \"call\".  */
6596     if (GET_CODE (callee) != REG
6597         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6598       XEXP (operands[1], 0) = force_reg (Pmode, callee);
6599   }"
6602 (define_insn "*call_value_reg"
6603   [(set (match_operand 0 "" "=r,f")
6604         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6605               (match_operand 2 "" "")))
6606    (use (match_operand 3 "" ""))
6607    (clobber (reg:SI LR_REGNUM))]
6608   "TARGET_ARM"
6609   "*
6610   return output_call (&operands[1]);
6611   "
6612   [(set_attr "length" "12")
6613    (set_attr "type" "call")]
6616 (define_insn "*call_value_mem"
6617   [(set (match_operand 0 "" "=r,f")
6618         (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6619               (match_operand 2 "" "")))
6620    (use (match_operand 3 "" ""))
6621    (clobber (reg:SI LR_REGNUM))]
6622   "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6623   "*
6624   return output_call_mem (&operands[1]);
6625   "
6626   [(set_attr "length" "12")
6627    (set_attr "type" "call")]
6630 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6631 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6633 (define_insn "*call_symbol"
6634   [(call (mem:SI (match_operand:SI 0 "" "X"))
6635          (match_operand 1 "" ""))
6636    (use (match_operand 2 "" ""))
6637    (clobber (reg:SI LR_REGNUM))]
6638   "TARGET_ARM
6639    && (GET_CODE (operands[0]) == SYMBOL_REF)
6640    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6641   "*
6642   {
6643     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6644   }"
6645   [(set_attr "type" "call")]
6648 (define_insn "*call_value_symbol"
6649   [(set (match_operand 0 "s_register_operand" "=r,f")
6650         (call (mem:SI (match_operand:SI 1 "" "X,X"))
6651         (match_operand:SI 2 "" "")))
6652    (use (match_operand 3 "" ""))
6653    (clobber (reg:SI LR_REGNUM))]
6654   "TARGET_ARM
6655    && (GET_CODE (operands[1]) == SYMBOL_REF)
6656    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6657   "*
6658   {
6659     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6660   }"
6661   [(set_attr "type" "call")]
6664 (define_insn "*call_insn"
6665   [(call (mem:SI (match_operand:SI 0 "" "X"))
6666          (match_operand:SI 1 "" ""))
6667    (use (match_operand 2 "" ""))
6668    (clobber (reg:SI LR_REGNUM))]
6669   "TARGET_THUMB
6670    && GET_CODE (operands[0]) == SYMBOL_REF
6671    && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6672   "bl\\t%a0"
6673   [(set_attr "length" "4")
6674    (set_attr "type" "call")]
6677 (define_insn "*call_value_insn"
6678   [(set (match_operand 0 "register_operand" "=l")
6679         (call (mem:SI (match_operand 1 "" "X"))
6680               (match_operand 2 "" "")))
6681    (use (match_operand 3 "" ""))
6682    (clobber (reg:SI LR_REGNUM))]
6683   "TARGET_THUMB
6684    && GET_CODE (operands[1]) == SYMBOL_REF
6685    && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6686   "bl\\t%a1"
6687   [(set_attr "length" "4")
6688    (set_attr "type" "call")]
6691 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6692 (define_expand "sibcall"
6693   [(parallel [(call (match_operand 0 "memory_operand" "")
6694                     (match_operand 1 "general_operand" ""))
6695               (return)
6696               (use (match_operand 2 "" ""))])]
6697   "TARGET_ARM"
6698   "
6699   {
6700     if (operands[2] == NULL_RTX)
6701       operands[2] = const0_rtx;
6702   }"
6705 (define_expand "sibcall_value"
6706   [(parallel [(set (match_operand 0 "register_operand" "")
6707                    (call (match_operand 1 "memory_operand" "")
6708                          (match_operand 2 "general_operand" "")))
6709               (return)
6710               (use (match_operand 3 "" ""))])]
6711   "TARGET_ARM"
6712   "
6713   {
6714     if (operands[3] == NULL_RTX)
6715       operands[3] = const0_rtx;
6716   }"
6719 (define_insn "*sibcall_insn"
6720  [(call (mem:SI (match_operand:SI 0 "" "X"))
6721         (match_operand 1 "" ""))
6722   (return)
6723   (use (match_operand 2 "" ""))]
6724   "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6725   "*
6726   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6727   "
6728   [(set_attr "type" "call")]
6731 (define_insn "*sibcall_value_insn"
6732  [(set (match_operand 0 "s_register_operand" "=r,f")
6733        (call (mem:SI (match_operand:SI 1 "" "X,X"))
6734              (match_operand 2 "" "")))
6735   (return)
6736   (use (match_operand 3 "" ""))]
6737   "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6738   "*
6739   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6740   "
6741   [(set_attr "type" "call")]
6744 ;; Often the return insn will be the same as loading from memory, so set attr
6745 (define_insn "return"
6746   [(return)]
6747   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6748   "*
6749   {
6750     if (arm_ccfsm_state == 2)
6751       {
6752         arm_ccfsm_state += 2;
6753         return \"\";
6754       }
6755     return output_return_instruction (const_true_rtx, TRUE, FALSE);
6756   }"
6757   [(set_attr "type" "load")
6758    (set_attr "predicable" "yes")]
6761 (define_insn "*cond_return"
6762   [(set (pc)
6763         (if_then_else (match_operator 0 "arm_comparison_operator"
6764                        [(match_operand 1 "cc_register" "") (const_int 0)])
6765                       (return)
6766                       (pc)))]
6767   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6768   "*
6769   {
6770     if (arm_ccfsm_state == 2)
6771       {
6772         arm_ccfsm_state += 2;
6773         return \"\";
6774       }
6775     return output_return_instruction (operands[0], TRUE, FALSE);
6776   }"
6777   [(set_attr "conds" "use")
6778    (set_attr "type" "load")]
6781 (define_insn "*cond_return_inverted"
6782   [(set (pc)
6783         (if_then_else (match_operator 0 "arm_comparison_operator"
6784                        [(match_operand 1 "cc_register" "") (const_int 0)])
6785                       (pc)
6786                       (return)))]
6787   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6788   "*
6789   {
6790     if (arm_ccfsm_state == 2)
6791       {
6792         arm_ccfsm_state += 2;
6793         return \"\";
6794       }
6795     return output_return_instruction (operands[0], TRUE, TRUE);
6796   }"
6797   [(set_attr "conds" "use")
6798    (set_attr "type" "load")]
6801 ;; Generate a sequence of instructions to determine if the processor is
6802 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6803 ;; mask.
6805 (define_expand "return_addr_mask"
6806   [(set (match_dup 1)
6807       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6808                        (const_int 0)))
6809    (set (match_operand:SI 0 "s_register_operand" "")
6810       (if_then_else:SI (eq (match_dup 1) (const_int 0))
6811                        (const_int -1)
6812                        (const_int 67108860)))] ; 0x03fffffc
6813   "TARGET_ARM"
6814   "
6815   operands[1] = gen_rtx_REG (CC_NOOVmode, 24);
6816   ")
6818 (define_insn "*check_arch2"
6819   [(set (match_operand:CC_NOOV 0 "cc_register" "")
6820       (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6821                        (const_int 0)))]
6822   "TARGET_ARM"
6823   "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6824   [(set_attr "length" "8")
6825    (set_attr "conds" "set")]
6828 ;; Call subroutine returning any type.
6830 (define_expand "untyped_call"
6831   [(parallel [(call (match_operand 0 "" "")
6832                     (const_int 0))
6833               (match_operand 1 "" "")
6834               (match_operand 2 "" "")])]
6835   "TARGET_ARM"
6836   "
6837   {
6838     int i;
6840     emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6842     for (i = 0; i < XVECLEN (operands[2], 0); i++)
6843       {
6844         rtx set = XVECEXP (operands[2], 0, i);
6846         emit_move_insn (SET_DEST (set), SET_SRC (set));
6847       }
6849     /* The optimizer does not know that the call sets the function value
6850        registers we stored in the result block.  We avoid problems by
6851        claiming that all hard registers are used and clobbered at this
6852        point.  */
6853     emit_insn (gen_blockage ());
6855     DONE;
6856   }"
6859 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6860 ;; all of memory.  This blocks insns from being moved across this point.
6862 (define_insn "blockage"
6863   [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6864   "TARGET_EITHER"
6865   ""
6866   [(set_attr "length" "0")
6867    (set_attr "type" "block")]
6870 (define_expand "casesi"
6871   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6872    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
6873    (match_operand:SI 2 "const_int_operand" "")  ; total range
6874    (match_operand:SI 3 "" "")                   ; table label
6875    (match_operand:SI 4 "" "")]                  ; Out of range label
6876   "TARGET_ARM"
6877   "
6878   {
6879     rtx reg;
6880     if (operands[1] != const0_rtx)
6881       {
6882         reg = gen_reg_rtx (SImode);
6884         emit_insn (gen_addsi3 (reg, operands[0],
6885                                GEN_INT (-INTVAL (operands[1]))));
6886         operands[0] = reg;
6887       }
6889     if (!const_ok_for_arm (INTVAL (operands[2])))
6890       operands[2] = force_reg (SImode, operands[2]);
6892     emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6893                                          operands[4]));
6894     DONE;
6895   }"
6898 ;; The USE in this pattern is needed to tell flow analysis that this is
6899 ;; a CASESI insn.  It has no other purpose.
6900 (define_insn "casesi_internal"
6901   [(parallel [(set (pc)
6902                (if_then_else
6903                 (leu (match_operand:SI 0 "s_register_operand" "r")
6904                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
6905                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6906                                  (label_ref (match_operand 2 "" ""))))
6907                 (label_ref (match_operand 3 "" ""))))
6908               (clobber (reg:CC CC_REGNUM))
6909               (use (label_ref (match_dup 2)))])]
6910   "TARGET_ARM"
6911   "*
6912     if (flag_pic)
6913       return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6914     return   \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6915   "
6916   [(set_attr "conds" "clob")
6917    (set_attr "length" "12")]
6920 (define_expand "indirect_jump"
6921   [(set (pc)
6922         (match_operand:SI 0 "s_register_operand" ""))]
6923   "TARGET_EITHER"
6924   ""
6927 (define_insn "*arm_indirect_jump"
6928   [(set (pc)
6929         (match_operand:SI 0 "s_register_operand" "r"))]
6930   "TARGET_ARM"
6931   "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6932   [(set_attr "predicable" "yes")]
6935 ;; Although not supported by the define_expand above,
6936 ;; cse/combine may generate this form.
6937 (define_insn "*load_indirect_jump"
6938   [(set (pc)
6939         (match_operand:SI 0 "memory_operand" "m"))]
6940   "TARGET_ARM"
6941   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6942   [(set_attr "type" "load")
6943    (set_attr "pool_range" "4096")
6944    (set_attr "neg_pool_range" "4084")
6945    (set_attr "predicable" "yes")]
6948 (define_insn "*thumb_indirect_jump"
6949   [(set (pc)
6950         (match_operand:SI 0 "register_operand" "l*r"))]
6951   "TARGET_THUMB"
6952   "mov\\tpc, %0"
6953   [(set_attr "conds" "clob")
6954    (set_attr "length" "2")]
6958 ;; Misc insns
6960 (define_insn "nop"
6961   [(const_int 0)]
6962   "TARGET_EITHER"
6963   "*
6964   if (TARGET_ARM)
6965     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6966   return  \"mov\\tr8, r8\";
6967   "
6968   [(set (attr "length")
6969         (if_then_else (eq_attr "is_thumb" "yes")
6970                       (const_int 2)
6971                       (const_int 4)))]
6975 ;; Patterns to allow combination of arithmetic, cond code and shifts
6977 (define_insn "*arith_shiftsi"
6978   [(set (match_operand:SI 0 "s_register_operand" "=r")
6979         (match_operator:SI 1 "shiftable_operator"
6980           [(match_operator:SI 3 "shift_operator"
6981              [(match_operand:SI 4 "s_register_operand" "r")
6982               (match_operand:SI 5 "reg_or_int_operand" "rI")])
6983            (match_operand:SI 2 "s_register_operand" "r")]))]
6984   "TARGET_ARM"
6985   "%i1%?\\t%0, %2, %4%S3"
6986   [(set_attr "predicable" "yes")
6987    (set_attr "shift" "4")
6988    ]
6991 (define_insn "*arith_shiftsi_compare0"
6992   [(set (reg:CC_NOOV CC_REGNUM)
6993         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6994                           [(match_operator:SI 3 "shift_operator"
6995                             [(match_operand:SI 4 "s_register_operand" "r")
6996                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
6997                            (match_operand:SI 2 "s_register_operand" "r")])
6998                          (const_int 0)))
6999    (set (match_operand:SI 0 "s_register_operand" "=r")
7000         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7001                          (match_dup 2)]))]
7002   "TARGET_ARM"
7003   "%i1%?s\\t%0, %2, %4%S3"
7004   [(set_attr "conds" "set")
7005    (set_attr "shift" "4")
7006    ]
7009 (define_insn "*arith_shiftsi_compare0_scratch"
7010   [(set (reg:CC_NOOV CC_REGNUM)
7011         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7012                           [(match_operator:SI 3 "shift_operator"
7013                             [(match_operand:SI 4 "s_register_operand" "r")
7014                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
7015                            (match_operand:SI 2 "s_register_operand" "r")])
7016                          (const_int 0)))
7017    (clobber (match_scratch:SI 0 "=r"))]
7018   "TARGET_ARM"
7019   "%i1%?s\\t%0, %2, %4%S3"
7020   [(set_attr "conds" "set")
7021    (set_attr "shift" "4")
7022    ]
7025 (define_insn "*sub_shiftsi"
7026   [(set (match_operand:SI 0 "s_register_operand" "=r")
7027         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7028                   (match_operator:SI 2 "shift_operator"
7029                    [(match_operand:SI 3 "s_register_operand" "r")
7030                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7031   "TARGET_ARM"
7032   "sub%?\\t%0, %1, %3%S2"
7033   [(set_attr "predicable" "yes")
7034    (set_attr "shift" "3")
7035    ]
7038 (define_insn "*sub_shiftsi_compare0"
7039   [(set (reg:CC_NOOV CC_REGNUM)
7040         (compare:CC_NOOV
7041          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7042                    (match_operator:SI 2 "shift_operator"
7043                     [(match_operand:SI 3 "s_register_operand" "r")
7044                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7045          (const_int 0)))
7046    (set (match_operand:SI 0 "s_register_operand" "=r")
7047         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7048                                                  (match_dup 4)])))]
7049   "TARGET_ARM"
7050   "sub%?s\\t%0, %1, %3%S2"
7051   [(set_attr "conds" "set")
7052    (set_attr "shift" "3") 
7053    ]
7056 (define_insn "*sub_shiftsi_compare0_scratch"
7057   [(set (reg:CC_NOOV CC_REGNUM)
7058         (compare:CC_NOOV
7059          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7060                    (match_operator:SI 2 "shift_operator"
7061                     [(match_operand:SI 3 "s_register_operand" "r")
7062                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7063          (const_int 0)))
7064    (clobber (match_scratch:SI 0 "=r"))]
7065   "TARGET_ARM"
7066   "sub%?s\\t%0, %1, %3%S2"
7067   [(set_attr "conds" "set")
7068    (set_attr "shift" "3") 
7069    ]
7074 (define_insn "*and_scc"
7075   [(set (match_operand:SI 0 "s_register_operand" "=r")
7076         (and:SI (match_operator:SI 1 "arm_comparison_operator"
7077                  [(match_operand 3 "cc_register" "") (const_int 0)])
7078                 (match_operand:SI 2 "s_register_operand" "r")))]
7079   "TARGET_ARM"
7080   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7081   [(set_attr "conds" "use")
7082    (set_attr "length" "8")]
7085 (define_insn "*ior_scc"
7086   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7087         (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7088                  [(match_operand 3 "cc_register" "") (const_int 0)])
7089                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7090   "TARGET_ARM"
7091   "@
7092    orr%d2\\t%0, %1, #1
7093    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7094   [(set_attr "conds" "use")
7095    (set_attr "length" "4,8")]
7098 (define_insn "*compare_scc"
7099   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7100         (match_operator:SI 1 "arm_comparison_operator"
7101          [(match_operand:SI 2 "s_register_operand" "r,r")
7102           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7103    (clobber (reg:CC CC_REGNUM))]
7104   "TARGET_ARM"
7105   "*
7106     if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7107       return \"mov\\t%0, %2, lsr #31\";
7109     if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7110       return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7112     if (GET_CODE (operands[1]) == NE)
7113       {
7114         if (which_alternative == 1)
7115           return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7116         return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7117       }
7118     if (which_alternative == 1)
7119       output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7120     else
7121       output_asm_insn (\"cmp\\t%2, %3\", operands);
7122     return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7123   "
7124   [(set_attr "conds" "clob")
7125    (set_attr "length" "12")]
7128 (define_insn "*cond_move"
7129   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7130         (if_then_else:SI (match_operator 3 "equality_operator"
7131                           [(match_operator 4 "arm_comparison_operator"
7132                             [(match_operand 5 "cc_register" "") (const_int 0)])
7133                            (const_int 0)])
7134                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7135                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7136   "TARGET_ARM"
7137   "*
7138     if (GET_CODE (operands[3]) == NE)
7139       {
7140         if (which_alternative != 1)
7141           output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7142         if (which_alternative != 0)
7143           output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7144         return \"\";
7145       }
7146     if (which_alternative != 0)
7147       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7148     if (which_alternative != 1)
7149       output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7150     return \"\";
7151   "
7152   [(set_attr "conds" "use")
7153    (set_attr "length" "4,4,8")]
7156 (define_insn "*cond_arith"
7157   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7158         (match_operator:SI 5 "shiftable_operator" 
7159          [(match_operator:SI 4 "arm_comparison_operator"
7160            [(match_operand:SI 2 "s_register_operand" "r,r")
7161             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7162           (match_operand:SI 1 "s_register_operand" "0,?r")]))
7163    (clobber (reg:CC CC_REGNUM))]
7164   "TARGET_ARM"
7165   "*
7166     if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7167       return \"%i5\\t%0, %1, %2, lsr #31\";
7169     output_asm_insn (\"cmp\\t%2, %3\", operands);
7170     if (GET_CODE (operands[5]) == AND)
7171       output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7172     else if (GET_CODE (operands[5]) == MINUS)
7173       output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7174     else if (which_alternative != 0)
7175       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7176     return \"%i5%d4\\t%0, %1, #1\";
7177   "
7178   [(set_attr "conds" "clob")
7179    (set_attr "length" "12")]
7182 (define_insn "*cond_sub"
7183   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7184         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7185                   (match_operator:SI 4 "arm_comparison_operator"
7186                    [(match_operand:SI 2 "s_register_operand" "r,r")
7187                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7188    (clobber (reg:CC CC_REGNUM))]
7189   "TARGET_ARM"
7190   "*
7191     output_asm_insn (\"cmp\\t%2, %3\", operands);
7192     if (which_alternative != 0)
7193       output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7194     return \"sub%d4\\t%0, %1, #1\";
7195   "
7196   [(set_attr "conds" "clob")
7197    (set_attr "length" "8,12")]
7200 (define_insn "*cmp_ite0"
7201   [(set (match_operand 6 "dominant_cc_register" "")
7202         (compare
7203          (if_then_else:SI
7204           (match_operator 4 "arm_comparison_operator"
7205            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7206             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7207           (match_operator:SI 5 "arm_comparison_operator"
7208            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7209             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7210           (const_int 0))
7211          (const_int 0)))]
7212   "TARGET_ARM"
7213   "*
7214   {
7215     static const char * const opcodes[4][2] =
7216     {
7217       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7218        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7219       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7220        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7221       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7222        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7223       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7224        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7225     };
7226     int swap =
7227       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7229     return opcodes[which_alternative][swap];
7230   }"
7231   [(set_attr "conds" "set")
7232    (set_attr "length" "8")]
7235 (define_insn "*cmp_ite1"
7236   [(set (match_operand 6 "dominant_cc_register" "")
7237         (compare
7238          (if_then_else:SI
7239           (match_operator 4 "arm_comparison_operator"
7240            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7241             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7242           (match_operator:SI 5 "arm_comparison_operator"
7243            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7244             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7245           (const_int 1))
7246          (const_int 0)))]
7247   "TARGET_ARM"
7248   "*
7249   {
7250     static const char * const opcodes[4][2] =
7251     {
7252       {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7253        \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7254       {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7255        \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7256       {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7257        \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7258       {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7259        \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7260     };
7261     int swap =
7262       comparison_dominates_p (GET_CODE (operands[5]),
7263                               reverse_condition (GET_CODE (operands[4])));
7265     return opcodes[which_alternative][swap];
7266   }"
7267   [(set_attr "conds" "set")
7268    (set_attr "length" "8")]
7271 (define_insn "*cmp_and"
7272   [(set (match_operand 6 "dominant_cc_register" "")
7273         (compare
7274          (and:SI
7275           (match_operator 4 "arm_comparison_operator"
7276            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7277             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7278           (match_operator:SI 5 "arm_comparison_operator"
7279            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7280             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7281          (const_int 0)))]
7282   "TARGET_ARM"
7283   "*
7284   {
7285     static const char *const opcodes[4][2] =
7286     {
7287       {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7288        \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7289       {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7290        \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7291       {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7292        \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7293       {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7294        \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7295     };
7296     int swap =
7297       comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7299     return opcodes[which_alternative][swap];
7300   }"
7301   [(set_attr "conds" "set")
7302    (set_attr "predicable" "no")
7303    (set_attr "length" "8")]
7306 (define_insn "*cmp_ior"
7307   [(set (match_operand 6 "dominant_cc_register" "")
7308         (compare
7309          (ior:SI
7310           (match_operator 4 "arm_comparison_operator"
7311            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7312             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7313           (match_operator:SI 5 "arm_comparison_operator"
7314            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7315             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7316          (const_int 0)))]
7317   "TARGET_ARM"
7318   "*
7320   static const char *const opcodes[4][2] =
7321   {
7322     {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7323      \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7324     {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7325      \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7326     {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7327      \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7328     {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7329      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7330   };
7331   int swap =
7332     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7334   return opcodes[which_alternative][swap];
7337   [(set_attr "conds" "set")
7338    (set_attr "length" "8")]
7341 (define_insn "*negscc"
7342   [(set (match_operand:SI 0 "s_register_operand" "=r")
7343         (neg:SI (match_operator 3 "arm_comparison_operator"
7344                  [(match_operand:SI 1 "s_register_operand" "r")
7345                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7346    (clobber (reg:CC CC_REGNUM))]
7347   "TARGET_ARM"
7348   "*
7349   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7350     return \"mov\\t%0, %1, asr #31\";
7352   if (GET_CODE (operands[3]) == NE)
7353     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7355   if (GET_CODE (operands[3]) == GT)
7356     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7358   output_asm_insn (\"cmp\\t%1, %2\", operands);
7359   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7360   return \"mvn%d3\\t%0, #0\";
7361   "
7362   [(set_attr "conds" "clob")
7363    (set_attr "length" "12")]
7366 (define_insn "movcond"
7367   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7368         (if_then_else:SI
7369          (match_operator 5 "arm_comparison_operator"
7370           [(match_operand:SI 3 "s_register_operand" "r,r,r")
7371            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7372          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7373          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7374    (clobber (reg:CC CC_REGNUM))]
7375   "TARGET_ARM"
7376   "*
7377   if (GET_CODE (operands[5]) == LT
7378       && (operands[4] == const0_rtx))
7379     {
7380       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7381         {
7382           if (operands[2] == const0_rtx)
7383             return \"and\\t%0, %1, %3, asr #31\";
7384           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7385         }
7386       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7387         {
7388           if (operands[1] == const0_rtx)
7389             return \"bic\\t%0, %2, %3, asr #31\";
7390           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7391         }
7392       /* The only case that falls through to here is when both ops 1 & 2
7393          are constants */
7394     }
7396   if (GET_CODE (operands[5]) == GE
7397       && (operands[4] == const0_rtx))
7398     {
7399       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7400         {
7401           if (operands[2] == const0_rtx)
7402             return \"bic\\t%0, %1, %3, asr #31\";
7403           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7404         }
7405       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7406         {
7407           if (operands[1] == const0_rtx)
7408             return \"and\\t%0, %2, %3, asr #31\";
7409           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7410         }
7411       /* The only case that falls through to here is when both ops 1 & 2
7412          are constants */
7413     }
7414   if (GET_CODE (operands[4]) == CONST_INT
7415       && !const_ok_for_arm (INTVAL (operands[4])))
7416     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7417   else
7418     output_asm_insn (\"cmp\\t%3, %4\", operands);
7419   if (which_alternative != 0)
7420     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7421   if (which_alternative != 1)
7422     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7423   return \"\";
7424   "
7425   [(set_attr "conds" "clob")
7426    (set_attr "length" "8,8,12")]
7429 (define_insn "*ifcompare_plus_move"
7430   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7431         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7432                           [(match_operand:SI 4 "s_register_operand" "r,r")
7433                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7434                          (plus:SI
7435                           (match_operand:SI 2 "s_register_operand" "r,r")
7436                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7437                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7438    (clobber (reg:CC CC_REGNUM))]
7439   "TARGET_ARM"
7440   "#"
7441   [(set_attr "conds" "clob")
7442    (set_attr "length" "8,12")]
7445 (define_insn "*if_plus_move"
7446   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7447         (if_then_else:SI
7448          (match_operator 4 "arm_comparison_operator"
7449           [(match_operand 5 "cc_register" "") (const_int 0)])
7450          (plus:SI
7451           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7452           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7453          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7454   "TARGET_ARM"
7455   "@
7456    add%d4\\t%0, %2, %3
7457    sub%d4\\t%0, %2, #%n3
7458    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7459    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7460   [(set_attr "conds" "use")
7461    (set_attr "length" "4,4,8,8")
7462    (set_attr "type" "*,*,*,*")]
7465 (define_insn "*ifcompare_move_plus"
7466   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7467         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7468                           [(match_operand:SI 4 "s_register_operand" "r,r")
7469                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7470                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7471                          (plus:SI
7472                           (match_operand:SI 2 "s_register_operand" "r,r")
7473                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7474    (clobber (reg:CC CC_REGNUM))]
7475   "TARGET_ARM"
7476   "#"
7477   [(set_attr "conds" "clob")
7478    (set_attr "length" "8,12")]
7481 (define_insn "*if_move_plus"
7482   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7483         (if_then_else:SI
7484          (match_operator 4 "arm_comparison_operator"
7485           [(match_operand 5 "cc_register" "") (const_int 0)])
7486          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7487          (plus:SI
7488           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7489           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7490   "TARGET_ARM"
7491   "@
7492    add%D4\\t%0, %2, %3
7493    sub%D4\\t%0, %2, #%n3
7494    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7495    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7496   [(set_attr "conds" "use")
7497    (set_attr "length" "4,4,8,8")
7498    (set_attr "type" "*,*,*,*")]
7501 (define_insn "*ifcompare_arith_arith"
7502   [(set (match_operand:SI 0 "s_register_operand" "=r")
7503         (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7504                           [(match_operand:SI 5 "s_register_operand" "r")
7505                            (match_operand:SI 6 "arm_add_operand" "rIL")])
7506                          (match_operator:SI 8 "shiftable_operator"
7507                           [(match_operand:SI 1 "s_register_operand" "r")
7508                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7509                          (match_operator:SI 7 "shiftable_operator"
7510                           [(match_operand:SI 3 "s_register_operand" "r")
7511                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7512    (clobber (reg:CC CC_REGNUM))]
7513   "TARGET_ARM"
7514   "#"
7515   [(set_attr "conds" "clob")
7516    (set_attr "length" "12")]
7519 (define_insn "*if_arith_arith"
7520   [(set (match_operand:SI 0 "s_register_operand" "=r")
7521         (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7522                           [(match_operand 8 "cc_register" "") (const_int 0)])
7523                          (match_operator:SI 6 "shiftable_operator"
7524                           [(match_operand:SI 1 "s_register_operand" "r")
7525                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
7526                          (match_operator:SI 7 "shiftable_operator"
7527                           [(match_operand:SI 3 "s_register_operand" "r")
7528                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7529   "TARGET_ARM"
7530   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7531   [(set_attr "conds" "use")
7532    (set_attr "length" "8")]
7535 (define_insn "*ifcompare_arith_move"
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 2 "s_register_operand" "r,r")
7539                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7540                          (match_operator:SI 7 "shiftable_operator"
7541                           [(match_operand:SI 4 "s_register_operand" "r,r")
7542                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7543                          (match_operand:SI 1 "arm_rhs_operand" "0,?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[3] == const0_rtx
7551       && GET_CODE (operands[7]) != AND
7552       && GET_CODE (operands[5]) == REG
7553       && GET_CODE (operands[1]) == REG 
7554       && REGNO (operands[1]) == REGNO (operands[4])
7555       && REGNO (operands[4]) != REGNO (operands[0]))
7556     {
7557       if (GET_CODE (operands[6]) == LT)
7558         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7559       else if (GET_CODE (operands[6]) == GE)
7560         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7561     }
7562   if (GET_CODE (operands[3]) == CONST_INT
7563       && !const_ok_for_arm (INTVAL (operands[3])))
7564     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7565   else
7566     output_asm_insn (\"cmp\\t%2, %3\", operands);
7567   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7568   if (which_alternative != 0)
7569     return \"mov%D6\\t%0, %1\";
7570   return \"\";
7571   "
7572   [(set_attr "conds" "clob")
7573    (set_attr "length" "8,12")]
7576 (define_insn "*if_arith_move"
7577   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7578         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7579                           [(match_operand 6 "cc_register" "") (const_int 0)])
7580                          (match_operator:SI 5 "shiftable_operator"
7581                           [(match_operand:SI 2 "s_register_operand" "r,r")
7582                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7583                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7584   "TARGET_ARM"
7585   "@
7586    %I5%d4\\t%0, %2, %3
7587    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7588   [(set_attr "conds" "use")
7589    (set_attr "length" "4,8")
7590    (set_attr "type" "*,*")]
7593 (define_insn "*ifcompare_move_arith"
7594   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7595         (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7596                           [(match_operand:SI 4 "s_register_operand" "r,r")
7597                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7598                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7599                          (match_operator:SI 7 "shiftable_operator"
7600                           [(match_operand:SI 2 "s_register_operand" "r,r")
7601                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7602    (clobber (reg:CC CC_REGNUM))]
7603   "TARGET_ARM"
7604   "*
7605   /* If we have an operation where (op x 0) is the identity operation and
7606      the conditional operator is LT or GE and we are comparing against zero and
7607      everything is in registers then we can do this in two instructions */
7608   if (operands[5] == const0_rtx
7609       && GET_CODE (operands[7]) != AND
7610       && GET_CODE (operands[3]) == REG
7611       && GET_CODE (operands[1]) == REG 
7612       && REGNO (operands[1]) == REGNO (operands[2])
7613       && REGNO (operands[2]) != REGNO (operands[0]))
7614     {
7615       if (GET_CODE (operands[6]) == GE)
7616         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7617       else if (GET_CODE (operands[6]) == LT)
7618         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7619     }
7621   if (GET_CODE (operands[5]) == CONST_INT
7622       && !const_ok_for_arm (INTVAL (operands[5])))
7623     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7624   else
7625     output_asm_insn (\"cmp\\t%4, %5\", operands);
7627   if (which_alternative != 0)
7628     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7629   return \"%I7%D6\\t%0, %2, %3\";
7630   "
7631   [(set_attr "conds" "clob")
7632    (set_attr "length" "8,12")]
7635 (define_insn "*if_move_arith"
7636   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7637         (if_then_else:SI
7638          (match_operator 4 "arm_comparison_operator"
7639           [(match_operand 6 "cc_register" "") (const_int 0)])
7640          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7641          (match_operator:SI 5 "shiftable_operator"
7642           [(match_operand:SI 2 "s_register_operand" "r,r")
7643            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7644   "TARGET_ARM"
7645   "@
7646    %I5%D4\\t%0, %2, %3
7647    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7648   [(set_attr "conds" "use")
7649    (set_attr "length" "4,8")
7650    (set_attr "type" "*,*")]
7653 (define_insn "*ifcompare_move_not"
7654   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7655         (if_then_else:SI
7656          (match_operator 5 "arm_comparison_operator"
7657           [(match_operand:SI 3 "s_register_operand" "r,r")
7658            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7659          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7660          (not:SI
7661           (match_operand:SI 2 "s_register_operand" "r,r"))))
7662    (clobber (reg:CC CC_REGNUM))]
7663   "TARGET_ARM"
7664   "#"
7665   [(set_attr "conds" "clob")
7666    (set_attr "length" "8,12")]
7669 (define_insn "*if_move_not"
7670   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7671         (if_then_else:SI
7672          (match_operator 4 "arm_comparison_operator"
7673           [(match_operand 3 "cc_register" "") (const_int 0)])
7674          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7675          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7676   "TARGET_ARM"
7677   "@
7678    mvn%D4\\t%0, %2
7679    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7680    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7681   [(set_attr "conds" "use")
7682    (set_attr "length" "4,8,8")]
7685 (define_insn "*ifcompare_not_move"
7686   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7687         (if_then_else:SI 
7688          (match_operator 5 "arm_comparison_operator"
7689           [(match_operand:SI 3 "s_register_operand" "r,r")
7690            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7691          (not:SI
7692           (match_operand:SI 2 "s_register_operand" "r,r"))
7693          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7694    (clobber (reg:CC CC_REGNUM))]
7695   "TARGET_ARM"
7696   "#"
7697   [(set_attr "conds" "clob")
7698    (set_attr "length" "8,12")]
7701 (define_insn "*if_not_move"
7702   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7703         (if_then_else:SI
7704          (match_operator 4 "arm_comparison_operator"
7705           [(match_operand 3 "cc_register" "") (const_int 0)])
7706          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7707          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7708   "TARGET_ARM"
7709   "@
7710    mvn%d4\\t%0, %2
7711    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7712    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7713   [(set_attr "conds" "use")
7714    (set_attr "length" "4,8,8")]
7717 (define_insn "*ifcompare_shift_move"
7718   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7719         (if_then_else:SI
7720          (match_operator 6 "arm_comparison_operator"
7721           [(match_operand:SI 4 "s_register_operand" "r,r")
7722            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7723          (match_operator:SI 7 "shift_operator"
7724           [(match_operand:SI 2 "s_register_operand" "r,r")
7725            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7726          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7727    (clobber (reg:CC CC_REGNUM))]
7728   "TARGET_ARM"
7729   "#"
7730   [(set_attr "conds" "clob")
7731    (set_attr "length" "8,12")]
7734 (define_insn "*if_shift_move"
7735   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7736         (if_then_else:SI
7737          (match_operator 5 "arm_comparison_operator"
7738           [(match_operand 6 "cc_register" "") (const_int 0)])
7739          (match_operator:SI 4 "shift_operator"
7740           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7741            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7742          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7743   "TARGET_ARM"
7744   "@
7745    mov%d5\\t%0, %2%S4
7746    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7747    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7748   [(set_attr "conds" "use")
7749    (set_attr "shift" "2")
7750    (set_attr "length" "4,8,8")]
7753 (define_insn "*ifcompare_move_shift"
7754   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7755         (if_then_else:SI
7756          (match_operator 6 "arm_comparison_operator"
7757           [(match_operand:SI 4 "s_register_operand" "r,r")
7758            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7759          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7760          (match_operator:SI 7 "shift_operator"
7761           [(match_operand:SI 2 "s_register_operand" "r,r")
7762            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7763    (clobber (reg:CC CC_REGNUM))]
7764   "TARGET_ARM"
7765   "#"
7766   [(set_attr "conds" "clob")
7767    (set_attr "length" "8,12")]
7770 (define_insn "*if_move_shift"
7771   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7772         (if_then_else:SI
7773          (match_operator 5 "arm_comparison_operator"
7774           [(match_operand 6 "cc_register" "") (const_int 0)])
7775          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7776          (match_operator:SI 4 "shift_operator"
7777           [(match_operand:SI 2 "s_register_operand" "r,r,r")
7778            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7779   "TARGET_ARM"
7780   "@
7781    mov%D5\\t%0, %2%S4
7782    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7783    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7784   [(set_attr "conds" "use")
7785    (set_attr "shift" "2")
7786    (set_attr "length" "4,8,8")]
7789 (define_insn "*ifcompare_shift_shift"
7790   [(set (match_operand:SI 0 "s_register_operand" "=r")
7791         (if_then_else:SI
7792          (match_operator 7 "arm_comparison_operator"
7793           [(match_operand:SI 5 "s_register_operand" "r")
7794            (match_operand:SI 6 "arm_add_operand" "rIL")])
7795          (match_operator:SI 8 "shift_operator"
7796           [(match_operand:SI 1 "s_register_operand" "r")
7797            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7798          (match_operator:SI 9 "shift_operator"
7799           [(match_operand:SI 3 "s_register_operand" "r")
7800            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7801    (clobber (reg:CC CC_REGNUM))]
7802   "TARGET_ARM"
7803   "#"
7804   [(set_attr "conds" "clob")
7805    (set_attr "length" "12")]
7808 (define_insn "*if_shift_shift"
7809   [(set (match_operand:SI 0 "s_register_operand" "=r")
7810         (if_then_else:SI
7811          (match_operator 5 "arm_comparison_operator"
7812           [(match_operand 8 "cc_register" "") (const_int 0)])
7813          (match_operator:SI 6 "shift_operator"
7814           [(match_operand:SI 1 "s_register_operand" "r")
7815            (match_operand:SI 2 "arm_rhs_operand" "rM")])
7816          (match_operator:SI 7 "shift_operator"
7817           [(match_operand:SI 3 "s_register_operand" "r")
7818            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7819   "TARGET_ARM"
7820   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7821   [(set_attr "conds" "use")
7822    (set_attr "shift" "1")
7823    (set_attr "length" "8")]
7826 (define_insn "*ifcompare_not_arith"
7827   [(set (match_operand:SI 0 "s_register_operand" "=r")
7828         (if_then_else:SI
7829          (match_operator 6 "arm_comparison_operator"
7830           [(match_operand:SI 4 "s_register_operand" "r")
7831            (match_operand:SI 5 "arm_add_operand" "rIL")])
7832          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7833          (match_operator:SI 7 "shiftable_operator"
7834           [(match_operand:SI 2 "s_register_operand" "r")
7835            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7836    (clobber (reg:CC CC_REGNUM))]
7837   "TARGET_ARM"
7838   "#"
7839   [(set_attr "conds" "clob")
7840    (set_attr "length" "12")]
7843 (define_insn "*if_not_arith"
7844   [(set (match_operand:SI 0 "s_register_operand" "=r")
7845         (if_then_else:SI
7846          (match_operator 5 "arm_comparison_operator"
7847           [(match_operand 4 "cc_register" "") (const_int 0)])
7848          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7849          (match_operator:SI 6 "shiftable_operator"
7850           [(match_operand:SI 2 "s_register_operand" "r")
7851            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7852   "TARGET_ARM"
7853   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7854   [(set_attr "conds" "use")
7855    (set_attr "length" "8")]
7858 (define_insn "*ifcompare_arith_not"
7859   [(set (match_operand:SI 0 "s_register_operand" "=r")
7860         (if_then_else:SI
7861          (match_operator 6 "arm_comparison_operator"
7862           [(match_operand:SI 4 "s_register_operand" "r")
7863            (match_operand:SI 5 "arm_add_operand" "rIL")])
7864          (match_operator:SI 7 "shiftable_operator"
7865           [(match_operand:SI 2 "s_register_operand" "r")
7866            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7867          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7868    (clobber (reg:CC CC_REGNUM))]
7869   "TARGET_ARM"
7870   "#"
7871   [(set_attr "conds" "clob")
7872    (set_attr "length" "12")]
7875 (define_insn "*if_arith_not"
7876   [(set (match_operand:SI 0 "s_register_operand" "=r")
7877         (if_then_else:SI
7878          (match_operator 5 "arm_comparison_operator"
7879           [(match_operand 4 "cc_register" "") (const_int 0)])
7880          (match_operator:SI 6 "shiftable_operator"
7881           [(match_operand:SI 2 "s_register_operand" "r")
7882            (match_operand:SI 3 "arm_rhs_operand" "rI")])
7883          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7884   "TARGET_ARM"
7885   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7886   [(set_attr "conds" "use")
7887    (set_attr "length" "8")]
7890 (define_insn "*ifcompare_neg_move"
7891   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7892         (if_then_else:SI
7893          (match_operator 5 "arm_comparison_operator"
7894           [(match_operand:SI 3 "s_register_operand" "r,r")
7895            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7896          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7897          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7898    (clobber (reg:CC CC_REGNUM))]
7899   "TARGET_ARM"
7900   "#"
7901   [(set_attr "conds" "clob")
7902    (set_attr "length" "8,12")]
7905 (define_insn "*if_neg_move"
7906   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7907         (if_then_else:SI
7908          (match_operator 4 "arm_comparison_operator"
7909           [(match_operand 3 "cc_register" "") (const_int 0)])
7910          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7911          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7912   "TARGET_ARM"
7913   "@
7914    rsb%d4\\t%0, %2, #0
7915    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7916    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7917   [(set_attr "conds" "use")
7918    (set_attr "length" "4,8,8")]
7921 (define_insn "*ifcompare_move_neg"
7922   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7923         (if_then_else:SI
7924          (match_operator 5 "arm_comparison_operator"
7925           [(match_operand:SI 3 "s_register_operand" "r,r")
7926            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7927          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7928          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7929    (clobber (reg:CC CC_REGNUM))]
7930   "TARGET_ARM"
7931   "#"
7932   [(set_attr "conds" "clob")
7933    (set_attr "length" "8,12")]
7936 (define_insn "*if_move_neg"
7937   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7938         (if_then_else:SI
7939          (match_operator 4 "arm_comparison_operator"
7940           [(match_operand 3 "cc_register" "") (const_int 0)])
7941          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7942          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7943   "TARGET_ARM"
7944   "@
7945    rsb%D4\\t%0, %2, #0
7946    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7947    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7948   [(set_attr "conds" "use")
7949    (set_attr "length" "4,8,8")]
7952 (define_insn "*arith_adjacentmem"
7953   [(set (match_operand:SI 0 "s_register_operand" "=r")
7954         (match_operator:SI 1 "shiftable_operator"
7955          [(match_operand:SI 2 "memory_operand" "m")
7956           (match_operand:SI 3 "memory_operand" "m")]))
7957    (clobber (match_scratch:SI 4 "=r"))]
7958   "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7959   "*
7960   {
7961     rtx ldm[3];
7962     rtx arith[4];
7963     int val1 = 0, val2 = 0;
7965     if (REGNO (operands[0]) > REGNO (operands[4]))
7966       {
7967         ldm[1] = operands[4];
7968         ldm[2] = operands[0];
7969       }
7970     else
7971       {
7972         ldm[1] = operands[0];
7973         ldm[2] = operands[4];
7974       }
7975     if (GET_CODE (XEXP (operands[2], 0)) != REG)
7976       val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7977     if (GET_CODE (XEXP (operands[3], 0)) != REG)
7978       val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7979     arith[0] = operands[0];
7980     arith[3] = operands[1];
7981     if (val1 < val2)
7982       {
7983         arith[1] = ldm[1];
7984         arith[2] = ldm[2];
7985       }
7986     else
7987       {
7988         arith[1] = ldm[2];
7989         arith[2] = ldm[1];
7990       }
7991    if (val1 && val2)
7992       {
7993         rtx ops[3];
7994         ldm[0] = ops[0] = operands[4];
7995         ops[1] = XEXP (XEXP (operands[2], 0), 0);
7996         ops[2] = XEXP (XEXP (operands[2], 0), 1);
7997         output_add_immediate (ops);
7998         if (val1 < val2)
7999           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8000         else
8001           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8002       }
8003     else if (val1)
8004       {
8005         ldm[0] = XEXP (operands[3], 0);
8006         if (val1 < val2)
8007           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8008         else
8009           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8010       }
8011     else
8012       {
8013         ldm[0] = XEXP (operands[2], 0);
8014         if (val1 < val2)
8015           output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8016         else
8017           output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8018       }
8019     output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8020     return \"\";
8021   }"
8022   [(set_attr "length" "12")
8023    (set_attr "predicable" "yes")
8024    (set_attr "type" "load")]
8027 ;; the arm can support extended pre-inc instructions
8029 ;; In all these cases, we use operands 0 and 1 for the register being
8030 ;; incremented because those are the operands that local-alloc will
8031 ;; tie and these are the pair most likely to be tieable (and the ones
8032 ;; that will benefit the most).
8034 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8035 ;; elimination will cause too many headaches.
8037 (define_insn "*strqi_preinc"
8038   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8039                          (match_operand:SI 2 "index_operand" "rJ")))
8040         (match_operand:QI 3 "s_register_operand" "r"))
8041    (set (match_operand:SI 0 "s_register_operand" "=r")
8042         (plus:SI (match_dup 1) (match_dup 2)))]
8043   "TARGET_ARM
8044    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8045    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8046    && (GET_CODE (operands[2]) != REG
8047        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8048   "str%?b\\t%3, [%0, %2]!"
8049   [(set_attr "type" "store1")
8050    (set_attr "predicable" "yes")]
8053 (define_insn "*strqi_predec"
8054   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8055                           (match_operand:SI 2 "s_register_operand" "r")))
8056         (match_operand:QI 3 "s_register_operand" "r"))
8057    (set (match_operand:SI 0 "s_register_operand" "=r")
8058         (minus:SI (match_dup 1) (match_dup 2)))]
8059   "TARGET_ARM
8060    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8061    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8062    && (GET_CODE (operands[2]) != REG
8063        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8064   "str%?b\\t%3, [%0, -%2]!"
8065   [(set_attr "type" "store1")
8066    (set_attr "predicable" "yes")]
8069 (define_insn "*loadqi_preinc"
8070   [(set (match_operand:QI 3 "s_register_operand" "=r")
8071         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8072                          (match_operand:SI 2 "index_operand" "rJ"))))
8073    (set (match_operand:SI 0 "s_register_operand" "=r")
8074         (plus:SI (match_dup 1) (match_dup 2)))]
8075   "TARGET_ARM
8076    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8077    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8078    && (GET_CODE (operands[2]) != REG
8079        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8080   "ldr%?b\\t%3, [%0, %2]!"
8081   [(set_attr "type" "load")
8082    (set_attr "predicable" "yes")]
8085 (define_insn "*loadqi_predec"
8086   [(set (match_operand:QI 3 "s_register_operand" "=r")
8087         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8088                           (match_operand:SI 2 "s_register_operand" "r"))))
8089    (set (match_operand:SI 0 "s_register_operand" "=r")
8090         (minus:SI (match_dup 1) (match_dup 2)))]
8091   "TARGET_ARM
8092    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8093    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8094    && (GET_CODE (operands[2]) != REG
8095        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8096   "ldr%?b\\t%3, [%0, -%2]!"
8097   [(set_attr "type" "load")
8098    (set_attr "predicable" "yes")]
8101 (define_insn "*loadqisi_preinc"
8102   [(set (match_operand:SI 3 "s_register_operand" "=r")
8103         (zero_extend:SI
8104          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8105                           (match_operand:SI 2 "index_operand" "rJ")))))
8106    (set (match_operand:SI 0 "s_register_operand" "=r")
8107         (plus:SI (match_dup 1) (match_dup 2)))]
8108   "TARGET_ARM
8109    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8110    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8111    && (GET_CODE (operands[2]) != REG
8112        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8113   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8114   [(set_attr "type" "load")
8115    (set_attr "predicable" "yes")]
8118 (define_insn "*loadqisi_predec"
8119   [(set (match_operand:SI 3 "s_register_operand" "=r")
8120         (zero_extend:SI
8121          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8122                            (match_operand:SI 2 "s_register_operand" "r")))))
8123    (set (match_operand:SI 0 "s_register_operand" "=r")
8124         (minus:SI (match_dup 1) (match_dup 2)))]
8125   "TARGET_ARM
8126    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8127    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8128    && (GET_CODE (operands[2]) != REG
8129        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8130   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8131   [(set_attr "type" "load")
8132    (set_attr "predicable" "yes")]
8135 (define_insn "*strsi_preinc"
8136   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8137                          (match_operand:SI 2 "index_operand" "rJ")))
8138         (match_operand:SI 3 "s_register_operand" "r"))
8139    (set (match_operand:SI 0 "s_register_operand" "=r")
8140         (plus:SI (match_dup 1) (match_dup 2)))]
8141   "TARGET_ARM
8142    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8143    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8144    && (GET_CODE (operands[2]) != REG
8145        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8146   "str%?\\t%3, [%0, %2]!"
8147   [(set_attr "type" "store1")
8148    (set_attr "predicable" "yes")]
8151 (define_insn "*strsi_predec"
8152   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8153                           (match_operand:SI 2 "s_register_operand" "r")))
8154         (match_operand:SI 3 "s_register_operand" "r"))
8155    (set (match_operand:SI 0 "s_register_operand" "=r")
8156         (minus:SI (match_dup 1) (match_dup 2)))]
8157   "TARGET_ARM
8158    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8159    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8160    && (GET_CODE (operands[2]) != REG
8161        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8162   "str%?\\t%3, [%0, -%2]!"
8163   [(set_attr "type" "store1")
8164    (set_attr "predicable" "yes")]
8167 (define_insn "*loadsi_preinc"
8168   [(set (match_operand:SI 3 "s_register_operand" "=r")
8169         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8170                          (match_operand:SI 2 "index_operand" "rJ"))))
8171    (set (match_operand:SI 0 "s_register_operand" "=r")
8172         (plus:SI (match_dup 1) (match_dup 2)))]
8173   "TARGET_ARM
8174    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8175    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8176    && (GET_CODE (operands[2]) != REG
8177        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8178   "ldr%?\\t%3, [%0, %2]!"
8179   [(set_attr "type" "load")
8180    (set_attr "predicable" "yes")]
8183 (define_insn "*loadsi_predec"
8184   [(set (match_operand:SI 3 "s_register_operand" "=r")
8185         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8186                           (match_operand:SI 2 "s_register_operand" "r"))))
8187    (set (match_operand:SI 0 "s_register_operand" "=r")
8188         (minus:SI (match_dup 1) (match_dup 2)))]
8189   "TARGET_ARM
8190    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8191    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8192    && (GET_CODE (operands[2]) != REG
8193        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8194   "ldr%?\\t%3, [%0, -%2]!"
8195   [(set_attr "type" "load")
8196    (set_attr "predicable" "yes")]
8199 (define_insn "*loadhi_preinc"
8200   [(set (match_operand:HI 3 "s_register_operand" "=r")
8201         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8202                          (match_operand:SI 2 "index_operand" "rJ"))))
8203    (set (match_operand:SI 0 "s_register_operand" "=r")
8204         (plus:SI (match_dup 1) (match_dup 2)))]
8205   "TARGET_ARM
8206    && !BYTES_BIG_ENDIAN
8207    && !TARGET_MMU_TRAPS
8208    && !arm_arch4
8209    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8210    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8211    && (GET_CODE (operands[2]) != REG
8212        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8213   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8214   [(set_attr "type" "load")
8215    (set_attr "predicable" "yes")]
8218 (define_insn "*loadhi_predec"
8219   [(set (match_operand:HI 3 "s_register_operand" "=r")
8220         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8221                           (match_operand:SI 2 "s_register_operand" "r"))))
8222    (set (match_operand:SI 0 "s_register_operand" "=r")
8223         (minus:SI (match_dup 1) (match_dup 2)))]
8224   "TARGET_ARM
8225    && !BYTES_BIG_ENDIAN
8226    && !TARGET_MMU_TRAPS
8227    && !arm_arch4
8228    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8229    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8230    && (GET_CODE (operands[2]) != REG
8231        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8232   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8233   [(set_attr "type" "load")
8234    (set_attr "predicable" "yes")]
8237 (define_insn "*strqi_shiftpreinc"
8238   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8239                           [(match_operand:SI 3 "s_register_operand" "r")
8240                            (match_operand:SI 4 "const_shift_operand" "n")])
8241                          (match_operand:SI 1 "s_register_operand" "0")))
8242         (match_operand:QI 5 "s_register_operand" "r"))
8243    (set (match_operand:SI 0 "s_register_operand" "=r")
8244         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8245                  (match_dup 1)))]
8246   "TARGET_ARM
8247    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8248    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8249    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8250   "str%?b\\t%5, [%0, %3%S2]!"
8251   [(set_attr "type" "store1")
8252    (set_attr "predicable" "yes")]
8255 (define_insn "*strqi_shiftpredec"
8256   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8257                           (match_operator:SI 2 "shift_operator"
8258                            [(match_operand:SI 3 "s_register_operand" "r")
8259                             (match_operand:SI 4 "const_shift_operand" "n")])))
8260         (match_operand:QI 5 "s_register_operand" "r"))
8261    (set (match_operand:SI 0 "s_register_operand" "=r")
8262         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8263                                                  (match_dup 4)])))]
8264   "TARGET_ARM
8265    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8266    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8267    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8268   "str%?b\\t%5, [%0, -%3%S2]!"
8269   [(set_attr "type" "store1")
8270    (set_attr "predicable" "yes")]
8273 (define_insn "*loadqi_shiftpreinc"
8274   [(set (match_operand:QI 5 "s_register_operand" "=r")
8275         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8276                           [(match_operand:SI 3 "s_register_operand" "r")
8277                            (match_operand:SI 4 "const_shift_operand" "n")])
8278                          (match_operand:SI 1 "s_register_operand" "0"))))
8279    (set (match_operand:SI 0 "s_register_operand" "=r")
8280         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8281                  (match_dup 1)))]
8282   "TARGET_ARM
8283    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8284    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8285    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8286   "ldr%?b\\t%5, [%0, %3%S2]!"
8287   [(set_attr "type" "load")
8288    (set_attr "predicable" "yes")]
8291 (define_insn "*loadqi_shiftpredec"
8292   [(set (match_operand:QI 5 "s_register_operand" "=r")
8293         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8294                           (match_operator:SI 2 "shift_operator"
8295                            [(match_operand:SI 3 "s_register_operand" "r")
8296                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8297    (set (match_operand:SI 0 "s_register_operand" "=r")
8298         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8299                                                  (match_dup 4)])))]
8300   "TARGET_ARM
8301    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8302    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8303    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8304   "ldr%?b\\t%5, [%0, -%3%S2]!"
8305   [(set_attr "type" "load")
8306    (set_attr "predicable" "yes")]
8309 (define_insn "*strsi_shiftpreinc"
8310   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8311                           [(match_operand:SI 3 "s_register_operand" "r")
8312                            (match_operand:SI 4 "const_shift_operand" "n")])
8313                          (match_operand:SI 1 "s_register_operand" "0")))
8314         (match_operand:SI 5 "s_register_operand" "r"))
8315    (set (match_operand:SI 0 "s_register_operand" "=r")
8316         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8317                  (match_dup 1)))]
8318   "TARGET_ARM
8319    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8320    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8321    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8322   "str%?\\t%5, [%0, %3%S2]!"
8323   [(set_attr "type" "store1")
8324    (set_attr "predicable" "yes")]
8327 (define_insn "*strsi_shiftpredec"
8328   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8329                           (match_operator:SI 2 "shift_operator"
8330                            [(match_operand:SI 3 "s_register_operand" "r")
8331                             (match_operand:SI 4 "const_shift_operand" "n")])))
8332         (match_operand:SI 5 "s_register_operand" "r"))
8333    (set (match_operand:SI 0 "s_register_operand" "=r")
8334         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8335                                                  (match_dup 4)])))]
8336   "TARGET_ARM
8337    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8338    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8339    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8340   "str%?\\t%5, [%0, -%3%S2]!"
8341   [(set_attr "type" "store1")
8342    (set_attr "predicable" "yes")]
8345 (define_insn "*loadsi_shiftpreinc"
8346   [(set (match_operand:SI 5 "s_register_operand" "=r")
8347         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8348                           [(match_operand:SI 3 "s_register_operand" "r")
8349                            (match_operand:SI 4 "const_shift_operand" "n")])
8350                          (match_operand:SI 1 "s_register_operand" "0"))))
8351    (set (match_operand:SI 0 "s_register_operand" "=r")
8352         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8353                  (match_dup 1)))]
8354   "TARGET_ARM
8355    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8356    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8357    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8358   "ldr%?\\t%5, [%0, %3%S2]!"
8359   [(set_attr "type" "load")
8360    (set_attr "predicable" "yes")]
8363 (define_insn "*loadsi_shiftpredec"
8364   [(set (match_operand:SI 5 "s_register_operand" "=r")
8365         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8366                           (match_operator:SI 2 "shift_operator"
8367                            [(match_operand:SI 3 "s_register_operand" "r")
8368                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8369    (set (match_operand:SI 0 "s_register_operand" "=r")
8370         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8371                                                  (match_dup 4)])))]
8372   "TARGET_ARM
8373    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8374    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8375    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8376   "ldr%?\\t%5, [%0, -%3%S2]!"
8377   [(set_attr "type" "load")
8378    (set_attr "predicable" "yes")])
8380 (define_insn "*loadhi_shiftpreinc"
8381   [(set (match_operand:HI 5 "s_register_operand" "=r")
8382         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8383                           [(match_operand:SI 3 "s_register_operand" "r")
8384                            (match_operand:SI 4 "const_shift_operand" "n")])
8385                          (match_operand:SI 1 "s_register_operand" "0"))))
8386    (set (match_operand:SI 0 "s_register_operand" "=r")
8387         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8388                  (match_dup 1)))]
8389   "TARGET_ARM
8390    && !BYTES_BIG_ENDIAN
8391    && !TARGET_MMU_TRAPS
8392    && !arm_arch4
8393    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8394    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8395    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8396   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8397   [(set_attr "type" "load")
8398    (set_attr "predicable" "yes")]
8401 (define_insn "*loadhi_shiftpredec"
8402   [(set (match_operand:HI 5 "s_register_operand" "=r")
8403         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8404                           (match_operator:SI 2 "shift_operator"
8405                            [(match_operand:SI 3 "s_register_operand" "r")
8406                             (match_operand:SI 4 "const_shift_operand" "n")]))))
8407    (set (match_operand:SI 0 "s_register_operand" "=r")
8408         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8409                                                  (match_dup 4)])))]
8410   "TARGET_ARM
8411    && !BYTES_BIG_ENDIAN
8412    && !TARGET_MMU_TRAPS
8413    && !arm_arch4
8414    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8415    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8416    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8417   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8418   [(set_attr "type" "load")
8419    (set_attr "predicable" "yes")]
8422 ; It can also support extended post-inc expressions, but combine doesn't
8423 ; try these....
8424 ; It doesn't seem worth adding peepholes for anything but the most common
8425 ; cases since, unlike combine, the increment must immediately follow the load
8426 ; for this pattern to match.
8427 ; We must watch to see that the source/destination register isn't also the
8428 ; same as the base address register, and that if the index is a register,
8429 ; that it is not the same as the base address register.  In such cases the
8430 ; instruction that we would generate would have UNPREDICTABLE behaviour so 
8431 ; we cannot use it.
8433 (define_peephole
8434   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8435         (match_operand:QI 2 "s_register_operand" "r"))
8436    (set (match_dup 0)
8437         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
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 (match_operand:QI 0 "s_register_operand" "=r")
8447         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8448    (set (match_dup 1)
8449         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8450   "TARGET_ARM
8451    && REGNO (operands[0]) != REGNO(operands[1])
8452    && (GET_CODE (operands[2]) != REG
8453        || REGNO(operands[0]) != REGNO (operands[2]))"
8454   "ldr%?b\\t%0, [%1], %2"
8457 (define_peephole
8458   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8459         (match_operand:SI 2 "s_register_operand" "r"))
8460    (set (match_dup 0)
8461         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8462   "TARGET_ARM
8463    && (REGNO (operands[2]) != REGNO (operands[0]))
8464    && (GET_CODE (operands[1]) != REG
8465        || (REGNO (operands[1]) != REGNO (operands[0])))"
8466   "str%?\\t%2, [%0], %1"
8469 (define_peephole
8470   [(set (match_operand:HI 0 "s_register_operand" "=r")
8471         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8472    (set (match_dup 1)
8473         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8474   "TARGET_ARM
8475    && !BYTES_BIG_ENDIAN
8476    && !TARGET_MMU_TRAPS
8477    && !arm_arch4
8478    && REGNO (operands[0]) != REGNO(operands[1])
8479    && (GET_CODE (operands[2]) != REG
8480        || REGNO(operands[0]) != REGNO (operands[2]))"
8481   "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8484 (define_peephole
8485   [(set (match_operand:SI 0 "s_register_operand" "=r")
8486         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8487    (set (match_dup 1)
8488         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8489   "TARGET_ARM
8490    && REGNO (operands[0]) != REGNO(operands[1])
8491    && (GET_CODE (operands[2]) != REG
8492        || REGNO(operands[0]) != REGNO (operands[2]))"
8493   "ldr%?\\t%0, [%1], %2"
8496 (define_peephole
8497   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8498                          (match_operand:SI 1 "index_operand" "rJ")))
8499         (match_operand:QI 2 "s_register_operand" "r"))
8500    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8501   "TARGET_ARM
8502    && (REGNO (operands[2]) != REGNO (operands[0]))
8503    && (GET_CODE (operands[1]) != REG
8504        || (REGNO (operands[1]) != REGNO (operands[0])))"
8505   "str%?b\\t%2, [%0, %1]!"
8508 (define_peephole
8509   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8510                           [(match_operand:SI 0 "s_register_operand" "r")
8511                            (match_operand:SI 1 "const_int_operand" "n")])
8512                          (match_operand:SI 2 "s_register_operand" "+r")))
8513         (match_operand:QI 3 "s_register_operand" "r"))
8514    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8515                                (match_dup 2)))]
8516   "TARGET_ARM
8517    && (REGNO (operands[3]) != REGNO (operands[2]))
8518    && (REGNO (operands[0]) != REGNO (operands[2]))"
8519   "str%?b\\t%3, [%2, %0%S4]!"
8522 ; This pattern is never tried by combine, so do it as a peephole
8524 (define_peephole2
8525   [(set (match_operand:SI 0 "s_register_operand" "")
8526         (match_operand:SI 1 "s_register_operand" ""))
8527    (set (reg:CC CC_REGNUM)
8528         (compare:CC (match_dup 1) (const_int 0)))]
8529   "TARGET_ARM
8530   "
8531   [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8532               (set (match_dup 0) (match_dup 1))])]
8533   ""
8536 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8537 ; reversed, check that the memory references aren't volatile.
8539 (define_peephole
8540   [(set (match_operand:SI 0 "s_register_operand" "=r")
8541         (match_operand:SI 4 "memory_operand" "m"))
8542    (set (match_operand:SI 1 "s_register_operand" "=r")
8543         (match_operand:SI 5 "memory_operand" "m"))
8544    (set (match_operand:SI 2 "s_register_operand" "=r")
8545         (match_operand:SI 6 "memory_operand" "m"))
8546    (set (match_operand:SI 3 "s_register_operand" "=r")
8547         (match_operand:SI 7 "memory_operand" "m"))]
8548   "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8549   "*
8550   return emit_ldm_seq (operands, 4);
8551   "
8554 (define_peephole
8555   [(set (match_operand:SI 0 "s_register_operand" "=r")
8556         (match_operand:SI 3 "memory_operand" "m"))
8557    (set (match_operand:SI 1 "s_register_operand" "=r")
8558         (match_operand:SI 4 "memory_operand" "m"))
8559    (set (match_operand:SI 2 "s_register_operand" "=r")
8560         (match_operand:SI 5 "memory_operand" "m"))]
8561   "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8562   "*
8563   return emit_ldm_seq (operands, 3);
8564   "
8567 (define_peephole
8568   [(set (match_operand:SI 0 "s_register_operand" "=r")
8569         (match_operand:SI 2 "memory_operand" "m"))
8570    (set (match_operand:SI 1 "s_register_operand" "=r")
8571         (match_operand:SI 3 "memory_operand" "m"))]
8572   "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8573   "*
8574   return emit_ldm_seq (operands, 2);
8575   "
8578 (define_peephole
8579   [(set (match_operand:SI 4 "memory_operand" "=m")
8580         (match_operand:SI 0 "s_register_operand" "r"))
8581    (set (match_operand:SI 5 "memory_operand" "=m")
8582         (match_operand:SI 1 "s_register_operand" "r"))
8583    (set (match_operand:SI 6 "memory_operand" "=m")
8584         (match_operand:SI 2 "s_register_operand" "r"))
8585    (set (match_operand:SI 7 "memory_operand" "=m")
8586         (match_operand:SI 3 "s_register_operand" "r"))]
8587   "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8588   "*
8589   return emit_stm_seq (operands, 4);
8590   "
8593 (define_peephole
8594   [(set (match_operand:SI 3 "memory_operand" "=m")
8595         (match_operand:SI 0 "s_register_operand" "r"))
8596    (set (match_operand:SI 4 "memory_operand" "=m")
8597         (match_operand:SI 1 "s_register_operand" "r"))
8598    (set (match_operand:SI 5 "memory_operand" "=m")
8599         (match_operand:SI 2 "s_register_operand" "r"))]
8600   "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8601   "*
8602   return emit_stm_seq (operands, 3);
8603   "
8606 (define_peephole
8607   [(set (match_operand:SI 2 "memory_operand" "=m")
8608         (match_operand:SI 0 "s_register_operand" "r"))
8609    (set (match_operand:SI 3 "memory_operand" "=m")
8610         (match_operand:SI 1 "s_register_operand" "r"))]
8611   "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8612   "*
8613   return emit_stm_seq (operands, 2);
8614   "
8617 (define_split
8618   [(set (match_operand:SI 0 "s_register_operand" "")
8619         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8620                        (const_int 0))
8621                 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8622                          [(match_operand:SI 3 "s_register_operand" "")
8623                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
8624    (clobber (match_operand:SI 5 "s_register_operand" ""))]
8625   "TARGET_ARM"
8626   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8627    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8628                               (match_dup 5)))]
8629   ""
8632 ;; This split can be used because CC_Z mode implies that the following
8633 ;; branch will be an equality, or an unsigned inequality, so the sign
8634 ;; extension is not needed.
8636 (define_split
8637   [(set (reg:CC_Z CC_REGNUM)
8638         (compare:CC_Z
8639          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8640                     (const_int 24))
8641          (match_operand 1 "const_int_operand" "")))
8642    (clobber (match_scratch:SI 2 ""))]
8643   "TARGET_ARM
8644    && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8645        == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8646   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8647    (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8648   "
8649   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8650   "
8653 (define_expand "prologue"
8654   [(clobber (const_int 0))]
8655   "TARGET_EITHER"
8656   "if (TARGET_ARM)
8657      arm_expand_prologue ();
8658    else
8659      thumb_expand_prologue ();
8660   DONE;
8661   "
8664 (define_expand "epilogue"
8665   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8666   "TARGET_EITHER"
8667   "
8668   if (TARGET_THUMB)
8669     thumb_expand_epilogue ();
8670   else if (USE_RETURN_INSN (FALSE))
8671     {
8672       emit_jump_insn (gen_return ());
8673       DONE;
8674     }
8675   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8676         gen_rtvec (1,
8677                 gen_rtx_RETURN (VOIDmode)),
8678         VUNSPEC_EPILOGUE));
8679   DONE;
8680   "
8683 (define_insn "sibcall_epilogue"
8684   [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8685   "TARGET_ARM"
8686   "*
8687   if (USE_RETURN_INSN (FALSE))
8688     return output_return_instruction (const_true_rtx, FALSE, FALSE);
8689   return arm_output_epilogue (FALSE);
8690   "
8691 ;; Length is absolute worst case
8692   [(set_attr "length" "44")
8693    (set_attr "type" "block")]
8696 (define_insn "*epilogue_insns"
8697   [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8698   "TARGET_EITHER"
8699   "*
8700   if (TARGET_ARM)
8701     return arm_output_epilogue (TRUE);
8702   else /* TARGET_THUMB */
8703     return thumb_unexpanded_epilogue ();
8704   "
8705   ; Length is absolute worst case
8706   [(set_attr "length" "44")
8707    (set_attr "type" "block")]
8710 (define_expand "eh_epilogue"
8711   [(use (match_operand:SI 0 "register_operand" "r"))
8712    (use (match_operand:SI 1 "register_operand" "r"))
8713    (use (match_operand:SI 2 "register_operand" "r"))]
8714   "TARGET_EITHER"
8715   "
8716   {
8717     cfun->machine->eh_epilogue_sp_ofs = operands[1];
8718     if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8719       {
8720         rtx ra = gen_rtx_REG (Pmode, 2);
8722         emit_move_insn (ra, operands[2]);
8723         operands[2] = ra;
8724       }
8725     /* This is a hack -- we may have crystalized the function type too
8726        early.  */
8727     cfun->machine->func_type = 0;
8728   }"
8731 ;; This split is only used during output to reduce the number of patterns
8732 ;; that need assembler instructions adding to them.  We allowed the setting
8733 ;; of the conditions to be implicit during rtl generation so that
8734 ;; the conditional compare patterns would work.  However this conflicts to
8735 ;; some extent with the conditional data operations, so we have to split them
8736 ;; up again here.
8738 (define_split
8739   [(set (match_operand:SI 0 "s_register_operand" "")
8740         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8741                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8742                          (match_dup 0)
8743                          (match_operand 4 "" "")))
8744    (clobber (reg:CC CC_REGNUM))]
8745   "TARGET_ARM && reload_completed"
8746   [(set (match_dup 5) (match_dup 6))
8747    (cond_exec (match_dup 7)
8748               (set (match_dup 0) (match_dup 4)))]
8749   "
8750   {
8751     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8752                                              operands[2], operands[3]);
8753     enum rtx_code rc = GET_CODE (operands[1]);
8755     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8756     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8757     if (mode == CCFPmode || mode == CCFPEmode)
8758       rc = reverse_condition_maybe_unordered (rc);
8759     else
8760       rc = reverse_condition (rc);
8762     operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8763   }"
8766 (define_split
8767   [(set (match_operand:SI 0 "s_register_operand" "")
8768         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8769                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8770                          (match_operand 4 "" "")
8771                          (match_dup 0)))
8772    (clobber (reg:CC CC_REGNUM))]
8773   "TARGET_ARM && reload_completed"
8774   [(set (match_dup 5) (match_dup 6))
8775    (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8776               (set (match_dup 0) (match_dup 4)))]
8777   "
8778   {
8779     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8780                                              operands[2], operands[3]);
8782     operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8783     operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8784   }"
8787 (define_split
8788   [(set (match_operand:SI 0 "s_register_operand" "")
8789         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8790                           [(match_operand 2 "" "") (match_operand 3 "" "")])
8791                          (match_operand 4 "" "")
8792                          (match_operand 5 "" "")))
8793    (clobber (reg:CC CC_REGNUM))]
8794   "TARGET_ARM && reload_completed"
8795   [(set (match_dup 6) (match_dup 7))
8796    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8797               (set (match_dup 0) (match_dup 4)))
8798    (cond_exec (match_dup 8)
8799               (set (match_dup 0) (match_dup 5)))]
8800   "
8801   {
8802     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8803                                              operands[2], operands[3]);
8804     enum rtx_code rc = GET_CODE (operands[1]);
8806     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8807     operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8808     if (mode == CCFPmode || mode == CCFPEmode)
8809       rc = reverse_condition_maybe_unordered (rc);
8810     else
8811       rc = reverse_condition (rc);
8813     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8814   }"
8817 (define_split
8818   [(set (match_operand:SI 0 "s_register_operand" "")
8819         (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8820                           [(match_operand:SI 2 "s_register_operand" "")
8821                            (match_operand:SI 3 "arm_add_operand" "")])
8822                          (match_operand:SI 4 "arm_rhs_operand" "")
8823                          (not:SI
8824                           (match_operand:SI 5 "s_register_operand" ""))))
8825    (clobber (reg:CC CC_REGNUM))]
8826   "TARGET_ARM && reload_completed"
8827   [(set (match_dup 6) (match_dup 7))
8828    (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8829               (set (match_dup 0) (match_dup 4)))
8830    (cond_exec (match_dup 8)
8831               (set (match_dup 0) (not:SI (match_dup 5))))]
8832   "
8833   {
8834     enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8835                                              operands[2], operands[3]);
8836     enum rtx_code rc = GET_CODE (operands[1]);
8838     operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8839     operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8840     if (mode == CCFPmode || mode == CCFPEmode)
8841       rc = reverse_condition_maybe_unordered (rc);
8842     else
8843       rc = reverse_condition (rc);
8845     operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8846   }"
8849 (define_insn "*cond_move_not"
8850   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8851         (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8852                           [(match_operand 3 "cc_register" "") (const_int 0)])
8853                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8854                          (not:SI
8855                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
8856   "TARGET_ARM"
8857   "@
8858    mvn%D4\\t%0, %2
8859    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8860   [(set_attr "conds" "use")
8861    (set_attr "length" "4,8")]
8864 ;; The next two patterns occur when an AND operation is followed by a
8865 ;; scc insn sequence 
8867 (define_insn "*sign_extract_onebit"
8868   [(set (match_operand:SI 0 "s_register_operand" "=r")
8869         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8870                          (const_int 1)
8871                          (match_operand:SI 2 "const_int_operand" "n")))]
8872   "TARGET_ARM"
8873   "*
8874     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8875     output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8876     return \"mvnne\\t%0, #0\";
8877   "
8878   [(set_attr "conds" "clob")
8879    (set_attr "length" "8")]
8882 (define_insn "*not_signextract_onebit"
8883   [(set (match_operand:SI 0 "s_register_operand" "=r")
8884         (not:SI
8885          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8886                           (const_int 1)
8887                           (match_operand:SI 2 "const_int_operand" "n"))))]
8888   "TARGET_ARM"
8889   "*
8890     operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8891     output_asm_insn (\"tst\\t%1, %2\", operands);
8892     output_asm_insn (\"mvneq\\t%0, #0\", operands);
8893     return \"movne\\t%0, #0\";
8894   "
8895   [(set_attr "conds" "clob")
8896    (set_attr "length" "12")]
8899 ;; Push multiple registers to the stack.  Registers are in parallel (use ...)
8900 ;; expressions.  For simplicity, the first register is also in the unspec
8901 ;; part.
8902 (define_insn "*push_multi"
8903   [(match_parallel 2 "multi_register_push"
8904     [(set (match_operand:BLK 0 "memory_operand" "=m")
8905           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8906                       UNSPEC_PUSH_MULT))])]
8907   "TARGET_ARM"
8908   "*
8909   {
8910     int num_saves = XVECLEN (operands[2], 0);
8911      
8912     /* For the StrongARM at least it is faster to
8913        use STR to store only a single register.  */
8914     if (num_saves == 1)
8915       output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8916     else
8917       {
8918         int i;
8919         char pattern[100];
8921         strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8923         for (i = 1; i < num_saves; i++)
8924           {
8925             strcat (pattern, \", %|\");
8926             strcat (pattern,
8927                     reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8928           }
8930         strcat (pattern, \"}\");
8931         output_asm_insn (pattern, operands);
8932       }
8934     return \"\";
8935   }"
8936   [(set_attr "type" "store4")]
8939 (define_insn "stack_tie"
8940   [(set (mem:BLK (scratch))
8941         (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8942                      (match_operand:SI 1 "s_register_operand" "r")]
8943                     UNSPEC_PRLG_STK))]
8944   ""
8945   ""
8946   [(set_attr "length" "0")]
8949 ;; Similarly for the floating point registers
8950 (define_insn "*push_fp_multi"
8951   [(match_parallel 2 "multi_register_push"
8952     [(set (match_operand:BLK 0 "memory_operand" "=m")
8953           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8954                       UNSPEC_PUSH_MULT))])]
8955   "TARGET_ARM"
8956   "*
8957   {
8958     char pattern[100];
8960     sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8961     output_asm_insn (pattern, operands);
8962     return \"\";
8963   }"
8964   [(set_attr "type" "f_store")]
8967 ;; Special patterns for dealing with the constant pool
8969 (define_insn "align_4"
8970   [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8971   "TARGET_EITHER"
8972   "*
8973   assemble_align (32);
8974   return \"\";
8975   "
8978 (define_insn "consttable_end"
8979   [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8980   "TARGET_EITHER"
8981   "*
8982   making_const_table = FALSE;
8983   return \"\";
8984   "
8987 (define_insn "consttable_1"
8988   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8989   "TARGET_THUMB"
8990   "*
8991   making_const_table = TRUE;
8992   assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8993   assemble_zeros (3);
8994   return \"\";
8995   "
8996   [(set_attr "length" "4")]
8999 (define_insn "consttable_2"
9000   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9001   "TARGET_THUMB"
9002   "*
9003   making_const_table = TRUE;
9004   assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9005   assemble_zeros (2);
9006   return \"\";
9007   "
9008   [(set_attr "length" "4")]
9011 (define_insn "consttable_4"
9012   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9013   "TARGET_EITHER"
9014   "*
9015   {
9016     making_const_table = TRUE;
9017     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9018       {
9019       case MODE_FLOAT:
9020       {
9021         REAL_VALUE_TYPE r;
9022         REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9023         assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9024         break;
9025       }
9026       default:
9027         assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9028         break;
9029       }
9030     return \"\";
9031   }"
9032   [(set_attr "length" "4")]
9035 (define_insn "consttable_8"
9036   [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9037   "TARGET_EITHER"
9038   "*
9039   {
9040     making_const_table = TRUE;
9041     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9042       {
9043        case MODE_FLOAT:
9044         {
9045           REAL_VALUE_TYPE r;
9046           REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9047           assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9048           break;
9049         }
9050       default:
9051         assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9052         break;
9053       }
9054     return \"\";
9055   }"
9056   [(set_attr "length" "8")]
9059 ;; Miscellaneous Thumb patterns
9061 (define_expand "tablejump"
9062   [(parallel [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9063               (use (label_ref (match_operand 1 "" "")))])]
9064   "TARGET_THUMB"
9065   "
9066   if (flag_pic)
9067     {
9068       /* Hopefully, CSE will eliminate this copy.  */
9069       rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9070       rtx reg2 = gen_reg_rtx (SImode);
9072       emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9073       operands[0] = reg2;
9074     }
9075   "
9078 (define_insn "*thumb_tablejump"
9079   [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9080    (use (label_ref (match_operand 1 "" "")))]
9081   "TARGET_THUMB"
9082   "mov\\t%|pc, %0"
9083   [(set_attr "length" "2")]
9086 ;; V5 Instructions,
9088 (define_insn "clz"
9089   [(set (match_operand:SI             0 "s_register_operand" "=r")
9090         (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9091                    UNSPEC_CLZ))]
9092   "TARGET_ARM && arm_arch5"
9093   "clz\\t%0, %1")
9095 (define_expand "ffssi2"
9096   [(set (match_operand:SI 0 "s_register_operand" "")
9097         (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9098   "TARGET_ARM && arm_arch5"
9099   "
9100   {
9101     rtx t1, t2, t3;
9103     t1 = gen_reg_rtx (SImode);
9104     t2 = gen_reg_rtx (SImode);
9105     t3 = gen_reg_rtx (SImode);
9107     emit_insn (gen_negsi2 (t1, operands[1]));
9108     emit_insn (gen_andsi3 (t2, operands[1], t1));
9109     emit_insn (gen_clz (t3, t2));
9110     emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9111     DONE;
9112   }"
9115 ;; V5E instructions.
9117 (define_insn "prefetch"
9118   [(prefetch (match_operand:SI 0 "address_operand" "p")
9119              (match_operand:SI 1 "" "")
9120              (match_operand:SI 2 "" ""))]
9121   "TARGET_ARM && arm_arch5e"
9122   "pld\\t%a0")
9124 ;; General predication pattern
9126 (define_cond_exec
9127   [(match_operator 0 "arm_comparison_operator"
9128     [(match_operand 1 "cc_register" "")
9129      (const_int 0)])]
9130   "TARGET_ARM"
9131   ""
9134 (define_insn "prologue_use"
9135   [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9136   ""
9137   "%@ %0 needed for prologue"