Apply Dimitri Makarov's patch to import attribute short_call and #pragma
[official-gcc.git] / gcc / config / arm / arm.md
blobed1a3da80b787afaee53ba37ae3aa0fe1f572f62
1 ;;- Machine description for ARM for GNU compiler
2 ;;  Copyright (C) 1991, 93-98, 1999 Free Software Foundation, Inc.
3 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
4 ;;  and Martin Simmons (@harleqn.co.uk).
5 ;;  More major hacks by Richard Earnshaw (rearnsha@arm.com).
7 ;; This file is part of GNU CC.
9 ;; GNU CC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
14 ;; GNU CC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU CC; see the file COPYING.  If not, write to
21 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
24 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26 ;; There are patterns in this file to support XFmode arithmetic.
27 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
28 ;; (See arm.h)
30 ;; UNSPEC Usage:
31 ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
32 ;;   the mode is MODE_FLOAT
33 ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
34 ;;   the mode is MODE_FLOAT
35 ;; 2 `push multiple' operation: operand 0 is the first register.  Subsequent
36 ;;   registers are in parallel (use...) expressions.
37 ;; 3 A symbol that has been treated properly for pic usage, that is, we
38 ;;   will add the pic_register value to it before trying to dereference it.
39 ;; Note: sin and cos are no-longer used.
41 ;; Attributes
43 ; PROG_MODE attribute is used to determine whether condition codes are
44 ; clobbered by a call insn: they are if in prog32 mode.  This is controlled
45 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
46 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
48 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
50 ; Floating Point Unit.  If we only have floating point emulation, then there
51 ; is no point in scheduling the floating point insns.  (Well, for best
52 ; performance we should try and group them together).
54 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
56 ; LENGTH of an instruction (in bytes)
57 (define_attr "length" "" (const_int 4))
59 ; POOL_RANGE is how far away from a constant pool entry that this insn
60 ; can be placed.  If the distance is zero, then this insn will never
61 ; reference the pool.
62 (define_attr "pool_range" "" (const_int 0))
64 ; An assembler sequence may clobber the condition codes without us knowing
65 ; If such an insn references the pool, then we have no way of knowing how,
66 ; so use the most conservative value for pool_range.
67 (define_asm_attributes
68  [(set_attr "conds" "clob")
69   (set_attr "length" "4")
70   (set_attr "pool_range" "250")])
72 ; TYPE attribute is used to detect floating point instructions which, if
73 ; running on a co-processor can run in parallel with other, basic instructions
74 ; If write-buffer scheduling is enabled then it can also be used in the
75 ; scheduling of writes.
77 ; Classification of each insn
78 ; normal        any data instruction that doesn't hit memory or fp regs
79 ; mult          a multiply instruction
80 ; block         blockage insn, this blocks all functional units
81 ; float         a floating point arithmetic operation (subject to expansion)
82 ; fdivx         XFmode floating point division
83 ; fdivd         DFmode floating point division
84 ; fdivs         SFmode floating point division
85 ; fmul          Floating point multiply
86 ; ffmul         Fast floating point multiply
87 ; farith        Floating point arithmetic (4 cycle)
88 ; ffarith       Fast floating point arithmetic (2 cycle)
89 ; float_em      a floating point arithmetic operation that is normally emulated
90 ;               even on a machine with an fpa.
91 ; f_load        a floating point load from memory
92 ; f_store       a floating point store to memory
93 ; f_mem_r       a transfer of a floating point register to a real reg via mem
94 ; r_mem_f       the reverse of f_mem_r
95 ; f_2_r         fast transfer float to arm (no memory needed)
96 ; r_2_f         fast transfer arm to float
97 ; call          a subroutine call
98 ; load          any load from memory
99 ; store1        store 1 word to memory from arm registers
100 ; store2        store 2 words
101 ; store3        store 3 words
102 ; store4        store 4 words
104 (define_attr "type"
105         "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" 
106         (const_string "normal"))
108 ; Load scheduling, set from the arm_ld_sched variable
109 ; initialised by arm_override_options() 
110 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
112 ; condition codes: this one is used by final_prescan_insn to speed up
113 ; conditionalizing instructions.  It saves having to scan the rtl to see if
114 ; it uses or alters the condition codes.
116 ; USE means that the condition codes are used by the insn in the process of
117 ; outputting code, this means (at present) that we can't use the insn in
118 ; inlined branches
120 ; SET means that the purpose of the insn is to set the condition codes in a
121 ; well defined manner.
123 ; CLOB means that the condition codes are altered in an undefined manner, if
124 ; they are altered at all
126 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
127 ; but are if the branch wasn't taken; the effect is to limit the branch
128 ; elimination scanning.
130 ; NOCOND means that the condition codes are neither altered nor affect the
131 ; output of this insn
133 (define_attr "conds" "use,set,clob,jump_clob,nocond"
134         (if_then_else (eq_attr "type" "call")
135          (if_then_else (eq_attr "prog_mode" "prog32")
136           (const_string "clob") (const_string "nocond"))
137          (const_string "nocond")))
139 ; Only model the write buffer for ARM6 and ARM7.  Earlier processors don't
140 ; have one.  Later ones, such as StrongARM, have write-back caches, so don't
141 ; suffer blockages enough to warrent modelling this (and it can adversely
142 ; affect the schedule).
143 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
145 (define_attr "write_conflict" "no,yes"
146   (if_then_else (eq_attr "type"
147                  "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
148                 (const_string "yes")
149                 (const_string "no")))
151 (define_attr "core_cycles" "single,multi"
152   (if_then_else (eq_attr "type"
153                  "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
154                 (const_string "single")
155                 (const_string "multi")))
157 ; The write buffer on some of the arm6 processors is hard to model exactly.
158 ; There is room in the buffer for up to two addresses and up to eight words
159 ; of memory, but the two needn't be split evenly.  When writing the two
160 ; addresses are fully pipelined.  However, a read from memory that is not
161 ; currently in the cache will block until the writes have completed.
162 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
163 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
164 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
165 ; cycle to add as well.
167 ;; (define_function_unit {name} {num-units} {n-users} {test}
168 ;;                       {ready-delay} {issue-delay} [{conflict-list}])
169 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
170                                      (eq_attr "type" "fdivx")) 71 69)
172 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
173                                      (eq_attr "type" "fdivd")) 59 57)
175 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
176                                      (eq_attr "type" "fdivs")) 31 29)
178 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
179                                      (eq_attr "type" "fmul")) 9 7)
181 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
182                                      (eq_attr "type" "ffmul")) 6 4)
184 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
185                                      (eq_attr "type" "farith")) 4 2)
187 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
188                                      (eq_attr "type" "ffarith")) 2 2)
190 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
191                                      (eq_attr "type" "r_2_f")) 5 3)
193 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
194                                      (eq_attr "type" "f_2_r")) 1 2)
196 ;; The fpa10 doesn't really have a memory read unit, but it can start to
197 ;; speculatively execute the instruction in the pipeline, provided the data
198 ;; is already loaded, so pretend reads have a delay of 2 (and that the
199 ;; pipeline is infinite.
201 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
202                                          (eq_attr "type" "f_load")) 3 1)
204 ;;--------------------------------------------------------------------
205 ;; Write buffer
206 ;;--------------------------------------------------------------------
207 ;; Strictly we should model a 4-deep write buffer for ARM7xx based chips
208 (define_function_unit "write_buf" 1 2
209   (and (eq_attr "model_wbuf" "yes")
210        (eq_attr "type" "store1,r_mem_f")) 5 3)
211 (define_function_unit "write_buf" 1 2 
212   (and (eq_attr "model_wbuf" "yes")
213        (eq_attr "type" "store2")) 7 4)
214 (define_function_unit "write_buf" 1 2
215   (and (eq_attr "model_wbuf" "yes")
216        (eq_attr "type" "store3")) 9 5)
217 (define_function_unit "write_buf" 1 2
218   (and (eq_attr "model_wbuf" "yes")
219        (eq_attr "type" "store4")) 11 6)
221 ;;--------------------------------------------------------------------
222 ;; Write blockage unit
223 ;;--------------------------------------------------------------------
224 ;; The write_blockage unit models (partially), the fact that reads will stall
225 ;; until the write buffer empties.
226 ;; The f_mem_r and r_mem_f could also block, but they are to the stack,
227 ;; so we don't model them here
228 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
229                                                 (eq_attr "type" "store1")) 5 5
230         [(eq_attr "write_conflict" "yes")])
231 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
232                                                 (eq_attr "type" "store2")) 7 7
233         [(eq_attr "write_conflict" "yes")])
234 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
235                                                 (eq_attr "type" "store3")) 9 9
236         [(eq_attr "write_conflict" "yes")])
237 (define_function_unit "write_blockage" 1 0
238         (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
239         [(eq_attr "write_conflict" "yes")])
240 (define_function_unit "write_blockage" 1 0
241         (and (eq_attr "model_wbuf" "yes")
242              (eq_attr "write_conflict" "yes")) 1 1)
244 ;;--------------------------------------------------------------------
245 ;; Core unit
246 ;;--------------------------------------------------------------------
247 ;; Everything must spend at least one cycle in the core unit
248 (define_function_unit "core" 1 0
249   (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
251 (define_function_unit "core" 1 0
252   (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
254 (define_function_unit "core" 1 0
255   (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
257 (define_function_unit "core" 1 0
258   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
260 (define_function_unit "core" 1 0
261   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
263 (define_function_unit "core" 1 0
264   (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
266 (define_function_unit "core" 1 0
267   (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
269 (define_function_unit "core" 1 0
270   (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
272 (define_function_unit "core" 1 0
273   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
274        (eq_attr "type" "mult")) 4 4)
276 (define_function_unit "core" 1 0
277   (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
278        (eq_attr "type" "mult")) 3 2)
280 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
282 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
284 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
286 ;; Note: For DImode insns, there is normally no reason why operands should
287 ;; not be in the same register, what we don't want is for something being
288 ;; written to partially overlap something that is an input.
290 ;; Split up 64bit addition so that the component insns can schedule
291 ;; independently.
292 (define_split
293   [(set (match_operand:DI          0 "s_register_operand" "")
294         (plus:DI (match_operand:DI 1 "s_register_operand"  "")
295                  (match_operand:DI 2 "s_register_operand"   "")))
296    (clobber (reg:CC 24))]
297   "reload_completed"
298   [(parallel [(set (reg:CC_C 24)
299                       (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
300                                     (match_dup 1)))
301               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
302    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
303                                (plus:SI (match_dup 4) (match_dup 5))))]
304   "
306   operands[3] = gen_highpart (SImode, operands[0]);
307   operands[0] = gen_lowpart (SImode, operands[0]);
308   operands[4] = gen_highpart (SImode, operands[1]);
309   operands[1] = gen_lowpart (SImode, operands[1]);
310   operands[5] = gen_highpart (SImode, operands[2]);
311   operands[2] = gen_lowpart (SImode, operands[2]);
314 ;; The first insn created by this splitter must set the low part of
315 ;; operand0 as well as the carry bit in the CC register.  The second
316 ;; insn must compute the sum of the carry bit, the sign extension of
317 ;; operand 2 from 32 to 64 bits and the high part of operand 1.
318 (define_split
319   [(set (match_operand:DI 0 "s_register_operand" "")
320         (plus:DI (sign_extend:DI
321                   (match_operand:SI 2 "s_register_operand" ""))
322                   (match_operand:DI 1 "s_register_operand" "")))
323    (clobber (reg:CC 24))]
324   "reload_completed"
325   [(parallel [(set (reg:CC_C 24)
326                       (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
327                                     (match_dup 1)))
328               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
329    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
330                                (plus:SI (ashiftrt:SI (match_dup 2)
331                                                      (const_int 31))
332                                         (match_dup 4))))]
333   "
335   operands[3] = gen_highpart (SImode, operands[0]);
336   operands[0] = gen_lowpart (SImode, operands[0]);
337   operands[4] = gen_highpart (SImode, operands[1]);
338   operands[1] = gen_lowpart (SImode, operands[1]);
339   operands[2] = gen_lowpart (SImode, operands[2]);
342 ;; The first insn created by this splitter must set the low part of
343 ;; operand0 as well as the carry bit in the CC register.  The second
344 ;; insn must compute the sum of the carry bit and the high bits from
345 ;; operand 1
346 (define_split
347   [(set (match_operand:DI 0 "s_register_operand" "")
348         (plus:DI (zero_extend:DI
349                   (match_operand:SI 2 "s_register_operand" ""))
350                   (match_operand:DI 1 "s_register_operand" "")))
351    (clobber (reg:CC 24))]
352   "reload_completed"
353   [(parallel [(set (reg:CC_C 24)
354                       (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
355                                     (match_dup 1)))
356               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
357    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
358                                (plus:SI (match_dup 4) (const_int 0))))]
359   "
361   operands[3] = gen_highpart (SImode, operands[0]);
362   operands[0] = gen_lowpart (SImode, operands[0]);
363   operands[4] = gen_highpart (SImode, operands[1]);
364   operands[1] = gen_lowpart (SImode, operands[1]);
365   operands[2] = gen_lowpart (SImode, operands[2]);
368 ;; Addition insns.
370 (define_insn "adddi3"
371   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
372         (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
373                  (match_operand:DI 2 "s_register_operand" "r,0")))
374    (clobber (reg:CC 24))]
375   ""
376   "#"
377 [(set_attr "conds" "clob")
378  (set_attr "length" "8")])
380 (define_insn "*adddi_sesidi_di"
381   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
382         (plus:DI (sign_extend:DI
383                   (match_operand:SI 2 "s_register_operand" "r,r"))
384                  (match_operand:DI 1 "s_register_operand" "r,0")))
385    (clobber (reg:CC 24))]
386   ""
387   "#"
388 [(set_attr "conds" "clob")
389  (set_attr "length" "8")])
391 (define_insn "*adddi_zesidi_di"
392   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
393         (plus:DI (zero_extend:DI
394                   (match_operand:SI 2 "s_register_operand" "r,r"))
395                  (match_operand:DI 1 "s_register_operand" "r,0")))
396    (clobber (reg:CC 24))]
397   ""
398   "#"
399 [(set_attr "conds" "clob")
400  (set_attr "length" "8")])
402 (define_expand "addsi3"
403   [(set (match_operand:SI 0 "s_register_operand" "")
404         (plus:SI (match_operand:SI 1 "s_register_operand" "")
405                  (match_operand:SI 2 "reg_or_int_operand" "")))]
406   ""
407   "
408   if (GET_CODE (operands[2]) == CONST_INT)
409     {
410       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
411                           operands[1],
412                           (reload_in_progress || reload_completed ? 0
413                            : preserve_subexpressions_p ()));
414       DONE;
415     }
418 (define_split
419   [(set (match_operand:SI 0 "s_register_operand" "")
420         (plus:SI (match_operand:SI 1 "s_register_operand" "")
421                  (match_operand:SI 2 "const_int_operand" "")))]
422   "! (const_ok_for_arm (INTVAL (operands[2]))
423       || const_ok_for_arm (-INTVAL (operands[2])))"
424   [(clobber (const_int 0))]
425   "
426   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
427                       operands[1], 0);
428   DONE;
431 (define_insn "*addsi3_insn"
432   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
433         (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
434                  (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
435   ""
436   "@
437    add%?\\t%0, %1, %2
438    sub%?\\t%0, %1, #%n2
439    #"
440 [(set_attr "length" "4,4,16")])
442 (define_insn "*addsi3_compare0"
443   [(set (reg:CC_NOOV 24)
444         (compare:CC_NOOV
445          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
446                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
447          (const_int 0)))
448    (set (match_operand:SI 0 "s_register_operand" "=r,r")
449         (plus:SI (match_dup 1) (match_dup 2)))]
450   ""
451   "@
452    add%?s\\t%0, %1, %2
453    sub%?s\\t%0, %1, #%n2"
454 [(set_attr "conds" "set")])
456 (define_insn "*addsi3_compare0_scratch"
457   [(set (reg:CC_NOOV 24)
458         (compare:CC_NOOV
459          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
460                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
461          (const_int 0)))]
462   ""
463   "@
464    cmn%?\\t%0, %1
465    cmp%?\\t%0, #%n1"
466 [(set_attr "conds" "set")])
468 ;; The next four insns work because they compare the result with one of
469 ;; the operands, and we know that the use of the condition code is
470 ;; either GEU or LTU, so we can use the carry flag from the addition
471 ;; instead of doing the compare a second time.
472 (define_insn "*addsi3_compare_op1"
473   [(set (reg:CC_C 24)
474         (compare:CC_C
475          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
476                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
477          (match_dup 1)))
478    (set (match_operand:SI 0 "s_register_operand" "=r,r")
479         (plus:SI (match_dup 1) (match_dup 2)))]
480   ""
481   "@
482    add%?s\\t%0, %1, %2
483    sub%?s\\t%0, %1, #%n2"
484 [(set_attr "conds" "set")])
486 (define_insn "*addsi3_compare_op2"
487   [(set (reg:CC_C 24)
488         (compare:CC_C
489          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
490                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
491          (match_dup 2)))
492    (set (match_operand:SI 0 "s_register_operand" "=r,r")
493         (plus:SI (match_dup 1) (match_dup 2)))]
494   ""
495   "@
496    add%?s\\t%0, %1, %2
497    sub%?s\\t%0, %1, #%n2"
498 [(set_attr "conds" "set")])
500 (define_insn "*compare_addsi2_op0"
501   [(set (reg:CC_C 24)
502         (compare:CC_C
503          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
504                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
505          (match_dup 0)))]
506   ""
507   "@
508    cmn%?\\t%0, %1
509    cmp%?\\t%0, #%n1"
510 [(set_attr "conds" "set")])
512 (define_insn "*compare_addsi2_op1"
513   [(set (reg:CC_C 24)
514         (compare:CC_C
515          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
516                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
517          (match_dup 1)))]
518   ""
519   "@
520    cmn%?\\t%0, %1
521    cmp%?\\t%0, #%n1"
522 [(set_attr "conds" "set")])
524 (define_insn "*addsi3_carryin"
525   [(set (match_operand:SI 0 "s_register_operand" "=r")
526         (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
527                  (plus:SI (match_operand:SI 1 "s_register_operand" "r")
528                           (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
529   ""
530   "adc%?\\t%0, %1, %2"
531 [(set_attr "conds" "use")])
533 (define_insn "*addsi3_carryin_shift"
534   [(set (match_operand:SI 0 "s_register_operand" "")
535         (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
536                  (plus:SI
537                    (match_operator:SI 2 "shift_operator"
538                       [(match_operand:SI 3 "s_register_operand" "")
539                        (match_operand:SI 4 "reg_or_int_operand" "")])
540                     (match_operand:SI 1 "s_register_operand" ""))))]
541   ""
542   "adc%?\\t%0, %1, %3%S2"
543   [(set_attr "conds" "use")]
546 (define_insn "*addsi3_carryin_alt1"
547   [(set (match_operand:SI 0 "s_register_operand" "=r")
548         (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
549                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
550                  (ltu:SI (reg:CC_C 24) (const_int 0))))]
551   ""
552   "adc%?\\t%0, %1, %2"
553 [(set_attr "conds" "use")])
555 (define_insn "*addsi3_carryin_alt2"
556   [(set (match_operand:SI 0 "s_register_operand" "=r")
557         (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
558                           (match_operand:SI 1 "s_register_operand" "r"))
559                  (match_operand:SI 2 "arm_rhs_operand" "rI")))]
560   ""
561   "adc%?\\t%0, %1, %2"
562 [(set_attr "conds" "use")])
564 (define_insn "*addsi3_carryin_alt3"
565   [(set (match_operand:SI 0 "s_register_operand" "=r")
566         (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
567                           (match_operand:SI 2 "arm_rhs_operand" "rI"))
568                  (match_operand:SI 1 "s_register_operand" "r")))]
569   ""
570   "adc%?\\t%0, %1, %2"
571 [(set_attr "conds" "use")])
573 (define_insn "incscc"
574   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
575         (plus:SI (match_operator:SI 2 "comparison_operator"
576                     [(match_operand 3 "cc_register" "") (const_int 0)])
577                  (match_operand:SI 1 "s_register_operand" "0,?r")))]
578   ""
579   "@
580   add%d2\\t%0, %1, #1
581   mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
582 [(set_attr "conds" "use")
583  (set_attr "length" "4,8")])
585 ; If a constant is too big to fit in a single instruction then the constant
586 ; will be pre-loaded into a register taking at least two insns, we might be
587 ; able to merge it with an add, but it depends on the exact value.
589 (define_split
590   [(set (match_operand:SI 0 "s_register_operand" "=r")
591         (plus:SI (match_operand:SI 1 "s_register_operand" "r")
592                  (match_operand:SI 2 "const_int_operand" "n")))]
593   "!(const_ok_for_arm (INTVAL (operands[2]))
594      || const_ok_for_arm (-INTVAL (operands[2])))"
595   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
596    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
597   "
599   unsigned int val = (unsigned) INTVAL (operands[2]);
600   int i;
601   unsigned int temp;
603   /* this code is similar to the approach followed in movsi, but it must
604      generate exactly two insns */
606   for (i = 30; i >= 0; i -= 2)
607     {
608       if (val & (3 << i))
609         {
610           i -= 6;
611           if (i < 0) i = 0;
612           if (const_ok_for_arm (temp = (val & ~(255 << i))))
613             {
614               val &= 255 << i;
615               break;
616             }
617           /* we might be able to do this as (larger number - small number) */
618           temp = ((val >> i) & 255) + 1;
619           if (temp > 255 && i < 24)
620             {
621               i += 2;
622               temp = ((val >> i) & 255) + 1;
623             }
624           if (const_ok_for_arm ((temp << i) - val))
625             {
626               i = temp << i;
627               temp = (unsigned) - (int) (i - val);
628               val = i;
629               break;
630             }
631           FAIL;
632         }
633     }
634   /* if we got here, we have found a way of doing it in two instructions.
635      the two constants are in val and temp */
636   operands[2] = GEN_INT ((int)val);
637   operands[3] = GEN_INT ((int)temp);
641 (define_insn "addsf3"
642   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
643         (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
644                  (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
645   "TARGET_HARD_FLOAT"
646   "@
647    adf%?s\\t%0, %1, %2
648    suf%?s\\t%0, %1, #%N2"
649 [(set_attr "type" "farith")])
651 (define_insn "adddf3"
652   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
653         (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
654                  (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
655   "TARGET_HARD_FLOAT"
656   "@
657    adf%?d\\t%0, %1, %2
658    suf%?d\\t%0, %1, #%N2"
659 [(set_attr "type" "farith")])
661 (define_insn "*adddf_esfdf_df"
662   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
663         (plus:DF (float_extend:DF
664                   (match_operand:SF 1 "s_register_operand" "f,f"))
665                  (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
666   "TARGET_HARD_FLOAT"
667   "@
668    adf%?d\\t%0, %1, %2
669    suf%?d\\t%0, %1, #%N2"
670 [(set_attr "type" "farith")])
672 (define_insn "*adddf_df_esfdf"
673   [(set (match_operand:DF 0 "s_register_operand" "=f")
674         (plus:DF (match_operand:DF 1 "s_register_operand" "f")
675                  (float_extend:DF
676                   (match_operand:SF 2 "s_register_operand" "f"))))]
677   "TARGET_HARD_FLOAT"
678   "adf%?d\\t%0, %1, %2"
679 [(set_attr "type" "farith")])
681 (define_insn "*adddf_esfdf_esfdf"
682   [(set (match_operand:DF 0 "s_register_operand" "=f")
683         (plus:DF (float_extend:DF 
684                   (match_operand:SF 1 "s_register_operand" "f"))
685                  (float_extend:DF
686                   (match_operand:SF 2 "s_register_operand" "f"))))]
687   "TARGET_HARD_FLOAT"
688   "adf%?d\\t%0, %1, %2"
689 [(set_attr "type" "farith")])
691 (define_insn "addxf3"
692   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
693         (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
694                  (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
695   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
696   "@
697    adf%?e\\t%0, %1, %2
698    suf%?e\\t%0, %1, #%N2"
699 [(set_attr "type" "farith")])
701 (define_insn "subdi3"
702   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
703         (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
704                   (match_operand:DI 2 "s_register_operand" "r,0,0")))
705    (clobber (reg:CC 24))]
706   ""
707   "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
708 [(set_attr "conds" "clob")
709  (set_attr "length" "8")])
711 (define_insn "*subdi_di_zesidi"
712   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
713         (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
714                   (zero_extend:DI
715                    (match_operand:SI 2 "s_register_operand" "r,r"))))
716    (clobber (reg:CC 24))]
717   ""
718   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
719 [(set_attr "conds" "clob")
720  (set_attr "length" "8")])
722 (define_insn "*subdi_di_sesidi"
723   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
724         (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
725                   (sign_extend:DI
726                    (match_operand:SI 2 "s_register_operand" "r,r"))))
727    (clobber (reg:CC 24))]
728   ""
729   "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
730 [(set_attr "conds" "clob")
731  (set_attr "length" "8")])
733 (define_insn "*subdi_zesidi_di"
734   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
735         (minus:DI (zero_extend:DI
736                    (match_operand:SI 2 "s_register_operand" "r,r"))
737                   (match_operand:DI 1 "s_register_operand" "?r,0")))
738    (clobber (reg:CC 24))]
739   ""
740   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
741 [(set_attr "conds" "clob")
742  (set_attr "length" "8")])
744 (define_insn "*subdi_sesidi_di"
745   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
746         (minus:DI (sign_extend:DI
747                    (match_operand:SI 2 "s_register_operand" "r,r"))
748                   (match_operand:DI 1 "s_register_operand" "?r,0")))
749    (clobber (reg:CC 24))]
750   ""
751   "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
752 [(set_attr "conds" "clob")
753  (set_attr "length" "8")])
755 (define_insn "*subdi_zesidi_zesidi"
756   [(set (match_operand:DI 0 "s_register_operand" "=r")
757         (minus:DI (zero_extend:DI
758                    (match_operand:SI 1 "s_register_operand" "r"))
759                   (zero_extend:DI
760                    (match_operand:SI 2 "s_register_operand" "r"))))
761    (clobber (reg:CC 24))]
762   ""
763   "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
764 [(set_attr "conds" "clob")
765  (set_attr "length" "8")])
767 (define_expand "subsi3"
768   [(set (match_operand:SI 0 "s_register_operand" "")
769         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
770                   (match_operand:SI 2 "s_register_operand" "")))]
771   ""
772   "
773   if (GET_CODE (operands[1]) == CONST_INT)
774     {
775       arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
776                           operands[2],
777                           (reload_in_progress || reload_completed ? 0
778                            : preserve_subexpressions_p ()));
779       DONE;
780     }
783 (define_insn "*subsi3_insn"
784   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
785         (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
786                   (match_operand:SI 2 "s_register_operand" "r,r")))]
787   ""
788   "@
789    rsb%?\\t%0, %2, %1
790    #"
791 [(set_attr "length" "4,16")])
793 (define_split
794   [(set (match_operand:SI 0 "s_register_operand" "")
795         (minus:SI (match_operand:SI 1 "const_int_operand" "")
796                   (match_operand:SI 2 "s_register_operand" "")))]
797   "! const_ok_for_arm (INTVAL (operands[1]))"
798   [(clobber (const_int 0))]
799   "
800   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
801                       operands[2], 0);
802   DONE;
805 (define_insn "*subsi3_compare0"
806   [(set (reg:CC_NOOV 24)
807         (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
808                                  (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
809                          (const_int 0)))
810    (set (match_operand:SI 0 "s_register_operand" "=r,r")
811         (minus:SI (match_dup 1) (match_dup 2)))]
812   ""
813   "@
814    sub%?s\\t%0, %1, %2
815    rsb%?s\\t%0, %2, %1"
816 [(set_attr "conds" "set")])
818 (define_insn "decscc"
819   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
820         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
821                   (match_operator:SI 2 "comparison_operator"
822                    [(match_operand 3 "cc_register" "") (const_int 0)])))]
823   ""
824   "@
825   sub%d2\\t%0, %1, #1
826   mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
827 [(set_attr "conds" "use")
828  (set_attr "length" "*,8")])
830 (define_insn "subsf3"
831   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
832         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
833                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
834   "TARGET_HARD_FLOAT"
835   "@
836    suf%?s\\t%0, %1, %2
837    rsf%?s\\t%0, %2, %1"
838 [(set_attr "type" "farith")])
840 (define_insn "subdf3"
841   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
842         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
843                   (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
844   "TARGET_HARD_FLOAT"
845   "@
846    suf%?d\\t%0, %1, %2
847    rsf%?d\\t%0, %2, %1"
848 [(set_attr "type" "farith")])
850 (define_insn "*subdf_esfdf_df"
851   [(set (match_operand:DF 0 "s_register_operand" "=f")
852         (minus:DF (float_extend:DF
853                    (match_operand:SF 1 "s_register_operand" "f"))
854                   (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
855   "TARGET_HARD_FLOAT"
856   "suf%?d\\t%0, %1, %2"
857 [(set_attr "type" "farith")])
859 (define_insn "*subdf_df_esfdf"
860   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
861         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
862                   (float_extend:DF
863                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
864   "TARGET_HARD_FLOAT"
865   "@
866    suf%?d\\t%0, %1, %2
867    rsf%?d\\t%0, %2, %1"
868 [(set_attr "type" "farith")])
870 (define_insn "*subdf_esfdf_esfdf"
871   [(set (match_operand:DF 0 "s_register_operand" "=f")
872         (minus:DF (float_extend:DF
873                    (match_operand:SF 1 "s_register_operand" "f"))
874                   (float_extend:DF
875                    (match_operand:SF 2 "s_register_operand" "f"))))]
876   "TARGET_HARD_FLOAT"
877   "suf%?d\\t%0, %1, %2"
878 [(set_attr "type" "farith")])
880 (define_insn "subxf3"
881   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
882         (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
883                   (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
884   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
885   "@
886    suf%?e\\t%0, %1, %2
887    rsf%?e\\t%0, %2, %1"
888 [(set_attr "type" "farith")])
890 ;; Multiplication insns
892 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
893 (define_insn "mulsi3"
894   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
895         (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
896                  (match_operand:SI 1 "s_register_operand" "%?r,0")))]
897   ""
898   "mul%?\\t%0, %2, %1"
899 [(set_attr "type" "mult")])
901 (define_insn "*mulsi3_compare0"
902   [(set (reg:CC_NOOV 24)
903         (compare:CC_NOOV (mult:SI
904                           (match_operand:SI 2 "s_register_operand" "r,r")
905                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
906                          (const_int 0)))
907    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
908         (mult:SI (match_dup 2) (match_dup 1)))]
909   ""
910   "mul%?s\\t%0, %2, %1"
911 [(set_attr "conds" "set")
912  (set_attr "type" "mult")])
914 (define_insn "*mulsi_compare0_scratch"
915   [(set (reg:CC_NOOV 24)
916         (compare:CC_NOOV (mult:SI
917                           (match_operand:SI 2 "s_register_operand" "r,r")
918                           (match_operand:SI 1 "s_register_operand" "%?r,0"))
919                          (const_int 0)))
920    (clobber (match_scratch:SI 0 "=&r,&r"))]
921   ""
922   "mul%?s\\t%0, %2, %1"
923 [(set_attr "conds" "set")
924  (set_attr "type" "mult")])
926 ;; Unnamed templates to match MLA instruction.
928 (define_insn "*mulsi3addsi"
929   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
930         (plus:SI
931           (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
932                    (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
933           (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
934   ""
935   "mla%?\\t%0, %2, %1, %3"
936 [(set_attr "type" "mult")])
938 (define_insn "*mulsi3addsi_compare0"
939   [(set (reg:CC_NOOV 24)
940         (compare:CC_NOOV (plus:SI
941                           (mult:SI
942                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
943                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
944                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
945                          (const_int 0)))
946    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
947         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
948                  (match_dup 3)))]
949   ""
950   "mla%?s\\t%0, %2, %1, %3"
951 [(set_attr "conds" "set")
952  (set_attr "type" "mult")])
954 (define_insn "*mulsi3addsi_compare0_scratch"
955   [(set (reg:CC_NOOV 24)
956         (compare:CC_NOOV (plus:SI
957                           (mult:SI
958                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
959                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
960                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
961                          (const_int 0)))
962    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
963   ""
964   "mla%?s\\t%0, %2, %1, %3"
965 [(set_attr "conds" "set")
966  (set_attr "type" "mult")])
968 ;; Unnamed template to match long long multiply-accumlate (smlal)
970 (define_insn "*mulsidi3adddi"
971   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
972         (plus:DI
973           (mult:DI (sign_extend:DI
974                     (match_operand:SI 2 "s_register_operand" "r,0,1"))
975                    (sign_extend:DI
976                     (match_operand:SI 1 "s_register_operand" "%r,r,r")))
977           (match_dup 0)))]
978   "arm_fast_multiply"
979   "smlal%?\\t%Q0, %R0, %1, %2"
980 [(set_attr "type" "mult")])
982 (define_insn "mulsidi3"
983   [(set (match_operand:DI 0 "s_register_operand" "=&r")
984       (mult:DI (sign_extend:DI
985                 (match_operand:SI 1 "s_register_operand" "%r"))
986                (sign_extend:DI
987                (match_operand:SI 2 "s_register_operand" "r"))))]
988   "arm_fast_multiply"
989   "smull%?\\t%Q0, %R0, %1, %2"
990 [(set_attr "type" "mult")])
992 (define_insn "umulsidi3"
993   [(set (match_operand:DI 0 "s_register_operand" "=&r")
994       (mult:DI (zero_extend:DI
995                 (match_operand:SI 1 "s_register_operand" "%r"))
996                (zero_extend:DI
997                 (match_operand:SI 2 "s_register_operand" "r"))))]
998   "arm_fast_multiply"
999   "umull%?\\t%Q0, %R0, %1, %2"
1000 [(set_attr "type" "mult")])
1002 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1004 (define_insn "*umulsidi3adddi"
1005   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
1006         (plus:DI
1007           (mult:DI (zero_extend:DI
1008                     (match_operand:SI 2 "s_register_operand" "r,0,1"))
1009                    (zero_extend:DI
1010                     (match_operand:SI 1 "s_register_operand" "%r,r,r")))
1011           (match_dup 0)))]
1012   "arm_fast_multiply"
1013   "umlal%?\\t%Q0, %R0, %1, %2"
1014 [(set_attr "type" "mult")])
1016 (define_insn "smulsi3_highpart"
1017   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1018         (truncate:SI
1019          (lshiftrt:DI
1020           (mult:DI (sign_extend:DI
1021                     (match_operand:SI 1 "s_register_operand" "%r,0"))
1022                    (sign_extend:DI
1023                     (match_operand:SI 2 "s_register_operand" "r,r")))
1024           (const_int 32))))
1025    (clobber (match_scratch:SI 3 "=&r,&r"))]
1026   "arm_fast_multiply"
1027   "smull%?\\t%3, %0, %2, %1"
1028 [(set_attr "type" "mult")])
1030 (define_insn "umulsi3_highpart"
1031   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1032         (truncate:SI
1033          (lshiftrt:DI
1034           (mult:DI (zero_extend:DI
1035                     (match_operand:SI 1 "s_register_operand" "%r,0"))
1036                    (zero_extend:DI
1037                     (match_operand:SI 2 "s_register_operand" "r,r")))
1038           (const_int 32))))
1039    (clobber (match_scratch:SI 3 "=&r,&r"))]
1040   "arm_fast_multiply"
1041   "umull%?\\t%3, %0, %2, %1"
1042 [(set_attr "type" "mult")])
1044 (define_insn "mulsf3"
1045   [(set (match_operand:SF 0 "s_register_operand" "=f")
1046         (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1047                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1048   "TARGET_HARD_FLOAT"
1049   "fml%?s\\t%0, %1, %2"
1050 [(set_attr "type" "ffmul")])
1052 (define_insn "muldf3"
1053   [(set (match_operand:DF 0 "s_register_operand" "=f")
1054         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1055                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1056   "TARGET_HARD_FLOAT"
1057   "muf%?d\\t%0, %1, %2"
1058 [(set_attr "type" "fmul")])
1060 (define_insn "*muldf_esfdf_df"
1061   [(set (match_operand:DF 0 "s_register_operand" "=f")
1062         (mult:DF (float_extend:DF
1063                   (match_operand:SF 1 "s_register_operand" "f"))
1064                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1065   "TARGET_HARD_FLOAT"
1066   "muf%?d\\t%0, %1, %2"
1067 [(set_attr "type" "fmul")])
1069 (define_insn "*muldf_df_esfdf"
1070   [(set (match_operand:DF 0 "s_register_operand" "=f")
1071         (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1072                  (float_extend:DF
1073                   (match_operand:SF 2 "s_register_operand" "f"))))]
1074   "TARGET_HARD_FLOAT"
1075   "muf%?d\\t%0, %1, %2"
1076 [(set_attr "type" "fmul")])
1078 (define_insn "*muldf_esfdf_esfdf"
1079   [(set (match_operand:DF 0 "s_register_operand" "=f")
1080         (mult:DF (float_extend:DF
1081                   (match_operand:SF 1 "s_register_operand" "f"))
1082                  (float_extend:DF
1083                   (match_operand:SF 2 "s_register_operand" "f"))))]
1084   "TARGET_HARD_FLOAT"
1085   "muf%?d\\t%0, %1, %2"
1086 [(set_attr "type" "fmul")])
1088 (define_insn "mulxf3"
1089   [(set (match_operand:XF 0 "s_register_operand" "=f")
1090         (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1091                  (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1092   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1093   "muf%?e\\t%0, %1, %2"
1094 [(set_attr "type" "fmul")])
1096 ;; Division insns
1098 (define_insn "divsf3"
1099   [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1100         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1101                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1102   "TARGET_HARD_FLOAT"
1103   "@
1104    fdv%?s\\t%0, %1, %2
1105    frd%?s\\t%0, %2, %1"
1106 [(set_attr "type" "fdivs")])
1108 (define_insn "divdf3"
1109   [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1110         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1111                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1112   "TARGET_HARD_FLOAT"
1113   "@
1114    dvf%?d\\t%0, %1, %2
1115    rdf%?d\\t%0, %2, %1"
1116 [(set_attr "type" "fdivd")])
1118 (define_insn "*divdf_esfdf_df"
1119   [(set (match_operand:DF 0 "s_register_operand" "=f")
1120         (div:DF (float_extend:DF
1121                  (match_operand:SF 1 "s_register_operand" "f"))
1122                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1123   "TARGET_HARD_FLOAT"
1124   "dvf%?d\\t%0, %1, %2"
1125 [(set_attr "type" "fdivd")])
1127 (define_insn "*divdf_df_esfdf"
1128   [(set (match_operand:DF 0 "s_register_operand" "=f")
1129         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1130                 (float_extend:DF
1131                  (match_operand:SF 2 "s_register_operand" "f"))))]
1132   "TARGET_HARD_FLOAT"
1133   "rdf%?d\\t%0, %2, %1"
1134 [(set_attr "type" "fdivd")])
1136 (define_insn "*divdf_esfdf_esfdf"
1137   [(set (match_operand:DF 0 "s_register_operand" "=f")
1138         (div:DF (float_extend:DF
1139                  (match_operand:SF 1 "s_register_operand" "f"))
1140                 (float_extend:DF
1141                  (match_operand:SF 2 "s_register_operand" "f"))))]
1142   "TARGET_HARD_FLOAT"
1143   "dvf%?d\\t%0, %1, %2"
1144 [(set_attr "type" "fdivd")])
1146 (define_insn "divxf3"
1147   [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1148         (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1149                 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1150   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1151   "@
1152    dvf%?e\\t%0, %1, %2
1153    rdf%?e\\t%0, %2, %1"
1154 [(set_attr "type" "fdivx")])
1156 ;; Modulo insns
1158 (define_insn "modsf3"
1159   [(set (match_operand:SF 0 "s_register_operand" "=f")
1160         (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1161                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1162   "TARGET_HARD_FLOAT"
1163   "rmf%?s\\t%0, %1, %2"
1164 [(set_attr "type" "fdivs")])
1166 (define_insn "moddf3"
1167   [(set (match_operand:DF 0 "s_register_operand" "=f")
1168         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1169                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1170   "TARGET_HARD_FLOAT"
1171   "rmf%?d\\t%0, %1, %2"
1172 [(set_attr "type" "fdivd")])
1174 (define_insn "*moddf_esfdf_df"
1175   [(set (match_operand:DF 0 "s_register_operand" "=f")
1176         (mod:DF (float_extend:DF
1177                  (match_operand:SF 1 "s_register_operand" "f"))
1178                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1179   "TARGET_HARD_FLOAT"
1180   "rmf%?d\\t%0, %1, %2"
1181 [(set_attr "type" "fdivd")])
1183 (define_insn "*moddf_df_esfdf"
1184   [(set (match_operand:DF 0 "s_register_operand" "=f")
1185         (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1186                 (float_extend:DF
1187                  (match_operand:SF 2 "s_register_operand" "f"))))]
1188   "TARGET_HARD_FLOAT"
1189   "rmf%?d\\t%0, %1, %2"
1190 [(set_attr "type" "fdivd")])
1192 (define_insn "*moddf_esfdf_esfdf"
1193   [(set (match_operand:DF 0 "s_register_operand" "=f")
1194         (mod:DF (float_extend:DF
1195                  (match_operand:SF 1 "s_register_operand" "f"))
1196                 (float_extend:DF
1197                  (match_operand:SF 2 "s_register_operand" "f"))))]
1198   "TARGET_HARD_FLOAT"
1199   "rmf%?d\\t%0, %1, %2"
1200 [(set_attr "type" "fdivd")])
1202 (define_insn "modxf3"
1203   [(set (match_operand:XF 0 "s_register_operand" "=f")
1204         (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1205                 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1206   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1207   "rmf%?e\\t%0, %1, %2"
1208 [(set_attr "type" "fdivx")])
1210 ;; Boolean and,ior,xor insns
1212 ;; Split up double word logical operations
1214 ;; Split up simple DImode logical operations.  Simply perform the logical
1215 ;; operation on the upper and lower halves of the registers.
1216 (define_split
1217   [(set (match_operand:DI 0 "s_register_operand" "")
1218         (match_operator:DI 6 "logical_binary_operator"
1219           [(match_operand:DI 1 "s_register_operand" "")
1220            (match_operand:DI 2 "s_register_operand" "")]))]
1221   "reload_completed"
1222   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1223    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1224   "
1226   operands[3] = gen_highpart (SImode, operands[0]);
1227   operands[0] = gen_lowpart (SImode, operands[0]);
1228   operands[4] = gen_highpart (SImode, operands[1]);
1229   operands[1] = gen_lowpart (SImode, operands[1]);
1230   operands[5] = gen_highpart (SImode, operands[2]);
1231   operands[2] = gen_lowpart (SImode, operands[2]);
1234 (define_split
1235   [(set (match_operand:DI 0 "s_register_operand" "")
1236         (not:DI (match_operand:DI 1 "s_register_operand" "")))]
1237   "reload_completed"
1238   [(set (match_dup 0) (not:SI (match_dup 1)))
1239    (set (match_dup 2) (not:SI (match_dup 3)))]
1240   "
1242   operands[2] = gen_highpart (SImode, operands[0]);
1243   operands[0] = gen_lowpart (SImode, operands[0]);
1244   operands[3] = gen_highpart (SImode, operands[1]);
1245   operands[1] = gen_lowpart (SImode, operands[1]);
1248 (define_split
1249   [(set (match_operand:DI 0 "s_register_operand" "")
1250         (and:DI
1251           (not:DI (match_operand:DI 1 "s_register_operand" ""))
1252           (match_operand:DI 2 "s_register_operand" "")))]
1253   "reload_completed"
1254   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1255    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1256   "
1258   operands[3] = gen_highpart (SImode, operands[0]);
1259   operands[0] = gen_lowpart (SImode, operands[0]);
1260   operands[4] = gen_highpart (SImode, operands[1]);
1261   operands[1] = gen_lowpart (SImode, operands[1]);
1262   operands[5] = gen_highpart (SImode, operands[2]);
1263   operands[2] = gen_lowpart (SImode, operands[2]);
1266 (define_split
1267   [(set (match_operand:DI 0 "s_register_operand" "")
1268         (match_operator:DI 6 "logical_binary_operator"
1269           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1270            (match_operand:DI 1 "s_register_operand" "")]))]
1271   "reload_completed"
1272   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1273    (set (match_dup 3) (match_op_dup:SI 6
1274                         [(ashiftrt:SI (match_dup 2) (const_int 31))
1275                          (match_dup 4)]))]
1276   "
1278   operands[3] = gen_highpart (SImode, operands[0]);
1279   operands[0] = gen_lowpart (SImode, operands[0]);
1280   operands[4] = gen_highpart (SImode, operands[1]);
1281   operands[1] = gen_lowpart (SImode, operands[1]);
1282   operands[5] = gen_highpart (SImode, operands[2]);
1283   operands[2] = gen_lowpart (SImode, operands[2]);
1286 (define_split
1287   [(set (match_operand:DI 0 "s_register_operand" "")
1288         (and:DI (not:DI (sign_extend:DI
1289                         (match_operand:SI 2 "s_register_operand" "")))
1290                 (match_operand:DI 1 "s_register_operand" "")))]
1291   "reload_completed"
1292   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1293    (set (match_dup 3) (and:SI (not:SI
1294                                 (ashiftrt:SI (match_dup 2) (const_int 31)))
1295                                (match_dup 4)))]
1296   "
1298   operands[3] = gen_highpart (SImode, operands[0]);
1299   operands[0] = gen_lowpart (SImode, operands[0]);
1300   operands[4] = gen_highpart (SImode, operands[1]);
1301   operands[1] = gen_lowpart (SImode, operands[1]);
1302   operands[2] = gen_lowpart (SImode, operands[2]);
1305 ;; The zero extend of operand 2 clears the high word of the output
1306 ;; operand.
1307 (define_split
1308   [(set (match_operand:DI 0 "s_register_operand" "")
1309         (and:DI
1310           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1311           (match_operand:DI 1 "s_register_operand" "")))]
1312   "reload_completed"
1313   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1314    (set (match_dup 3) (const_int 0))]
1315   "
1317   operands[3] = gen_highpart (SImode, operands[0]);
1318   operands[0] = gen_lowpart (SImode, operands[0]);
1319   operands[1] = gen_lowpart (SImode, operands[1]);
1322 ;; The zero extend of operand 2 means we can just copy the high part of
1323 ;; operand1 into operand0.
1324 (define_split
1325   [(set (match_operand:DI 0 "s_register_operand" "")
1326         (ior:DI
1327           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1328           (match_operand:DI 1 "s_register_operand" "")))]
1329   "operands[0] != operands[1] && reload_completed"
1330   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1331    (set (match_dup 3) (match_dup 4))]
1332   "
1334   operands[4] = gen_highpart (SImode, operands[1]);
1335   operands[3] = gen_highpart (SImode, operands[0]);
1336   operands[0] = gen_lowpart (SImode, operands[0]);
1337   operands[1] = gen_lowpart (SImode, operands[1]);
1340 ;; The zero extend of operand 2 means we can just copy the high part of
1341 ;; operand1 into operand0.
1342 (define_split
1343   [(set (match_operand:DI 0 "s_register_operand" "")
1344         (xor:DI
1345           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1346           (match_operand:DI 1 "s_register_operand" "")))]
1347   "operands[0] != operands[1] && reload_completed"
1348   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1349    (set (match_dup 3) (match_dup 4))]
1350   "
1352   operands[4] = gen_highpart (SImode, operands[1]);
1353   operands[3] = gen_highpart (SImode, operands[0]);
1354   operands[0] = gen_lowpart (SImode, operands[0]);
1355   operands[1] = gen_lowpart (SImode, operands[1]);
1358 ;; (not (zero_extend ...)) allows us to just copy the high word from
1359 ;; operand1 to operand0.
1360 (define_split
1361   [(set (match_operand:DI 0 "s_register_operand" "")
1362         (and:DI (not:DI (zero_extend:DI
1363                         (match_operand:SI 2 "s_register_operand" "")))
1364                 (match_operand:DI 1 "s_register_operand" "")))]
1365   "operands[0] != operands[1] && reload_completed"
1366   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1367    (set (match_dup 3) (match_dup 4))]
1368   "
1370   operands[3] = gen_highpart (SImode, operands[0]);
1371   operands[0] = gen_lowpart (SImode, operands[0]);
1372   operands[4] = gen_highpart (SImode, operands[1]);
1373   operands[1] = gen_lowpart (SImode, operands[1]);
1374   operands[2] = gen_lowpart (SImode, operands[2]);
1377 (define_insn "anddi3"
1378   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1379         (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1380                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1381   ""
1382   "#"
1383 [(set_attr "length" "8")])
1385 (define_insn "*anddi_zesidi_di"
1386   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1387         (and:DI (zero_extend:DI
1388                  (match_operand:SI 2 "s_register_operand" "r,r"))
1389                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1390   ""
1391   "#"
1392 [(set_attr "length" "8")])
1394 (define_insn "*anddi_sesdi_di"
1395   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1396         (and:DI (sign_extend:DI
1397                  (match_operand:SI 2 "s_register_operand" "r,r"))
1398                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1399   ""
1400   "#"
1401 [(set_attr "length" "8")])
1403 (define_expand "andsi3"
1404   [(set (match_operand:SI 0 "s_register_operand" "")
1405         (and:SI (match_operand:SI 1 "s_register_operand" "")
1406                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1407   ""
1408   "
1409   if (GET_CODE (operands[2]) == CONST_INT)
1410     {
1411       arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1412                           operands[1],
1413                           (reload_in_progress || reload_completed
1414                            ? 0 : preserve_subexpressions_p ()));
1415       DONE;
1416     }
1419 (define_insn "*andsi3_insn"
1420   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1421         (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1422                 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1423   ""
1424   "@
1425    and%?\\t%0, %1, %2
1426    bic%?\\t%0, %1, #%B2
1427    #"
1428 [(set_attr "length" "4,4,16")])
1430 (define_split
1431   [(set (match_operand:SI 0 "s_register_operand" "")
1432         (and:SI (match_operand:SI 1 "s_register_operand" "")
1433                 (match_operand:SI 2 "const_int_operand" "")))]
1434   "! (const_ok_for_arm (INTVAL (operands[2]))
1435       || const_ok_for_arm (~ INTVAL (operands[2])))"
1436   [(clobber (const_int 0))]
1437   "
1438   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1439                        operands[1], 0);
1440   DONE;
1443 (define_insn "*andsi3_compare0"
1444   [(set (reg:CC_NOOV 24)
1445         (compare:CC_NOOV
1446          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1447                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1448          (const_int 0)))
1449    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1450         (and:SI (match_dup 1) (match_dup 2)))]
1451   ""
1452   "@
1453    and%?s\\t%0, %1, %2
1454    bic%?s\\t%0, %1, #%B2"
1455 [(set_attr "conds" "set")])
1457 (define_insn "*andsi3_compare0_scratch"
1458   [(set (reg:CC_NOOV 24)
1459         (compare:CC_NOOV
1460          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1461                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1462          (const_int 0)))
1463    (clobber (match_scratch:SI 3 "=X,r"))]
1464   ""
1465   "@
1466    tst%?\\t%0, %1
1467    bic%?s\\t%3, %0, #%B1"
1468 [(set_attr "conds" "set")])
1470 (define_insn "*zeroextractsi_compare0_scratch"
1471   [(set (reg:CC_NOOV 24)
1472         (compare:CC_NOOV (zero_extract:SI
1473                           (match_operand:SI 0 "s_register_operand" "r")
1474                           (match_operand 1 "const_int_operand" "n")
1475                           (match_operand 2 "const_int_operand" "n"))
1476                          (const_int 0)))]
1477   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1478    && INTVAL (operands[1]) > 0 
1479    && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1480    && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1481   "*
1482   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1483                          << INTVAL (operands[2]));
1484   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1485   return \"\";
1487 [(set_attr "conds" "set")])
1489 (define_insn "*ne_zeroextractsi"
1490   [(set (match_operand:SI 0 "s_register_operand" "=r")
1491         (ne:SI (zero_extract:SI
1492                 (match_operand:SI 1 "s_register_operand" "r")
1493                 (match_operand:SI 2 "const_int_operand" "n")
1494                 (match_operand:SI 3 "const_int_operand" "n"))
1495                (const_int 0)))]
1496   "INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1497    && INTVAL (operands[2]) > 0 
1498    && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1499    && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32"
1500   "*
1501   operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1502                          << INTVAL (operands[3]));
1503   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1504   return \"movne\\t%0, #1\";
1506 [(set_attr "conds" "clob")
1507  (set_attr "length" "8")])
1509 ;;; ??? This pattern is bogus.  If operand3 has bits outside the range
1510 ;;; represented by the bitfield, then this will produce incorrect results.
1511 ;;; Somewhere, the value needs to be truncated.  On targets like the m68k,
1512 ;;; which have a real bitfield insert instruction, the truncation happens
1513 ;;; in the bitfield insert instruction itself.  Since arm does not have a
1514 ;;; bitfield insert instruction, we would have to emit code here to truncate
1515 ;;; the value before we insert.  This loses some of the advantage of having
1516 ;;; this insv pattern, so this pattern needs to be reevalutated.
1518 (define_expand "insv"
1519   [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1520                          (match_operand:SI 1 "general_operand" "")
1521                          (match_operand:SI 2 "general_operand" ""))
1522         (match_operand:SI 3 "nonmemory_operand" ""))]
1523   ""
1524   "
1526   int start_bit = INTVAL (operands[2]);
1527   int width = INTVAL (operands[1]);
1528   HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1529   rtx target, subtarget;
1530   
1531   target = operands[0];
1532   /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1533      subreg as the final target.  */
1534   if (GET_CODE (target) == SUBREG)
1535     {
1536       subtarget = gen_reg_rtx (SImode);
1537       if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1538           < GET_MODE_SIZE (SImode))
1539         target = SUBREG_REG (target);
1540     }
1541   else
1542     subtarget = target;    
1543     
1544   if (GET_CODE (operands[3]) == CONST_INT)
1545     {
1546       /* Since we are inserting a known constant, we may be able to
1547          reduce the number of bits that we have to clear so that
1548          the mask becomes simple.  */
1549       /* ??? This code does not check to see if the new mask is actually
1550          simpler.  It may not be.  */
1551       rtx op1 = gen_reg_rtx (SImode);
1552       /* ??? Truncate operand3 to fit in the bitfield.  See comment before
1553          start of this pattern.  */
1554       HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1555       HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1557       emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1558       emit_insn (gen_iorsi3 (subtarget, op1,
1559                              GEN_INT (op3_value << start_bit)));
1560     }
1561   else if (start_bit == 0
1562            && ! (const_ok_for_arm (mask)
1563                  || const_ok_for_arm (~mask)))
1564     {
1565       /* A Trick, since we are setting the bottom bits in the word,
1566          we can shift operand[3] up, operand[0] down, OR them together
1567          and rotate the result back again.  This takes 3 insns, and
1568          the third might be mergable into another op.  */
1569       /* The shift up copes with the possibility that operand[3] is
1570          wider than the bitfield.  */
1571       rtx op0 = gen_reg_rtx (SImode);
1572       rtx op1 = gen_reg_rtx (SImode);
1574       emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1575       emit_insn (gen_iorsi3 (op1, gen_rtx_LSHIFTRT (SImode, operands[0],
1576                                                             operands[1]),
1577                              op0));
1578       emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1579     }
1580   else if ((width + start_bit == 32)
1581            && ! (const_ok_for_arm (mask)
1582                  || const_ok_for_arm (~mask)))
1583     {
1584       /* Similar trick, but slightly less efficient.  */
1586       rtx op0 = gen_reg_rtx (SImode);
1587       rtx op1 = gen_reg_rtx (SImode);
1589       emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1590       emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1591       emit_insn (gen_iorsi3 (subtarget,
1592                              gen_rtx_LSHIFTRT (SImode, op1, operands[1]),
1593                              op0));
1594     }
1595   else
1596     {
1597       rtx op0 = GEN_INT (mask);
1598       rtx op1 = gen_reg_rtx (SImode);
1599       rtx op2 = gen_reg_rtx (SImode);
1601       if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1602         {
1603           rtx tmp = gen_reg_rtx (SImode);
1605           emit_insn (gen_movsi (tmp, op0));
1606           op0 = tmp;
1607         }
1609       /* Mask out any bits in operand[3] that are not needed.  */
1610       emit_insn (gen_andsi3 (op1, operands[3], op0));
1612       if (GET_CODE (op0) == CONST_INT
1613           && (const_ok_for_arm (mask << start_bit)
1614               || const_ok_for_arm (~ (mask << start_bit))))
1615         {
1616           op0 = GEN_INT (~(mask << start_bit));
1617           emit_insn (gen_andsi3 (op2, operands[0], op0));
1618         }
1619       else
1620         {
1621           if (GET_CODE (op0) == CONST_INT)
1622             {
1623               rtx tmp = gen_reg_rtx (SImode);
1625               emit_insn (gen_movsi (tmp, op0));
1626               op0 = tmp;
1627             }
1629           if (start_bit != 0)
1630             op0 = gen_rtx_ASHIFT (SImode, op0, operands[2]);
1631             
1632           emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1633         }
1635       if (start_bit != 0)
1636         op1 = gen_rtx_ASHIFT (SImode, op1, operands[2]);
1638       emit_insn (gen_iorsi3 (subtarget, op1, op2));
1639     }
1641   if (subtarget != target)
1642     {
1643       /* If TARGET is still a SUBREG, then it must be wider than a word,
1644          so we must be careful only to set the subword we were asked to. */
1645       if (GET_CODE (target) == SUBREG)
1646         emit_move_insn (target, subtarget);
1647       else
1648         emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1649     }
1651   DONE;
1655 ;; constants for op 2 will never be given to these patterns.
1656 (define_insn "*anddi_notdi_di"
1657   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1658         (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1659                 (match_operand:DI 1 "s_register_operand" "0,r")))]
1660   ""
1661   "#"
1662 [(set_attr "length" "8")])
1663   
1664 (define_insn "*anddi_notzesidi_di"
1665   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1666         (and:DI (not:DI (zero_extend:DI
1667                          (match_operand:SI 2 "s_register_operand" "r,r")))
1668                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1669   ""
1670   "@
1671    bic%?\\t%Q0, %Q1, %2
1672    #"
1673 [(set_attr "length" "4,8")])
1674   
1675 (define_insn "*anddi_notsesidi_di"
1676   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1677         (and:DI (not:DI (sign_extend:DI
1678                          (match_operand:SI 2 "s_register_operand" "r,r")))
1679                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1680   ""
1681   "#"
1682 [(set_attr "length" "8")])
1683   
1684 (define_insn "andsi_notsi_si"
1685   [(set (match_operand:SI 0 "s_register_operand" "=r")
1686         (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1687                 (match_operand:SI 1 "s_register_operand" "r")))]
1688   ""
1689   "bic%?\\t%0, %1, %2")
1691 (define_insn "andsi_not_shiftsi_si"
1692   [(set (match_operand:SI 0 "s_register_operand" "=r")
1693         (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1694                          [(match_operand:SI 2 "s_register_operand" "r")
1695                           (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1696                 (match_operand:SI 1 "s_register_operand" "r")))]
1697   ""
1698   "bic%?\\t%0, %1, %2%S4"
1701 (define_insn "*andsi_notsi_si_compare0"
1702   [(set (reg:CC_NOOV 24)
1703         (compare:CC_NOOV
1704          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1705                  (match_operand:SI 1 "s_register_operand" "r"))
1706          (const_int 0)))
1707    (set (match_operand:SI 0 "s_register_operand" "=r")
1708         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1709   ""
1710   "bic%?s\\t%0, %1, %2"
1711 [(set_attr "conds" "set")])
1713 (define_insn "*andsi_notsi_si_compare0_scratch"
1714   [(set (reg:CC_NOOV 24)
1715         (compare:CC_NOOV
1716          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1717                  (match_operand:SI 1 "s_register_operand" "r"))
1718          (const_int 0)))
1719    (clobber (match_scratch:SI 0 "=r"))]
1720   ""
1721   "bic%?s\\t%0, %1, %2"
1722 [(set_attr "conds" "set")])
1724 (define_insn "iordi3"
1725   [(set (match_operand:DI 0 "s_register_operand" "=&r")
1726         (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1727                 (match_operand:DI 2 "s_register_operand" "r")))]
1728   ""
1729   "#"
1730 [(set_attr "length" "8")])
1732 (define_insn "*iordi_zesidi_di"
1733   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1734         (ior:DI (zero_extend:DI
1735                  (match_operand:SI 2 "s_register_operand" "r,r"))
1736                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1737   ""
1738   "@
1739    orr%?\\t%Q0, %Q1, %2
1740    #"
1741 [(set_attr "length" "4,8")])
1743 (define_insn "*iordi_sesidi_di"
1744   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1745         (ior:DI (sign_extend:DI
1746                  (match_operand:SI 2 "s_register_operand" "r,r"))
1747                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1748   ""
1749   "#"
1750 [(set_attr "length" "8")])
1752 (define_expand "iorsi3"
1753   [(set (match_operand:SI 0 "s_register_operand" "")
1754         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1755                 (match_operand:SI 2 "reg_or_int_operand" "")))]
1756   ""
1757   "
1758   if (GET_CODE (operands[2]) == CONST_INT)
1759     {
1760       arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1761                           operands[1],
1762                           (reload_in_progress || reload_completed
1763                            ? 0 : preserve_subexpressions_p ()));
1764       DONE;
1765     }
1768 (define_insn "*iorsi3_insn"
1769   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1770         (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1771                 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1772   ""
1773   "@
1774    orr%?\\t%0, %1, %2
1775    #"
1776 [(set_attr "length" "4,16")])
1778 (define_split
1779   [(set (match_operand:SI 0 "s_register_operand" "")
1780         (ior:SI (match_operand:SI 1 "s_register_operand" "")
1781                 (match_operand:SI 2 "const_int_operand" "")))]
1782   "! const_ok_for_arm (INTVAL (operands[2]))"
1783   [(clobber (const_int 0))]
1784   "
1785   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1786                       operands[1], 0);
1787   DONE;
1789   
1790 (define_insn "*iorsi3_compare0"
1791   [(set (reg:CC_NOOV 24)
1792         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1793                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1794                          (const_int 0)))
1795    (set (match_operand:SI 0 "s_register_operand" "=r")
1796         (ior:SI (match_dup 1) (match_dup 2)))]
1797   ""
1798   "orr%?s\\t%0, %1, %2"
1799 [(set_attr "conds" "set")])
1801 (define_insn "*iorsi3_compare0_scratch"
1802   [(set (reg:CC_NOOV 24)
1803         (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1804                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1805                          (const_int 0)))
1806    (clobber (match_scratch:SI 0 "=r"))]
1807   ""
1808   "orr%?s\\t%0, %1, %2"
1809 [(set_attr "conds" "set")])
1811 (define_insn "xordi3"
1812   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1813         (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1814                 (match_operand:DI 2 "s_register_operand" "r,0")))]
1815   ""
1816   "#"
1817 [(set_attr "length" "8")])
1819 (define_insn "*xordi_zesidi_di"
1820   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1821         (xor:DI (zero_extend:DI
1822                  (match_operand:SI 2 "s_register_operand" "r,r"))
1823                 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1824   ""
1825   "@
1826    eor%?\\t%Q0, %Q1, %2
1827    #"
1828 [(set_attr "length" "4,8")])
1830 (define_insn "*xordi_sesidi_di"
1831   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1832         (xor:DI (sign_extend:DI
1833                  (match_operand:SI 2 "s_register_operand" "r,r"))
1834                 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1835   ""
1836   "#"
1837 [(set_attr "length" "8")])
1839 (define_insn "xorsi3"
1840   [(set (match_operand:SI 0 "s_register_operand" "=r")
1841         (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1842                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1843   ""
1844   "eor%?\\t%0, %1, %2")
1846 (define_insn "*xorsi3_compare0"
1847   [(set (reg:CC_NOOV 24)
1848         (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1849                                  (match_operand:SI 2 "arm_rhs_operand" "rI"))
1850                          (const_int 0)))
1851    (set (match_operand:SI 0 "s_register_operand" "=r")
1852         (xor:SI (match_dup 1) (match_dup 2)))]
1853   ""
1854   "eor%?s\\t%0, %1, %2"
1855 [(set_attr "conds" "set")])
1857 (define_insn "*xorsi3_compare0_scratch"
1858   [(set (reg:CC_NOOV 24)
1859         (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1860                                  (match_operand:SI 1 "arm_rhs_operand" "rI"))
1861                          (const_int 0)))]
1862   ""
1863   "teq%?\\t%0, %1"
1864 [(set_attr "conds" "set")])
1866 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C), 
1867 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1868 ;; insns
1870 (define_split
1871   [(set (match_operand:SI 0 "s_register_operand" "=r")
1872         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1873                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1874                 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1875    (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1876   ""
1877   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1878                               (not:SI (match_dup 3))))
1879    (set (match_dup 0) (not:SI (match_dup 4)))]
1880   ""
1883 (define_insn "*andsi_iorsi3_notsi"
1884   [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1885         (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1886                         (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1887                 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1888   ""
1889   "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1890 [(set_attr "length" "8")])
1894 ;; Minimum and maximum insns
1896 (define_insn "smaxsi3"
1897   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1898         (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1899                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1900    (clobber (reg:CC 24))]
1901   ""
1902   "@
1903    cmp\\t%1, %2\;movlt\\t%0, %2
1904    cmp\\t%1, %2\;movge\\t%0, %1
1905    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1906 [(set_attr "conds" "clob")
1907  (set_attr "length" "8,8,12")])
1909 (define_insn "sminsi3"
1910   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1911         (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1912                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1913    (clobber (reg:CC 24))]
1914   ""
1915   "@
1916    cmp\\t%1, %2\;movge\\t%0, %2
1917    cmp\\t%1, %2\;movlt\\t%0, %1
1918    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1919 [(set_attr "conds" "clob")
1920  (set_attr "length" "8,8,12")])
1922 (define_insn "umaxsi3"
1923   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1924         (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1925                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1926    (clobber (reg:CC 24))]
1927   ""
1928   "@
1929    cmp\\t%1, %2\;movcc\\t%0, %2
1930    cmp\\t%1, %2\;movcs\\t%0, %1
1931    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1932 [(set_attr "conds" "clob")
1933  (set_attr "length" "8,8,12")])
1935 (define_insn "uminsi3"
1936   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1937         (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1938                  (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1939    (clobber (reg:CC 24))]
1940   ""
1941   "@
1942    cmp\\t%1, %2\;movcs\\t%0, %2
1943    cmp\\t%1, %2\;movcc\\t%0, %1
1944    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1945 [(set_attr "conds" "clob")
1946  (set_attr "length" "8,8,12")])
1948 (define_insn "*store_minmaxsi"
1949   [(set (match_operand:SI 0 "memory_operand" "=m")
1950         (match_operator:SI 3 "minmax_operator"
1951          [(match_operand:SI 1 "s_register_operand" "r")
1952           (match_operand:SI 2 "s_register_operand" "r")]))
1953    (clobber (reg:CC 24))]
1954   ""
1955   "*
1956   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1957                          operands[2]);
1958   output_asm_insn (\"cmp\\t%1, %2\", operands);
1959   output_asm_insn (\"str%d3\\t%1, %0\", operands);
1960   output_asm_insn (\"str%D3\\t%2, %0\", operands);
1961   return \"\";
1963 [(set_attr "conds" "clob")
1964  (set_attr "length" "12")
1965  (set_attr "type" "store1")])
1967 ; Reject the frame pointer in operand[1], since reloading this after
1968 ; it has been eliminated can cause carnage.
1969 (define_insn "*minmax_arithsi"
1970   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1971         (match_operator:SI 4 "shiftable_operator"
1972          [(match_operator:SI 5 "minmax_operator"
1973            [(match_operand:SI 2 "s_register_operand" "r,r")
1974             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1975           (match_operand:SI 1 "s_register_operand" "0,?r")]))
1976    (clobber (reg:CC 24))]
1977   "GET_CODE (operands[1]) != REG
1978    || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
1979        && REGNO(operands[1]) != ARG_POINTER_REGNUM)"
1980   "*
1982   enum rtx_code code = GET_CODE (operands[4]);
1984   operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1985                          operands[3]);
1986   output_asm_insn (\"cmp\\t%2, %3\", operands);
1987   output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1988   if (which_alternative != 0 || operands[3] != const0_rtx
1989       || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1990     output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1991   return \"\";
1994 [(set_attr "conds" "clob")
1995  (set_attr "length" "12")])
1998 ;; Shift and rotation insns
2000 (define_expand "ashlsi3"
2001   [(set (match_operand:SI 0 "s_register_operand" "")
2002         (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2003                    (match_operand:SI 2 "arm_rhs_operand" "")))]
2004   ""
2005   "
2006   if (GET_CODE (operands[2]) == CONST_INT
2007       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2008     {
2009       emit_insn (gen_movsi (operands[0], const0_rtx));
2010       DONE;
2011     }
2014 (define_expand "ashrsi3"
2015   [(set (match_operand:SI 0 "s_register_operand" "")
2016         (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2017                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2018   ""
2019   "
2020   if (GET_CODE (operands[2]) == CONST_INT
2021       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2022     operands[2] = GEN_INT (31);
2025 (define_expand "lshrsi3"
2026   [(set (match_operand:SI 0 "s_register_operand" "")
2027         (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2028                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2029   ""
2030   "
2031   if (GET_CODE (operands[2]) == CONST_INT
2032       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2033     {
2034       emit_insn (gen_movsi (operands[0], const0_rtx));
2035       DONE;
2036     }
2039 (define_expand "rotlsi3"
2040   [(set (match_operand:SI 0 "s_register_operand" "")
2041         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2042                      (match_operand:SI 2 "reg_or_int_operand" "")))]
2043   ""
2044   "
2045   if (GET_CODE (operands[2]) == CONST_INT)
2046     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2047   else
2048     {
2049       rtx reg = gen_reg_rtx (SImode);
2050       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2051       operands[2] = reg;
2052     }
2055 (define_expand "rotrsi3"
2056   [(set (match_operand:SI 0 "s_register_operand" "")
2057         (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2058                      (match_operand:SI 2 "arm_rhs_operand" "")))]
2059   ""
2060   "
2061   if (GET_CODE (operands[2]) == CONST_INT
2062       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2063     operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2066 (define_insn "*shiftsi3"
2067   [(set (match_operand:SI 0 "s_register_operand" "=r")
2068         (match_operator:SI 3 "shift_operator"
2069          [(match_operand:SI 1 "s_register_operand" "r")
2070           (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2071   ""
2072   "mov%?\\t%0, %1%S3"
2075 (define_insn "*shiftsi3_compare0"
2076   [(set (reg:CC_NOOV 24)
2077         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2078                           [(match_operand:SI 1 "s_register_operand" "r")
2079                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2080                          (const_int 0)))
2081    (set (match_operand:SI 0 "s_register_operand" "=r")
2082         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2083   ""
2084   "mov%?s\\t%0, %1%S3"
2085   [(set_attr "conds" "set")
2088 (define_insn "*shiftsi3_compare0_scratch"
2089   [(set (reg:CC_NOOV 24)
2090         (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2091                           [(match_operand:SI 1 "s_register_operand" "r")
2092                            (match_operand:SI 2 "arm_rhs_operand" "rM")])
2093                          (const_int 0)))
2094    (clobber (match_scratch:SI 0 "=r"))]
2095   ""
2096   "mov%?s\\t%0, %1%S3"
2097   [(set_attr "conds" "set")
2100 (define_insn "*notsi_shiftsi"
2101   [(set (match_operand:SI 0 "s_register_operand" "=r")
2102         (not:SI (match_operator:SI 3 "shift_operator"
2103                  [(match_operand:SI 1 "s_register_operand" "r")
2104                   (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2105   ""
2106   "mvn%?\\t%0, %1%S3"
2109 (define_insn "*notsi_shiftsi_compare0"
2110   [(set (reg:CC_NOOV 24)
2111         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2112                           [(match_operand:SI 1 "s_register_operand" "r")
2113                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2114                          (const_int 0)))
2115    (set (match_operand:SI 0 "s_register_operand" "=r")
2116         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2117   ""
2118   "mvn%?s\\t%0, %1%S3"
2119   [(set_attr "conds" "set")
2122 (define_insn "*not_shiftsi_compare0_scratch"
2123   [(set (reg:CC_NOOV 24)
2124         (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2125                           [(match_operand:SI 1 "s_register_operand" "r")
2126                            (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2127                          (const_int 0)))
2128    (clobber (match_scratch:SI 0 "=r"))]
2129   ""
2130   "mvn%?s\\t%0, %1%S3"
2131   [(set_attr "conds" "set")
2135 ;; Unary arithmetic insns
2137 (define_insn "negdi2"
2138   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2139         (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2140   ""
2141   "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2142 [(set_attr "conds" "clob")
2143  (set_attr "length" "8")])
2145 (define_insn "negsi2"
2146   [(set (match_operand:SI 0 "s_register_operand" "=r")
2147         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2148   ""
2149   "rsb%?\\t%0, %1, #0")
2151 (define_insn "negsf2"
2152   [(set (match_operand:SF 0 "s_register_operand" "=f")
2153         (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2154   "TARGET_HARD_FLOAT"
2155   "mnf%?s\\t%0, %1"
2156 [(set_attr "type" "ffarith")])
2158 (define_insn "negdf2"
2159   [(set (match_operand:DF 0 "s_register_operand" "=f")
2160         (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2161   "TARGET_HARD_FLOAT"
2162   "mnf%?d\\t%0, %1"
2163 [(set_attr "type" "ffarith")])
2165 (define_insn "*negdf_esfdf"
2166   [(set (match_operand:DF 0 "s_register_operand" "=f")
2167         (neg:DF (float_extend:DF
2168                  (match_operand:SF 1 "s_register_operand" "f"))))]
2169   "TARGET_HARD_FLOAT"
2170   "mnf%?d\\t%0, %1"
2171 [(set_attr "type" "ffarith")])
2173 (define_insn "negxf2"
2174   [(set (match_operand:XF 0 "s_register_operand" "=f")
2175         (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2176   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2177   "mnf%?e\\t%0, %1"
2178 [(set_attr "type" "ffarith")])
2180 ;; abssi2 doesn't really clobber the condition codes if a different register
2181 ;; is being set.  To keep things simple, assume during rtl manipulations that
2182 ;; it does, but tell the final scan operator the truth.  Similarly for
2183 ;; (neg (abs...))
2185 (define_insn "abssi2"
2186   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2187         (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2188    (clobber (reg:CC 24))]
2189   ""
2190   "@
2191    cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2192    eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2193 [(set_attr "conds" "clob,*")
2194  (set_attr "length" "8")])
2196 (define_insn "*neg_abssi2"
2197   [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2198         (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2199    (clobber (reg:CC 24))]
2200   ""
2201   "@
2202    cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2203    eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2204 [(set_attr "conds" "clob,*")
2205  (set_attr "length" "8")])
2207 (define_insn "abssf2"
2208   [(set (match_operand:SF 0 "s_register_operand" "=f")
2209          (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2210   "TARGET_HARD_FLOAT"
2211   "abs%?s\\t%0, %1"
2212 [(set_attr "type" "ffarith")])
2214 (define_insn "absdf2"
2215   [(set (match_operand:DF 0 "s_register_operand" "=f")
2216         (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2217   "TARGET_HARD_FLOAT"
2218   "abs%?d\\t%0, %1"
2219 [(set_attr "type" "ffarith")])
2221 (define_insn "*absdf_esfdf"
2222   [(set (match_operand:DF 0 "s_register_operand" "=f")
2223         (abs:DF (float_extend:DF
2224                  (match_operand:SF 1 "s_register_operand" "f"))))]
2225   "TARGET_HARD_FLOAT"
2226   "abs%?d\\t%0, %1"
2227 [(set_attr "type" "ffarith")])
2229 (define_insn "absxf2"
2230   [(set (match_operand:XF 0 "s_register_operand" "=f")
2231         (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2232   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2233   "abs%?e\\t%0, %1"
2234 [(set_attr "type" "ffarith")])
2236 (define_insn "sqrtsf2"
2237   [(set (match_operand:SF 0 "s_register_operand" "=f")
2238         (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2239   "TARGET_HARD_FLOAT"
2240   "sqt%?s\\t%0, %1"
2241 [(set_attr "type" "float_em")])
2243 (define_insn "sqrtdf2"
2244   [(set (match_operand:DF 0 "s_register_operand" "=f")
2245         (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2246   "TARGET_HARD_FLOAT"
2247   "sqt%?d\\t%0, %1"
2248 [(set_attr "type" "float_em")])
2250 (define_insn "*sqrtdf_esfdf"
2251   [(set (match_operand:DF 0 "s_register_operand" "=f")
2252         (sqrt:DF (float_extend:DF
2253                   (match_operand:SF 1 "s_register_operand" "f"))))]
2254   "TARGET_HARD_FLOAT"
2255   "sqt%?d\\t%0, %1"
2256 [(set_attr "type" "float_em")])
2258 (define_insn "sqrtxf2"
2259   [(set (match_operand:XF 0 "s_register_operand" "=f")
2260         (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2261   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2262   "sqt%?e\\t%0, %1"
2263 [(set_attr "type" "float_em")])
2265 ;; SIN COS TAN and family are always emulated, so it's probably better
2266 ;; to always call a library function.
2267 ;(define_insn "sinsf2"
2268 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2269 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
2270 ;  "TARGET_HARD_FLOAT"
2271 ;  "sin%?s\\t%0, %1"
2272 ;[(set_attr "type" "float_em")])
2274 ;(define_insn "sindf2"
2275 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2276 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
2277 ;  "TARGET_HARD_FLOAT"
2278 ;  "sin%?d\\t%0, %1"
2279 ;[(set_attr "type" "float_em")])
2281 ;(define_insn "*sindf_esfdf"
2282 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2283 ;       (unspec:DF [(float_extend:DF
2284 ;                    (match_operand:SF 1 "s_register_operand" "f"))] 0))]
2285 ;  "TARGET_HARD_FLOAT"
2286 ;  "sin%?d\\t%0, %1"
2287 ;[(set_attr "type" "float_em")])
2289 ;(define_insn "sinxf2"
2290 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2291 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
2292 ;  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2293 ;  "sin%?e\\t%0, %1"
2294 ;[(set_attr "type" "float_em")])
2296 ;(define_insn "cossf2"
2297 ;  [(set (match_operand:SF 0 "s_register_operand" "=f")
2298 ;       (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
2299 ;  "TARGET_HARD_FLOAT"
2300 ;  "cos%?s\\t%0, %1"
2301 ;[(set_attr "type" "float_em")])
2303 ;(define_insn "cosdf2"
2304 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2305 ;       (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
2306 ;  "TARGET_HARD_FLOAT"
2307 ;  "cos%?d\\t%0, %1"
2308 ;[(set_attr "type" "float_em")])
2310 ;(define_insn "*cosdf_esfdf"
2311 ;  [(set (match_operand:DF 0 "s_register_operand" "=f")
2312 ;       (unspec:DF [(float_extend:DF
2313 ;                    (match_operand:SF 1 "s_register_operand" "f"))] 1))]
2314 ;  "TARGET_HARD_FLOAT"
2315 ;  "cos%?d\\t%0, %1"
2316 ;[(set_attr "type" "float_em")])
2318 ;(define_insn "cosxf2"
2319 ;  [(set (match_operand:XF 0 "s_register_operand" "=f")
2320 ;       (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
2321 ;  "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2322 ;  "cos%?e\\t%0, %1"
2323 ;[(set_attr "type" "float_em")])
2325 (define_insn "one_cmpldi2"
2326   [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2327         (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2328   ""
2329   "#"
2330 [(set_attr "length" "8")])
2332 (define_insn "one_cmplsi2"
2333   [(set (match_operand:SI 0 "s_register_operand" "=r")
2334         (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2335   ""
2336   "mvn%?\\t%0, %1")
2338 (define_insn "*notsi_compare0"
2339   [(set (reg:CC_NOOV 24)
2340         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2341                          (const_int 0)))
2342    (set (match_operand:SI 0 "s_register_operand" "=r")
2343         (not:SI (match_dup 1)))]
2344   ""
2345   "mvn%?s\\t%0, %1"
2346 [(set_attr "conds" "set")])
2348 (define_insn "*notsi_compare0_scratch"
2349   [(set (reg:CC_NOOV 24)
2350         (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2351                          (const_int 0)))
2352    (clobber (match_scratch:SI 0 "=r"))]
2353   ""
2354   "mvn%?s\\t%0, %1"
2355 [(set_attr "conds" "set")])
2357 ;; Fixed <--> Floating conversion insns
2359 (define_insn "floatsisf2"
2360   [(set (match_operand:SF 0 "s_register_operand" "=f")
2361         (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2362   "TARGET_HARD_FLOAT"
2363   "flt%?s\\t%0, %1"
2364 [(set_attr "type" "r_2_f")])
2366 (define_insn "floatsidf2"
2367   [(set (match_operand:DF 0 "s_register_operand" "=f")
2368         (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2369   "TARGET_HARD_FLOAT"
2370   "flt%?d\\t%0, %1"
2371 [(set_attr "type" "r_2_f")])
2373 (define_insn "floatsixf2"
2374   [(set (match_operand:XF 0 "s_register_operand" "=f")
2375         (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
2376   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2377   "flt%?e\\t%0, %1"
2378 [(set_attr "type" "r_2_f")])
2380 (define_insn "fix_truncsfsi2"
2381   [(set (match_operand:SI 0 "s_register_operand" "=r")
2382         (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2383   "TARGET_HARD_FLOAT"
2384   "fix%?z\\t%0, %1"
2385 [(set_attr "type" "f_2_r")])
2387 (define_insn "fix_truncdfsi2"
2388   [(set (match_operand:SI 0 "s_register_operand" "=r")
2389         (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2390   "TARGET_HARD_FLOAT"
2391   "fix%?z\\t%0, %1"
2392 [(set_attr "type" "f_2_r")])
2394 (define_insn "fix_truncxfsi2"
2395   [(set (match_operand:SI 0 "s_register_operand" "=r")
2396         (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
2397   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2398   "fix%?z\\t%0, %1"
2399 [(set_attr "type" "f_2_r")])
2401 ;; Truncation insns
2403 (define_insn "truncdfsf2"
2404   [(set (match_operand:SF 0 "s_register_operand" "=f")
2405         (float_truncate:SF
2406          (match_operand:DF 1 "s_register_operand" "f")))]
2407   "TARGET_HARD_FLOAT"
2408   "mvf%?s\\t%0, %1"
2409 [(set_attr "type" "ffarith")])
2411 (define_insn "truncxfsf2"
2412   [(set (match_operand:SF 0 "s_register_operand" "=f")
2413         (float_truncate:SF
2414          (match_operand:XF 1 "s_register_operand" "f")))]
2415   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2416   "mvf%?s\\t%0, %1"
2417 [(set_attr "type" "ffarith")])
2419 (define_insn "truncxfdf2"
2420   [(set (match_operand:DF 0 "s_register_operand" "=f")
2421         (float_truncate:DF
2422          (match_operand:XF 1 "s_register_operand" "f")))]
2423   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2424   "mvf%?d\\t%0, %1"
2425 [(set_attr "type" "ffarith")])
2427 ;; Zero and sign extension instructions.
2429 (define_insn "zero_extendsidi2"
2430   [(set (match_operand:DI 0 "s_register_operand" "=r")
2431         (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2432   ""
2433   "*
2434   if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2435     output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2436   return \"mov%?\\t%R0, #0\";
2438 [(set_attr "length" "8")])
2440 (define_insn "zero_extendqidi2"
2441   [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2442         (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2443   ""
2444   "@
2445    and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2446    ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2447 [(set_attr "length" "8")
2448  (set_attr "type" "*,load")
2449  (set_attr "pool_range" "*,4096")])
2451 (define_insn "extendsidi2"
2452   [(set (match_operand:DI 0 "s_register_operand" "=r")
2453         (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2454   ""
2455   "*
2456   if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2457     output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2458   return \"mov%?\\t%R0, %Q0, asr #31\";
2460 [(set_attr "length" "8")])
2462 (define_expand "zero_extendhisi2"
2463   [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2464                                  (const_int 16)))
2465    (set (match_operand:SI 0 "s_register_operand" "")
2466         (lshiftrt:SI (match_dup 2) (const_int 16)))]
2467   ""
2468   "
2470   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2471     {
2472      /* Note: We do not have to worry about TARGET_MMU_TRAPS
2473         here because the insn below will generate an LDRH instruction
2474         rather than an LDR instruction, so we cannot get an unaligned
2475         word access.  */
2476       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2477                               gen_rtx_ZERO_EXTEND (SImode, operands[1])));
2478       DONE;
2479     }
2480   if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2481     {
2482       emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2483       DONE;
2484     }
2485   if (! s_register_operand (operands[1], HImode))
2486     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2487   operands[1] = gen_lowpart (SImode, operands[1]);
2488   operands[2] = gen_reg_rtx (SImode); 
2491 (define_insn "*zero_extendhisi_insn"
2492   [(set (match_operand:SI 0 "s_register_operand" "=r")
2493         (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2494   "arm_arch4"
2495   "ldr%?h\\t%0, %1"
2496 [(set_attr "type" "load")
2497  (set_attr "pool_range" "256")])
2499 (define_split
2500   [(set (match_operand:SI 0 "s_register_operand" "")
2501         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2502    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2503   "! arm_arch4"
2504   [(set (match_dup 2) (match_dup 1))
2505    (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2506   "
2508   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2509     FAIL;
2512 (define_split
2513   [(set (match_operand:SI 0 "s_register_operand" "")
2514         (match_operator:SI 3 "shiftable_operator"
2515          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2516           (match_operand:SI 4 "s_register_operand" "")]))
2517    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2518   "! arm_arch4"
2519   [(set (match_dup 2) (match_dup 1))
2520    (set (match_dup 0)
2521         (match_op_dup 3
2522          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2523   "
2525   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2526     FAIL;
2529 (define_expand "zero_extendqisi2"
2530   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2531         (zero_extend:SI
2532          (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2533   ""
2534   "
2535   if (GET_CODE (operands[1]) != MEM)
2536     {
2537       emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
2538                              GEN_INT (255)));
2539       DONE;
2540     }
2543 (define_insn "*load_extendqisi"
2544   [(set (match_operand:SI 0 "s_register_operand" "=r")
2545         (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2546   ""
2547   "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
2548 [(set_attr "type" "load")
2549  (set_attr "pool_range" "4096")])
2551 (define_split
2552   [(set (match_operand:SI 0 "s_register_operand" "")
2553         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
2554    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2555   "GET_CODE (operands[1]) != MEM"
2556   [(set (match_dup 2) (match_dup 1))
2557    (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
2558   "")
2560 (define_insn "*compareqi_eq0"
2561   [(set (reg:CC_Z 24)
2562         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
2563                          (const_int 0)))]
2564   ""
2565   "tst\\t%0, #255"
2566 [(set_attr "conds" "set")])
2568 (define_expand "extendhisi2"
2569   [(set (match_dup 2)
2570         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2571                    (const_int 16)))
2572    (set (match_operand:SI 0 "s_register_operand" "")
2573         (ashiftrt:SI (match_dup 2)
2574                      (const_int 16)))]
2575   ""
2576   "
2578   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2579     {
2580      /* Note: We do not have to worry about TARGET_MMU_TRAPS
2581         here because the insn below will generate an LDRH instruction
2582         rather than an LDR instruction, so we cannot get an unaligned
2583         word access.  */
2584       emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2585                  gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2586       DONE;
2587     }
2589   if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2590     {
2591       emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
2592       DONE;
2593     }
2594   if (! s_register_operand (operands[1], HImode))
2595     operands[1] = copy_to_mode_reg (HImode, operands[1]);
2596   operands[1] = gen_lowpart (SImode, operands[1]);
2597   operands[2] = gen_reg_rtx (SImode);
2600 (define_expand "extendhisi2_mem"
2601   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
2602    (set (match_dup 3)
2603         (zero_extend:SI (match_dup 7)))
2604    (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
2605    (set (match_operand:SI 0 "" "")
2606         (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
2607   ""
2608   "
2610   rtx mem1, mem2;
2611   rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2613   mem1 = gen_rtx_MEM (QImode, addr);
2614   MEM_COPY_ATTRIBUTES (mem1, operands[1]);
2615   RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
2616   mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
2617   MEM_COPY_ATTRIBUTES (mem2, operands[1]);
2618   RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
2619   operands[0] = gen_lowpart (SImode, operands[0]);
2620   operands[1] = mem1;
2621   operands[2] = gen_reg_rtx (SImode);
2622   operands[3] = gen_reg_rtx (SImode);
2623   operands[6] = gen_reg_rtx (SImode);
2624   operands[7] = mem2;
2626   if (BYTES_BIG_ENDIAN)
2627     {
2628       operands[4] = operands[2];
2629       operands[5] = operands[3];
2630     }
2631   else
2632     {
2633       operands[4] = operands[3];
2634       operands[5] = operands[2];
2635     }
2639 (define_insn "*extendhisi_insn"
2640   [(set (match_operand:SI 0 "s_register_operand" "=r")
2641         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2642   "arm_arch4"
2643   "ldr%?sh\\t%0, %1"
2644 [(set_attr "type" "load")
2645  (set_attr "pool_range" "256")])
2647 (define_split
2648   [(set (match_operand:SI 0 "s_register_operand" "")
2649         (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2650    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2651   "! arm_arch4"
2652   [(set (match_dup 2) (match_dup 1))
2653    (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
2654   "
2656   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2657     FAIL;
2660 (define_split
2661   [(set (match_operand:SI 0 "s_register_operand" "")
2662         (match_operator:SI 3 "shiftable_operator"
2663          [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2664           (match_operand:SI 4 "s_register_operand" "")]))
2665    (clobber (match_operand:SI 2 "s_register_operand" ""))]
2666   "! arm_arch4"
2667   [(set (match_dup 2) (match_dup 1))
2668    (set (match_dup 0)
2669         (match_op_dup 3
2670          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2671   "
2673   if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2674     FAIL;
2677 (define_expand "extendqihi2"
2678   [(set (match_dup 2)
2679         (ashift:SI (match_operand:QI 1 "general_operand" "")
2680                    (const_int 24)))
2681    (set (match_operand:HI 0 "s_register_operand" "")
2682         (ashiftrt:SI (match_dup 2)
2683                      (const_int 24)))]
2684   ""
2685   "
2687   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2688     {
2689       emit_insn (gen_rtx_SET (VOIDmode,
2690                               operands[0],
2691                               gen_rtx_SIGN_EXTEND (HImode, operands[1])));
2692       DONE;
2693     }
2694   if (! s_register_operand (operands[1], QImode))
2695     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2696   operands[0] = gen_lowpart (SImode, operands[0]);
2697   operands[1] = gen_lowpart (SImode, operands[1]);
2698   operands[2] = gen_reg_rtx (SImode);
2701 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2702 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2703 (define_insn "*extendqihi_insn"
2704   [(set (match_operand:HI 0 "s_register_operand" "=r")
2705         (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
2706   "arm_arch4"
2707   "*
2708   /* If the address is invalid, this will split the instruction into two. */
2709   if (bad_signed_byte_operand (operands[1], QImode))
2710     return \"#\";
2711   return \"ldr%?sb\\t%0, %1\";
2713 [(set_attr "type" "load")
2714  (set_attr "length" "8")
2715  (set_attr "pool_range" "256")])
2717 (define_split
2718   [(set (match_operand:HI 0 "s_register_operand" "")
2719         (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2720   "arm_arch4 && reload_completed"
2721   [(set (match_dup 3) (match_dup 1))
2722    (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
2723   "
2724   {
2725     HOST_WIDE_INT offset;
2727     operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
2728     operands[2] = gen_rtx_MEM (QImode, operands[3]);
2729     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2730     RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2731     operands[1] = XEXP (operands[1], 0);
2732     if (GET_CODE (operands[1]) == PLUS
2733         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2734         && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2735               || const_ok_for_arm (-offset)))
2736       {
2737         HOST_WIDE_INT low = (offset > 0
2738                              ? (offset & 0xff) : -((-offset) & 0xff));
2739         XEXP (operands[2], 0) = plus_constant (operands[3], low);
2740         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2741       }
2742     /* Ensure the sum is in correct canonical form */
2743     else if (GET_CODE (operands[1]) == PLUS
2744              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2745              && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2746       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2747                                            XEXP (operands[1], 1),
2748                                            XEXP (operands[1], 0));
2749   }
2752 (define_expand "extendqisi2"
2753   [(set (match_dup 2)
2754         (ashift:SI (match_operand:QI 1 "general_operand" "")
2755                    (const_int 24)))
2756    (set (match_operand:SI 0 "s_register_operand" "")
2757         (ashiftrt:SI (match_dup 2)
2758                      (const_int 24)))]
2759   ""
2760   "
2762   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2763     {
2764       emit_insn (gen_rtx_SET (VOIDmode,
2765                               operands[0],
2766                               gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2767       DONE;
2768     }
2769   if (! s_register_operand (operands[1], QImode))
2770     operands[1] = copy_to_mode_reg (QImode, operands[1]);
2771   operands[1] = gen_lowpart (SImode, operands[1]);
2772   operands[2] = gen_reg_rtx (SImode);
2775 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2776 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2777 (define_insn "*extendqisi_insn"
2778   [(set (match_operand:SI 0 "s_register_operand" "=r")
2779         (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2780   "arm_arch4"
2781   "*
2782   /* If the address is invalid, this will split the instruction into two. */
2783   if (bad_signed_byte_operand (operands[1], QImode))
2784     return \"#\";
2785   return \"ldr%?sb\\t%0, %1\";
2787 [(set_attr "type" "load")
2788  (set_attr "length" "8")
2789  (set_attr "pool_range" "256")])
2791 (define_split
2792   [(set (match_operand:SI 0 "s_register_operand" "")
2793         (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2794   "arm_arch4 && reload_completed"
2795   [(set (match_dup 0) (match_dup 1))
2796    (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2797   "
2798   {
2799     HOST_WIDE_INT offset;
2801     operands[2] = gen_rtx_MEM (QImode, operands[0]);
2802     MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2803     RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2804     operands[1] = XEXP (operands[1], 0);
2805     if (GET_CODE (operands[1]) == PLUS
2806         && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2807         && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2808               || const_ok_for_arm (-offset)))
2809       {
2810         HOST_WIDE_INT low = (offset > 0
2811                              ? (offset & 0xff) : -((-offset) & 0xff));
2812         XEXP (operands[2], 0) = plus_constant (operands[0], low);
2813         operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2814       }
2815     /* Ensure the sum is in correct canonical form */
2816     else if (GET_CODE (operands[1]) == PLUS
2817              && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2818              && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2819       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2820                                            XEXP (operands[1], 1),
2821                                            XEXP (operands[1], 0));
2822   }
2825 (define_insn "extendsfdf2"
2826   [(set (match_operand:DF 0 "s_register_operand" "=f")
2827         (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2828   "TARGET_HARD_FLOAT"
2829   "mvf%?d\\t%0, %1"
2830 [(set_attr "type" "ffarith")])
2832 (define_insn "extendsfxf2"
2833   [(set (match_operand:XF 0 "s_register_operand" "=f")
2834         (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2835   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2836   "mvf%?e\\t%0, %1"
2837 [(set_attr "type" "ffarith")])
2839 (define_insn "extenddfxf2"
2840   [(set (match_operand:XF 0 "s_register_operand" "=f")
2841         (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2842   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2843   "mvf%?e\\t%0, %1"
2844 [(set_attr "type" "ffarith")])
2847 ;; Move insns (including loads and stores)
2849 ;; XXX Just some ideas about movti.
2850 ;; I don't think these are a good idea on the arm, there just aren't enough
2851 ;; registers
2852 ;;(define_expand "loadti"
2853 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
2854 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
2855 ;;  "" "")
2857 ;;(define_expand "storeti"
2858 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2859 ;;      (match_operand:TI 1 "s_register_operand" ""))]
2860 ;;  "" "")
2862 ;;(define_expand "movti"
2863 ;;  [(set (match_operand:TI 0 "general_operand" "")
2864 ;;      (match_operand:TI 1 "general_operand" ""))]
2865 ;;  ""
2866 ;;  "
2868 ;;  rtx insn;
2870 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2871 ;;    operands[1] = copy_to_reg (operands[1]);
2872 ;;  if (GET_CODE (operands[0]) == MEM)
2873 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2874 ;;  else if (GET_CODE (operands[1]) == MEM)
2875 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2876 ;;  else
2877 ;;    FAIL;
2879 ;;  emit_insn (insn);
2880 ;;  DONE;
2881 ;;}")
2883 ;; Recognise garbage generated above.
2885 ;;(define_insn ""
2886 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2887 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2888 ;;  ""
2889 ;;  "*
2890 ;;  {
2891 ;;    register mem = (which_alternative < 3);
2892 ;;    register char *template;
2894 ;;    operands[mem] = XEXP (operands[mem], 0);
2895 ;;    switch (which_alternative)
2896 ;;      {
2897 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2898 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
2899 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
2900 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
2901 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
2902 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
2903 ;;      }
2904 ;;    output_asm_insn (template, operands);
2905 ;;    return \"\";
2906 ;;  }")
2909 (define_insn "movdi"
2910   [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2911         (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2912   ""
2913   "*
2914   return (output_move_double (operands));
2916 [(set_attr "length" "8,8,8")
2917  (set_attr "type" "*,load,store2")
2918  (set_attr "pool_range" "0,1020,0")])
2920 (define_expand "movsi"
2921   [(set (match_operand:SI 0 "general_operand" "")
2922         (match_operand:SI 1 "general_operand" ""))]
2923   ""
2924   "
2925   /* Everything except mem = const or mem = mem can be done easily */
2926   if (GET_CODE (operands[0]) == MEM)
2927     operands[1] = force_reg (SImode, operands[1]);
2928   if (GET_CODE (operands[1]) == CONST_INT
2929       && !(const_ok_for_arm (INTVAL (operands[1]))
2930            || const_ok_for_arm (~INTVAL (operands[1]))))
2931     {
2932       arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2933                           NULL_RTX,
2934                           (reload_in_progress || reload_completed ? 0
2935                            : preserve_subexpressions_p ()));
2936       DONE;
2937     }
2938     
2939   if (flag_pic
2940       && (CONSTANT_P (operands[1])
2941          || symbol_mentioned_p (operands[1])
2942          || label_mentioned_p (operands[1])))
2943     operands[1] = legitimize_pic_address (operands[1], SImode,
2944                                           ((reload_in_progress
2945                                             || reload_completed)
2946                                            ? operands[0] : 0));
2949 (define_insn "*movsi_insn"
2950   [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2951         (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
2952   "register_operand (operands[0], SImode)
2953    || register_operand (operands[1], SImode)"
2954   "@
2955    mov%?\\t%0, %1
2956    mvn%?\\t%0, #%B1
2957    ldr%?\\t%0, %1
2958    str%?\\t%1, %0"
2959 [(set_attr "type" "*,*,load,store1")
2960  (set_attr "pool_range" "*,*,4096,*")])
2962 (define_split
2963   [(set (match_operand:SI 0 "s_register_operand" "")
2964         (match_operand:SI 1 "const_int_operand" ""))]
2965   "! (const_ok_for_arm (INTVAL (operands[1]))
2966       || const_ok_for_arm (~INTVAL (operands[1])))"
2967   [(clobber (const_int 0))]
2968   "
2969   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2970                       NULL_RTX, 0);
2971   DONE;
2974 (define_expand "movaddr"
2975   [(set (match_operand:SI 0 "s_register_operand" "")
2976         (match_operand:DI 1 "address_operand" ""))]
2977   ""
2978   "")
2980 (define_insn "*movaddr_insn"
2981   [(set (match_operand:SI 0 "s_register_operand" "=r")
2982         (match_operand:DI 1 "address_operand" "p"))]
2983   "reload_completed
2984    && (GET_CODE (operands[1]) == LABEL_REF
2985        || (GET_CODE (operands[1]) == CONST
2986            && GET_CODE (XEXP (operands[1], 0)) == PLUS
2987            && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2988            && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2989   "adr%?\\t%0, %a1")
2991 ;; When generating pic, we need to load the symbol offset into a register.
2992 ;; So that the optimizer does not confuse this with a normal symbol load
2993 ;; we use an unspec.  The offset will be loaded from a constant pool entry,
2994 ;; since that is the only type of relocation we can use.
2996 ;; The rather odd constraints on the following are to force reload to leave
2997 ;; the insn alone, and to force the minipool generation pass to then move
2998 ;; the GOT symbol to memory.
3000 (define_insn "pic_load_addr"
3001   [(set (match_operand:SI 0 "s_register_operand" "=r")
3002         (unspec:SI [(match_operand:SI 1 "" "mX")] 3))]
3003   "flag_pic"
3004   "ldr%?\\t%0, %1"
3005  [(set_attr "type" "load")
3006   (set_attr "pool_range" "4096")])
3008 ;; This variant is used for AOF assembly, since it needs to mention the
3009 ;; pic register in the rtl.
3010 (define_expand "pic_load_addr_based"
3011   [(set (match_operand:SI 0 "s_register_operand" "=r")
3012         (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
3013   "flag_pic"
3014   "operands[2] = pic_offset_table_rtx;")
3016 (define_insn "*pic_load_addr_based_insn"
3017   [(set (match_operand:SI 0 "s_register_operand" "=r")
3018         (unspec:SI [(match_operand 1 "" "")
3019                     (match_operand 2 "s_register_operand" "r")] 3))]
3020   "flag_pic && operands[2] == pic_offset_table_rtx"
3021   "*
3022 #ifdef AOF_ASSEMBLER
3023   operands[1] = aof_pic_entry (operands[1]);
3024 #endif
3025   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3026   return \"\";
3028 [(set_attr "type" "load")
3029  (set_attr "pool_range" "4096")])
3031 (define_insn "pic_add_dot_plus_eight"
3032   [(set (match_operand:SI 0 "register_operand" "+r")
3033         (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
3034    (use (label_ref (match_operand 1 "" "")))]
3035   "flag_pic"
3036   "*
3037   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
3038                              CODE_LABEL_NUMBER (operands[1]));
3039   return \"add%?\\t%0, %|pc, %0\";
3042 ;; If copying one reg to another we can set the condition codes according to
3043 ;; its value.  Such a move is common after a return from subroutine and the
3044 ;; result is being tested against zero.
3046 (define_insn "*movsi_compare0"
3047   [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
3048                                 (const_int 0)))
3049    (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
3050   ""
3051   "@
3052    cmp%?\\t%0, #0
3053    sub%?s\\t%0, %1, #0"
3054 [(set_attr "conds" "set")])
3056 ;; Subroutine to store a half word from a register into memory.
3057 ;; Operand 0 is the source register (HImode)
3058 ;; Operand 1 is the destination address in a register (SImode)
3060 ;; In both this routine and the next, we must be careful not to spill
3061 ;; a memory address of reg+large_const into a separate PLUS insn, since this
3062 ;; can generate unrecognizable rtl.
3064 (define_expand "storehi"
3065   [;; store the low byte
3066    (set (match_operand 1 "" "") (match_dup 3))
3067    ;; extract the high byte
3068    (set (match_dup 2)
3069         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3070    ;; store the high byte
3071    (set (match_dup 4) (subreg:QI (match_dup 2) 0))]     ;explicit subreg safe
3072   ""
3073   "
3075   rtx addr = XEXP (operands[1], 0);
3076   enum rtx_code code = GET_CODE (addr);
3078   if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3079       || code == MINUS)
3080     addr = force_reg (SImode, addr);
3082   operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
3083   operands[1] = change_address (operands[1], QImode, NULL_RTX);
3084   operands[3] = gen_lowpart (QImode, operands[0]);
3085   operands[0] = gen_lowpart (SImode, operands[0]);
3086   operands[2] = gen_reg_rtx (SImode); 
3090 (define_expand "storehi_bigend"
3091   [(set (match_dup 4) (match_dup 3))
3092    (set (match_dup 2)
3093         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3094    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
3095   ""
3096   "
3098   rtx addr = XEXP (operands[1], 0);
3099   enum rtx_code code = GET_CODE (addr);
3101   if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3102       || code == MINUS)
3103     addr = force_reg (SImode, addr);
3105   operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
3106   operands[1] = change_address (operands[1], QImode, NULL_RTX);
3107   operands[3] = gen_lowpart (QImode, operands[0]);
3108   operands[0] = gen_lowpart (SImode, operands[0]);
3109   operands[2] = gen_reg_rtx (SImode);
3113 ;; Subroutine to store a half word integer constant into memory.
3114 (define_expand "storeinthi"
3115   [(set (match_operand 0 "" "")
3116         (subreg:QI (match_operand 1 "" "") 0))
3117    (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
3118   ""
3119   "
3121   HOST_WIDE_INT value = INTVAL (operands[1]);
3122   rtx addr = XEXP (operands[0], 0);
3123   enum rtx_code code = GET_CODE (addr);
3125   if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3126       || code == MINUS)
3127     addr = force_reg (SImode, addr);
3129   operands[1] = gen_reg_rtx (SImode);
3130   if (BYTES_BIG_ENDIAN)
3131     {
3132       emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
3133       if ((value & 255) == ((value >> 8) & 255))
3134         operands[2] = operands[1];
3135       else
3136         {
3137           operands[2] = gen_reg_rtx (SImode);
3138           emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
3139         }
3140     }
3141   else
3142     {
3143       emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
3144       if ((value & 255) == ((value >> 8) & 255))
3145         operands[2] = operands[1];
3146       else
3147         {
3148           operands[2] = gen_reg_rtx (SImode);
3149           emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
3150         }
3151     }
3153   operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
3154   operands[0] = change_address (operands[0], QImode, NULL_RTX);
3158 (define_expand "storehi_single_op"
3159   [(set (match_operand:HI 0 "memory_operand" "")
3160         (match_operand:HI 1 "general_operand" ""))]
3161   "arm_arch4"
3162   "
3163   if (! s_register_operand (operands[1], HImode))
3164     operands[1] = copy_to_mode_reg (HImode, operands[1]);
3167 (define_expand "movhi"
3168   [(set (match_operand:HI 0 "general_operand" "")
3169         (match_operand:HI 1 "general_operand" ""))]
3170   ""
3171   "
3173   if (! (reload_in_progress || reload_completed))
3174     {
3175       if (GET_CODE (operands[0]) == MEM)
3176         {
3177           if (arm_arch4)
3178             {
3179               emit_insn (gen_storehi_single_op (operands[0], operands[1]));
3180               DONE;
3181             }
3182           if (GET_CODE (operands[1]) == CONST_INT)
3183             emit_insn (gen_storeinthi (operands[0], operands[1]));
3184           else
3185             {
3186               if (GET_CODE (operands[1]) == MEM)
3187                 operands[1] = force_reg (HImode, operands[1]);
3188               if (BYTES_BIG_ENDIAN)
3189                 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
3190               else
3191                 emit_insn (gen_storehi (operands[1], operands[0]));
3192             }
3193           DONE;
3194         }
3195       /* Sign extend a constant, and keep it in an SImode reg.  */
3196       else if (GET_CODE (operands[1]) == CONST_INT)
3197         {
3198           rtx reg = gen_reg_rtx (SImode);
3199           HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
3201           /* If the constant is already valid, leave it alone.  */
3202           if (! const_ok_for_arm (val))
3203             {
3204               /* If setting all the top bits will make the constant 
3205                  loadable in a single instruction, then set them.  
3206                  Otherwise, sign extend the number.  */
3208               if (const_ok_for_arm (~ (val | ~0xffff)))
3209                 val |= ~0xffff;
3210               else if (val & 0x8000)
3211                 val |= ~0xffff;
3212             }
3214           emit_insn (gen_movsi (reg, GEN_INT (val)));
3215           operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
3216         }
3217       else if (! arm_arch4)
3218         {
3219          /* Note: We do not have to worry about TARGET_MMU_TRAPS
3220             for v4 and up architectures because LDRH instructions will
3221             be used to access the HI values, and these cannot generate
3222             unaligned word access faults in the MMU.  */
3223           if (GET_CODE (operands[1]) == MEM)
3224             {
3225               if (TARGET_MMU_TRAPS)
3226                 {
3227                   rtx base;
3228                   rtx offset = const0_rtx;
3229                   rtx reg = gen_reg_rtx (SImode);
3231                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
3232                        || (GET_CODE (base) == PLUS
3233                            && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
3234                            && ((INTVAL(offset) & 1) != 1)
3235                            && GET_CODE (base = XEXP (base, 0)) == REG))
3236                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
3237                     {
3238                       HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
3239                       rtx new;
3241                       new = gen_rtx_MEM (SImode,
3242                                          plus_constant (base, new_offset));
3243                       MEM_COPY_ATTRIBUTES (new, operands[1]);
3244                       RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
3245                       emit_insn (gen_movsi (reg, new));
3246                       if (((INTVAL (offset) & 2) != 0)
3247                           ^ (BYTES_BIG_ENDIAN ? 1 : 0))
3248                         {
3249                           rtx reg2 = gen_reg_rtx (SImode);
3251                           emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
3252                           reg = reg2;
3253                         }
3254                     }
3255                   else
3256                     emit_insn (gen_movhi_bytes (reg, operands[1]));
3258                   operands[1] = gen_lowpart (HImode, reg);
3259                 }
3260               else if (BYTES_BIG_ENDIAN)
3261                 {
3262                   rtx base;
3263                   rtx offset = const0_rtx;
3265                   if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
3266                        || (GET_CODE (base) == PLUS
3267                            && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
3268                            && GET_CODE (base = XEXP (base, 0)) == REG))
3269                       && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
3270                     {
3271                       rtx reg = gen_reg_rtx (SImode);
3272                       rtx new;
3274                       if ((INTVAL (offset) & 2) == 2)
3275                         {
3276                           HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
3277                           new = gen_rtx_MEM (SImode,
3278                                              plus_constant (base, new_offset));
3279                           MEM_COPY_ATTRIBUTES (new, operands[1]);
3280                           RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
3281                           emit_insn (gen_movsi (reg, new));
3282                         }
3283                       else
3284                         {
3285                           new = gen_rtx_MEM (SImode, XEXP (operands[1], 0));
3286                           MEM_COPY_ATTRIBUTES (new, operands[1]);
3287                           RTX_UNCHANGING_P (new)
3288                             = RTX_UNCHANGING_P (operands[1]);
3289                           emit_insn (gen_rotated_loadsi (reg, new));
3290                         }
3292                       operands[1] = gen_lowpart (HImode, reg);
3293                     }
3294                   else
3295                     {
3296                       emit_insn (gen_movhi_bigend (operands[0], operands[1]));
3297                       DONE;
3298                     }
3299                 }
3300             }
3301         }
3302     }
3303   /* Handle loading a large integer during reload */
3304   else if (GET_CODE (operands[1]) == CONST_INT
3305            && ! const_ok_for_arm (INTVAL (operands[1]))
3306            && ! const_ok_for_arm (~INTVAL (operands[1])))
3307     {
3308       /* Writing a constant to memory needs a scratch, which should
3309          be handled with SECONDARY_RELOADs.  */
3310       if (GET_CODE (operands[0]) != REG)
3311         abort ();
3313       operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
3314       emit_insn (gen_movsi (operands[0], operands[1]));
3315       DONE;
3316     }
3320 (define_insn "rotated_loadsi"
3321   [(set (match_operand:SI 0 "s_register_operand" "=r")
3322         (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
3323                    (const_int 16)))]
3324   "! TARGET_MMU_TRAPS"
3325   "*
3327   rtx ops[2];
3329   ops[0] = operands[0];
3330   ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
3331   output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
3332   return \"\";
3334 [(set_attr "type" "load")])
3336 (define_expand "movhi_bytes"
3337   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3338    (set (match_dup 3)
3339         (zero_extend:SI (match_dup 6)))
3340    (set (match_operand:SI 0 "" "")
3341          (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
3342   ""
3343   "
3345   rtx mem1, mem2;
3346   rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3348   mem1 = gen_rtx_MEM (QImode, addr);
3349   MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3350   RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
3351   mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3352   MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3353   RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
3354   operands[0] = gen_lowpart (SImode, operands[0]);
3355   operands[1] = mem1;
3356   operands[2] = gen_reg_rtx (SImode);
3357   operands[3] = gen_reg_rtx (SImode);
3358   operands[6] = mem2;
3360   if (BYTES_BIG_ENDIAN)
3361     {
3362       operands[4] = operands[2];
3363       operands[5] = operands[3];
3364     }
3365   else
3366     {
3367       operands[4] = operands[3];
3368       operands[5] = operands[2];
3369     }
3373 (define_expand "movhi_bigend"
3374   [(set (match_dup 2)
3375         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
3376                    (const_int 16)))
3377    (set (match_dup 3)
3378         (ashiftrt:SI (match_dup 2) (const_int 16)))
3379    (set (match_operand:HI 0 "s_register_operand" "")
3380         (subreg:HI (match_dup 3) 0))]
3381   ""
3382   "
3383   operands[2] = gen_reg_rtx (SImode);
3384   operands[3] = gen_reg_rtx (SImode);
3387 ;; Pattern to recognise insn generated default case above
3388 (define_insn "*movhi_insn_arch4"
3389   [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
3390         (match_operand:HI 1 "general_operand"  "rI,K,m,r"))]
3391   "arm_arch4
3392    && (GET_CODE (operands[1]) != CONST_INT
3393        || const_ok_for_arm (INTVAL (operands[1]))
3394        || const_ok_for_arm (~INTVAL (operands[1])))"
3395   "@
3396    mov%?\\t%0, %1\\t%@ movhi
3397    mvn%?\\t%0, #%B1\\t%@ movhi
3398    ldr%?h\\t%0, %1\\t%@ movhi
3399    str%?h\\t%1, %0\\t%@ movhi"
3400 [(set_attr "type" "*,*,load,store1")
3401  (set_attr "pool_range" "*,*,256,*")])
3403 (define_insn "*movhi_insn_littleend"
3404   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3405         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
3406   "! arm_arch4
3407    && ! BYTES_BIG_ENDIAN
3408    && ! TARGET_MMU_TRAPS
3409    && (GET_CODE (operands[1]) != CONST_INT
3410        || const_ok_for_arm (INTVAL (operands[1]))
3411        || const_ok_for_arm (~INTVAL (operands[1])))"
3412   "@
3413    mov%?\\t%0, %1\\t%@ movhi
3414    mvn%?\\t%0, #%B1\\t%@ movhi
3415    ldr%?\\t%0, %1\\t%@ movhi"
3416 [(set_attr "type" "*,*,load")
3417  (set_attr "pool_range" "4096")])
3419 (define_insn "*movhi_insn_bigend"
3420   [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3421         (match_operand:HI 1 "general_operand"  "rI,K,m"))]
3422   "! arm_arch4
3423    && BYTES_BIG_ENDIAN
3424    && ! TARGET_MMU_TRAPS
3425    && (GET_CODE (operands[1]) != CONST_INT
3426        || const_ok_for_arm (INTVAL (operands[1]))
3427        || const_ok_for_arm (~INTVAL (operands[1])))"
3428   "@
3429    mov%?\\t%0, %1\\t%@ movhi
3430    mvn%?\\t%0, #%B1\\t%@ movhi
3431    ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
3432 [(set_attr "type" "*,*,load")
3433  (set_attr "length" "4,4,8")
3434  (set_attr "pool_range" "*,*,4092")])
3436 (define_insn "*loadhi_si_bigend"
3437   [(set (match_operand:SI 0 "s_register_operand" "=r")
3438         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
3439                    (const_int 16)))]
3440   "BYTES_BIG_ENDIAN
3441    && ! TARGET_MMU_TRAPS"
3442   "ldr%?\\t%0, %1\\t%@ movhi_bigend"
3443 [(set_attr "type" "load")
3444  (set_attr "pool_range" "4096")])
3446 (define_insn "*movhi_bytes"
3447   [(set (match_operand:HI 0 "s_register_operand" "=r,r")
3448         (match_operand:HI 1 "arm_rhs_operand"  "rI,K"))]
3449   "TARGET_MMU_TRAPS"
3450   "@
3451    mov%?\\t%0, %1\\t%@ movhi
3452    mvn%?\\t%0, #%B1\\t%@ movhi")
3454 ;; We use a DImode scratch because we may occasionally need an additional
3455 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
3456 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
3457 (define_expand "reload_outhi"
3458   [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
3459               (match_operand:HI 1 "s_register_operand" "r")
3460               (match_operand:DI 2 "s_register_operand" "=&r")])]
3461   ""
3462   "
3463   arm_reload_out_hi (operands);
3464   DONE;
3467 (define_expand "reload_inhi"
3468   [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
3469               (match_operand:HI 1 "reload_memory_operand" "o")
3470               (match_operand:DI 2 "s_register_operand" "=&r")])]
3471   "TARGET_MMU_TRAPS"
3472   "
3473   arm_reload_in_hi (operands);
3474   DONE;
3477 (define_expand "movqi"
3478   [(set (match_operand:QI 0 "general_operand" "")
3479         (match_operand:QI 1 "general_operand" ""))]
3480   ""
3481   "
3482   /* Everything except mem = const or mem = mem can be done easily */
3484   if (!(reload_in_progress || reload_completed))
3485     {
3486       if (GET_CODE (operands[1]) == CONST_INT)
3487         {
3488           rtx reg = gen_reg_rtx (SImode);
3490           emit_insn (gen_movsi (reg, operands[1]));
3491           operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
3492         }
3493       if (GET_CODE (operands[0]) == MEM)
3494         operands[1] = force_reg (QImode, operands[1]);
3495     }
3499 (define_insn "*movqi_insn"
3500   [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
3501         (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
3502   "register_operand (operands[0], QImode)
3503    || register_operand (operands[1], QImode)"
3504   "@
3505    mov%?\\t%0, %1
3506    mvn%?\\t%0, #%B1
3507    ldr%?b\\t%0, %1
3508    str%?b\\t%1, %0"
3509 [(set_attr "type" "*,*,load,store1")])
3511 (define_expand "movsf"
3512   [(set (match_operand:SF 0 "general_operand" "")
3513         (match_operand:SF 1 "general_operand" ""))]
3514   ""
3515   "
3516   if (GET_CODE (operands[0]) == MEM)
3517     operands[1] = force_reg (SFmode, operands[1]);
3520 (define_insn "*movsf_hard_insn"
3521   [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
3522         (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
3523   "TARGET_HARD_FLOAT
3524    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3525   "@
3526    mvf%?s\\t%0, %1
3527    mnf%?s\\t%0, #%N1
3528    ldf%?s\\t%0, %1
3529    stf%?s\\t%1, %0
3530    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
3531    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
3532    mov%?\\t%0, %1
3533    ldr%?\\t%0, %1\\t%@ float
3534    str%?\\t%1, %0\\t%@ float"
3535 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
3536  (set_attr "type"
3537          "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
3538  (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")])
3540 ;; Exactly the same as above, except that all `f' cases are deleted.
3541 ;; This is necessary to prevent reload from ever trying to use a `f' reg
3542 ;; when -msoft-float.
3544 (define_insn "*movsf_soft_insn"
3545   [(set (match_operand:SF 0 "general_operand" "=r,r,m")
3546         (match_operand:SF 1 "general_operand" "r,mE,r"))]
3547   "TARGET_SOFT_FLOAT
3548    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3549   "@
3550    mov%?\\t%0, %1
3551    ldr%?\\t%0, %1\\t%@ float
3552    str%?\\t%1, %0\\t%@ float"
3553 [(set_attr "length" "4,4,4")
3554  (set_attr "type" "*,load,store1")
3555  (set_attr "pool_range" "*,4096,*")])
3557 (define_expand "movdf"
3558   [(set (match_operand:DF 0 "general_operand" "")
3559         (match_operand:DF 1 "general_operand" ""))]
3560   ""
3561   "
3562   if (GET_CODE (operands[0]) == MEM)
3563     operands[1] = force_reg (DFmode, operands[1]);
3566 ;; Reloading a df mode value stored in integer regs to memory can require a
3567 ;; scratch reg.
3568 (define_expand "reload_outdf"
3569   [(match_operand:DF 0 "reload_memory_operand" "=o")
3570    (match_operand:DF 1 "s_register_operand" "r")
3571    (match_operand:SI 2 "s_register_operand" "=&r")]
3572   ""
3573   "
3575   enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
3577   if (code == REG)
3578     operands[2] = XEXP (operands[0], 0);
3579   else if (code == POST_INC || code == PRE_DEC)
3580     {
3581       operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
3582       operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
3583       emit_insn (gen_movdi (operands[0], operands[1]));
3584       DONE;
3585     }
3586   else if (code == PRE_INC)
3587     {
3588       rtx reg = XEXP (XEXP (operands[0], 0), 0);
3589       emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
3590       operands[2] = reg;
3591     }
3592   else if (code == POST_DEC)
3593     operands[2] = XEXP (XEXP (operands[0], 0), 0);
3594   else
3595     emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
3596                            XEXP (XEXP (operands[0], 0), 1)));
3598   emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
3599                                     operands[1]));
3601   if (code == POST_DEC)
3602     emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
3604   DONE;
3608 (define_insn "*movdf_hard_insn"
3609   [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
3610         (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
3611   "TARGET_HARD_FLOAT
3612    && (GET_CODE (operands[0]) != MEM
3613        || register_operand (operands[1], DFmode))"
3614   "*
3616   switch (which_alternative)
3617     {
3618     default:
3619     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
3620     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
3621     case 2: case 3: case 4: return output_move_double (operands);
3622     case 5: return \"mvf%?d\\t%0, %1\";
3623     case 6: return \"mnf%?d\\t%0, #%N1\";
3624     case 7: return \"ldf%?d\\t%0, %1\";
3625     case 8: return \"stf%?d\\t%1, %0\";
3626     case 9: return output_mov_double_fpu_from_arm (operands);
3627     case 10: return output_mov_double_arm_from_fpu (operands);
3628     }
3631 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
3632  (set_attr "type"
3633 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
3634  (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")])
3636 ;; Software floating point version.  This is essentially the same as movdi.
3637 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
3638 ;; an `f' reg.
3640 (define_insn "*movdf_soft_insn"
3641   [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
3642         (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
3643   "TARGET_SOFT_FLOAT"
3644   "* return output_move_double (operands);"
3645 [(set_attr "length" "8,8,8")
3646  (set_attr "type" "*,load,store2")
3647  (set_attr "pool_range" "252")])
3649 (define_expand "movxf"
3650   [(set (match_operand:XF 0 "general_operand" "")
3651         (match_operand:XF 1 "general_operand" ""))]
3652   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3653   "")
3655 ;; Even when the XFmode patterns aren't enabled, we enable this after
3656 ;; reloading so that we can push floating point registers in the prologue.
3658 (define_insn "*movxf_hard_insn"
3659   [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
3660         (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
3661   "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
3662   "*
3663   switch (which_alternative)
3664     {
3665     default:
3666     case 0: return \"mvf%?e\\t%0, %1\";
3667     case 1: return \"mnf%?e\\t%0, #%N1\";
3668     case 2: return \"ldf%?e\\t%0, %1\";
3669     case 3: return \"stf%?e\\t%1, %0\";
3670     case 4: return output_mov_long_double_fpu_from_arm (operands);
3671     case 5: return output_mov_long_double_arm_from_fpu (operands);
3672     case 6: return output_mov_long_double_arm_from_arm (operands);
3673     }
3675 [(set_attr "length" "4,4,4,4,8,8,12")
3676  (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
3677  (set_attr "pool_range" "*,*,1024,*,*,*,*")])
3680 ;; load- and store-multiple insns
3681 ;; The arm can load/store any set of registers, provided that they are in
3682 ;; ascending order; but that is beyond GCC so stick with what it knows.
3684 (define_expand "load_multiple"
3685   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3686                           (match_operand:SI 1 "" ""))
3687                      (use (match_operand:SI 2 "" ""))])]
3688   ""
3689   "
3690   /* Support only fixed point registers */
3691   if (GET_CODE (operands[2]) != CONST_INT
3692       || INTVAL (operands[2]) > 14
3693       || INTVAL (operands[2]) < 2
3694       || GET_CODE (operands[1]) != MEM
3695       || GET_CODE (operands[0]) != REG
3696       || REGNO (operands[0]) > 14
3697       || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
3698     FAIL;
3700   operands[3]
3701     = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
3702                              force_reg (SImode, XEXP (operands[1], 0)),
3703                              TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
3704                              MEM_IN_STRUCT_P(operands[1]),
3705                              MEM_SCALAR_P (operands[1]));
3708 ;; Load multiple with write-back
3710 (define_insn "*ldmsi_postinc"
3711   [(match_parallel 0 "load_multiple_operation"
3712     [(set (match_operand:SI 1 "s_register_operand" "+r")
3713           (plus:SI (match_dup 1)
3714                    (match_operand:SI 2 "const_int_operand" "n")))
3715      (set (match_operand:SI 3 "s_register_operand" "=r")
3716           (mem:SI (match_dup 1)))])]
3717   "(INTVAL (operands[2])  == 4 * (XVECLEN (operands[0], 0) - 2))"
3718   "*
3720   rtx ops[3];
3721   int count = XVECLEN (operands[0], 0);
3723   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3724   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
3725   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
3727   output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
3728   return \"\";
3731 [(set_attr "type" "load")])
3733 ;; Ordinary load multiple
3735 (define_insn "*ldmsi"
3736   [(match_parallel 0 "load_multiple_operation"
3737     [(set (match_operand:SI 1 "s_register_operand" "=r")
3738           (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
3739   ""
3740   "*
3742   rtx ops[3];
3743   int count = XVECLEN (operands[0], 0);
3745   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3746   ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
3747   ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
3749   output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
3750   return \"\";
3753 [(set_attr "type" "load")])
3755 (define_expand "store_multiple"
3756   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3757                           (match_operand:SI 1 "" ""))
3758                      (use (match_operand:SI 2 "" ""))])]
3759   ""
3760   "
3761   /* Support only fixed point registers */
3762   if (GET_CODE (operands[2]) != CONST_INT
3763       || INTVAL (operands[2]) > 14
3764       || INTVAL (operands[2]) < 2
3765       || GET_CODE (operands[1]) != REG
3766       || GET_CODE (operands[0]) != MEM
3767       || REGNO (operands[1]) > 14
3768       || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
3769     FAIL;
3771   operands[3]
3772     = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
3773                               force_reg (SImode, XEXP (operands[0], 0)),
3774                               TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
3775                               MEM_IN_STRUCT_P(operands[0]), 
3776                               MEM_SCALAR_P (operands[0]));
3779 ;; Store multiple with write-back
3781 (define_insn "*stmsi_postinc"
3782   [(match_parallel 0 "store_multiple_operation"
3783     [(set (match_operand:SI 1 "s_register_operand" "+r")
3784           (plus:SI (match_dup 1)
3785                    (match_operand:SI 2 "const_int_operand" "n")))
3786      (set (mem:SI (match_dup 1))
3787           (match_operand:SI 3 "s_register_operand" "r"))])]
3788   "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3789   "*
3791   rtx ops[3];
3792   int count = XVECLEN (operands[0], 0);
3794   ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3795   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
3796   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
3798   output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
3799   return \"\";
3802 [(set (attr "type")
3803       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3804                 (const_string "store2")
3805              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
3806                 (const_string "store3")]
3807           (const_string "store4")))])
3809 ;; Ordinary store multiple
3811 (define_insn "*stmsi"
3812   [(match_parallel 0 "store_multiple_operation"
3813     [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
3814           (match_operand:SI 1 "s_register_operand" "r"))])]
3815   ""
3816   "*
3818   rtx ops[3];
3819   int count = XVECLEN (operands[0], 0);
3821   ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
3822   ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
3823   ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
3825   output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
3826   return \"\";
3829 [(set (attr "type")
3830       (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
3831                 (const_string "store2")
3832              (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3833                 (const_string "store3")]
3834           (const_string "store4")))])
3836 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
3837 ;; We could let this apply for blocks of less than this, but it clobbers so
3838 ;; many registers that there is then probably a better way.
3840 (define_expand "movstrqi"
3841   [(match_operand:BLK 0 "general_operand" "")
3842    (match_operand:BLK 1 "general_operand" "")
3843    (match_operand:SI 2 "const_int_operand" "")
3844    (match_operand:SI 3 "const_int_operand" "")]
3845   ""
3846   "
3847   if (arm_gen_movstrqi (operands))
3848     DONE;
3849   FAIL;
3853 ;; Comparison and test insns
3855 (define_expand "cmpsi"
3856   [(match_operand:SI 0 "s_register_operand" "")
3857    (match_operand:SI 1 "arm_add_operand" "")]
3858   ""
3859   "
3861   arm_compare_op0 = operands[0];
3862   arm_compare_op1 = operands[1];
3863   DONE;
3867 (define_expand "cmpsf"
3868   [(match_operand:SF 0 "s_register_operand" "")
3869    (match_operand:SF 1 "fpu_rhs_operand" "")]
3870   "TARGET_HARD_FLOAT"
3871   "
3873   arm_compare_op0 = operands[0];
3874   arm_compare_op1 = operands[1];
3875   DONE;
3879 (define_expand "cmpdf"
3880   [(match_operand:DF 0 "s_register_operand" "")
3881    (match_operand:DF 1 "fpu_rhs_operand" "")]
3882   "TARGET_HARD_FLOAT"
3883   "
3885   arm_compare_op0 = operands[0];
3886   arm_compare_op1 = operands[1];
3887   DONE;
3891 (define_expand "cmpxf"
3892   [(match_operand:XF 0 "s_register_operand" "")
3893    (match_operand:XF 1 "fpu_rhs_operand" "")]
3894   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3895   "
3897   arm_compare_op0 = operands[0];
3898   arm_compare_op1 = operands[1];
3899   DONE;
3903 (define_insn "*cmpsi_insn"
3904   [(set (reg:CC 24)
3905         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3906                     (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3907   ""
3908   "@
3909    cmp%?\\t%0, %1
3910    cmn%?\\t%0, #%n1"
3911 [(set_attr "conds" "set")])
3913 (define_insn "*cmpsi_shiftsi"
3914   [(set (reg:CC 24)
3915         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3916                     (match_operator:SI 3 "shift_operator"
3917                      [(match_operand:SI 1 "s_register_operand" "r")
3918                       (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3919   ""
3920   "cmp%?\\t%0, %1%S3"
3921   [(set_attr "conds" "set")
3924 (define_insn "*cmpsi_shiftsi_swp"
3925   [(set (reg:CC_SWP 24)
3926         (compare:CC_SWP (match_operator:SI 3 "shift_operator"
3927                          [(match_operand:SI 1 "s_register_operand" "r")
3928                           (match_operand:SI 2 "reg_or_int_operand" "rM")])
3929                         (match_operand:SI 0 "s_register_operand" "r")))]
3930   ""
3931   "cmp%?\\t%0, %1%S3"
3932   [(set_attr "conds" "set")
3935 (define_insn "*cmpsi_neg_shiftsi"
3936   [(set (reg:CC 24)
3937         (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3938                     (neg:SI (match_operator:SI 3 "shift_operator"
3939                              [(match_operand:SI 1 "s_register_operand" "r")
3940                               (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3941   ""
3942   "cmn%?\\t%0, %1%S3"
3943   [(set_attr "conds" "set")
3946 (define_insn "*cmpsf_insn"
3947   [(set (reg:CCFP 24)
3948         (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3949                       (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3950   "TARGET_HARD_FLOAT"
3951   "@
3952    cmf%?\\t%0, %1
3953    cnf%?\\t%0, #%N1"
3954 [(set_attr "conds" "set")
3955  (set_attr "type" "f_2_r")])
3957 (define_insn "*cmpdf_insn"
3958   [(set (reg:CCFP 24)
3959         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3960                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3961   "TARGET_HARD_FLOAT"
3962   "@
3963    cmf%?\\t%0, %1
3964    cnf%?\\t%0, #%N1"
3965 [(set_attr "conds" "set")
3966  (set_attr "type" "f_2_r")])
3968 (define_insn "*cmpesfdf_df"
3969   [(set (reg:CCFP 24)
3970         (compare:CCFP (float_extend:DF
3971                        (match_operand:SF 0 "s_register_operand" "f,f"))
3972                       (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3973   "TARGET_HARD_FLOAT"
3974   "@
3975    cmf%?\\t%0, %1
3976    cnf%?\\t%0, #%N1"
3977 [(set_attr "conds" "set")
3978  (set_attr "type" "f_2_r")])
3980 (define_insn "*cmpdf_esfdf"
3981   [(set (reg:CCFP 24)
3982         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3983                       (float_extend:DF
3984                        (match_operand:SF 1 "s_register_operand" "f"))))]
3985   "TARGET_HARD_FLOAT"
3986   "cmf%?\\t%0, %1"
3987 [(set_attr "conds" "set")
3988  (set_attr "type" "f_2_r")])
3990 (define_insn "*cmpxf_insn"
3991   [(set (reg:CCFP 24)
3992         (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3993                       (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3994   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3995   "@
3996    cmf%?\\t%0, %1
3997    cnf%?\\t%0, #%N1"
3998 [(set_attr "conds" "set")
3999  (set_attr "type" "f_2_r")])
4001 (define_insn "*cmpsf_trap"
4002   [(set (reg:CCFPE 24)
4003         (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
4004                        (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
4005   "TARGET_HARD_FLOAT"
4006   "@
4007    cmf%?e\\t%0, %1
4008    cnf%?e\\t%0, #%N1"
4009 [(set_attr "conds" "set")
4010  (set_attr "type" "f_2_r")])
4012 (define_insn "*cmpdf_trap"
4013   [(set (reg:CCFPE 24)
4014         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
4015                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
4016   "TARGET_HARD_FLOAT"
4017   "@
4018    cmf%?e\\t%0, %1
4019    cnf%?e\\t%0, #%N1"
4020 [(set_attr "conds" "set")
4021  (set_attr "type" "f_2_r")])
4023 (define_insn "*cmp_esfdf_df_trap"
4024   [(set (reg:CCFPE 24)
4025         (compare:CCFPE (float_extend:DF
4026                         (match_operand:SF 0 "s_register_operand" "f,f"))
4027                        (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
4028   "TARGET_HARD_FLOAT"
4029   "@
4030    cmf%?e\\t%0, %1
4031    cnf%?e\\t%0, #%N1"
4032 [(set_attr "conds" "set")
4033  (set_attr "type" "f_2_r")])
4035 (define_insn "*cmp_df_esfdf_trap"
4036   [(set (reg:CCFPE 24)
4037         (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
4038                        (float_extend:DF
4039                         (match_operand:SF 1 "s_register_operand" "f"))))]
4040   "TARGET_HARD_FLOAT"
4041   "cmf%?e\\t%0, %1"
4042 [(set_attr "conds" "set")
4043  (set_attr "type" "f_2_r")])
4045 (define_insn "*cmpxf_trap"
4046   [(set (reg:CCFPE 24)
4047         (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
4048                        (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
4049   "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
4050   "@
4051    cmf%?e\\t%0, %1
4052    cnf%?e\\t%0, #%N1"
4053 [(set_attr "conds" "set")
4054  (set_attr "type" "f_2_r")])
4056 ; This insn allows redundant compares to be removed by cse, nothing should
4057 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
4058 ; is deleted later on. The match_dup will match the mode here, so that
4059 ; mode changes of the condition codes aren't lost by this even though we don't
4060 ; specify what they are.
4062 (define_insn "*deleted_compare"
4063   [(set (match_operand 0 "cc_register" "") (match_dup 0))]
4064   ""
4065   "\\t%@ deleted compare"
4066 [(set_attr "conds" "set")
4067  (set_attr "length" "0")])
4070 ;; Conditional branch insns
4072 (define_expand "beq"
4073   [(set (pc)
4074         (if_then_else (eq (match_dup 1) (const_int 0))
4075                       (label_ref (match_operand 0 "" ""))
4076                       (pc)))]
4077   ""
4078   "
4080   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);
4084 (define_expand "bne"
4085   [(set (pc)
4086         (if_then_else (ne (match_dup 1) (const_int 0))
4087                       (label_ref (match_operand 0 "" ""))
4088                       (pc)))]
4089   ""
4090   "
4092   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);
4096 (define_expand "bgt"
4097   [(set (pc)
4098         (if_then_else (gt (match_dup 1) (const_int 0))
4099                       (label_ref (match_operand 0 "" ""))
4100                       (pc)))]
4101   ""
4102   "
4104   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);
4108 (define_expand "ble"
4109   [(set (pc)
4110         (if_then_else (le (match_dup 1) (const_int 0))
4111                       (label_ref (match_operand 0 "" ""))
4112                       (pc)))]
4113   ""
4114   "
4116   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);
4120 (define_expand "bge"
4121   [(set (pc)
4122         (if_then_else (ge (match_dup 1) (const_int 0))
4123                       (label_ref (match_operand 0 "" ""))
4124                       (pc)))]
4125   ""
4126   "
4128   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);
4132 (define_expand "blt"
4133   [(set (pc)
4134         (if_then_else (lt (match_dup 1) (const_int 0))
4135                       (label_ref (match_operand 0 "" ""))
4136                       (pc)))]
4137   ""
4138   "
4140   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);
4144 (define_expand "bgtu"
4145   [(set (pc)
4146         (if_then_else (gtu (match_dup 1) (const_int 0))
4147                       (label_ref (match_operand 0 "" ""))
4148                       (pc)))]
4149   ""
4150   "
4152   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);
4156 (define_expand "bleu"
4157   [(set (pc)
4158         (if_then_else (leu (match_dup 1) (const_int 0))
4159                       (label_ref (match_operand 0 "" ""))
4160                       (pc)))]
4161   ""
4162   "
4164   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);
4168 (define_expand "bgeu"
4169   [(set (pc)
4170         (if_then_else (geu (match_dup 1) (const_int 0))
4171                       (label_ref (match_operand 0 "" ""))
4172                       (pc)))]
4173   ""
4174   "
4176   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);
4180 (define_expand "bltu"
4181   [(set (pc)
4182         (if_then_else (ltu (match_dup 1) (const_int 0))
4183                       (label_ref (match_operand 0 "" ""))
4184                       (pc)))]
4185   ""
4186   "
4188   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);
4192 ;; patterns to match conditional branch insns
4194 (define_insn "*condbranch"
4195   [(set (pc)
4196         (if_then_else (match_operator 1 "comparison_operator"
4197                        [(match_operand 2 "cc_register" "") (const_int 0)])
4198                       (label_ref (match_operand 0 "" ""))
4199                       (pc)))]
4200   ""
4201   "*
4203   extern int arm_ccfsm_state;
4205   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4206   {
4207     arm_ccfsm_state += 2;
4208     return \"\";
4209   }
4210   return \"b%d1\\t%l0\";
4212 [(set_attr "conds" "use")])
4214 (define_insn "*condbranch_reversed"
4215   [(set (pc)
4216         (if_then_else (match_operator 1 "comparison_operator"
4217                        [(match_operand 2 "cc_register" "") (const_int 0)])
4218                       (pc)
4219                       (label_ref (match_operand 0 "" ""))))]
4220   ""
4221   "*
4223   extern int arm_ccfsm_state;
4225   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4226   {
4227     arm_ccfsm_state += 2;
4228     return \"\";
4229   }
4230   return \"b%D1\\t%l0\";
4232 [(set_attr "conds" "use")])
4235 ; scc insns
4237 (define_expand "seq"
4238   [(set (match_operand:SI 0 "s_register_operand" "=r")
4239         (eq:SI (match_dup 1) (const_int 0)))]
4240   ""
4241   "
4243   operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);
4247 (define_expand "sne"
4248   [(set (match_operand:SI 0 "s_register_operand" "=r")
4249         (ne:SI (match_dup 1) (const_int 0)))]
4250   ""
4251   "
4253   operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);
4257 (define_expand "sgt"
4258   [(set (match_operand:SI 0 "s_register_operand" "=r")
4259         (gt:SI (match_dup 1) (const_int 0)))]
4260   ""
4261   "
4263   operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);
4267 (define_expand "sle"
4268   [(set (match_operand:SI 0 "s_register_operand" "=r")
4269         (le:SI (match_dup 1) (const_int 0)))]
4270   ""
4271   "
4273   operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);
4277 (define_expand "sge"
4278   [(set (match_operand:SI 0 "s_register_operand" "=r")
4279         (ge:SI (match_dup 1) (const_int 0)))]
4280   ""
4281   "
4283   operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);
4287 (define_expand "slt"
4288   [(set (match_operand:SI 0 "s_register_operand" "=r")
4289         (lt:SI (match_dup 1) (const_int 0)))]
4290   ""
4291   "
4293   operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);
4297 (define_expand "sgtu"
4298   [(set (match_operand:SI 0 "s_register_operand" "=r")
4299         (gtu:SI (match_dup 1) (const_int 0)))]
4300   ""
4301   "
4303   operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);
4307 (define_expand "sleu"
4308   [(set (match_operand:SI 0 "s_register_operand" "=r")
4309         (leu:SI (match_dup 1) (const_int 0)))]
4310   ""
4311   "
4313   operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);
4317 (define_expand "sgeu"
4318   [(set (match_operand:SI 0 "s_register_operand" "=r")
4319         (geu:SI (match_dup 1) (const_int 0)))]
4320   ""
4321   "
4323   operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);
4327 (define_expand "sltu"
4328   [(set (match_operand:SI 0 "s_register_operand" "=r")
4329         (ltu:SI (match_dup 1) (const_int 0)))]
4330   ""
4331   "
4333   operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);
4337 (define_insn "*mov_scc"
4338   [(set (match_operand:SI 0 "s_register_operand" "=r")
4339         (match_operator:SI 1 "comparison_operator"
4340          [(match_operand 2 "cc_register" "") (const_int 0)]))]
4341   ""
4342   "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
4343 [(set_attr "conds" "use")
4344  (set_attr "length" "8")])
4346 (define_insn "*mov_negscc"
4347   [(set (match_operand:SI 0 "s_register_operand" "=r")
4348         (neg:SI (match_operator:SI 1 "comparison_operator"
4349                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
4350   ""
4351   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
4352 [(set_attr "conds" "use")
4353  (set_attr "length" "8")])
4355 (define_insn "*mov_notscc"
4356   [(set (match_operand:SI 0 "s_register_operand" "=r")
4357         (not:SI (match_operator:SI 1 "comparison_operator"
4358                  [(match_operand 2 "cc_register" "") (const_int 0)])))]
4359   ""
4360   "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
4361 [(set_attr "conds" "use")
4362  (set_attr "length" "8")])
4365 ;; Conditional move insns
4367 (define_expand "movsicc"
4368   [(set (match_operand:SI 0 "s_register_operand" "")
4369         (if_then_else:SI (match_operand 1 "comparison_operator" "")
4370                          (match_operand:SI 2 "arm_not_operand" "")
4371                          (match_operand:SI 3 "arm_not_operand" "")))]
4372   ""
4373   "
4375   enum rtx_code code = GET_CODE (operands[1]);
4376   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
4378   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4381 (define_expand "movsfcc"
4382   [(set (match_operand:SF 0 "s_register_operand" "")
4383         (if_then_else:SF (match_operand 1 "comparison_operator" "")
4384                          (match_operand:SF 2 "s_register_operand" "")
4385                          (match_operand:SF 3 "nonmemory_operand" "")))]
4386   ""
4387   "
4389   enum rtx_code code = GET_CODE (operands[1]);
4390   rtx ccreg;
4392   /* When compiling for SOFT_FLOAT, ensure both arms are in registers. 
4393      Otherwise, ensure it is a valid FP add operand */
4394   if ((! TARGET_HARD_FLOAT)
4395       || (! fpu_add_operand (operands[3], SFmode)))
4396     operands[3] = force_reg (SFmode, operands[3]);
4398   ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
4400   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4403 (define_expand "movdfcc"
4404   [(set (match_operand:DF 0 "s_register_operand" "")
4405         (if_then_else:DF (match_operand 1 "comparison_operator" "")
4406                          (match_operand:DF 2 "s_register_operand" "")
4407                          (match_operand:DF 3 "fpu_add_operand" "")))]
4408   "TARGET_HARD_FLOAT"
4409   "
4411   enum rtx_code code = GET_CODE (operands[1]);
4412   rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
4414   operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4417 (define_insn "*movsicc_insn"
4418   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
4419         (if_then_else:SI
4420          (match_operator 3 "comparison_operator"
4421           [(match_operand 4 "cc_register" "") (const_int 0)])
4422          (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
4423          (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
4424   ""
4425   "@
4426    mov%D3\\t%0, %2
4427    mvn%D3\\t%0, #%B2
4428    mov%d3\\t%0, %1
4429    mvn%d3\\t%0, #%B1
4430    mov%d3\\t%0, %1\;mov%D3\\t%0, %2
4431    mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
4432    mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
4433    mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
4434   [(set_attr "length" "4,4,4,4,8,8,8,8")
4435    (set_attr "conds" "use")])
4437 (define_insn "*movsfcc_hard_insn"
4438   [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4439         (if_then_else:SF
4440          (match_operator 3 "comparison_operator" 
4441           [(match_operand 4 "cc_register" "") (const_int 0)])
4442          (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4443          (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4444   "TARGET_HARD_FLOAT"
4445   "@
4446    mvf%D3s\\t%0, %2
4447    mnf%D3s\\t%0, #%N2
4448    mvf%d3s\\t%0, %1
4449    mnf%d3s\\t%0, #%N1
4450    mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
4451    mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
4452    mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
4453    mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
4454   [(set_attr "length" "4,4,4,4,8,8,8,8")
4455    (set_attr "type" "ffarith")
4456    (set_attr "conds" "use")])
4458 (define_insn "*movsfcc_soft_insn"
4459   [(set (match_operand:SF 0 "s_register_operand" "=r,r")
4460         (if_then_else:SF (match_operator 3 "comparison_operator"
4461                           [(match_operand 4 "cc_register" "") (const_int 0)])
4462                          (match_operand:SF 1 "s_register_operand" "0,r")
4463                          (match_operand:SF 2 "s_register_operand" "r,0")))]
4464   "TARGET_SOFT_FLOAT"
4465   "@
4466    mov%D3\\t%0, %2
4467    mov%d3\\t%0, %1"
4468   [(set_attr "conds" "use")])
4470 (define_insn "*movdfcc_insn"
4471   [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4472         (if_then_else:DF
4473          (match_operator 3 "comparison_operator"
4474           [(match_operand 4 "cc_register" "") (const_int 0)])
4475          (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4476          (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4477   "TARGET_HARD_FLOAT"
4478   "@
4479    mvf%D3d\\t%0, %2
4480    mnf%D3d\\t%0, #%N2
4481    mvf%d3d\\t%0, %1
4482    mnf%d3d\\t%0, #%N1
4483    mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
4484    mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
4485    mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
4486    mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
4487   [(set_attr "length" "4,4,4,4,8,8,8,8")
4488    (set_attr "type" "ffarith")
4489    (set_attr "conds" "use")])
4491 ;; Jump and linkage insns
4493 (define_insn "jump"
4494   [(set (pc)
4495         (label_ref (match_operand 0 "" "")))]
4496   ""
4497   "*
4499   extern int arm_ccfsm_state;
4501   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4502     {
4503       arm_ccfsm_state += 2;
4504       return \"\";
4505     }
4506   return \"b%?\\t%l0\";
4509 (define_expand "call"
4510   [(parallel [(call (match_operand 0 "memory_operand" "")
4511                     (match_operand 1 "general_operand" ""))
4512               (use (match_operand 2 "" ""))
4513               (clobber (reg:SI 14))])]
4514   ""
4515   "
4516   {
4517     rtx callee;
4518     
4519     /* In an untyped call, we can get NULL for operand 2.  */
4520     if (operands[2] == NULL_RTX)
4521       operands[2] = const0_rtx;
4522       
4523     /* This is to decide if we should generate indirect calls by loading the
4524        32 bit address of the callee into a register before performing the
4525        branch and link.  operand[2] encodes the long_call/short_call
4526        attribute of the function being called.  This attribute is set whenever
4527        __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
4528        is used, and the short_call attribute can also be set if function is
4529        declared as static or if it has already been defined in the current
4530        compilation unit.  See arm.c and arm.h for info about this.  The third
4531        parameter to arm_is_longcall_p is used to tell it which pattern
4532        invoked it.  */
4533     callee  = XEXP (operands[0], 0);
4534     
4535     if (GET_CODE (callee) != REG
4536        && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
4537       XEXP (operands[0], 0) = force_reg (Pmode, callee);
4538   }"
4541 (define_insn "*call_reg"
4542   [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
4543          (match_operand 1 "" "g"))
4544    (use (match_operand:SI 2 "immediate_operand" "n"))
4545    (clobber (reg:SI 14))]
4546   ""
4547   "*
4548   return output_call (operands);
4550 ;; length is worst case, normally it is only two
4551 [(set_attr "length" "12")
4552  (set_attr "type" "call")])
4554 (define_insn "*call_mem"
4555   [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
4556          (match_operand 1 "general_operand" "g"))
4557    (use (match_operand:SI 2 "" ""))
4558    (clobber (reg:SI 14))]
4559   ""
4560   "*
4561   return output_call_mem (operands);
4563 [(set_attr "length" "12")
4564  (set_attr "type" "call")])
4566 (define_expand "call_value"
4567   [(parallel [(set (match_operand 0 "" "=rf")
4568                    (call (match_operand 1 "memory_operand" "m")
4569                          (match_operand 2 "general_operand" "g")))
4570               (use (match_operand:SI 3 "" ""))
4571               (clobber (reg:SI 14))])]
4572   ""
4573   "
4574   {
4575     rtx callee = XEXP (operands[1], 0);
4576     
4577     /* In an untyped call, we can get NULL for operand 2.  */
4578     if (operands[3] == 0)
4579       operands[3] = const0_rtx;
4580       
4581     /* See the comment in define_expand \"call\".  */
4582     if (GET_CODE (callee) != REG
4583         && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
4584       XEXP (operands[1], 0) = force_reg (Pmode, callee);
4585   }"
4588 (define_insn "*call_value_reg"
4589   [(set (match_operand 0 "" "=rf")
4590         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4591               (match_operand 2 "general_operand" "g")))
4592    (use (match_operand 3 "" ""))
4593    (clobber (reg:SI 14))]
4594   ""
4595   "*
4596   return output_call (&operands[1]);
4598 [(set_attr "length" "12")
4599  (set_attr "type" "call")])
4601 (define_insn "*call_value_mem"
4602   [(set (match_operand 0 "" "=rf")
4603         (call (mem:SI (match_operand 1 "memory_operand" "m"))
4604         (match_operand 2 "general_operand" "g")))
4605    (use (match_operand 3 "" ""))
4606    (clobber (reg:SI 14))]
4607   "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
4608   "*
4609   return output_call_mem (&operands[1]);
4611 [(set_attr "length" "12")
4612  (set_attr "type" "call")])
4614 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
4615 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
4617 (define_insn "*call_symbol"
4618   [(call (mem:SI (match_operand:SI 0 "" "X"))
4619          (match_operand:SI 1 "general_operand" "g"))
4620    (use (match_operand 2 "" ""))
4621    (clobber (reg:SI 14))]
4622   "(GET_CODE (operands[0]) == SYMBOL_REF)
4623    && ! arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
4624   "*
4625   {
4626     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
4627   }"
4628 [(set_attr "type" "call")])
4630 (define_insn "*call_value_symbol"
4631   [(set (match_operand 0 "s_register_operand" "=rf")
4632         (call (mem:SI (match_operand:SI 1 "" "X"))
4633         (match_operand:SI 2 "general_operand" "g")))
4634    (use (match_operand 3 "" ""))
4635    (clobber (reg:SI 14))]
4636   "(GET_CODE (operands[1]) == SYMBOL_REF)
4637    && ! arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
4638   "*
4639   {
4640     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
4641   }"
4642 [(set_attr "type" "call")])
4644 ;; Often the return insn will be the same as loading from memory, so set attr
4645 (define_insn "return"
4646   [(return)]
4647   "USE_RETURN_INSN (FALSE)"
4648   "*
4650   extern int arm_ccfsm_state;
4652   if (arm_ccfsm_state == 2)
4653   {
4654     arm_ccfsm_state += 2;
4655     return \"\";
4656   }
4657   return output_return_instruction (NULL, TRUE, FALSE);
4659 [(set_attr "type" "load")])
4661 (define_insn "*cond_return"
4662   [(set (pc)
4663         (if_then_else (match_operator 0 "comparison_operator"
4664                        [(match_operand 1 "cc_register" "") (const_int 0)])
4665                       (return)
4666                       (pc)))]
4667   "USE_RETURN_INSN (TRUE)"
4668   "*
4670   extern int arm_ccfsm_state;
4672   if (arm_ccfsm_state == 2)
4673   {
4674     arm_ccfsm_state += 2;
4675     return \"\";
4676   }
4677   return output_return_instruction (operands[0], TRUE, FALSE);
4679 [(set_attr "conds" "use")
4680  (set_attr "type" "load")])
4682 (define_insn "*cond_return_inverted"
4683   [(set (pc)
4684         (if_then_else (match_operator 0 "comparison_operator"
4685                        [(match_operand 1 "cc_register" "") (const_int 0)])
4686                       (pc)
4687                       (return)))]
4688   "USE_RETURN_INSN (TRUE)"
4689   "*
4691   extern int arm_ccfsm_state;
4693   if (arm_ccfsm_state == 2)
4694   {
4695     arm_ccfsm_state += 2;
4696     return \"\";
4697   }
4698   return output_return_instruction (operands[0], TRUE, TRUE);
4700 [(set_attr "conds" "use")
4701  (set_attr "type" "load")])
4703 ;; Call subroutine returning any type.
4705 (define_expand "untyped_call"
4706   [(parallel [(call (match_operand 0 "" "")
4707                     (const_int 0))
4708               (match_operand 1 "" "")
4709               (match_operand 2 "" "")])]
4710   ""
4711   "
4713   int i;
4715   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
4717   for (i = 0; i < XVECLEN (operands[2], 0); i++)
4718     {
4719       rtx set = XVECEXP (operands[2], 0, i);
4720       emit_move_insn (SET_DEST (set), SET_SRC (set));
4721     }
4723   /* The optimizer does not know that the call sets the function value
4724      registers we stored in the result block.  We avoid problems by
4725      claiming that all hard registers are used and clobbered at this
4726      point.  */
4727   emit_insn (gen_blockage ());
4729   DONE;
4732 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
4733 ;; all of memory.  This blocks insns from being moved across this point.
4735 (define_insn "blockage"
4736   [(unspec_volatile [(const_int 0)] 0)]
4737   ""
4738   ""
4739 [(set_attr "length" "0")
4740  (set_attr "type" "block")])
4742 (define_expand "casesi"
4743   [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
4744    (match_operand:SI 1 "const_int_operand" "")  ; lower bound
4745    (match_operand:SI 2 "const_int_operand" "")  ; total range
4746    (match_operand:SI 3 "" "")                   ; table label
4747    (match_operand:SI 4 "" "")]                  ; Out of range label
4748   ""
4749   "
4751   rtx reg;
4752   if (operands[1] != const0_rtx)
4753     {
4754       reg = gen_reg_rtx (SImode);
4755       emit_insn (gen_addsi3 (reg, operands[0],
4756                              GEN_INT (-INTVAL (operands[1]))));
4757       operands[0] = reg;
4758     }
4760   if (! const_ok_for_arm (INTVAL (operands[2])))
4761     operands[2] = force_reg (SImode, operands[2]);
4763   emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
4764                                        operands[4]));
4765   DONE;
4768 ;; The USE in this pattern is needed to tell flow analysis that this is
4769 ;; a CASESI insn.  It has no other purpose.
4770 (define_insn "casesi_internal"
4771   [(parallel [(set (pc)
4772                (if_then_else
4773                 (leu (match_operand:SI 0 "s_register_operand" "r")
4774                      (match_operand:SI 1 "arm_rhs_operand" "rI"))
4775                 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
4776                                  (label_ref (match_operand 2 "" ""))))
4777                 (label_ref (match_operand 3 "" ""))))
4778               (clobber (reg:CC 24))
4779               (use (label_ref (match_dup 2)))])]
4780   ""
4781   "*
4782   if (flag_pic)
4783     return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
4784   return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
4786 [(set_attr "conds" "clob")
4787  (set_attr "length" "12")])
4789 (define_insn "indirect_jump"
4790   [(set (pc)
4791         (match_operand:SI 0 "s_register_operand" "r"))]
4792   ""
4793   "mov%?\\t%|pc, %0\\t%@ indirect jump")
4795 (define_insn "*load_indirect_jump"
4796   [(set (pc)
4797         (match_operand:SI 0 "memory_operand" "m"))]
4798   ""
4799   "ldr%?\\t%|pc, %0\\t%@ indirect jump"
4800 [(set_attr "type" "load")])
4802 ;; Misc insns
4804 (define_insn "nop"
4805   [(const_int 0)]
4806   ""
4807   "mov%?\\t%|r0, %|r0\\t%@ nop")
4809 ;; Patterns to allow combination of arithmetic, cond code and shifts
4811 (define_insn "*arith_shiftsi"
4812   [(set (match_operand:SI 0 "s_register_operand" "=r")
4813         (match_operator:SI 1 "shiftable_operator"
4814           [(match_operator:SI 3 "shift_operator"
4815              [(match_operand:SI 4 "s_register_operand" "r")
4816               (match_operand:SI 5 "reg_or_int_operand" "rI")])
4817            (match_operand:SI 2 "s_register_operand" "r")]))]
4818   ""
4819   "%i1%?\\t%0, %2, %4%S3"
4822 (define_insn "*arith_shiftsi_compare0"
4823   [(set (reg:CC_NOOV 24)
4824         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4825                           [(match_operator:SI 3 "shift_operator"
4826                             [(match_operand:SI 4 "s_register_operand" "r")
4827                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4828                            (match_operand:SI 2 "s_register_operand" "r")])
4829                          (const_int 0)))
4830    (set (match_operand:SI 0 "s_register_operand" "=r")
4831         (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4832                          (match_dup 2)]))]
4833   ""
4834   "%i1%?s\\t%0, %2, %4%S3"
4835   [(set_attr "conds" "set")
4838 (define_insn "*arith_shiftsi_compare0_scratch"
4839   [(set (reg:CC_NOOV 24)
4840         (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4841                           [(match_operator:SI 3 "shift_operator"
4842                             [(match_operand:SI 4 "s_register_operand" "r")
4843                              (match_operand:SI 5 "reg_or_int_operand" "rI")])
4844                            (match_operand:SI 2 "s_register_operand" "r")])
4845                          (const_int 0)))
4846    (clobber (match_scratch:SI 0 "=r"))]
4847   ""
4848   "%i1%?s\\t%0, %2, %4%S3"
4849   [(set_attr "conds" "set")
4852 (define_insn "*sub_shiftsi"
4853   [(set (match_operand:SI 0 "s_register_operand" "=r")
4854         (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4855                   (match_operator:SI 2 "shift_operator"
4856                    [(match_operand:SI 3 "s_register_operand" "r")
4857                     (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4858   ""
4859   "sub%?\\t%0, %1, %3%S2"
4862 (define_insn "*sub_shiftsi_compare0"
4863   [(set (reg:CC_NOOV 24)
4864         (compare:CC_NOOV
4865          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4866                    (match_operator:SI 2 "shift_operator"
4867                     [(match_operand:SI 3 "s_register_operand" "r")
4868                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4869          (const_int 0)))
4870    (set (match_operand:SI 0 "s_register_operand" "=r")
4871         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4872                                                  (match_dup 4)])))]
4873   ""
4874   "sub%?s\\t%0, %1, %3%S2"
4875   [(set_attr "conds" "set")
4878 (define_insn "*sub_shiftsi_compare0_scratch"
4879   [(set (reg:CC_NOOV 24)
4880         (compare:CC_NOOV
4881          (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4882                    (match_operator:SI 2 "shift_operator"
4883                     [(match_operand:SI 3 "s_register_operand" "r")
4884                      (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4885          (const_int 0)))
4886    (clobber (match_scratch:SI 0 "=r"))]
4887   ""
4888   "sub%?s\\t%0, %1, %3%S2"
4889   [(set_attr "conds" "set")
4892 ;; These variants of the above insns can occur if the first operand is the
4893 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
4894 ;; seem to be a way around it.  Most of the predicates have to be null
4895 ;; because the format can be generated part way through reload, so
4896 ;; if we don't match it as soon as it becomes available, reload doesn't know
4897 ;; how to reload pseudos that haven't got hard registers; the constraints will
4898 ;; sort everything out.
4900 (define_insn "*reload_mulsi3"
4901   [(set (match_operand:SI 0 "" "=&r")
4902         (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4903                            [(match_operand:SI 3 "" "r")
4904                             (match_operand:SI 4 "" "rM")])
4905                           (match_operand:SI 2 "" "r"))
4906                  (match_operand:SI 1 "const_int_operand" "n")))]
4907   "reload_in_progress"
4908   "*
4909   output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4910   operands[2] = operands[1];
4911   operands[1] = operands[0];
4912   return output_add_immediate (operands);
4914 ; we have no idea how long the add_immediate is, it could be up to 4.
4915 [(set_attr "length" "20")])
4917 (define_insn "*reload_mulsi_compare0"
4918   [(set (reg:CC_NOOV 24)
4919         (compare:CC_NOOV (plus:SI
4920                           (plus:SI 
4921                            (match_operator:SI 5 "shift_operator"
4922                             [(match_operand:SI 3 "" "r")
4923                              (match_operand:SI 4 "" "rM")])
4924                            (match_operand:SI 1 "" "r"))
4925                           (match_operand:SI 2 "const_int_operand" "n"))
4926                          (const_int 0)))
4927    (set (match_operand:SI 0 "" "=&r")
4928         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4929                           (match_dup 1))
4930                  (match_dup 2)))]
4931   "reload_in_progress"
4932   "*
4933   output_add_immediate (operands);
4934   return \"add%?s\\t%0, %0, %3%S5\";
4936 [(set_attr "conds" "set")
4937  (set_attr "length" "20")])
4939 (define_insn "*reload_mulsi_compare0_scratch"
4940   [(set (reg:CC_NOOV 24)
4941         (compare:CC_NOOV (plus:SI
4942                           (plus:SI 
4943                            (match_operator:SI 5 "shift_operator"
4944                             [(match_operand:SI 3 "" "r")
4945                              (match_operand:SI 4 "" "rM")])
4946                            (match_operand:SI 1 "" "r"))
4947                           (match_operand:SI 2 "const_int_operand" "n"))
4948                          (const_int 0)))
4949    (clobber (match_scratch:SI 0 "=&r"))]
4950   "reload_in_progress"
4951   "*
4952   output_add_immediate (operands);
4953   return \"add%?s\\t%0, %0, %3%S5\";
4955 [(set_attr "conds" "set")
4956  (set_attr "length" "20")])
4958 ;; These are similar, but are needed when the mla pattern contains the
4959 ;; eliminated register as operand 3.
4961 (define_insn "*reload_muladdsi"
4962   [(set (match_operand:SI 0 "" "=&r,&r")
4963         (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4964                                    (match_operand:SI 2 "" "r,r"))
4965                           (match_operand:SI 3 "" "r,r"))
4966                  (match_operand:SI 4 "const_int_operand" "n,n")))]
4967   "reload_in_progress"
4968   "*
4969   output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4970   operands[2] = operands[4];
4971   operands[1] = operands[0];
4972   return output_add_immediate (operands);
4974 [(set_attr "length" "20")
4975  (set_attr "type" "mult")])
4977 (define_insn "*reload_muladdsi_compare0"
4978   [(set (reg:CC_NOOV 24)
4979         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4980                                             (match_operand:SI 3 "" "r")
4981                                             (match_operand:SI 4 "" "r"))
4982                                            (match_operand:SI 1 "" "r"))
4983                                   (match_operand:SI 2 "const_int_operand" "n"))
4984                          (const_int 0)))
4985    (set (match_operand:SI 0 "" "=&r")
4986         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4987                  (match_dup 2)))]
4988   "reload_in_progress"
4989   "*
4990   output_add_immediate (operands);
4991   output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4992   return \"\";
4994 [(set_attr "length" "20")
4995  (set_attr "conds" "set")
4996  (set_attr "type" "mult")])
4998 (define_insn "*reload_muladdsi_compare0_scratch"
4999   [(set (reg:CC_NOOV 24)
5000         (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
5001                                             (match_operand:SI 3 "" "r")
5002                                             (match_operand:SI 4 "" "r"))
5003                                            (match_operand:SI 1 "" "r"))
5004                                   (match_operand:SI 2 "const_int_operand" "n"))
5005                          (const_int 0)))
5006    (clobber (match_scratch:SI 0 "=&r"))]
5007   "reload_in_progress"
5008   "*
5009   output_add_immediate (operands);
5010   return \"mla%?s\\t%0, %3, %4, %0\";
5012 [(set_attr "length" "20")
5013  (set_attr "conds" "set")
5014  (set_attr "type" "mult")])
5018 (define_insn "*and_scc"
5019   [(set (match_operand:SI 0 "s_register_operand" "=r")
5020         (and:SI (match_operator 1 "comparison_operator"
5021                  [(match_operand 3 "cc_register" "") (const_int 0)])
5022                 (match_operand:SI 2 "s_register_operand" "r")))]
5023   ""
5024   "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
5025 [(set_attr "conds" "use")
5026  (set_attr "length" "8")])
5028 (define_insn "*ior_scc"
5029   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5030         (ior:SI (match_operator 2 "comparison_operator"
5031                  [(match_operand 3 "cc_register" "") (const_int 0)])
5032                 (match_operand:SI 1 "s_register_operand" "0,?r")))]
5033   ""
5034   "@
5035    orr%d2\\t%0, %1, #1
5036    mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
5037 [(set_attr "conds" "use")
5038  (set_attr "length" "4,8")])
5040 (define_insn "*compare_scc"
5041   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5042         (match_operator 1 "comparison_operator"
5043          [(match_operand:SI 2 "s_register_operand" "r,r")
5044           (match_operand:SI 3 "arm_add_operand" "rI,L")]))
5045    (clobber (reg:CC 24))]
5046   ""
5047   "*
5048   if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
5049     return \"mov\\t%0, %2, lsr #31\";
5051   if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
5052     return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
5054   if (GET_CODE (operands[1]) == NE)
5055     {
5056       if (which_alternative == 1)
5057         return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
5058       return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
5059     }
5060   if (which_alternative == 1)
5061     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
5062   else
5063     output_asm_insn (\"cmp\\t%2, %3\", operands);
5064   return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
5066 [(set_attr "conds" "clob")
5067  (set_attr "length" "12")])
5069 (define_insn "*cond_move"
5070   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5071         (if_then_else:SI (match_operator 3 "equality_operator"
5072                           [(match_operator 4 "comparison_operator"
5073                             [(match_operand 5 "cc_register" "") (const_int 0)])
5074                            (const_int 0)])
5075                          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
5076                          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
5077   ""
5078   "*
5079   if (GET_CODE (operands[3]) == NE)
5080     {
5081       if (which_alternative != 1)
5082         output_asm_insn (\"mov%D4\\t%0, %2\", operands);
5083       if (which_alternative != 0)
5084         output_asm_insn (\"mov%d4\\t%0, %1\", operands);
5085       return \"\";
5086     }
5087   if (which_alternative != 0)
5088     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
5089   if (which_alternative != 1)
5090     output_asm_insn (\"mov%d4\\t%0, %2\", operands);
5091   return \"\";
5093 [(set_attr "conds" "use")
5094  (set_attr "length" "4,4,8")])
5096 (define_insn "*cond_arith"
5097   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5098         (match_operator:SI 5 "shiftable_operator" 
5099          [(match_operator:SI 4 "comparison_operator"
5100            [(match_operand:SI 2 "s_register_operand" "r,r")
5101             (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
5102           (match_operand:SI 1 "s_register_operand" "0,?r")]))
5103    (clobber (reg:CC 24))]
5104   ""
5105   "*
5106   if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
5107     return \"%i5\\t%0, %1, %2, lsr #31\";
5109   output_asm_insn (\"cmp\\t%2, %3\", operands);
5110   if (GET_CODE (operands[5]) == AND)
5111     output_asm_insn (\"mov%D4\\t%0, #0\", operands);
5112   else if (GET_CODE (operands[5]) == MINUS)
5113     output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
5114   else if (which_alternative != 0)
5115     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
5116   return \"%i5%d4\\t%0, %1, #1\";
5118 [(set_attr "conds" "clob")
5119  (set_attr "length" "12")])
5121 (define_insn "*cond_sub"
5122   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5123         (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
5124                   (match_operator:SI 4 "comparison_operator"
5125                    [(match_operand:SI 2 "s_register_operand" "r,r")
5126                     (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
5127    (clobber (reg:CC 24))]
5128   ""
5129   "*
5130   output_asm_insn (\"cmp\\t%2, %3\", operands);
5131   if (which_alternative != 0)
5132     output_asm_insn (\"mov%D4\\t%0, %1\", operands);
5133   return \"sub%d4\\t%0, %1, #1\";
5135 [(set_attr "conds" "clob")
5136  (set_attr "length" "8,12")])
5138 (define_insn "*cmp_ite0"
5139   [(set (match_operand:CC 6 "dominant_cc_register" "")
5140         (compare
5141          (if_then_else:SI
5142           (match_operator 4 "comparison_operator"
5143            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
5144             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
5145           (match_operator:SI 5 "comparison_operator"
5146            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
5147             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
5148           (const_int 0))
5149          (const_int 0)))]
5150   ""
5151   "*
5153   char* opcodes[4][2] =
5154   {
5155     {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
5156     {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
5157     {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
5158     {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
5159      \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
5160   };
5161   int swap =
5162     comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
5164   return opcodes[which_alternative][swap];
5167 [(set_attr "conds" "set")
5168  (set_attr "length" "8")])
5170 (define_insn "*cmp_ite1"
5171   [(set (match_operand:CC 6 "dominant_cc_register" "")
5172         (compare
5173          (if_then_else:SI
5174           (match_operator 4 "comparison_operator"
5175            [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
5176             (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
5177           (match_operator:SI 5 "comparison_operator"
5178            [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
5179             (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
5180           (const_int 1))
5181          (const_int 0)))]
5182   ""
5183   "*
5185   char* opcodes[4][2] =
5186   {
5187     {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
5188     {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
5189     {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
5190     {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
5191      \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
5192   };
5193   int swap =
5194     comparison_dominates_p (GET_CODE (operands[5]),
5195                             reverse_condition (GET_CODE (operands[4])));
5197   return opcodes[which_alternative][swap];
5200 [(set_attr "conds" "set")
5201  (set_attr "length" "8")])
5203 (define_insn "*negscc"
5204   [(set (match_operand:SI 0 "s_register_operand" "=r")
5205         (neg:SI (match_operator 3 "comparison_operator"
5206                  [(match_operand:SI 1 "s_register_operand" "r")
5207                   (match_operand:SI 2 "arm_rhs_operand" "rI")])))
5208    (clobber (reg:CC 24))]
5209   ""
5210   "*
5211   if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
5212     return \"mov\\t%0, %1, asr #31\";
5214   if (GET_CODE (operands[3]) == NE)
5215     return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
5217   if (GET_CODE (operands[3]) == GT)
5218     return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
5220   output_asm_insn (\"cmp\\t%1, %2\", operands);
5221   output_asm_insn (\"mov%D3\\t%0, #0\", operands);
5222   return \"mvn%d3\\t%0, #0\";
5224 [(set_attr "conds" "clob")
5225  (set_attr "length" "12")])
5227 (define_insn "movcond"
5228   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5229         (if_then_else:SI
5230          (match_operator 5 "comparison_operator"
5231           [(match_operand:SI 3 "s_register_operand" "r,r,r")
5232            (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
5233          (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
5234          (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
5235    (clobber (reg:CC 24))]
5236   ""
5237   "*
5238   if (GET_CODE (operands[5]) == LT
5239       && (operands[4] == const0_rtx))
5240     {
5241       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
5242         {
5243           if (operands[2] == const0_rtx)
5244             return \"and\\t%0, %1, %3, asr #31\";
5245           return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
5246         }
5247       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
5248         {
5249           if (operands[1] == const0_rtx)
5250             return \"bic\\t%0, %2, %3, asr #31\";
5251           return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
5252         }
5253       /* The only case that falls through to here is when both ops 1 & 2
5254          are constants */
5255     }
5257   if (GET_CODE (operands[5]) == GE
5258       && (operands[4] == const0_rtx))
5259     {
5260       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
5261         {
5262           if (operands[2] == const0_rtx)
5263             return \"bic\\t%0, %1, %3, asr #31\";
5264           return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
5265         }
5266       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
5267         {
5268           if (operands[1] == const0_rtx)
5269             return \"and\\t%0, %2, %3, asr #31\";
5270           return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
5271         }
5272       /* The only case that falls through to here is when both ops 1 & 2
5273          are constants */
5274     }
5275   if (GET_CODE (operands[4]) == CONST_INT
5276       && !const_ok_for_arm (INTVAL (operands[4])))
5277     output_asm_insn (\"cmn\\t%3, #%n4\", operands);
5278   else
5279     output_asm_insn (\"cmp\\t%3, %4\", operands);
5280   if (which_alternative != 0)
5281     output_asm_insn (\"mov%d5\\t%0, %1\", operands);
5282   if (which_alternative != 1)
5283     output_asm_insn (\"mov%D5\\t%0, %2\", operands);
5284   return \"\";
5286 [(set_attr "conds" "clob")
5287  (set_attr "length" "8,8,12")])
5289 (define_insn "*ifcompare_plus_move"
5290   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5291         (if_then_else:SI (match_operator 6 "comparison_operator"
5292                           [(match_operand:SI 4 "s_register_operand" "r,r")
5293                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5294                          (plus:SI
5295                           (match_operand:SI 2 "s_register_operand" "r,r")
5296                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
5297                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5298    (clobber (reg:CC 24))]
5299   ""
5300   "#"
5301 [(set_attr "conds" "clob")
5302  (set_attr "length" "8,12")])
5304 (define_insn "*if_plus_move"
5305   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
5306         (if_then_else:SI
5307          (match_operator 4 "comparison_operator"
5308           [(match_operand 5 "cc_register" "") (const_int 0)])
5309          (plus:SI
5310           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
5311           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
5312          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
5313   ""
5314   "@
5315    add%d4\\t%0, %2, %3
5316    sub%d4\\t%0, %2, #%n3
5317    add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
5318    sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
5319 [(set_attr "conds" "use")
5320  (set_attr "length" "4,4,8,8")
5321  (set_attr "type" "*,*,*,*")])
5323 (define_insn "*ifcompare_move_plus"
5324   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5325         (if_then_else:SI (match_operator 6 "comparison_operator"
5326                           [(match_operand:SI 4 "s_register_operand" "r,r")
5327                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5328                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5329                          (plus:SI
5330                           (match_operand:SI 2 "s_register_operand" "r,r")
5331                           (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
5332    (clobber (reg:CC 24))]
5333   ""
5334   "#"
5335 [(set_attr "conds" "clob")
5336  (set_attr "length" "8,12")])
5338 (define_insn "*if_move_plus"
5339   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
5340         (if_then_else:SI
5341          (match_operator 4 "comparison_operator"
5342           [(match_operand 5 "cc_register" "") (const_int 0)])
5343          (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
5344          (plus:SI
5345           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
5346           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
5347   ""
5348   "@
5349    add%D4\\t%0, %2, %3
5350    sub%D4\\t%0, %2, #%n3
5351    add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
5352    sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
5353 [(set_attr "conds" "use")
5354  (set_attr "length" "4,4,8,8")
5355  (set_attr "type" "*,*,*,*")])
5357 (define_insn "*ifcompare_arith_arith"
5358   [(set (match_operand:SI 0 "s_register_operand" "=r")
5359         (if_then_else:SI (match_operator 9 "comparison_operator"
5360                           [(match_operand:SI 5 "s_register_operand" "r")
5361                            (match_operand:SI 6 "arm_add_operand" "rIL")])
5362                          (match_operator:SI 8 "shiftable_operator"
5363                           [(match_operand:SI 1 "s_register_operand" "r")
5364                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
5365                          (match_operator:SI 7 "shiftable_operator"
5366                           [(match_operand:SI 3 "s_register_operand" "r")
5367                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))
5368    (clobber (reg:CC 24))]
5369   ""
5370   "#"
5371 [(set_attr "conds" "clob")
5372  (set_attr "length" "12")])
5374 (define_insn "*if_arith_arith"
5375   [(set (match_operand:SI 0 "s_register_operand" "=r")
5376         (if_then_else:SI (match_operator 5 "comparison_operator"
5377                           [(match_operand 8 "cc_register" "") (const_int 0)])
5378                          (match_operator:SI 6 "shiftable_operator"
5379                           [(match_operand:SI 1 "s_register_operand" "r")
5380                            (match_operand:SI 2 "arm_rhs_operand" "rI")])
5381                          (match_operator:SI 7 "shiftable_operator"
5382                           [(match_operand:SI 3 "s_register_operand" "r")
5383                            (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
5384   ""
5385   "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
5386 [(set_attr "conds" "use")
5387  (set_attr "length" "8")])
5389 (define_insn "*ifcompare_arith_move"
5390   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5391         (if_then_else:SI (match_operator 6 "comparison_operator"
5392                           [(match_operand:SI 2 "s_register_operand" "r,r")
5393                            (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
5394                          (match_operator:SI 7 "shiftable_operator"
5395                           [(match_operand:SI 4 "s_register_operand" "r,r")
5396                            (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
5397                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5398    (clobber (reg:CC 24))]
5399   ""
5400   "*
5401   /* If we have an operation where (op x 0) is the identity operation and
5402      the conditional operator is LT or GE and we are comparing against zero and
5403      everything is in registers then we can do this in two instructions */
5404   if (operands[3] == const0_rtx
5405       && GET_CODE (operands[7]) != AND
5406       && GET_CODE (operands[5]) == REG
5407       && GET_CODE (operands[1]) == REG 
5408       && REGNO (operands[1]) == REGNO (operands[4])
5409       && REGNO (operands[4]) != REGNO (operands[0]))
5410     {
5411       if (GET_CODE (operands[6]) == LT)
5412         return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5413       else if (GET_CODE (operands[6]) == GE)
5414         return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5415     }
5416   if (GET_CODE (operands[3]) == CONST_INT
5417       && !const_ok_for_arm (INTVAL (operands[3])))
5418     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
5419   else
5420     output_asm_insn (\"cmp\\t%2, %3\", operands);
5421   output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
5422   if (which_alternative != 0)
5423     return \"mov%D6\\t%0, %1\";
5424   return \"\";
5426 [(set_attr "conds" "clob")
5427  (set_attr "length" "8,12")])
5429 (define_insn "*if_arith_move"
5430   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5431         (if_then_else:SI (match_operator 4 "comparison_operator"
5432                           [(match_operand 6 "cc_register" "") (const_int 0)])
5433                          (match_operator:SI 5 "shiftable_operator"
5434                           [(match_operand:SI 2 "s_register_operand" "r,r")
5435                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
5436                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
5437   ""
5438   "@
5439    %I5%d4\\t%0, %2, %3
5440    %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
5441 [(set_attr "conds" "use")
5442  (set_attr "length" "4,8")
5443  (set_attr "type" "*,*")])
5445 (define_insn "*ifcompare_move_arith"
5446   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5447         (if_then_else:SI (match_operator 6 "comparison_operator"
5448                           [(match_operand:SI 4 "s_register_operand" "r,r")
5449                            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5450                          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5451                          (match_operator:SI 7 "shiftable_operator"
5452                           [(match_operand:SI 2 "s_register_operand" "r,r")
5453                            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
5454    (clobber (reg:CC 24))]
5455   ""
5456   "*
5457   /* If we have an operation where (op x 0) is the identity operation and
5458      the conditional operator is LT or GE and we are comparing against zero and
5459      everything is in registers then we can do this in two instructions */
5460   if (operands[5] == const0_rtx
5461       && GET_CODE (operands[7]) != AND
5462       && GET_CODE (operands[3]) == REG
5463       && GET_CODE (operands[1]) == REG 
5464       && REGNO (operands[1]) == REGNO (operands[2])
5465       && REGNO (operands[2]) != REGNO (operands[0]))
5466     {
5467       if (GET_CODE (operands[6]) == GE)
5468         return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5469       else if (GET_CODE (operands[6]) == LT)
5470         return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5471     }
5473   if (GET_CODE (operands[5]) == CONST_INT
5474       && !const_ok_for_arm (INTVAL (operands[5])))
5475     output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5476   else
5477     output_asm_insn (\"cmp\\t%4, %5\", operands);
5479   if (which_alternative != 0)
5480     output_asm_insn (\"mov%d6\\t%0, %1\", operands);
5481   return \"%I7%D6\\t%0, %2, %3\";
5483 [(set_attr "conds" "clob")
5484  (set_attr "length" "8,12")])
5486 (define_insn "*if_move_arith"
5487   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5488         (if_then_else:SI
5489          (match_operator 4 "comparison_operator"
5490           [(match_operand 6 "cc_register" "") (const_int 0)])
5491          (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5492          (match_operator:SI 5 "shiftable_operator"
5493           [(match_operand:SI 2 "s_register_operand" "r,r")
5494            (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
5495   ""
5496   "@
5497    %I5%D4\\t%0, %2, %3
5498    %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
5499 [(set_attr "conds" "use")
5500  (set_attr "length" "4,8")
5501  (set_attr "type" "*,*")])
5503 (define_insn "*ifcompare_move_not"
5504   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5505         (if_then_else:SI
5506          (match_operator 5 "comparison_operator"
5507           [(match_operand:SI 3 "s_register_operand" "r,r")
5508            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5509          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5510          (not:SI
5511           (match_operand:SI 2 "s_register_operand" "r,r"))))
5512    (clobber (reg:CC 24))]
5513   ""
5514   "#"
5515 [(set_attr "conds" "clob")
5516  (set_attr "length" "8,12")])
5518 (define_insn "*if_move_not"
5519   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5520         (if_then_else:SI
5521          (match_operator 4 "comparison_operator"
5522           [(match_operand 3 "cc_register" "") (const_int 0)])
5523          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5524          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5525   ""
5526   "@
5527    mvn%D4\\t%0, %2
5528    mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
5529    mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
5530 [(set_attr "conds" "use")
5531  (set_attr "length" "4,8,8")])
5533 (define_insn "*ifcompare_not_move"
5534   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5535         (if_then_else:SI 
5536          (match_operator 5 "comparison_operator"
5537           [(match_operand:SI 3 "s_register_operand" "r,r")
5538            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5539          (not:SI
5540           (match_operand:SI 2 "s_register_operand" "r,r"))
5541          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5542    (clobber (reg:CC 24))]
5543   ""
5544   "#"
5545 [(set_attr "conds" "clob")
5546  (set_attr "length" "8,12")])
5548 (define_insn "*if_not_move"
5549   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5550         (if_then_else:SI
5551          (match_operator 4 "comparison_operator"
5552           [(match_operand 3 "cc_register" "") (const_int 0)])
5553          (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5554          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5555   ""
5556   "@
5557    mvn%d4\\t%0, %2
5558    mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
5559    mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
5560 [(set_attr "conds" "use")
5561  (set_attr "length" "4,8,8")])
5563 (define_insn "*ifcompare_shift_move"
5564   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5565         (if_then_else:SI
5566          (match_operator 6 "comparison_operator"
5567           [(match_operand:SI 4 "s_register_operand" "r,r")
5568            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5569          (match_operator:SI 7 "shift_operator"
5570           [(match_operand:SI 2 "s_register_operand" "r,r")
5571            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
5572          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5573    (clobber (reg:CC 24))]
5574   ""
5575   "#"
5576 [(set_attr "conds" "clob")
5577  (set_attr "length" "8,12")])
5579 (define_insn "*if_shift_move"
5580   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5581         (if_then_else:SI
5582          (match_operator 5 "comparison_operator"
5583           [(match_operand 6 "cc_register" "") (const_int 0)])
5584          (match_operator:SI 4 "shift_operator"
5585           [(match_operand:SI 2 "s_register_operand" "r,r,r")
5586            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
5587          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5588   ""
5589   "@
5590    mov%d5\\t%0, %2%S4
5591    mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
5592    mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
5593 [(set_attr "conds" "use")
5594  (set_attr "length" "4,8,8")])
5596 (define_insn "*ifcompare_move_shift"
5597   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5598         (if_then_else:SI
5599          (match_operator 6 "comparison_operator"
5600           [(match_operand:SI 4 "s_register_operand" "r,r")
5601            (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5602          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5603          (match_operator:SI 7 "shift_operator"
5604           [(match_operand:SI 2 "s_register_operand" "r,r")
5605            (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
5606    (clobber (reg:CC 24))]
5607   ""
5608   "#"
5609 [(set_attr "conds" "clob")
5610  (set_attr "length" "8,12")])
5612 (define_insn "*if_move_shift"
5613   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5614         (if_then_else:SI
5615          (match_operator 5 "comparison_operator"
5616           [(match_operand 6 "cc_register" "") (const_int 0)])
5617          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5618          (match_operator:SI 4 "shift_operator"
5619           [(match_operand:SI 2 "s_register_operand" "r,r,r")
5620            (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
5621   ""
5622   "@
5623    mov%D5\\t%0, %2%S4
5624    mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
5625    mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
5626 [(set_attr "conds" "use")
5627  (set_attr "length" "4,8,8")])
5629 (define_insn "*ifcompare_shift_shift"
5630   [(set (match_operand:SI 0 "s_register_operand" "=r")
5631         (if_then_else:SI
5632          (match_operator 7 "comparison_operator"
5633           [(match_operand:SI 5 "s_register_operand" "r")
5634            (match_operand:SI 6 "arm_add_operand" "rIL")])
5635          (match_operator:SI 8 "shift_operator"
5636           [(match_operand:SI 1 "s_register_operand" "r")
5637            (match_operand:SI 2 "arm_rhs_operand" "rM")])
5638          (match_operator:SI 9 "shift_operator"
5639           [(match_operand:SI 3 "s_register_operand" "r")
5640            (match_operand:SI 4 "arm_rhs_operand" "rM")])))
5641    (clobber (reg:CC 24))]
5642   ""
5643   "#"
5644 [(set_attr "conds" "clob")
5645  (set_attr "length" "12")])
5647 (define_insn "*if_shift_shift"
5648   [(set (match_operand:SI 0 "s_register_operand" "=r")
5649         (if_then_else:SI
5650          (match_operator 5 "comparison_operator"
5651           [(match_operand 8 "cc_register" "") (const_int 0)])
5652          (match_operator:SI 6 "shift_operator"
5653           [(match_operand:SI 1 "s_register_operand" "r")
5654            (match_operand:SI 2 "arm_rhs_operand" "rM")])
5655          (match_operator:SI 7 "shift_operator"
5656           [(match_operand:SI 3 "s_register_operand" "r")
5657            (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
5658   ""
5659   "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
5660 [(set_attr "conds" "use")
5661  (set_attr "length" "8")])
5663 (define_insn "*ifcompare_not_arith"
5664   [(set (match_operand:SI 0 "s_register_operand" "=r")
5665         (if_then_else:SI
5666          (match_operator 6 "comparison_operator"
5667           [(match_operand:SI 4 "s_register_operand" "r")
5668            (match_operand:SI 5 "arm_add_operand" "rIL")])
5669          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5670          (match_operator:SI 7 "shiftable_operator"
5671           [(match_operand:SI 2 "s_register_operand" "r")
5672            (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5673    (clobber (reg:CC 24))]
5674   ""
5675   "#"
5676 [(set_attr "conds" "clob")
5677  (set_attr "length" "12")])
5679 (define_insn "*if_not_arith"
5680   [(set (match_operand:SI 0 "s_register_operand" "=r")
5681         (if_then_else:SI
5682          (match_operator 5 "comparison_operator"
5683           [(match_operand 4 "cc_register" "") (const_int 0)])
5684          (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5685          (match_operator:SI 6 "shiftable_operator"
5686           [(match_operand:SI 2 "s_register_operand" "r")
5687            (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
5688   ""
5689   "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
5690 [(set_attr "conds" "use")
5691  (set_attr "length" "8")])
5693 (define_insn "*ifcompare_arith_not"
5694   [(set (match_operand:SI 0 "s_register_operand" "=r")
5695         (if_then_else:SI
5696          (match_operator 6 "comparison_operator"
5697           [(match_operand:SI 4 "s_register_operand" "r")
5698            (match_operand:SI 5 "arm_add_operand" "rIL")])
5699          (match_operator:SI 7 "shiftable_operator"
5700           [(match_operand:SI 2 "s_register_operand" "r")
5701            (match_operand:SI 3 "arm_rhs_operand" "rI")])
5702          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5703    (clobber (reg:CC 24))]
5704   ""
5705   "#"
5706 [(set_attr "conds" "clob")
5707  (set_attr "length" "12")])
5709 (define_insn "*if_arith_not"
5710   [(set (match_operand:SI 0 "s_register_operand" "=r")
5711         (if_then_else:SI
5712          (match_operator 5 "comparison_operator"
5713           [(match_operand 4 "cc_register" "") (const_int 0)])
5714          (match_operator:SI 6 "shiftable_operator"
5715           [(match_operand:SI 2 "s_register_operand" "r")
5716            (match_operand:SI 3 "arm_rhs_operand" "rI")])
5717          (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
5718   ""
5719   "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
5720 [(set_attr "conds" "use")
5721  (set_attr "length" "8")])
5723 (define_insn "*ifcompare_neg_move"
5724   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5725         (if_then_else:SI
5726          (match_operator 5 "comparison_operator"
5727           [(match_operand:SI 3 "s_register_operand" "r,r")
5728            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5729          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
5730          (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5731    (clobber (reg:CC 24))]
5732   ""
5733   "#"
5734 [(set_attr "conds" "clob")
5735  (set_attr "length" "8,12")])
5737 (define_insn "*if_neg_move"
5738   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5739         (if_then_else:SI
5740          (match_operator 4 "comparison_operator"
5741           [(match_operand 3 "cc_register" "") (const_int 0)])
5742          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5743          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5744   ""
5745   "@
5746    rsb%d4\\t%0, %2, #0
5747    mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
5748    mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
5749 [(set_attr "conds" "use")
5750  (set_attr "length" "4,8,8")])
5752 (define_insn "*ifcompare_move_neg"
5753   [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5754         (if_then_else:SI
5755          (match_operator 5 "comparison_operator"
5756           [(match_operand:SI 3 "s_register_operand" "r,r")
5757            (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5758          (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5759          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
5760    (clobber (reg:CC 24))]
5761   ""
5762   "#"
5763 [(set_attr "conds" "clob")
5764  (set_attr "length" "8,12")])
5766 (define_insn "*if_move_neg"
5767   [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5768         (if_then_else:SI
5769          (match_operator 4 "comparison_operator"
5770           [(match_operand 3 "cc_register" "") (const_int 0)])
5771          (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5772          (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5773   ""
5774   "@
5775    rsb%D4\\t%0, %2, #0
5776    mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
5777    mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
5778 [(set_attr "conds" "use")
5779  (set_attr "length" "4,8,8")])
5781 (define_insn "*arith_adjacentmem"
5782   [(set (match_operand:SI 0 "s_register_operand" "=r")
5783         (match_operator:SI 1 "shiftable_operator"
5784          [(match_operand:SI 2 "memory_operand" "m")
5785           (match_operand:SI 3 "memory_operand" "m")]))
5786    (clobber (match_scratch:SI 4 "=r"))]
5787   "adjacent_mem_locations (operands[2], operands[3])"
5788   "*
5790   rtx ldm[3];
5791   rtx arith[4];
5792   int val1 = 0, val2 = 0;
5794   if (REGNO (operands[0]) > REGNO (operands[4]))
5795     {
5796       ldm[1] = operands[4];
5797       ldm[2] = operands[0];
5798     }
5799   else
5800     {
5801       ldm[1] = operands[0];
5802       ldm[2] = operands[4];
5803     }
5804   if (GET_CODE (XEXP (operands[2], 0)) != REG)
5805     val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5806   if (GET_CODE (XEXP (operands[3], 0)) != REG)
5807     val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5808   arith[0] = operands[0];
5809   arith[3] = operands[1];
5810   if (val1 < val2)
5811     {
5812       arith[1] = ldm[1];
5813       arith[2] = ldm[2];
5814     }
5815   else
5816     {
5817       arith[1] = ldm[2];
5818       arith[2] = ldm[1];
5819     }
5820   if (val1 && val2)
5821     {
5822       rtx ops[3];
5823       ldm[0] = ops[0] = operands[4];
5824       ops[1] = XEXP (XEXP (operands[2], 0), 0);
5825       ops[2] = XEXP (XEXP (operands[2], 0), 1);
5826       output_add_immediate (ops);
5827       if (val1 < val2)
5828         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5829       else
5830         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5831     }
5832   else if (val1)
5833     {
5834       ldm[0] = XEXP (operands[3], 0);
5835       if (val1 < val2)
5836         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5837       else
5838         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5839     }
5840   else
5841     {
5842       ldm[0] = XEXP (operands[2], 0);
5843       if (val1 < val2)
5844         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5845       else
5846         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5847     }
5848   output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
5849   return \"\";
5852 [(set_attr "length" "12")
5853  (set_attr "type" "load")])
5855 ;; the arm can support extended pre-inc instructions
5857 ;; In all these cases, we use operands 0 and 1 for the register being
5858 ;; incremented because those are the operands that local-alloc will
5859 ;; tie and these are the pair most likely to be tieable (and the ones
5860 ;; that will benefit the most).
5862 ;; We reject the frame pointer if it occurs anywhere in these patterns since
5863 ;; elimination will cause too many headaches.
5865 (define_insn "*strqi_preinc"
5866   [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5867                          (match_operand:SI 2 "index_operand" "rJ")))
5868         (match_operand:QI 3 "s_register_operand" "r"))
5869    (set (match_operand:SI 0 "s_register_operand" "=r")
5870         (plus:SI (match_dup 1) (match_dup 2)))]
5871   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5872    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5873    && (GET_CODE (operands[2]) != REG
5874        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5875   "str%?b\\t%3, [%0, %2]!"
5876 [(set_attr "type" "store1")])
5878 (define_insn "*strqi_predec"
5879   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5880                           (match_operand:SI 2 "s_register_operand" "r")))
5881         (match_operand:QI 3 "s_register_operand" "r"))
5882    (set (match_operand:SI 0 "s_register_operand" "=r")
5883         (minus:SI (match_dup 1) (match_dup 2)))]
5884   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5885    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5886    && (GET_CODE (operands[2]) != REG
5887        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5888   "str%?b\\t%3, [%0, -%2]!"
5889 [(set_attr "type" "store1")])
5891 (define_insn "*loadqi_preinc"
5892   [(set (match_operand:QI 3 "s_register_operand" "=r")
5893         (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5894                          (match_operand:SI 2 "index_operand" "rJ"))))
5895    (set (match_operand:SI 0 "s_register_operand" "=r")
5896         (plus:SI (match_dup 1) (match_dup 2)))]
5897   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5898    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5899    && (GET_CODE (operands[2]) != REG
5900        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5901   "ldr%?b\\t%3, [%0, %2]!"
5902 [(set_attr "type" "load")])
5904 (define_insn "*loadqi_predec"
5905   [(set (match_operand:QI 3 "s_register_operand" "=r")
5906         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5907                           (match_operand:SI 2 "s_register_operand" "r"))))
5908    (set (match_operand:SI 0 "s_register_operand" "=r")
5909         (minus:SI (match_dup 1) (match_dup 2)))]
5910   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5911    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5912    && (GET_CODE (operands[2]) != REG
5913        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5914   "ldr%?b\\t%3, [%0, -%2]!"
5915 [(set_attr "type" "load")])
5917 (define_insn "*loadqisi_preinc"
5918   [(set (match_operand:SI 3 "s_register_operand" "=r")
5919         (zero_extend:SI
5920          (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5921                           (match_operand:SI 2 "index_operand" "rJ")))))
5922    (set (match_operand:SI 0 "s_register_operand" "=r")
5923         (plus:SI (match_dup 1) (match_dup 2)))]
5924   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5925    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5926    && (GET_CODE (operands[2]) != REG
5927        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5928   "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
5929 [(set_attr "type" "load")])
5931 (define_insn "*loadqisi_predec"
5932   [(set (match_operand:SI 3 "s_register_operand" "=r")
5933         (zero_extend:SI
5934          (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5935                            (match_operand:SI 2 "s_register_operand" "r")))))
5936    (set (match_operand:SI 0 "s_register_operand" "=r")
5937         (minus:SI (match_dup 1) (match_dup 2)))]
5938   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5939    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5940    && (GET_CODE (operands[2]) != REG
5941        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5942   "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
5943 [(set_attr "type" "load")])
5945 (define_insn "*strsi_preinc"
5946   [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5947                          (match_operand:SI 2 "index_operand" "rJ")))
5948         (match_operand:SI 3 "s_register_operand" "r"))
5949    (set (match_operand:SI 0 "s_register_operand" "=r")
5950         (plus:SI (match_dup 1) (match_dup 2)))]
5951   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5952    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5953    && (GET_CODE (operands[2]) != REG
5954        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5955   "str%?\\t%3, [%0, %2]!"
5956 [(set_attr "type" "store1")])
5958 (define_insn "*strsi_predec"
5959   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5960                           (match_operand:SI 2 "s_register_operand" "r")))
5961         (match_operand:SI 3 "s_register_operand" "r"))
5962    (set (match_operand:SI 0 "s_register_operand" "=r")
5963         (minus:SI (match_dup 1) (match_dup 2)))]
5964   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5965    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5966    && (GET_CODE (operands[2]) != REG
5967        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5968   "str%?\\t%3, [%0, -%2]!"
5969 [(set_attr "type" "store1")])
5971 (define_insn "*loadsi_preinc"
5972   [(set (match_operand:SI 3 "s_register_operand" "=r")
5973         (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5974                          (match_operand:SI 2 "index_operand" "rJ"))))
5975    (set (match_operand:SI 0 "s_register_operand" "=r")
5976         (plus:SI (match_dup 1) (match_dup 2)))]
5977   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5978    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5979    && (GET_CODE (operands[2]) != REG
5980        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5981   "ldr%?\\t%3, [%0, %2]!"
5982 [(set_attr "type" "load")])
5984 (define_insn "*loadsi_predec"
5985   [(set (match_operand:SI 3 "s_register_operand" "=r")
5986         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5987                           (match_operand:SI 2 "s_register_operand" "r"))))
5988    (set (match_operand:SI 0 "s_register_operand" "=r")
5989         (minus:SI (match_dup 1) (match_dup 2)))]
5990   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5991    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5992    && (GET_CODE (operands[2]) != REG
5993        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5994   "ldr%?\\t%3, [%0, -%2]!"
5995 [(set_attr "type" "load")])
5997 (define_insn "*loadhi_preinc"
5998   [(set (match_operand:HI 3 "s_register_operand" "=r")
5999         (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
6000                          (match_operand:SI 2 "index_operand" "rJ"))))
6001    (set (match_operand:SI 0 "s_register_operand" "=r")
6002         (plus:SI (match_dup 1) (match_dup 2)))]
6003   "(! BYTES_BIG_ENDIAN)
6004    && ! TARGET_MMU_TRAPS
6005    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
6006    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6007    && (GET_CODE (operands[2]) != REG
6008        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
6009   "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
6010 [(set_attr "type" "load")])
6012 (define_insn "*loadhi_predec"
6013   [(set (match_operand:HI 3 "s_register_operand" "=r")
6014         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
6015                           (match_operand:SI 2 "s_register_operand" "r"))))
6016    (set (match_operand:SI 0 "s_register_operand" "=r")
6017         (minus:SI (match_dup 1) (match_dup 2)))]
6018   "(!BYTES_BIG_ENDIAN)
6019    && ! TARGET_MMU_TRAPS
6020    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
6021    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6022    && (GET_CODE (operands[2]) != REG
6023        || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
6024   "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
6025 [(set_attr "type" "load")])
6027 (define_insn "*strqi_shiftpreinc"
6028   [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
6029                           [(match_operand:SI 3 "s_register_operand" "r")
6030                            (match_operand:SI 4 "const_shift_operand" "n")])
6031                          (match_operand:SI 1 "s_register_operand" "0")))
6032         (match_operand:QI 5 "s_register_operand" "r"))
6033    (set (match_operand:SI 0 "s_register_operand" "=r")
6034         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6035                  (match_dup 1)))]
6036   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6037    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6038    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6039   "str%?b\\t%5, [%0, %3%S2]!"
6040 [(set_attr "type" "store1")])
6042 (define_insn "*strqi_shiftpredec"
6043   [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
6044                           (match_operator:SI 2 "shift_operator"
6045                            [(match_operand:SI 3 "s_register_operand" "r")
6046                             (match_operand:SI 4 "const_shift_operand" "n")])))
6047         (match_operand:QI 5 "s_register_operand" "r"))
6048    (set (match_operand:SI 0 "s_register_operand" "=r")
6049         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6050                                                  (match_dup 4)])))]
6051   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6052    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6053    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6054   "str%?b\\t%5, [%0, -%3%S2]!"
6055 [(set_attr "type" "store1")])
6057 (define_insn "*loadqi_shiftpreinc"
6058   [(set (match_operand:QI 5 "s_register_operand" "=r")
6059         (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
6060                           [(match_operand:SI 3 "s_register_operand" "r")
6061                            (match_operand:SI 4 "const_shift_operand" "n")])
6062                          (match_operand:SI 1 "s_register_operand" "0"))))
6063    (set (match_operand:SI 0 "s_register_operand" "=r")
6064         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6065                  (match_dup 1)))]
6066   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6067    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6068    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6069   "ldr%?b\\t%5, [%0, %3%S2]!"
6070 [(set_attr "type" "load")])
6072 (define_insn "*loadqi_shiftpredec"
6073   [(set (match_operand:QI 5 "s_register_operand" "=r")
6074         (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
6075                           (match_operator:SI 2 "shift_operator"
6076                            [(match_operand:SI 3 "s_register_operand" "r")
6077                             (match_operand:SI 4 "const_shift_operand" "n")]))))
6078    (set (match_operand:SI 0 "s_register_operand" "=r")
6079         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6080                                                  (match_dup 4)])))]
6081   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6082    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6083    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6084   "ldr%?b\\t%5, [%0, -%3%S2]!"
6085 [(set_attr "type" "load")])
6087 (define_insn "*strsi_shiftpreinc"
6088   [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
6089                           [(match_operand:SI 3 "s_register_operand" "r")
6090                            (match_operand:SI 4 "const_shift_operand" "n")])
6091                          (match_operand:SI 1 "s_register_operand" "0")))
6092         (match_operand:SI 5 "s_register_operand" "r"))
6093    (set (match_operand:SI 0 "s_register_operand" "=r")
6094         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6095                  (match_dup 1)))]
6096   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6097    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6098    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6099   "str%?\\t%5, [%0, %3%S2]!"
6100 [(set_attr "type" "store1")])
6102 (define_insn "*strsi_shiftpredec"
6103   [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
6104                           (match_operator:SI 2 "shift_operator"
6105                            [(match_operand:SI 3 "s_register_operand" "r")
6106                             (match_operand:SI 4 "const_shift_operand" "n")])))
6107         (match_operand:SI 5 "s_register_operand" "r"))
6108    (set (match_operand:SI 0 "s_register_operand" "=r")
6109         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6110                                                  (match_dup 4)])))]
6111   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6112    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6113    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6114   "str%?\\t%5, [%0, -%3%S2]!"
6115 [(set_attr "type" "store1")])
6117 (define_insn "*loadsi_shiftpreinc"
6118   [(set (match_operand:SI 5 "s_register_operand" "=r")
6119         (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
6120                           [(match_operand:SI 3 "s_register_operand" "r")
6121                            (match_operand:SI 4 "const_shift_operand" "n")])
6122                          (match_operand:SI 1 "s_register_operand" "0"))))
6123    (set (match_operand:SI 0 "s_register_operand" "=r")
6124         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6125                  (match_dup 1)))]
6126   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6127    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6128    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6129   "ldr%?\\t%5, [%0, %3%S2]!"
6130 [(set_attr "type" "load")])
6132 (define_insn "*loadsi_shiftpredec"
6133   [(set (match_operand:SI 5 "s_register_operand" "=r")
6134         (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
6135                           (match_operator:SI 2 "shift_operator"
6136                            [(match_operand:SI 3 "s_register_operand" "r")
6137                             (match_operand:SI 4 "const_shift_operand" "n")]))))
6138    (set (match_operand:SI 0 "s_register_operand" "=r")
6139         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6140                                                  (match_dup 4)])))]
6141   "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6142    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6143    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6144   "ldr%?\\t%5, [%0, -%3%S2]!"
6145 [(set_attr "type" "load")])
6147 (define_insn "*loadhi_shiftpreinc"
6148   [(set (match_operand:HI 5 "s_register_operand" "=r")
6149         (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
6150                           [(match_operand:SI 3 "s_register_operand" "r")
6151                            (match_operand:SI 4 "const_shift_operand" "n")])
6152                          (match_operand:SI 1 "s_register_operand" "0"))))
6153    (set (match_operand:SI 0 "s_register_operand" "=r")
6154         (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6155                  (match_dup 1)))]
6156   "(! BYTES_BIG_ENDIAN)
6157    && ! TARGET_MMU_TRAPS
6158    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
6159    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6160    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6161   "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
6162 [(set_attr "type" "load")])
6164 (define_insn "*loadhi_shiftpredec"
6165   [(set (match_operand:HI 5 "s_register_operand" "=r")
6166         (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
6167                           (match_operator:SI 2 "shift_operator"
6168                            [(match_operand:SI 3 "s_register_operand" "r")
6169                             (match_operand:SI 4 "const_shift_operand" "n")]))))
6170    (set (match_operand:SI 0 "s_register_operand" "=r")
6171         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6172                                                  (match_dup 4)])))]
6173   "(! BYTES_BIG_ENDIAN)
6174    && ! TARGET_MMU_TRAPS
6175    && REGNO (operands[0]) != FRAME_POINTER_REGNUM
6176    && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6177    && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6178   "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
6179 [(set_attr "type" "load")])
6181 ; It can also support extended post-inc expressions, but combine doesn't
6182 ; try these....
6183 ; It doesn't seem worth adding peepholes for anything but the most common
6184 ; cases since, unlike combine, the increment must immediately follow the load
6185 ; for this pattern to match.
6186 ; When loading we must watch to see that the base register isn't trampled by
6187 ; the load.  In such cases this isn't a post-inc expression.
6189 (define_peephole
6190   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
6191         (match_operand:QI 2 "s_register_operand" "r"))
6192    (set (match_dup 0)
6193         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
6194   ""
6195   "str%?b\\t%2, [%0], %1")
6197 (define_peephole
6198   [(set (match_operand:QI 0 "s_register_operand" "=r")
6199         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
6200    (set (match_dup 1)
6201         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
6202   "REGNO(operands[0]) != REGNO(operands[1])
6203    && (GET_CODE (operands[2]) != REG
6204        || REGNO(operands[0]) != REGNO (operands[2]))"
6205   "ldr%?b\\t%0, [%1], %2")
6207 (define_peephole
6208   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
6209         (match_operand:SI 2 "s_register_operand" "r"))
6210    (set (match_dup 0)
6211         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
6212   ""
6213   "str%?\\t%2, [%0], %1")
6215 (define_peephole
6216   [(set (match_operand:HI 0 "s_register_operand" "=r")
6217         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
6218    (set (match_dup 1)
6219         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
6220   "(! BYTES_BIG_ENDIAN)
6221    && ! TARGET_MMU_TRAPS
6222    && REGNO(operands[0]) != REGNO(operands[1])
6223    && (GET_CODE (operands[2]) != REG
6224        || REGNO(operands[0]) != REGNO (operands[2]))"
6225   "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
6227 (define_peephole
6228   [(set (match_operand:SI 0 "s_register_operand" "=r")
6229         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
6230    (set (match_dup 1)
6231         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
6232   "REGNO(operands[0]) != REGNO(operands[1])
6233    && (GET_CODE (operands[2]) != REG
6234        || REGNO(operands[0]) != REGNO (operands[2]))"
6235   "ldr%?\\t%0, [%1], %2")
6237 (define_peephole
6238   [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
6239                          (match_operand:SI 1 "index_operand" "rJ")))
6240         (match_operand:QI 2 "s_register_operand" "r"))
6241    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
6242   ""
6243   "str%?b\\t%2, [%0, %1]!")
6245 (define_peephole
6246   [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
6247                           [(match_operand:SI 0 "s_register_operand" "r")
6248                            (match_operand:SI 1 "const_int_operand" "n")])
6249                          (match_operand:SI 2 "s_register_operand" "+r")))
6250         (match_operand:QI 3 "s_register_operand" "r"))
6251    (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
6252                                (match_dup 2)))]
6253   ""
6254   "str%?b\\t%3, [%2, %0%S4]!")
6256 ; This pattern is never tried by combine, so do it as a peephole
6258 (define_peephole
6259   [(set (match_operand:SI 0 "s_register_operand" "=r")
6260         (match_operand:SI 1 "s_register_operand" "r"))
6261    (set (reg:CC 24)
6262         (compare:CC (match_dup 1) (const_int 0)))]
6263   ""
6264   "sub%?s\\t%0, %1, #0"
6265 [(set_attr "conds" "set")])
6267 ; Peepholes to spot possible load- and store-multiples, if the ordering is
6268 ; reversed, check that the memory references aren't volatile.
6270 (define_peephole
6271   [(set (match_operand:SI 0 "s_register_operand" "=r")
6272         (match_operand:SI 4 "memory_operand" "m"))
6273    (set (match_operand:SI 1 "s_register_operand" "=r")
6274         (match_operand:SI 5 "memory_operand" "m"))
6275    (set (match_operand:SI 2 "s_register_operand" "=r")
6276         (match_operand:SI 6 "memory_operand" "m"))
6277    (set (match_operand:SI 3 "s_register_operand" "=r")
6278         (match_operand:SI 7 "memory_operand" "m"))]
6279   "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
6280   "*
6281   return emit_ldm_seq (operands, 4);
6284 (define_peephole
6285   [(set (match_operand:SI 0 "s_register_operand" "=r")
6286         (match_operand:SI 3 "memory_operand" "m"))
6287    (set (match_operand:SI 1 "s_register_operand" "=r")
6288         (match_operand:SI 4 "memory_operand" "m"))
6289    (set (match_operand:SI 2 "s_register_operand" "=r")
6290         (match_operand:SI 5 "memory_operand" "m"))]
6291   "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
6292   "*
6293   return emit_ldm_seq (operands, 3);
6296 (define_peephole
6297   [(set (match_operand:SI 0 "s_register_operand" "=r")
6298         (match_operand:SI 2 "memory_operand" "m"))
6299    (set (match_operand:SI 1 "s_register_operand" "=r")
6300         (match_operand:SI 3 "memory_operand" "m"))]
6301   "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
6302   "*
6303   return emit_ldm_seq (operands, 2);
6306 (define_peephole
6307   [(set (match_operand:SI 4 "memory_operand" "=m")
6308         (match_operand:SI 0 "s_register_operand" "r"))
6309    (set (match_operand:SI 5 "memory_operand" "=m")
6310         (match_operand:SI 1 "s_register_operand" "r"))
6311    (set (match_operand:SI 6 "memory_operand" "=m")
6312         (match_operand:SI 2 "s_register_operand" "r"))
6313    (set (match_operand:SI 7 "memory_operand" "=m")
6314         (match_operand:SI 3 "s_register_operand" "r"))]
6315   "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
6316   "*
6317   return emit_stm_seq (operands, 4);
6320 (define_peephole
6321   [(set (match_operand:SI 3 "memory_operand" "=m")
6322         (match_operand:SI 0 "s_register_operand" "r"))
6323    (set (match_operand:SI 4 "memory_operand" "=m")
6324         (match_operand:SI 1 "s_register_operand" "r"))
6325    (set (match_operand:SI 5 "memory_operand" "=m")
6326         (match_operand:SI 2 "s_register_operand" "r"))]
6327   "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
6328   "*
6329   return emit_stm_seq (operands, 3);
6332 (define_peephole
6333   [(set (match_operand:SI 2 "memory_operand" "=m")
6334         (match_operand:SI 0 "s_register_operand" "r"))
6335    (set (match_operand:SI 3 "memory_operand" "=m")
6336         (match_operand:SI 1 "s_register_operand" "r"))]
6337   "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
6338   "*
6339   return emit_stm_seq (operands, 2);
6342 ;; A call followed by return can be replaced by restoring the regs and
6343 ;; jumping to the subroutine, provided we aren't passing the address of
6344 ;; any of our local variables.  If we call alloca then this is unsafe
6345 ;; since restoring the frame frees the memory, which is not what we want.
6346 ;; Sometimes the return might have been targeted by the final prescan:
6347 ;; if so then emit a proper return insn as well.
6348 ;; Unfortunately, if the frame pointer is required, we don't know if the
6349 ;; current function has any implicit stack pointer adjustments that will 
6350 ;; be restored by the return: we can't therefore do a tail call.
6351 ;; Another unfortunate that we can't handle is if current_function_args_size
6352 ;; is non-zero: in this case elimination of the argument pointer assumed
6353 ;; that lr was pushed onto the stack, so eliminating upsets the offset
6354 ;; calculations.
6356 (define_peephole
6357   [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
6358                           (match_operand:SI 1 "general_operand" "g"))
6359                     (clobber (reg:SI 14))])
6360    (return)]
6361   "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN (FALSE)
6362     && !get_frame_size () && !current_function_calls_alloca
6363     && !frame_pointer_needed && !current_function_args_size)"
6364   "*
6366   extern rtx arm_target_insn;
6367   extern int arm_ccfsm_state;
6369   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6370   {
6371     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6372     output_return_instruction (NULL, TRUE, FALSE);
6373     arm_ccfsm_state = 0;
6374     arm_target_insn = NULL;
6375   }
6377   output_return_instruction (NULL, FALSE, FALSE);
6378   return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6380 [(set_attr "type" "call")
6381  (set_attr "length" "8")])
6383 (define_peephole
6384   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6385                    (call (mem:SI (match_operand:SI 1 "" "X"))
6386                          (match_operand:SI 2 "general_operand" "g")))
6387               (clobber (reg:SI 14))])
6388    (return)]
6389   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN (FALSE)
6390     && !get_frame_size () && !current_function_calls_alloca
6391     && !frame_pointer_needed && !current_function_args_size)"
6392   "*
6394   extern rtx arm_target_insn;
6395   extern int arm_ccfsm_state;
6397   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6398   {
6399     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6400     output_return_instruction (NULL, TRUE, FALSE);
6401     arm_ccfsm_state = 0;
6402     arm_target_insn = NULL;
6403   }
6405   output_return_instruction (NULL, FALSE, FALSE);
6406   return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6408 [(set_attr "type" "call")
6409  (set_attr "length" "8")])
6411 ;; As above but when this function is not void, we must be returning the
6412 ;; result of the called subroutine.
6414 (define_peephole
6415   [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6416                    (call (mem:SI (match_operand:SI 1 "" "X"))
6417                          (match_operand:SI 2 "general_operand" "g")))
6418               (clobber (reg:SI 14))])
6419    (use (match_dup 0))
6420    (return)]
6421   "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN (FALSE)
6422     && !get_frame_size () && !current_function_calls_alloca
6423     && !frame_pointer_needed && !current_function_args_size)"
6424   "*
6426   extern rtx arm_target_insn;
6427   extern int arm_ccfsm_state;
6429   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6430   {
6431     arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6432     output_return_instruction (NULL, TRUE, FALSE);
6433     arm_ccfsm_state = 0;
6434     arm_target_insn = NULL;
6435   }
6437   output_return_instruction (NULL, FALSE, FALSE);
6438   return \"b%?\\t%a1\";
6440 [(set_attr "type" "call")
6441  (set_attr "length" "8")])
6443 (define_split
6444   [(set (match_operand:SI 0 "s_register_operand" "")
6445         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
6446                        (const_int 0))
6447                 (neg:SI (match_operator:SI 2 "comparison_operator"
6448                          [(match_operand:SI 3 "s_register_operand" "")
6449                           (match_operand:SI 4 "arm_rhs_operand" "")]))))
6450    (clobber (match_operand:SI 5 "s_register_operand" ""))]
6451   ""
6452   [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
6453    (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6454                               (match_dup 5)))]
6455   "")
6457 ;; This split can be used because CC_Z mode implies that the following
6458 ;; branch will be an equality, or an unsigned inequality, so the sign
6459 ;; extension is not needed.
6461 (define_split
6462   [(set (reg:CC_Z 24)
6463         (compare:CC_Z
6464          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
6465                     (const_int 24))
6466          (match_operand 1 "const_int_operand" "")))
6467    (clobber (match_scratch:SI 2 ""))]
6468   "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
6469    == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
6470   [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
6471    (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
6472   "
6473   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
6476 (define_expand "prologue"
6477   [(clobber (const_int 0))]
6478   ""
6479   "
6480   arm_expand_prologue ();
6481   DONE;
6484 (define_expand "epilogue"
6485   [(unspec_volatile [(return)] 6)]
6486   ""
6487   "
6488   if (USE_RETURN_INSN (FALSE))
6489     {
6490       emit_jump_insn (gen_return ());
6491       DONE;
6492     }
6495 (define_insn "*epilogue_insn"
6496   [(unspec_volatile [(return)] 6)]
6497   ""
6498   "*
6499   return arm_output_epilogue ();
6501 ;; Length is absolute worst case
6502 [(set_attr "length" "44")
6503  (set_attr "type" "block")])
6505 ;; This split is only used during output to reduce the number of patterns
6506 ;; that need assembler instructions adding to them.  We allowed the setting
6507 ;; of the conditions to be implicit during rtl generation so that
6508 ;; the conditional compare patterns would work.  However this conflicts to
6509 ;; some extent with the conditional data operations, so we have to split them
6510 ;; up again here.
6512 (define_split
6513   [(set (match_operand:SI 0 "s_register_operand" "")
6514         (if_then_else:SI (match_operator 1 "comparison_operator"
6515                           [(match_operand 2 "" "") (match_operand 3 "" "")])
6516                          (match_operand 4 "" "")
6517                          (match_operand 5 "" "")))
6518    (clobber (reg:CC 24))]
6519   "reload_completed"
6520   [(set (match_dup 6) (match_dup 7))
6521    (set (match_dup 0) 
6522         (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
6523                          (match_dup 4)
6524                          (match_dup 5)))]
6525   "
6527   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
6528                                            operands[3]);
6530   operands[6] = gen_rtx_REG (mode, 24);
6531   operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
6535 ;; The next two patterns occur when an AND operation is followed by a
6536 ;; scc insn sequence 
6538 (define_insn "*sign_extract_onebit"
6539   [(set (match_operand:SI 0 "s_register_operand" "=r")
6540         (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6541                          (const_int 1)
6542                          (match_operand:SI 2 "const_int_operand" "n")))]
6543   ""
6544   "*
6545   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6546   output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6547   return \"mvnne\\t%0, #0\";
6549 [(set_attr "conds" "clob")
6550  (set_attr "length" "8")])
6552 (define_insn "*not_signextract_onebit"
6553   [(set (match_operand:SI 0 "s_register_operand" "=r")
6554         (not:SI
6555          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6556                           (const_int 1)
6557                           (match_operand:SI 2 "const_int_operand" "n"))))]
6558   ""
6559   "*
6560   operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6561   output_asm_insn (\"tst\\t%1, %2\", operands);
6562   output_asm_insn (\"mvneq\\t%0, #0\", operands);
6563   return \"movne\\t%0, #0\";
6565 [(set_attr "conds" "clob")
6566  (set_attr "length" "12")])
6568 ;; Push multiple registers to the stack.  The first register is in the
6569 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
6570 ;; expressions.
6571 (define_insn "*push_multi"
6572   [(match_parallel 2 "multi_register_push"
6573     [(set (match_operand:BLK 0 "memory_operand" "=m")
6574           (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
6575   ""
6576   "*
6578   extern int lr_save_eliminated;
6579   int num_saves = XVECLEN (operands[2], 0);
6580      
6581    if (lr_save_eliminated)
6582     {
6583       if (num_saves > 1)
6584         abort ();
6585     }
6586  /* For the StrongARM at least it is faster to
6587      use STR to store only a single register.  */
6588   else if (num_saves == 1)
6589     output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
6590   else
6591     {
6592       int i;
6593       char pattern[100];
6595       if (lr_save_eliminated)
6596         abort ();
6598       strcpy (pattern, \"stmfd\\t%m0!, {%1\");
6599                        
6600       for (i = 1; i < num_saves; i++)
6601         {
6602           strcat (pattern, \", %|\");
6603           strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
6604                                               0))]);
6605         }
6606         
6607       strcat (pattern, \"}\");
6608       output_asm_insn (pattern, operands);
6609     }
6610     
6611   return \"\";
6613 [(set_attr "type" "store4")])
6615 ;; Similarly for the floating point registers
6616 (define_insn "*push_fp_multi"
6617   [(match_parallel 2 "multi_register_push"
6618     [(set (match_operand:BLK 0 "memory_operand" "=m")
6619           (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
6620   ""
6621   "*
6623   char pattern[100];
6625   sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
6626   output_asm_insn (pattern, operands);
6627   return \"\";
6629 [(set_attr "type" "f_store")])
6631 ;; Special patterns for dealing with the constant pool
6633 (define_insn "consttable_4"
6634   [(unspec_volatile [(match_operand 0 "" "")] 2)]
6635   ""
6636   "*
6638   making_const_table = TRUE;
6639   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6640     {
6641     case MODE_FLOAT:
6642     {
6643       union real_extract u;
6644       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6645       assemble_real (u.d, GET_MODE (operands[0]));
6646       break;
6647     }
6648     default:
6649       assemble_integer (operands[0], 4, 1);
6650       break;
6651     }
6652   return \"\";
6654 [(set_attr "length" "4")])
6656 (define_insn "consttable_8"
6657   [(unspec_volatile [(match_operand 0 "" "")] 3)]
6658   ""
6659   "*
6661   making_const_table = TRUE;
6662   switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6663     {
6664     case MODE_FLOAT:
6665     {
6666       union real_extract u;
6667       bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6668       assemble_real (u.d, GET_MODE (operands[0]));
6669       break;
6670     }
6671     default:
6672       assemble_integer (operands[0], 8, 1);
6673       break;
6674     }
6675   return \"\";
6677 [(set_attr "length" "8")])
6679 (define_insn "consttable_end"
6680   [(unspec_volatile [(const_int 0)] 4)]
6681   ""
6682   "*
6683   making_const_table = FALSE;
6684   return \"\";
6687 (define_insn "align_4"
6688   [(unspec_volatile [(const_int 0)] 5)]
6689   ""
6690   "*
6691   assemble_align (32);
6692   return \"\";