1 ;;- Machine description for Advanced RISC Machines' ARM for GNU compiler
2 ;; Copyright (C) 1991, 93, 94, 95, 96, 1997 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 (rwe11@cl.cam.ac.uk)
7 ;; This file is part of GNU CC.
9 ;; GNU CC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; GNU CC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU CC; see the file COPYING. If not, write to
21 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
24 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26 ;; There are patterns in this file to support XFmode arithmetic.
27 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
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.
43 ; PROG_MODE attribute is used to determine whether condition codes are
44 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
45 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
46 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
48 ; CPU attribute is used to determine whether condition codes are clobbered
49 ; by a call insn: on the arm6 they are if in 32-bit addressing mode; on the
50 ; arm2 and arm3 the condition codes are restored by the return.
52 (define_attr "cpu" "arm2,arm3,arm6,arm7,arm8,st_arm"
53 (const (symbol_ref "arm_cpu_attr")))
55 ; Floating Point Unit. If we only have floating point emulation, then there
56 ; is no point in scheduling the floating point insns. (Well, for best
57 ; performance we should try and group them together).
59 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
61 ; LENGTH of an instruction (in bytes)
62 (define_attr "length" "" (const_int 4))
64 ; An assembler sequence may clobber the condition codes without us knowing
65 (define_asm_attributes
66 [(set_attr "conds" "clob")
67 (set_attr "length" "4")])
69 ; TYPE attribute is used to detect floating point instructions which, if
70 ; running on a co-processor can run in parallel with other, basic instructions
71 ; If write-buffer scheduling is enabled then it can also be used in the
72 ; scheduling of writes.
74 ; Classification of each insn
75 ; normal any data instruction that doesn't hit memory or fp regs
76 ; mult a multiply instruction
77 ; block blockage insn, this blocks all functional units
78 ; float a floating point arithmetic operation (subject to expansion)
79 ; fdivx XFmode floating point division
80 ; fdivd DFmode floating point division
81 ; fdivs SFmode floating point division
82 ; fmul Floating point multiply
83 ; ffmul Fast floating point multiply
84 ; farith Floating point arithmetic (4 cycle)
85 ; ffarith Fast floating point arithmetic (2 cycle)
86 ; float_em a floating point arithmetic operation that is normally emulated
87 ; even on a machine with an fpa.
88 ; f_load a floating point load from memory
89 ; f_store a floating point store to memory
90 ; f_mem_r a transfer of a floating point register to a real reg via mem
91 ; r_mem_f the reverse of f_mem_r
92 ; f_2_r fast transfer float to arm (no memory needed)
93 ; r_2_f fast transfer arm to float
94 ; call a subroutine call
95 ; load any load from memory
96 ; store1 store 1 word to memory from arm registers
97 ; store2 store 2 words
98 ; store3 store 3 words
99 ; store4 store 4 words
102 "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"
103 (const_string "normal"))
105 ; Load scheduling, set from the cpu characteristic
106 (define_attr "ldsched" "no,yes"
107 (if_then_else (eq_attr "cpu" "arm8,st_arm")
109 (const_string "no")))
111 ; condition codes: this one is used by final_prescan_insn to speed up
112 ; conditionalizing instructions. It saves having to scan the rtl to see if
113 ; it uses or alters the condition codes.
115 ; USE means that the condition codes are used by the insn in the process of
116 ; outputting code, this means (at present) that we can't use the insn in
119 ; SET means that the purpose of the insn is to set the condition codes in a
120 ; well defined manner.
122 ; CLOB means that the condition codes are altered in an undefined manner, if
123 ; they are altered at all
125 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
126 ; but are if the branch wasn't taken; the effect is to limit the branch
127 ; elimination scanning.
129 ; NOCOND means that the condition codes are neither altered nor affect the
130 ; output of this insn
132 (define_attr "conds" "use,set,clob,jump_clob,nocond"
133 (if_then_else (eq_attr "type" "call")
134 (if_then_else (eq_attr "prog_mode" "prog32")
135 (const_string "clob") (const_string "nocond"))
136 (const_string "nocond")))
138 (define_attr "write_conflict" "no,yes"
139 (if_then_else (eq_attr "type"
140 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
142 (const_string "no")))
144 (define_attr "core_cycles" "single,multi"
145 (if_then_else (eq_attr "type"
146 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
147 (const_string "single")
148 (const_string "multi")))
150 ; The write buffer on some of the arm6 processors is hard to model exactly.
151 ; There is room in the buffer for up to two addresses and up to eight words
152 ; of memory, but the two needn't be split evenly. When writing the two
153 ; addresses are fully pipelined. However, a read from memory that is not
154 ; currently in the cache will block until the writes have completed.
155 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
156 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
157 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
158 ; cycle to add as well.
160 ;; (define_function_unit {name} {num-units} {n-users} {test}
161 ;; {ready-delay} {issue-delay} [{conflict-list}])
162 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
163 (eq_attr "type" "fdivx")) 71 69)
165 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
166 (eq_attr "type" "fdivd")) 59 57)
168 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
169 (eq_attr "type" "fdivs")) 31 29)
171 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
172 (eq_attr "type" "fmul")) 9 7)
174 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
175 (eq_attr "type" "ffmul")) 6 4)
177 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
178 (eq_attr "type" "farith")) 4 2)
180 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
181 (eq_attr "type" "ffarith")) 2 2)
183 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
184 (eq_attr "type" "r_2_f")) 5 3)
186 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
187 (eq_attr "type" "f_2_r")) 1 2)
189 ;; The fpa10 doesn't really have a memory read unit, but it can start to
190 ;; speculatively execute the instruction in the pipeline, provided the data
191 ;; is already loaded, so pretend reads have a delay of 2 (and that the
192 ;; pipeline is infinite.
194 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
195 (eq_attr "type" "f_load")) 3 1)
197 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store1") 5 3)
198 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store2") 7 4)
199 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store3") 9 5)
200 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store4") 11 6)
201 (define_function_unit "write_buf" 1 2 (eq_attr "type" "r_mem_f") 5 3)
203 ;; The write_blockage unit models (partially), the fact that writes will stall
204 ;; until the write buffer empties.
206 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store1") 5 5
207 [(eq_attr "write_conflict" "yes")])
208 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store2") 7 7
209 [(eq_attr "write_conflict" "yes")])
210 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store3") 9 9
211 [(eq_attr "write_conflict" "yes")])
212 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store4") 11 11
213 [(eq_attr "write_conflict" "yes")])
214 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "r_mem_f") 5 5
215 [(eq_attr "write_conflict" "yes")])
216 (define_function_unit "write_blockage" 1 0
217 (eq_attr "write_conflict" "yes") 1 1)
221 (define_function_unit "core" 1 1 (eq_attr "core_cycles" "single") 1 1)
223 (define_function_unit "core" 1 1
224 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 1 1)
226 (define_function_unit "core" 1 1
227 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load")) 2 2)
229 (define_function_unit "core" 1 1 (eq_attr "type" "mult") 16 16)
231 (define_function_unit "core" 1 1
232 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
234 (define_function_unit "core" 1 1
235 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "store1")) 2 2)
237 (define_function_unit "core" 1 1 (eq_attr "type" "store2") 3 3)
239 (define_function_unit "core" 1 1 (eq_attr "type" "store3") 4 4)
241 (define_function_unit "core" 1 1 (eq_attr "type" "store4") 5 5)
243 (define_function_unit "core" 1 1
244 (and (eq_attr "core_cycles" "multi")
245 (eq_attr "type" "!mult,load,store2,store3,store4")) 32 32)
247 (define_function_unit "loader" 1 0
248 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
251 ;; Note: For DImode insns, there is normally no reason why operands should
252 ;; not be in the same register, what we don't want is for something being
253 ;; written to partially overlap something that is an input.
257 (define_insn "adddi3"
258 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
259 (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
260 (match_operand:DI 2 "s_register_operand" "r,0")))
261 (clobber (reg:CC 24))]
263 "adds\\t%Q0, %Q1, %Q2\;adc\\t%R0, %R1, %R2"
264 [(set_attr "conds" "clob")
265 (set_attr "length" "8")])
267 (define_insn "*adddi_sesidi_di"
268 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
269 (plus:DI (sign_extend:DI
270 (match_operand:SI 2 "s_register_operand" "r,r"))
271 (match_operand:DI 1 "s_register_operand" "r,0")))
272 (clobber (reg:CC 24))]
274 "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, %2, asr #31"
275 [(set_attr "conds" "clob")
276 (set_attr "length" "8")])
278 (define_insn "*adddi_zesidi_di"
279 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
280 (plus:DI (zero_extend:DI
281 (match_operand:SI 2 "s_register_operand" "r,r"))
282 (match_operand:DI 1 "s_register_operand" "r,0")))
283 (clobber (reg:CC 24))]
285 "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, #0"
286 [(set_attr "conds" "clob")
287 (set_attr "length" "8")])
289 (define_expand "addsi3"
290 [(set (match_operand:SI 0 "s_register_operand" "")
291 (plus:SI (match_operand:SI 1 "s_register_operand" "")
292 (match_operand:SI 2 "reg_or_int_operand" "")))]
295 if (GET_CODE (operands[2]) == CONST_INT)
297 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
299 (reload_in_progress || reload_completed ? 0
300 : preserve_subexpressions_p ()));
306 [(set (match_operand:SI 0 "s_register_operand" "")
307 (plus:SI (match_operand:SI 1 "s_register_operand" "")
308 (match_operand:SI 2 "const_int_operand" "")))]
309 "! (const_ok_for_arm (INTVAL (operands[2]))
310 || const_ok_for_arm (-INTVAL (operands[2])))"
311 [(clobber (const_int 0))]
313 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
318 (define_insn "*addsi3_insn"
319 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
320 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
321 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
327 [(set_attr "length" "4,4,16")])
329 (define_insn "*addsi3_compare0"
330 [(set (reg:CC_NOOV 24)
332 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
333 (match_operand:SI 2 "arm_add_operand" "rI,L"))
335 (set (match_operand:SI 0 "s_register_operand" "=r,r")
336 (plus:SI (match_dup 1) (match_dup 2)))]
340 sub%?s\\t%0, %1, #%n2"
341 [(set_attr "conds" "set")])
343 (define_insn "*addsi3_compare0_scratch"
344 [(set (reg:CC_NOOV 24)
346 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
347 (match_operand:SI 1 "arm_add_operand" "rI,L"))
353 [(set_attr "conds" "set")])
355 ;; The next four insns work because they compare the result with one of
356 ;; the operands, and we know that the use of the condition code is
357 ;; either GEU or LTU, so we can use the carry flag from the addition
358 ;; instead of doing the compare a second time.
359 (define_insn "*addsi3_compare_op1"
362 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
363 (match_operand:SI 2 "arm_add_operand" "rI,L"))
365 (set (match_operand:SI 0 "s_register_operand" "=r,r")
366 (plus:SI (match_dup 1) (match_dup 2)))]
370 sub%?s\\t%0, %1, #%n2"
371 [(set_attr "conds" "set")])
373 (define_insn "*addsi3_compare_op2"
376 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
377 (match_operand:SI 2 "arm_add_operand" "rI,L"))
379 (set (match_operand:SI 0 "s_register_operand" "=r,r")
380 (plus:SI (match_dup 1) (match_dup 2)))]
384 sub%?s\\t%0, %1, #%n2"
385 [(set_attr "conds" "set")])
387 (define_insn "*compare_addsi2_op0"
390 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
391 (match_operand:SI 1 "arm_add_operand" "rI,L"))
397 [(set_attr "conds" "set")])
399 (define_insn "*compare_addsi2_op1"
402 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
403 (match_operand:SI 1 "arm_add_operand" "rI,L"))
409 [(set_attr "conds" "set")])
411 (define_insn "*addsi3_carryin"
412 [(set (match_operand:SI 0 "s_register_operand" "=r")
413 (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
414 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
415 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
418 [(set_attr "conds" "use")])
420 (define_insn "*addsi3_carryin_alt1"
421 [(set (match_operand:SI 0 "s_register_operand" "=r")
422 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
423 (match_operand:SI 2 "arm_rhs_operand" "rI"))
424 (ltu:SI (reg:CC_C 24) (const_int 0))))]
427 [(set_attr "conds" "use")])
429 (define_insn "*addsi3_carryin_alt2"
430 [(set (match_operand:SI 0 "s_register_operand" "=r")
431 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
432 (match_operand:SI 1 "s_register_operand" "r"))
433 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
436 [(set_attr "conds" "use")])
438 (define_insn "*addsi3_carryin_alt3"
439 [(set (match_operand:SI 0 "s_register_operand" "=r")
440 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
441 (match_operand:SI 2 "arm_rhs_operand" "rI"))
442 (match_operand:SI 1 "s_register_operand" "r")))]
445 [(set_attr "conds" "use")])
447 (define_insn "incscc"
448 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
449 (plus:SI (match_operator:SI 2 "comparison_operator"
450 [(match_operand 3 "cc_register" "") (const_int 0)])
451 (match_operand:SI 1 "s_register_operand" "0,?r")))]
455 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
456 [(set_attr "conds" "use")
457 (set_attr "length" "4,8")])
459 ; If a constant is too big to fit in a single instruction then the constant
460 ; will be pre-loaded into a register taking at least two insns, we might be
461 ; able to merge it with an add, but it depends on the exact value.
464 [(set (match_operand:SI 0 "s_register_operand" "=r")
465 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
466 (match_operand:SI 2 "const_int_operand" "n")))]
467 "!(const_ok_for_arm (INTVAL (operands[2]))
468 || const_ok_for_arm (-INTVAL (operands[2])))"
469 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
470 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
473 unsigned int val = (unsigned) INTVAL (operands[2]);
477 /* this code is similar to the approach followed in movsi, but it must
478 generate exactly two insns */
480 for (i = 30; i >= 0; i -= 2)
486 if (const_ok_for_arm (temp = (val & ~(255 << i))))
491 /* we might be able to do this as (larger number - small number) */
492 temp = ((val >> i) & 255) + 1;
493 if (temp > 255 && i < 24)
496 temp = ((val >> i) & 255) + 1;
498 if (const_ok_for_arm ((temp << i) - val))
501 temp = (unsigned) - (int) (i - val);
508 /* if we got here, we have found a way of doing it in two instructions.
509 the two constants are in val and temp */
510 operands[2] = GEN_INT ((int)val);
511 operands[3] = GEN_INT ((int)temp);
515 (define_insn "addsf3"
516 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
517 (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
518 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
522 suf%?s\\t%0, %1, #%N2"
523 [(set_attr "type" "farith")])
525 (define_insn "adddf3"
526 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
527 (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
528 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
532 suf%?d\\t%0, %1, #%N2"
533 [(set_attr "type" "farith")])
535 (define_insn "*adddf_df_esfdf"
536 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
537 (plus:DF (float_extend:DF
538 (match_operand:SF 1 "s_register_operand" "f,f"))
539 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
543 suf%?d\\t%0, %1, #%N2"
544 [(set_attr "type" "farith")])
546 (define_insn "*adddf_df_esfdf"
547 [(set (match_operand:DF 0 "s_register_operand" "=f")
548 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
550 (match_operand:SF 2 "s_register_operand" "f"))))]
552 "adf%?d\\t%0, %1, %2"
553 [(set_attr "type" "farith")])
555 (define_insn "*adddf_esfdf_esfdf"
556 [(set (match_operand:DF 0 "s_register_operand" "=f")
557 (plus:DF (float_extend:DF
558 (match_operand:SF 1 "s_register_operand" "f"))
560 (match_operand:SF 2 "s_register_operand" "f"))))]
562 "adf%?d\\t%0, %1, %2"
563 [(set_attr "type" "farith")])
565 (define_insn "addxf3"
566 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
567 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
568 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
569 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
572 suf%?e\\t%0, %1, #%N2"
573 [(set_attr "type" "farith")])
575 (define_insn "subdi3"
576 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
577 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
578 (match_operand:DI 2 "s_register_operand" "r,0,0")))
579 (clobber (reg:CC 24))]
581 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
582 [(set_attr "conds" "clob")
583 (set_attr "length" "8")])
585 (define_insn "*subdi_di_zesidi"
586 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
587 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
589 (match_operand:SI 2 "s_register_operand" "r,r"))))
590 (clobber (reg:CC 24))]
592 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
593 [(set_attr "conds" "clob")
594 (set_attr "length" "8")])
596 (define_insn "*subdi_di_sesidi"
597 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
598 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
600 (match_operand:SI 2 "s_register_operand" "r,r"))))
601 (clobber (reg:CC 24))]
603 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
604 [(set_attr "conds" "clob")
605 (set_attr "length" "8")])
607 (define_insn "*subdi_zesidi_di"
608 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
609 (minus:DI (zero_extend:DI
610 (match_operand:SI 2 "s_register_operand" "r,r"))
611 (match_operand:DI 1 "s_register_operand" "?r,0")))
612 (clobber (reg:CC 24))]
614 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
615 [(set_attr "conds" "clob")
616 (set_attr "length" "8")])
618 (define_insn "*subdi_sesidi_di"
619 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
620 (minus:DI (sign_extend:DI
621 (match_operand:SI 2 "s_register_operand" "r,r"))
622 (match_operand:DI 1 "s_register_operand" "?r,0")))
623 (clobber (reg:CC 24))]
625 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
626 [(set_attr "conds" "clob")
627 (set_attr "length" "8")])
629 (define_insn "*subdi_zesidi_zesidi"
630 [(set (match_operand:DI 0 "s_register_operand" "=r")
631 (minus:DI (zero_extend:DI
632 (match_operand:SI 1 "s_register_operand" "r"))
634 (match_operand:SI 2 "s_register_operand" "r"))))
635 (clobber (reg:CC 24))]
637 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
638 [(set_attr "conds" "clob")
639 (set_attr "length" "8")])
641 (define_expand "subsi3"
642 [(set (match_operand:SI 0 "s_register_operand" "")
643 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
644 (match_operand:SI 2 "s_register_operand" "")))]
647 if (GET_CODE (operands[1]) == CONST_INT)
649 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
651 (reload_in_progress || reload_completed ? 0
652 : preserve_subexpressions_p ()));
657 (define_insn "*subsi3_insn"
658 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
659 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
660 (match_operand:SI 2 "s_register_operand" "r,r")))]
665 [(set_attr "length" "4,16")])
668 [(set (match_operand:SI 0 "s_register_operand" "")
669 (minus:SI (match_operand:SI 1 "const_int_operand" "")
670 (match_operand:SI 2 "s_register_operand" "")))]
671 "! const_ok_for_arm (INTVAL (operands[1]))"
672 [(clobber (const_int 0))]
674 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
679 (define_insn "*subsi3_compare0"
680 [(set (reg:CC_NOOV 24)
681 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
682 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
684 (set (match_operand:SI 0 "s_register_operand" "=r,r")
685 (minus:SI (match_dup 1) (match_dup 2)))]
690 [(set_attr "conds" "set")])
692 (define_insn "decscc"
693 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
694 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
695 (match_operator:SI 2 "comparison_operator"
696 [(match_operand 3 "cc_register" "") (const_int 0)])))]
700 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
701 [(set_attr "conds" "use")
702 (set_attr "length" "*,8")])
704 (define_insn "subsf3"
705 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
706 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
707 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
712 [(set_attr "type" "farith")])
714 (define_insn "subdf3"
715 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
716 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
717 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
722 [(set_attr "type" "farith")])
724 (define_insn "*subdf_esfdf_df"
725 [(set (match_operand:DF 0 "s_register_operand" "=f")
726 (minus:DF (float_extend:DF
727 (match_operand:SF 1 "s_register_operand" "f"))
728 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
730 "suf%?d\\t%0, %1, %2"
731 [(set_attr "type" "farith")])
733 (define_insn "*subdf_df_esfdf"
734 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
735 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
737 (match_operand:SF 2 "s_register_operand" "f,f"))))]
742 [(set_attr "type" "farith")])
744 (define_insn "*subdf_esfdf_esfdf"
745 [(set (match_operand:DF 0 "s_register_operand" "=f")
746 (minus:DF (float_extend:DF
747 (match_operand:SF 1 "s_register_operand" "f"))
749 (match_operand:SF 2 "s_register_operand" "f"))))]
751 "suf%?d\\t%0, %1, %2"
752 [(set_attr "type" "farith")])
754 (define_insn "subxf3"
755 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
756 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
757 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
758 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
762 [(set_attr "type" "farith")])
764 ;; Multiplication insns
766 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
767 (define_insn "mulsi3"
768 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
769 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
770 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
773 [(set_attr "type" "mult")])
775 (define_insn "*mulsi3_compare0"
776 [(set (reg:CC_NOOV 24)
777 (compare:CC_NOOV (mult:SI
778 (match_operand:SI 2 "s_register_operand" "r,r")
779 (match_operand:SI 1 "s_register_operand" "%?r,0"))
781 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
782 (mult:SI (match_dup 2) (match_dup 1)))]
784 "mul%?s\\t%0, %2, %1"
785 [(set_attr "conds" "set")
786 (set_attr "type" "mult")])
788 (define_insn "*mulsi_compare0_scratch"
789 [(set (reg:CC_NOOV 24)
790 (compare:CC_NOOV (mult:SI
791 (match_operand:SI 2 "s_register_operand" "r,r")
792 (match_operand:SI 1 "s_register_operand" "%?r,0"))
794 (clobber (match_scratch:SI 0 "=&r,&r"))]
796 "mul%?s\\t%0, %2, %1"
797 [(set_attr "conds" "set")
798 (set_attr "type" "mult")])
800 ;; Unnamed templates to match MLA instruction.
802 (define_insn "*mulsi3addsi"
803 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
805 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
806 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
807 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
809 "mla%?\\t%0, %2, %1, %3"
810 [(set_attr "type" "mult")])
812 (define_insn "*mulsi3addsi_compare0"
813 [(set (reg:CC_NOOV 24)
814 (compare:CC_NOOV (plus:SI
816 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
817 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
818 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
820 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
821 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
824 "mla%?s\\t%0, %2, %1, %3"
825 [(set_attr "conds" "set")
826 (set_attr "type" "mult")])
828 (define_insn "*mulsi3addsi_compare0_scratch"
829 [(set (reg:CC_NOOV 24)
830 (compare:CC_NOOV (plus:SI
832 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
833 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
834 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
836 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
838 "mla%?s\\t%0, %2, %1, %3"
839 [(set_attr "conds" "set")
840 (set_attr "type" "mult")])
842 (define_insn "mulsidi3"
843 [(set (match_operand:DI 0 "s_register_operand" "=&r")
844 (mult:DI (sign_extend:DI
845 (match_operand:SI 1 "s_register_operand" "%r"))
847 (match_operand:SI 2 "s_register_operand" "r"))))]
849 "smull%?\\t%Q0, %R0, %1, %2"
850 [(set_attr "type" "mult")])
852 (define_insn "umulsidi3"
853 [(set (match_operand:DI 0 "s_register_operand" "=&r")
854 (mult:DI (zero_extend:DI
855 (match_operand:SI 1 "s_register_operand" "%r"))
857 (match_operand:SI 2 "s_register_operand" "r"))))]
859 "umull%?\\t%Q0, %R0, %1, %2"
860 [(set_attr "type" "mult")])
862 (define_insn "smulsi3_highpart"
863 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
866 (mult:DI (sign_extend:DI
867 (match_operand:SI 1 "s_register_operand" "%r,0"))
869 (match_operand:SI 2 "s_register_operand" "r,r")))
871 (clobber (match_scratch:SI 3 "=&r,&r"))]
873 "smull%?\\t%3, %0, %2, %1"
874 [(set_attr "type" "mult")])
876 (define_insn "umulsi3_highpart"
877 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
880 (mult:DI (zero_extend:DI
881 (match_operand:SI 1 "s_register_operand" "%r,0"))
883 (match_operand:SI 2 "s_register_operand" "r,r")))
885 (clobber (match_scratch:SI 3 "=&r,&r"))]
887 "umull%?\\t%3, %0, %2, %1"
888 [(set_attr "type" "mult")])
890 (define_insn "mulsf3"
891 [(set (match_operand:SF 0 "s_register_operand" "=f")
892 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
893 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
895 "fml%?s\\t%0, %1, %2"
896 [(set_attr "type" "ffmul")])
898 (define_insn "muldf3"
899 [(set (match_operand:DF 0 "s_register_operand" "=f")
900 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
901 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
903 "muf%?d\\t%0, %1, %2"
904 [(set_attr "type" "fmul")])
906 (define_insn "*muldf_esfdf_df"
907 [(set (match_operand:DF 0 "s_register_operand" "=f")
908 (mult:DF (float_extend:DF
909 (match_operand:SF 1 "s_register_operand" "f"))
910 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
912 "muf%?d\\t%0, %1, %2"
913 [(set_attr "type" "fmul")])
915 (define_insn "*muldf_df_esfdf"
916 [(set (match_operand:DF 0 "s_register_operand" "=f")
917 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
919 (match_operand:SF 2 "s_register_operand" "f"))))]
921 "muf%?d\\t%0, %1, %2"
922 [(set_attr "type" "fmul")])
924 (define_insn "*muldf_esfdf_esfdf"
925 [(set (match_operand:DF 0 "s_register_operand" "=f")
926 (mult:DF (float_extend:DF
927 (match_operand:SF 1 "s_register_operand" "f"))
929 (match_operand:SF 2 "s_register_operand" "f"))))]
931 "muf%?d\\t%0, %1, %2"
932 [(set_attr "type" "fmul")])
934 (define_insn "mulxf3"
935 [(set (match_operand:XF 0 "s_register_operand" "=f")
936 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
937 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
938 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
939 "muf%?e\\t%0, %1, %2"
940 [(set_attr "type" "fmul")])
944 (define_insn "divsf3"
945 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
946 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
947 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
952 [(set_attr "type" "fdivs")])
954 (define_insn "divdf3"
955 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
956 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
957 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
962 [(set_attr "type" "fdivd")])
964 (define_insn "*divdf_esfdf_df"
965 [(set (match_operand:DF 0 "s_register_operand" "=f")
966 (div:DF (float_extend:DF
967 (match_operand:SF 1 "s_register_operand" "f"))
968 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
970 "dvf%?d\\t%0, %1, %2"
971 [(set_attr "type" "fdivd")])
973 (define_insn "*divdf_df_esfdf"
974 [(set (match_operand:DF 0 "s_register_operand" "=f")
975 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
977 (match_operand:SF 2 "s_register_operand" "f"))))]
979 "rdf%?d\\t%0, %2, %1"
980 [(set_attr "type" "fdivd")])
982 (define_insn "*divdf_esfdf_esfdf"
983 [(set (match_operand:DF 0 "s_register_operand" "=f")
984 (div:DF (float_extend:DF
985 (match_operand:SF 1 "s_register_operand" "f"))
987 (match_operand:SF 2 "s_register_operand" "f"))))]
989 "dvf%?d\\t%0, %1, %2"
990 [(set_attr "type" "fdivd")])
992 (define_insn "divxf3"
993 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
994 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
995 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
996 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1000 [(set_attr "type" "fdivx")])
1004 (define_insn "modsf3"
1005 [(set (match_operand:SF 0 "s_register_operand" "=f")
1006 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1007 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1009 "rmf%?s\\t%0, %1, %2"
1010 [(set_attr "type" "fdivs")])
1012 (define_insn "moddf3"
1013 [(set (match_operand:DF 0 "s_register_operand" "=f")
1014 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1015 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1017 "rmf%?d\\t%0, %1, %2"
1018 [(set_attr "type" "fdivd")])
1020 (define_insn "*moddf_esfdf_df"
1021 [(set (match_operand:DF 0 "s_register_operand" "=f")
1022 (mod:DF (float_extend:DF
1023 (match_operand:SF 1 "s_register_operand" "f"))
1024 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1026 "rmf%?d\\t%0, %1, %2"
1027 [(set_attr "type" "fdivd")])
1029 (define_insn "*moddf_df_esfdf"
1030 [(set (match_operand:DF 0 "s_register_operand" "=f")
1031 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1033 (match_operand:SF 2 "s_register_operand" "f"))))]
1035 "rmf%?d\\t%0, %1, %2"
1036 [(set_attr "type" "fdivd")])
1038 (define_insn "*moddf_esfdf_esfdf"
1039 [(set (match_operand:DF 0 "s_register_operand" "=f")
1040 (mod:DF (float_extend:DF
1041 (match_operand:SF 1 "s_register_operand" "f"))
1043 (match_operand:SF 2 "s_register_operand" "f"))))]
1045 "rmf%?d\\t%0, %1, %2"
1046 [(set_attr "type" "fdivd")])
1048 (define_insn "modxf3"
1049 [(set (match_operand:XF 0 "s_register_operand" "=f")
1050 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1051 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1052 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1053 "rmf%?e\\t%0, %1, %2"
1054 [(set_attr "type" "fdivx")])
1056 ;; Boolean and,ior,xor insns
1058 (define_insn "anddi3"
1059 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1060 (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1061 (match_operand:DI 2 "s_register_operand" "r,0")))]
1063 "and%?\\t%Q0, %Q1, %Q2\;and%?\\t%R0, %R1, %R2"
1064 [(set_attr "length" "8")])
1066 (define_insn "*anddi_zesidi_di"
1067 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1068 (and:DI (zero_extend:DI
1069 (match_operand:SI 2 "s_register_operand" "r,r"))
1070 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1072 "and%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, #0"
1073 [(set_attr "length" "8")])
1075 (define_insn "*anddi_sesdi_di"
1076 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1077 (and:DI (sign_extend:DI
1078 (match_operand:SI 2 "s_register_operand" "r,r"))
1079 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1081 "and%?\\t%Q0, %Q1, %2\;and%?\\t%R0, %R1, %2, asr #31"
1082 [(set_attr "length" "8")])
1084 (define_expand "andsi3"
1085 [(set (match_operand:SI 0 "s_register_operand" "")
1086 (and:SI (match_operand:SI 1 "s_register_operand" "")
1087 (match_operand:SI 2 "reg_or_int_operand" "")))]
1090 if (GET_CODE (operands[2]) == CONST_INT)
1092 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1094 (reload_in_progress || reload_completed
1095 ? 0 : preserve_subexpressions_p ()));
1100 (define_insn "*andsi3_insn"
1101 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1102 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1103 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1107 bic%?\\t%0, %1, #%B2
1109 [(set_attr "length" "4,4,16")])
1112 [(set (match_operand:SI 0 "s_register_operand" "")
1113 (and:SI (match_operand:SI 1 "s_register_operand" "")
1114 (match_operand:SI 2 "const_int_operand" "")))]
1115 "! (const_ok_for_arm (INTVAL (operands[2]))
1116 || const_ok_for_arm (~ INTVAL (operands[2])))"
1117 [(clobber (const_int 0))]
1119 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1124 (define_insn "*andsi3_compare0"
1125 [(set (reg:CC_NOOV 24)
1127 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1128 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1130 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1131 (and:SI (match_dup 1) (match_dup 2)))]
1135 bic%?s\\t%0, %1, #%B2"
1136 [(set_attr "conds" "set")])
1138 (define_insn "*andsi3_compare0_scratch"
1139 [(set (reg:CC_NOOV 24)
1141 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1142 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1144 (clobber (match_scratch:SI 3 "=X,r"))]
1148 bic%?s\\t%3, %0, #%B1"
1149 [(set_attr "conds" "set")])
1151 (define_insn "*zeroextractsi_compare0_scratch"
1152 [(set (reg:CC_NOOV 24)
1153 (compare:CC_NOOV (zero_extract:SI
1154 (match_operand:SI 0 "s_register_operand" "r")
1155 (match_operand 1 "const_int_operand" "n")
1156 (match_operand 2 "const_int_operand" "n"))
1158 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1159 && INTVAL (operands[1]) > 0
1160 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1161 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1164 unsigned int mask = 0;
1165 int cnt = INTVAL (operands[1]);
1168 mask = (mask << 1) | 1;
1169 operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1170 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1174 [(set_attr "conds" "set")])
1176 (define_insn "*zeroextractqi_compare0_scratch"
1177 [(set (reg:CC_NOOV 24)
1178 (compare:CC_NOOV (zero_extract:SI
1179 (match_operand:QI 0 "memory_operand" "m")
1180 (match_operand 1 "const_int_operand" "n")
1181 (match_operand 2 "const_int_operand" "n"))
1183 (clobber (match_scratch:QI 3 "=r"))]
1184 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 8
1185 && INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8"
1188 unsigned int mask = 0;
1189 int cnt = INTVAL (operands[1]);
1192 mask = (mask << 1) | 1;
1193 operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1194 output_asm_insn (\"ldr%?b\\t%3, %0\", operands);
1195 output_asm_insn (\"tst%?\\t%3, %1\", operands);
1199 [(set_attr "conds" "set")
1200 (set_attr "length" "8")])
1202 (define_expand "insv"
1203 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1204 (match_operand:SI 1 "general_operand" "")
1205 (match_operand:SI 2 "general_operand" ""))
1206 (match_operand:SI 3 "nonmemory_operand" ""))]
1210 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << INTVAL (operands[1])) - 1;
1211 rtx target, subtarget;
1213 target = operands[0];
1214 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1215 subreg as the final target. */
1216 if (GET_CODE (target) == SUBREG)
1218 subtarget = gen_reg_rtx (SImode);
1219 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1220 < GET_MODE_SIZE (SImode))
1221 target = SUBREG_REG (target);
1226 if (GET_CODE (operands[3]) == CONST_INT)
1228 /* Since we are inserting a known constant, we may be able to
1229 reduce the number of bits that we have to clear so that
1230 the mask becomes simple. */
1231 rtx op1 = gen_reg_rtx (SImode);
1232 HOST_WIDE_INT mask2 = ((mask & ~INTVAL (operands[3]))
1233 << INTVAL (operands[2]));
1235 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1236 emit_insn (gen_iorsi3 (subtarget, op1,
1237 GEN_INT (INTVAL (operands[3])
1238 << INTVAL (operands[2]))));
1240 else if (INTVAL (operands[2]) == 0
1241 && ! (const_ok_for_arm (mask)
1242 || const_ok_for_arm (~mask)))
1244 /* A Trick, since we are setting the bottom bits in the word,
1245 we can shift operand[3] up, operand[0] down, OR them together
1246 and rotate the result back again. This takes 3 insns, and
1247 the third might be mergable into another op. */
1249 rtx op0 = gen_reg_rtx (SImode);
1250 rtx op1 = gen_reg_rtx (SImode);
1252 emit_insn (gen_ashlsi3 (op0, operands[3],
1253 GEN_INT (32 - INTVAL (operands[1]))));
1254 emit_insn (gen_iorsi3 (op1, gen_rtx (LSHIFTRT, SImode, operands[0],
1257 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1259 else if ((INTVAL (operands[1]) + INTVAL (operands[2]) == 32)
1260 && ! (const_ok_for_arm (mask)
1261 || const_ok_for_arm (~mask)))
1263 /* Similar trick, but slightly less efficient. */
1265 rtx op0 = gen_reg_rtx (SImode);
1266 rtx op1 = gen_reg_rtx (SImode);
1268 emit_insn (gen_ashlsi3 (op0, operands[3],
1269 GEN_INT (32 - INTVAL (operands[1]))));
1270 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1271 emit_insn (gen_iorsi3 (subtarget,
1272 gen_rtx (LSHIFTRT, SImode, op1,
1273 operands[1]), op0));
1277 rtx op0 = GEN_INT (mask);
1278 rtx op1 = gen_reg_rtx (SImode);
1279 rtx op2 = gen_reg_rtx (SImode);
1281 if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1283 rtx tmp = gen_reg_rtx (SImode);
1285 emit_insn (gen_movsi (tmp, op0));
1289 emit_insn (gen_andsi3 (op1, operands[3], op0));
1291 if (GET_CODE (op0) == CONST_INT
1292 && (const_ok_for_arm (mask << INTVAL (operands[2]))
1293 || const_ok_for_arm (~ (mask << INTVAL (operands[2])))))
1295 op0 = GEN_INT (~(mask << INTVAL (operands[2])));
1296 emit_insn (gen_andsi3 (op2, operands[0], op0));
1300 if (GET_CODE (op0) == CONST_INT)
1302 rtx tmp = gen_reg_rtx (SImode);
1304 emit_insn (gen_movsi (tmp, op0));
1308 if (INTVAL (operands[2]) != 0)
1309 op0 = gen_rtx (ASHIFT, SImode, op0, operands[2]);
1310 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1313 if (INTVAL (operands[2]) != 0)
1314 op1 = gen_rtx (ASHIFT, SImode, op1, operands[2]);
1316 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1319 if (subtarget != target)
1321 /* If TARGET is still a SUBREG, then it must be wider than a word,
1322 so we must be careful only to set the subword we were asked to. */
1323 if (GET_CODE (target) == SUBREG)
1324 emit_move_insn (target, subtarget);
1326 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1333 ;; constants for op 2 will never be given to these patterns.
1334 (define_insn "*anddi_notdi_di"
1335 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1336 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1337 (match_operand:DI 1 "s_register_operand" "0,r")))]
1339 "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2"
1340 [(set_attr "length" "8")])
1342 (define_insn "*anddi_notzesidi_di"
1343 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1344 (and:DI (not:DI (zero_extend:DI
1345 (match_operand:SI 2 "s_register_operand" "r,r")))
1346 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1349 bic%?\\t%Q0, %Q1, %2
1350 bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1351 [(set_attr "length" "4,8")])
1353 (define_insn "*anddi_notsesidi_di"
1354 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1355 (and:DI (not:DI (sign_extend:DI
1356 (match_operand:SI 2 "s_register_operand" "r,r")))
1357 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1359 "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
1360 [(set_attr "length" "8")])
1362 (define_insn "andsi_notsi_si"
1363 [(set (match_operand:SI 0 "s_register_operand" "=r")
1364 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1365 (match_operand:SI 1 "s_register_operand" "r")))]
1367 "bic%?\\t%0, %1, %2")
1369 (define_insn "andsi_not_shiftsi_si"
1370 [(set (match_operand:SI 0 "s_register_operand" "=r")
1371 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1372 [(match_operand:SI 2 "s_register_operand" "r")
1373 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1374 (match_operand:SI 1 "s_register_operand" "r")))]
1376 "bic%?\\t%0, %1, %2%S4")
1378 (define_insn "*andsi_notsi_si_compare0"
1379 [(set (reg:CC_NOOV 24)
1381 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1382 (match_operand:SI 1 "s_register_operand" "r"))
1384 (set (match_operand:SI 0 "s_register_operand" "=r")
1385 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1387 "bic%?s\\t%0, %1, %2"
1388 [(set_attr "conds" "set")])
1390 (define_insn "*andsi_notsi_si_compare0_scratch"
1391 [(set (reg:CC_NOOV 24)
1393 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1394 (match_operand:SI 1 "s_register_operand" "r"))
1396 (clobber (match_scratch:SI 0 "=r"))]
1398 "bic%?s\\t%0, %1, %2"
1399 [(set_attr "conds" "set")])
1401 (define_insn "iordi3"
1402 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1403 (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1404 (match_operand:DI 2 "s_register_operand" "r")))]
1406 "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2"
1407 [(set_attr "length" "8")])
1409 (define_insn "*iordi_zesidi_di"
1410 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1411 (ior:DI (zero_extend:DI
1412 (match_operand:SI 2 "s_register_operand" "r,r"))
1413 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1416 orr%?\\t%Q0, %Q1, %2
1417 orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1418 [(set_attr "length" "4,8")])
1420 (define_insn "*iordi_sesidi_di"
1421 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1422 (ior:DI (sign_extend:DI
1423 (match_operand:SI 2 "s_register_operand" "r,r"))
1424 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1426 "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
1427 [(set_attr "length" "8")])
1429 (define_expand "iorsi3"
1430 [(set (match_operand:SI 0 "s_register_operand" "")
1431 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1432 (match_operand:SI 2 "reg_or_int_operand" "")))]
1435 if (GET_CODE (operands[2]) == CONST_INT)
1437 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1439 (reload_in_progress || reload_completed
1440 ? 0 : preserve_subexpressions_p ()));
1445 (define_insn "*iorsi3_insn"
1446 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1447 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1448 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1453 [(set_attr "length" "4,16")])
1456 [(set (match_operand:SI 0 "s_register_operand" "")
1457 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1458 (match_operand:SI 2 "const_int_operand" "")))]
1459 "! const_ok_for_arm (INTVAL (operands[2]))"
1460 [(clobber (const_int 0))]
1462 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1467 (define_insn "*iorsi3_compare0"
1468 [(set (reg:CC_NOOV 24)
1469 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1470 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1472 (set (match_operand:SI 0 "s_register_operand" "=r")
1473 (ior:SI (match_dup 1) (match_dup 2)))]
1475 "orr%?s\\t%0, %1, %2"
1476 [(set_attr "conds" "set")])
1478 (define_insn "*iorsi3_compare0_scratch"
1479 [(set (reg:CC_NOOV 24)
1480 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1481 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1483 (clobber (match_scratch:SI 0 "=r"))]
1485 "orr%?s\\t%0, %1, %2"
1486 [(set_attr "conds" "set")])
1488 (define_insn "xordi3"
1489 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1490 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1491 (match_operand:DI 2 "s_register_operand" "r,0")))]
1493 "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2"
1494 [(set_attr "length" "8")])
1496 (define_insn "*xordi_zesidi_di"
1497 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1498 (xor:DI (zero_extend:DI
1499 (match_operand:SI 2 "s_register_operand" "r,r"))
1500 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1503 eor%?\\t%Q0, %Q1, %2
1504 eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1505 [(set_attr "length" "4,8")])
1507 (define_insn "*xordi_sesidi_di"
1508 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1509 (xor:DI (sign_extend:DI
1510 (match_operand:SI 2 "s_register_operand" "r,r"))
1511 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1513 "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
1514 [(set_attr "length" "8")])
1516 (define_insn "xorsi3"
1517 [(set (match_operand:SI 0 "s_register_operand" "=r")
1518 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1519 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1521 "eor%?\\t%0, %1, %2")
1523 (define_insn "*xorsi3_compare0"
1524 [(set (reg:CC_NOOV 24)
1525 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1526 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1528 (set (match_operand:SI 0 "s_register_operand" "=r")
1529 (xor:SI (match_dup 1) (match_dup 2)))]
1531 "eor%?s\\t%0, %1, %2"
1532 [(set_attr "conds" "set")])
1534 (define_insn "*xorsi3_compare0_scratch"
1535 [(set (reg:CC_NOOV 24)
1536 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1537 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1541 [(set_attr "conds" "set")])
1543 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
1544 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1548 [(set (match_operand:SI 0 "s_register_operand" "=r")
1549 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1550 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1551 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1552 (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1554 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1555 (not:SI (match_dup 3))))
1556 (set (match_dup 0) (not:SI (match_dup 4)))]
1560 (define_insn "*andsi_iorsi3_notsi"
1561 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1562 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1563 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1564 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1566 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1567 [(set_attr "length" "8")])
1571 ;; Minimum and maximum insns
1573 (define_insn "smaxsi3"
1574 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1575 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1576 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1577 (clobber (reg:CC 24))]
1580 cmp\\t%1, %2\;movlt\\t%0, %2
1581 cmp\\t%1, %2\;movge\\t%0, %1
1582 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1583 [(set_attr "conds" "clob")
1584 (set_attr "length" "8,8,12")])
1586 (define_insn "sminsi3"
1587 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1588 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1589 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1590 (clobber (reg:CC 24))]
1593 cmp\\t%1, %2\;movge\\t%0, %2
1594 cmp\\t%1, %2\;movlt\\t%0, %1
1595 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1596 [(set_attr "conds" "clob")
1597 (set_attr "length" "8,8,12")])
1599 (define_insn "umaxsi3"
1600 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1601 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1602 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1603 (clobber (reg:CC 24))]
1606 cmp\\t%1, %2\;movcc\\t%0, %2
1607 cmp\\t%1, %2\;movcs\\t%0, %1
1608 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1609 [(set_attr "conds" "clob")
1610 (set_attr "length" "8,8,12")])
1612 (define_insn "uminsi3"
1613 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1614 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1615 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1616 (clobber (reg:CC 24))]
1619 cmp\\t%1, %2\;movcs\\t%0, %2
1620 cmp\\t%1, %2\;movcc\\t%0, %1
1621 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1622 [(set_attr "conds" "clob")
1623 (set_attr "length" "8,8,12")])
1625 (define_insn "*store_minmaxsi"
1626 [(set (match_operand:SI 0 "memory_operand" "=m")
1627 (match_operator:SI 3 "minmax_operator"
1628 [(match_operand:SI 1 "s_register_operand" "r")
1629 (match_operand:SI 2 "s_register_operand" "r")]))
1630 (clobber (reg:CC 24))]
1633 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1635 output_asm_insn (\"cmp\\t%1, %2\", operands);
1636 output_asm_insn (\"str%d3\\t%1, %0\", operands);
1637 output_asm_insn (\"str%D3\\t%2, %0\", operands);
1640 [(set_attr "conds" "clob")
1641 (set_attr "length" "12")
1642 (set_attr "type" "store1")])
1644 ; Reject the frame pointer in operand[1], since reloading this after
1645 ; it has been eliminated can cause carnage.
1646 (define_insn "*minmax_arithsi"
1647 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1648 (match_operator:SI 4 "shiftable_operator"
1649 [(match_operator:SI 5 "minmax_operator"
1650 [(match_operand:SI 2 "s_register_operand" "r,r")
1651 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1652 (match_operand:SI 1 "s_register_operand" "0,?r")]))
1653 (clobber (reg:CC 24))]
1654 "GET_CODE (operands[1]) != REG
1655 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
1656 && REGNO(operands[1]) != ARG_POINTER_REGNUM)"
1659 enum rtx_code code = GET_CODE (operands[4]);
1661 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1663 output_asm_insn (\"cmp\\t%2, %3\", operands);
1664 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1665 if (which_alternative != 0 || operands[3] != const0_rtx
1666 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1667 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1671 [(set_attr "conds" "clob")
1672 (set_attr "length" "12")])
1675 ;; Shift and rotation insns
1677 (define_expand "ashlsi3"
1678 [(set (match_operand:SI 0 "s_register_operand" "")
1679 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
1680 (match_operand:SI 2 "arm_rhs_operand" "")))]
1683 if (GET_CODE (operands[2]) == CONST_INT
1684 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1686 emit_insn (gen_movsi (operands[0], const0_rtx));
1691 (define_expand "ashrsi3"
1692 [(set (match_operand:SI 0 "s_register_operand" "")
1693 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1694 (match_operand:SI 2 "arm_rhs_operand" "")))]
1697 if (GET_CODE (operands[2]) == CONST_INT
1698 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1699 operands[2] = GEN_INT (31);
1702 (define_expand "lshrsi3"
1703 [(set (match_operand:SI 0 "s_register_operand" "")
1704 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1705 (match_operand:SI 2 "arm_rhs_operand" "")))]
1708 if (GET_CODE (operands[2]) == CONST_INT
1709 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1711 emit_insn (gen_movsi (operands[0], const0_rtx));
1716 (define_expand "rotlsi3"
1717 [(set (match_operand:SI 0 "s_register_operand" "")
1718 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1719 (match_operand:SI 2 "reg_or_int_operand" "")))]
1722 if (GET_CODE (operands[2]) == CONST_INT)
1723 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
1726 rtx reg = gen_reg_rtx (SImode);
1727 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
1732 (define_expand "rotrsi3"
1733 [(set (match_operand:SI 0 "s_register_operand" "")
1734 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1735 (match_operand:SI 2 "arm_rhs_operand" "")))]
1738 if (GET_CODE (operands[2]) == CONST_INT
1739 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1740 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
1743 (define_insn "*shiftsi3"
1744 [(set (match_operand:SI 0 "s_register_operand" "=r")
1745 (match_operator:SI 3 "shift_operator"
1746 [(match_operand:SI 1 "s_register_operand" "r")
1747 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
1749 "mov%?\\t%0, %1%S3")
1751 (define_insn "*shiftsi3_compare0"
1752 [(set (reg:CC_NOOV 24)
1753 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1754 [(match_operand:SI 1 "s_register_operand" "r")
1755 (match_operand:SI 2 "arm_rhs_operand" "rM")])
1757 (set (match_operand:SI 0 "s_register_operand" "=r")
1758 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
1760 "mov%?s\\t%0, %1%S3"
1761 [(set_attr "conds" "set")])
1763 (define_insn "*shiftsi3_compare0_scratch"
1764 [(set (reg:CC_NOOV 24)
1765 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1766 [(match_operand:SI 1 "s_register_operand" "r")
1767 (match_operand:SI 2 "arm_rhs_operand" "rM")])
1769 (clobber (match_scratch:SI 0 "=r"))]
1771 "mov%?s\\t%0, %1%S3"
1772 [(set_attr "conds" "set")])
1774 (define_insn "*notsi_shiftsi"
1775 [(set (match_operand:SI 0 "s_register_operand" "=r")
1776 (not:SI (match_operator:SI 3 "shift_operator"
1777 [(match_operand:SI 1 "s_register_operand" "r")
1778 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
1780 "mvn%?\\t%0, %1%S3")
1782 (define_insn "*notsi_shiftsi_compare0"
1783 [(set (reg:CC_NOOV 24)
1784 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1785 [(match_operand:SI 1 "s_register_operand" "r")
1786 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1788 (set (match_operand:SI 0 "s_register_operand" "=r")
1789 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1791 "mvn%?s\\t%0, %1%S3"
1792 [(set_attr "conds" "set")])
1794 (define_insn "*not_shiftsi_compare0_scratch"
1795 [(set (reg:CC_NOOV 24)
1796 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1797 [(match_operand:SI 1 "s_register_operand" "r")
1798 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1800 (clobber (match_scratch:SI 0 "=r"))]
1802 "mvn%?s\\t%0, %1%S3"
1803 [(set_attr "conds" "set")])
1806 ;; Unary arithmetic insns
1808 (define_insn "negdi2"
1809 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1810 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1812 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
1813 [(set_attr "conds" "clob")
1814 (set_attr "length" "8")])
1816 (define_insn "negsi2"
1817 [(set (match_operand:SI 0 "s_register_operand" "=r")
1818 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1820 "rsb%?\\t%0, %1, #0")
1822 (define_insn "negsf2"
1823 [(set (match_operand:SF 0 "s_register_operand" "=f")
1824 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1827 [(set_attr "type" "ffarith")])
1829 (define_insn "negdf2"
1830 [(set (match_operand:DF 0 "s_register_operand" "=f")
1831 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1834 [(set_attr "type" "ffarith")])
1836 (define_insn "*negdf_esfdf"
1837 [(set (match_operand:DF 0 "s_register_operand" "=f")
1838 (neg:DF (float_extend:DF
1839 (match_operand:SF 1 "s_register_operand" "f"))))]
1842 [(set_attr "type" "ffarith")])
1844 (define_insn "negxf2"
1845 [(set (match_operand:XF 0 "s_register_operand" "=f")
1846 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1847 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1849 [(set_attr "type" "ffarith")])
1851 ;; abssi2 doesn't really clobber the condition codes if a different register
1852 ;; is being set. To keep things simple, assume during rtl manipulations that
1853 ;; it does, but tell the final scan operator the truth. Similarly for
1856 (define_insn "abssi2"
1857 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1858 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1862 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
1863 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
1864 [(set_attr "conds" "clob,*")
1865 (set_attr "length" "8")])
1867 (define_insn "*neg_abssi2"
1868 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1869 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1873 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
1874 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
1875 [(set_attr "conds" "clob,*")
1876 (set_attr "length" "8")])
1878 (define_insn "abssf2"
1879 [(set (match_operand:SF 0 "s_register_operand" "=f")
1880 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1883 [(set_attr "type" "ffarith")])
1885 (define_insn "absdf2"
1886 [(set (match_operand:DF 0 "s_register_operand" "=f")
1887 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1890 [(set_attr "type" "ffarith")])
1892 (define_insn "*absdf_esfdf"
1893 [(set (match_operand:DF 0 "s_register_operand" "=f")
1894 (abs:DF (float_extend:DF
1895 (match_operand:SF 1 "s_register_operand" "f"))))]
1898 [(set_attr "type" "ffarith")])
1900 (define_insn "absxf2"
1901 [(set (match_operand:XF 0 "s_register_operand" "=f")
1902 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1903 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1905 [(set_attr "type" "ffarith")])
1907 (define_insn "sqrtsf2"
1908 [(set (match_operand:SF 0 "s_register_operand" "=f")
1909 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1912 [(set_attr "type" "float_em")])
1914 (define_insn "sqrtdf2"
1915 [(set (match_operand:DF 0 "s_register_operand" "=f")
1916 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1919 [(set_attr "type" "float_em")])
1921 (define_insn "*sqrtdf_esfdf"
1922 [(set (match_operand:DF 0 "s_register_operand" "=f")
1923 (sqrt:DF (float_extend:DF
1924 (match_operand:SF 1 "s_register_operand" "f"))))]
1927 [(set_attr "type" "float_em")])
1929 (define_insn "sqrtxf2"
1930 [(set (match_operand:XF 0 "s_register_operand" "=f")
1931 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1932 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1934 [(set_attr "type" "float_em")])
1936 ;; SIN COS TAN and family are always emulated, so it's probably better
1937 ;; to always call a library function.
1938 ;(define_insn "sinsf2"
1939 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
1940 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1941 ; "TARGET_HARD_FLOAT"
1943 ;[(set_attr "type" "float_em")])
1945 ;(define_insn "sindf2"
1946 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
1947 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1948 ; "TARGET_HARD_FLOAT"
1950 ;[(set_attr "type" "float_em")])
1952 ;(define_insn "*sindf_esfdf"
1953 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
1954 ; (unspec:DF [(float_extend:DF
1955 ; (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1956 ; "TARGET_HARD_FLOAT"
1958 ;[(set_attr "type" "float_em")])
1960 ;(define_insn "sinxf2"
1961 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
1962 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1963 ; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1965 ;[(set_attr "type" "float_em")])
1967 ;(define_insn "cossf2"
1968 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
1969 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
1970 ; "TARGET_HARD_FLOAT"
1972 ;[(set_attr "type" "float_em")])
1974 ;(define_insn "cosdf2"
1975 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
1976 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
1977 ; "TARGET_HARD_FLOAT"
1979 ;[(set_attr "type" "float_em")])
1981 ;(define_insn "*cosdf_esfdf"
1982 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
1983 ; (unspec:DF [(float_extend:DF
1984 ; (match_operand:SF 1 "s_register_operand" "f"))] 1))]
1985 ; "TARGET_HARD_FLOAT"
1987 ;[(set_attr "type" "float_em")])
1989 ;(define_insn "cosxf2"
1990 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
1991 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
1992 ; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1994 ;[(set_attr "type" "float_em")])
1996 (define_insn "one_cmpldi2"
1997 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1998 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2000 "mvn%?\\t%Q0, %Q1\;mvn%?\\t%R0, %R1"
2001 [(set_attr "length" "8")])
2003 (define_insn "one_cmplsi2"
2004 [(set (match_operand:SI 0 "s_register_operand" "=r")
2005 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2009 (define_insn "*notsi_compare0"
2010 [(set (reg:CC_NOOV 24)
2011 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2013 (set (match_operand:SI 0 "s_register_operand" "=r")
2014 (not:SI (match_dup 1)))]
2017 [(set_attr "conds" "set")])
2019 (define_insn "*notsi_compare0_scratch"
2020 [(set (reg:CC_NOOV 24)
2021 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2023 (clobber (match_scratch:SI 0 "=r"))]
2026 [(set_attr "conds" "set")])
2028 ;; Fixed <--> Floating conversion insns
2030 (define_insn "floatsisf2"
2031 [(set (match_operand:SF 0 "s_register_operand" "=f")
2032 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2035 [(set_attr "type" "r_2_f")])
2037 (define_insn "floatsidf2"
2038 [(set (match_operand:DF 0 "s_register_operand" "=f")
2039 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2042 [(set_attr "type" "r_2_f")])
2044 (define_insn "floatsixf2"
2045 [(set (match_operand:XF 0 "s_register_operand" "=f")
2046 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
2047 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2049 [(set_attr "type" "r_2_f")])
2051 (define_insn "fix_truncsfsi2"
2052 [(set (match_operand:SI 0 "s_register_operand" "=r")
2053 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2056 [(set_attr "type" "f_2_r")])
2058 (define_insn "fix_truncdfsi2"
2059 [(set (match_operand:SI 0 "s_register_operand" "=r")
2060 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2063 [(set_attr "type" "f_2_r")])
2065 (define_insn "fix_truncxfsi2"
2066 [(set (match_operand:SI 0 "s_register_operand" "=r")
2067 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
2068 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2070 [(set_attr "type" "f_2_r")])
2074 (define_insn "truncdfsf2"
2075 [(set (match_operand:SF 0 "s_register_operand" "=f")
2077 (match_operand:DF 1 "s_register_operand" "f")))]
2080 [(set_attr "type" "ffarith")])
2082 (define_insn "truncxfsf2"
2083 [(set (match_operand:SF 0 "s_register_operand" "=f")
2085 (match_operand:XF 1 "s_register_operand" "f")))]
2086 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2088 [(set_attr "type" "ffarith")])
2090 (define_insn "truncxfdf2"
2091 [(set (match_operand:DF 0 "s_register_operand" "=f")
2093 (match_operand:XF 1 "s_register_operand" "f")))]
2094 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2096 [(set_attr "type" "ffarith")])
2098 ;; Zero and sign extension instructions.
2100 (define_insn "zero_extendsidi2"
2101 [(set (match_operand:DI 0 "s_register_operand" "=r")
2102 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2105 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2106 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2107 return \"mov%?\\t%R0, #0\";
2109 [(set_attr "length" "8")])
2111 (define_insn "zero_extendqidi2"
2112 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2113 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2116 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2117 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2118 [(set_attr "length" "8")
2119 (set_attr "type" "*,load")])
2121 (define_insn "extendsidi2"
2122 [(set (match_operand:DI 0 "s_register_operand" "=r")
2123 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2126 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2127 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2128 return \"mov%?\\t%R0, %Q0, asr #31\";
2130 [(set_attr "length" "8")])
2132 (define_expand "zero_extendhisi2"
2133 [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2135 (set (match_operand:SI 0 "s_register_operand" "")
2136 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2140 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2142 emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2143 gen_rtx (ZERO_EXTEND, SImode, operands[1])));
2146 if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2148 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2151 if (! s_register_operand (operands[1], HImode))
2152 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2153 operands[1] = gen_lowpart (SImode, operands[1]);
2154 operands[2] = gen_reg_rtx (SImode);
2157 (define_insn "*zero_extendhisi_insn"
2158 [(set (match_operand:SI 0 "s_register_operand" "=r")
2159 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2162 [(set_attr "type" "load")])
2165 [(set (match_operand:SI 0 "s_register_operand" "")
2166 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2167 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2169 [(set (match_dup 2) (match_dup 1))
2170 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2173 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2178 [(set (match_operand:SI 0 "s_register_operand" "")
2179 (match_operator:SI 3 "shiftable_operator"
2180 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2181 (match_operand:SI 4 "s_register_operand" "")]))
2182 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2184 [(set (match_dup 2) (match_dup 1))
2187 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2190 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2194 (define_expand "zero_extendqisi2"
2195 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2197 (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2200 if (GET_CODE (operands[1]) != MEM)
2202 emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
2208 (define_insn "*load_extendqisi"
2209 [(set (match_operand:SI 0 "s_register_operand" "=r")
2210 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2212 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
2213 [(set_attr "type" "load")])
2216 [(set (match_operand:SI 0 "s_register_operand" "")
2217 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
2218 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2219 "GET_CODE (operands[1]) != MEM"
2220 [(set (match_dup 2) (match_dup 1))
2221 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
2224 (define_insn "*compareqi_eq0"
2226 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
2230 [(set_attr "conds" "set")])
2232 (define_expand "extendhisi2"
2234 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2236 (set (match_operand:SI 0 "s_register_operand" "")
2237 (ashiftrt:SI (match_dup 2)
2242 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2244 emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2245 gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2249 if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2251 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
2254 if (! s_register_operand (operands[1], HImode))
2255 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2256 operands[1] = gen_lowpart (SImode, operands[1]);
2257 operands[2] = gen_reg_rtx (SImode);
2260 (define_expand "extendhisi2_mem"
2261 [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" ""))))
2263 (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1)))))
2264 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
2265 (set (match_operand:SI 0 "" "")
2266 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
2269 operands[0] = gen_lowpart (SImode, operands[0]);
2270 operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2271 operands[2] = gen_reg_rtx (SImode);
2272 operands[3] = gen_reg_rtx (SImode);
2273 operands[6] = gen_reg_rtx (SImode);
2275 if (BYTES_BIG_ENDIAN)
2277 operands[4] = operands[2];
2278 operands[5] = operands[3];
2282 operands[4] = operands[3];
2283 operands[5] = operands[2];
2287 (define_insn "*extendhisi_insn"
2288 [(set (match_operand:SI 0 "s_register_operand" "=r")
2289 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2292 [(set_attr "type" "load")])
2295 [(set (match_operand:SI 0 "s_register_operand" "")
2296 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2297 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2299 [(set (match_dup 2) (match_dup 1))
2300 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
2303 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2308 [(set (match_operand:SI 0 "s_register_operand" "")
2309 (match_operator:SI 3 "shiftable_operator"
2310 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2311 (match_operand:SI 4 "s_register_operand" "")]))
2312 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2314 [(set (match_dup 2) (match_dup 1))
2317 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2320 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2324 (define_expand "extendqihi2"
2326 (ashift:SI (match_operand:QI 1 "general_operand" "")
2328 (set (match_operand:HI 0 "s_register_operand" "")
2329 (ashiftrt:SI (match_dup 2)
2334 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2336 emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2337 gen_rtx (SIGN_EXTEND, HImode, operands[1])));
2340 if (! s_register_operand (operands[1], QImode))
2341 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2342 operands[0] = gen_lowpart (SImode, operands[0]);
2343 operands[1] = gen_lowpart (SImode, operands[1]);
2344 operands[2] = gen_reg_rtx (SImode);
2347 (define_insn "*extendqihi_insn"
2348 [(set (match_operand:HI 0 "s_register_operand" "=r")
2349 (sign_extend:HI (match_operand:QI 1 "memory_operand" "o<>")))]
2352 [(set_attr "type" "load")])
2354 (define_expand "extendqisi2"
2356 (ashift:SI (match_operand:QI 1 "s_register_operand" "")
2358 (set (match_operand:SI 0 "s_register_operand" "")
2359 (ashiftrt:SI (match_dup 2)
2364 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2366 emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2367 gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2370 if (! s_register_operand (operands[1], QImode))
2371 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2372 operands[1] = gen_lowpart (SImode, operands[1]);
2373 operands[2] = gen_reg_rtx (SImode);
2376 (define_insn "*extendqisi_insn"
2377 [(set (match_operand:SI 0 "s_register_operand" "=r")
2378 (sign_extend:SI (match_operand:QI 1 "memory_operand" "o<>")))]
2381 [(set_attr "type" "load")])
2383 (define_insn "extendsfdf2"
2384 [(set (match_operand:DF 0 "s_register_operand" "=f")
2385 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2388 [(set_attr "type" "ffarith")])
2390 (define_insn "extendsfxf2"
2391 [(set (match_operand:XF 0 "s_register_operand" "=f")
2392 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2393 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2395 [(set_attr "type" "ffarith")])
2397 (define_insn "extenddfxf2"
2398 [(set (match_operand:XF 0 "s_register_operand" "=f")
2399 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2400 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2402 [(set_attr "type" "ffarith")])
2405 ;; Move insns (including loads and stores)
2407 ;; XXX Just some ideas about movti.
2408 ;; I don't think these are a good idea on the arm, there just aren't enough
2410 ;;(define_expand "loadti"
2411 ;; [(set (match_operand:TI 0 "s_register_operand" "")
2412 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
2415 ;;(define_expand "storeti"
2416 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2417 ;; (match_operand:TI 1 "s_register_operand" ""))]
2420 ;;(define_expand "movti"
2421 ;; [(set (match_operand:TI 0 "general_operand" "")
2422 ;; (match_operand:TI 1 "general_operand" ""))]
2428 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2429 ;; operands[1] = copy_to_reg (operands[1]);
2430 ;; if (GET_CODE (operands[0]) == MEM)
2431 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2432 ;; else if (GET_CODE (operands[1]) == MEM)
2433 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2437 ;; emit_insn (insn);
2441 ;; Recognise garbage generated above.
2444 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2445 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2449 ;; register mem = (which_alternative < 3);
2450 ;; register char *template;
2452 ;; operands[mem] = XEXP (operands[mem], 0);
2453 ;; switch (which_alternative)
2455 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2456 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
2457 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
2458 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
2459 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
2460 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
2462 ;; output_asm_insn (template, operands);
2467 (define_insn "movdi"
2468 [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2469 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2472 return (output_move_double (operands));
2474 [(set_attr "length" "8,8,8")
2475 (set_attr "type" "*,load,store2")])
2477 (define_expand "movsi"
2478 [(set (match_operand:SI 0 "general_operand" "")
2479 (match_operand:SI 1 "general_operand" ""))]
2482 /* Everything except mem = const or mem = mem can be done easily */
2483 if (GET_CODE (operands[0]) == MEM)
2484 operands[1] = force_reg (SImode, operands[1]);
2485 if (GET_CODE (operands[1]) == CONST_INT
2486 && !(const_ok_for_arm (INTVAL (operands[1]))
2487 || const_ok_for_arm (~INTVAL (operands[1]))))
2489 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2491 (reload_in_progress || reload_completed ? 0
2492 : preserve_subexpressions_p ()));
2495 if (CONSTANT_P (operands[1]) && flag_pic)
2496 operands[1] = legitimize_pic_address (operands[1], SImode,
2497 ((reload_in_progress
2498 || reload_completed)
2499 ? operands[0] : 0));
2502 (define_insn "*movsi_insn"
2503 [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2504 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
2505 "register_operand (operands[0], SImode)
2506 || register_operand (operands[1], SImode)"
2512 [(set_attr "type" "*,*,load,store1")])
2515 [(set (match_operand:SI 0 "s_register_operand" "")
2516 (match_operand:SI 1 "const_int_operand" ""))]
2517 "! (const_ok_for_arm (INTVAL (operands[1]))
2518 || const_ok_for_arm (~INTVAL (operands[1])))"
2519 [(clobber (const_int 0))]
2521 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2526 (define_expand "movaddr"
2527 [(set (match_operand:SI 0 "s_register_operand" "")
2528 (match_operand:DI 1 "address_operand" ""))]
2532 (define_insn "*movaddr_insn"
2533 [(set (match_operand:SI 0 "s_register_operand" "=r")
2534 (match_operand:DI 1 "address_operand" "p"))]
2536 && (GET_CODE (operands[1]) == LABEL_REF
2537 || (GET_CODE (operands[1]) == CONST
2538 && GET_CODE (XEXP (operands[1], 0)) == PLUS
2539 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2540 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2543 /* When generating pic, we need to load the symbol offset into a register.
2544 So that the optimizer does not confuse this with a normal symbol load
2545 we use an unspec. The offset will be loaded from a constant pool entry,
2546 since that is the only type of relocation we can use. */
2548 (define_insn "pic_load_addr"
2549 [(set (match_operand:SI 0 "s_register_operand" "=r")
2550 (unspec:SI [(match_operand 1 "" "")] 3))]
2553 [(set_attr "type" "load")])
2555 ;; This variant is used for AOF assembly, since it needs to mention the
2556 ;; pic register in the rtl.
2557 (define_expand "pic_load_addr_based"
2558 [(set (match_operand:SI 0 "s_register_operand" "=r")
2559 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
2561 "operands[2] = pic_offset_table_rtx;")
2563 (define_insn "*pic_load_addr_based_insn"
2564 [(set (match_operand:SI 0 "s_register_operand" "=r")
2565 (unspec:SI [(match_operand 1 "" "")
2566 (match_operand 2 "s_register_operand" "r")] 3))]
2567 "flag_pic && operands[2] == pic_offset_table_rtx"
2569 #ifdef AOF_ASSEMBLER
2570 operands[1] = aof_pic_entry (operands[1]);
2572 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
2574 " [(set_attr "type" "load")])
2576 (define_insn "pic_add_dot_plus_eight"
2577 [(set (pc) (label_ref (match_operand 0 "" "")))
2578 (set (match_operand 1 "register_operand" "+r")
2579 (plus:SI (match_dup 1) (const (plus:SI (pc) (const_int 8)))))]
2581 "add%?\\t%1, %|pc, %1")
2583 ;; If copying one reg to another we can set the condition codes according to
2584 ;; its value. Such a move is common after a return from subroutine and the
2585 ;; result is being tested against zero.
2587 (define_insn "*movsi_compare0"
2588 [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
2590 (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2594 sub%?s\\t%0, %1, #0"
2595 [(set_attr "conds" "set")])
2597 ;; Subroutine to store a half word from a register into memory.
2598 ;; Operand 0 is the source register (HImode)
2599 ;; Operand 1 is the destination address in a register (SImode)
2601 ;; In both this routine and the next, we must be careful not to spill
2602 ;; a memory address of reg+large_const into a separate PLUS insn, since this
2603 ;; can generate unrecognizable rtl.
2605 (define_expand "storehi"
2606 [;; store the low byte
2607 (set (match_operand 1 "" "") (match_dup 3))
2608 ;; extract the high byte
2610 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2611 ;; store the high byte
2612 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
2616 rtx addr = XEXP (operands[1], 0);
2617 enum rtx_code code = GET_CODE (addr);
2619 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2621 addr = force_reg (SImode, addr);
2623 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2624 operands[1] = change_address (operands[1], QImode, NULL_RTX);
2625 operands[3] = gen_lowpart (QImode, operands[0]);
2626 operands[0] = gen_lowpart (SImode, operands[0]);
2627 operands[2] = gen_reg_rtx (SImode);
2631 (define_expand "storehi_bigend"
2632 [(set (match_dup 4) (match_dup 3))
2634 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2635 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
2639 rtx addr = XEXP (operands[1], 0);
2640 enum rtx_code code = GET_CODE (addr);
2642 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2644 addr = force_reg (SImode, addr);
2646 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2647 operands[1] = change_address (operands[1], QImode, NULL_RTX);
2648 operands[3] = gen_lowpart (QImode, operands[0]);
2649 operands[0] = gen_lowpart (SImode, operands[0]);
2650 operands[2] = gen_reg_rtx (SImode);
2654 ;; Subroutine to store a half word integer constant into memory.
2655 (define_expand "storeinthi"
2656 [(set (match_operand 0 "" "")
2657 (subreg:QI (match_operand 1 "" "") 0))
2658 (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
2662 HOST_WIDE_INT value = INTVAL (operands[1]);
2663 rtx addr = XEXP (operands[0], 0);
2664 enum rtx_code code = GET_CODE (addr);
2666 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2668 addr = force_reg (SImode, addr);
2670 operands[1] = gen_reg_rtx (SImode);
2671 if (BYTES_BIG_ENDIAN)
2673 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2674 if ((value & 255) == ((value >> 8) & 255))
2675 operands[2] = operands[1];
2678 operands[2] = gen_reg_rtx (SImode);
2679 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2684 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2685 if ((value & 255) == ((value >> 8) & 255))
2686 operands[2] = operands[1];
2689 operands[2] = gen_reg_rtx (SImode);
2690 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2694 operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
2695 operands[0] = change_address (operands[0], QImode, NULL_RTX);
2699 (define_expand "storehi_single_op"
2700 [(set (match_operand:HI 0 "memory_operand" "")
2701 (match_operand:HI 1 "general_operand" ""))]
2704 if (! s_register_operand (operands[1], HImode))
2705 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2708 (define_expand "movhi"
2709 [(set (match_operand:HI 0 "general_operand" "")
2710 (match_operand:HI 1 "general_operand" ""))]
2716 if (! (reload_in_progress || reload_completed))
2718 if (GET_CODE (operands[0]) == MEM)
2722 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2725 if (GET_CODE (operands[1]) == CONST_INT)
2726 emit_insn (gen_storeinthi (operands[0], operands[1]));
2729 if (GET_CODE (operands[1]) == MEM)
2730 operands[1] = force_reg (HImode, operands[1]);
2731 if (BYTES_BIG_ENDIAN)
2732 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
2734 emit_insn (gen_storehi (operands[1], operands[0]));
2738 /* Sign extend a constant, and keep it in an SImode reg. */
2739 else if (GET_CODE (operands[1]) == CONST_INT)
2741 rtx reg = gen_reg_rtx (SImode);
2742 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2744 /* If the constant is already valid, leave it alone. */
2745 if (! const_ok_for_arm (val))
2747 /* If setting all the top bits will make the constant
2748 loadable in a single instruction, then set them.
2749 Otherwise, sign extend the number. */
2751 if (const_ok_for_arm (~ (val | ~0xffff)))
2753 else if (val & 0x8000)
2757 emit_insn (gen_movsi (reg, GEN_INT (val)));
2758 operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
2760 else if (! arm_arch4)
2762 if (GET_CODE (operands[1]) == MEM)
2764 if (TARGET_SHORT_BY_BYTES)
2767 rtx offset = const0_rtx;
2768 rtx reg = gen_reg_rtx (SImode);
2770 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2771 || (GET_CODE (base) == PLUS
2772 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2773 && GET_CODE (base = XEXP (base, 0)) == REG))
2774 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2776 HOST_WIDE_INT new_offset = INTVAL (offset) & ~2;
2778 emit_insn (gen_movsi (reg, gen_rtx (MEM, SImode,
2779 plus_constant (base, new_offset))));
2780 if (((INTVAL (offset) & 2) != 0)
2781 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
2783 rtx reg2 = gen_reg_rtx (SImode);
2785 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
2790 emit_insn (gen_movhi_bytes (reg, operands[1]));
2792 operands[1] = gen_lowpart (HImode, reg);
2794 else if (BYTES_BIG_ENDIAN)
2797 rtx offset = const0_rtx;
2799 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2800 || (GET_CODE (base) == PLUS
2801 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2802 && GET_CODE (base = XEXP (base, 0)) == REG))
2803 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2805 rtx reg = gen_reg_rtx (SImode);
2808 if ((INTVAL (offset) & 2) == 2)
2810 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
2811 new_mem = gen_rtx (MEM, SImode,
2812 plus_constant (base, new_offset));
2814 emit_insn (gen_movsi (reg, new_mem));
2818 new_mem = gen_rtx (MEM, SImode,
2819 XEXP (operands[1], 0));
2820 emit_insn (gen_rotated_loadsi (reg, new_mem));
2823 operands[1] = gen_lowpart (HImode, reg);
2827 emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2834 /* Handle loading a large integer during reload */
2835 else if (GET_CODE (operands[1]) == CONST_INT
2836 && ! const_ok_for_arm (INTVAL (operands[1]))
2837 && ! const_ok_for_arm (~INTVAL (operands[1])))
2839 /* Writing a constant to memory needs a scratch, which should
2840 be handled with SECONDARY_RELOADs. */
2841 if (GET_CODE (operands[0]) != REG)
2844 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
2845 emit_insn (gen_movsi (operands[0], operands[1]));
2851 (define_insn "rotated_loadsi"
2852 [(set (match_operand:SI 0 "s_register_operand" "=r")
2853 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
2855 "! TARGET_SHORT_BY_BYTES"
2860 ops[0] = operands[0];
2861 ops[1] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 2));
2862 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
2865 [(set_attr "type" "load")])
2867 (define_expand "movhi_bytes"
2868 [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" ""))))
2870 (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1)))))
2871 (set (match_operand:SI 0 "" "")
2872 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
2875 operands[0] = gen_lowpart (SImode, operands[0]);
2876 operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2877 operands[2] = gen_reg_rtx (SImode);
2878 operands[3] = gen_reg_rtx (SImode);
2880 if (BYTES_BIG_ENDIAN)
2882 operands[4] = operands[2];
2883 operands[5] = operands[3];
2887 operands[4] = operands[3];
2888 operands[5] = operands[2];
2892 (define_expand "movhi_bigend"
2894 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
2897 (ashiftrt:SI (match_dup 2) (const_int 16)))
2898 (set (match_operand:HI 0 "s_register_operand" "")
2899 (subreg:HI (match_dup 3) 0))]
2902 operands[2] = gen_reg_rtx (SImode);
2903 operands[3] = gen_reg_rtx (SImode);
2906 ;; Pattern to recognise insn generated default case above
2908 (define_insn "*movhi_insn_arch4"
2909 [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
2910 (match_operand:HI 1 "general_operand" "rI,K,m,r"))]
2912 && (GET_CODE (operands[1]) != CONST_INT
2913 || const_ok_for_arm (INTVAL (operands[1]))
2914 || const_ok_for_arm (~INTVAL (operands[1])))"
2916 mov%?\\t%0, %1\\t%@ movhi
2917 mvn%?\\t%0, #%B1\\t%@ movhi
2918 ldr%?h\\t%0, %1\\t%@ movhi
2919 str%?h\\t%1, %0\\t%@ movhi"
2920 [(set_attr "type" "*,*,load,store1")])
2922 (define_insn "*movhi_insn_littleend"
2923 [(set (match_operand:HI 0 "general_operand" "=r,r,r")
2924 (match_operand:HI 1 "general_operand" "rI,K,m"))]
2926 && ! BYTES_BIG_ENDIAN
2927 && ! TARGET_SHORT_BY_BYTES
2928 && (GET_CODE (operands[1]) != CONST_INT
2929 || const_ok_for_arm (INTVAL (operands[1]))
2930 || const_ok_for_arm (~INTVAL (operands[1])))"
2932 mov%?\\t%0, %1\\t%@ movhi
2933 mvn%?\\t%0, #%B1\\t%@ movhi
2934 ldr%?\\t%0, %1\\t%@ movhi"
2935 [(set_attr "type" "*,*,load")])
2937 (define_insn "*movhi_insn_bigend"
2938 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
2939 (match_operand:HI 1 "general_operand" "rI,K,m"))]
2942 && ! TARGET_SHORT_BY_BYTES
2943 && (GET_CODE (operands[1]) != CONST_INT
2944 || const_ok_for_arm (INTVAL (operands[1]))
2945 || const_ok_for_arm (~INTVAL (operands[1])))"
2947 mov%?\\t%0, %1\\t%@ movhi
2948 mvn%?\\t%0, #%B1\\t%@ movhi
2949 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
2950 [(set_attr "type" "*,*,load")
2951 (set_attr "length" "4,4,8")])
2953 (define_insn "*loadhi_si_bigend"
2954 [(set (match_operand:SI 0 "s_register_operand" "=r")
2955 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
2958 && ! TARGET_SHORT_BY_BYTES"
2959 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
2960 [(set_attr "type" "load")])
2962 (define_insn "*movhi_bytes"
2963 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
2964 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
2965 "TARGET_SHORT_BY_BYTES"
2967 mov%?\\t%0, %1\\t%@ movhi
2968 mvn%?\\t%0, #%B1\\t%@ movhi")
2971 (define_expand "reload_outhi"
2972 [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
2973 (match_operand:HI 1 "s_register_operand" "r")
2974 (match_operand:SI 2 "s_register_operand" "=&r")])]
2977 arm_reload_out_hi (operands);
2981 (define_expand "reload_inhi"
2982 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
2983 (match_operand:HI 1 "reload_memory_operand" "o")
2984 (match_operand:SI 2 "s_register_operand" "=&r")])]
2985 "TARGET_SHORT_BY_BYTES"
2987 arm_reload_in_hi (operands);
2991 (define_expand "movqi"
2992 [(set (match_operand:QI 0 "general_operand" "")
2993 (match_operand:QI 1 "general_operand" ""))]
2996 /* Everything except mem = const or mem = mem can be done easily */
2998 if (!(reload_in_progress || reload_completed))
3000 if (GET_CODE (operands[1]) == CONST_INT)
3002 rtx reg = gen_reg_rtx (SImode);
3004 emit_insn (gen_movsi (reg, operands[1]));
3005 operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
3007 if (GET_CODE (operands[0]) == MEM)
3008 operands[1] = force_reg (QImode, operands[1]);
3013 (define_insn "*movqi_insn"
3014 [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
3015 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
3016 "register_operand (operands[0], QImode)
3017 || register_operand (operands[1], QImode)"
3023 [(set_attr "type" "*,*,load,store1")])
3025 (define_expand "movsf"
3026 [(set (match_operand:SF 0 "general_operand" "")
3027 (match_operand:SF 1 "general_operand" ""))]
3030 if (GET_CODE (operands[0]) == MEM)
3031 operands[1] = force_reg (SFmode, operands[1]);
3034 (define_insn "*movsf_hard_insn"
3035 [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
3036 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
3038 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3044 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
3045 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
3047 ldr%?\\t%0, %1\\t%@ float
3048 str%?\\t%1, %0\\t%@ float"
3049 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
3051 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
3053 ;; Exactly the same as above, except that all `f' cases are deleted.
3054 ;; This is necessary to prevent reload from ever trying to use a `f' reg
3055 ;; when -msoft-float.
3057 (define_insn "*movsf_soft_insn"
3058 [(set (match_operand:SF 0 "general_operand" "=r,r,m")
3059 (match_operand:SF 1 "general_operand" "r,mE,r"))]
3061 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3064 ldr%?\\t%0, %1\\t%@ float
3065 str%?\\t%1, %0\\t%@ float"
3066 [(set_attr "length" "4,4,4")
3067 (set_attr "type" "*,load,store1")])
3069 (define_expand "movdf"
3070 [(set (match_operand:DF 0 "general_operand" "")
3071 (match_operand:DF 1 "general_operand" ""))]
3074 if (GET_CODE (operands[0]) == MEM)
3075 operands[1] = force_reg (DFmode, operands[1]);
3078 ;; Reloading a df mode value stored in integer regs to memory can require a
3080 (define_expand "reload_outdf"
3081 [(match_operand:DF 0 "reload_memory_operand" "=o")
3082 (match_operand:DF 1 "s_register_operand" "r")
3083 (match_operand:SI 2 "s_register_operand" "=&r")]
3087 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
3090 operands[2] = XEXP (operands[0], 0);
3091 else if (code == POST_INC || code == PRE_DEC)
3093 operands[0] = gen_rtx (SUBREG, DImode, operands[0], 0);
3094 operands[1] = gen_rtx (SUBREG, DImode, operands[1], 0);
3095 emit_insn (gen_movdi (operands[0], operands[1]));
3098 else if (code == PRE_INC)
3100 rtx reg = XEXP (XEXP (operands[0], 0), 0);
3101 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
3104 else if (code == POST_DEC)
3105 operands[2] = XEXP (XEXP (operands[0], 0), 0);
3107 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
3108 XEXP (XEXP (operands[0], 0), 1)));
3110 emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, DFmode, operands[2]),
3113 if (code == POST_DEC)
3114 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
3120 (define_insn "*movdf_hard_insn"
3121 [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
3122 (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
3124 && (GET_CODE (operands[0]) != MEM
3125 || register_operand (operands[1], DFmode))"
3130 switch (which_alternative)
3132 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
3133 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
3134 case 2: case 3: case 4: return output_move_double (operands);
3135 case 5: return \"mvf%?d\\t%0, %1\";
3136 case 6: return \"mnf%?d\\t%0, #%N1\";
3137 case 7: return \"ldf%?d\\t%0, %1\";
3138 case 8: return \"stf%?d\\t%1, %0\";
3139 case 9: return output_mov_double_fpu_from_arm (operands);
3140 case 10: return output_mov_double_arm_from_fpu (operands);
3144 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
3146 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
3148 ;; Software floating point version. This is essentially the same as movdi.
3149 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
3152 (define_insn "*movdf_soft_insn"
3153 [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
3154 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
3156 "* return output_move_double (operands);"
3157 [(set_attr "length" "8,8,8")
3158 (set_attr "type" "*,load,store2")])
3160 (define_expand "movxf"
3161 [(set (match_operand:XF 0 "general_operand" "")
3162 (match_operand:XF 1 "general_operand" ""))]
3163 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3166 ;; Even when the XFmode patterns aren't enabled, we enable this after
3167 ;; reloading so that we can push floating point registers in the prologue.
3169 (define_insn "*movxf_hard_insn"
3170 [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
3171 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
3172 "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
3174 switch (which_alternative)
3176 case 0: return \"mvf%?e\\t%0, %1\";
3177 case 1: return \"mnf%?e\\t%0, #%N1\";
3178 case 2: return \"ldf%?e\\t%0, %1\";
3179 case 3: return \"stf%?e\\t%1, %0\";
3180 case 4: return output_mov_long_double_fpu_from_arm (operands);
3181 case 5: return output_mov_long_double_arm_from_fpu (operands);
3182 case 6: return output_mov_long_double_arm_from_arm (operands);
3185 [(set_attr "length" "4,4,4,4,8,8,12")
3186 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
3189 ;; load- and store-multiple insns
3190 ;; The arm can load/store any set of registers, provided that they are in
3191 ;; ascending order; but that is beyond GCC so stick with what it knows.
3193 (define_expand "load_multiple"
3194 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3195 (match_operand:SI 1 "" ""))
3196 (use (match_operand:SI 2 "" ""))])]
3199 /* Support only fixed point registers */
3200 if (GET_CODE (operands[2]) != CONST_INT
3201 || INTVAL (operands[2]) > 14
3202 || INTVAL (operands[2]) < 2
3203 || GET_CODE (operands[1]) != MEM
3204 || GET_CODE (operands[0]) != REG
3205 || REGNO (operands[0]) > 14
3206 || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
3210 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
3211 force_reg (SImode, XEXP (operands[1], 0)),
3212 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
3213 MEM_IN_STRUCT_P(operands[1]));
3216 ;; Load multiple with write-back
3218 (define_insn "*ldmsi_postinc"
3219 [(match_parallel 0 "load_multiple_operation"
3220 [(set (match_operand:SI 1 "s_register_operand" "+r")
3221 (plus:SI (match_dup 1)
3222 (match_operand:SI 2 "const_int_operand" "n")))
3223 (set (match_operand:SI 3 "s_register_operand" "=r")
3224 (mem:SI (match_dup 1)))])]
3225 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3229 int count = XVECLEN (operands[0], 0);
3231 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3232 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
3233 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
3235 output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
3239 [(set_attr "type" "load")])
3241 ;; Ordinary load multiple
3243 (define_insn "*ldmsi"
3244 [(match_parallel 0 "load_multiple_operation"
3245 [(set (match_operand:SI 1 "s_register_operand" "=r")
3246 (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
3251 int count = XVECLEN (operands[0], 0);
3253 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3254 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
3255 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
3257 output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
3261 [(set_attr "type" "load")])
3263 (define_expand "store_multiple"
3264 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3265 (match_operand:SI 1 "" ""))
3266 (use (match_operand:SI 2 "" ""))])]
3269 /* Support only fixed point registers */
3270 if (GET_CODE (operands[2]) != CONST_INT
3271 || INTVAL (operands[2]) > 14
3272 || INTVAL (operands[2]) < 2
3273 || GET_CODE (operands[1]) != REG
3274 || GET_CODE (operands[0]) != MEM
3275 || REGNO (operands[1]) > 14
3276 || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
3280 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
3281 force_reg (SImode, XEXP (operands[0], 0)),
3282 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
3283 MEM_IN_STRUCT_P(operands[0]));
3286 ;; Store multiple with write-back
3288 (define_insn "*stmsi_postinc"
3289 [(match_parallel 0 "store_multiple_operation"
3290 [(set (match_operand:SI 1 "s_register_operand" "+r")
3291 (plus:SI (match_dup 1)
3292 (match_operand:SI 2 "const_int_operand" "n")))
3293 (set (mem:SI (match_dup 1))
3294 (match_operand:SI 3 "s_register_operand" "r"))])]
3295 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3299 int count = XVECLEN (operands[0], 0);
3301 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3302 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
3303 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
3305 output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
3310 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3311 (const_string "store2")
3312 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
3313 (const_string "store3")]
3314 (const_string "store4")))])
3316 ;; Ordinary store multiple
3318 (define_insn "*stmsi"
3319 [(match_parallel 0 "store_multiple_operation"
3320 [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
3321 (match_operand:SI 1 "s_register_operand" "r"))])]
3326 int count = XVECLEN (operands[0], 0);
3328 ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
3329 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
3330 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
3332 output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
3337 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
3338 (const_string "store2")
3339 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3340 (const_string "store3")]
3341 (const_string "store4")))])
3343 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
3344 ;; We could let this apply for blocks of less than this, but it clobbers so
3345 ;; many registers that there is then probably a better way.
3347 (define_expand "movstrqi"
3348 [(match_operand:BLK 0 "general_operand" "")
3349 (match_operand:BLK 1 "general_operand" "")
3350 (match_operand:SI 2 "const_int_operand" "")
3351 (match_operand:SI 3 "const_int_operand" "")]
3354 if (arm_gen_movstrqi (operands))
3360 ;; Comparison and test insns
3362 (define_expand "cmpsi"
3363 [(match_operand:SI 0 "s_register_operand" "")
3364 (match_operand:SI 1 "arm_add_operand" "")]
3368 arm_compare_op0 = operands[0];
3369 arm_compare_op1 = operands[1];
3375 (define_expand "cmpsf"
3376 [(match_operand:SF 0 "s_register_operand" "")
3377 (match_operand:SF 1 "fpu_rhs_operand" "")]
3381 arm_compare_op0 = operands[0];
3382 arm_compare_op1 = operands[1];
3388 (define_expand "cmpdf"
3389 [(match_operand:DF 0 "s_register_operand" "")
3390 (match_operand:DF 1 "fpu_rhs_operand" "")]
3394 arm_compare_op0 = operands[0];
3395 arm_compare_op1 = operands[1];
3401 (define_expand "cmpxf"
3402 [(match_operand:XF 0 "s_register_operand" "")
3403 (match_operand:XF 1 "fpu_rhs_operand" "")]
3404 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3407 arm_compare_op0 = operands[0];
3408 arm_compare_op1 = operands[1];
3414 (define_insn "*cmpsi_insn"
3416 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3417 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3422 [(set_attr "conds" "set")])
3424 (define_insn "*cmpsi_shiftsi"
3426 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3427 (match_operator:SI 3 "shift_operator"
3428 [(match_operand:SI 1 "s_register_operand" "r")
3429 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3432 [(set_attr "conds" "set")])
3434 (define_insn "*cmpsi_shiftsi_swp"
3435 [(set (reg:CC_SWP 24)
3436 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
3437 [(match_operand:SI 1 "s_register_operand" "r")
3438 (match_operand:SI 2 "reg_or_int_operand" "rM")])
3439 (match_operand:SI 0 "s_register_operand" "r")))]
3442 [(set_attr "conds" "set")])
3444 (define_insn "*cmpsi_neg_shiftsi"
3446 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3447 (neg:SI (match_operator:SI 3 "shift_operator"
3448 [(match_operand:SI 1 "s_register_operand" "r")
3449 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3452 [(set_attr "conds" "set")])
3454 (define_insn "*cmpsf_insn"
3456 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3457 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3462 [(set_attr "conds" "set")
3463 (set_attr "type" "f_2_r")])
3465 (define_insn "*cmpdf_insn"
3467 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3468 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3473 [(set_attr "conds" "set")
3474 (set_attr "type" "f_2_r")])
3476 (define_insn "*cmpesfdf_df"
3478 (compare:CCFP (float_extend:DF
3479 (match_operand:SF 0 "s_register_operand" "f,f"))
3480 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3485 [(set_attr "conds" "set")
3486 (set_attr "type" "f_2_r")])
3488 (define_insn "*cmpdf_esfdf"
3490 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3492 (match_operand:SF 1 "s_register_operand" "f"))))]
3495 [(set_attr "conds" "set")
3496 (set_attr "type" "f_2_r")])
3498 (define_insn "*cmpxf_insn"
3500 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3501 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3502 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3506 [(set_attr "conds" "set")
3507 (set_attr "type" "f_2_r")])
3509 (define_insn "*cmpsf_trap"
3510 [(set (reg:CCFPE 24)
3511 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3512 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3517 [(set_attr "conds" "set")
3518 (set_attr "type" "f_2_r")])
3520 (define_insn "*cmpdf_trap"
3521 [(set (reg:CCFPE 24)
3522 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3523 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3528 [(set_attr "conds" "set")
3529 (set_attr "type" "f_2_r")])
3531 (define_insn "*cmp_esfdf_df_trap"
3532 [(set (reg:CCFPE 24)
3533 (compare:CCFPE (float_extend:DF
3534 (match_operand:SF 0 "s_register_operand" "f,f"))
3535 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3540 [(set_attr "conds" "set")
3541 (set_attr "type" "f_2_r")])
3543 (define_insn "*cmp_df_esfdf_trap"
3544 [(set (reg:CCFPE 24)
3545 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3547 (match_operand:SF 1 "s_register_operand" "f"))))]
3550 [(set_attr "conds" "set")
3551 (set_attr "type" "f_2_r")])
3553 (define_insn "*cmpxf_trap"
3554 [(set (reg:CCFPE 24)
3555 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3556 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3557 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3561 [(set_attr "conds" "set")
3562 (set_attr "type" "f_2_r")])
3564 ; This insn allows redundant compares to be removed by cse, nothing should
3565 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3566 ; is deleted later on. The match_dup will match the mode here, so that
3567 ; mode changes of the condition codes aren't lost by this even though we don't
3568 ; specify what they are.
3570 (define_insn "*deleted_compare"
3571 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3573 "\\t%@ deleted compare"
3574 [(set_attr "conds" "set")
3575 (set_attr "length" "0")])
3578 ;; Conditional branch insns
3580 (define_expand "beq"
3582 (if_then_else (eq (match_dup 1) (const_int 0))
3583 (label_ref (match_operand 0 "" ""))
3588 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3593 (define_expand "bne"
3595 (if_then_else (ne (match_dup 1) (const_int 0))
3596 (label_ref (match_operand 0 "" ""))
3601 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3606 (define_expand "bgt"
3608 (if_then_else (gt (match_dup 1) (const_int 0))
3609 (label_ref (match_operand 0 "" ""))
3614 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3619 (define_expand "ble"
3621 (if_then_else (le (match_dup 1) (const_int 0))
3622 (label_ref (match_operand 0 "" ""))
3627 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3632 (define_expand "bge"
3634 (if_then_else (ge (match_dup 1) (const_int 0))
3635 (label_ref (match_operand 0 "" ""))
3640 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3645 (define_expand "blt"
3647 (if_then_else (lt (match_dup 1) (const_int 0))
3648 (label_ref (match_operand 0 "" ""))
3653 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3658 (define_expand "bgtu"
3660 (if_then_else (gtu (match_dup 1) (const_int 0))
3661 (label_ref (match_operand 0 "" ""))
3666 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3671 (define_expand "bleu"
3673 (if_then_else (leu (match_dup 1) (const_int 0))
3674 (label_ref (match_operand 0 "" ""))
3679 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3684 (define_expand "bgeu"
3686 (if_then_else (geu (match_dup 1) (const_int 0))
3687 (label_ref (match_operand 0 "" ""))
3692 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3697 (define_expand "bltu"
3699 (if_then_else (ltu (match_dup 1) (const_int 0))
3700 (label_ref (match_operand 0 "" ""))
3705 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3710 ;; patterns to match conditional branch insns
3712 (define_insn "*condbranch"
3714 (if_then_else (match_operator 1 "comparison_operator"
3715 [(match_operand 2 "cc_register" "") (const_int 0)])
3716 (label_ref (match_operand 0 "" ""))
3721 extern int arm_ccfsm_state;
3723 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3725 arm_ccfsm_state += 2;
3728 return \"b%d1\\t%l0\";
3730 [(set_attr "conds" "use")])
3732 (define_insn "*condbranch_reversed"
3734 (if_then_else (match_operator 1 "comparison_operator"
3735 [(match_operand 2 "cc_register" "") (const_int 0)])
3737 (label_ref (match_operand 0 "" ""))))]
3741 extern int arm_ccfsm_state;
3743 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3745 arm_ccfsm_state += 2;
3748 return \"b%D1\\t%l0\";
3750 [(set_attr "conds" "use")])
3755 (define_expand "seq"
3756 [(set (match_operand:SI 0 "s_register_operand" "=r")
3757 (eq:SI (match_dup 1) (const_int 0)))]
3761 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3766 (define_expand "sne"
3767 [(set (match_operand:SI 0 "s_register_operand" "=r")
3768 (ne:SI (match_dup 1) (const_int 0)))]
3772 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3777 (define_expand "sgt"
3778 [(set (match_operand:SI 0 "s_register_operand" "=r")
3779 (gt:SI (match_dup 1) (const_int 0)))]
3783 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3788 (define_expand "sle"
3789 [(set (match_operand:SI 0 "s_register_operand" "=r")
3790 (le:SI (match_dup 1) (const_int 0)))]
3794 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3799 (define_expand "sge"
3800 [(set (match_operand:SI 0 "s_register_operand" "=r")
3801 (ge:SI (match_dup 1) (const_int 0)))]
3805 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3810 (define_expand "slt"
3811 [(set (match_operand:SI 0 "s_register_operand" "=r")
3812 (lt:SI (match_dup 1) (const_int 0)))]
3816 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3821 (define_expand "sgtu"
3822 [(set (match_operand:SI 0 "s_register_operand" "=r")
3823 (gtu:SI (match_dup 1) (const_int 0)))]
3827 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3832 (define_expand "sleu"
3833 [(set (match_operand:SI 0 "s_register_operand" "=r")
3834 (leu:SI (match_dup 1) (const_int 0)))]
3838 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3843 (define_expand "sgeu"
3844 [(set (match_operand:SI 0 "s_register_operand" "=r")
3845 (geu:SI (match_dup 1) (const_int 0)))]
3849 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3854 (define_expand "sltu"
3855 [(set (match_operand:SI 0 "s_register_operand" "=r")
3856 (ltu:SI (match_dup 1) (const_int 0)))]
3860 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3865 (define_insn "*mov_scc"
3866 [(set (match_operand:SI 0 "s_register_operand" "=r")
3867 (match_operator:SI 1 "comparison_operator"
3868 [(match_operand 2 "cc_register" "") (const_int 0)]))]
3870 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
3871 [(set_attr "conds" "use")
3872 (set_attr "length" "8")])
3874 (define_insn "*mov_negscc"
3875 [(set (match_operand:SI 0 "s_register_operand" "=r")
3876 (neg:SI (match_operator:SI 1 "comparison_operator"
3877 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3879 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
3880 [(set_attr "conds" "use")
3881 (set_attr "length" "8")])
3883 (define_insn "*mov_notscc"
3884 [(set (match_operand:SI 0 "s_register_operand" "=r")
3885 (not:SI (match_operator:SI 1 "comparison_operator"
3886 [(match_operand 2 "cc_register" "") (const_int 0)])))]
3888 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
3889 [(set_attr "conds" "use")
3890 (set_attr "length" "8")])
3893 ;; Conditional move insns
3895 (define_expand "movsicc"
3896 [(set (match_operand:SI 0 "s_register_operand" "")
3897 (if_then_else:SI (match_operand 1 "comparison_operator" "")
3898 (match_operand:SI 2 "arm_not_operand" "")
3899 (match_operand:SI 3 "arm_not_operand" "")))]
3903 enum rtx_code code = GET_CODE (operands[1]);
3904 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3907 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3910 (define_expand "movsfcc"
3911 [(set (match_operand:SF 0 "s_register_operand" "")
3912 (if_then_else:SF (match_operand 1 "comparison_operator" "")
3913 (match_operand:SF 2 "s_register_operand" "")
3914 (match_operand:SF 3 "nonmemory_operand" "")))]
3918 enum rtx_code code = GET_CODE (operands[1]);
3921 /* When compiling for SOFT_FLOAT, ensure both arms are in registers. */
3922 if (! TARGET_HARD_FLOAT)
3923 operands[3] = force_reg (SFmode, operands[3]);
3925 ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3928 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3931 (define_expand "movdfcc"
3932 [(set (match_operand:DF 0 "s_register_operand" "")
3933 (if_then_else:DF (match_operand 1 "comparison_operator" "")
3934 (match_operand:DF 2 "s_register_operand" "")
3935 (match_operand:DF 3 "nonmemory_operand" "")))]
3939 enum rtx_code code = GET_CODE (operands[1]);
3940 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3943 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3946 (define_insn "*movsicc_insn"
3947 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
3949 (match_operator 3 "comparison_operator"
3950 [(match_operand 4 "cc_register" "") (const_int 0)])
3951 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
3952 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
3959 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
3960 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
3961 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
3962 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
3963 [(set_attr "length" "4,4,4,4,8,8,8,8")
3964 (set_attr "conds" "use")])
3966 (define_insn "*movsfcc_hard_insn"
3967 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
3969 (match_operator 3 "comparison_operator"
3970 [(match_operand 4 "cc_register" "") (const_int 0)])
3971 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
3972 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
3979 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
3980 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
3981 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
3982 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
3983 [(set_attr "length" "4,4,4,4,8,8,8,8")
3984 (set_attr "type" "ffarith")
3985 (set_attr "conds" "use")])
3987 (define_insn "*movsfcc_soft_insn"
3988 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
3989 (if_then_else:SF (match_operator 3 "comparison_operator"
3990 [(match_operand 4 "cc_register" "") (const_int 0)])
3991 (match_operand:SF 1 "s_register_operand" "0,r")
3992 (match_operand:SF 2 "s_register_operand" "r,0")))]
3997 [(set_attr "conds" "use")])
3999 (define_insn "*movdfcc_insn"
4000 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4002 (match_operator 3 "comparison_operator"
4003 [(match_operand 4 "cc_register" "") (const_int 0)])
4004 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4005 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4012 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
4013 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
4014 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
4015 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
4016 [(set_attr "length" "4,4,4,4,8,8,8,8")
4017 (set_attr "type" "ffarith")
4018 (set_attr "conds" "use")])
4020 ;; Jump and linkage insns
4024 (label_ref (match_operand 0 "" "")))]
4028 extern int arm_ccfsm_state;
4030 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4032 arm_ccfsm_state += 2;
4035 return \"b%?\\t%l0\";
4038 (define_expand "call"
4039 [(parallel [(call (match_operand 0 "memory_operand" "")
4040 (match_operand 1 "general_operand" ""))
4041 (clobber (reg:SI 14))])]
4045 (define_insn "*call_reg"
4046 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
4047 (match_operand 1 "" "g"))
4048 (clobber (reg:SI 14))]
4051 return output_call (operands);
4053 ;; length is worst case, normally it is only two
4054 [(set_attr "length" "12")
4055 (set_attr "type" "call")])
4057 (define_insn "*call_mem"
4058 [(call (mem:SI (match_operand 0 "memory_operand" "m"))
4059 (match_operand 1 "general_operand" "g"))
4060 (clobber (reg:SI 14))]
4063 return output_call_mem (operands);
4065 [(set_attr "length" "12")
4066 (set_attr "type" "call")])
4068 (define_expand "call_value"
4069 [(parallel [(set (match_operand 0 "" "=rf")
4070 (call (match_operand 1 "memory_operand" "m")
4071 (match_operand 2 "general_operand" "g")))
4072 (clobber (reg:SI 14))])]
4076 (define_insn "*call_value_reg"
4077 [(set (match_operand 0 "" "=rf")
4078 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4079 (match_operand 2 "general_operand" "g")))
4080 (clobber (reg:SI 14))]
4083 return output_call (&operands[1]);
4085 [(set_attr "length" "12")
4086 (set_attr "type" "call")])
4088 (define_insn "*call_value_mem"
4089 [(set (match_operand 0 "" "=rf")
4090 (call (mem:SI (match_operand 1 "memory_operand" "m"))
4091 (match_operand 2 "general_operand" "g")))
4092 (clobber (reg:SI 14))]
4093 "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
4095 return output_call_mem (&operands[1]);
4097 [(set_attr "length" "12")
4098 (set_attr "type" "call")])
4100 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
4101 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
4103 (define_insn "*call_symbol"
4104 [(call (mem:SI (match_operand:SI 0 "" "X"))
4105 (match_operand:SI 1 "general_operand" "g"))
4106 (clobber (reg:SI 14))]
4107 "GET_CODE (operands[0]) == SYMBOL_REF"
4109 [(set_attr "type" "call")])
4111 (define_insn "*call_value_symbol"
4112 [(set (match_operand 0 "s_register_operand" "=rf")
4113 (call (mem:SI (match_operand:SI 1 "" "X"))
4114 (match_operand:SI 2 "general_operand" "g")))
4115 (clobber (reg:SI 14))]
4116 "GET_CODE(operands[1]) == SYMBOL_REF"
4118 [(set_attr "type" "call")])
4120 ;; Often the return insn will be the same as loading from memory, so set attr
4121 (define_insn "return"
4126 extern int arm_ccfsm_state;
4128 if (arm_ccfsm_state == 2)
4130 arm_ccfsm_state += 2;
4133 return output_return_instruction (NULL, TRUE, FALSE);
4135 [(set_attr "type" "load")])
4137 (define_insn "*cond_return"
4139 (if_then_else (match_operator 0 "comparison_operator"
4140 [(match_operand 1 "cc_register" "") (const_int 0)])
4146 extern int arm_ccfsm_state;
4148 if (arm_ccfsm_state == 2)
4150 arm_ccfsm_state += 2;
4153 return output_return_instruction (operands[0], TRUE, FALSE);
4155 [(set_attr "conds" "use")
4156 (set_attr "type" "load")])
4158 (define_insn "*cond_return_inverted"
4160 (if_then_else (match_operator 0 "comparison_operator"
4161 [(match_operand 1 "cc_register" "") (const_int 0)])
4167 extern int arm_ccfsm_state;
4169 if (arm_ccfsm_state == 2)
4171 arm_ccfsm_state += 2;
4174 return output_return_instruction (operands[0], TRUE, TRUE);
4176 [(set_attr "conds" "use")
4177 (set_attr "type" "load")])
4179 ;; Call subroutine returning any type.
4181 (define_expand "untyped_call"
4182 [(parallel [(call (match_operand 0 "" "")
4184 (match_operand 1 "" "")
4185 (match_operand 2 "" "")])]
4191 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
4193 for (i = 0; i < XVECLEN (operands[2], 0); i++)
4195 rtx set = XVECEXP (operands[2], 0, i);
4196 emit_move_insn (SET_DEST (set), SET_SRC (set));
4199 /* The optimizer does not know that the call sets the function value
4200 registers we stored in the result block. We avoid problems by
4201 claiming that all hard registers are used and clobbered at this
4203 emit_insn (gen_blockage ());
4208 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
4209 ;; all of memory. This blocks insns from being moved across this point.
4211 (define_insn "blockage"
4212 [(unspec_volatile [(const_int 0)] 0)]
4215 [(set_attr "length" "0")
4216 (set_attr "type" "block")])
4218 (define_expand "casesi"
4219 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
4220 (match_operand:SI 1 "const_int_operand" "") ; lower bound
4221 (match_operand:SI 2 "const_int_operand" "") ; total range
4222 (match_operand:SI 3 "" "") ; table label
4223 (match_operand:SI 4 "" "")] ; Out of range label
4228 if (operands[1] != const0_rtx)
4230 reg = gen_reg_rtx (SImode);
4231 emit_insn (gen_addsi3 (reg, operands[0],
4232 GEN_INT (-INTVAL (operands[1]))));
4236 if (! const_ok_for_arm (INTVAL (operands[2])))
4237 operands[2] = force_reg (SImode, operands[2]);
4239 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
4244 ;; The USE in this pattern is needed to tell flow analysis that this is
4245 ;; a CASESI insn. It has no other purpose.
4246 (define_insn "casesi_internal"
4247 [(parallel [(set (pc)
4249 (leu (match_operand:SI 0 "s_register_operand" "r")
4250 (match_operand:SI 1 "arm_rhs_operand" "rI"))
4251 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
4252 (label_ref (match_operand 2 "" ""))))
4253 (label_ref (match_operand 3 "" ""))))
4254 (use (label_ref (match_dup 2)))])]
4258 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
4259 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
4261 [(set_attr "conds" "clob")
4262 (set_attr "length" "12")])
4264 (define_insn "indirect_jump"
4266 (match_operand:SI 0 "s_register_operand" "r"))]
4268 "mov%?\\t%|pc, %0\\t%@ indirect jump")
4270 (define_insn "*load_indirect_jump"
4272 (match_operand:SI 0 "memory_operand" "m"))]
4274 "ldr%?\\t%|pc, %0\\t%@ indirect jump"
4275 [(set_attr "type" "load")])
4282 "mov%?\\tr0, r0\\t%@ nop")
4284 ;; Patterns to allow combination of arithmetic, cond code and shifts
4286 (define_insn "*arith_shiftsi"
4287 [(set (match_operand:SI 0 "s_register_operand" "=r")
4288 (match_operator:SI 1 "shiftable_operator"
4289 [(match_operator:SI 3 "shift_operator"
4290 [(match_operand:SI 4 "s_register_operand" "r")
4291 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4292 (match_operand:SI 2 "s_register_operand" "r")]))]
4294 "%i1%?\\t%0, %2, %4%S3")
4296 (define_insn "*arith_shiftsi_compare0"
4297 [(set (reg:CC_NOOV 24)
4298 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4299 [(match_operator:SI 3 "shift_operator"
4300 [(match_operand:SI 4 "s_register_operand" "r")
4301 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4302 (match_operand:SI 2 "s_register_operand" "r")])
4304 (set (match_operand:SI 0 "s_register_operand" "=r")
4305 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4308 "%i1%?s\\t%0, %2, %4%S3"
4309 [(set_attr "conds" "set")])
4311 (define_insn "*arith_shiftsi_compare0_scratch"
4312 [(set (reg:CC_NOOV 24)
4313 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4314 [(match_operator:SI 3 "shift_operator"
4315 [(match_operand:SI 4 "s_register_operand" "r")
4316 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4317 (match_operand:SI 2 "s_register_operand" "r")])
4319 (clobber (match_scratch:SI 0 "=r"))]
4321 "%i1%?s\\t%0, %2, %4%S3"
4322 [(set_attr "conds" "set")])
4324 (define_insn "*sub_shiftsi"
4325 [(set (match_operand:SI 0 "s_register_operand" "=r")
4326 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4327 (match_operator:SI 2 "shift_operator"
4328 [(match_operand:SI 3 "s_register_operand" "r")
4329 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4331 "sub%?\\t%0, %1, %3%S2")
4333 (define_insn "*sub_shiftsi_compare0"
4334 [(set (reg:CC_NOOV 24)
4336 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4337 (match_operator:SI 2 "shift_operator"
4338 [(match_operand:SI 3 "s_register_operand" "r")
4339 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4341 (set (match_operand:SI 0 "s_register_operand" "=r")
4342 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4345 "sub%?s\\t%0, %1, %3%S2"
4346 [(set_attr "conds" "set")])
4348 (define_insn "*sub_shiftsi_compare0_scratch"
4349 [(set (reg:CC_NOOV 24)
4351 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4352 (match_operator:SI 2 "shift_operator"
4353 [(match_operand:SI 3 "s_register_operand" "r")
4354 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4356 (clobber (match_scratch:SI 0 "=r"))]
4358 "sub%?s\\t%0, %1, %3%S2"
4359 [(set_attr "conds" "set")])
4361 ;; These variants of the above insns can occur if the first operand is the
4362 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
4363 ;; seem to be a way around it. Most of the predicates have to be null
4364 ;; because the format can be generated part way through reload, so
4365 ;; if we don't match it as soon as it becomes available, reload doesn't know
4366 ;; how to reload pseudos that haven't got hard registers; the constraints will
4367 ;; sort everything out.
4369 (define_insn "*reload_mulsi3"
4370 [(set (match_operand:SI 0 "" "=&r")
4371 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4372 [(match_operand:SI 3 "" "r")
4373 (match_operand:SI 4 "" "rM")])
4374 (match_operand:SI 2 "" "r"))
4375 (match_operand:SI 1 "const_int_operand" "n")))]
4376 "reload_in_progress"
4378 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4379 operands[2] = operands[1];
4380 operands[1] = operands[0];
4381 return output_add_immediate (operands);
4383 ; we have no idea how long the add_immediate is, it could be up to 4.
4384 [(set_attr "length" "20")])
4386 (define_insn "*reload_mulsi_compare0"
4387 [(set (reg:CC_NOOV 24)
4388 (compare:CC_NOOV (plus:SI
4390 (match_operator:SI 5 "shift_operator"
4391 [(match_operand:SI 3 "" "r")
4392 (match_operand:SI 4 "" "rM")])
4393 (match_operand:SI 1 "" "r"))
4394 (match_operand:SI 2 "const_int_operand" "n"))
4396 (set (match_operand:SI 0 "" "=&r")
4397 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4400 "reload_in_progress"
4402 output_add_immediate (operands);
4403 return \"add%?s\\t%0, %0, %3%S5\";
4405 [(set_attr "conds" "set")
4406 (set_attr "length" "20")])
4408 (define_insn "*reload_mulsi_compare0_scratch"
4409 [(set (reg:CC_NOOV 24)
4410 (compare:CC_NOOV (plus:SI
4412 (match_operator:SI 5 "shift_operator"
4413 [(match_operand:SI 3 "" "r")
4414 (match_operand:SI 4 "" "rM")])
4415 (match_operand:SI 1 "" "r"))
4416 (match_operand:SI 2 "const_int_operand" "n"))
4418 (clobber (match_scratch:SI 0 "=&r"))]
4419 "reload_in_progress"
4421 output_add_immediate (operands);
4422 return \"add%?s\\t%0, %0, %3%S5\";
4424 [(set_attr "conds" "set")
4425 (set_attr "length" "20")])
4427 ;; These are similar, but are needed when the mla pattern contains the
4428 ;; eliminated register as operand 3.
4430 (define_insn "*reload_muladdsi"
4431 [(set (match_operand:SI 0 "" "=&r,&r")
4432 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4433 (match_operand:SI 2 "" "r,r"))
4434 (match_operand:SI 3 "" "r,r"))
4435 (match_operand:SI 4 "const_int_operand" "n,n")))]
4436 "reload_in_progress"
4438 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4439 operands[2] = operands[4];
4440 operands[1] = operands[0];
4441 return output_add_immediate (operands);
4443 [(set_attr "length" "20")
4444 (set_attr "type" "mult")])
4446 (define_insn "*reload_muladdsi_compare0"
4447 [(set (reg:CC_NOOV 24)
4448 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4449 (match_operand:SI 3 "" "r")
4450 (match_operand:SI 4 "" "r"))
4451 (match_operand:SI 1 "" "r"))
4452 (match_operand:SI 2 "const_int_operand" "n"))
4454 (set (match_operand:SI 0 "" "=&r")
4455 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4457 "reload_in_progress"
4459 output_add_immediate (operands);
4460 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4463 [(set_attr "length" "20")
4464 (set_attr "conds" "set")
4465 (set_attr "type" "mult")])
4467 (define_insn "*reload_muladdsi_compare0_scratch"
4468 [(set (reg:CC_NOOV 24)
4469 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4470 (match_operand:SI 3 "" "r")
4471 (match_operand:SI 4 "" "r"))
4472 (match_operand:SI 1 "" "r"))
4473 (match_operand:SI 2 "const_int_operand" "n"))
4475 (clobber (match_scratch:SI 0 "=&r"))]
4476 "reload_in_progress"
4478 output_add_immediate (operands);
4479 return \"mla%?s\\t%0, %3, %4, %0\";
4481 [(set_attr "length" "20")
4482 (set_attr "conds" "set")
4483 (set_attr "type" "mult")])
4487 (define_insn "*and_scc"
4488 [(set (match_operand:SI 0 "s_register_operand" "=r")
4489 (and:SI (match_operator 1 "comparison_operator"
4490 [(match_operand 3 "cc_register" "") (const_int 0)])
4491 (match_operand:SI 2 "s_register_operand" "r")))]
4493 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
4494 [(set_attr "conds" "use")
4495 (set_attr "length" "8")])
4497 (define_insn "*ior_scc"
4498 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4499 (ior:SI (match_operator 2 "comparison_operator"
4500 [(match_operand 3 "cc_register" "") (const_int 0)])
4501 (match_operand:SI 1 "s_register_operand" "0,?r")))]
4505 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
4506 [(set_attr "conds" "use")
4507 (set_attr "length" "4,8")])
4509 (define_insn "*compare_scc"
4510 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4511 (match_operator 1 "comparison_operator"
4512 [(match_operand:SI 2 "s_register_operand" "r,r")
4513 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
4517 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4518 return \"mov\\t%0, %2, lsr #31\";
4520 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4521 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4523 if (GET_CODE (operands[1]) == NE)
4525 if (which_alternative == 1)
4526 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4527 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4529 if (which_alternative == 1)
4530 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4532 output_asm_insn (\"cmp\\t%2, %3\", operands);
4533 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4535 [(set_attr "conds" "clob")
4536 (set_attr "length" "12")])
4538 (define_insn "*cond_move"
4539 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4540 (if_then_else:SI (match_operator 3 "equality_operator"
4541 [(match_operator 4 "comparison_operator"
4542 [(match_operand 5 "cc_register" "") (const_int 0)])
4544 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4545 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4548 if (GET_CODE (operands[3]) == NE)
4550 if (which_alternative != 1)
4551 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4552 if (which_alternative != 0)
4553 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4556 if (which_alternative != 0)
4557 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4558 if (which_alternative != 1)
4559 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4562 [(set_attr "conds" "use")
4563 (set_attr "length" "4,4,8")])
4565 (define_insn "*cond_arith"
4566 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4567 (match_operator:SI 5 "shiftable_operator"
4568 [(match_operator:SI 4 "comparison_operator"
4569 [(match_operand:SI 2 "s_register_operand" "r,r")
4570 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4571 (match_operand:SI 1 "s_register_operand" "0,?r")]))
4575 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4576 return \"%i5\\t%0, %1, %2, lsr #31\";
4578 output_asm_insn (\"cmp\\t%2, %3\", operands);
4579 if (GET_CODE (operands[5]) == AND)
4580 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4581 else if (GET_CODE (operands[5]) == MINUS)
4582 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4583 else if (which_alternative != 0)
4584 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4585 return \"%i5%d4\\t%0, %1, #1\";
4587 [(set_attr "conds" "clob")
4588 (set_attr "length" "12")])
4590 (define_insn "*cond_sub"
4591 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4592 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4593 (match_operator:SI 4 "comparison_operator"
4594 [(match_operand:SI 2 "s_register_operand" "r,r")
4595 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4599 output_asm_insn (\"cmp\\t%2, %3\", operands);
4600 if (which_alternative != 0)
4601 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4602 return \"sub%d4\\t%0, %1, #1\";
4604 [(set_attr "conds" "clob")
4605 (set_attr "length" "8,12")])
4607 (define_insn "*cmp_ite0"
4608 [(set (match_operand 6 "dominant_cc_register" "")
4611 (match_operator 4 "comparison_operator"
4612 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4613 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4614 (match_operator:SI 5 "comparison_operator"
4615 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4616 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4622 char* opcodes[4][2] =
4624 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
4625 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
4626 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
4627 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
4628 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
4631 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
4633 return opcodes[which_alternative][swap];
4636 [(set_attr "conds" "set")
4637 (set_attr "length" "8")])
4639 (define_insn "*cmp_ite1"
4640 [(set (match_operand 6 "dominant_cc_register" "")
4643 (match_operator 4 "comparison_operator"
4644 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4645 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4646 (match_operator:SI 5 "comparison_operator"
4647 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4648 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4654 char* opcodes[4][2] =
4656 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
4657 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
4658 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
4659 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
4660 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
4663 comparison_dominates_p (GET_CODE (operands[5]),
4664 reverse_condition (GET_CODE (operands[4])));
4666 return opcodes[which_alternative][swap];
4669 [(set_attr "conds" "set")
4670 (set_attr "length" "8")])
4672 (define_insn "*negscc"
4673 [(set (match_operand:SI 0 "s_register_operand" "=r")
4674 (neg:SI (match_operator 3 "comparison_operator"
4675 [(match_operand:SI 1 "s_register_operand" "r")
4676 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4680 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4681 return \"mov\\t%0, %1, asr #31\";
4683 if (GET_CODE (operands[3]) == NE)
4684 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4686 if (GET_CODE (operands[3]) == GT)
4687 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4689 output_asm_insn (\"cmp\\t%1, %2\", operands);
4690 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4691 return \"mvn%d3\\t%0, #0\";
4693 [(set_attr "conds" "clob")
4694 (set_attr "length" "12")])
4696 (define_insn "movcond"
4697 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4699 (match_operator 5 "comparison_operator"
4700 [(match_operand:SI 3 "s_register_operand" "r,r,r")
4701 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4702 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4703 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4707 if (GET_CODE (operands[5]) == LT
4708 && (operands[4] == const0_rtx))
4710 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4712 if (operands[2] == const0_rtx)
4713 return \"and\\t%0, %1, %3, asr #31\";
4714 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4716 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4718 if (operands[1] == const0_rtx)
4719 return \"bic\\t%0, %2, %3, asr #31\";
4720 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4722 /* The only case that falls through to here is when both ops 1 & 2
4726 if (GET_CODE (operands[5]) == GE
4727 && (operands[4] == const0_rtx))
4729 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4731 if (operands[2] == const0_rtx)
4732 return \"bic\\t%0, %1, %3, asr #31\";
4733 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4735 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4737 if (operands[1] == const0_rtx)
4738 return \"and\\t%0, %2, %3, asr #31\";
4739 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4741 /* The only case that falls through to here is when both ops 1 & 2
4744 if (GET_CODE (operands[4]) == CONST_INT
4745 && !const_ok_for_arm (INTVAL (operands[4])))
4746 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4748 output_asm_insn (\"cmp\\t%3, %4\", operands);
4749 if (which_alternative != 0)
4750 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4751 if (which_alternative != 1)
4752 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4755 [(set_attr "conds" "clob")
4756 (set_attr "length" "8,8,12")])
4758 (define_insn "*ifcompare_plus_move"
4759 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4760 (if_then_else:SI (match_operator 6 "comparison_operator"
4761 [(match_operand:SI 4 "s_register_operand" "r,r")
4762 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4764 (match_operand:SI 2 "s_register_operand" "r,r")
4765 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
4766 (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4770 [(set_attr "conds" "clob")
4771 (set_attr "length" "8,12")])
4773 (define_insn "*if_plus_move"
4774 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r")
4776 (match_operator 4 "comparison_operator"
4777 [(match_operand 5 "cc_register" "") (const_int 0)])
4779 (match_operand:SI 2 "s_register_operand" "r,r,r,r,r,r")
4780 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L,rI,L"))
4781 (match_operand:SI 1 "arm_rhsm_operand" "0,0,?rI,?rI,m,m")))]
4785 sub%d4\\t%0, %2, #%n3
4786 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4787 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1
4788 add%d4\\t%0, %2, %3\;ldr%D4\\t%0, %1
4789 sub%d4\\t%0, %2, #%n3\;ldr%D4\\t%0, %1"
4790 [(set_attr "conds" "use")
4791 (set_attr "length" "4,4,8,8,8,8")
4792 (set_attr "type" "*,*,*,*,load,load")])
4794 (define_insn "*ifcompare_move_plus"
4795 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4796 (if_then_else:SI (match_operator 6 "comparison_operator"
4797 [(match_operand:SI 4 "s_register_operand" "r,r")
4798 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4799 (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4801 (match_operand:SI 2 "s_register_operand" "r,r")
4802 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4806 [(set_attr "conds" "clob")
4807 (set_attr "length" "8,12")])
4809 (define_insn "*if_move_plus"
4810 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r")
4812 (match_operator 4 "comparison_operator"
4813 [(match_operand 5 "cc_register" "") (const_int 0)])
4814 (match_operand:SI 1 "arm_rhsm_operand" "0,0,?rI,?rI,m,m")
4816 (match_operand:SI 2 "s_register_operand" "r,r,r,r,r,r")
4817 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L,rI,L"))))]
4821 sub%D4\\t%0, %2, #%n3
4822 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4823 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1
4824 add%D4\\t%0, %2, %3\;ldr%d4\\t%0, %1
4825 sub%D4\\t%0, %2, #%n3\;ldr%d4\\t%0, %1"
4826 [(set_attr "conds" "use")
4827 (set_attr "length" "4,4,8,8,8,8")
4828 (set_attr "type" "*,*,*,*,load,load")])
4830 (define_insn "*ifcompare_arith_arith"
4831 [(set (match_operand:SI 0 "s_register_operand" "=r")
4832 (if_then_else:SI (match_operator 9 "comparison_operator"
4833 [(match_operand:SI 5 "s_register_operand" "r")
4834 (match_operand:SI 6 "arm_add_operand" "rIL")])
4835 (match_operator:SI 8 "shiftable_operator"
4836 [(match_operand:SI 1 "s_register_operand" "r")
4837 (match_operand:SI 2 "arm_rhs_operand" "rI")])
4838 (match_operator:SI 7 "shiftable_operator"
4839 [(match_operand:SI 3 "s_register_operand" "r")
4840 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
4844 [(set_attr "conds" "clob")
4845 (set_attr "length" "12")])
4847 (define_insn "*if_arith_arith"
4848 [(set (match_operand:SI 0 "s_register_operand" "=r")
4849 (if_then_else:SI (match_operator 5 "comparison_operator"
4850 [(match_operand 8 "cc_register" "") (const_int 0)])
4851 (match_operator:SI 6 "shiftable_operator"
4852 [(match_operand:SI 1 "s_register_operand" "r")
4853 (match_operand:SI 2 "arm_rhs_operand" "rI")])
4854 (match_operator:SI 7 "shiftable_operator"
4855 [(match_operand:SI 3 "s_register_operand" "r")
4856 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
4858 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
4859 [(set_attr "conds" "use")
4860 (set_attr "length" "8")])
4862 (define_insn "*ifcompare_arith_move"
4863 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4864 (if_then_else:SI (match_operator 6 "comparison_operator"
4865 [(match_operand:SI 2 "s_register_operand" "r,r")
4866 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
4867 (match_operator:SI 7 "shiftable_operator"
4868 [(match_operand:SI 4 "s_register_operand" "r,r")
4869 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
4870 (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4874 /* If we have an operation where (op x 0) is the identity operation and
4875 the conditional operator is LT or GE and we are comparing against zero and
4876 everything is in registers then we can do this in two instructions */
4877 if (operands[3] == const0_rtx
4878 && GET_CODE (operands[7]) != AND
4879 && GET_CODE (operands[5]) == REG
4880 && GET_CODE (operands[1]) == REG
4881 && REGNO (operands[1]) == REGNO (operands[4])
4882 && REGNO (operands[4]) != REGNO (operands[0]))
4884 if (GET_CODE (operands[6]) == LT)
4885 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4886 else if (GET_CODE (operands[6]) == GE)
4887 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4889 if (GET_CODE (operands[3]) == CONST_INT
4890 && !const_ok_for_arm (INTVAL (operands[3])))
4891 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4893 output_asm_insn (\"cmp\\t%2, %3\", operands);
4894 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
4895 if (which_alternative != 0)
4897 if (GET_CODE (operands[1]) == MEM)
4898 return \"ldr%D6\\t%0, %1\";
4900 return \"mov%D6\\t%0, %1\";
4904 [(set_attr "conds" "clob")
4905 (set_attr "length" "8,12")])
4907 (define_insn "*if_arith_move"
4908 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4909 (if_then_else:SI (match_operator 4 "comparison_operator"
4910 [(match_operand 6 "cc_register" "") (const_int 0)])
4911 (match_operator:SI 5 "shiftable_operator"
4912 [(match_operand:SI 2 "s_register_operand" "r,r,r")
4913 (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI")])
4914 (match_operand:SI 1 "arm_rhsm_operand" "0,?rI,m")))]
4918 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4919 %I5%d4\\t%0, %2, %3\;ldr%D4\\t%0, %1"
4920 [(set_attr "conds" "use")
4921 (set_attr "length" "4,8,8")
4922 (set_attr "type" "*,*,load")])
4924 (define_insn "*ifcompare_move_arith"
4925 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4926 (if_then_else:SI (match_operator 6 "comparison_operator"
4927 [(match_operand:SI 4 "s_register_operand" "r,r")
4928 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4929 (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4930 (match_operator:SI 7 "shiftable_operator"
4931 [(match_operand:SI 2 "s_register_operand" "r,r")
4932 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4936 /* If we have an operation where (op x 0) is the identity operation and
4937 the conditional operator is LT or GE and we are comparing against zero and
4938 everything is in registers then we can do this in two instructions */
4939 if (operands[5] == const0_rtx
4940 && GET_CODE (operands[7]) != AND
4941 && GET_CODE (operands[3]) == REG
4942 && GET_CODE (operands[1]) == REG
4943 && REGNO (operands[1]) == REGNO (operands[2])
4944 && REGNO (operands[2]) != REGNO (operands[0]))
4946 if (GET_CODE (operands[6]) == GE)
4947 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4948 else if (GET_CODE (operands[6]) == LT)
4949 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4952 if (GET_CODE (operands[5]) == CONST_INT
4953 && !const_ok_for_arm (INTVAL (operands[5])))
4954 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4956 output_asm_insn (\"cmp\\t%4, %5\", operands);
4958 if (which_alternative != 0)
4960 if (GET_CODE (operands[1]) == MEM)
4961 output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4963 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4965 return \"%I7%D6\\t%0, %2, %3\";
4967 [(set_attr "conds" "clob")
4968 (set_attr "length" "8,12")])
4970 (define_insn "*if_move_arith"
4971 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4973 (match_operator 4 "comparison_operator"
4974 [(match_operand 6 "cc_register" "") (const_int 0)])
4975 (match_operand:SI 1 "arm_rhsm_operand" "0,?rI,m")
4976 (match_operator:SI 5 "shiftable_operator"
4977 [(match_operand:SI 2 "s_register_operand" "r,r,r")
4978 (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI")])))]
4982 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4983 %I5%D4\\t%0, %2, %3\;ldr%d4\\t%0, %1"
4984 [(set_attr "conds" "use")
4985 (set_attr "length" "4,8,8")
4986 (set_attr "type" "*,*,load")])
4988 (define_insn "*ifcompare_move_not"
4989 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4991 (match_operator 5 "comparison_operator"
4992 [(match_operand:SI 3 "s_register_operand" "r,r")
4993 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
4994 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
4996 (match_operand:SI 2 "s_register_operand" "r,r"))))
5000 [(set_attr "conds" "clob")
5001 (set_attr "length" "8,12")])
5003 (define_insn "*if_move_not"
5004 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5006 (match_operator 4 "comparison_operator"
5007 [(match_operand 3 "cc_register" "") (const_int 0)])
5008 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5009 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5013 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
5014 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
5015 [(set_attr "conds" "use")
5016 (set_attr "length" "4,8,8")])
5018 (define_insn "*ifcompare_not_move"
5019 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5021 (match_operator 5 "comparison_operator"
5022 [(match_operand:SI 3 "s_register_operand" "r,r")
5023 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5025 (match_operand:SI 2 "s_register_operand" "r,r"))
5026 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5030 [(set_attr "conds" "clob")
5031 (set_attr "length" "8,12")])
5033 (define_insn "*if_not_move"
5034 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5036 (match_operator 4 "comparison_operator"
5037 [(match_operand 3 "cc_register" "") (const_int 0)])
5038 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5039 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5043 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
5044 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
5045 [(set_attr "conds" "use")
5046 (set_attr "length" "4,8,8")])
5048 (define_insn "*ifcompare_shift_move"
5049 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5051 (match_operator 6 "comparison_operator"
5052 [(match_operand:SI 4 "s_register_operand" "r,r")
5053 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5054 (match_operator:SI 7 "shift_operator"
5055 [(match_operand:SI 2 "s_register_operand" "r,r")
5056 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
5057 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5061 [(set_attr "conds" "clob")
5062 (set_attr "length" "8,12")])
5064 (define_insn "*if_shift_move"
5065 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5067 (match_operator 5 "comparison_operator"
5068 [(match_operand 6 "cc_register" "") (const_int 0)])
5069 (match_operator:SI 4 "shift_operator"
5070 [(match_operand:SI 2 "s_register_operand" "r,r,r")
5071 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
5072 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5076 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
5077 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
5078 [(set_attr "conds" "use")
5079 (set_attr "length" "4,8,8")])
5081 (define_insn "*ifcompare_move_shift"
5082 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5084 (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_not_operand" "0,?rIK")
5088 (match_operator:SI 7 "shift_operator"
5089 [(match_operand:SI 2 "s_register_operand" "r,r")
5090 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
5094 [(set_attr "conds" "clob")
5095 (set_attr "length" "8,12")])
5097 (define_insn "*if_move_shift"
5098 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5100 (match_operator 5 "comparison_operator"
5101 [(match_operand 6 "cc_register" "") (const_int 0)])
5102 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5103 (match_operator:SI 4 "shift_operator"
5104 [(match_operand:SI 2 "s_register_operand" "r,r,r")
5105 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
5109 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
5110 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
5111 [(set_attr "conds" "use")
5112 (set_attr "length" "4,8,8")])
5114 (define_insn "*ifcompare_shift_shift"
5115 [(set (match_operand:SI 0 "s_register_operand" "=r")
5117 (match_operator 7 "comparison_operator"
5118 [(match_operand:SI 5 "s_register_operand" "r")
5119 (match_operand:SI 6 "arm_add_operand" "rIL")])
5120 (match_operator:SI 8 "shift_operator"
5121 [(match_operand:SI 1 "s_register_operand" "r")
5122 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5123 (match_operator:SI 9 "shift_operator"
5124 [(match_operand:SI 3 "s_register_operand" "r")
5125 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
5129 [(set_attr "conds" "clob")
5130 (set_attr "length" "12")])
5132 (define_insn "*if_shift_shift"
5133 [(set (match_operand:SI 0 "s_register_operand" "=r")
5135 (match_operator 5 "comparison_operator"
5136 [(match_operand 8 "cc_register" "") (const_int 0)])
5137 (match_operator:SI 6 "shift_operator"
5138 [(match_operand:SI 1 "s_register_operand" "r")
5139 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5140 (match_operator:SI 7 "shift_operator"
5141 [(match_operand:SI 3 "s_register_operand" "r")
5142 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
5144 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
5145 [(set_attr "conds" "use")
5146 (set_attr "length" "8")])
5148 (define_insn "*ifcompare_not_arith"
5149 [(set (match_operand:SI 0 "s_register_operand" "=r")
5151 (match_operator 6 "comparison_operator"
5152 [(match_operand:SI 4 "s_register_operand" "r")
5153 (match_operand:SI 5 "arm_add_operand" "rIL")])
5154 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5155 (match_operator:SI 7 "shiftable_operator"
5156 [(match_operand:SI 2 "s_register_operand" "r")
5157 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5161 [(set_attr "conds" "clob")
5162 (set_attr "length" "12")])
5164 (define_insn "*if_not_arith"
5165 [(set (match_operand:SI 0 "s_register_operand" "=r")
5167 (match_operator 5 "comparison_operator"
5168 [(match_operand 4 "cc_register" "") (const_int 0)])
5169 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5170 (match_operator:SI 6 "shiftable_operator"
5171 [(match_operand:SI 2 "s_register_operand" "r")
5172 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
5174 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
5175 [(set_attr "conds" "use")
5176 (set_attr "length" "8")])
5178 (define_insn "*ifcompare_arith_not"
5179 [(set (match_operand:SI 0 "s_register_operand" "=r")
5181 (match_operator 6 "comparison_operator"
5182 [(match_operand:SI 4 "s_register_operand" "r")
5183 (match_operand:SI 5 "arm_add_operand" "rIL")])
5184 (match_operator:SI 7 "shiftable_operator"
5185 [(match_operand:SI 2 "s_register_operand" "r")
5186 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5187 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5191 [(set_attr "conds" "clob")
5192 (set_attr "length" "12")])
5194 (define_insn "*if_arith_not"
5195 [(set (match_operand:SI 0 "s_register_operand" "=r")
5197 (match_operator 5 "comparison_operator"
5198 [(match_operand 4 "cc_register" "") (const_int 0)])
5199 (match_operator:SI 6 "shiftable_operator"
5200 [(match_operand:SI 2 "s_register_operand" "r")
5201 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5202 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
5204 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
5205 [(set_attr "conds" "use")
5206 (set_attr "length" "8")])
5208 (define_insn "*ifcompare_neg_move"
5209 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5211 (match_operator 5 "comparison_operator"
5212 [(match_operand:SI 3 "s_register_operand" "r,r")
5213 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5214 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
5215 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5216 (clobber (reg:CC 24))]
5219 [(set_attr "conds" "clob")
5220 (set_attr "length" "8,12")])
5222 (define_insn "*if_neg_move"
5223 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5225 (match_operator 4 "comparison_operator"
5226 [(match_operand 3 "cc_register" "") (const_int 0)])
5227 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5228 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5232 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
5233 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
5234 [(set_attr "conds" "use")
5235 (set_attr "length" "4,8,8")])
5237 (define_insn "*ifcompare_move_neg"
5238 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5240 (match_operator 5 "comparison_operator"
5241 [(match_operand:SI 3 "s_register_operand" "r,r")
5242 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5243 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5244 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
5245 (clobber (reg:CC 24))]
5248 [(set_attr "conds" "clob")
5249 (set_attr "length" "8,12")])
5251 (define_insn "*if_move_neg"
5252 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5254 (match_operator 4 "comparison_operator"
5255 [(match_operand 3 "cc_register" "") (const_int 0)])
5256 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5257 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5261 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
5262 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
5263 [(set_attr "conds" "use")
5264 (set_attr "length" "4,8,8")])
5266 (define_insn "*arith_adjacentmem"
5267 [(set (match_operand:SI 0 "s_register_operand" "=r")
5268 (match_operator:SI 1 "shiftable_operator"
5269 [(match_operand:SI 2 "memory_operand" "m")
5270 (match_operand:SI 3 "memory_operand" "m")]))
5271 (clobber (match_scratch:SI 4 "=r"))]
5272 "adjacent_mem_locations (operands[2], operands[3])"
5277 int val1 = 0, val2 = 0;
5279 if (REGNO (operands[0]) > REGNO (operands[4]))
5281 ldm[1] = operands[4];
5282 ldm[2] = operands[0];
5286 ldm[1] = operands[0];
5287 ldm[2] = operands[4];
5289 if (GET_CODE (XEXP (operands[2], 0)) != REG)
5290 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5291 if (GET_CODE (XEXP (operands[3], 0)) != REG)
5292 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5293 arith[0] = operands[0];
5294 arith[3] = operands[1];
5308 ldm[0] = ops[0] = operands[4];
5309 ops[1] = XEXP (XEXP (operands[2], 0), 0);
5310 ops[2] = XEXP (XEXP (operands[2], 0), 1);
5311 output_add_immediate (ops);
5313 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5315 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5319 ldm[0] = XEXP (operands[3], 0);
5321 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5323 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5327 ldm[0] = XEXP (operands[2], 0);
5329 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5331 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5333 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
5337 [(set_attr "length" "12")
5338 (set_attr "type" "load")])
5340 ;; the arm can support extended pre-inc instructions
5342 ;; In all these cases, we use operands 0 and 1 for the register being
5343 ;; incremented because those are the operands that local-alloc will
5344 ;; tie and these are the pair most likely to be tieable (and the ones
5345 ;; that will benefit the most).
5347 ;; We reject the frame pointer if it occurs anywhere in these patterns since
5348 ;; elimination will cause too many headaches.
5350 (define_insn "*strqi_preinc"
5351 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5352 (match_operand:SI 2 "index_operand" "rJ")))
5353 (match_operand:QI 3 "s_register_operand" "r"))
5354 (set (match_operand:SI 0 "s_register_operand" "=r")
5355 (plus:SI (match_dup 1) (match_dup 2)))]
5356 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5357 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5358 && (GET_CODE (operands[2]) != REG
5359 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5360 "str%?b\\t%3, [%0, %2]!"
5361 [(set_attr "type" "store1")])
5363 (define_insn "*strqi_predec"
5364 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5365 (match_operand:SI 2 "s_register_operand" "r")))
5366 (match_operand:QI 3 "s_register_operand" "r"))
5367 (set (match_operand:SI 0 "s_register_operand" "=r")
5368 (minus:SI (match_dup 1) (match_dup 2)))]
5369 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5370 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5371 && (GET_CODE (operands[2]) != REG
5372 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5373 "str%?b\\t%3, [%0, -%2]!"
5374 [(set_attr "type" "store1")])
5376 (define_insn "*loadqi_preinc"
5377 [(set (match_operand:QI 3 "s_register_operand" "=r")
5378 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5379 (match_operand:SI 2 "index_operand" "rJ"))))
5380 (set (match_operand:SI 0 "s_register_operand" "=r")
5381 (plus:SI (match_dup 1) (match_dup 2)))]
5382 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5383 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5384 && (GET_CODE (operands[2]) != REG
5385 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5386 "ldr%?b\\t%3, [%0, %2]!"
5387 [(set_attr "type" "load")])
5389 (define_insn "*loadqi_predec"
5390 [(set (match_operand:QI 3 "s_register_operand" "=r")
5391 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5392 (match_operand:SI 2 "s_register_operand" "r"))))
5393 (set (match_operand:SI 0 "s_register_operand" "=r")
5394 (minus:SI (match_dup 1) (match_dup 2)))]
5395 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5396 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5397 && (GET_CODE (operands[2]) != REG
5398 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5399 "ldr%?b\\t%3, [%0, -%2]!"
5400 [(set_attr "type" "load")])
5402 (define_insn "*loadqisi_preinc"
5403 [(set (match_operand:SI 3 "s_register_operand" "=r")
5405 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5406 (match_operand:SI 2 "index_operand" "rJ")))))
5407 (set (match_operand:SI 0 "s_register_operand" "=r")
5408 (plus:SI (match_dup 1) (match_dup 2)))]
5409 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5410 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5411 && (GET_CODE (operands[2]) != REG
5412 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5413 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
5414 [(set_attr "type" "load")])
5416 (define_insn "*loadqisi_predec"
5417 [(set (match_operand:SI 3 "s_register_operand" "=r")
5419 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5420 (match_operand:SI 2 "s_register_operand" "r")))))
5421 (set (match_operand:SI 0 "s_register_operand" "=r")
5422 (minus:SI (match_dup 1) (match_dup 2)))]
5423 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5424 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5425 && (GET_CODE (operands[2]) != REG
5426 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5427 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
5428 [(set_attr "type" "load")])
5430 (define_insn "*strsi_preinc"
5431 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5432 (match_operand:SI 2 "index_operand" "rJ")))
5433 (match_operand:SI 3 "s_register_operand" "r"))
5434 (set (match_operand:SI 0 "s_register_operand" "=r")
5435 (plus:SI (match_dup 1) (match_dup 2)))]
5436 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5437 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5438 && (GET_CODE (operands[2]) != REG
5439 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5440 "str%?\\t%3, [%0, %2]!"
5441 [(set_attr "type" "store1")])
5443 (define_insn "*strqi_predec"
5444 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5445 (match_operand:SI 2 "s_register_operand" "r")))
5446 (match_operand:SI 3 "s_register_operand" "r"))
5447 (set (match_operand:SI 0 "s_register_operand" "=r")
5448 (minus:SI (match_dup 1) (match_dup 2)))]
5449 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5450 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5451 && (GET_CODE (operands[2]) != REG
5452 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5453 "str%?\\t%3, [%0, -%2]!"
5454 [(set_attr "type" "store1")])
5456 (define_insn "*loadsi_preinc"
5457 [(set (match_operand:SI 3 "s_register_operand" "=r")
5458 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5459 (match_operand:SI 2 "index_operand" "rJ"))))
5460 (set (match_operand:SI 0 "s_register_operand" "=r")
5461 (plus:SI (match_dup 1) (match_dup 2)))]
5462 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5463 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5464 && (GET_CODE (operands[2]) != REG
5465 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5466 "ldr%?\\t%3, [%0, %2]!"
5467 [(set_attr "type" "load")])
5469 (define_insn "*loadsi_predec"
5470 [(set (match_operand:SI 3 "s_register_operand" "=r")
5471 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5472 (match_operand:SI 2 "s_register_operand" "r"))))
5473 (set (match_operand:SI 0 "s_register_operand" "=r")
5474 (minus:SI (match_dup 1) (match_dup 2)))]
5475 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5476 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5477 && (GET_CODE (operands[2]) != REG
5478 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5479 "ldr%?\\t%3, [%0, -%2]!"
5480 [(set_attr "type" "load")])
5482 (define_insn "*loadhi_preinc"
5483 [(set (match_operand:HI 3 "s_register_operand" "=r")
5484 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5485 (match_operand:SI 2 "index_operand" "rJ"))))
5486 (set (match_operand:SI 0 "s_register_operand" "=r")
5487 (plus:SI (match_dup 1) (match_dup 2)))]
5488 "(! BYTES_BIG_ENDIAN)
5489 && ! TARGET_SHORT_BY_BYTES
5490 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5491 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5492 && (GET_CODE (operands[2]) != REG
5493 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5494 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5495 [(set_attr "type" "load")])
5497 (define_insn "*loadhi_predec"
5498 [(set (match_operand:HI 3 "s_register_operand" "=r")
5499 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5500 (match_operand:SI 2 "s_register_operand" "r"))))
5501 (set (match_operand:SI 0 "s_register_operand" "=r")
5502 (minus:SI (match_dup 1) (match_dup 2)))]
5503 "(!BYTES_BIG_ENDIAN)
5504 && ! TARGET_SHORT_BY_BYTES
5505 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5506 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5507 && (GET_CODE (operands[2]) != REG
5508 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5509 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5510 [(set_attr "type" "load")])
5512 (define_insn "*strqi_shiftpreinc"
5513 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5514 [(match_operand:SI 3 "s_register_operand" "r")
5515 (match_operand:SI 4 "const_shift_operand" "n")])
5516 (match_operand:SI 1 "s_register_operand" "0")))
5517 (match_operand:QI 5 "s_register_operand" "r"))
5518 (set (match_operand:SI 0 "s_register_operand" "=r")
5519 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5521 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5522 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5523 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5524 "str%?b\\t%5, [%0, %3%S2]!"
5525 [(set_attr "type" "store1")])
5527 (define_insn "*strqi_shiftpredec"
5528 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5529 (match_operator:SI 2 "shift_operator"
5530 [(match_operand:SI 3 "s_register_operand" "r")
5531 (match_operand:SI 4 "const_shift_operand" "n")])))
5532 (match_operand:QI 5 "s_register_operand" "r"))
5533 (set (match_operand:SI 0 "s_register_operand" "=r")
5534 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5536 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5537 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5538 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5539 "str%?b\\t%5, [%0, -%3%S2]!"
5540 [(set_attr "type" "store1")])
5542 (define_insn "*loadqi_shiftpreinc"
5543 [(set (match_operand:QI 5 "s_register_operand" "=r")
5544 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5545 [(match_operand:SI 3 "s_register_operand" "r")
5546 (match_operand:SI 4 "const_shift_operand" "n")])
5547 (match_operand:SI 1 "s_register_operand" "0"))))
5548 (set (match_operand:SI 0 "s_register_operand" "=r")
5549 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5551 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5552 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5553 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5554 "ldr%?b\\t%5, [%0, %3%S2]!"
5555 [(set_attr "type" "load")])
5557 (define_insn "*loadqi_shiftpredec"
5558 [(set (match_operand:QI 5 "s_register_operand" "=r")
5559 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5560 (match_operator:SI 2 "shift_operator"
5561 [(match_operand:SI 3 "s_register_operand" "r")
5562 (match_operand:SI 4 "const_shift_operand" "n")]))))
5563 (set (match_operand:SI 0 "s_register_operand" "=r")
5564 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5566 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5567 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5568 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5569 "ldr%?b\\t%5, [%0, -%3%S2]!"
5570 [(set_attr "type" "load")])
5572 (define_insn "*strsi_shiftpreinc"
5573 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5574 [(match_operand:SI 3 "s_register_operand" "r")
5575 (match_operand:SI 4 "const_shift_operand" "n")])
5576 (match_operand:SI 1 "s_register_operand" "0")))
5577 (match_operand:SI 5 "s_register_operand" "r"))
5578 (set (match_operand:SI 0 "s_register_operand" "=r")
5579 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5581 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5582 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5583 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5584 "str%?\\t%5, [%0, %3%S2]!"
5585 [(set_attr "type" "store1")])
5587 (define_insn "*strsi_shiftpredec"
5588 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5589 (match_operator:SI 2 "shift_operator"
5590 [(match_operand:SI 3 "s_register_operand" "r")
5591 (match_operand:SI 4 "const_shift_operand" "n")])))
5592 (match_operand:SI 5 "s_register_operand" "r"))
5593 (set (match_operand:SI 0 "s_register_operand" "=r")
5594 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5596 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5597 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5598 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5599 "str%?\\t%5, [%0, -%3%S2]!"
5600 [(set_attr "type" "store1")])
5602 (define_insn "*loadqi_shiftpreinc"
5603 [(set (match_operand:SI 5 "s_register_operand" "=r")
5604 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5605 [(match_operand:SI 3 "s_register_operand" "r")
5606 (match_operand:SI 4 "const_shift_operand" "n")])
5607 (match_operand:SI 1 "s_register_operand" "0"))))
5608 (set (match_operand:SI 0 "s_register_operand" "=r")
5609 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5611 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5612 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5613 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5614 "ldr%?\\t%5, [%0, %3%S2]!"
5615 [(set_attr "type" "load")])
5617 (define_insn "*loadqi_shiftpredec"
5618 [(set (match_operand:SI 5 "s_register_operand" "=r")
5619 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5620 (match_operator:SI 2 "shift_operator"
5621 [(match_operand:SI 3 "s_register_operand" "r")
5622 (match_operand:SI 4 "const_shift_operand" "n")]))))
5623 (set (match_operand:SI 0 "s_register_operand" "=r")
5624 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5626 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5627 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5628 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5629 "ldr%?\\t%5, [%0, -%3%S2]!"
5630 [(set_attr "type" "load")])
5632 (define_insn "*loadhi_shiftpreinc"
5633 [(set (match_operand:HI 5 "s_register_operand" "=r")
5634 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5635 [(match_operand:SI 3 "s_register_operand" "r")
5636 (match_operand:SI 4 "const_shift_operand" "n")])
5637 (match_operand:SI 1 "s_register_operand" "0"))))
5638 (set (match_operand:SI 0 "s_register_operand" "=r")
5639 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5641 "(! BYTES_BIG_ENDIAN)
5642 && ! TARGET_SHORT_BY_BYTES
5643 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5644 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5645 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5646 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5647 [(set_attr "type" "load")])
5649 (define_insn "*loadhi_shiftpredec"
5650 [(set (match_operand:HI 5 "s_register_operand" "=r")
5651 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5652 (match_operator:SI 2 "shift_operator"
5653 [(match_operand:SI 3 "s_register_operand" "r")
5654 (match_operand:SI 4 "const_shift_operand" "n")]))))
5655 (set (match_operand:SI 0 "s_register_operand" "=r")
5656 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5658 "(! BYTES_BIG_ENDIAN)
5659 && ! TARGET_SHORT_BY_BYTES
5660 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5661 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5662 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5663 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5664 [(set_attr "type" "load")])
5666 ; It can also support extended post-inc expressions, but combine doesn't
5668 ; It doesn't seem worth adding peepholes for anything but the most common
5669 ; cases since, unlike combine, the increment must immediately follow the load
5670 ; for this pattern to match.
5671 ; When loading we must watch to see that the base register isn't trampled by
5672 ; the load. In such cases this isn't a post-inc expression.
5675 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5676 (match_operand:QI 2 "s_register_operand" "r"))
5678 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5680 "str%?b\\t%2, [%0], %1")
5683 [(set (match_operand:QI 0 "s_register_operand" "=r")
5684 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5686 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5687 "REGNO(operands[0]) != REGNO(operands[1])
5688 && (GET_CODE (operands[2]) != REG
5689 || REGNO(operands[0]) != REGNO (operands[2]))"
5690 "ldr%?b\\t%0, [%1], %2")
5693 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5694 (match_operand:SI 2 "s_register_operand" "r"))
5696 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5698 "str%?\\t%2, [%0], %1")
5701 [(set (match_operand:HI 0 "s_register_operand" "=r")
5702 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5704 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5705 "(! BYTES_BIG_ENDIAN)
5706 && ! TARGET_SHORT_BY_BYTES
5707 && REGNO(operands[0]) != REGNO(operands[1])
5708 && (GET_CODE (operands[2]) != REG
5709 || REGNO(operands[0]) != REGNO (operands[2]))"
5710 "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5713 [(set (match_operand:SI 0 "s_register_operand" "=r")
5714 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5716 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5717 "REGNO(operands[0]) != REGNO(operands[1])
5718 && (GET_CODE (operands[2]) != REG
5719 || REGNO(operands[0]) != REGNO (operands[2]))"
5720 "ldr%?\\t%0, [%1], %2")
5723 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5724 (match_operand:SI 1 "index_operand" "rJ")))
5725 (match_operand:QI 2 "s_register_operand" "r"))
5726 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5728 "str%?b\\t%2, [%0, %1]!")
5731 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5732 [(match_operand:SI 0 "s_register_operand" "r")
5733 (match_operand:SI 1 "const_int_operand" "n")])
5734 (match_operand:SI 2 "s_register_operand" "+r")))
5735 (match_operand:QI 3 "s_register_operand" "r"))
5736 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5739 "str%?b\\t%3, [%2, %0%S4]!")
5741 ; This pattern is never tried by combine, so do it as a peephole
5744 [(set (match_operand:SI 0 "s_register_operand" "=r")
5745 (match_operand:SI 1 "s_register_operand" "r"))
5747 (compare:CC (match_dup 1) (const_int 0)))]
5749 "sub%?s\\t%0, %1, #0"
5750 [(set_attr "conds" "set")])
5752 ; Peepholes to spot possible load- and store-multiples.
5755 [(set (match_operand:SI 0 "s_register_operand" "=r")
5756 (match_operand:SI 4 "memory_operand" "m"))
5757 (set (match_operand:SI 1 "s_register_operand" "=r")
5758 (match_operand:SI 5 "memory_operand" "m"))
5759 (set (match_operand:SI 2 "s_register_operand" "=r")
5760 (match_operand:SI 6 "memory_operand" "m"))
5761 (set (match_operand:SI 3 "s_register_operand" "=r")
5762 (match_operand:SI 7 "memory_operand" "m"))]
5763 "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5765 return emit_ldm_seq (operands, 4);
5769 [(set (match_operand:SI 0 "s_register_operand" "=r")
5770 (match_operand:SI 3 "memory_operand" "m"))
5771 (set (match_operand:SI 1 "s_register_operand" "=r")
5772 (match_operand:SI 4 "memory_operand" "m"))
5773 (set (match_operand:SI 2 "s_register_operand" "=r")
5774 (match_operand:SI 5 "memory_operand" "m"))]
5775 "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5777 return emit_ldm_seq (operands, 3);
5781 [(set (match_operand:SI 0 "s_register_operand" "=r")
5782 (match_operand:SI 2 "memory_operand" "m"))
5783 (set (match_operand:SI 1 "s_register_operand" "=r")
5784 (match_operand:SI 3 "memory_operand" "m"))]
5785 "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5787 return emit_ldm_seq (operands, 2);
5791 [(set (match_operand:SI 4 "memory_operand" "=m")
5792 (match_operand:SI 0 "s_register_operand" "r"))
5793 (set (match_operand:SI 5 "memory_operand" "=m")
5794 (match_operand:SI 1 "s_register_operand" "r"))
5795 (set (match_operand:SI 6 "memory_operand" "=m")
5796 (match_operand:SI 2 "s_register_operand" "r"))
5797 (set (match_operand:SI 7 "memory_operand" "=m")
5798 (match_operand:SI 3 "s_register_operand" "r"))]
5799 "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5801 return emit_stm_seq (operands, 4);
5805 [(set (match_operand:SI 3 "memory_operand" "=m")
5806 (match_operand:SI 0 "s_register_operand" "r"))
5807 (set (match_operand:SI 4 "memory_operand" "=m")
5808 (match_operand:SI 1 "s_register_operand" "r"))
5809 (set (match_operand:SI 5 "memory_operand" "=m")
5810 (match_operand:SI 2 "s_register_operand" "r"))]
5811 "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5813 return emit_stm_seq (operands, 3);
5817 [(set (match_operand:SI 2 "memory_operand" "=m")
5818 (match_operand:SI 0 "s_register_operand" "r"))
5819 (set (match_operand:SI 3 "memory_operand" "=m")
5820 (match_operand:SI 1 "s_register_operand" "r"))]
5821 "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5823 return emit_stm_seq (operands, 2);
5826 ;; A call followed by return can be replaced by restoring the regs and
5827 ;; jumping to the subroutine, provided we aren't passing the address of
5828 ;; any of our local variables. If we call alloca then this is unsafe
5829 ;; since restoring the frame frees the memory, which is not what we want.
5830 ;; Sometimes the return might have been targeted by the final prescan:
5831 ;; if so then emit a proper return insn as well.
5832 ;; Unfortunately, if the frame pointer is required, we don't know if the
5833 ;; current function has any implicit stack pointer adjustments that will
5834 ;; be restored by the return: we can't therefore do a tail call.
5835 ;; Another unfortunate that we can't handle is if current_function_args_size
5836 ;; is non-zero: in this case elimination of the argument pointer assumed
5837 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5841 [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5842 (match_operand:SI 1 "general_operand" "g"))
5843 (clobber (reg:SI 14))])
5845 "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN
5846 && !get_frame_size () && !current_function_calls_alloca
5847 && !frame_pointer_needed && !current_function_args_size)"
5850 extern rtx arm_target_insn;
5851 extern int arm_ccfsm_state;
5853 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5855 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5856 output_return_instruction (NULL, TRUE, FALSE);
5857 arm_ccfsm_state = 0;
5858 arm_target_insn = NULL;
5861 output_return_instruction (NULL, FALSE, FALSE);
5862 return \"b%?\\t%a0\";
5864 [(set_attr "type" "call")
5865 (set_attr "length" "8")])
5868 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5869 (call (mem:SI (match_operand:SI 1 "" "X"))
5870 (match_operand:SI 2 "general_operand" "g")))
5871 (clobber (reg:SI 14))])
5873 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5874 && !get_frame_size () && !current_function_calls_alloca
5875 && !frame_pointer_needed && !current_function_args_size)"
5878 extern rtx arm_target_insn;
5879 extern int arm_ccfsm_state;
5881 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5883 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5884 output_return_instruction (NULL, TRUE, FALSE);
5885 arm_ccfsm_state = 0;
5886 arm_target_insn = NULL;
5889 output_return_instruction (NULL, FALSE, FALSE);
5890 return \"b%?\\t%a1\";
5892 [(set_attr "type" "call")
5893 (set_attr "length" "8")])
5895 ;; As above but when this function is not void, we must be returning the
5896 ;; result of the called subroutine.
5899 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5900 (call (mem:SI (match_operand:SI 1 "" "X"))
5901 (match_operand:SI 2 "general_operand" "g")))
5902 (clobber (reg:SI 14))])
5905 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5906 && !get_frame_size () && !current_function_calls_alloca
5907 && !frame_pointer_needed && !current_function_args_size)"
5910 extern rtx arm_target_insn;
5911 extern int arm_ccfsm_state;
5913 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5915 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5916 output_return_instruction (NULL, TRUE, FALSE);
5917 arm_ccfsm_state = 0;
5918 arm_target_insn = NULL;
5921 output_return_instruction (NULL, FALSE, FALSE);
5922 return \"b%?\\t%a1\";
5924 [(set_attr "type" "call")
5925 (set_attr "length" "8")])
5928 [(set (match_operand:SI 0 "s_register_operand" "")
5929 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
5931 (neg:SI (match_operator:SI 2 "comparison_operator"
5932 [(match_operand:SI 3 "s_register_operand" "")
5933 (match_operand:SI 4 "arm_rhs_operand" "")]))))
5934 (clobber (match_operand:SI 5 "s_register_operand" ""))]
5936 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
5937 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5941 ;; This split can be used because CC_Z mode implies that the following
5942 ;; branch will be an equality, or an unsigned inequality, so the sign
5943 ;; extension is not needed.
5948 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
5950 (match_operand 1 "const_int_operand" "")))
5951 (clobber (match_scratch:SI 2 ""))]
5952 "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
5953 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
5954 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
5955 (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
5957 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
5960 (define_expand "prologue"
5961 [(clobber (const_int 0))]
5964 arm_expand_prologue ();
5968 ;; This split is only used during output to reduce the number of patterns
5969 ;; that need assembler instructions adding to them. We allowed the setting
5970 ;; of the conditions to be implicit during rtl generation so that
5971 ;; the conditional compare patterns would work. However this conflicts to
5972 ;; some extent with the conditional data operations, so we have to split them
5976 [(set (match_operand:SI 0 "s_register_operand" "")
5977 (if_then_else:SI (match_operator 1 "comparison_operator"
5978 [(match_operand 2 "" "") (match_operand 3 "" "")])
5979 (match_operand 4 "" "")
5980 (match_operand 5 "" "")))
5983 [(set (match_dup 6) (match_dup 7))
5985 (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
5990 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
5993 operands[6] = gen_rtx (REG, mode, 24);
5994 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
5999 ;; The next two patterns occur when an AND operation is followed by a
6000 ;; scc insn sequence
6002 (define_insn "*sign_extract_onebit"
6003 [(set (match_operand:SI 0 "s_register_operand" "=r")
6004 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6006 (match_operand:SI 2 "const_int_operand" "n")))]
6009 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6010 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6011 return \"mvnne\\t%0, #0\";
6013 [(set_attr "conds" "clob")
6014 (set_attr "length" "8")])
6016 (define_insn "*not_signextract_onebit"
6017 [(set (match_operand:SI 0 "s_register_operand" "=r")
6019 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6021 (match_operand:SI 2 "const_int_operand" "n"))))]
6024 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6025 output_asm_insn (\"tst\\t%1, %2\", operands);
6026 output_asm_insn (\"mvneq\\t%0, #0\", operands);
6027 return \"movne\\t%0, #0\";
6029 [(set_attr "conds" "clob")
6030 (set_attr "length" "12")])
6032 ;; Push multiple registers to the stack. The first register is in the
6033 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
6035 (define_insn "*push_multi"
6036 [(match_parallel 2 "multi_register_push"
6037 [(set (match_operand:BLK 0 "memory_operand" "=m")
6038 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
6044 extern int lr_save_eliminated;
6046 if (lr_save_eliminated)
6048 if (XVECLEN (operands[2], 0) > 1)
6052 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
6053 for (i = 1; i < XVECLEN (operands[2], 0); i++)
6055 strcat (pattern, \", %|\");
6056 strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
6059 strcat (pattern, \"}\");
6060 output_asm_insn (pattern, operands);
6063 [(set_attr "type" "store4")])
6065 ;; Similarly for the the floating point registers
6066 (define_insn "*push_fp_multi"
6067 [(match_parallel 2 "multi_register_push"
6068 [(set (match_operand:BLK 0 "memory_operand" "=m")
6069 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
6076 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
6077 output_asm_insn (pattern, operands);
6080 [(set_attr "type" "f_store")])
6082 ;; Special patterns for dealing with the constant pool
6084 (define_insn "consttable_4"
6085 [(unspec_volatile [(match_operand 0 "" "")] 2)]
6089 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6093 union real_extract u;
6094 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6095 assemble_real (u.d, GET_MODE (operands[0]));
6099 assemble_integer (operands[0], 4, 1);
6104 [(set_attr "length" "4")])
6106 (define_insn "consttable_8"
6107 [(unspec_volatile [(match_operand 0 "" "")] 3)]
6111 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6115 union real_extract u;
6116 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6117 assemble_real (u.d, GET_MODE (operands[0]));
6121 assemble_integer (operands[0], 8, 1);
6126 [(set_attr "length" "8")])
6128 (define_insn "consttable_end"
6129 [(unspec_volatile [(const_int 0)] 4)]
6132 /* Nothing to do (currently). */
6136 (define_insn "align_4"
6137 [(unspec_volatile [(const_int 0)] 5)]
6140 assemble_align (32);