1 ;;- Machine description for Advanced RISC Machines' ARM for GNU compiler
2 ;; Copyright (C) 1991, 1993, 1994, 1995 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.
42 ; PROG_MODE attribute is used to determine whether condition codes are
43 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
44 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
45 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
47 ; CPU attribute is used to determine whether condition codes are clobbered
48 ; by a call insn: on the arm6 they are if in 32-bit addressing mode; on the
49 ; arm2 and arm3 the condition codes are restored by the return.
51 (define_attr "cpu" "arm2,arm3,arm6,arm7"
52 (const (symbol_ref "arm_cpu_attr")))
54 ; Floating Point Unit. If we only have floating point emulation, then there
55 ; is no point in scheduling the floating point insns. (Well, for best
56 ; performance we should try and group them together).
58 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
60 ; LENGTH of an instruction (in bytes)
61 (define_attr "length" "" (const_int 4))
63 ; An assembler sequence may clobber the condition codes without us knowing
64 (define_asm_attributes
65 [(set_attr "conds" "clob")
66 (set_attr "length" "4")])
68 ; TYPE attribute is used to detect floating point instructions which, if
69 ; running on a co-processor can run in parallel with other, basic instructions
70 ; If write-buffer scheduling is enabled then it can also be used in the
71 ; scheduling of writes.
73 ; Classification of each insn
74 ; normal any data instruction that doesn't hit memory or fp regs
75 ; mult a multiply instruction
76 ; block blockage insn, this blocks all functional units
77 ; float a floating point arithmetic operation (subject to expansion)
78 ; fdivx XFmode floating point division
79 ; fdivd DFmode floating point division
80 ; fdivs SFmode floating point division
81 ; fmul Floating point multiply
82 ; ffmul Fast floating point multiply
83 ; farith Floating point arithmetic (4 cycle)
84 ; ffarith Fast floating point arithmetic (2 cycle)
85 ; float_em a floating point arithmetic operation that is normally emulated
86 ; even on a machine with an fpa.
87 ; f_load a floating point load from memory
88 ; f_store a floating point store to memory
89 ; f_mem_r a transfer of a floating point register to a real reg via mem
90 ; r_mem_f the reverse of f_mem_r
91 ; f_2_r fast transfer float to arm (no memory needed)
92 ; r_2_f fast transfer arm to float
93 ; call a subroutine call
94 ; load any load from memory
95 ; store1 store 1 word to memory from arm registers
96 ; store2 store 2 words
97 ; store3 store 3 words
98 ; store4 store 4 words
101 "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"
102 (const_string "normal"))
104 ; condition codes: this one is used by final_prescan_insn to speed up
105 ; conditionalizing instructions. It saves having to scan the rtl to see if
106 ; it uses or alters the condition codes.
108 ; USE means that the condition codes are used by the insn in the process of
109 ; outputting code, this means (at present) that we can't use the insn in
112 ; SET means that the purpose of the insn is to set the condition codes in a
113 ; well defined manner.
115 ; CLOB means that the condition codes are altered in an undefined manner, if
116 ; they are altered at all
118 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
119 ; but are if the branch wasn't taken; the effect is to limit the branch
120 ; elimination scanning.
122 ; NOCOND means that the condition codes are neither altered nor affect the
123 ; output of this insn
125 (define_attr "conds" "use,set,clob,jump_clob,nocond"
126 (if_then_else (eq_attr "type" "call")
127 (if_then_else (eq_attr "prog_mode" "prog32")
128 (const_string "clob") (const_string "nocond"))
129 (const_string "nocond")))
131 (define_attr "write_conflict" "no,yes"
132 (if_then_else (eq_attr "type"
133 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
135 (const_string "no")))
137 (define_attr "core_cycles" "single,multi"
138 (if_then_else (eq_attr "type"
139 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
140 (const_string "single")
141 (const_string "multi")))
143 ; The write buffer on some of the arm6 processors is hard to model exactly.
144 ; There is room in the buffer for up to two addresses and up to eight words
145 ; of memory, but the two needn't be split evenly. When writing the two
146 ; addresses are fully pipelined. However, a read from memory that is not
147 ; currently in the cache will block until the writes have completed.
148 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
149 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
150 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
151 ; cycle to add as well.
153 ;; (define_function_unit {name} {num-units} {n-users} {test}
154 ;; {ready-delay} {issue-delay} [{conflict-list}])
155 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
156 (eq_attr "type" "fdivx")) 71 69)
158 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
159 (eq_attr "type" "fdivd")) 59 57)
161 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
162 (eq_attr "type" "fdivs")) 31 29)
164 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
165 (eq_attr "type" "fmul")) 9 7)
167 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
168 (eq_attr "type" "ffmul")) 6 4)
170 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
171 (eq_attr "type" "farith")) 4 2)
173 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
174 (eq_attr "type" "ffarith")) 2 2)
176 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
177 (eq_attr "type" "r_2_f")) 5 3)
179 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
180 (eq_attr "type" "f_2_r")) 1 2)
182 ;; The fpa10 doesn't really have a memory read unit, but it can start to
183 ;; speculatively execute the instruction in the pipeline, provided the data
184 ;; is already loaded, so pretend reads have a delay of 2 (and that the
185 ;; pipeline is infinite.
187 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
188 (eq_attr "type" "f_load")) 3 1)
190 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store1") 5 3)
191 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store2") 7 4)
192 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store3") 9 5)
193 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store4") 11 6)
194 (define_function_unit "write_buf" 1 2 (eq_attr "type" "r_mem_f") 5 3)
196 ;; The write_blockage unit models (partially), the fact that writes will stall
197 ;; until the write buffer empties.
199 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store1") 5 5
200 [(eq_attr "write_conflict" "yes")])
201 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store2") 7 7
202 [(eq_attr "write_conflict" "yes")])
203 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store3") 9 9
204 [(eq_attr "write_conflict" "yes")])
205 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "store4") 11 11
206 [(eq_attr "write_conflict" "yes")])
207 (define_function_unit "write_blockage" 1 0 (eq_attr "type" "r_mem_f") 5 5
208 [(eq_attr "write_conflict" "yes")])
209 (define_function_unit "write_blockage" 1 0
210 (eq_attr "write_conflict" "yes") 1 1)
212 (define_function_unit "core" 1 1 (eq_attr "core_cycles" "single") 1 1)
214 (define_function_unit "core" 1 1 (eq_attr "type" "load") 2 2)
216 (define_function_unit "core" 1 1 (eq_attr "type" "mult") 16 16)
218 (define_function_unit "core" 1 1 (eq_attr "type" "store1") 2 2)
220 (define_function_unit "core" 1 1 (eq_attr "type" "store2") 3 3)
222 (define_function_unit "core" 1 1 (eq_attr "type" "store3") 4 4)
224 (define_function_unit "core" 1 1 (eq_attr "type" "store4") 5 5)
226 (define_function_unit "core" 1 1
227 (and (eq_attr "core_cycles" "multi")
228 (eq_attr "type" "!mult,load,store2,store3,store4")) 32 32)
231 ;; Note: For DImode insns, there is normally no reason why operands should
232 ;; not be in the same register, what we don't want is for something being
233 ;; written to partially overlap something that is an input.
237 (define_insn "adddi3"
238 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
239 (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
240 (match_operand:DI 2 "s_register_operand" "r,0")))
241 (clobber (reg:CC 24))]
243 "adds\\t%0, %1, %2\;adc\\t%R0, %R1, %R2"
244 [(set_attr "conds" "clob")
245 (set_attr "length" "8")])
247 (define_insn "*adddi_sesidi_di"
248 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
249 (plus:DI (sign_extend:DI
250 (match_operand:SI 1 "s_register_operand" "r,r"))
251 (match_operand:DI 2 "s_register_operand" "r,0")))
252 (clobber (reg:CC 24))]
254 "adds\\t%0, %2, %1\;adc\\t%R0, %R2, %1, asr #31"
255 [(set_attr "conds" "clob")
256 (set_attr "length" "8")])
258 (define_insn "*adddi_zesidi_di"
259 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
260 (plus:DI (zero_extend:DI
261 (match_operand:SI 1 "s_register_operand" "r,r"))
262 (match_operand:DI 2 "s_register_operand" "r,0")))
263 (clobber (reg:CC 24))]
265 "adds\\t%0, %2, %1\;adc\\t%R0, %R2, #0"
266 [(set_attr "conds" "clob")
267 (set_attr "length" "8")])
269 (define_expand "addsi3"
270 [(set (match_operand:SI 0 "s_register_operand" "")
271 (plus:SI (match_operand:SI 1 "s_register_operand" "")
272 (match_operand:SI 2 "reg_or_int_operand" "")))]
275 if (GET_CODE (operands[2]) == CONST_INT)
277 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
279 (reload_in_progress || reload_completed ? 0
280 : preserve_subexpressions_p ()));
286 [(set (match_operand:SI 0 "s_register_operand" "")
287 (plus:SI (match_operand:SI 1 "s_register_operand" "")
288 (match_operand:SI 2 "const_int_operand" "")))]
289 "! (const_ok_for_arm (INTVAL (operands[2]))
290 || const_ok_for_arm (-INTVAL (operands[2])))"
291 [(clobber (const_int 0))]
293 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
298 (define_insn "*addsi3_insn"
299 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
300 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
301 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
307 [(set_attr "length" "4,4,16")])
309 (define_insn "*addsi3_compare0"
310 [(set (reg:CC_NOOV 24)
312 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
313 (match_operand:SI 2 "arm_add_operand" "rI,L"))
315 (set (match_operand:SI 0 "s_register_operand" "=r,r")
316 (plus:SI (match_dup 1) (match_dup 2)))]
320 sub%?s\\t%0, %1, #%n2"
321 [(set_attr "conds" "set")])
323 (define_insn "*addsi3_compareneg"
325 (compare:CC (match_operand:SI 1 "s_register_operand" "r,r")
326 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
327 (set (match_operand:SI 0 "s_register_operand" "=r,r")
328 (plus:SI (match_dup 1) (match_dup 2)))]
332 sub%?s\\t%0, %1, #%n2"
333 [(set_attr "conds" "set")])
335 (define_insn "incscc"
336 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
337 (plus:SI (match_operator:SI 2 "comparison_operator"
338 [(reg 24) (const_int 0)])
339 (match_operand:SI 1 "s_register_operand" "0,?r")))]
343 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
344 [(set_attr "conds" "use")
345 (set_attr "length" "4,8")])
347 ; If a constant is too big to fit in a single instruction then the constant
348 ; will be pre-loaded into a register taking at least two insns, we might be
349 ; able to merge it with an add, but it depends on the exact value.
352 [(set (match_operand:SI 0 "s_register_operand" "=r")
353 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
354 (match_operand:SI 2 "immediate_operand" "n")))]
355 "!(const_ok_for_arm (INTVAL (operands[2]))
356 || const_ok_for_arm (-INTVAL (operands[2])))"
357 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
358 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
361 unsigned int val = (unsigned) INTVAL (operands[2]);
365 /* this code is similar to the approach followed in movsi, but it must
366 generate exactly two insns */
368 for (i = 30; i >= 0; i -= 2)
374 if (const_ok_for_arm (temp = (val & ~(255 << i))))
379 /* we might be able to do this as (larger number - small number) */
380 temp = ((val >> i) & 255) + 1;
381 if (temp > 255 && i < 24)
384 temp = ((val >> i) & 255) + 1;
386 if (const_ok_for_arm ((temp << i) - val))
389 temp = (unsigned) - (int) (i - val);
396 /* if we got here, we have found a way of doing it in two instructions.
397 the two constants are in val and temp */
398 operands[2] = GEN_INT ((int)val);
399 operands[3] = GEN_INT ((int)temp);
403 (define_insn "addsf3"
404 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
405 (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
406 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
410 suf%?s\\t%0, %1, #%N2"
411 [(set_attr "type" "farith")])
413 (define_insn "adddf3"
414 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
415 (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
416 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
420 suf%?d\\t%0, %1, #%N2"
421 [(set_attr "type" "farith")])
423 (define_insn "*adddf_df_esfdf"
424 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
425 (plus:DF (float_extend:DF
426 (match_operand:SF 1 "s_register_operand" "f,f"))
427 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
431 suf%?d\\t%0, %1, #%N2"
432 [(set_attr "type" "farith")])
434 (define_insn "*adddf_df_esfdf"
435 [(set (match_operand:DF 0 "s_register_operand" "=f")
436 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
438 (match_operand:SF 2 "s_register_operand" "f"))))]
440 "adf%?d\\t%0, %1, %2"
441 [(set_attr "type" "farith")])
443 (define_insn "*adddf_esfdf_esfdf"
444 [(set (match_operand:DF 0 "s_register_operand" "=f")
445 (plus:DF (float_extend:DF
446 (match_operand:SF 1 "s_register_operand" "f"))
448 (match_operand:SF 2 "s_register_operand" "f"))))]
450 "adf%?d\\t%0, %1, %2"
451 [(set_attr "type" "farith")])
453 (define_insn "addxf3"
454 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
455 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
456 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
457 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
460 suf%?e\\t%0, %1, #%N2"
461 [(set_attr "type" "farith")])
463 (define_insn "subdi3"
464 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
465 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
466 (match_operand:DI 2 "s_register_operand" "r,0,0")))
467 (clobber (reg:CC 24))]
469 "subs\\t%0, %1, %2\;sbc\\t%R0, %R1, %R2"
470 [(set_attr "conds" "clob")
471 (set_attr "length" "8")])
473 (define_insn "*subdi_di_zesidi"
474 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
475 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
477 (match_operand:SI 2 "s_register_operand" "r,r"))))
478 (clobber (reg:CC 24))]
480 "subs\\t%0, %1, %2\;sbc\\t%R0, %R1, #0"
481 [(set_attr "conds" "clob")
482 (set_attr "length" "8")])
484 (define_insn "*subdi_di_sesidi"
485 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
486 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
488 (match_operand:SI 2 "s_register_operand" "r,r"))))
489 (clobber (reg:CC 24))]
491 "subs\\t%0, %1, %2\;sbc\\t%R0, %R1, %2, asr #31"
492 [(set_attr "conds" "clob")
493 (set_attr "length" "8")])
495 (define_insn "*subdi_zesidi_di"
496 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
497 (minus:DI (zero_extend:DI
498 (match_operand:SI 2 "s_register_operand" "r,r"))
499 (match_operand:DI 1 "s_register_operand" "?r,0")))
500 (clobber (reg:CC 24))]
502 "rsbs\\t%0, %1, %2\;rsc\\t%R0, %R1, #0"
503 [(set_attr "conds" "clob")
504 (set_attr "length" "8")])
506 (define_insn "*subdi_sesidi_di"
507 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
508 (minus:DI (sign_extend:DI
509 (match_operand:SI 2 "s_register_operand" "r,r"))
510 (match_operand:DI 1 "s_register_operand" "?r,0")))
511 (clobber (reg:CC 24))]
513 "rsbs\\t%0, %1, %2\;rsc\\t%R0, %R1, %2, asr #31"
514 [(set_attr "conds" "clob")
515 (set_attr "length" "8")])
517 (define_insn "*subdi_zesidi_zesidi"
518 [(set (match_operand:DI 0 "s_register_operand" "=r")
519 (minus:DI (zero_extend:DI
520 (match_operand:SI 1 "s_register_operand" "r"))
522 (match_operand:SI 2 "s_register_operand" "r"))))
523 (clobber (reg:CC 24))]
525 "subs\\t%0, %1, %2\;rsc\\t%R0, %1, %1"
526 [(set_attr "conds" "clob")
527 (set_attr "length" "8")])
529 (define_expand "subsi3"
530 [(set (match_operand:SI 0 "s_register_operand" "")
531 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
532 (match_operand:SI 2 "s_register_operand" "")))]
535 if (GET_CODE (operands[1]) == CONST_INT)
537 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
539 (reload_in_progress || reload_completed ? 0
540 : preserve_subexpressions_p ()));
545 (define_insn "*subsi3_insn"
546 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
547 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
548 (match_operand:SI 2 "s_register_operand" "r,r")))]
553 [(set_attr "length" "4,16")])
556 [(set (match_operand:SI 0 "s_register_operand" "")
557 (minus:SI (match_operand:SI 1 "const_int_operand" "")
558 (match_operand:SI 2 "s_register_operand" "")))]
559 "! const_ok_for_arm (INTVAL (operands[1]))"
560 [(clobber (const_int 0))]
562 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
567 (define_insn "*subsi3_compare0"
568 [(set (reg:CC_NOOV 24)
569 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
570 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
572 (set (match_operand:SI 0 "s_register_operand" "=r,r")
573 (minus:SI (match_dup 1) (match_dup 2)))]
578 [(set_attr "conds" "set")])
580 (define_insn "decscc"
581 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
582 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
583 (match_operator:SI 2 "comparison_operator"
584 [(reg 24) (const_int 0)])))]
588 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
589 [(set_attr "conds" "use")
590 (set_attr "length" "*,8")])
592 (define_insn "subsf3"
593 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
594 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
595 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
600 [(set_attr "type" "farith")])
602 (define_insn "subdf3"
603 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
604 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
605 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
610 [(set_attr "type" "farith")])
612 (define_insn "*subdf_esfdf_df"
613 [(set (match_operand:DF 0 "s_register_operand" "=f")
614 (minus:DF (float_extend:DF
615 (match_operand:SF 1 "s_register_operand" "f"))
616 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
618 "suf%?d\\t%0, %1, %2"
619 [(set_attr "type" "farith")])
621 (define_insn "*subdf_df_esfdf"
622 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
623 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
625 (match_operand:SF 2 "s_register_operand" "f,f"))))]
630 [(set_attr "type" "farith")])
632 (define_insn "*subdf_esfdf_esfdf"
633 [(set (match_operand:DF 0 "s_register_operand" "=f")
634 (minus:DF (float_extend:DF
635 (match_operand:SF 1 "s_register_operand" "f"))
637 (match_operand:SF 2 "s_register_operand" "f"))))]
639 "suf%?d\\t%0, %1, %2"
640 [(set_attr "type" "farith")])
642 (define_insn "subxf3"
643 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
644 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
645 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
646 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
650 [(set_attr "type" "farith")])
652 ;; Multiplication insns
654 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
655 (define_insn "mulsi3"
656 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
657 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
658 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
661 [(set_attr "type" "mult")])
663 (define_insn "*mulsi3_compare0"
664 [(set (reg:CC_NOOV 24)
665 (compare:CC_NOOV (mult:SI
666 (match_operand:SI 2 "s_register_operand" "r,r")
667 (match_operand:SI 1 "s_register_operand" "%?r,0"))
669 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
670 (mult:SI (match_dup 2) (match_dup 1)))]
672 "mul%?s\\t%0, %2, %1"
673 [(set_attr "conds" "set")
674 (set_attr "type" "mult")])
676 (define_insn "*mulsi_compare0_scratch"
677 [(set (reg:CC_NOOV 24)
678 (compare:CC_NOOV (mult:SI
679 (match_operand:SI 2 "s_register_operand" "r,r")
680 (match_operand:SI 1 "s_register_operand" "%?r,0"))
682 (clobber (match_scratch:SI 0 "=&r,&r"))]
684 "mul%?s\\t%0, %2, %1"
685 [(set_attr "conds" "set")
686 (set_attr "type" "mult")])
688 ;; Unnamed templates to match MLA instruction.
690 (define_insn "*mulsi3addsi"
691 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
693 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
694 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
695 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
697 "mla%?\\t%0, %2, %1, %3"
698 [(set_attr "type" "mult")])
700 (define_insn "*mulsi3addsi_compare0"
701 [(set (reg:CC_NOOV 24)
702 (compare:CC_NOOV (plus:SI
704 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
705 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
706 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
708 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
709 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
712 "mla%?s\\t%0, %2, %1, %3"
713 [(set_attr "conds" "set")
714 (set_attr "type" "mult")])
716 (define_insn "*mulsi3addsi_compare0_scratch"
717 [(set (reg:CC_NOOV 24)
718 (compare:CC_NOOV (plus:SI
720 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
721 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
722 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
724 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
726 "mla%?s\\t%0, %2, %1, %3"
727 [(set_attr "conds" "set")
728 (set_attr "type" "mult")])
730 (define_insn "mulsidi3"
731 [(set (match_operand:DI 0 "s_register_operand" "=&r")
732 (mult:DI (sign_extend:DI
733 (match_operand:SI 1 "s_register_operand" "%r"))
735 (match_operand:SI 2 "s_register_operand" "r"))))]
737 "smull%?\\t%0, %R0, %1, %2"
738 [(set_attr "type" "mult")])
740 (define_insn "umulsidi3"
741 [(set (match_operand:DI 0 "s_register_operand" "=&r")
742 (mult:DI (zero_extend:DI
743 (match_operand:SI 1 "s_register_operand" "%r"))
745 (match_operand:SI 2 "s_register_operand" "r"))))]
747 "umull%?\\t%0, %R0, %1, %2"
748 [(set_attr "type" "mult")])
750 (define_insn "mulsf3"
751 [(set (match_operand:SF 0 "s_register_operand" "=f")
752 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
753 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
755 "fml%?s\\t%0, %1, %2"
756 [(set_attr "type" "ffmul")])
758 (define_insn "muldf3"
759 [(set (match_operand:DF 0 "s_register_operand" "=f")
760 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
761 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
763 "muf%?d\\t%0, %1, %2"
764 [(set_attr "type" "fmul")])
766 (define_insn "*muldf_esfdf_df"
767 [(set (match_operand:DF 0 "s_register_operand" "=f")
768 (mult:DF (float_extend:DF
769 (match_operand:SF 1 "s_register_operand" "f"))
770 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
772 "muf%?d\\t%0, %1, %2"
773 [(set_attr "type" "fmul")])
775 (define_insn "*muldf_df_esfdf"
776 [(set (match_operand:DF 0 "s_register_operand" "=f")
777 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
779 (match_operand:SF 2 "s_register_operand" "f"))))]
781 "muf%?d\\t%0, %1, %2"
782 [(set_attr "type" "fmul")])
784 (define_insn "*muldf_esfdf_esfdf"
785 [(set (match_operand:DF 0 "s_register_operand" "=f")
786 (mult:DF (float_extend:DF
787 (match_operand:SF 1 "s_register_operand" "f"))
789 (match_operand:SF 2 "s_register_operand" "f"))))]
791 "muf%?d\\t%0, %1, %2"
792 [(set_attr "type" "fmul")])
794 (define_insn "mulxf3"
795 [(set (match_operand:XF 0 "s_register_operand" "=f")
796 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
797 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
798 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
799 "muf%?e\\t%0, %1, %2"
800 [(set_attr "type" "fmul")])
804 (define_insn "divsf3"
805 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
806 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
807 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
812 [(set_attr "type" "fdivs")])
814 (define_insn "divdf3"
815 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
816 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
817 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
822 [(set_attr "type" "fdivd")])
824 (define_insn "*divdf_esfdf_df"
825 [(set (match_operand:DF 0 "s_register_operand" "=f")
826 (div:DF (float_extend:DF
827 (match_operand:SF 1 "s_register_operand" "f"))
828 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
830 "dvf%?d\\t%0, %1, %2"
831 [(set_attr "type" "fdivd")])
833 (define_insn "*divdf_df_esfdf"
834 [(set (match_operand:DF 0 "s_register_operand" "=f")
835 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
837 (match_operand:SF 2 "s_register_operand" "f"))))]
839 "rdf%?d\\t%0, %2, %1"
840 [(set_attr "type" "fdivd")])
842 (define_insn "*divdf_esfdf_esfdf"
843 [(set (match_operand:DF 0 "s_register_operand" "=f")
844 (div:DF (float_extend:DF
845 (match_operand:SF 1 "s_register_operand" "f"))
847 (match_operand:SF 2 "s_register_operand" "f"))))]
849 "dvf%?d\\t%0, %1, %2"
850 [(set_attr "type" "fdivd")])
852 (define_insn "divxf3"
853 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
854 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
855 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
856 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
860 [(set_attr "type" "fdivx")])
864 (define_insn "modsf3"
865 [(set (match_operand:SF 0 "s_register_operand" "=f")
866 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
867 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
869 "rmf%?s\\t%0, %1, %2"
870 [(set_attr "type" "fdivs")])
872 (define_insn "moddf3"
873 [(set (match_operand:DF 0 "s_register_operand" "=f")
874 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
875 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
877 "rmf%?d\\t%0, %1, %2"
878 [(set_attr "type" "fdivd")])
880 (define_insn "*moddf_esfdf_df"
881 [(set (match_operand:DF 0 "s_register_operand" "=f")
882 (mod:DF (float_extend:DF
883 (match_operand:SF 1 "s_register_operand" "f"))
884 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
886 "rmf%?d\\t%0, %1, %2"
887 [(set_attr "type" "fdivd")])
889 (define_insn "*moddf_df_esfdf"
890 [(set (match_operand:DF 0 "s_register_operand" "=f")
891 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
893 (match_operand:SF 2 "s_register_operand" "f"))))]
895 "rmf%?d\\t%0, %1, %2"
896 [(set_attr "type" "fdivd")])
898 (define_insn "*moddf_esfdf_esfdf"
899 [(set (match_operand:DF 0 "s_register_operand" "=f")
900 (mod:DF (float_extend:DF
901 (match_operand:SF 1 "s_register_operand" "f"))
903 (match_operand:SF 2 "s_register_operand" "f"))))]
905 "rmf%?d\\t%0, %1, %2"
906 [(set_attr "type" "fdivd")])
908 (define_insn "modxf3"
909 [(set (match_operand:XF 0 "s_register_operand" "=f")
910 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
911 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
912 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
913 "rmf%?e\\t%0, %1, %2"
914 [(set_attr "type" "fdivx")])
916 ;; Boolean and,ior,xor insns
918 (define_insn "anddi3"
919 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
920 (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
921 (match_operand:DI 2 "s_register_operand" "r,0")))]
923 "and%?\\t%0, %1, %2\;and%?\\t%R0, %R1, %R2"
924 [(set_attr "length" "8")])
926 (define_insn "*anddi_zesidi_di"
927 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
928 (and:DI (zero_extend:DI
929 (match_operand:SI 2 "s_register_operand" "r,r"))
930 (match_operand:DI 1 "s_register_operand" "?r,0")))]
932 "and%?\\t%0, %1, %2\;mov%?\\t%R0, #0"
933 [(set_attr "length" "8")])
935 (define_insn "*anddi_sesdi_di"
936 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
937 (and:DI (sign_extend:DI
938 (match_operand:SI 2 "s_register_operand" "r,r"))
939 (match_operand:DI 1 "s_register_operand" "?r,0")))]
941 "and%?\\t%0, %1, %2\;and%?\\t%R0, %R1, %2, asr #31"
942 [(set_attr "length" "8")])
944 (define_expand "andsi3"
945 [(set (match_operand:SI 0 "s_register_operand" "")
946 (and:SI (match_operand:SI 1 "s_register_operand" "")
947 (match_operand:SI 2 "reg_or_int_operand" "")))]
950 if (GET_CODE (operands[2]) == CONST_INT)
952 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
954 (reload_in_progress || reload_completed
955 ? 0 : preserve_subexpressions_p ()));
960 (define_insn "*andsi3_insn"
961 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
962 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
963 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
969 [(set_attr "length" "4,4,16")])
972 [(set (match_operand:SI 0 "s_register_operand" "")
973 (and:SI (match_operand:SI 1 "s_register_operand" "")
974 (match_operand:SI 2 "const_int_operand" "")))]
975 "! (const_ok_for_arm (INTVAL (operands[2]))
976 || const_ok_for_arm (~ INTVAL (operands[2])))"
977 [(clobber (const_int 0))]
979 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
984 (define_insn "*andsi3_compare0"
985 [(set (reg:CC_NOOV 24)
987 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
988 (match_operand:SI 2 "arm_not_operand" "rI,K"))
990 (set (match_operand:SI 0 "s_register_operand" "=r,r")
991 (and:SI (match_dup 1) (match_dup 2)))]
995 bic%?s\\t%0, %1, #%B2"
996 [(set_attr "conds" "set")])
998 (define_insn "*andsi3_compare0_scratch"
999 [(set (reg:CC_NOOV 24)
1001 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1002 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1004 (clobber (match_scratch:SI 3 "=X,r"))]
1008 bic%?s\\t%3, %0, #%B1"
1009 [(set_attr "conds" "set")])
1011 (define_insn "*zeroextractsi_compare0_scratch"
1012 [(set (reg:CC_NOOV 24)
1013 (compare:CC_NOOV (zero_extract:SI
1014 (match_operand:SI 0 "s_register_operand" "r")
1015 (match_operand:SI 1 "immediate_operand" "n")
1016 (match_operand:SI 2 "immediate_operand" "n"))
1018 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1019 && INTVAL (operands[1]) > 0
1020 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1021 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1024 unsigned int mask = 0;
1025 int cnt = INTVAL (operands[1]);
1028 mask = (mask << 1) | 1;
1029 operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1030 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1034 [(set_attr "conds" "set")])
1036 (define_insn "*zeroextractqi_compare0_scratch"
1037 [(set (reg:CC_NOOV 24)
1038 (compare:CC_NOOV (zero_extract:SI
1039 (match_operand:QI 0 "memory_operand" "m")
1040 (match_operand 1 "immediate_operand" "n")
1041 (match_operand 2 "immediate_operand" "n"))
1043 (clobber (match_scratch:QI 3 "=r"))]
1044 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 8
1045 && INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8"
1048 unsigned int mask = 0;
1049 int cnt = INTVAL (operands[1]);
1052 mask = (mask << 1) | 1;
1053 operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1054 output_asm_insn (\"ldr%?b\\t%3, %0\", operands);
1055 output_asm_insn (\"tst%?\\t%3, %1\", operands);
1059 [(set_attr "conds" "set")
1060 (set_attr "length" "8")])
1062 ;; constants for op 2 will never be given to these patterns.
1063 (define_insn "*anddi_notdi_di"
1064 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1065 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1066 (match_operand:DI 1 "s_register_operand" "0,r")))]
1068 "bic%?\\t%0, %1, %2\;bic%?\\t%R0, %R1, %R2"
1069 [(set_attr "length" "8")])
1071 (define_insn "*anddi_notzesidi_di"
1072 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1073 (and:DI (not:DI (zero_extend:DI
1074 (match_operand:SI 2 "s_register_operand" "r,r")))
1075 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1079 bic%?\\t%0, %1, %2\;mov%?\\t%R0, %R1"
1080 [(set_attr "length" "4,8")])
1082 (define_insn "*anddi_notsesidi_di"
1083 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1084 (and:DI (not:DI (sign_extend:DI
1085 (match_operand:SI 2 "s_register_operand" "r,r")))
1086 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1088 "bic%?\\t%0, %1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
1089 [(set_attr "length" "8")])
1091 (define_insn "*andsi_notsi_si"
1092 [(set (match_operand:SI 0 "s_register_operand" "=r")
1093 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1094 (match_operand:SI 1 "s_register_operand" "r")))]
1096 "bic%?\\t%0, %1, %2")
1098 (define_insn "*andsi_notsi_si_compare0"
1099 [(set (reg:CC_NOOV 24)
1101 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1102 (match_operand:SI 1 "s_register_operand" "r"))
1104 (set (match_operand:SI 0 "s_register_operand" "=r")
1105 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1107 "bic%?s\\t%0, %1, %2"
1108 [(set_attr "conds" "set")])
1110 (define_insn "*andsi_notsi_si_compare0_scratch"
1111 [(set (reg:CC_NOOV 24)
1113 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1114 (match_operand:SI 1 "s_register_operand" "r"))
1116 (clobber (match_scratch:SI 0 "=r"))]
1118 "bic%?s\\t%0, %1, %2"
1119 [(set_attr "conds" "set")])
1121 (define_insn "iordi3"
1122 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1123 (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1124 (match_operand:DI 2 "s_register_operand" "r")))]
1126 "orr%?\\t%0, %1, %2\;orr%?\\t%R0, %R1, %R2"
1127 [(set_attr "length" "8")])
1129 (define_insn "*iordi_zesidi_di"
1130 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1131 (ior:DI (zero_extend:DI
1132 (match_operand:SI 2 "s_register_operand" "r,r"))
1133 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1137 orr%?\\t%0, %1, %2\;mov%?\\t%R0, %R1"
1138 [(set_attr "length" "4,8")])
1140 (define_insn "*iordi_sesidi_di"
1141 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1142 (ior:DI (sign_extend:DI
1143 (match_operand:SI 2 "s_register_operand" "r,r"))
1144 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1146 "orr%?\\t%0, %1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
1147 [(set_attr "length" "8")])
1149 (define_expand "iorsi3"
1150 [(set (match_operand:SI 0 "s_register_operand" "")
1151 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1152 (match_operand:SI 2 "reg_or_int_operand" "")))]
1155 if (GET_CODE (operands[2]) == CONST_INT)
1157 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1159 (reload_in_progress || reload_completed
1160 ? 0 : preserve_subexpressions_p ()));
1165 (define_insn "*iorsi3_insn"
1166 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1167 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1168 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1173 [(set_attr "length" "4,16")])
1176 [(set (match_operand:SI 0 "s_register_operand" "")
1177 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1178 (match_operand:SI 2 "const_int_operand" "")))]
1179 "! const_ok_for_arm (INTVAL (operands[2]))"
1180 [(clobber (const_int 0))]
1182 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1187 (define_insn "*iorsi3_compare0"
1188 [(set (reg:CC_NOOV 24)
1189 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1190 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1192 (set (match_operand:SI 0 "s_register_operand" "=r")
1193 (ior:SI (match_dup 1) (match_dup 2)))]
1195 "orr%?s\\t%0, %1, %2"
1196 [(set_attr "conds" "set")])
1198 (define_insn "*iorsi3_compare0_scratch"
1199 [(set (reg:CC_NOOV 24)
1200 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1201 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1203 (clobber (match_scratch:SI 0 "=r"))]
1205 "orr%?s\\t%0, %1, %2"
1206 [(set_attr "conds" "set")])
1208 (define_insn "xordi3"
1209 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1210 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1211 (match_operand:DI 2 "s_register_operand" "r,0")))]
1213 "eor%?\\t%0, %1, %2\;eor%?\\t%R0, %R1, %R2"
1214 [(set_attr "length" "8")])
1216 (define_insn "*xordi_zesidi_di"
1217 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1218 (xor:DI (zero_extend:DI
1219 (match_operand:SI 2 "s_register_operand" "r,r"))
1220 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1224 eor%?\\t%0, %1, %2\;mov%?\\t%R0, %R1"
1225 [(set_attr "length" "4,8")])
1227 (define_insn "*xordi_sesidi_di"
1228 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1229 (xor:DI (sign_extend:DI
1230 (match_operand:SI 2 "s_register_operand" "r,r"))
1231 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1233 "eor%?\\t%0, %1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
1234 [(set_attr "length" "8")])
1236 (define_insn "xorsi3"
1237 [(set (match_operand:SI 0 "s_register_operand" "=r")
1238 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1239 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1241 "eor%?\\t%0, %1, %2")
1243 (define_insn "*xorsi3_compare0"
1244 [(set (reg:CC_NOOV 24)
1245 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1246 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1248 (set (match_operand:SI 0 "s_register_operand" "=r")
1249 (xor:SI (match_dup 1) (match_dup 2)))]
1251 "eor%?s\\t%0, %1, %2"
1252 [(set_attr "conds" "set")])
1254 (define_insn "*xorsi3_compare0_scratch"
1255 [(set (reg:CC_NOOV 24)
1256 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1257 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1261 [(set_attr "conds" "set")])
1263 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
1264 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1268 [(set (match_operand:SI 0 "s_register_operand" "=r")
1269 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1270 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1271 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1272 (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1274 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1275 (not:SI (match_dup 3))))
1276 (set (match_dup 0) (not:SI (match_dup 4)))]
1280 (define_insn "*andsi_iorsi3_notsi"
1281 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1282 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1283 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1284 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1286 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1287 [(set_attr "length" "8")])
1291 ;; Minimum and maximum insns
1293 (define_insn "smaxsi3"
1294 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1295 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1296 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1297 (clobber (reg:CC 24))]
1300 cmp\\t%1, %2\;movlt\\t%0, %2
1301 cmp\\t%1, %2\;movge\\t%0, %1
1302 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1303 [(set_attr "conds" "clob")
1304 (set_attr "length" "8,8,12")])
1306 (define_insn "sminsi3"
1307 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1308 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1309 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1310 (clobber (reg:CC 24))]
1313 cmp\\t%1, %2\;movge\\t%0, %2
1314 cmp\\t%1, %2\;movlt\\t%0, %1
1315 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1316 [(set_attr "conds" "clob")
1317 (set_attr "length" "8,8,12")])
1319 (define_insn "umaxsi3"
1320 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1321 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1322 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1323 (clobber (reg:CC 24))]
1326 cmp\\t%1, %2\;movcc\\t%0, %2
1327 cmp\\t%1, %2\;movcs\\t%0, %1
1328 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1329 [(set_attr "conds" "clob")
1330 (set_attr "length" "8,8,12")])
1332 (define_insn "uminsi3"
1333 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1334 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1335 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1336 (clobber (reg:CC 24))]
1339 cmp\\t%1, %2\;movcs\\t%0, %2
1340 cmp\\t%1, %2\;movcc\\t%0, %1
1341 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1342 [(set_attr "conds" "clob")
1343 (set_attr "length" "8,8,12")])
1345 (define_insn "*store_minmansi"
1346 [(set (match_operand:SI 0 "memory_operand" "=m")
1347 (match_operator:SI 3 "minmax_operator"
1348 [(match_operand:SI 1 "s_register_operand" "r")
1349 (match_operand:SI 2 "s_register_operand" "r")]))
1350 (clobber (reg:CC 24))]
1353 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1355 output_asm_insn (\"cmp\\t%1, %2\", operands);
1356 output_asm_insn (\"str%d3\\t%1, %0\", operands);
1357 output_asm_insn (\"str%D3\\t%2, %0\", operands);
1360 [(set_attr "conds" "clob")
1361 (set_attr "length" "12")
1362 (set_attr "type" "store1")])
1364 (define_insn "*minmax_arithsi"
1365 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1366 (match_operator:SI 4 "shiftable_operator"
1367 [(match_operator:SI 5 "minmax_operator"
1368 [(match_operand:SI 2 "s_register_operand" "r,r")
1369 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1370 (match_operand:SI 1 "s_register_operand" "0,?r")]))
1371 (clobber (reg:CC 24))]
1375 enum rtx_code code = GET_CODE (operands[4]);
1377 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1379 output_asm_insn (\"cmp\\t%2, %3\", operands);
1380 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1381 if (which_alternative != 0 || operands[3] != const0_rtx
1382 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1383 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1387 [(set_attr "conds" "clob")
1388 (set_attr "length" "12")])
1391 ;; Shift and rotation insns
1393 (define_expand "ashlsi3"
1394 [(set (match_operand:SI 0 "s_register_operand" "")
1395 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
1396 (match_operand:SI 2 "arm_rhs_operand" "")))]
1399 if (GET_CODE (operands[2]) == CONST_INT
1400 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1402 emit_insn (gen_movsi (operands[0], const0_rtx));
1407 (define_expand "ashrsi3"
1408 [(set (match_operand:SI 0 "s_register_operand" "")
1409 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1410 (match_operand:SI 2 "arm_rhs_operand" "")))]
1413 if (GET_CODE (operands[2]) == CONST_INT
1414 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1415 operands[2] = GEN_INT (31);
1418 (define_expand "lshrsi3"
1419 [(set (match_operand:SI 0 "s_register_operand" "")
1420 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1421 (match_operand:SI 2 "arm_rhs_operand" "")))]
1424 if (GET_CODE (operands[2]) == CONST_INT
1425 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1427 emit_insn (gen_movsi (operands[0], const0_rtx));
1432 (define_expand "rotlsi3"
1433 [(set (match_operand:SI 0 "s_register_operand" "")
1434 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1435 (match_operand:SI 2 "reg_or_int_operand" "")))]
1438 if (GET_CODE (operands[2]) == CONST_INT)
1439 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
1442 rtx reg = gen_reg_rtx (SImode);
1443 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
1448 (define_expand "rotrsi3"
1449 [(set (match_operand:SI 0 "s_register_operand" "")
1450 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1451 (match_operand:SI 2 "arm_rhs_operand" "")))]
1454 if (GET_CODE (operands[2]) == CONST_INT
1455 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1456 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
1459 (define_insn "*shiftsi3"
1460 [(set (match_operand:SI 0 "s_register_operand" "=r")
1461 (match_operator:SI 3 "shift_operator"
1462 [(match_operand:SI 1 "s_register_operand" "r")
1463 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
1465 "mov%?\\t%0, %1%S3")
1467 (define_insn "*shiftsi3_compare0"
1468 [(set (reg:CC_NOOV 24)
1469 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1470 [(match_operand:SI 1 "s_register_operand" "r")
1471 (match_operand:SI 2 "arm_rhs_operand" "rM")])
1473 (set (match_operand:SI 0 "s_register_operand" "=r")
1474 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
1476 "mov%?s\\t%0, %1%S3"
1477 [(set_attr "conds" "set")])
1479 (define_insn "*shiftsi3_compare0_scratch"
1480 [(set (reg:CC_NOOV 24)
1481 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1482 [(match_operand:SI 1 "s_register_operand" "r")
1483 (match_operand:SI 2 "arm_rhs_operand" "rM")])
1485 (clobber (match_scratch:SI 0 "=r"))]
1487 "mov%?s\\t%0, %1%S3"
1488 [(set_attr "conds" "set")])
1490 (define_insn "*notsi_shiftsi"
1491 [(set (match_operand:SI 0 "s_register_operand" "=r")
1492 (not:SI (match_operator:SI 3 "shift_operator"
1493 [(match_operand:SI 1 "s_register_operand" "r")
1494 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
1496 "mvn%?\\t%0, %1%S3")
1498 (define_insn "*notsi_shiftsi_compare0"
1499 [(set (reg:CC_NOOV 24)
1500 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1501 [(match_operand:SI 1 "s_register_operand" "r")
1502 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1504 (set (match_operand:SI 0 "s_register_operand" "=r")
1505 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1507 "mvn%?s\\t%0, %1%S3"
1508 [(set_attr "conds" "set")])
1510 (define_insn "*not_shiftsi_compare0_scratch"
1511 [(set (reg:CC_NOOV 24)
1512 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1513 [(match_operand:SI 1 "s_register_operand" "r")
1514 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1516 (clobber (match_scratch:SI 0 "=r"))]
1518 "mvn%?s\\t%0, %1%S3"
1519 [(set_attr "conds" "set")])
1522 ;; Unary arithmetic insns
1524 (define_insn "negdi2"
1525 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1526 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1528 "rsbs\\t%0, %1, #0\;rsc\\t%R0, %R1, #0"
1529 [(set_attr "conds" "clob")
1530 (set_attr "length" "8")])
1532 (define_insn "negsi2"
1533 [(set (match_operand:SI 0 "s_register_operand" "=r")
1534 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1536 "rsb%?\\t%0, %1, #0")
1538 (define_insn "negsf2"
1539 [(set (match_operand:SF 0 "s_register_operand" "=f")
1540 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1543 [(set_attr "type" "ffarith")])
1545 (define_insn "negdf2"
1546 [(set (match_operand:DF 0 "s_register_operand" "=f")
1547 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1550 [(set_attr "type" "ffarith")])
1552 (define_insn "*negdf_esfdf"
1553 [(set (match_operand:DF 0 "s_register_operand" "=f")
1554 (neg:DF (float_extend:DF
1555 (match_operand:SF 1 "s_register_operand" "f"))))]
1558 [(set_attr "type" "ffarith")])
1560 (define_insn "negxf2"
1561 [(set (match_operand:XF 0 "s_register_operand" "=f")
1562 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1563 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1565 [(set_attr "type" "ffarith")])
1567 ;; abssi2 doesn't really clobber the condition codes if a different register
1568 ;; is being set. To keep things simple, assume during rtl manipulations that
1569 ;; it does, but tell the final scan operator the truth. Similarly for
1572 (define_insn "abssi2"
1573 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1574 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1578 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
1579 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
1580 [(set_attr "conds" "clob,*")
1581 (set_attr "length" "8")])
1583 (define_insn "*neg_abssi2"
1584 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1585 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1589 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
1590 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
1591 [(set_attr "conds" "clob,*")
1592 (set_attr "length" "8")])
1594 (define_insn "abssf2"
1595 [(set (match_operand:SF 0 "s_register_operand" "=f")
1596 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1599 [(set_attr "type" "ffarith")])
1601 (define_insn "absdf2"
1602 [(set (match_operand:DF 0 "s_register_operand" "=f")
1603 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1606 [(set_attr "type" "ffarith")])
1608 (define_insn "*absdf_esfdf"
1609 [(set (match_operand:DF 0 "s_register_operand" "=f")
1610 (abs:DF (float_extend:DF
1611 (match_operand:SF 1 "s_register_operand" "f"))))]
1614 [(set_attr "type" "ffarith")])
1616 (define_insn "absxf2"
1617 [(set (match_operand:XF 0 "s_register_operand" "=f")
1618 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1619 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1621 [(set_attr "type" "ffarith")])
1623 (define_insn "sqrtsf2"
1624 [(set (match_operand:SF 0 "s_register_operand" "=f")
1625 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1628 [(set_attr "type" "float_em")])
1630 (define_insn "sqrtdf2"
1631 [(set (match_operand:DF 0 "s_register_operand" "=f")
1632 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1635 [(set_attr "type" "float_em")])
1637 (define_insn "*sqrtdf_esfdf"
1638 [(set (match_operand:DF 0 "s_register_operand" "=f")
1639 (sqrt:DF (float_extend:DF
1640 (match_operand:SF 1 "s_register_operand" "f"))))]
1643 [(set_attr "type" "float_em")])
1645 (define_insn "sqrtxf2"
1646 [(set (match_operand:XF 0 "s_register_operand" "=f")
1647 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1648 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1650 [(set_attr "type" "float_em")])
1652 (define_insn "sinsf2"
1653 [(set (match_operand:SF 0 "s_register_operand" "=f")
1654 (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1657 [(set_attr "type" "float_em")])
1659 (define_insn "sindf2"
1660 [(set (match_operand:DF 0 "s_register_operand" "=f")
1661 (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1664 [(set_attr "type" "float_em")])
1666 (define_insn "*sindf_esfdf"
1667 [(set (match_operand:DF 0 "s_register_operand" "=f")
1668 (unspec:DF [(float_extend:DF
1669 (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1672 [(set_attr "type" "float_em")])
1674 (define_insn "sinxf2"
1675 [(set (match_operand:XF 0 "s_register_operand" "=f")
1676 (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1677 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1679 [(set_attr "type" "float_em")])
1681 (define_insn "cossf2"
1682 [(set (match_operand:SF 0 "s_register_operand" "=f")
1683 (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
1686 [(set_attr "type" "float_em")])
1688 (define_insn "cosdf2"
1689 [(set (match_operand:DF 0 "s_register_operand" "=f")
1690 (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
1693 [(set_attr "type" "float_em")])
1695 (define_insn "*cosdf_esfdf"
1696 [(set (match_operand:DF 0 "s_register_operand" "=f")
1697 (unspec:DF [(float_extend:DF
1698 (match_operand:SF 1 "s_register_operand" "f"))] 1))]
1701 [(set_attr "type" "float_em")])
1703 (define_insn "cosxf2"
1704 [(set (match_operand:XF 0 "s_register_operand" "=f")
1705 (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
1706 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1708 [(set_attr "type" "float_em")])
1710 (define_insn "one_cmpldi2"
1711 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1712 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1714 "mvn%?\\t%0, %1\;mvn%?\\t%R0, %R1"
1715 [(set_attr "length" "8")])
1717 (define_insn "one_cmplsi2"
1718 [(set (match_operand:SI 0 "s_register_operand" "=r")
1719 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
1723 (define_insn "*notsi_compare0"
1724 [(set (reg:CC_NOOV 24)
1725 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1727 (set (match_operand:SI 0 "s_register_operand" "=r")
1728 (not:SI (match_dup 1)))]
1731 [(set_attr "conds" "set")])
1733 (define_insn "*notsi_compare0_scratch"
1734 [(set (reg:CC_NOOV 24)
1735 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1737 (clobber (match_scratch:SI 0 "=r"))]
1740 [(set_attr "conds" "set")])
1742 ;; Fixed <--> Floating conversion insns
1744 (define_insn "floatsisf2"
1745 [(set (match_operand:SF 0 "s_register_operand" "=f")
1746 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
1749 [(set_attr "type" "r_2_f")])
1751 (define_insn "floatsidf2"
1752 [(set (match_operand:DF 0 "s_register_operand" "=f")
1753 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
1756 [(set_attr "type" "r_2_f")])
1758 (define_insn "floatsixf2"
1759 [(set (match_operand:XF 0 "s_register_operand" "=f")
1760 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
1761 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1763 [(set_attr "type" "r_2_f")])
1765 (define_insn "fix_truncsfsi2"
1766 [(set (match_operand:SI 0 "s_register_operand" "=r")
1767 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
1770 [(set_attr "type" "f_2_r")])
1772 (define_insn "fix_truncdfsi2"
1773 [(set (match_operand:SI 0 "s_register_operand" "=r")
1774 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
1777 [(set_attr "type" "f_2_r")])
1779 (define_insn "fix_truncxfsi2"
1780 [(set (match_operand:SI 0 "s_register_operand" "=r")
1781 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
1782 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1784 [(set_attr "type" "f_2_r")])
1788 (define_insn "truncdfsf2"
1789 [(set (match_operand:SF 0 "s_register_operand" "=f")
1791 (match_operand:DF 1 "s_register_operand" "f")))]
1794 [(set_attr "type" "ffarith")])
1796 (define_insn "truncxfsf2"
1797 [(set (match_operand:SF 0 "s_register_operand" "=f")
1799 (match_operand:XF 1 "s_register_operand" "f")))]
1800 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1802 [(set_attr "type" "ffarith")])
1804 (define_insn "truncxfdf2"
1805 [(set (match_operand:DF 0 "s_register_operand" "=f")
1807 (match_operand:XF 1 "s_register_operand" "f")))]
1808 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1810 [(set_attr "type" "ffarith")])
1812 ;; Zero and sign extension instructions.
1814 (define_insn "zero_extendsidi2"
1815 [(set (match_operand:DI 0 "s_register_operand" "=r")
1816 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
1819 if (REGNO (operands[1]) != REGNO (operands[0]))
1820 output_asm_insn (\"mov%?\\t%0, %1\", operands);
1821 return \"mov%?\\t%R0, #0\";
1823 [(set_attr "length" "8")])
1825 (define_insn "zero_extendqidi2"
1826 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
1827 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1830 and%?\\t%0, %1, #255\;mov%?\\t%R0, #0
1831 ldr%?b\\t%0, %1\;mov%?\\t%R0, #0"
1832 [(set_attr "length" "8")
1833 (set_attr "type" "*,load")])
1835 (define_insn "extendsidi2"
1836 [(set (match_operand:DI 0 "s_register_operand" "=r")
1837 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
1840 if (REGNO (operands[1]) != REGNO (operands[0]))
1841 output_asm_insn (\"mov%?\\t%0, %1\", operands);
1842 return \"mov%?\\t%R0, %0, asr #31\";
1844 [(set_attr "length" "8")])
1846 (define_expand "zero_extendhisi2"
1847 [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
1849 (set (match_operand:SI 0 "s_register_operand" "")
1850 (lshiftrt:SI (match_dup 2) (const_int 16)))]
1854 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
1856 emit_insn (gen_rtx (SET, VOIDmode, operands[0],
1857 gen_rtx (ZERO_EXTEND, SImode, operands[1])));
1860 if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
1862 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
1865 if (! s_register_operand (operands[1], HImode))
1866 operands[1] = copy_to_mode_reg (HImode, operands[1]);
1867 operands[1] = gen_lowpart (SImode, operands[1]);
1868 operands[2] = gen_reg_rtx (SImode);
1871 (define_insn "*zero_extendhisi_insn"
1872 [(set (match_operand:SI 0 "s_register_operand" "=r")
1873 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1876 [(set_attr "type" "load")])
1878 (define_expand "zero_extendqisi2"
1879 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1881 (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
1884 if (GET_CODE (operands[1]) != MEM)
1886 emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
1892 (define_insn "*load_extendqisi"
1893 [(set (match_operand:SI 0 "s_register_operand" "=r")
1894 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
1896 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
1897 [(set_attr "type" "load")])
1900 [(set (match_operand:SI 0 "s_register_operand" "")
1901 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
1902 (clobber (match_operand:SI 2 "s_register_operand" ""))]
1903 "GET_CODE (operands[1]) != MEM"
1904 [(set (match_dup 2) (match_dup 1))
1905 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
1908 (define_insn "*compareqi_eq0"
1909 [(set (reg:CC_NOOV 24)
1910 (compare:CC_NOOV (match_operand:QI 0 "s_register_operand" "r")
1914 [(set_attr "conds" "set")])
1916 (define_expand "extendhisi2"
1918 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
1920 (set (match_operand:SI 0 "s_register_operand" "")
1921 (ashiftrt:SI (match_dup 2)
1926 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
1928 emit_insn (gen_rtx (SET, VOIDmode, operands[0],
1929 gen_rtx (SIGN_EXTEND, SImode, operands[1])));
1933 if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
1935 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
1938 if (! s_register_operand (operands[1], HImode))
1939 operands[1] = copy_to_mode_reg (HImode, operands[1]);
1940 operands[1] = gen_lowpart (SImode, operands[1]);
1941 operands[2] = gen_reg_rtx (SImode);
1944 (define_expand "extendhisi2_mem"
1945 [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" ""))))
1947 (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1)))))
1948 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
1949 (set (match_operand:SI 0 "" "")
1950 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
1953 operands[0] = gen_lowpart (SImode, operands[0]);
1954 operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
1955 operands[2] = gen_reg_rtx (SImode);
1956 operands[3] = gen_reg_rtx (SImode);
1957 operands[6] = gen_reg_rtx (SImode);
1959 if (BYTES_BIG_ENDIAN)
1961 operands[4] = operands[2];
1962 operands[5] = operands[3];
1966 operands[4] = operands[3];
1967 operands[5] = operands[2];
1971 (define_insn "*extendhisi_insn"
1972 [(set (match_operand:SI 0 "s_register_operand" "=r")
1973 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
1976 [(set_attr "type" "load")])
1978 (define_expand "extendqihi2"
1980 (ashift:SI (match_operand:QI 1 "general_operand" "")
1982 (set (match_operand:HI 0 "s_register_operand" "")
1983 (ashiftrt:SI (match_dup 2)
1988 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
1990 emit_insn (gen_rtx (SET, VOIDmode, operands[0],
1991 gen_rtx (SIGN_EXTEND, HImode, operands[1])));
1994 if (! s_register_operand (operands[1], QImode))
1995 operands[1] = copy_to_mode_reg (QImode, operands[1]);
1996 operands[0] = gen_lowpart (SImode, operands[0]);
1997 operands[1] = gen_lowpart (SImode, operands[1]);
1998 operands[2] = gen_reg_rtx (SImode);
2001 (define_insn "*extendqihi_insn"
2002 [(set (match_operand:HI 0 "s_register_operand" "=r")
2003 (sign_extend:HI (match_operand:QI 1 "memory_operand" "o<>")))]
2006 [(set_attr "type" "load")])
2008 (define_expand "extendqisi2"
2010 (ashift:SI (match_operand:QI 1 "s_register_operand" "")
2012 (set (match_operand:SI 0 "s_register_operand" "")
2013 (ashiftrt:SI (match_dup 2)
2018 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2020 emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2021 gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2024 if (! s_register_operand (operands[1], QImode))
2025 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2026 operands[1] = gen_lowpart (SImode, operands[1]);
2027 operands[2] = gen_reg_rtx (SImode);
2030 (define_insn "*extendqisi_insn"
2031 [(set (match_operand:SI 0 "s_register_operand" "=r")
2032 (sign_extend:SI (match_operand:QI 1 "memory_operand" "o<>")))]
2035 [(set_attr "type" "load")])
2037 (define_insn "extendsfdf2"
2038 [(set (match_operand:DF 0 "s_register_operand" "=f")
2039 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2042 [(set_attr "type" "ffarith")])
2044 (define_insn "extendsfxf2"
2045 [(set (match_operand:XF 0 "s_register_operand" "=f")
2046 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2047 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2049 [(set_attr "type" "ffarith")])
2051 (define_insn "extenddfxf2"
2052 [(set (match_operand:XF 0 "s_register_operand" "=f")
2053 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2054 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2056 [(set_attr "type" "ffarith")])
2059 ;; Move insns (including loads and stores)
2061 ;; XXX Just some ideas about movti.
2062 ;; I don't think these are a good idea on the arm, there just aren't enough
2064 ;;(define_expand "loadti"
2065 ;; [(set (match_operand:TI 0 "s_register_operand" "")
2066 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
2069 ;;(define_expand "storeti"
2070 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2071 ;; (match_operand:TI 1 "s_register_operand" ""))]
2074 ;;(define_expand "movti"
2075 ;; [(set (match_operand:TI 0 "general_operand" "")
2076 ;; (match_operand:TI 1 "general_operand" ""))]
2082 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2083 ;; operands[1] = copy_to_reg (operands[1]);
2084 ;; if (GET_CODE (operands[0]) == MEM)
2085 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2086 ;; else if (GET_CODE (operands[1]) == MEM)
2087 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2091 ;; emit_insn (insn);
2095 ;; Recognise garbage generated above.
2098 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2099 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2103 ;; register mem = (which_alternative < 3);
2104 ;; register char *template;
2106 ;; operands[mem] = XEXP (operands[mem], 0);
2107 ;; switch (which_alternative)
2109 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2110 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
2111 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
2112 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
2113 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
2114 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
2116 ;; output_asm_insn (template, operands);
2121 (define_insn "movdi"
2122 [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2123 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2126 return (output_move_double (operands));
2128 [(set_attr "length" "8,8,8")
2129 (set_attr "type" "*,load,store2")])
2131 (define_expand "movsi"
2132 [(set (match_operand:SI 0 "general_operand" "")
2133 (match_operand:SI 1 "general_operand" ""))]
2136 /* Everything except mem = const or mem = mem can be done easily */
2137 if (GET_CODE (operands[0]) == MEM)
2138 operands[1] = force_reg (SImode, operands[1]);
2139 if (GET_CODE (operands[1]) == CONST_INT
2140 && !(const_ok_for_arm (INTVAL (operands[1]))
2141 || const_ok_for_arm (~INTVAL (operands[1]))))
2143 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2145 (reload_in_progress || reload_completed ? 0
2146 : preserve_subexpressions_p ()));
2151 (define_insn "*movsi_insn"
2152 [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2153 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
2154 "register_operand (operands[0], SImode)
2155 || register_operand (operands[1], SImode)"
2161 [(set_attr "type" "*,*,load,store1")])
2164 [(set (match_operand:SI 0 "s_register_operand" "")
2165 (match_operand:SI 1 "const_int_operand" ""))]
2166 "! (const_ok_for_arm (INTVAL (operands[1]))
2167 || const_ok_for_arm (~INTVAL (operands[1])))"
2168 [(clobber (const_int 0))]
2170 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2175 (define_expand "movaddr"
2176 [(set (match_operand:SI 0 "s_register_operand" "")
2177 (match_operand:DI 1 "address_operand" ""))]
2181 (define_insn "*movaddr_insn"
2182 [(set (match_operand:SI 0 "s_register_operand" "=r")
2183 (match_operand:DI 1 "address_operand" "p"))]
2185 && (GET_CODE (operands[1]) == LABEL_REF
2186 || (GET_CODE (operands[1]) == CONST
2187 && GET_CODE (XEXP (operands[1], 0)) == PLUS
2188 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2189 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2192 ;; If copying one reg to another we can set the condition codes according to
2193 ;; its value. Such a move is common after a return from subroutine and the
2194 ;; result is being tested against zero.
2196 (define_insn "*movsi_compare0"
2197 [(set (reg:CC 24) (compare (match_operand:SI 1 "s_register_operand" "0,r")
2199 (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2203 sub%?s\\t%0, %1, #0"
2204 [(set_attr "conds" "set")])
2206 ;; Subroutine to store a half word from a register into memory.
2207 ;; Operand 0 is the source register (HImode)
2208 ;; Operand 1 is the destination address in a register (SImode)
2210 ;; In both this routine and the next, we must be careful not to spill
2211 ;; a memory address of reg+large_const into a separate PLUS insn, since this
2212 ;; can generate unrecognizable rtl.
2214 (define_expand "storehi"
2215 [;; store the low byte
2216 (set (mem:QI (match_operand:SI 1 "" "")) (match_dup 3))
2217 ;; extract the high byte
2219 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2220 ;; store the high byte
2221 (set (mem:QI (match_dup 4))
2222 (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
2226 enum rtx_code code = GET_CODE (operands[1]);
2228 if ((code == PLUS || code == MINUS)
2229 && (GET_CODE (XEXP (operands[1], 1)) == REG
2230 || GET_CODE (XEXP (operands[1], 0)) != REG))
2231 operands[1] = force_reg (SImode, operands[1]);
2232 operands[4] = plus_constant (operands[1], 1);
2233 operands[3] = gen_lowpart (QImode, operands[0]);
2234 operands[0] = gen_lowpart (SImode, operands[0]);
2235 operands[2] = gen_reg_rtx (SImode);
2239 (define_expand "storehi_bigend"
2240 [(set (mem:QI (match_dup 4)) (match_dup 3))
2242 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2243 (set (mem:QI (match_operand 1 "" ""))
2244 (subreg:QI (match_dup 2) 0))]
2248 enum rtx_code code = GET_CODE (operands[1]);
2249 if ((code == PLUS || code == MINUS)
2250 && (GET_CODE (XEXP (operands[1], 1)) == REG
2251 || GET_CODE (XEXP (operands[1], 0)) != REG))
2252 operands[1] = force_reg (SImode, operands[1]);
2254 operands[4] = plus_constant (operands[1], 1);
2255 operands[3] = gen_lowpart (QImode, operands[0]);
2256 operands[0] = gen_lowpart (SImode, operands[0]);
2257 operands[2] = gen_reg_rtx (SImode);
2261 ;; Subroutine to store a half word integer constant into memory.
2262 (define_expand "storeinthi"
2263 [(set (mem:QI (match_operand:SI 0 "" ""))
2264 (subreg:QI (match_operand 1 "" "") 0))
2265 (set (mem:QI (match_dup 3)) (subreg:QI (match_dup 2) 0))]
2269 HOST_WIDE_INT value = INTVAL (operands[1]);
2270 enum rtx_code code = GET_CODE (operands[0]);
2272 if ((code == PLUS || code == MINUS)
2273 && (GET_CODE (XEXP (operands[0], 1)) == REG
2274 || GET_CODE (XEXP (operands[0], 0)) != REG))
2275 operands[0] = force_reg (SImode, operands[0]);
2277 operands[1] = gen_reg_rtx (SImode);
2278 if (BYTES_BIG_ENDIAN)
2280 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2281 if ((value & 255) == ((value >> 8) & 255))
2282 operands[2] = operands[1];
2285 operands[2] = gen_reg_rtx (SImode);
2286 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2291 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2292 if ((value & 255) == ((value >> 8) & 255))
2293 operands[2] = operands[1];
2296 operands[2] = gen_reg_rtx (SImode);
2297 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2301 operands[3] = plus_constant (operands[0], 1);
2305 (define_expand "storehi_single_op"
2306 [(set (match_operand:HI 0 "memory_operand" "")
2307 (match_operand:HI 1 "general_operand" ""))]
2310 if (! s_register_operand (operands[1], HImode))
2311 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2314 (define_expand "movhi"
2315 [(set (match_operand:HI 0 "general_operand" "")
2316 (match_operand:HI 1 "general_operand" ""))]
2322 if (! (reload_in_progress || reload_completed))
2324 if (GET_CODE (operands[0]) == MEM)
2328 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2331 if (GET_CODE (operands[1]) == CONST_INT)
2332 emit_insn (gen_storeinthi (XEXP (operands[0], 0), operands[1]));
2335 if (GET_CODE (operands[1]) == MEM)
2336 operands[1] = force_reg (HImode, operands[1]);
2337 if (BYTES_BIG_ENDIAN)
2338 emit_insn (gen_storehi_bigend (operands[1],
2339 XEXP (operands[0], 0)));
2341 emit_insn (gen_storehi (operands[1], XEXP (operands[0], 0)));
2345 /* Sign extend a constant, and keep it in an SImode reg. */
2346 else if (GET_CODE (operands[1]) == CONST_INT)
2348 rtx reg = gen_reg_rtx (SImode);
2349 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2351 /* If the constant is already valid, leave it alone. */
2352 if (! const_ok_for_arm (val))
2354 /* If setting all the top bits will make the constant
2355 loadable in a single instruction, then set them.
2356 Otherwise, sign extend the number. */
2358 if (const_ok_for_arm (~ (val | ~0xffff)))
2360 else if (val & 0x8000)
2364 emit_insn (gen_movsi (reg, GEN_INT (val)));
2365 operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
2367 else if (! arm_arch4)
2369 if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2371 rtx reg = gen_reg_rtx (SImode);
2372 emit_insn (gen_movhi_bytes (reg, operands[1]));
2373 operands[1] = gen_lowpart (HImode, reg);
2375 else if (BYTES_BIG_ENDIAN && GET_CODE (operands[1]) == MEM)
2377 emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2385 (define_expand "movhi_bytes"
2386 [(set (match_dup 2) (zero_extend:SI (mem:QI (match_operand:HI 1 "" ""))))
2388 (zero_extend:SI (mem:QI (plus:SI (match_dup 1) (const_int 1)))))
2389 (set (match_operand:SI 0 "" "")
2390 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
2393 operands[0] = gen_lowpart (SImode, operands[0]);
2394 operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2395 operands[2] = gen_reg_rtx (SImode);
2396 operands[3] = gen_reg_rtx (SImode);
2398 if (BYTES_BIG_ENDIAN)
2400 operands[4] = operands[2];
2401 operands[5] = operands[3];
2405 operands[4] = operands[3];
2406 operands[5] = operands[2];
2410 (define_expand "movhi_bigend"
2412 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
2415 (ashiftrt:SI (match_dup 2) (const_int 16)))
2416 (set (match_operand:HI 0 "s_register_operand" "")
2417 (subreg:HI (match_dup 3) 0))]
2420 operands[2] = gen_reg_rtx (SImode);
2421 operands[3] = gen_reg_rtx (SImode);
2424 ;; Pattern to recognise insn generated default case above
2426 (define_insn "*movhi_insn_arch4"
2427 [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
2428 (match_operand:HI 1 "general_operand" "rI,K,m,r"))]
2430 && (GET_CODE (operands[1]) != CONST_INT
2431 || const_ok_for_arm (INTVAL (operands[1]))
2432 || const_ok_for_arm (~INTVAL (operands[1])))"
2434 mov%?\\t%0, %1\\t%@ movhi
2435 mvn%?\\t%0, #%B1\\t%@ movhi
2436 ldr%?h\\t%0, %1\\t%@ movhi
2437 str%?h\\t%1, %0\\t%@ movhi"
2438 [(set_attr "type" "*,*,load,store1")])
2440 (define_insn "*movhi_insn_littleend"
2441 [(set (match_operand:HI 0 "general_operand" "=r,r,r")
2442 (match_operand:HI 1 "general_operand" "rI,K,m"))]
2444 && ! BYTES_BIG_ENDIAN
2445 && ! TARGET_SHORT_BY_BYTES
2446 && (GET_CODE (operands[1]) != CONST_INT
2447 || const_ok_for_arm (INTVAL (operands[1]))
2448 || const_ok_for_arm (~INTVAL (operands[1])))"
2450 mov%?\\t%0, %1\\t%@ movhi
2451 mvn%?\\t%0, #%B1\\t%@ movhi
2452 ldr%?\\t%0, %1\\t%@ movhi"
2453 [(set_attr "type" "*,*,load")])
2455 (define_insn "*movhi_insn_bigend"
2456 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
2457 (match_operand:HI 1 "general_operand" "rI,K,m"))]
2460 && ! TARGET_SHORT_BY_BYTES
2461 && (GET_CODE (operands[1]) != CONST_INT
2462 || const_ok_for_arm (INTVAL (operands[1]))
2463 || const_ok_for_arm (~INTVAL (operands[1])))"
2465 mov%?\\t%0, %1\\t%@ movhi
2466 mvn%?\\t%0, #%B1\\t%@ movhi
2467 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
2468 [(set_attr "type" "*,*,load")
2469 (set_attr "length" "4,4,8")])
2471 (define_insn "*loadhi_si_bigend"
2472 [(set (match_operand:SI 0 "s_register_operand" "=r")
2473 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
2476 && ! TARGET_SHORT_BY_BYTES"
2477 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
2478 [(set_attr "type" "load")])
2480 (define_insn "*movhi_bytes"
2481 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
2482 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
2483 "TARGET_SHORT_BY_BYTES"
2485 mov%?\\t%0, %1\\t%@ movhi
2486 mvn%?\\t%0, #%B1\\t%@ movhi")
2489 (define_expand "reload_outhi"
2490 [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
2491 (match_operand:HI 1 "s_register_operand" "r")
2492 (match_operand:SI 2 "s_register_operand" "=&r")])]
2495 arm_reload_out_hi (operands);
2499 (define_expand "reload_inhi"
2500 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
2501 (match_operand:HI 1 "reload_memory_operand" "o")
2502 (match_operand:SI 2 "s_register_operand" "=&r")])]
2503 "TARGET_SHORT_BY_BYTES"
2505 arm_reload_in_hi (operands);
2509 (define_expand "movqi"
2510 [(set (match_operand:QI 0 "general_operand" "")
2511 (match_operand:QI 1 "general_operand" ""))]
2514 /* Everything except mem = const or mem = mem can be done easily */
2516 if (!(reload_in_progress || reload_completed))
2518 if (GET_CODE (operands[1]) == CONST_INT)
2520 rtx reg = gen_reg_rtx (SImode);
2522 emit_insn (gen_movsi (reg, operands[1]));
2523 operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
2525 if (GET_CODE (operands[0]) == MEM)
2526 operands[1] = force_reg (QImode, operands[1]);
2531 (define_insn "*movqi_insn"
2532 [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
2533 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
2534 "register_operand (operands[0], QImode)
2535 || register_operand (operands[1], QImode)"
2541 [(set_attr "type" "*,*,load,store1")])
2543 (define_expand "movsf"
2544 [(set (match_operand:SF 0 "general_operand" "")
2545 (match_operand:SF 1 "general_operand" ""))]
2548 if (GET_CODE (operands[0]) == MEM)
2549 operands[1] = force_reg (SFmode, operands[1]);
2552 (define_insn "*movsf_hard_insn"
2553 [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
2554 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
2556 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
2562 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
2563 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
2565 ldr%?\\t%0, %1\\t%@ float
2566 str%?\\t%1, %0\\t%@ float"
2567 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
2569 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
2571 ;; Exactly the same as above, except that all `f' cases are deleted.
2572 ;; This is necessary to prevent reload from ever trying to use a `f' reg
2573 ;; when -msoft-float.
2575 (define_insn "*movsf_soft_insn"
2576 [(set (match_operand:SF 0 "general_operand" "=r,r,m")
2577 (match_operand:SF 1 "general_operand" "r,mE,r"))]
2579 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
2582 ldr%?\\t%0, %1\\t%@ float
2583 str%?\\t%1, %0\\t%@ float"
2584 [(set_attr "length" "4,4,4")
2585 (set_attr "type" "*,load,store1")])
2587 (define_expand "movdf"
2588 [(set (match_operand:DF 0 "general_operand" "")
2589 (match_operand:DF 1 "general_operand" ""))]
2592 if (GET_CODE (operands[0]) == MEM)
2593 operands[1] = force_reg (DFmode, operands[1]);
2596 ;; Reloading a df mode value stored in integer regs to memory can require a
2598 (define_expand "reload_outdf"
2599 [(match_operand:DF 0 "reload_memory_operand" "=o")
2600 (match_operand:DF 1 "s_register_operand" "r")
2601 (match_operand:SI 2 "s_register_operand" "=&r")]
2605 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
2608 operands[2] = XEXP (operands[0], 0);
2609 else if (code == POST_INC || code == PRE_DEC)
2611 operands[0] = gen_rtx (SUBREG, DImode, operands[0], 0);
2612 operands[1] = gen_rtx (SUBREG, DImode, operands[1], 0);
2613 emit_insn (gen_movdi (operands[0], operands[1]));
2616 else if (code == PRE_INC)
2618 rtx reg = XEXP (XEXP (operands[0], 0), 0);
2619 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
2622 else if (code == POST_DEC)
2623 operands[2] = XEXP (XEXP (operands[0], 0), 0);
2625 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
2626 XEXP (XEXP (operands[0], 0), 1)));
2628 emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, DFmode, operands[2]),
2631 if (code == POST_DEC)
2632 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
2638 (define_insn "*movdf_hard_insn"
2639 [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
2640 (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
2642 && (GET_CODE (operands[0]) != MEM
2643 || register_operand (operands[1], DFmode))"
2648 switch (which_alternative)
2650 case 0: return \"ldm%?ia\\t%m1, {%0, %R0}\\t%@ double\";
2651 case 1: return \"stm%?ia\\t%m0, {%1, %R1}\\t%@ double\";
2652 case 2: case 3: case 4: return output_move_double (operands);
2653 case 5: return \"mvf%?d\\t%0, %1\";
2654 case 6: return \"mnf%?d\\t%0, #%N1\";
2655 case 7: return \"ldf%?d\\t%0, %1\";
2656 case 8: return \"stf%?d\\t%1, %0\";
2657 case 9: return output_mov_double_fpu_from_arm (operands);
2658 case 10: return output_mov_double_arm_from_fpu (operands);
2662 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
2664 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
2666 ;; Software floating point version. This is essentially the same as movdi.
2667 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
2670 (define_insn "*movdf_soft_insn"
2671 [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
2672 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
2674 "* return output_move_double (operands);"
2675 [(set_attr "length" "8,8,8")
2676 (set_attr "type" "*,load,store2")])
2678 (define_expand "movxf"
2679 [(set (match_operand:XF 0 "general_operand" "")
2680 (match_operand:XF 1 "general_operand" ""))]
2681 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2684 ;; Even when the XFmode patterns aren't enabled, we enable this after
2685 ;; reloading so that we can push floating point registers in the prologue.
2687 (define_insn "*movxf_hard_insn"
2688 [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
2689 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
2690 "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
2692 switch (which_alternative)
2694 case 0: return \"mvf%?e\\t%0, %1\";
2695 case 1: return \"mnf%?e\\t%0, #%N1\";
2696 case 2: return \"ldf%?e\\t%0, %1\";
2697 case 3: return \"stf%?e\\t%1, %0\";
2698 case 4: return output_mov_long_double_fpu_from_arm (operands);
2699 case 5: return output_mov_long_double_arm_from_fpu (operands);
2700 case 6: return output_mov_long_double_arm_from_arm (operands);
2703 [(set_attr "length" "4,4,4,4,8,8,12")
2704 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
2707 ;; load- and store-multiple insns
2708 ;; The arm can load/store any set of registers, provided that they are in
2709 ;; ascending order; but that is beyond GCC so stick with what it knows.
2711 (define_expand "load_multiple"
2712 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2713 (match_operand:SI 1 "" ""))
2714 (use (match_operand:SI 2 "" ""))])]
2717 /* Support only fixed point registers */
2718 if (GET_CODE (operands[2]) != CONST_INT
2719 || INTVAL (operands[2]) > 14
2720 || INTVAL (operands[2]) < 2
2721 || GET_CODE (operands[1]) != MEM
2722 || GET_CODE (operands[0]) != REG
2723 || REGNO (operands[0]) > 14
2724 || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
2728 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
2729 force_reg (SImode, XEXP (operands[1], 0)),
2733 ;; Load multiple with write-back
2735 (define_insn "*ldmsi_postinc"
2736 [(match_parallel 0 "load_multiple_operation"
2737 [(set (match_operand:SI 1 "s_register_operand" "+r")
2738 (plus:SI (match_dup 1)
2739 (match_operand:SI 2 "immediate_operand" "n")))
2740 (set (match_operand:SI 3 "s_register_operand" "=r")
2741 (mem:SI (match_dup 1)))])]
2742 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
2746 int count = XVECLEN (operands[0], 0);
2748 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2749 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
2750 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
2752 output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
2756 [(set_attr "type" "load")])
2758 ;; Ordinary load multiple
2760 (define_insn "*ldmsi"
2761 [(match_parallel 0 "load_multiple_operation"
2762 [(set (match_operand:SI 1 "s_register_operand" "=r")
2763 (match_operand:SI 2 "indirect_operand" "Q"))])]
2768 int count = XVECLEN (operands[0], 0);
2770 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2771 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
2772 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
2774 output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
2778 [(set_attr "type" "load")])
2780 (define_expand "store_multiple"
2781 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2782 (match_operand:SI 1 "" ""))
2783 (use (match_operand:SI 2 "" ""))])]
2786 /* Support only fixed point registers */
2787 if (GET_CODE (operands[2]) != CONST_INT
2788 || INTVAL (operands[2]) > 14
2789 || INTVAL (operands[2]) < 2
2790 || GET_CODE (operands[1]) != REG
2791 || GET_CODE (operands[0]) != MEM
2792 || REGNO (operands[1]) > 14
2793 || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
2797 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
2798 force_reg (SImode, XEXP (operands[0], 0)),
2802 ;; Store multiple with write-back
2804 (define_insn "*stmsi_postinc"
2805 [(match_parallel 0 "store_multiple_operation"
2806 [(set (match_operand:SI 1 "s_register_operand" "+r")
2807 (plus:SI (match_dup 1)
2808 (match_operand:SI 2 "immediate_operand" "n")))
2809 (set (mem:SI (match_dup 1))
2810 (match_operand:SI 3 "s_register_operand" "r"))])]
2811 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
2815 int count = XVECLEN (operands[0], 0);
2817 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2818 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
2819 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
2821 output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
2826 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
2827 (const_string "store2")
2828 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
2829 (const_string "store3")]
2830 (const_string "store4")))])
2832 ;; Ordinary store multiple
2834 (define_insn "*stmsi"
2835 [(match_parallel 0 "store_multiple_operation"
2836 [(set (match_operand:SI 2 "indirect_operand" "=Q")
2837 (match_operand:SI 1 "s_register_operand" "r"))])]
2842 int count = XVECLEN (operands[0], 0);
2844 ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
2845 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
2846 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
2848 output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
2853 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
2854 (const_string "store2")
2855 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
2856 (const_string "store3")]
2857 (const_string "store4")))])
2859 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
2860 ;; We could let this apply for blocks of less than this, but it clobbers so
2861 ;; many registers that there is then probably a better way.
2863 (define_expand "movstrqi"
2864 [(match_operand:BLK 0 "general_operand" "")
2865 (match_operand:BLK 1 "general_operand" "")
2866 (match_operand:SI 2 "const_int_operand" "")
2867 (match_operand:SI 3 "const_int_operand" "")]
2870 if (arm_gen_movstrqi (operands))
2876 ;; Comparison and test insns
2878 (define_expand "cmpsi"
2880 (compare:CC (match_operand:SI 0 "s_register_operand" "")
2881 (match_operand:SI 1 "arm_add_operand" "")))]
2885 arm_compare_op0 = operands[0];
2886 arm_compare_op1 = operands[1];
2892 (define_expand "cmpsf"
2894 (compare:CC (match_operand:SF 0 "s_register_operand" "")
2895 (match_operand:SF 1 "fpu_rhs_operand" "")))]
2899 arm_compare_op0 = operands[0];
2900 arm_compare_op1 = operands[1];
2906 (define_expand "cmpdf"
2908 (compare:CC (match_operand:DF 0 "s_register_operand" "")
2909 (match_operand:DF 1 "fpu_rhs_operand" "")))]
2913 arm_compare_op0 = operands[0];
2914 arm_compare_op1 = operands[1];
2920 (define_expand "cmpxf"
2922 (compare:CC (match_operand:XF 0 "s_register_operand" "")
2923 (match_operand:XF 1 "fpu_rhs_operand" "")))]
2924 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2927 arm_compare_op0 = operands[0];
2928 arm_compare_op1 = operands[1];
2934 (define_insn "*cmpsi_insn"
2935 [(set (match_operand 0 "cc_register" "")
2936 (compare (match_operand:SI 1 "s_register_operand" "r,r")
2937 (match_operand:SI 2 "arm_add_operand" "rI,L")))]
2942 [(set_attr "conds" "set")])
2944 (define_insn "*cmpsi_negsi"
2945 [(set (match_operand 0 "cc_register" "")
2946 (compare (match_operand:SI 1 "s_register_operand" "r")
2947 (neg:SI (match_operand:SI 2 "s_register_operand" "r"))))]
2950 [(set_attr "conds" "set")])
2952 (define_insn "*cmpsi_shiftsi"
2953 [(set (match_operand 0 "cc_register" "")
2954 (compare (match_operand:SI 1 "s_register_operand" "r")
2955 (match_operator:SI 2 "shift_operator"
2956 [(match_operand:SI 3 "s_register_operand" "r")
2957 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
2960 [(set_attr "conds" "set")])
2962 (define_insn "*cmpsi_neg_shiftsi"
2963 [(set (match_operand 0 "cc_register" "")
2964 (compare (match_operand:SI 1 "s_register_operand" "r")
2965 (neg:SI (match_operator:SI 2 "shift_operator"
2966 [(match_operand:SI 3 "s_register_operand" "r")
2967 (match_operand:SI 4 "arm_rhs_operand" "rM")]))))]
2970 [(set_attr "conds" "set")])
2972 (define_insn "*cmpsf_insn"
2974 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
2975 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
2980 [(set_attr "conds" "set")
2981 (set_attr "type" "f_2_r")])
2983 (define_insn "*cmpdf_insn"
2985 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
2986 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
2991 [(set_attr "conds" "set")
2992 (set_attr "type" "f_2_r")])
2994 (define_insn "*cmpesfdf_df"
2996 (compare:CCFP (float_extend:DF
2997 (match_operand:SF 0 "s_register_operand" "f,f"))
2998 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3003 [(set_attr "conds" "set")
3004 (set_attr "type" "f_2_r")])
3006 (define_insn "*cmpdf_esfdf"
3008 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3010 (match_operand:SF 1 "s_register_operand" "f"))))]
3013 [(set_attr "conds" "set")
3014 (set_attr "type" "f_2_r")])
3016 (define_insn "*cmpxf_insn"
3018 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3019 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3020 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3024 [(set_attr "conds" "set")
3025 (set_attr "type" "f_2_r")])
3027 (define_insn "*cmpsf_trap"
3028 [(set (reg:CCFPE 24)
3029 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3030 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3035 [(set_attr "conds" "set")
3036 (set_attr "type" "f_2_r")])
3038 (define_insn "*cmpdf_trap"
3039 [(set (reg:CCFPE 24)
3040 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3041 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3046 [(set_attr "conds" "set")
3047 (set_attr "type" "f_2_r")])
3049 (define_insn "*cmp_esfdf_df_trap"
3050 [(set (reg:CCFPE 24)
3051 (compare:CCFPE (float_extend:DF
3052 (match_operand:SF 0 "s_register_operand" "f,f"))
3053 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3058 [(set_attr "conds" "set")
3059 (set_attr "type" "f_2_r")])
3061 (define_insn "*cmp_df_esfdf_trap"
3062 [(set (reg:CCFPE 24)
3063 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3065 (match_operand:SF 1 "s_register_operand" "f"))))]
3068 [(set_attr "conds" "set")
3069 (set_attr "type" "f_2_r")])
3071 (define_insn "*cmpxf_trap"
3072 [(set (reg:CCFPE 24)
3073 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3074 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3075 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3079 [(set_attr "conds" "set")
3080 (set_attr "type" "f_2_r")])
3082 ; This insn allows redundant compares to be removed by cse, nothing should
3083 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3084 ; is deleted later on. The match_dup will match the mode here, so that
3085 ; mode changes of the condition codes aren't lost by this even though we don't
3086 ; specify what they are.
3088 (define_insn "*delted_compare"
3089 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3091 "\\t%@ deleted compare"
3092 [(set_attr "conds" "set")
3093 (set_attr "length" "0")])
3096 ;; Conditional branch insns
3098 (define_expand "beq"
3100 (if_then_else (eq (match_dup 1) (const_int 0))
3101 (label_ref (match_operand 0 "" ""))
3106 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3111 (define_expand "bne"
3113 (if_then_else (ne (match_dup 1) (const_int 0))
3114 (label_ref (match_operand 0 "" ""))
3119 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3124 (define_expand "bgt"
3126 (if_then_else (gt (match_dup 1) (const_int 0))
3127 (label_ref (match_operand 0 "" ""))
3132 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3137 (define_expand "ble"
3139 (if_then_else (le (match_dup 1) (const_int 0))
3140 (label_ref (match_operand 0 "" ""))
3145 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3150 (define_expand "bge"
3152 (if_then_else (ge (match_dup 1) (const_int 0))
3153 (label_ref (match_operand 0 "" ""))
3158 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3163 (define_expand "blt"
3165 (if_then_else (lt (match_dup 1) (const_int 0))
3166 (label_ref (match_operand 0 "" ""))
3171 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3176 (define_expand "bgtu"
3178 (if_then_else (gtu (match_dup 1) (const_int 0))
3179 (label_ref (match_operand 0 "" ""))
3184 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3189 (define_expand "bleu"
3191 (if_then_else (leu (match_dup 1) (const_int 0))
3192 (label_ref (match_operand 0 "" ""))
3197 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3202 (define_expand "bgeu"
3204 (if_then_else (geu (match_dup 1) (const_int 0))
3205 (label_ref (match_operand 0 "" ""))
3210 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3215 (define_expand "bltu"
3217 (if_then_else (ltu (match_dup 1) (const_int 0))
3218 (label_ref (match_operand 0 "" ""))
3223 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3228 ;; patterns to match conditional branch insns
3230 (define_insn "*condbranch"
3232 (if_then_else (match_operator 1 "comparison_operator"
3233 [(reg 24) (const_int 0)])
3234 (label_ref (match_operand 0 "" ""))
3239 extern int arm_ccfsm_state;
3241 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3243 arm_ccfsm_state += 2;
3246 return \"b%d1\\t%l0\";
3248 [(set_attr "conds" "use")])
3250 (define_insn "*condbranch_reversed"
3252 (if_then_else (match_operator 1 "comparison_operator"
3253 [(reg 24) (const_int 0)])
3255 (label_ref (match_operand 0 "" ""))))]
3256 "REVERSIBLE_CC_MODE (GET_MODE (XEXP (operands[1], 0)))"
3259 extern int arm_ccfsm_state;
3261 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3263 arm_ccfsm_state += 2;
3266 return \"b%D1\\t%l0\";
3268 [(set_attr "conds" "use")])
3273 (define_expand "seq"
3274 [(set (match_operand:SI 0 "s_register_operand" "=r")
3275 (eq:SI (match_dup 1) (const_int 0)))]
3279 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3284 (define_expand "sne"
3285 [(set (match_operand:SI 0 "s_register_operand" "=r")
3286 (ne:SI (match_dup 1) (const_int 0)))]
3290 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3295 (define_expand "sgt"
3296 [(set (match_operand:SI 0 "s_register_operand" "=r")
3297 (gt:SI (match_dup 1) (const_int 0)))]
3301 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3306 (define_expand "sle"
3307 [(set (match_operand:SI 0 "s_register_operand" "=r")
3308 (le:SI (match_dup 1) (const_int 0)))]
3312 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3317 (define_expand "sge"
3318 [(set (match_operand:SI 0 "s_register_operand" "=r")
3319 (ge:SI (match_dup 1) (const_int 0)))]
3323 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3328 (define_expand "slt"
3329 [(set (match_operand:SI 0 "s_register_operand" "=r")
3330 (lt:SI (match_dup 1) (const_int 0)))]
3334 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3339 (define_expand "sgtu"
3340 [(set (match_operand:SI 0 "s_register_operand" "=r")
3341 (gtu:SI (match_dup 1) (const_int 0)))]
3345 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3350 (define_expand "sleu"
3351 [(set (match_operand:SI 0 "s_register_operand" "=r")
3352 (leu:SI (match_dup 1) (const_int 0)))]
3356 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3361 (define_expand "sgeu"
3362 [(set (match_operand:SI 0 "s_register_operand" "=r")
3363 (geu:SI (match_dup 1) (const_int 0)))]
3367 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3372 (define_expand "sltu"
3373 [(set (match_operand:SI 0 "s_register_operand" "=r")
3374 (ltu:SI (match_dup 1) (const_int 0)))]
3378 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3383 (define_insn "*mov_scc"
3384 [(set (match_operand:SI 0 "s_register_operand" "=r")
3385 (match_operator:SI 1 "comparison_operator" [(reg 24) (const_int 0)]))]
3387 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
3388 [(set_attr "conds" "use")
3389 (set_attr "length" "8")])
3391 (define_insn "*mov_negscc"
3392 [(set (match_operand:SI 0 "s_register_operand" "=r")
3393 (neg:SI (match_operator:SI 1 "comparison_operator"
3394 [(reg 24) (const_int 0)])))]
3396 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
3397 [(set_attr "conds" "use")
3398 (set_attr "length" "8")])
3400 (define_insn "*mov_notscc"
3401 [(set (match_operand:SI 0 "s_register_operand" "=r")
3402 (not:SI (match_operator:SI 1 "comparison_operator"
3403 [(reg 24) (const_int 0)])))]
3405 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
3406 [(set_attr "conds" "use")
3407 (set_attr "length" "8")])
3410 ;; Conditional move insns
3412 (define_expand "movsicc"
3413 [(set (match_operand:SI 0 "register_operand" "")
3414 (if_then_else (match_operand 1 "comparison_operator" "")
3415 (match_operand:SI 2 "arm_not_operand" "")
3416 (match_operand:SI 3 "register_operand" "")))]
3420 enum rtx_code code = GET_CODE (operands[1]);
3421 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3424 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3427 (define_expand "movsfcc"
3428 [(set (match_operand:SF 0 "register_operand" "")
3429 (if_then_else (match_operand 1 "comparison_operator" "")
3430 (match_operand:SF 2 "nonmemory_operand" "")
3431 (match_operand:SF 3 "register_operand" "")))]
3435 enum rtx_code code = GET_CODE (operands[1]);
3436 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3439 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3442 (define_expand "movdfcc"
3443 [(set (match_operand:DF 0 "register_operand" "")
3444 (if_then_else (match_operand 1 "comparison_operator" "")
3445 (match_operand:DF 2 "nonmemory_operand" "")
3446 (match_operand:DF 3 "register_operand" "")))]
3450 enum rtx_code code = GET_CODE (operands[1]);
3451 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
3454 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
3457 (define_insn "*movsicc_insn"
3458 [(set (match_operand:SI 0 "register_operand" "=r,r")
3459 (if_then_else (match_operator 1 "comparison_operator"
3460 [(reg 24) (const_int 0)])
3461 (match_operand:SI 2 "arm_not_operand" "rI,K")
3462 (match_operand:SI 3 "register_operand" "0,0")))]
3467 [(set_attr "type" "*,*")
3468 (set_attr "conds" "use,use")])
3470 (define_insn "*movsfcc_hard_insn"
3471 [(set (match_operand:SF 0 "register_operand" "=f")
3472 (if_then_else (match_operator 1 "comparison_operator"
3473 [(reg 24) (const_int 0)])
3474 (match_operand:SF 2 "register_operand" "f")
3475 (match_operand:SF 3 "register_operand" "0")))]
3478 [(set_attr "type" "ffarith")
3479 (set_attr "conds" "use")])
3481 (define_insn "*movsfcc_soft_insn"
3482 [(set (match_operand:SF 0 "register_operand" "=r")
3483 (if_then_else (match_operator 1 "comparison_operator"
3484 [(reg 24) (const_int 0)])
3485 (match_operand:SF 2 "register_operand" "r")
3486 (match_operand:SF 3 "register_operand" "0")))]
3489 [(set_attr "type" "*")
3490 (set_attr "conds" "use")])
3492 (define_insn "*movdfcc_insn"
3493 [(set (match_operand:DF 0 "register_operand" "=f")
3494 (if_then_else (match_operator 1 "comparison_operator"
3495 [(reg 24) (const_int 0)])
3496 (match_operand:DF 2 "register_operand" "f")
3497 (match_operand:DF 3 "register_operand" "0")))]
3500 [(set_attr "type" "ffarith")
3501 (set_attr "conds" "use")])
3503 ;; Jump and linkage insns
3507 (label_ref (match_operand 0 "" "")))]
3511 extern int arm_ccfsm_state;
3513 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3515 arm_ccfsm_state += 2;
3518 return \"b%?\\t%l0\";
3521 (define_expand "call"
3522 [(parallel [(call (match_operand 0 "memory_operand" "")
3523 (match_operand 1 "general_operand" ""))
3524 (clobber (reg:SI 14))])]
3528 (define_insn "*call_reg"
3529 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
3530 (match_operand 1 "" "g"))
3531 (clobber (reg:SI 14))]
3534 return output_call (operands);
3536 ;; length is worst case, normally it is only two
3537 [(set_attr "length" "12")
3538 (set_attr "type" "call")])
3540 (define_insn "*call_mem"
3541 [(call (mem:SI (match_operand 0 "memory_operand" "m"))
3542 (match_operand 1 "general_operand" "g"))
3543 (clobber (reg:SI 14))]
3546 return output_call_mem (operands);
3548 [(set_attr "length" "12")
3549 (set_attr "type" "call")])
3551 (define_expand "call_value"
3552 [(parallel [(set (match_operand 0 "" "=rf")
3553 (call (match_operand 1 "memory_operand" "m")
3554 (match_operand 2 "general_operand" "g")))
3555 (clobber (reg:SI 14))])]
3559 (define_insn "*call_value_reg"
3560 [(set (match_operand 0 "" "=rf")
3561 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
3562 (match_operand 2 "general_operand" "g")))
3563 (clobber (reg:SI 14))]
3566 return output_call (&operands[1]);
3568 [(set_attr "length" "12")
3569 (set_attr "type" "call")])
3571 (define_insn "*call_value_mem"
3572 [(set (match_operand 0 "" "=rf")
3573 (call (mem:SI (match_operand 1 "memory_operand" "m"))
3574 (match_operand 2 "general_operand" "g")))
3575 (clobber (reg:SI 14))]
3576 "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
3578 return output_call_mem (&operands[1]);
3580 [(set_attr "length" "12")
3581 (set_attr "type" "call")])
3583 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
3584 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
3586 (define_insn "*call_symbol"
3587 [(call (mem:SI (match_operand:SI 0 "" "X"))
3588 (match_operand:SI 1 "general_operand" "g"))
3589 (clobber (reg:SI 14))]
3590 "GET_CODE (operands[0]) == SYMBOL_REF"
3592 [(set_attr "type" "call")])
3594 (define_insn "*call_value_symbol"
3595 [(set (match_operand 0 "s_register_operand" "=rf")
3596 (call (mem:SI (match_operand:SI 1 "" "X"))
3597 (match_operand:SI 2 "general_operand" "g")))
3598 (clobber (reg:SI 14))]
3599 "GET_CODE(operands[1]) == SYMBOL_REF"
3601 [(set_attr "type" "call")])
3603 ;; Often the return insn will be the same as loading from memory, so set attr
3604 (define_insn "return"
3609 extern int arm_ccfsm_state;
3611 if (arm_ccfsm_state == 2)
3613 arm_ccfsm_state += 2;
3616 return output_return_instruction (NULL, TRUE);
3618 [(set_attr "type" "load")])
3620 (define_insn "*cond_return"
3622 (if_then_else (match_operator 0 "comparison_operator"
3623 [(reg 24) (const_int 0)])
3629 extern int arm_ccfsm_state;
3631 if (arm_ccfsm_state == 2)
3633 arm_ccfsm_state += 2;
3636 return output_return_instruction (operands[0], TRUE);
3638 [(set_attr "conds" "use")
3639 (set_attr "type" "load")])
3641 (define_insn "*cond_return_inverted"
3643 (if_then_else (match_operator 0 "comparison_operator"
3644 [(reg 24) (const_int 0)])
3650 extern int arm_ccfsm_state;
3652 if (arm_ccfsm_state == 2)
3654 arm_ccfsm_state += 2;
3657 return output_return_instruction
3658 (gen_rtx (reverse_condition (GET_CODE (operands[0])),
3659 GET_MODE (operands[0]), XEXP (operands[0], 0),
3660 XEXP (operands[0], 1)),
3663 [(set_attr "conds" "use")
3664 (set_attr "type" "load")])
3666 ;; Call subroutine returning any type.
3668 (define_expand "untyped_call"
3669 [(parallel [(call (match_operand 0 "" "")
3671 (match_operand 1 "" "")
3672 (match_operand 2 "" "")])]
3678 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
3680 for (i = 0; i < XVECLEN (operands[2], 0); i++)
3682 rtx set = XVECEXP (operands[2], 0, i);
3683 emit_move_insn (SET_DEST (set), SET_SRC (set));
3686 /* The optimizer does not know that the call sets the function value
3687 registers we stored in the result block. We avoid problems by
3688 claiming that all hard registers are used and clobbered at this
3690 emit_insn (gen_blockage ());
3695 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
3696 ;; all of memory. This blocks insns from being moved across this point.
3698 (define_insn "blockage"
3699 [(unspec_volatile [(const_int 0)] 0)]
3702 [(set_attr "length" "0")
3703 (set_attr "type" "block")])
3705 (define_expand "casesi"
3706 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
3707 (match_operand:SI 1 "immediate_operand" "") ; lower bound
3708 (match_operand:SI 2 "immediate_operand" "") ; total range
3709 (match_operand:SI 3 "" "") ; table label
3710 (match_operand:SI 4 "" "")] ; Out of range label
3715 if (operands[1] != const0_rtx)
3717 reg = gen_reg_rtx (SImode);
3718 emit_insn (gen_addsi3 (reg, operands[0],
3719 GEN_INT (-INTVAL (operands[1]))));
3723 if (! const_ok_for_arm (INTVAL (operands[2])))
3724 operands[2] = force_reg (SImode, operands[2]);
3726 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
3731 (define_insn "casesi_internal"
3734 (leu (match_operand:SI 0 "s_register_operand" "r")
3735 (match_operand:SI 1 "arm_rhs_operand" "rI"))
3736 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
3737 (label_ref (match_operand 2 "" ""))))
3738 (label_ref (match_operand 3 "" ""))))]
3742 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
3743 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
3745 [(set_attr "conds" "clob")
3746 (set_attr "length" "12")])
3748 (define_insn "indirect_jump"
3750 (match_operand:SI 0 "s_register_operand" "r"))]
3752 "mov%?\\t%|pc, %0\\t%@ indirect jump")
3754 (define_insn "*load_indirect_jump"
3756 (match_operand:SI 0 "memory_operand" "m"))]
3758 "ldr%?\\t%|pc, %0\\t%@ indirect jump"
3759 [(set_attr "type" "load")])
3766 "mov%?\\tr0, r0\\t%@ nop")
3768 ;; Patterns to allow combination of arithmetic, cond code and shifts
3770 (define_insn "*arith_shiftsi"
3771 [(set (match_operand:SI 0 "s_register_operand" "=r")
3772 (match_operator:SI 1 "shiftable_operator"
3773 [(match_operator:SI 3 "shift_operator"
3774 [(match_operand:SI 4 "s_register_operand" "r")
3775 (match_operand:SI 5 "reg_or_int_operand" "rI")])
3776 (match_operand:SI 2 "s_register_operand" "r")]))]
3778 "%i1%?\\t%0, %2, %4%S3")
3780 (define_insn "*arith_shiftsi_compare0"
3781 [(set (reg:CC_NOOV 24)
3782 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
3783 [(match_operator:SI 3 "shift_operator"
3784 [(match_operand:SI 4 "s_register_operand" "r")
3785 (match_operand:SI 5 "reg_or_int_operand" "rI")])
3786 (match_operand:SI 2 "s_register_operand" "r")])
3788 (set (match_operand:SI 0 "s_register_operand" "=r")
3789 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
3792 "%i1%?s\\t%0, %2, %4%S3"
3793 [(set_attr "conds" "set")])
3795 (define_insn "*arith_shiftsi_compare0_scratch"
3796 [(set (reg:CC_NOOV 24)
3797 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
3798 [(match_operator:SI 3 "shift_operator"
3799 [(match_operand:SI 4 "s_register_operand" "r")
3800 (match_operand:SI 5 "reg_or_int_operand" "rI")])
3801 (match_operand:SI 2 "s_register_operand" "r")])
3803 (clobber (match_scratch:SI 0 "=r"))]
3805 "%i1%?s\\t%0, %2, %4%S3"
3806 [(set_attr "conds" "set")])
3808 (define_insn "*sub_shiftsi"
3809 [(set (match_operand:SI 0 "s_register_operand" "=r")
3810 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3811 (match_operator:SI 2 "shift_operator"
3812 [(match_operand:SI 3 "s_register_operand" "r")
3813 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
3815 "sub%?\\t%0, %1, %3%S2")
3817 (define_insn "*sub_shiftsi_compare0"
3818 [(set (reg:CC_NOOV 24)
3820 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3821 (match_operator:SI 2 "shift_operator"
3822 [(match_operand:SI 3 "s_register_operand" "r")
3823 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
3825 (set (match_operand:SI 0 "s_register_operand" "=r")
3826 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
3829 "sub%?s\\t%0, %1, %3%S2"
3830 [(set_attr "conds" "set")])
3832 (define_insn "*sub_shiftsi_compare0_scratch"
3833 [(set (reg:CC_NOOV 24)
3835 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3836 (match_operator:SI 2 "shift_operator"
3837 [(match_operand:SI 3 "s_register_operand" "r")
3838 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
3840 (clobber (match_scratch:SI 0 "=r"))]
3842 "sub%?s\\t%0, %1, %3%S2"
3843 [(set_attr "conds" "set")])
3845 ;; These variants of the above insns can occur if the first operand is the
3846 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
3847 ;; seem to be a way around it. Most of the predicates have to be null
3848 ;; because the format can be generated part way through reload, so
3849 ;; if we don't match it as soon as it becomes available, reload doesn't know
3850 ;; how to reload pseudos that haven't got hard registers; the constraints will
3851 ;; sort everything out.
3853 (define_insn "*reload_mulsi3"
3854 [(set (match_operand:SI 0 "" "=&r")
3855 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
3856 [(match_operand:SI 3 "" "r")
3857 (match_operand:SI 4 "" "rM")])
3858 (match_operand:SI 2 "" "r"))
3859 (match_operand:SI 1 "const_int_operand" "n")))]
3860 "reload_in_progress"
3862 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
3863 operands[2] = operands[1];
3864 operands[1] = operands[0];
3865 return output_add_immediate (operands);
3867 ; we have no idea how long the add_immediate is, it could be up to 4.
3868 [(set_attr "length" "20")])
3870 (define_insn "*relaod_mulsi_compare0"
3871 [(set (reg:CC_NOOV 24)
3872 (compare:CC_NOOV (plus:SI
3874 (match_operator:SI 5 "shift_operator"
3875 [(match_operand:SI 3 "" "r")
3876 (match_operand:SI 4 "" "rM")])
3877 (match_operand:SI 1 "" "r"))
3878 (match_operand:SI 2 "const_int_operand" "n"))
3880 (set (match_operand:SI 0 "" "=&r")
3881 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
3884 "reload_in_progress"
3886 output_add_immediate (operands);
3887 return \"add%?s\\t%0, %0, %3%S5\";
3889 [(set_attr "conds" "set")
3890 (set_attr "length" "20")])
3892 (define_insn "*reload_mulsi_compare0_scratch"
3893 [(set (reg:CC_NOOV 24)
3894 (compare:CC_NOOV (plus:SI
3896 (match_operator:SI 5 "shift_operator"
3897 [(match_operand:SI 3 "" "r")
3898 (match_operand:SI 4 "" "rM")])
3899 (match_operand:SI 1 "" "r"))
3900 (match_operand:SI 2 "const_int_operand" "n"))
3902 (clobber (match_scratch:SI 0 "=&r"))]
3903 "reload_in_progress"
3905 output_add_immediate (operands);
3906 return \"add%?s\\t%0, %0, %3%S5\";
3908 [(set_attr "conds" "set")
3909 (set_attr "length" "20")])
3911 ;; These are similar, but are needed when the mla pattern contains the
3912 ;; eliminated register as operand 3.
3914 (define_insn "*reload_muladdsi"
3915 [(set (match_operand:SI 0 "" "=&r,&r")
3916 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
3917 (match_operand:SI 2 "" "r,r"))
3918 (match_operand:SI 3 "" "r,r"))
3919 (match_operand:SI 4 "const_int_operand" "n,n")))]
3920 "reload_in_progress"
3922 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
3923 operands[2] = operands[4];
3924 operands[1] = operands[0];
3925 return output_add_immediate (operands);
3927 [(set_attr "length" "20")
3928 (set_attr "type" "mult")])
3930 (define_insn "*reload_muladdsi_compare0"
3931 [(set (reg:CC_NOOV 24)
3932 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
3933 (match_operand:SI 3 "" "r")
3934 (match_operand:SI 4 "" "r"))
3935 (match_operand:SI 1 "" "r"))
3936 (match_operand:SI 2 "const_int_operand" "n"))
3938 (set (match_operand:SI 0 "" "=&r")
3939 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
3941 "reload_in_progress"
3943 output_add_immediate (operands);
3944 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
3947 [(set_attr "length" "20")
3948 (set_attr "conds" "set")
3949 (set_attr "type" "mult")])
3951 (define_insn "*reload_muladdsi_compare0_scratch"
3952 [(set (reg:CC_NOOV 24)
3953 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
3954 (match_operand:SI 3 "" "r")
3955 (match_operand:SI 4 "" "r"))
3956 (match_operand:SI 1 "" "r"))
3957 (match_operand:SI 2 "const_int_operand" "n"))
3959 (clobber (match_scratch:SI 0 "=&r"))]
3960 "reload_in_progress"
3962 output_add_immediate (operands);
3963 return \"mla%?s\\t%0, %3, %4, %0\";
3965 [(set_attr "length" "20")
3966 (set_attr "conds" "set")
3967 (set_attr "type" "mult")])
3971 (define_insn "*and_scc"
3972 [(set (match_operand:SI 0 "s_register_operand" "=r")
3973 (and:SI (match_operator 1 "comparison_operator"
3974 [(match_operand 3 "reversible_cc_register" "") (const_int 0)])
3975 (match_operand:SI 2 "s_register_operand" "r")))]
3977 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
3978 [(set_attr "conds" "use")
3979 (set_attr "length" "8")])
3981 (define_insn "*ior_scc"
3982 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3983 (ior:SI (match_operator 2 "comparison_operator"
3984 [(reg 24) (const_int 0)])
3985 (match_operand:SI 1 "s_register_operand" "0,?r")))]
3989 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
3990 [(set_attr "conds" "use")
3991 (set_attr "length" "4,8")])
3993 (define_insn "*compare_scc"
3994 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
3995 (match_operator 1 "comparison_operator"
3996 [(match_operand:SI 2 "s_register_operand" "r,r")
3997 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
4001 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4002 return \"mov\\t%0, %2, lsr #31\";
4004 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4005 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4007 if (GET_CODE (operands[1]) == NE)
4009 if (which_alternative == 1)
4010 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4011 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4013 if (which_alternative == 1)
4014 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4016 output_asm_insn (\"cmp\\t%2, %3\", operands);
4017 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4019 [(set_attr "conds" "clob")
4020 (set_attr "length" "12")])
4022 (define_insn "*ior_compare_compare"
4023 [(set (match_operand:SI 0 "s_register_operand" "=&r")
4024 (ior:SI (match_operator 1 "comparison_operator"
4025 [(match_operand:SI 2 "s_register_operand" "r")
4026 (match_operand:SI 3 "arm_rhs_operand" "rI")])
4027 (match_operator 4 "comparison_operator"
4028 [(match_operand:SI 5 "s_register_operand" "r")
4029 (match_operand:SI 6 "arm_rhs_operand" "rI")])))
4034 int dominant = comparison_dominates_p (GET_CODE (operands[4]),
4035 GET_CODE (operands[1]));
4037 output_asm_insn (dominant ? \"cmp\\t%5, %6\" : \"cmp\\t%2, %3\",
4039 output_asm_insn (\"mov\\t%0, #0\", operands);
4040 if (GET_CODE (operands[1]) == GET_CODE (operands[4])
4041 || comparison_dominates_p (GET_CODE (operands[1]),
4042 GET_CODE (operands[4]))
4044 output_asm_insn (dominant ? \"cmp%D4\\t%2, %3\" : \"cmp%D1\\t%5,%6\",
4047 output_asm_insn (\"mov%d1\\t%0, #1\;cmp\\t%5, %6\", operands);
4048 return dominant ? \"mov%d1\\t%0, #1\" : \"mov%d4\\t%0, #1\";
4051 [(set_attr "conds" "clob")
4053 (set_attr "length" "20")])
4058 (match_operator 5 "equality_operator"
4059 [(ior:SI (match_operator 6 "comparison_operator"
4060 [(match_operand:SI 0 "s_register_operand" "")
4061 (match_operand:SI 1 "arm_add_operand" "")])
4062 (match_operator 7 "comparison_operator"
4063 [(match_operand:SI 2 "s_register_operand" "")
4064 (match_operand:SI 3 "arm_add_operand" "")]))
4066 (label_ref (match_operand 4 "" ""))
4069 "(GET_CODE (operands[6]) == GET_CODE (operands[7])
4070 || comparison_dominates_p (GET_CODE (operands[6]), GET_CODE (operands[7]))
4071 || comparison_dominates_p (GET_CODE (operands[7]), GET_CODE (operands[6])))"
4073 (compare:CC (ior:CC (match_op_dup 6
4074 [(match_dup 0) (match_dup 1)])
4076 [(match_dup 2) (match_dup 3)]))
4079 (if_then_else (match_op_dup 5 [(reg:CC 24) (const_int 0)])
4080 (label_ref (match_dup 4))
4084 enum rtx_code code = comparison_dominates_p (GET_CODE (operands[6]),
4085 GET_CODE (operands[7]))
4086 ? GET_CODE (operands[7]) : GET_CODE (operands[6]);
4088 if (GET_CODE (operands[5]) == NE)
4089 operands[5] = gen_rtx (code, CCmode,
4090 XEXP (operands[5], 0), XEXP (operands[5], 1));
4092 operands[5] = gen_rtx (reverse_condition (code), CCmode,
4093 XEXP (operands[5], 0), XEXP (operands[5], 1));
4097 ;; Don't match these patterns if we can use a conditional compare, since they
4098 ;; tell the final prescan branch eliminator code that full branch inlining
4101 (define_insn "*impossible_cond_compare"
4104 (ne (ior:SI (match_operator 5 "comparison_operator"
4105 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4106 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4107 (match_operator 6 "comparison_operator"
4108 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4109 (match_operand:SI 3 "arm_rhs_operand" "rI,rI,L,L")]))
4111 (label_ref (match_operand 4 "" ""))
4114 "!(GET_CODE (operands[5]) == GET_CODE (operands[6])
4115 || comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[6]))
4116 || comparison_dominates_p (GET_CODE (operands[6]), GET_CODE (operands[5])))"
4119 extern int arm_ccfsm_state;
4121 if (which_alternative & 1)
4122 output_asm_insn (\"cmn\\t%0, #%n1\;b%d5\\t%l4\", operands);
4124 output_asm_insn (\"cmp\\t%0, %1\;b%d5\\t%l4\", operands);
4126 if (which_alternative >= 2)
4127 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4129 output_asm_insn (\"cmp\\t%2, %3\", operands);
4131 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4133 arm_ccfsm_state += 2;
4136 return \"b%d6\\t%l4\";
4138 [(set_attr "conds" "jump_clob")
4139 (set_attr "length" "16")])
4141 (define_insn "*condition_compare_ior"
4144 (ior:CC (match_operator 4 "comparison_operator"
4145 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4146 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4147 (match_operator 5 "comparison_operator"
4148 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4149 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
4151 "(GET_CODE (operands[4]) == GET_CODE (operands[5])
4152 || comparison_dominates_p (GET_CODE (operands[4]), GET_CODE (operands[5]))
4153 || comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])))"
4155 if (comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])))
4157 if (which_alternative >= 2)
4158 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4160 output_asm_insn (\"cmp\\t%2, %3\", operands);
4162 if (which_alternative & 1)
4163 return \"cmn%D5\\t%0, #%n1\";
4164 return \"cmp%D5\\t%0, %1\";
4167 if (which_alternative & 1)
4168 output_asm_insn (\"cmn\\t%0, #%n1\", operands);
4170 output_asm_insn (\"cmp\\t%0, %1\", operands);
4172 if (which_alternative >= 2)
4173 return \"cmn%D4\\t%2, #%n3\";
4174 return \"cmp%D4\\t%2, %3\";
4176 [(set_attr "conds" "set")
4177 (set_attr "length" "8")])
4179 (define_insn "*cond_move"
4180 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4181 (if_then_else (match_operator 3 "equality_operator"
4182 [(match_operator 4 "comparison_operator"
4183 [(reg 24) (const_int 0)])
4185 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4186 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4189 if (GET_CODE (operands[3]) == NE)
4191 if (which_alternative != 1)
4192 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4193 if (which_alternative != 0)
4194 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4197 if (which_alternative != 0)
4198 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4199 if (which_alternative != 1)
4200 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4203 [(set_attr "conds" "use")
4204 (set_attr "length" "4,4,8")])
4206 (define_insn "*cond_arith"
4207 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4208 (match_operator:SI 5 "shiftable_operator"
4209 [(match_operator:SI 4 "comparison_operator"
4210 [(match_operand:SI 2 "s_register_operand" "r,r")
4211 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4212 (match_operand:SI 1 "s_register_operand" "0,?r")]))
4216 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4217 return \"%i5\\t%0, %1, %2, lsr #31\";
4219 output_asm_insn (\"cmp\\t%2, %3\", operands);
4220 if (GET_CODE (operands[5]) == AND)
4221 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4222 else if (GET_CODE (operands[5]) == MINUS)
4223 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4224 else if (which_alternative != 0)
4225 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4226 return \"%i5%d4\\t%0, %1, #1\";
4228 [(set_attr "conds" "clob")
4229 (set_attr "length" "12")])
4231 (define_insn "*cond_sub"
4232 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4233 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4234 (match_operator:SI 4 "comparison_operator"
4235 [(match_operand:SI 2 "s_register_operand" "r,r")
4236 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4240 output_asm_insn (\"cmp\\t%2, %3\", operands);
4241 if (which_alternative != 0)
4242 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4243 return \"sub%d4\\t%0, %1, #1\";
4245 [(set_attr "conds" "clob")
4246 (set_attr "length" "8,12")])
4248 (define_insn "*and_scc_scc"
4249 [(set (match_operand:SI 0 "s_register_operand" "=&r")
4250 (and:SI (match_operator 1 "comparison_operator"
4251 [(match_operand:SI 2 "s_register_operand" "r")
4252 (match_operand:SI 3 "arm_rhs_operand" "rI")])
4253 (match_operator 4 "comparison_operator"
4254 [(match_operand:SI 5 "s_register_operand" "r")
4255 (match_operand:SI 6 "arm_rhs_operand" "rI")])))
4261 comparison_dominates_p (reverse_condition (GET_CODE (operands[1])),
4262 reverse_condition (GET_CODE (operands[4])))
4264 : comparison_dominates_p (reverse_condition (GET_CODE (operands[4])),
4265 reverse_condition (GET_CODE (operands[1])))
4267 output_asm_insn (dominant == 2 ? \"cmp\\t%5, %6\" : \"cmp\\t%2, %3\",
4269 output_asm_insn (\"mov\\t%0, #1\", operands);
4270 if (GET_CODE (operands[1]) == GET_CODE (operands[4]) || dominant)
4272 output_asm_insn (dominant == 2 ? \"cmp%d4\\t%2, %3\"
4273 : \"cmp%d1\\t%5, %6\", operands);
4277 output_asm_insn (\"mov%D1\\t%0, #0\", operands);
4278 output_asm_insn (\"cmp\\t%5, %6\", operands);
4280 return dominant == 2 ? \"mov%D1\\t%0, #0\" : \"mov%D4\\t%0, #0\";
4283 [(set_attr "conds" "clob")
4284 (set_attr "length" "20")])
4288 (if_then_else (match_operator 1 "equality_operator"
4289 [(and:SI (match_operator 2 "comparison_operator"
4290 [(match_operand:SI 3 "s_register_operand" "")
4291 (match_operand:SI 4 "arm_add_operand" "")])
4292 (match_operator 0 "comparison_operator"
4293 [(match_operand:SI 5 "s_register_operand" "")
4294 (match_operand:SI 6 "arm_add_operand" "")]))
4296 (label_ref (match_operand 7 "" ""))
4299 "(GET_CODE (operands[2]) == GET_CODE (operands[0])
4300 || comparison_dominates_p (reverse_condition (GET_CODE (operands[2])),
4301 reverse_condition (GET_CODE (operands[0])))
4302 || comparison_dominates_p (reverse_condition (GET_CODE (operands[0])),
4303 reverse_condition (GET_CODE (operands[2]))))"
4305 (compare:CC (ior:CC (match_op_dup 2
4306 [(match_dup 3) (match_dup 4)])
4308 [(match_dup 5) (match_dup 6)]))
4311 (if_then_else (match_op_dup 1 [(reg:CC 24) (const_int 0)])
4312 (label_ref (match_dup 7))
4316 /* Use DeMorgans law to convert this into an IOR of the inverse conditions
4317 This is safe since we only do it for integer comparisons. */
4318 enum rtx_code code =
4319 comparison_dominates_p (reverse_condition (GET_CODE (operands[2])),
4320 reverse_condition (GET_CODE (operands[0])))
4321 ? GET_CODE (operands[0]) : GET_CODE (operands[2]);
4323 operands[2] = gen_rtx (reverse_condition (GET_CODE (operands[2])),
4324 GET_MODE (operands[2]), operands[3], operands[4]);
4325 operands[0] = gen_rtx (reverse_condition (GET_CODE (operands[0])),
4326 GET_MODE (operands[0]), operands[5], operands[6]);
4327 if (GET_CODE (operands[1]) == NE)
4328 operands[1] = gen_rtx (code, CCmode,
4329 XEXP (operands[1], 0), XEXP (operands[1], 1));
4331 operands[1] = gen_rtx (reverse_condition (code), CCmode,
4332 XEXP (operands[1], 0), XEXP (operands[1], 1));
4336 ;; Don't match these patterns if we can use a conditional compare, since they
4337 ;; tell the final prescan branch eliminator code that full branch inlining
4340 (define_insn "*impossible_cond_branch_and"
4343 (eq (and:SI (match_operator 1 "comparison_operator"
4344 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4345 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L")])
4346 (match_operator 4 "comparison_operator"
4347 [(match_operand:SI 5 "s_register_operand" "r,r,r,r")
4348 (match_operand:SI 6 "arm_rhs_operand" "rI,rI,L,L")]))
4350 (label_ref (match_operand 0 "" ""))
4353 "!(GET_CODE (operands[1]) == GET_CODE (operands[4])
4354 || comparison_dominates_p (reverse_condition (GET_CODE (operands[1])),
4355 reverse_condition (GET_CODE (operands[4])))
4356 || comparison_dominates_p (reverse_condition (GET_CODE (operands[4])),
4357 reverse_condition (GET_CODE (operands[1]))))"
4360 extern int arm_ccfsm_state;
4362 if (which_alternative & 1)
4363 output_asm_insn (\"cmn\\t%2, #%n3\;b%D1\\t%l0\", operands);
4365 output_asm_insn (\"cmp\\t%2, %3\;b%D1\\t%l0\", operands);
4367 if (which_alternative >= 2)
4368 output_asm_insn (\"cmn\\t%5, #%n6\", operands);
4370 output_asm_insn (\"cmp\\t%5, %6\", operands);
4372 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4374 arm_ccfsm_state += 2;
4377 return \"b%D4\\t%l0\";
4379 [(set_attr "conds" "jump_clob")
4380 (set_attr "length" "16")])
4382 (define_insn "*negscc"
4383 [(set (match_operand:SI 0 "s_register_operand" "=r")
4384 (neg:SI (match_operator 3 "comparison_operator"
4385 [(match_operand:SI 1 "s_register_operand" "r")
4386 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4390 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4391 return \"mov\\t%0, %1, asr #31\";
4393 if (GET_CODE (operands[3]) == NE)
4394 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4396 if (GET_CODE (operands[3]) == GT)
4397 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4399 output_asm_insn (\"cmp\\t%1, %2\", operands);
4400 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4401 return \"mvn%d3\\t%0, #0\";
4403 [(set_attr "conds" "clob")
4404 (set_attr "length" "12")])
4406 (define_insn "movcond"
4407 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4409 (match_operator 5 "comparison_operator"
4410 [(match_operand:SI 3 "s_register_operand" "r,r,r")
4411 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4412 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4413 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4417 if (GET_CODE (operands[5]) == LT
4418 && (operands[4] == const0_rtx))
4420 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4422 if (operands[2] == const0_rtx)
4423 return \"and\\t%0, %1, %3, asr #31\";
4424 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4426 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4428 if (operands[1] == const0_rtx)
4429 return \"bic\\t%0, %2, %3, asr #31\";
4430 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4432 /* The only case that falls through to here is when both ops 1 & 2
4436 if (GET_CODE (operands[5]) == GE
4437 && (operands[4] == const0_rtx))
4439 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4441 if (operands[2] == const0_rtx)
4442 return \"bic\\t%0, %1, %3, asr #31\";
4443 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4445 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4447 if (operands[1] == const0_rtx)
4448 return \"and\\t%0, %2, %3, asr #31\";
4449 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4451 /* The only case that falls through to here is when both ops 1 & 2
4454 if (GET_CODE (operands[4]) == CONST_INT
4455 && !const_ok_for_arm (INTVAL (operands[4])))
4456 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4458 output_asm_insn (\"cmp\\t%3, %4\", operands);
4459 if (which_alternative != 0)
4460 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4461 if (which_alternative != 1)
4462 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4465 [(set_attr "conds" "clob")
4466 (set_attr "length" "8,8,12")])
4468 (define_insn "*ifcompare_arith_arith"
4469 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4470 (if_then_else:SI (match_operator 9 "comparison_operator"
4471 [(match_operand:SI 5 "s_register_operand" "r,r")
4472 (match_operand:SI 6 "arm_add_operand" "rI,L")])
4473 (match_operator:SI 8 "shiftable_operator"
4474 [(match_operand:SI 1 "s_register_operand" "r,r")
4475 (match_operand:SI 2 "arm_rhs_operand" "rI,rI")])
4476 (match_operator:SI 7 "shiftable_operator"
4477 [(match_operand:SI 3 "s_register_operand" "r,r")
4478 (match_operand:SI 4 "arm_rhs_operand" "rI,rI")])))
4482 cmp\\t%5, %6\;%I8%d9\\t%0, %1, %2\;%I7%D9\\t%0, %3, %4
4483 cmn\\t%5, #%n6\;%I8%d9\\t%0, %1, %2\;%I7%D9\\t%0, %3, %4"
4484 [(set_attr "conds" "clob")
4485 (set_attr "length" "12")])
4487 (define_insn "*ifcompare_arith_move"
4488 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4489 (if_then_else:SI (match_operator 6 "comparison_operator"
4490 [(match_operand:SI 2 "s_register_operand" "r,r")
4491 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
4492 (match_operator:SI 7 "shiftable_operator"
4493 [(match_operand:SI 4 "s_register_operand" "r,r")
4494 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
4495 (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4499 /* If we have an operation where (op x 0) is the identity operation and
4500 the conditional operator is LT or GE and we are comparing against zero and
4501 everything is in registers then we can do this in two instructions */
4502 if (operands[3] == const0_rtx
4503 && GET_CODE (operands[7]) != AND
4504 && GET_CODE (operands[5]) == REG
4505 && GET_CODE (operands[1]) == REG
4506 && REGNO (operands[1]) == REGNO (operands[4])
4507 && REGNO (operands[4]) != REGNO (operands[0]))
4509 if (GET_CODE (operands[6]) == LT)
4510 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4511 else if (GET_CODE (operands[6]) == GE)
4512 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
4514 if (GET_CODE (operands[3]) == CONST_INT
4515 && !const_ok_for_arm (INTVAL (operands[3])))
4516 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4518 output_asm_insn (\"cmp\\t%2, %3\", operands);
4519 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
4520 if (which_alternative != 0)
4522 if (GET_CODE (operands[1]) == MEM)
4523 return \"ldr%D6\\t%0, %1\";
4525 return \"mov%D6\\t%0, %1\";
4529 [(set_attr "conds" "clob")
4530 (set_attr "length" "8,12")])
4532 (define_insn "*ifcompare_move_arith"
4533 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4534 (if_then_else:SI (match_operator 6 "comparison_operator"
4535 [(match_operand:SI 4 "s_register_operand" "r,r")
4536 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4537 (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4538 (match_operator:SI 7 "shiftable_operator"
4539 [(match_operand:SI 2 "s_register_operand" "r,r")
4540 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4544 /* If we have an operation where (op x 0) is the identity operation and
4545 the conditional operator is LT or GE and we are comparing against zero and
4546 everything is in registers then we can do this in two instructions */
4547 if (operands[5] == const0_rtx
4548 && GET_CODE (operands[7]) != AND
4549 && GET_CODE (operands[3]) == REG
4550 && GET_CODE (operands[1]) == REG
4551 && REGNO (operands[1]) == REGNO (operands[2])
4552 && REGNO (operands[2]) != REGNO (operands[0]))
4554 if (GET_CODE (operands[6]) == GE)
4555 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4556 else if (GET_CODE (operands[6]) == LT)
4557 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
4560 if (GET_CODE (operands[5]) == CONST_INT
4561 && !const_ok_for_arm (INTVAL (operands[5])))
4562 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4564 output_asm_insn (\"cmp\\t%4, %5\", operands);
4566 if (which_alternative != 0)
4568 if (GET_CODE (operands[1]) == MEM)
4569 output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4571 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4573 return \"%I7%D6\\t%0, %2, %3\";
4575 [(set_attr "conds" "clob")
4576 (set_attr "length" "8,12")])
4578 (define_insn "*ifcompare_plus_move"
4579 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4580 (if_then_else:SI (match_operator 6 "comparison_operator"
4581 [(match_operand:SI 4 "s_register_operand" "r,r")
4582 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4584 (match_operand:SI 2 "s_register_operand" "r,r")
4585 (match_operand:SI 3 "arm_add_operand" "rL,rL"))
4586 (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4591 if (GET_CODE (operands[5]) == CONST_INT
4592 && !const_ok_for_arm (INTVAL (operands[5])))
4593 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4595 output_asm_insn (\"cmp\\t%4, %5\", operands);
4596 if (GET_CODE (operands[3]) == CONST_INT
4597 && !const_ok_for_arm (INTVAL (operands[3])))
4598 output_asm_insn (\"sub%d6\\t%0, %2, #%n3\", operands);
4600 output_asm_insn (\"add%d6\\t%0, %2, %3\", operands);
4601 if (which_alternative != 0)
4603 if (GET_CODE (operands[1]) == MEM)
4604 output_asm_insn (\"ldr%D6\\t%0, %1\", operands);
4606 output_asm_insn (\"mov%D6\\t%0, %1\", operands);
4611 [(set_attr "conds" "clob")
4612 (set_attr "length" "8,12")])
4614 (define_insn "*ifcompare_move_plus"
4615 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4616 (if_then_else:SI (match_operator 6 "comparison_operator"
4617 [(match_operand:SI 4 "s_register_operand" "r,r")
4618 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4619 (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4621 (match_operand:SI 2 "s_register_operand" "r,r")
4622 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4627 if (GET_CODE (operands[5]) == CONST_INT
4628 && !const_ok_for_arm (INTVAL (operands[5])))
4629 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4631 output_asm_insn (\"cmp\\t%4, %5\", operands);
4632 if (GET_CODE (operands[3]) == CONST_INT
4633 && !const_ok_for_arm (INTVAL (operands[3])))
4634 output_asm_insn (\"sub%D6\\t%0, %2, #%n3\", operands);
4636 output_asm_insn (\"add%D6\\t%0, %2, %3\", operands);
4637 if (which_alternative != 0)
4639 if (GET_CODE (operands[6]) == MEM)
4640 output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4642 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4647 [(set_attr "conds" "clob")
4648 (set_attr "length" "8,12")])
4650 (define_insn "ifcompare_move_not"
4651 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4652 (if_then_else:SI (match_operator 5 "comparison_operator"
4653 [(match_operand:SI 3 "s_register_operand" "r,r")
4654 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
4655 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4657 (match_operand:SI 2 "s_register_operand" "r,r"))))
4661 [(set_attr "conds" "clob")
4662 (set_attr "length" "8,12")])
4664 (define_insn "*ifcompare_not_move"
4665 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4667 (match_operator 5 "comparison_operator"
4668 [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4669 (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4671 (match_operand:SI 2 "s_register_operand" "r,r,r,r"))
4672 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4676 cmp\\t%3, %4\;mvn%d5\\t%0, %2
4677 cmn\\t%3, #%n4\;mvn%d5\\t%0, %2
4678 cmp\\t%3, %4\;mov%D5\\t%0, %1\;mvn%d5\\t%0, %2
4679 cmn\\t%3, #%n4\;mov%D5\\t%0, %1\;mvn%d5\\t%0, %2"
4680 [(set_attr "conds" "clob")
4681 (set_attr "length" "8,8,12,12")])
4683 (define_insn "*ifcompare_shift_move"
4684 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4686 (match_operator 6 "comparison_operator"
4687 [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
4688 (match_operand:SI 5 "arm_add_operand" "rI,L,rI,L")])
4689 (match_operator:SI 7 "shift_operator"
4690 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4691 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM,rM")])
4692 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4696 cmp\\t%4, %5\;mov%d6\\t%0, %2%S7
4697 cmn\\t%4, #%n5\;mov%d6\\t%0, %2%S7
4698 cmp\\t%4, %5\;mov%D6\\t%0, %1\;mov%d6\\t%0, %2%S7
4699 cmn\\t%4, #%n5\;mov%D6\\t%0, %1\;mov%d6\\t%0, %2%S7"
4700 [(set_attr "conds" "clob")
4701 (set_attr "length" "8,8,12,12")])
4703 (define_insn "ifcompare_move_shift"
4704 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4706 (match_operator 6 "comparison_operator"
4707 [(match_operand:SI 4 "s_register_operand" "r,r,r,r")
4708 (match_operand:SI 5 "arm_add_operand" "rI,L,rI,L")])
4709 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4710 (match_operator:SI 7 "shift_operator"
4711 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4712 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM,rM")])))
4716 cmp\\t%4, %5\;mov%D6\\t%0, %2%S7
4717 cmn\\t%4, #%n5\;mov%D6\\t%0, %2%S7
4718 cmp\\t%4, %5\;mov%d6\\t%0, %1\;mov%D6\\t%0, %2%S7
4719 cmn\\t%4, #%n5\;mov%d6\\t%0, %1\;mov%D6\\t%0, %2%S7"
4720 [(set_attr "conds" "clob")
4721 (set_attr "length" "8,8,12,12")])
4723 (define_insn "*ifcompare_shift_shift"
4724 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4726 (match_operator 7 "comparison_operator"
4727 [(match_operand:SI 5 "s_register_operand" "r,r")
4728 (match_operand:SI 6 "arm_add_operand" "rI,L")])
4729 (match_operator:SI 8 "shift_operator"
4730 [(match_operand:SI 1 "s_register_operand" "r,r")
4731 (match_operand:SI 2 "arm_rhs_operand" "rM,rM")])
4732 (match_operator:SI 9 "shift_operator"
4733 [(match_operand:SI 3 "s_register_operand" "r,r")
4734 (match_operand:SI 4 "arm_rhs_operand" "rI,rI")])))
4738 cmp\\t%5, %6\;mov%d7\\t%0, %1%S8\;mov%D7\\t%0, %3%S9
4739 cmn\\t%5, #%n6\;mov%d7\\t%0, %1%S8\;mov%D7\\t%0, %3%S9"
4740 [(set_attr "conds" "clob")
4741 (set_attr "length" "12")])
4743 (define_insn "*ifcompare_not_arith"
4744 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4746 (match_operator 6 "comparison_operator"
4747 [(match_operand:SI 4 "s_register_operand" "r,r")
4748 (match_operand:SI 5 "arm_add_operand" "rI,L")])
4749 (not:SI (match_operand:SI 1 "s_register_operand" "r,r"))
4750 (match_operator:SI 7 "shiftable_operator"
4751 [(match_operand:SI 2 "s_register_operand" "r,r")
4752 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4756 cmp\\t%4, %5\;mvn%d6\\t%0, %1\;%I7%D6\\t%0, %2, %3
4757 cmn\\t%4, #%n5\;mvn%d6\\t%0, %1\;%I7%D6\\t%0, %2, %3"
4758 [(set_attr "conds" "clob")
4759 (set_attr "length" "12")])
4761 (define_insn "*if_compare_arith_not"
4762 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4764 (match_operator 6 "comparison_operator"
4765 [(match_operand:SI 4 "s_register_operand" "r,r")
4766 (match_operand:SI 5 "arm_add_operand" "rI,L")])
4767 (match_operator:SI 7 "shiftable_operator"
4768 [(match_operand:SI 2 "s_register_operand" "r,r")
4769 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4770 (not:SI (match_operand:SI 1 "s_register_operand" "r,r"))))
4774 cmp\\t%4, %5\;mvn%D6\\t%0, %1\;%I7%d6\\t%0, %2, %3
4775 cmn\\t%4, #%n5\;mvn%D6\\t%0, %1\;%I7%d6\\t%0, %2, %3"
4776 [(set_attr "conds" "clob")
4777 (set_attr "length" "12")])
4779 (define_insn "*ifcompare_neg_move"
4780 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4782 (match_operator 5 "comparison_operator"
4783 [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4784 (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4785 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r"))
4786 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))
4787 (clobber (reg:CC 24))]
4790 cmp\\t%3, %4\;rsb%d5\\t%0, %2, #0
4791 cmn\\t%3, #%n4\;rsb%d5\\t%0, %2, #0
4792 cmp\\t%3, %4\;mov%D5\\t%0, %1\;rsb%d5\\t%0, %2, #0
4793 cmn\\t%3, #%n4\;mov%D5\\t%0, %1\;rsb%d5\\t%0, %2, #0"
4794 [(set_attr "conds" "clob")
4795 (set_attr "length" "8,8,12,12")])
4797 (define_insn "*ifcompare_move_neg"
4798 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4800 (match_operator 5 "comparison_operator"
4801 [(match_operand:SI 3 "s_register_operand" "r,r,r,r")
4802 (match_operand:SI 4 "arm_add_operand" "rI,L,rI,L")])
4803 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4804 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r"))))
4805 (clobber (reg:CC 24))]
4808 cmp\\t%3, %4\;rsb%D5\\t%0, %2, #0
4809 cmn\\t%3, #%n4\;rsb%D5\\t%0, %2, #0
4810 cmp\\t%3, %4\;mov%d5\\t%0, %1\;rsb%D5\\t%0, %2, #0
4811 cmn\\t%3, #%n4\;mov%d5\\t%0, %1\;rsb%D5\\t%0, %2, #0"
4812 [(set_attr "conds" "clob")
4813 (set_attr "length" "8,8,12,12")])
4815 (define_insn "*arith_adjacentmem"
4816 [(set (match_operand:SI 0 "s_register_operand" "=r")
4817 (match_operator:SI 1 "shiftable_operator"
4818 [(match_operand:SI 2 "memory_operand" "m")
4819 (match_operand:SI 3 "memory_operand" "m")]))
4820 (clobber (match_scratch:SI 4 "=r"))]
4821 "adjacent_mem_locations (operands[2], operands[3])"
4826 int val1 = 0, val2 = 0;
4828 if (REGNO (operands[0]) > REGNO (operands[4]))
4830 ldm[1] = operands[4];
4831 ldm[2] = operands[0];
4835 ldm[1] = operands[0];
4836 ldm[2] = operands[4];
4838 if (GET_CODE (XEXP (operands[2], 0)) != REG)
4839 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
4840 if (GET_CODE (XEXP (operands[3], 0)) != REG)
4841 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
4842 arith[0] = operands[0];
4843 arith[3] = operands[1];
4857 ldm[0] = ops[0] = operands[4];
4858 ops[1] = XEXP (XEXP (operands[2], 0), 0);
4859 ops[2] = XEXP (XEXP (operands[2], 0), 1);
4860 output_add_immediate (ops);
4862 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4864 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4868 ldm[0] = XEXP (operands[3], 0);
4870 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4872 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4876 ldm[0] = XEXP (operands[2], 0);
4878 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
4880 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
4882 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
4886 [(set_attr "length" "12")
4887 (set_attr "type" "load")])
4889 ;; the arm can support extended pre-inc instructions
4891 ;; In all these cases, we use operands 0 and 1 for the register being
4892 ;; incremented because those are the operands that local-alloc will
4893 ;; tie and these are the pair most likely to be tieable (and the ones
4894 ;; that will benefit the most).
4896 ;; We reject the frame pointer if it occurs anywhere in these patterns since
4897 ;; elimination will cause too many headaches.
4899 (define_insn "*strqi_preinc"
4900 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4901 (match_operand:SI 2 "index_operand" "rJ")))
4902 (match_operand:QI 3 "s_register_operand" "r"))
4903 (set (match_operand:SI 0 "s_register_operand" "=r")
4904 (plus:SI (match_dup 1) (match_dup 2)))]
4905 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4906 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4907 && (GET_CODE (operands[2]) != REG
4908 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4909 "str%?b\\t%3, [%0, %2]!"
4910 [(set_attr "type" "store1")])
4912 (define_insn "*strqi_predec"
4913 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4914 (match_operand:SI 2 "s_register_operand" "r")))
4915 (match_operand:QI 3 "s_register_operand" "r"))
4916 (set (match_operand:SI 0 "s_register_operand" "=r")
4917 (minus:SI (match_dup 1) (match_dup 2)))]
4918 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4919 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4920 && (GET_CODE (operands[2]) != REG
4921 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4922 "str%?b\\t%3, [%0, -%2]!"
4923 [(set_attr "type" "store1")])
4925 (define_insn "*loadqi_preinc"
4926 [(set (match_operand:QI 3 "s_register_operand" "=r")
4927 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4928 (match_operand:SI 2 "index_operand" "rJ"))))
4929 (set (match_operand:SI 0 "s_register_operand" "=r")
4930 (plus:SI (match_dup 1) (match_dup 2)))]
4931 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4932 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4933 && (GET_CODE (operands[2]) != REG
4934 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4935 "ldr%?b\\t%3, [%0, %2]!"
4936 [(set_attr "type" "load")])
4938 (define_insn "*loadqi_predec"
4939 [(set (match_operand:QI 3 "s_register_operand" "=r")
4940 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4941 (match_operand:SI 2 "s_register_operand" "r"))))
4942 (set (match_operand:SI 0 "s_register_operand" "=r")
4943 (minus:SI (match_dup 1) (match_dup 2)))]
4944 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4945 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4946 && (GET_CODE (operands[2]) != REG
4947 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4948 "ldr%?b\\t%3, [%0, -%2]!"
4949 [(set_attr "type" "load")])
4951 (define_insn "*loadqisi_preinc"
4952 [(set (match_operand:SI 3 "s_register_operand" "=r")
4954 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4955 (match_operand:SI 2 "index_operand" "rJ")))))
4956 (set (match_operand:SI 0 "s_register_operand" "=r")
4957 (plus:SI (match_dup 1) (match_dup 2)))]
4958 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4959 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4960 && (GET_CODE (operands[2]) != REG
4961 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4962 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
4963 [(set_attr "type" "load")])
4965 (define_insn "*loadqisi_predec"
4966 [(set (match_operand:SI 3 "s_register_operand" "=r")
4968 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4969 (match_operand:SI 2 "s_register_operand" "r")))))
4970 (set (match_operand:SI 0 "s_register_operand" "=r")
4971 (minus:SI (match_dup 1) (match_dup 2)))]
4972 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4973 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4974 && (GET_CODE (operands[2]) != REG
4975 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4976 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
4977 [(set_attr "type" "load")])
4979 (define_insn "*strsi_preinc"
4980 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
4981 (match_operand:SI 2 "index_operand" "rJ")))
4982 (match_operand:SI 3 "s_register_operand" "r"))
4983 (set (match_operand:SI 0 "s_register_operand" "=r")
4984 (plus:SI (match_dup 1) (match_dup 2)))]
4985 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4986 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
4987 && (GET_CODE (operands[2]) != REG
4988 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
4989 "str%?\\t%3, [%0, %2]!"
4990 [(set_attr "type" "store1")])
4992 (define_insn "*strqi_predec"
4993 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
4994 (match_operand:SI 2 "s_register_operand" "r")))
4995 (match_operand:SI 3 "s_register_operand" "r"))
4996 (set (match_operand:SI 0 "s_register_operand" "=r")
4997 (minus:SI (match_dup 1) (match_dup 2)))]
4998 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
4999 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5000 && (GET_CODE (operands[2]) != REG
5001 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5002 "str%?\\t%3, [%0, -%2]!"
5003 [(set_attr "type" "store1")])
5005 (define_insn "*loadsi_preinc"
5006 [(set (match_operand:SI 3 "s_register_operand" "=r")
5007 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5008 (match_operand:SI 2 "index_operand" "rJ"))))
5009 (set (match_operand:SI 0 "s_register_operand" "=r")
5010 (plus:SI (match_dup 1) (match_dup 2)))]
5011 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5012 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5013 && (GET_CODE (operands[2]) != REG
5014 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5015 "ldr%?\\t%3, [%0, %2]!"
5016 [(set_attr "type" "load")])
5018 (define_insn "*loadsi_predec"
5019 [(set (match_operand:SI 3 "s_register_operand" "=r")
5020 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5021 (match_operand:SI 2 "s_register_operand" "r"))))
5022 (set (match_operand:SI 0 "s_register_operand" "=r")
5023 (minus:SI (match_dup 1) (match_dup 2)))]
5024 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5025 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5026 && (GET_CODE (operands[2]) != REG
5027 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5028 "ldr%?\\t%3, [%0, -%2]!"
5029 [(set_attr "type" "load")])
5031 (define_insn "*loadhi_preinc"
5032 [(set (match_operand:HI 3 "s_register_operand" "=r")
5033 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5034 (match_operand:SI 2 "index_operand" "rJ"))))
5035 (set (match_operand:SI 0 "s_register_operand" "=r")
5036 (plus:SI (match_dup 1) (match_dup 2)))]
5037 "(! BYTES_BIG_ENDIAN)
5038 && ! TARGET_SHORT_BY_BYTES
5039 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5040 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5041 && (GET_CODE (operands[2]) != REG
5042 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5043 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5044 [(set_attr "type" "load")])
5046 (define_insn "*loadhi_predec"
5047 [(set (match_operand:HI 3 "s_register_operand" "=r")
5048 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5049 (match_operand:SI 2 "s_register_operand" "r"))))
5050 (set (match_operand:SI 0 "s_register_operand" "=r")
5051 (minus:SI (match_dup 1) (match_dup 2)))]
5052 "(!BYTES_BIG_ENDIAN)
5053 && ! TARGET_SHORT_BY_BYTES
5054 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5055 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5056 && (GET_CODE (operands[2]) != REG
5057 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5058 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5059 [(set_attr "type" "load")])
5061 (define_insn "*strqi_shiftpreinc"
5062 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5063 [(match_operand:SI 3 "s_register_operand" "r")
5064 (match_operand:SI 4 "const_shift_operand" "n")])
5065 (match_operand:SI 1 "s_register_operand" "0")))
5066 (match_operand:QI 5 "s_register_operand" "r"))
5067 (set (match_operand:SI 0 "s_register_operand" "=r")
5068 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5070 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5071 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5072 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5073 "str%?b\\t%5, [%0, %3%S2]!"
5074 [(set_attr "type" "store1")])
5076 (define_insn "*strqi_shiftpredec"
5077 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5078 (match_operator:SI 2 "shift_operator"
5079 [(match_operand:SI 3 "s_register_operand" "r")
5080 (match_operand:SI 4 "const_shift_operand" "n")])))
5081 (match_operand:QI 5 "s_register_operand" "r"))
5082 (set (match_operand:SI 0 "s_register_operand" "=r")
5083 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5085 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5086 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5087 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5088 "str%?b\\t%5, [%0, -%3%S2]!"
5089 [(set_attr "type" "store1")])
5091 (define_insn "*loadqi_shiftpreinc"
5092 [(set (match_operand:QI 5 "s_register_operand" "=r")
5093 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5094 [(match_operand:SI 3 "s_register_operand" "r")
5095 (match_operand:SI 4 "const_shift_operand" "n")])
5096 (match_operand:SI 1 "s_register_operand" "0"))))
5097 (set (match_operand:SI 0 "s_register_operand" "=r")
5098 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5100 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5101 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5102 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5103 "ldr%?b\\t%5, [%0, %3%S2]!"
5104 [(set_attr "type" "load")])
5106 (define_insn "*loadqi_shiftpredec"
5107 [(set (match_operand:QI 5 "s_register_operand" "=r")
5108 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5109 (match_operator:SI 2 "shift_operator"
5110 [(match_operand:SI 3 "s_register_operand" "r")
5111 (match_operand:SI 4 "const_shift_operand" "n")]))))
5112 (set (match_operand:SI 0 "s_register_operand" "=r")
5113 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5115 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5116 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5117 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5118 "ldr%?b\\t%5, [%0, -%3%S2]!"
5119 [(set_attr "type" "load")])
5121 (define_insn "*strsi_shiftpreinc"
5122 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5123 [(match_operand:SI 3 "s_register_operand" "r")
5124 (match_operand:SI 4 "const_shift_operand" "n")])
5125 (match_operand:SI 1 "s_register_operand" "0")))
5126 (match_operand:SI 5 "s_register_operand" "r"))
5127 (set (match_operand:SI 0 "s_register_operand" "=r")
5128 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5130 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5131 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5132 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5133 "str%?\\t%5, [%0, %3%S2]!"
5134 [(set_attr "type" "store1")])
5136 (define_insn "*strsi_shiftpredec"
5137 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5138 (match_operator:SI 2 "shift_operator"
5139 [(match_operand:SI 3 "s_register_operand" "r")
5140 (match_operand:SI 4 "const_shift_operand" "n")])))
5141 (match_operand:SI 5 "s_register_operand" "r"))
5142 (set (match_operand:SI 0 "s_register_operand" "=r")
5143 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5145 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5146 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5147 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5148 "str%?\\t%5, [%0, -%3%S2]!"
5149 [(set_attr "type" "store1")])
5151 (define_insn "*loadqi_shiftpreinc"
5152 [(set (match_operand:SI 5 "s_register_operand" "=r")
5153 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5154 [(match_operand:SI 3 "s_register_operand" "r")
5155 (match_operand:SI 4 "const_shift_operand" "n")])
5156 (match_operand:SI 1 "s_register_operand" "0"))))
5157 (set (match_operand:SI 0 "s_register_operand" "=r")
5158 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5160 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5161 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5162 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5163 "ldr%?\\t%5, [%0, %3%S2]!"
5164 [(set_attr "type" "load")])
5166 (define_insn "*loadqi_shiftpredec"
5167 [(set (match_operand:SI 5 "s_register_operand" "=r")
5168 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5169 (match_operator:SI 2 "shift_operator"
5170 [(match_operand:SI 3 "s_register_operand" "r")
5171 (match_operand:SI 4 "const_shift_operand" "n")]))))
5172 (set (match_operand:SI 0 "s_register_operand" "=r")
5173 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5175 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5176 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5177 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5178 "ldr%?\\t%5, [%0, -%3%S2]!"
5179 [(set_attr "type" "load")])
5181 (define_insn "*loadhi_shiftpreinc"
5182 [(set (match_operand:HI 5 "s_register_operand" "=r")
5183 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5184 [(match_operand:SI 3 "s_register_operand" "r")
5185 (match_operand:SI 4 "const_shift_operand" "n")])
5186 (match_operand:SI 1 "s_register_operand" "0"))))
5187 (set (match_operand:SI 0 "s_register_operand" "=r")
5188 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5190 "(! BYTES_BIG_ENDIAN)
5191 && ! TARGET_SHORT_BY_BYTES
5192 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5193 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5194 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5195 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5196 [(set_attr "type" "load")])
5198 (define_insn "*loadhi_shiftpredec"
5199 [(set (match_operand:HI 5 "s_register_operand" "=r")
5200 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5201 (match_operator:SI 2 "shift_operator"
5202 [(match_operand:SI 3 "s_register_operand" "r")
5203 (match_operand:SI 4 "const_shift_operand" "n")]))))
5204 (set (match_operand:SI 0 "s_register_operand" "=r")
5205 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5207 "(! BYTES_BIG_ENDIAN)
5208 && ! TARGET_SHORT_BY_BYTES
5209 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5210 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5211 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5212 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5213 [(set_attr "type" "load")])
5215 ; It can also support extended post-inc expressions, but combine doesn't
5217 ; It doesn't seem worth adding peepholes for anything but the most common
5218 ; cases since, unlike combine, the increment must immediately follow the load
5219 ; for this pattern to match.
5220 ; When loading we must watch to see that the base register isn't trampled by
5221 ; the load. In such cases this isn't a post-inc expression.
5224 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5225 (match_operand:QI 2 "s_register_operand" "r"))
5227 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5229 "str%?b\\t%2, [%0], %1")
5232 [(set (match_operand:QI 0 "s_register_operand" "=r")
5233 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5235 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5236 "REGNO(operands[0]) != REGNO(operands[1])
5237 && (GET_CODE (operands[2]) != REG
5238 || REGNO(operands[0]) != REGNO (operands[2]))"
5239 "ldr%?b\\t%0, [%1], %2")
5242 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5243 (match_operand:SI 2 "s_register_operand" "r"))
5245 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5247 "str%?\\t%2, [%0], %1")
5250 [(set (match_operand:HI 0 "s_register_operand" "=r")
5251 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5253 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5254 "(! BYTES_BIG_ENDIAN)
5255 && ! TARGET_SHORT_BY_BYTES
5256 && REGNO(operands[0]) != REGNO(operands[1])
5257 && (GET_CODE (operands[2]) != REG
5258 || REGNO(operands[0]) != REGNO (operands[2]))"
5259 "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5262 [(set (match_operand:SI 0 "s_register_operand" "=r")
5263 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5265 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5266 "REGNO(operands[0]) != REGNO(operands[1])
5267 && (GET_CODE (operands[2]) != REG
5268 || REGNO(operands[0]) != REGNO (operands[2]))"
5269 "ldr%?\\t%0, [%1], %2")
5272 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5273 (match_operand:SI 1 "index_operand" "rJ")))
5274 (match_operand:QI 2 "s_register_operand" "r"))
5275 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5277 "str%?b\\t%2, [%0, %1]!")
5280 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5281 [(match_operand:SI 0 "s_register_operand" "r")
5282 (match_operand:SI 1 "const_int_operand" "n")])
5283 (match_operand:SI 2 "s_register_operand" "+r")))
5284 (match_operand:QI 3 "s_register_operand" "r"))
5285 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5288 "str%?b\\t%3, [%2, %0%S4]!")
5290 ; This pattern is never tried by combine, so do it as a peephole
5293 [(set (match_operand:SI 0 "s_register_operand" "=r")
5294 (match_operand:SI 1 "s_register_operand" "r"))
5295 (set (match_operand 2 "cc_register" "")
5296 (compare (match_dup 1) (const_int 0)))]
5298 "sub%?s\\t%0, %1, #0"
5299 [(set_attr "conds" "set")])
5301 ; Peepholes to spot possible load- and store-multiples, if the ordering is
5302 ; reversed, check that the memory references aren't volatile.
5305 [(set (match_operand:SI 0 "s_register_operand" "=r")
5306 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5308 (set (match_operand:SI 2 "s_register_operand" "=r")
5309 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5310 (set (match_operand:SI 3 "s_register_operand" "=r")
5311 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5312 (set (match_operand:SI 4 "s_register_operand" "=r")
5313 (mem:SI (match_dup 1)))]
5314 "REGNO (operands[0]) > REGNO (operands[2])
5315 && REGNO (operands[2]) > REGNO (operands[3])
5316 && REGNO (operands[3]) > REGNO (operands[4])
5317 && !(REGNO (operands[1]) == REGNO (operands[0])
5318 || REGNO (operands[1]) == REGNO (operands[2])
5319 || REGNO (operands[1]) == REGNO (operands[3])
5320 || REGNO (operands[1]) == REGNO (operands[4]))
5321 && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5322 && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))
5323 && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5324 (prev_nonnote_insn (insn)))))
5325 && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5327 (prev_nonnote_insn (insn))))))"
5328 "ldm%?ia\\t%1, {%4, %3, %2, %0}\\t%@ phole ldm")
5331 [(set (match_operand:SI 0 "s_register_operand" "=r")
5332 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5334 (set (match_operand:SI 2 "s_register_operand" "=r")
5335 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5336 (set (match_operand:SI 3 "s_register_operand" "=r")
5337 (mem:SI (match_dup 1)))]
5338 "REGNO (operands[0]) > REGNO (operands[2])
5339 && REGNO (operands[2]) > REGNO (operands[3])
5340 && !(REGNO (operands[1]) == REGNO (operands[0])
5341 || REGNO (operands[1]) == REGNO (operands[2])
5342 || REGNO (operands[1]) == REGNO (operands[3]))
5343 && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5344 && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))
5345 && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5346 (prev_nonnote_insn (insn)))))"
5347 "ldm%?ia\\t%1, {%3, %2, %0}\\t%@ phole ldm")
5350 [(set (match_operand:SI 0 "s_register_operand" "=r")
5351 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5353 (set (match_operand:SI 2 "s_register_operand" "=r")
5354 (mem:SI (match_dup 1)))]
5355 "REGNO (operands[0]) > REGNO (operands[2])
5356 && !(REGNO (operands[1]) == REGNO (operands[0])
5357 || REGNO (operands[1]) == REGNO (operands[2]))
5358 && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5359 && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))"
5360 "ldm%?ia\\t%1, {%2, %0}\\t%@ phole ldm")
5363 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5365 (match_operand:SI 0 "s_register_operand" "r"))
5366 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5367 (match_operand:SI 2 "s_register_operand" "r"))
5368 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5369 (match_operand:SI 3 "s_register_operand" "r"))
5370 (set (mem:SI (match_dup 1))
5371 (match_operand:SI 4 "s_register_operand" "r"))]
5372 "REGNO (operands[0]) > REGNO (operands[2])
5373 && REGNO (operands[2]) > REGNO (operands[3])
5374 && REGNO (operands[3]) > REGNO (operands[4])
5375 && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5376 && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))
5377 && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5378 (prev_nonnote_insn (insn)))))
5379 && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5381 (prev_nonnote_insn (insn))))))"
5382 "stm%?ia\\t%1, {%4, %3, %2, %0}\\t%@ phole stm")
5385 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5387 (match_operand:SI 0 "s_register_operand" "r"))
5388 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5389 (match_operand:SI 2 "s_register_operand" "r"))
5390 (set (mem:SI (match_dup 1))
5391 (match_operand:SI 3 "s_register_operand" "r"))]
5392 "REGNO (operands[0]) > REGNO (operands[2])
5393 && REGNO (operands[2]) > REGNO (operands[3])
5394 && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5395 && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))
5396 && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5397 (prev_nonnote_insn (insn)))))"
5398 "stm%?ia\\t%1, {%3, %2, %0}\\t%@ phole stm")
5401 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5403 (match_operand:SI 0 "s_register_operand" "r"))
5404 (set (mem:SI (match_dup 1))
5405 (match_operand:SI 2 "s_register_operand" "r"))]
5406 "REGNO (operands[0]) > REGNO (operands[2])
5407 && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5408 && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))"
5409 "stm%?ia\\t%1, {%2, %0}\\t%@ phole stm")
5411 ;; A call followed by return can be replaced by restoring the regs and
5412 ;; jumping to the subroutine, provided we aren't passing the address of
5413 ;; any of our local variables. If we call alloca then this is unsafe
5414 ;; since restoring the frame frees the memory, which is not what we want.
5415 ;; Sometimes the return might have been targeted by the final prescan:
5416 ;; if so then emit a proper return insn as well.
5417 ;; Unfortunately, if the frame pointer is required, we don't know if the
5418 ;; current function has any implicit stack pointer adjustments that will
5419 ;; be restored by the return: we can't therefore do a tail call.
5420 ;; Another unfortunate that we can't handle is if current_function_args_size
5421 ;; is non-zero: in this case elimination of the argument pointer assumed
5422 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5426 [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5427 (match_operand:SI 1 "general_operand" "g"))
5428 (clobber (reg:SI 14))])
5430 "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN
5431 && !get_frame_size () && !current_function_calls_alloca
5432 && !frame_pointer_needed && !current_function_args_size)"
5435 extern rtx arm_target_insn;
5436 extern int arm_ccfsm_state, arm_current_cc;
5438 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5440 arm_current_cc ^= 1;
5441 output_return_instruction (NULL, TRUE);
5442 arm_ccfsm_state = 0;
5443 arm_target_insn = NULL;
5446 output_return_instruction (NULL, FALSE);
5447 return \"b%?\\t%a0\";
5449 [(set_attr "type" "call")
5450 (set_attr "length" "8")])
5453 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5454 (call (mem:SI (match_operand:SI 1 "" "X"))
5455 (match_operand:SI 2 "general_operand" "g")))
5456 (clobber (reg:SI 14))])
5458 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5459 && !get_frame_size () && !current_function_calls_alloca
5460 && !frame_pointer_needed && !current_function_args_size)"
5463 extern rtx arm_target_insn;
5464 extern int arm_ccfsm_state, arm_current_cc;
5466 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5468 arm_current_cc ^= 1;
5469 output_return_instruction (NULL, TRUE);
5470 arm_ccfsm_state = 0;
5471 arm_target_insn = NULL;
5474 output_return_instruction (NULL, FALSE);
5475 return \"b%?\\t%a1\";
5477 [(set_attr "type" "call")
5478 (set_attr "length" "8")])
5480 ;; As above but when this function is not void, we must be returning the
5481 ;; result of the called subroutine.
5484 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5485 (call (mem:SI (match_operand:SI 1 "" "X"))
5486 (match_operand:SI 2 "general_operand" "g")))
5487 (clobber (reg:SI 14))])
5490 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5491 && !get_frame_size () && !current_function_calls_alloca
5492 && !frame_pointer_needed && !current_function_args_size)"
5495 extern rtx arm_target_insn;
5496 extern int arm_ccfsm_state, arm_current_cc;
5498 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5500 arm_current_cc ^= 1;
5501 output_return_instruction (NULL, TRUE);
5502 arm_ccfsm_state = 0;
5503 arm_target_insn = NULL;
5506 output_return_instruction (NULL, FALSE);
5507 return \"b%?\\t%a1\";
5509 [(set_attr "type" "call")
5510 (set_attr "length" "8")])
5512 ;; If calling a subroutine and then jumping back to somewhere else, but not
5513 ;; too far away, then we can set the link register with the branch address
5514 ;; and jump direct to the subroutine. On return from the subroutine
5515 ;; execution continues at the branch; this avoids a prefetch stall.
5516 ;; We use the length attribute (via short_branch ()) to establish whether or
5517 ;; not this is possible, this is the same as the sparc does.
5520 [(parallel[(call (mem:SI (match_operand:SI 0 "" "X"))
5521 (match_operand:SI 1 "general_operand" "g"))
5522 (clobber (reg:SI 14))])
5524 (label_ref (match_operand 2 "" "")))]
5525 "0 && GET_CODE (operands[0]) == SYMBOL_REF
5526 && short_branch (INSN_UID (insn), INSN_UID (operands[2]))
5527 && arm_insn_not_targeted (insn)"
5530 int backward = arm_backwards_branch (INSN_UID (insn),
5531 INSN_UID (operands[2]));
5534 /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
5535 * above, leaving it out means that the code will still run on an arm 2 or 3
5540 output_asm_insn (\"sub%?\\t%|lr, %|pc, #(8 + . -%l2)\", operands);
5542 output_asm_insn (\"add%?\\t%|lr, %|pc, #(%l2 - . -8)\", operands);
5547 output_asm_insn (\"mov%?\\t%|lr, %|pc\\t%@ protect cc\", operands);
5549 output_asm_insn (\"sub%?\\t%|lr, %|lr, #(4 + . -%l2)\", operands);
5551 output_asm_insn (\"add%?\\t%|lr, %|lr, #(%l2 - . -4)\", operands);
5553 return \"b%?\\t%a0\";
5555 [(set_attr "type" "call")
5556 (set (attr "length")
5557 (if_then_else (eq_attr "prog_mode" "prog32")
5562 [(parallel[(set (match_operand:SI 0 "s_register_operand" "=r")
5563 (call (mem:SI (match_operand:SI 1 "" "X"))
5564 (match_operand:SI 2 "general_operand" "g")))
5565 (clobber (reg:SI 14))])
5567 (label_ref (match_operand 3 "" "")))]
5568 "0 && GET_CODE (operands[0]) == SYMBOL_REF
5569 && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
5570 && arm_insn_not_targeted (insn)"
5573 int backward = arm_backwards_branch (INSN_UID (insn),
5574 INSN_UID (operands[3]));
5577 /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
5578 * above, leaving it out means that the code will still run on an arm 2 or 3
5583 output_asm_insn (\"sub%?\\t%|lr, %|pc, #(8 + . -%l3)\", operands);
5585 output_asm_insn (\"add%?\\t%|lr, %|pc, #(%l3 - . -8)\", operands);
5590 output_asm_insn (\"mov%?\\t%|lr, %|pc\\t%@ protect cc\", operands);
5592 output_asm_insn (\"sub%?\\t%|lr, %|lr, #(4 + . -%l3)\", operands);
5594 output_asm_insn (\"add%?\\t%|lr, %|lr, #(%l3 - . -4)\", operands);
5596 return \"b%?\\t%a1\";
5598 [(set_attr "type" "call")
5599 (set (attr "length")
5600 (if_then_else (eq_attr "prog_mode" "prog32")
5606 (if_then_else (match_operator 0 "comparison_operator"
5607 [(match_operator:SI 1 "shift_operator"
5608 [(match_operand:SI 2 "s_register_operand" "r")
5609 (match_operand:SI 3 "reg_or_int_operand" "rM")])
5610 (match_operand:SI 4 "s_register_operand" "r")])
5611 (label_ref (match_operand 5 "" ""))
5616 (compare:CC (match_dup 4)
5617 (match_op_dup 1 [(match_dup 2) (match_dup 3)])))
5619 (if_then_else (match_op_dup 0 [(reg 24) (const_int 0)])
5620 (label_ref (match_dup 5))
5623 operands[0] = gen_rtx (swap_condition (GET_CODE (operands[0])), VOIDmode,
5624 operands[1], operands[2]);
5628 [(set (match_operand:SI 0 "s_register_operand" "")
5629 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
5631 (neg:SI (match_operator:SI 2 "comparison_operator"
5632 [(match_operand:SI 3 "s_register_operand" "")
5633 (match_operand:SI 4 "arm_rhs_operand" "")]))))
5634 (clobber (match_operand:SI 5 "s_register_operand" ""))]
5636 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
5637 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5641 ;; This pattern can be used because cc_noov mode implies that the following
5642 ;; branch will be an equality (EQ or NE), so the sign extension is not
5643 ;; needed. Combine doesn't eliminate these because by the time it sees the
5644 ;; branch it no-longer knows that the data came from memory.
5646 (define_insn "*loadqi_compare"
5647 [(set (reg:CC_NOOV 24)
5649 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "m") 0)
5651 (match_operand 1 "immediate_operand" "I")))
5652 (clobber (match_scratch:SI 2 "=r"))]
5653 "((unsigned long) INTVAL (operands[1]))
5654 == (((unsigned long) INTVAL (operands[1])) >> 24) << 24"
5656 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
5657 output_asm_insn (\"ldr%?b\\t%2, %0\", operands);
5658 output_asm_insn (\"cmp%?\\t%2, %1\", operands);
5661 [(set_attr "conds" "set")
5662 (set_attr "length" "8")
5663 (set_attr "type" "load")])
5665 (define_expand "prologue"
5666 [(clobber (const_int 0))]
5669 arm_expand_prologue ();
5673 ;; This split is only used during output to reduce the number of patterns
5674 ;; that need assembler instructions adding to them. We allowed the setting
5675 ;; of the conditions to be implicit during rtl generation so that
5676 ;; the conditional compare patterns would work. However this conflicts to
5677 ;; some extend with the conditional data operations, so we have to split them
5681 [(set (match_operand:SI 0 "s_register_operand" "")
5682 (if_then_else:SI (match_operator 1 "comparison_operator"
5683 [(match_operand 2 "" "") (match_operand 3 "" "")])
5684 (match_operand 4 "" "")
5685 (match_operand 5 "" "")))
5688 [(set (match_dup 6) (match_dup 7))
5690 (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
5695 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
5698 operands[6] = gen_rtx (REG, mode, 24);
5699 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
5704 (define_insn "*cond_move_not"
5705 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5706 (if_then_else:SI (match_operator 4 "comparison_operator"
5707 [(match_operand 3 "reversible_cc_register" "")
5709 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5711 (match_operand:SI 2 "s_register_operand" "r,r"))))]
5715 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
5716 [(set_attr "conds" "use")
5717 (set_attr "length" "4,8")])
5719 ;; The next two patterns occur when an AND operation is followed by a
5720 ;; scc insn sequence
5722 (define_insn "*sign_extract_onebit"
5723 [(set (match_operand:SI 0 "s_register_operand" "=r")
5724 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
5726 (match_operand:SI 2 "immediate_operand" "n")))]
5729 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
5730 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
5731 return \"mvnne\\t%0, #0\";
5733 [(set_attr "conds" "clob")
5734 (set_attr "length" "8")])
5736 (define_insn "*not_signextract_onebit"
5737 [(set (match_operand:SI 0 "s_register_operand" "=r")
5739 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
5741 (match_operand:SI 2 "immediate_operand" "n"))))]
5744 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
5745 output_asm_insn (\"tst\\t%1, %2\", operands);
5746 output_asm_insn (\"mvneq\\t%0, #0\", operands);
5747 return \"movne\\t%0, #0\";
5749 [(set_attr "conds" "clob")
5750 (set_attr "length" "12")])
5752 ;; Push multiple registers to the stack. The first register is in the
5753 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
5755 (define_insn "*push_multi"
5756 [(match_parallel 2 "multi_register_push"
5757 [(set (match_operand:BLK 0 "memory_operand" "=m")
5758 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
5764 extern int lr_save_eliminated;
5766 if (lr_save_eliminated)
5768 if (XVECLEN (operands[2], 0) > 1)
5772 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
5773 for (i = 1; i < XVECLEN (operands[2], 0); i++)
5775 strcat (pattern, \", %|\");
5776 strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
5779 strcat (pattern, \"}\");
5780 output_asm_insn (pattern, operands);
5783 [(set_attr "type" "store4")])
5785 ;; Special patterns for dealing with the constant pool
5787 (define_insn "consttable_4"
5788 [(unspec_volatile [(match_operand 0 "" "")] 2)]
5792 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
5796 union real_extract u;
5797 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
5798 assemble_real (u.d, GET_MODE (operands[0]));
5802 assemble_integer (operands[0], 4, 1);
5807 [(set_attr "length" "4")])
5809 (define_insn "consttable_8"
5810 [(unspec_volatile [(match_operand 0 "" "")] 3)]
5814 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
5818 union real_extract u;
5819 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
5820 assemble_real (u.d, GET_MODE (operands[0]));
5824 assemble_integer (operands[0], 8, 1);
5829 [(set_attr "length" "8")])
5831 (define_insn "consttable_end"
5832 [(unspec_volatile [(const_int 0)] 4)]
5839 (define_insn "align_4"
5840 [(unspec_volatile [(const_int 0)] 5)]
5843 readonly_data_section ();
5844 assemble_align (32);