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