OSDN Git Service

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