1 ;;- Machine description Acorn RISC Machine for GNU compiler
2 ;; Copyright (C) 1991, 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA.
23 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
25 ;; Every template must be output by arm_output_asm_insn, since this keeps
26 ;; track of the offset of labels within the text segment. This is needed to
27 ;; to be able to (correctly) output instructions for loading a value from a
28 ;; function's constant pool, since different instructions are needed when the
29 ;; constant pool is more than 4095 bytes away from the PC.
31 ;; There are patterns in this file to support XFmode arithmetic.
32 ;; Unfortunately RISCiX doesn't work well with these so they are disabled.
36 ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
37 ;; the mode is MODE_FLOAT
38 ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
39 ;; the mode is MODE_FLOAT
43 ; condition codes: this one is used by final_prescan_insn to speed up
44 ; conditionalizing instructions. It saves having to scan the rtl to see if
45 ; it uses or alters the condition codes.
47 ; USE means that the condition codes are used by the insn in the process of
48 ; outputting code, this means (at present) that we can't use the insn in
51 ; SET means that the purpose of the insn is to set the condition codes in a
52 ; well defined manner.
54 ; CLOB means that the condition codes are altered in an undefined manner, if
55 ; they are altered at all
57 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
58 ; but are if the branch wasn't taken; the effect is to limit the branch
59 ; elimination scanning.
61 ; NOCOND means that the condition codes are niether altered nor affect the
64 (define_attr "conds" "use,set,clob,jump_clob,nocond"
65 (const_string "nocond"))
67 ; CPU attribute is used to determine whether condition codes are clobbered
68 ; by a call insn: on the arm6 they are if in 32-bit addressing mode; on the
69 ; arm2 and arm3 the condition codes are restored by the return.
71 (define_attr "cpu" "arm2,arm3,arm6" (const (symbol_ref "arm_cpu_attr")))
73 ; LENGTH, all instructions are 4 bytes
74 (define_attr "length" "" (const_int 1))
76 ; An assembler sequence may clobber the condition codes without us knowing
77 (define_asm_attributes
78 [(set_attr "conds" "clob")
79 (set_attr "length" "1")])
81 ; TYPE attribute is used to detect floating point instructions which, if
82 ; running on a co-processor can run in parallel with other, basic instructions
83 ; If write-buffer scheduling is enabled then it can also be used in the
84 ; scheduling of writes.
86 ; Classification of each insn
87 ; normal any data instruction that doesn't hit memory or fp regs
88 ; block blockage insn, this blocks all functional units
89 ; float a floating point arithmetic operation (subject to expansion)
90 ; float_em a floating point arithmetic operation that is normally emulated
91 ; f_load a floating point load from memory
92 ; f_store a floating point store to memory
93 ; f_mem_r a transfer of a floating point register to a real reg via mem
94 ; r_mem_f the reverse of f_mem_r
95 ; f_2_r fast transfer float to arm (no memory needed)
96 ; r_2_f fast transfer arm to float
97 ; call a subroutine call
98 ; load any load from memory
99 ; store1 store 1 word to memory from arm registers
100 ; store2 store 2 words
101 ; store3 store 3 words
102 ; store4 store 4 words
105 "normal,block,float,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4"
106 (const_string "normal"))
108 (define_attr "write_conflict" "no,yes"
109 (if_then_else (eq_attr "type"
110 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
112 (const_string "no")))
114 ; The write buffer on some of the arm6 processors is hard to model exactly.
115 ; There is room in the buffer for up to two addresses and up to eight words
116 ; of memory, but the two needn't be split evenly. When writing the two
117 ; addresses are fully pipelined. However, a read from memory that is not
118 ; currently in the cache will block until the writes have completed.
119 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
120 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
121 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
122 ; cycle to add as well.
124 ;; (define_function_unit {name} {num-units} {n-users} {test}
125 ;; {ready-delay} {issue-delay} [{conflict-list}])
126 ;; This is not well tuned, but I don't have all the details.
127 (define_function_unit "fpa" 1 1 (eq_attr "type" "float") 5 0)
129 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store1") 3 3
130 [(eq_attr "write_conflict" "yes")])
131 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store2") 5 5
132 [(eq_attr "write_conflict" "yes")])
133 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store3") 7 7
134 [(eq_attr "write_conflict" "yes")])
135 (define_function_unit "write_buf" 1 2 (eq_attr "type" "store4") 9 9
136 [(eq_attr "write_conflict" "yes")])
137 (define_function_unit "write_buf" 1 2 (eq_attr "type" "r_mem_f") 3 3
138 [(eq_attr "write_conflict" "yes")])
140 ;; Note: For DImode insns, there is normally no reason why operands should
141 ;; not be in the same register, what we don't want is for something being
142 ;; written to partially overlap something that is an input.
146 (define_insn "adddi3"
147 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
148 (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
149 (match_operand:DI 2 "s_register_operand" "r,0")))
150 (clobber (reg:CC 24))]
153 arm_output_asm_insn (\"adds\\t%0, %1, %2\", operands);
154 return (arm_output_asm_insn (\"adc\\t%R0, %R1, %R2\", operands));
156 [(set_attr "conds" "clob")
157 (set_attr "length" "2")])
160 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
161 (plus:DI (sign_extend:DI
162 (match_operand:SI 1 "s_register_operand" "r,r"))
163 (match_operand:DI 2 "s_register_operand" "r,0")))
164 (clobber (reg:CC 24))]
167 arm_output_asm_insn (\"adds\\t%0, %2, %1\", operands);
168 return (arm_output_asm_insn (\"adc\\t%R0, %R2, %1, asr #31\", operands));
170 [(set_attr "conds" "clob")
171 (set_attr "length" "2")])
174 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
175 (plus:DI (zero_extend:DI
176 (match_operand:SI 1 "s_register_operand" "r,r"))
177 (match_operand:DI 2 "s_register_operand" "r,0")))
178 (clobber (reg:CC 24))]
181 arm_output_asm_insn (\"adds\\t%0, %2, %1\", operands);
182 return (arm_output_asm_insn (\"adc\\t%R0, %R2, #0\", operands));
184 [(set_attr "conds" "clob")
185 (set_attr "length" "2")])
187 (define_insn "addsi3"
188 [(set (match_operand:SI 0 "s_register_operand" "=r")
189 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
190 (match_operand:SI 2 "arm_add_operand" "rL")))]
193 if (GET_CODE (operands[2]) == CONST_INT
194 && !const_ok_for_arm (INTVAL (operands[2])))
196 operands[2] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[2]));
197 return arm_output_asm_insn (\"sub\\t%0, %1, %2\", operands);
199 return arm_output_asm_insn (\"add\\t%0, %1, %2\", operands);
203 [(set (reg:CC_NOOV 24)
204 (compare:CC_NOOV (plus:SI (match_operand:SI 1 "s_register_operand" "r")
205 (match_operand:SI 2 "arm_add_operand" "rL"))
207 (set (match_operand:SI 0 "s_register_operand" "=r")
208 (plus:SI (match_dup 1) (match_dup 2)))]
211 if (GET_CODE (operands[2]) == CONST_INT
212 && !const_ok_for_arm (INTVAL (operands[2])))
214 operands[2] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[2]));
215 return arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
217 return (arm_output_asm_insn (\"adds\\t%0, %1, %2\", operands));
219 [(set_attr "conds" "set")])
223 (compare:CC (match_operand:SI 1 "s_register_operand" "r")
224 (neg:SI (match_operand:SI 2 "arm_add_operand" "rL"))))
225 (set (match_operand:SI 0 "s_register_operand" "=r")
226 (plus:SI (match_dup 1) (match_dup 2)))]
229 if (GET_CODE (operands[2]) == CONST_INT
230 && !const_ok_for_arm (INTVAL (operands[2])))
232 operands[2] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[2]));
233 return arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
235 return (arm_output_asm_insn (\"adds\\t%0, %1, %2\", operands));
237 [(set_attr "conds" "set")])
239 (define_insn "incscc"
240 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
241 (plus:SI (match_operator:SI 2 "comparison_operator"
242 [(reg 24) (const_int 0)])
243 (match_operand:SI 1 "s_register_operand" "0,?r")))]
246 if (which_alternative == 1)
247 arm_output_asm_insn (\"mov%D2\\t%0, %1\", operands);
248 return arm_output_asm_insn (\"add%d2\\t%0, %1, #1\", operands);
250 [(set_attr "conds" "use")
251 (set_attr "length" "*,2")])
253 ; If a constant is too big to fit in a single instruction then the constant
254 ; will be pre-loaded into a register taking at least two insns, we might be
255 ; able to merge it with an add, but it depends on the exact value.
258 [(set (match_operand:SI 0 "s_register_operand" "=r")
259 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
260 (match_operand:SI 2 "immediate_operand" "n")))]
261 "!(const_ok_for_arm (INTVAL (operands[2]))
262 || const_ok_for_arm (-INTVAL (operands[2])))"
263 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
264 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
267 unsigned int val = (unsigned) INTVAL (operands[2]);
271 /* this code is similar to the approach followed in movsi, but it must
272 generate exactly two insns */
274 for (i = 30; i >= 0; i -= 2)
280 if (const_ok_for_arm (temp = (val & ~(255 << i))))
285 /* we might be able to do this as (larger number - small number) */
286 temp = ((val >> i) & 255) + 1;
287 if (temp > 255 && i < 24)
290 temp = ((val >> i) & 255) + 1;
292 if (const_ok_for_arm ((temp << i) - val))
295 temp = (unsigned) - (int) (i - val);
302 /* if we got here, we have found a way of doing it in two instructions.
303 the two constants are in val and temp */
304 operands[2] = GEN_INT ((int)val);
305 operands[3] = GEN_INT ((int)temp);
309 (define_insn "addsf3"
310 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
311 (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
312 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
318 switch (which_alternative)
321 return arm_output_asm_insn (\"adfs\\t%0, %1, %2\", operands);
323 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
324 r = REAL_VALUE_NEGATE (r);
325 operands[2] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[2]));
326 return arm_output_asm_insn (\"sufs\\t%0, %1, %2\", operands);
330 [(set_attr "type" "float")])
332 (define_insn "adddf3"
333 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
334 (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
335 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
341 switch (which_alternative)
344 return (arm_output_asm_insn (\"adfd\\t%0, %1, %2\", operands));
346 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
347 r = REAL_VALUE_NEGATE (r);
348 operands[2] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[2]));
349 return arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands);
353 [(set_attr "type" "float")])
356 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
357 (plus:DF (float_extend:DF
358 (match_operand:SF 1 "s_register_operand" "f,f"))
359 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
365 switch (which_alternative)
368 return (arm_output_asm_insn (\"adfd\\t%0, %1, %2\", operands));
370 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
371 r = REAL_VALUE_NEGATE (r);
372 operands[2] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[2]));
373 return arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands);
377 [(set_attr "type" "float")])
380 [(set (match_operand:DF 0 "s_register_operand" "=f")
381 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
383 (match_operand:SF 2 "s_register_operand" "f"))))]
386 return (arm_output_asm_insn (\"adfd\\t%0, %1, %2\", operands));
388 [(set_attr "type" "float")])
391 [(set (match_operand:DF 0 "s_register_operand" "=f")
392 (plus:DF (float_extend:DF
393 (match_operand:SF 1 "s_register_operand" "f"))
395 (match_operand:SF 2 "s_register_operand" "f"))))]
398 return (arm_output_asm_insn (\"adfd\\t%0, %1, %2\", operands));
400 [(set_attr "type" "float")])
402 (define_insn "addxf3"
403 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
404 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
405 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
411 switch (which_alternative)
414 return (arm_output_asm_insn (\"adfe\\t%0, %1, %2\", operands));
416 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[2]);
417 r = REAL_VALUE_NEGATE (r);
418 operands[2] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[2]));
419 return arm_output_asm_insn (\"sufe\\t%0, %1, %2\", operands);
423 [(set_attr "type" "float")])
425 (define_insn "subdi3"
426 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
427 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
428 (match_operand:DI 2 "s_register_operand" "r,0,0")))
429 (clobber (reg:CC 24))]
432 arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
433 return (arm_output_asm_insn (\"sbc\\t%R0, %R1, %R2\", operands));
435 [(set_attr "conds" "clob")
436 (set_attr "length" "2")])
439 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
440 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
442 (match_operand:SI 2 "s_register_operand" "r,r"))))
443 (clobber (reg:CC 24))]
446 arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
447 return (arm_output_asm_insn (\"sbc\\t%R0, %R1, #0\", operands));
449 [(set_attr "conds" "clob")
450 (set_attr "length" "2")])
453 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
454 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
456 (match_operand:SI 2 "s_register_operand" "r,r"))))
457 (clobber (reg:CC 24))]
460 arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
461 return (arm_output_asm_insn (\"sbc\\t%R0, %R1, %2, asr #31\", operands));
463 [(set_attr "conds" "clob")
464 (set_attr "length" "2")])
467 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
468 (minus:DI (zero_extend:DI
469 (match_operand:SI 2 "s_register_operand" "r,r"))
470 (match_operand:DI 1 "s_register_operand" "?r,0")))
471 (clobber (reg:CC 24))]
474 arm_output_asm_insn (\"rsbs\\t%0, %1, %2\", operands);
475 return (arm_output_asm_insn (\"rsc\\t%R0, %R1, #0\", operands));
477 [(set_attr "conds" "clob")
478 (set_attr "length" "2")])
481 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
482 (minus:DI (sign_extend:DI
483 (match_operand:SI 2 "s_register_operand" "r,r"))
484 (match_operand:DI 1 "s_register_operand" "?r,0")))
485 (clobber (reg:CC 24))]
488 arm_output_asm_insn (\"rsbs\\t%0, %1, %2\", operands);
489 return (arm_output_asm_insn (\"rsc\\t%R0, %R1, %2, asr #31\", operands));
491 [(set_attr "conds" "clob")
492 (set_attr "length" "2")])
495 [(set (match_operand:DI 0 "s_register_operand" "=r")
496 (minus:DI (zero_extend:DI
497 (match_operand:SI 1 "s_register_operand" "r"))
499 (match_operand:SI 2 "s_register_operand" "r"))))
500 (clobber (reg:CC 24))]
503 arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
504 return (arm_output_asm_insn (\"rsc\\t%R0, %1, %1 @ extend carry\",
507 [(set_attr "conds" "clob")
508 (set_attr "length" "2")])
510 (define_insn "subsi3"
511 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
512 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
513 (match_operand:SI 2 "arm_rhs_operand" "rI,r")))]
516 switch (which_alternative)
519 return (arm_output_asm_insn (\"sub\\t%0, %1, %2\", operands));
521 return (arm_output_asm_insn (\"rsb\\t%0, %2, %1\", operands));
526 [(set (reg:CC_NOOV 24)
527 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
528 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
530 (set (match_operand:SI 0 "s_register_operand" "=r,r")
531 (minus:SI (match_dup 1) (match_dup 2)))]
534 switch (which_alternative)
537 return arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
539 return arm_output_asm_insn (\"rsbs\\t%0, %2, %1\", operands);
542 [(set_attr "conds" "set")])
544 (define_insn "decscc"
545 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
546 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
547 (match_operator:SI 2 "comparison_operator"
548 [(reg 24) (const_int 0)])))]
551 if (which_alternative == 1)
552 arm_output_asm_insn (\"mov%D2\\t%0, %1\", operands);
553 return arm_output_asm_insn (\"sub%d2\\t%0, %1, #1\", operands);
555 [(set_attr "conds" "use")
556 (set_attr "length" "*,2")])
558 (define_insn "subsf3"
559 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
560 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
561 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
564 switch (which_alternative)
567 return (arm_output_asm_insn (\"sufs\\t%0, %1, %2\", operands));
569 return (arm_output_asm_insn (\"rsfs\\t%0, %2, %1\", operands));
572 [(set_attr "type" "float")])
574 (define_insn "subdf3"
575 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
576 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
577 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
580 switch (which_alternative)
583 return (arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands));
585 return (arm_output_asm_insn (\"rsfd\\t%0, %2, %1\", operands));
588 [(set_attr "type" "float")])
591 [(set (match_operand:DF 0 "s_register_operand" "=f")
592 (minus:DF (float_extend:DF
593 (match_operand:SF 1 "s_register_operand" "f"))
594 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
597 return arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands);
599 [(set_attr "type" "float")])
602 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
603 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
605 (match_operand:SF 2 "s_register_operand" "f,f"))))]
608 switch (which_alternative)
611 return (arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands));
613 return (arm_output_asm_insn (\"rsfd\\t%0, %2, %1\", operands));
616 [(set_attr "type" "float")])
619 [(set (match_operand:DF 0 "s_register_operand" "=f")
620 (minus:DF (float_extend:DF
621 (match_operand:SF 1 "s_register_operand" "f"))
623 (match_operand:SF 2 "s_register_operand" "f"))))]
626 return arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands);
628 [(set_attr "type" "float")])
630 (define_insn "subxf3"
631 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
632 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
633 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
636 switch (which_alternative)
639 return (arm_output_asm_insn (\"sufe\\t%0, %1, %2\", operands));
641 return (arm_output_asm_insn (\"rsfe\\t%0, %2, %1\", operands));
644 [(set_attr "type" "float")])
646 ;; Multiplication insns
648 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
649 (define_insn "mulsi3"
650 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
651 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
652 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
655 return (arm_output_asm_insn (\"mul\\t%0, %2, %1\", operands));
659 [(set (reg:CC_NOOV 24)
660 (compare:CC_NOOV (mult:SI
661 (match_operand:SI 2 "s_register_operand" "r,r")
662 (match_operand:SI 1 "s_register_operand" "%?r,0"))
664 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
665 (mult:SI (match_dup 2) (match_dup 1)))]
668 return (arm_output_asm_insn (\"muls\\t%0, %2, %1\", operands));
670 [(set_attr "conds" "set")])
673 [(set (reg:CC_NOOV 24)
674 (compare:CC_NOOV (mult:SI
675 (match_operand:SI 2 "s_register_operand" "r,r")
676 (match_operand:SI 1 "s_register_operand" "%?r,0"))
678 (clobber (match_scratch:SI 0 "=&r,&r"))]
681 return (arm_output_asm_insn (\"muls\\t%0, %2, %1\", operands));
683 [(set_attr "conds" "set")])
685 ;; Unnamed templates to match MLA instruction.
688 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
690 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
691 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
692 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
695 return (arm_output_asm_insn (\"mla\\t%0, %2, %1, %3\", operands));
699 [(set (reg:CC_NOOV 24)
700 (compare:CC_NOOV (plus:SI
702 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
703 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
704 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
706 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
707 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
711 return (arm_output_asm_insn (\"mlas\\t%0, %2, %1, %3\", operands));
713 [(set_attr "conds" "set")])
716 [(set (reg:CC_NOOV 24)
717 (compare:CC_NOOV (plus:SI
719 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
720 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
721 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
723 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
726 return (arm_output_asm_insn (\"mlas\\t%0, %2, %1, %3\", operands));
728 [(set_attr "conds" "set")])
730 (define_insn "mulsf3"
731 [(set (match_operand:SF 0 "s_register_operand" "=f")
732 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
733 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
736 return (arm_output_asm_insn (\"fmls\\t%0, %1, %2\", operands));
738 [(set_attr "type" "float")])
740 (define_insn "muldf3"
741 [(set (match_operand:DF 0 "s_register_operand" "=f")
742 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
743 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
746 return (arm_output_asm_insn (\"mufd\\t%0, %1, %2\", operands));
748 [(set_attr "type" "float")])
751 [(set (match_operand:DF 0 "s_register_operand" "=f")
752 (mult:DF (float_extend:DF
753 (match_operand:SF 1 "s_register_operand" "f"))
754 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
757 return (arm_output_asm_insn (\"mufd\\t%0, %1, %2\", operands));
759 [(set_attr "type" "float")])
762 [(set (match_operand:DF 0 "s_register_operand" "=f")
763 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
765 (match_operand:SF 2 "s_register_operand" "f"))))]
768 return (arm_output_asm_insn (\"mufd\\t%0, %1, %2\", operands));
770 [(set_attr "type" "float")])
773 [(set (match_operand:DF 0 "s_register_operand" "=f")
774 (mult:DF (float_extend:DF
775 (match_operand:SF 1 "s_register_operand" "f"))
777 (match_operand:SF 2 "s_register_operand" "f"))))]
780 return (arm_output_asm_insn (\"mufd\\t%0, %1, %2\", operands));
782 [(set_attr "type" "float")])
784 (define_insn "mulxf3"
785 [(set (match_operand:XF 0 "s_register_operand" "=f")
786 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
787 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
790 return (arm_output_asm_insn (\"mufe\\t%0, %1, %2\", operands));
792 [(set_attr "type" "float")])
796 (define_insn "divsf3"
797 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
798 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
799 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
802 switch (which_alternative)
805 return (arm_output_asm_insn (\"fdvs\\t%0, %1, %2\", operands));
807 return (arm_output_asm_insn (\"frds\\t%0, %2, %1\", operands));
810 [(set_attr "type" "float")])
812 (define_insn "divdf3"
813 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
814 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
815 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
818 switch (which_alternative)
821 return (arm_output_asm_insn (\"dvfd\\t%0, %1, %2\", operands));
823 return (arm_output_asm_insn (\"rdfd\\t%0, %2, %1\", operands));
826 [(set_attr "type" "float")])
829 [(set (match_operand:DF 0 "s_register_operand" "=f")
830 (div:DF (float_extend:DF
831 (match_operand:SF 1 "s_register_operand" "f"))
832 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
835 return (arm_output_asm_insn (\"dvfd\\t%0, %1, %2\", operands));
837 [(set_attr "type" "float")])
840 [(set (match_operand:DF 0 "s_register_operand" "=f")
841 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
843 (match_operand:SF 2 "s_register_operand" "f"))))]
846 return (arm_output_asm_insn (\"rdfd\\t%0, %2, %1\", operands));
848 [(set_attr "type" "float")])
851 [(set (match_operand:DF 0 "s_register_operand" "=f")
852 (div:DF (float_extend:DF
853 (match_operand:SF 1 "s_register_operand" "f"))
855 (match_operand:SF 2 "s_register_operand" "f"))))]
858 return (arm_output_asm_insn (\"dvfd\\t%0, %1, %2\", operands));
860 [(set_attr "type" "float")])
862 (define_insn "divxf3"
863 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
864 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
865 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
868 switch (which_alternative)
871 return (arm_output_asm_insn (\"dvfe\\t%0, %1, %2\", operands));
873 return (arm_output_asm_insn (\"rdfe\\t%0, %2, %1\", operands));
876 [(set_attr "type" "float")])
880 (define_insn "modsf3"
881 [(set (match_operand:SF 0 "s_register_operand" "=f")
882 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
883 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
886 return (arm_output_asm_insn (\"rmfs\\t%0, %1, %2\", operands));
888 [(set_attr "type" "float")])
890 (define_insn "moddf3"
891 [(set (match_operand:DF 0 "s_register_operand" "=f")
892 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
893 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
896 return (arm_output_asm_insn (\"rmfd\\t%0, %1, %2\", operands));
898 [(set_attr "type" "float")])
901 [(set (match_operand:DF 0 "s_register_operand" "=f")
902 (mod:DF (float_extend:DF
903 (match_operand:SF 1 "s_register_operand" "f"))
904 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
907 return (arm_output_asm_insn (\"rmfd\\t%0, %1, %2\", operands));
909 [(set_attr "type" "float")])
912 [(set (match_operand:DF 0 "s_register_operand" "=f")
913 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
915 (match_operand:SF 2 "s_register_operand" "f"))))]
918 return (arm_output_asm_insn (\"rmfd\\t%0, %1, %2\", operands));
920 [(set_attr "type" "float")])
923 [(set (match_operand:DF 0 "s_register_operand" "=f")
924 (mod:DF (float_extend:DF
925 (match_operand:SF 1 "s_register_operand" "f"))
927 (match_operand:SF 2 "s_register_operand" "f"))))]
930 return (arm_output_asm_insn (\"rmfd\\t%0, %1, %2\", operands));
932 [(set_attr "type" "float")])
934 (define_insn "modxf3"
935 [(set (match_operand:XF 0 "s_register_operand" "=f")
936 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
937 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
940 return (arm_output_asm_insn (\"rmfe\\t%0, %1, %2\", operands));
942 [(set_attr "type" "float")])
944 ;; Boolean and,ior,xor insns
946 (define_insn "anddi3"
947 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
948 (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
949 (match_operand:DI 2 "s_register_operand" "r,0")))]
952 arm_output_asm_insn (\"and\\t%0, %1, %2\", operands);
953 return (arm_output_asm_insn (\"and\\t%R0, %R1, %R2\", operands));
955 [(set_attr "length" "2")])
958 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
959 (and:DI (zero_extend:DI
960 (match_operand:SI 2 "s_register_operand" "r,r"))
961 (match_operand:DI 1 "s_register_operand" "?r,0")))]
964 arm_output_asm_insn (\"and\\t%0, %1, %2\", operands);
965 return arm_output_asm_insn (\"mov\\t%R0, #0\", operands);
967 [(set_attr "length" "2")])
970 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
971 (and:DI (sign_extend:DI
972 (match_operand:SI 2 "s_register_operand" "r,r"))
973 (match_operand:DI 1 "s_register_operand" "?r,0")))]
976 arm_output_asm_insn (\"and\\t%0, %1, %2\", operands);
977 return arm_output_asm_insn (\"and\\t%R0, %R1, %2, asr #31\", operands);
979 [(set_attr "length" "2")])
981 (define_insn "andsi3"
982 [(set (match_operand:SI 0 "s_register_operand" "=r")
983 (and:SI (match_operand:SI 1 "s_register_operand" "r")
984 (match_operand:SI 2 "arm_not_operand" "rK")))]
987 if (GET_CODE (operands[2]) == CONST_INT
988 && !const_ok_for_arm (INTVAL (operands[2])))
990 operands[2] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
991 return arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands);
993 return arm_output_asm_insn (\"and\\t%0, %1, %2\", operands);
997 [(set (reg:CC_NOOV 24)
998 (compare:CC_NOOV (and:SI (match_operand:SI 1 "s_register_operand" "r")
999 (match_operand:SI 2 "arm_not_operand" "rK"))
1001 (set (match_operand:SI 0 "s_register_operand" "=r")
1002 (and:SI (match_dup 1) (match_dup 2)))]
1005 if (GET_CODE (operands[2]) == CONST_INT
1006 && !const_ok_for_arm (INTVAL (operands[2])))
1008 operands[2] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]));
1009 return arm_output_asm_insn (\"bics\\t%0, %1, %2\", operands);
1011 return arm_output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1013 [(set_attr "conds" "set")])
1016 [(set (reg:CC_NOOV 24)
1017 (compare:CC_NOOV (and:SI (match_operand:SI 0 "s_register_operand" "r")
1018 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1022 return arm_output_asm_insn (\"tst\\t%0, %1\", operands);
1024 [(set_attr "conds" "set")])
1027 [(set (reg:CC_NOOV 24)
1028 (compare:CC_NOOV (and:SI (match_operand:SI 0 "s_register_operand" "r")
1029 (match_operand:SI 1 "immediate_operand" "K"))
1031 (clobber (match_scratch:SI 3 "=r"))]
1032 "const_ok_for_arm (~INTVAL (operands[1]))"
1034 operands[1] = GEN_INT (~INTVAL (operands[1]));
1035 return arm_output_asm_insn (\"bics\\t%3, %0, %1\", operands);
1037 [(set_attr "conds" "set")])
1040 [(set (reg:CC_NOOV 24)
1041 (compare:CC_NOOV (zero_extract:SI
1042 (match_operand:SI 0 "s_register_operand" "r")
1043 (match_operand:SI 1 "immediate_operand" "n")
1044 (match_operand:SI 2 "immediate_operand" "n"))
1046 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1047 && INTVAL (operands[1]) > 0
1048 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1049 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1052 unsigned int mask = 0;
1053 int cnt = INTVAL (operands[1]);
1056 mask = (mask << 1) | 1;
1057 operands[1] = gen_rtx (CONST_INT, VOIDmode, mask << INTVAL (operands[2]));
1058 return arm_output_asm_insn (\"tst\\t%0, %1\", operands);
1061 [(set_attr "conds" "set")])
1064 [(set (reg:CC_NOOV 24)
1065 (compare:CC_NOOV (zero_extract:SI
1066 (match_operand:QI 0 "memory_operand" "m")
1067 (match_operand 1 "immediate_operand" "n")
1068 (match_operand 2 "immediate_operand" "n"))
1070 (clobber (match_scratch:QI 3 "=r"))]
1071 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 8
1072 && INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8"
1075 unsigned int mask = 0;
1076 int cnt = INTVAL (operands[1]);
1079 mask = (mask << 1) | 1;
1080 operands[1] = gen_rtx (CONST_INT, VOIDmode, mask << INTVAL (operands[2]));
1081 arm_output_asm_insn (\"ldrb\\t%3, %0\", operands);
1082 return arm_output_asm_insn (\"tst\\t%3, %1\", operands);
1085 [(set_attr "conds" "set")
1086 (set_attr "length" "2")])
1088 ;; constants for op 2 will never be given to these patterns.
1090 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1091 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1092 (match_operand:DI 1 "s_register_operand" "0,r")))]
1095 arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands);
1096 return arm_output_asm_insn (\"bic\\t%R0, %R1, %R2\", operands);
1098 [(set_attr "length" "2")])
1101 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1102 (and:DI (not:DI (zero_extend:DI
1103 (match_operand:SI 2 "s_register_operand" "r,r")))
1104 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1107 arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands);
1108 if (REGNO (operands[1]) != REGNO (operands[0]))
1109 return arm_output_asm_insn (\"mov\\t%R0, %R1\", operands);
1112 [(set_attr "length" "2,1")])
1115 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1116 (and:DI (not:DI (sign_extend:DI
1117 (match_operand:SI 2 "s_register_operand" "r,r")))
1118 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1121 arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands);
1122 return arm_output_asm_insn (\"bic\\t%R0, %R1, %2, asr #31\", operands);
1124 [(set_attr "length" "2")])
1127 [(set (match_operand:SI 0 "s_register_operand" "=r")
1128 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1129 (match_operand:SI 1 "s_register_operand" "r")))]
1132 return (arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands));
1136 [(set (reg:CC_NOOV 24)
1137 (compare:CC_NOOV (and:SI
1138 (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1139 (match_operand:SI 1 "s_register_operand" "r"))
1141 (set (match_operand:SI 0 "s_register_operand" "=r")
1142 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1145 return (arm_output_asm_insn (\"bics\\t%0, %1, %2\", operands));
1147 [(set_attr "conds" "set")])
1150 [(set (reg:CC_NOOV 24)
1151 (compare:CC_NOOV (and:SI
1152 (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1153 (match_operand:SI 1 "s_register_operand" "r"))
1155 (clobber (match_scratch:SI 0 "=r"))]
1158 return (arm_output_asm_insn (\"bics\\t%0, %1, %2\", operands));
1160 [(set_attr "conds" "set")])
1162 (define_insn "iordi3"
1163 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1164 (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1165 (match_operand:DI 2 "s_register_operand" "r")))]
1168 arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands);
1169 return (arm_output_asm_insn (\"orr\\t%R0, %R1, %R2\", operands));
1171 [(set_attr "length" "2")])
1174 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1175 (ior:DI (zero_extend:DI
1176 (match_operand:SI 2 "s_register_operand" "r,r"))
1177 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1180 arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands);
1181 if (REGNO (operands[0]) != REGNO (operands[1]))
1182 return (arm_output_asm_insn (\"mov\\t%R0, %R1\", operands));
1185 [(set_attr "length" "2,1")])
1188 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1189 (ior:DI (sign_extend:DI
1190 (match_operand:SI 2 "s_register_operand" "r,r"))
1191 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1194 arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands);
1195 return (arm_output_asm_insn (\"orr\\t%R0, %R1, %2, asr #31\", operands));
1197 [(set_attr "length" "2")])
1199 (define_insn "iorsi3"
1200 [(set (match_operand:SI 0 "s_register_operand" "=r")
1201 (ior:SI (match_operand:SI 1 "s_register_operand" "r")
1202 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1205 return (arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands));
1209 [(set (reg:CC_NOOV 24)
1210 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1211 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1213 (set (match_operand:SI 0 "s_register_operand" "=r")
1214 (ior:SI (match_dup 1) (match_dup 2)))]
1217 return arm_output_asm_insn (\"orrs\\t%0, %1, %2\", operands);
1219 [(set_attr "conds" "set")])
1222 [(set (reg:CC_NOOV 24)
1223 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1224 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1226 (clobber (match_scratch:SI 0 "=r"))]
1229 return arm_output_asm_insn (\"orrs\\t%0, %1, %2\", operands);
1231 [(set_attr "conds" "set")])
1233 (define_insn "xordi3"
1234 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1235 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1236 (match_operand:DI 2 "s_register_operand" "r,0")))]
1239 arm_output_asm_insn (\"eor\\t%0, %1, %2\", operands);
1240 return arm_output_asm_insn (\"eor\\t%R0, %R1, %R2\", operands);
1242 [(set_attr "length" "2")])
1245 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1246 (xor:DI (zero_extend:DI
1247 (match_operand:SI 2 "s_register_operand" "r,r"))
1248 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1251 arm_output_asm_insn (\"eor\\t%0, %1, %2\", operands);
1252 if (REGNO (operands[0]) != REGNO (operands[1]))
1253 return arm_output_asm_insn (\"mov\\t%R0, %R1\", operands);
1256 [(set_attr "length" "2,1")])
1259 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1260 (xor:DI (sign_extend:DI
1261 (match_operand:SI 2 "s_register_operand" "r,r"))
1262 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1265 arm_output_asm_insn (\"eor\\t%0, %1, %2\", operands);
1266 return arm_output_asm_insn (\"eor\\t%R0, %R1, %2, asr #31\", operands);
1268 [(set_attr "length" "2")])
1270 (define_insn "xorsi3"
1271 [(set (match_operand:SI 0 "s_register_operand" "=r")
1272 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1273 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1276 return (arm_output_asm_insn (\"eor\\t%0, %1, %2\", operands));
1280 [(set (reg:CC_NOOV 24)
1281 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1282 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1284 (set (match_operand:SI 0 "s_register_operand" "=r")
1285 (xor:SI (match_dup 1) (match_dup 2)))]
1288 return arm_output_asm_insn (\"eors\\t%0, %1, %2\", operands);
1290 [(set_attr "conds" "set")])
1293 [(set (reg:CC_NOOV 24)
1294 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1295 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1299 return arm_output_asm_insn (\"teq\\t%0, %1\", operands);
1301 [(set_attr "conds" "set")])
1303 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
1304 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1308 [(set (match_operand:SI 0 "s_register_operand" "=r")
1309 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1310 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1311 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1312 (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1314 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1315 (not:SI (match_dup 3))))
1316 (set (match_dup 0) (not:SI (match_dup 4)))]
1321 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1322 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1323 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1324 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1327 arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands);
1328 return arm_output_asm_insn (\"bic\\t%0, %0, %3\", operands);
1330 [(set_attr "length" "2")])
1334 ;; Minimum and maximum insns
1336 (define_insn "smaxsi3"
1337 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1338 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1339 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1340 (clobber (reg:CC 24))]
1343 arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
1344 if (which_alternative != 0)
1345 arm_output_asm_insn (\"movge\\t%0, %1\", operands);
1346 if (which_alternative != 1)
1347 return arm_output_asm_insn (\"movlt\\t%0, %2\", operands);
1350 [(set_attr "conds" "clob")
1351 (set_attr "length" "2,2,3")])
1353 (define_insn "sminsi3"
1354 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1355 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1356 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1357 (clobber (reg:CC 24))]
1360 arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
1361 if (which_alternative != 0)
1362 arm_output_asm_insn (\"movle\\t%0, %1\", operands);
1363 if (which_alternative != 1)
1364 return arm_output_asm_insn (\"movgt\\t%0, %2\", operands);
1367 [(set_attr "conds" "clob")
1368 (set_attr "length" "2,2,3")])
1370 (define_insn "umaxsi3"
1371 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1372 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1373 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1374 (clobber (reg:CC 24))]
1377 arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
1378 if (which_alternative != 0)
1379 arm_output_asm_insn (\"movcs\\t%0, %1\", operands);
1380 if (which_alternative != 1)
1381 return arm_output_asm_insn (\"movcc\\t%0, %2\", operands);
1384 [(set_attr "conds" "clob")
1385 (set_attr "length" "2,2,3")])
1387 (define_insn "uminsi3"
1388 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1389 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1390 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1391 (clobber (reg:CC 24))]
1394 arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
1395 if (which_alternative != 0)
1396 arm_output_asm_insn (\"movcc\\t%0, %1\", operands);
1397 if (which_alternative != 1)
1398 return arm_output_asm_insn (\"movcs\\t%0, %2\", operands);
1401 [(set_attr "conds" "clob")
1402 (set_attr "length" "2,2,3")])
1405 [(set (match_operand:SI 0 "memory_operand" "=m")
1406 (match_operator:SI 3 "minmax_operator"
1407 [(match_operand:SI 1 "s_register_operand" "r")
1408 (match_operand:SI 2 "s_register_operand" "r")]))
1409 (clobber (reg:CC 24))]
1412 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1414 arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
1415 arm_output_asm_insn (\"str%d3\\t%1, %0\", operands);
1416 return arm_output_asm_insn (\"str%D3\\t%2, %0\", operands);
1418 [(set_attr "conds" "clob")
1419 (set_attr "length" "3")
1420 (set_attr "type" "store1")])
1423 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1424 (match_operator:SI 4 "shiftable_operator"
1425 [(match_operator:SI 5 "minmax_operator"
1426 [(match_operand:SI 2 "s_register_operand" "r,r")
1427 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1428 (match_operand:SI 1 "s_register_operand" "0,?r")]))
1429 (clobber (reg:CC 24))]
1434 enum rtx_code code = GET_CODE (operands[4]);
1435 char *inst = arithmetic_instr (operands[4], TRUE);
1437 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1439 arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
1440 sprintf (buf, \"%s%%d5\\t%%0, %%1, %%2\", inst);
1441 arm_output_asm_insn (buf, operands);
1442 if (which_alternative != 0 || operands[3] != const0_rtx
1443 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1445 sprintf (buf, \"%s%%D5\\t%%0, %%1, %%3\", inst);
1446 return arm_output_asm_insn (buf, operands);
1451 [(set_attr "conds" "clob")
1452 (set_attr "length" "3")])
1455 ;; Shift and rotation insns
1457 (define_insn "ashlsi3"
1458 [(set (match_operand:SI 0 "s_register_operand" "=r")
1459 (ashift:SI (match_operand:SI 1 "s_register_operand" "r")
1460 (match_operand:SI 2 "arm_rhs_operand" "rn")))]
1463 return (output_shifted_move (ASHIFT, operands));
1466 (define_insn "ashrsi3"
1467 [(set (match_operand:SI 0 "s_register_operand" "=r")
1468 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "r")
1469 (match_operand:SI 2 "arm_rhs_operand" "rn")))]
1472 return (output_shifted_move (ASHIFTRT, operands));
1475 ;; lshlsi3 is not defined because shift counts cannot be negative
1476 ;; An unnamed pattern is needed for expansion of zero_extend.
1479 [(set (match_operand:SI 0 "s_register_operand" "=r")
1480 (lshift:SI (match_operand:SI 1 "s_register_operand" "r")
1481 (match_operand:SI 2 "arm_rhs_operand" "rn")))]
1484 return (output_shifted_move (LSHIFT, operands));
1487 (define_insn "lshrsi3"
1488 [(set (match_operand:SI 0 "s_register_operand" "=r")
1489 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "r")
1490 (match_operand:SI 2 "arm_rhs_operand" "rn")))]
1493 return (output_shifted_move (LSHIFTRT, operands));
1496 ;; rotlsi3 is not defined yet to see what happens
1498 (define_insn "rotrsi3"
1499 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1500 (rotatert:SI (match_operand:SI 1 "s_register_operand" "r,r")
1501 (match_operand:SI 2 "arm_rhs_operand" "r,n")))]
1504 switch (which_alternative)
1507 return (arm_output_asm_insn (\"mov\\t%0, %1, ror %2\", operands));
1509 if (INTVAL(operands[2]) > 31)
1510 operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) % 32);
1511 return (arm_output_asm_insn (\"mov\\t%0, %1, ror %2\", operands));
1516 [(set (reg:CC_NOOV 24)
1517 (compare:CC_NOOV (match_operator:SI 1 "shift_operator"
1518 [(match_operand:SI 2 "s_register_operand" "r")
1519 (match_operand:SI 3 "arm_rhs_operand" "rn")])
1521 (set (match_operand:SI 0 "s_register_operand" "=r")
1522 (match_op_dup 1 [(match_dup 2) (match_dup 3)]))]
1528 sprintf (buf, \"movs\\t%%0, %%2, %s %%3\",
1529 shift_instr (GET_CODE (operands[1]), &operands[3]));
1530 return arm_output_asm_insn (buf, operands);
1533 [(set_attr "conds" "set")])
1536 [(set (reg:CC_NOOV 24)
1537 (compare:CC_NOOV (match_operator:SI 1 "shift_operator"
1538 [(match_operand:SI 2 "s_register_operand" "r")
1539 (match_operand:SI 3 "arm_rhs_operand" "rn")])
1541 (clobber (match_scratch:SI 0 "=r"))]
1547 sprintf (buf, \"movs\\t%%0, %%2, %s %%3\",
1548 shift_instr (GET_CODE (operands[1]), &operands[3]));
1549 return arm_output_asm_insn (buf, operands);
1552 [(set_attr "conds" "set")])
1555 [(set (match_operand:SI 0 "s_register_operand" "=r")
1556 (not:SI (match_operator:SI 1 "shift_operator"
1557 [(match_operand:SI 2 "s_register_operand" "r")
1558 (match_operand:SI 3 "arm_rhs_operand" "rn")])))]
1563 sprintf (buf, \"mvn\\t%%0, %%2, %s %%3\",
1564 shift_instr (GET_CODE (operands[1]), &operands[3]));
1565 return arm_output_asm_insn (buf, operands);
1570 [(set (reg:CC_NOOV 24)
1571 (compare:CC_NOOV (not:SI (match_operator:SI 1 "shift_operator"
1572 [(match_operand:SI 2 "s_register_operand" "r")
1573 (match_operand:SI 3 "arm_rhs_operand" "rn")]))
1575 (set (match_operand:SI 0 "s_register_operand" "=r")
1576 (not:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])))]
1581 sprintf (buf, \"mvns\\t%%0, %%2, %s %%3\",
1582 shift_instr (GET_CODE (operands[1]), &operands[3]));
1583 return arm_output_asm_insn (buf, operands);
1586 [(set_attr "conds" "set")])
1589 [(set (reg:CC_NOOV 24)
1590 (compare:CC_NOOV (not:SI (match_operator:SI 1 "shift_operator"
1591 [(match_operand:SI 2 "s_register_operand" "r")
1592 (match_operand:SI 3 "arm_rhs_operand" "rn")]))
1594 (clobber (match_scratch:SI 0 "=r"))]
1599 sprintf (buf, \"mvns\\t%%0, %%2, %s %%3\",
1600 shift_instr (GET_CODE (operands[1]), &operands[3]));
1601 return arm_output_asm_insn (buf, operands);
1604 [(set_attr "conds" "set")])
1607 ;; Unary arithmetic insns
1609 (define_insn "negdi2"
1610 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1611 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1614 arm_output_asm_insn (\"rsbs\\t%0, %1, #0\", operands);
1615 return (arm_output_asm_insn (\"rsc\\t%R0, %R1, #0\", operands));
1617 [(set_attr "conds" "clob")
1618 (set_attr "length" "2")])
1620 (define_insn "negsi2"
1621 [(set (match_operand:SI 0 "s_register_operand" "=r")
1622 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1625 return (arm_output_asm_insn (\"rsb\\t%0, %1, #0\", operands));
1628 (define_insn "negsf2"
1629 [(set (match_operand:SF 0 "s_register_operand" "=f")
1630 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1633 return (arm_output_asm_insn (\"mnfs\\t%0, %1\", operands));
1635 [(set_attr "type" "float")])
1637 (define_insn "negdf2"
1638 [(set (match_operand:DF 0 "s_register_operand" "=f")
1639 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1642 return (arm_output_asm_insn (\"mnfd\\t%0, %1\", operands));
1644 [(set_attr "type" "float")])
1647 [(set (match_operand:DF 0 "s_register_operand" "=f")
1648 (neg:DF (float_extend:DF
1649 (match_operand:SF 1 "s_register_operand" "f"))))]
1652 return (arm_output_asm_insn (\"mnfd\\t%0, %1\", operands));
1654 [(set_attr "type" "float")])
1656 (define_insn "negxf2"
1657 [(set (match_operand:XF 0 "s_register_operand" "=f")
1658 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1659 "ENABLE_XF_PATTERNS"
1661 return (arm_output_asm_insn (\"mnfe\\t%0, %1\", operands));
1663 [(set_attr "type" "float")])
1665 ;; abssi2 doesn't really clobber the condition codes if a different register
1666 ;; is being set. To keep things simple, assume during rtl manipulations that
1667 ;; it does, but tell the final scan operator the truth. Similarly for
1670 (define_insn "abssi2"
1671 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1672 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1676 switch (which_alternative)
1679 arm_output_asm_insn (\"cmp\\t%0, #0\", operands);
1680 return arm_output_asm_insn (\"rsblt\\t%0, %0, #0\", operands);
1682 arm_output_asm_insn (\"eor\\t%0, %1, %1, asr #31\", operands);
1683 return arm_output_asm_insn (\"sub\\t%0, %0, %1, asr #31\", operands);
1686 [(set_attr "conds" "clob,*")
1687 (set_attr "length" "2")])
1690 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1691 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1695 switch (which_alternative)
1698 arm_output_asm_insn (\"cmp\\t%0, #0\", operands);
1699 return arm_output_asm_insn (\"rsbgt\\t%0, %0, #0\", operands);
1701 arm_output_asm_insn (\"eor\\t%0, %1, %1, asr #31\", operands);
1702 return arm_output_asm_insn (\"rsb\\t%0, %0, %1, asr #31\", operands);
1705 [(set_attr "conds" "clob,*")
1706 (set_attr "length" "2")])
1708 (define_insn "abssf2"
1709 [(set (match_operand:SF 0 "s_register_operand" "=f")
1710 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1713 return (arm_output_asm_insn (\"abss\\t%0, %1\", operands));
1715 [(set_attr "type" "float")])
1717 (define_insn "absdf2"
1718 [(set (match_operand:DF 0 "s_register_operand" "=f")
1719 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1722 return (arm_output_asm_insn (\"absd\\t%0, %1\", operands));
1724 [(set_attr "type" "float")])
1727 [(set (match_operand:DF 0 "s_register_operand" "=f")
1728 (abs:DF (float_extend:DF
1729 (match_operand:SF 1 "s_register_operand" "f"))))]
1732 return (arm_output_asm_insn (\"absd\\t%0, %1\", operands));
1734 [(set_attr "type" "float")])
1736 (define_insn "absxf2"
1737 [(set (match_operand:XF 0 "s_register_operand" "=f")
1738 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1739 "ENABLE_XF_PATTERNS"
1741 return (arm_output_asm_insn (\"abse\\t%0, %1\", operands));
1743 [(set_attr "type" "float")])
1745 (define_insn "sqrtsf2"
1746 [(set (match_operand:SF 0 "s_register_operand" "=f")
1747 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1750 return (arm_output_asm_insn (\"sqts\\t%0, %1\", operands));
1752 [(set_attr "type" "float_em")])
1754 (define_insn "sqrtdf2"
1755 [(set (match_operand:DF 0 "s_register_operand" "=f")
1756 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1759 return (arm_output_asm_insn (\"sqtd\\t%0, %1\", operands));
1761 [(set_attr "type" "float_em")])
1764 [(set (match_operand:DF 0 "s_register_operand" "=f")
1765 (sqrt:DF (float_extend:DF
1766 (match_operand:SF 1 "s_register_operand" "f"))))]
1769 return (arm_output_asm_insn (\"sqtd\\t%0, %1\", operands));
1771 [(set_attr "type" "float_em")])
1773 (define_insn "sqrtxf2"
1774 [(set (match_operand:XF 0 "s_register_operand" "=f")
1775 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1776 "ENABLE_XF_PATTERNS"
1778 return (arm_output_asm_insn (\"sqte\\t%0, %1\", operands));
1780 [(set_attr "type" "float_em")])
1782 (define_insn "sinsf2"
1783 [(set (match_operand:SF 0 "s_register_operand" "=f")
1784 (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1787 return arm_output_asm_insn (\"sins\\t%0, %1\", operands);
1789 [(set_attr "type" "float_em")])
1791 (define_insn "sindf2"
1792 [(set (match_operand:DF 0 "s_register_operand" "=f")
1793 (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1796 return arm_output_asm_insn (\"sind\\t%0, %1\", operands);
1798 [(set_attr "type" "float_em")])
1801 [(set (match_operand:DF 0 "s_register_operand" "=f")
1802 (unspec:DF [(float_extend:DF
1803 (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1806 return arm_output_asm_insn (\"sind\\t%0, %1\", operands);
1808 [(set_attr "type" "float_em")])
1810 (define_insn "sinxf2"
1811 [(set (match_operand:XF 0 "s_register_operand" "=f")
1812 (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1813 "ENABLE_XF_PATTERNS"
1815 return arm_output_asm_insn (\"sine\\t%0, %1\", operands);
1817 [(set_attr "type" "float_em")])
1819 (define_insn "cossf2"
1820 [(set (match_operand:SF 0 "s_register_operand" "=f")
1821 (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
1824 return arm_output_asm_insn (\"coss\\t%0, %1\", operands);
1826 [(set_attr "type" "float_em")])
1828 (define_insn "cosdf2"
1829 [(set (match_operand:DF 0 "s_register_operand" "=f")
1830 (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
1833 return arm_output_asm_insn (\"cosd\\t%0, %1\", operands);
1835 [(set_attr "type" "float_em")])
1838 [(set (match_operand:DF 0 "s_register_operand" "=f")
1839 (unspec:DF [(float_extend:DF
1840 (match_operand:SF 1 "s_register_operand" "f"))] 1))]
1843 return arm_output_asm_insn (\"cosd\\t%0, %1\", operands);
1845 [(set_attr "type" "float_em")])
1847 (define_insn "cosxf2"
1848 [(set (match_operand:XF 0 "s_register_operand" "=f")
1849 (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
1850 "ENABLE_XF_PATTERNS"
1852 return arm_output_asm_insn (\"cose\\t%0, %1\", operands);
1854 [(set_attr "type" "float_em")])
1856 (define_insn "one_cmpldi2"
1857 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1858 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1861 arm_output_asm_insn (\"mvn\\t%0, %1\", operands);
1862 return arm_output_asm_insn (\"mvn\\t%R0, %R1\", operands);
1864 [(set_attr "length" "2")])
1866 (define_insn "one_cmplsi2"
1867 [(set (match_operand:SI 0 "s_register_operand" "=r")
1868 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
1871 return (arm_output_asm_insn (\"mvn\\t%0, %1\", operands));
1875 [(set (reg:CC_NOOV 24)
1876 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1878 (set (match_operand:SI 0 "s_register_operand" "=r")
1879 (not:SI (match_dup 1)))]
1882 return (arm_output_asm_insn (\"mvns\\t%0, %1\", operands));
1884 [(set_attr "conds" "set")])
1887 [(set (reg:CC_NOOV 24)
1888 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1890 (clobber (match_scratch:SI 0 "=r"))]
1893 return (arm_output_asm_insn (\"mvns\\t%0, %1\", operands));
1895 [(set_attr "conds" "set")])
1897 ;; Fixed <--> Floating conversion insns
1899 (define_insn "floatsisf2"
1900 [(set (match_operand:SF 0 "s_register_operand" "=f")
1901 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
1904 return (arm_output_asm_insn (\"flts\\t%0, %1\", operands));
1906 [(set_attr "type" "r_2_f")])
1908 (define_insn "floatsidf2"
1909 [(set (match_operand:DF 0 "s_register_operand" "=f")
1910 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
1913 return (arm_output_asm_insn (\"fltd\\t%0, %1\", operands));
1915 [(set_attr "type" "r_2_f")])
1917 (define_insn "floatsixf2"
1918 [(set (match_operand:XF 0 "s_register_operand" "=f")
1919 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
1920 "ENABLE_XF_PATTERNS"
1922 return (arm_output_asm_insn (\"flte\\t%0, %1\", operands));
1924 [(set_attr "type" "r_2_f")])
1926 (define_insn "fix_truncsfsi2"
1927 [(set (match_operand:SI 0 "s_register_operand" "=r")
1928 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
1931 return arm_output_asm_insn (\"fixz\\t%0, %1\", operands);
1933 [(set_attr "type" "f_2_r")])
1935 (define_insn "fix_truncdfsi2"
1936 [(set (match_operand:SI 0 "s_register_operand" "=r")
1937 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
1940 return arm_output_asm_insn (\"fixz\\t%0, %1\", operands);
1942 [(set_attr "type" "f_2_r")])
1944 (define_insn "fix_truncxfsi2"
1945 [(set (match_operand:SI 0 "s_register_operand" "=r")
1946 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
1947 "ENABLE_XF_PATTERNS"
1949 return arm_output_asm_insn (\"fixz\\t%0, %1\", operands);
1951 [(set_attr "type" "f_2_r")])
1955 (define_insn "truncdfsf2"
1956 [(set (match_operand:SF 0 "s_register_operand" "=f")
1958 (match_operand:DF 1 "s_register_operand" "f")))]
1961 return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands));
1963 [(set_attr "type" "float")])
1965 (define_insn "truncxfsf2"
1966 [(set (match_operand:SF 0 "s_register_operand" "=f")
1968 (match_operand:XF 1 "s_register_operand" "f")))]
1969 "ENABLE_XF_PATTERNS"
1971 return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands));
1973 [(set_attr "type" "float")])
1975 (define_insn "truncxfdf2"
1976 [(set (match_operand:DF 0 "s_register_operand" "=f")
1978 (match_operand:XF 1 "s_register_operand" "f")))]
1979 "ENABLE_XF_PATTERNS"
1981 return (arm_output_asm_insn (\"mvfd\\t%0, %1\", operands));
1983 [(set_attr "type" "float")])
1985 ;; Zero and sign extension instructions.
1987 (define_insn "zero_extendsidi2"
1988 [(set (match_operand:DI 0 "s_register_operand" "=r")
1989 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
1992 if (REGNO (operands[1]) != REGNO (operands[0]))
1993 arm_output_asm_insn (\"mov\\t%0, %1\", operands);
1994 return arm_output_asm_insn (\"mov\\t%R0, #0\", operands);
1996 [(set_attr "length" "2")])
1998 (define_insn "zero_extendqidi2"
1999 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2000 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2003 switch (which_alternative)
2006 arm_output_asm_insn (\"and\\t%0, %1, #255\", operands);
2009 arm_output_asm_insn (\"ldrb\\t%0, %1\",operands);
2012 return arm_output_asm_insn (\"mov\\t%R0, #0\", operands);
2014 [(set_attr "length" "2")
2015 (set_attr "type" "*,load")])
2017 (define_insn "extendsidi2"
2018 [(set (match_operand:DI 0 "s_register_operand" "=r")
2019 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2022 if (REGNO (operands[1]) != REGNO (operands[0]))
2023 arm_output_asm_insn (\"mov\\t%0, %1\", operands);
2024 return arm_output_asm_insn (\"mov\\t%R0, %0, asr #31\", operands);
2026 [(set_attr "length" "2")])
2028 (define_expand "zero_extendhisi2"
2030 (ashift:SI (match_operand:HI 1 "s_register_operand" "")
2032 (set (match_operand:SI 0 "s_register_operand" "")
2033 (lshiftrt:SI (match_dup 2)
2037 { operands[1] = gen_lowpart (SImode, operands[1]);
2038 operands[2] = gen_reg_rtx (SImode); }")
2040 (define_insn "zero_extendqihi2"
2041 [(set (match_operand:HI 0 "s_register_operand" "=r")
2043 (match_operand:QI 1 "s_register_operand" "r")))]
2046 return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ zero_extendqihi2\", operands));
2050 [(set (reg:CC_NOOV 24)
2051 (compare:CC_NOOV (match_operand:QI 1 "s_register_operand" "r")
2053 (set (match_operand:SI 0 "s_register_operand" "=r")
2054 (zero_extend:HI (match_dup 1)))]
2057 return arm_output_asm_insn (\"ands\\t%0, %1, #255\", operands);
2059 [(set_attr "conds" "set")])
2062 [(set (reg:CC_NOOV 24)
2063 (compare:CC_NOOV (match_operand:QI 0 "s_register_operand" "r")
2067 return arm_output_asm_insn (\"tst\\t%0, #255\", operands);
2069 [(set_attr "conds" "set")])
2071 (define_insn "zero_extendqisi2"
2072 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2074 (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2077 switch (which_alternative)
2080 return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ zero_extendqisi2\", operands));
2082 return (arm_output_asm_insn (\"ldrb\\t%0, %1\\t@ zero_extendqisi2\", operands));
2085 [(set_attr "type" "*,load")])
2088 [(set (reg:CC_NOOV 24)
2089 (compare:CC_NOOV (match_operand:QI 1 "s_register_operand" "r")
2091 (set (match_operand:SI 0 "s_register_operand" "=r")
2092 (zero_extend:SI (match_dup 1)))]
2095 return arm_output_asm_insn (\"ands\\t%0, %1, #255\", operands);
2097 [(set_attr "conds" "set")])
2100 [(set (reg:CC_NOOV 24)
2101 (compare:CC_NOOV (match_operand:QI 1 "s_register_operand" "r")
2103 (set (match_operand:QI 0 "s_register_operand" "=r")
2107 return arm_output_asm_insn (\"ands\\t%0, %1, #255\", operands);
2109 [(set_attr "conds" "set")])
2111 (define_expand "extendhisi2"
2113 (ashift:SI (match_operand:HI 1 "s_register_operand" "")
2115 (set (match_operand:SI 0 "s_register_operand" "")
2116 (ashiftrt:SI (match_dup 2)
2120 { operands[1] = gen_lowpart (SImode, operands[1]);
2121 operands[2] = gen_reg_rtx (SImode); }")
2123 (define_expand "extendqihi2"
2125 (ashift:SI (match_operand:QI 1 "s_register_operand" "")
2127 (set (match_operand:HI 0 "s_register_operand" "")
2128 (ashiftrt:SI (match_dup 2)
2132 { operands[0] = gen_lowpart (SImode, operands[0]);
2133 operands[1] = gen_lowpart (SImode, operands[1]);
2134 operands[2] = gen_reg_rtx (SImode); }")
2136 (define_expand "extendqisi2"
2138 (ashift:SI (match_operand:QI 1 "s_register_operand" "")
2140 (set (match_operand:SI 0 "s_register_operand" "")
2141 (ashiftrt:SI (match_dup 2)
2145 { operands[1] = gen_lowpart (SImode, operands[1]);
2146 operands[2] = gen_reg_rtx (SImode); }")
2148 (define_insn "extendsfdf2"
2149 [(set (match_operand:DF 0 "s_register_operand" "=f")
2150 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2153 return (arm_output_asm_insn (\"mvfd\\t%0, %1\", operands));
2155 [(set_attr "type" "float")])
2157 (define_insn "extendsfxf2"
2158 [(set (match_operand:XF 0 "s_register_operand" "=f")
2159 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2160 "ENABLE_XF_PATTERNS"
2162 return (arm_output_asm_insn (\"mvfe\\t%0, %1\", operands));
2165 (define_insn "extenddfxf2"
2166 [(set (match_operand:XF 0 "s_register_operand" "=f")
2167 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2168 "ENABLE_XF_PATTERNS"
2170 return (arm_output_asm_insn (\"mvfe\\t%0, %1\", operands));
2172 [(set_attr "type" "float")])
2175 ;; Move insns (including loads and stores)
2177 ;; XXX Just some ideas about movti.
2178 ;; I don't think these are a good idea on the arm, there just aren't enough
2180 ;;(define_expand "loadti"
2181 ;; [(set (match_operand:TI 0 "s_register_operand" "")
2182 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
2185 ;;(define_expand "storeti"
2186 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2187 ;; (match_operand:TI 1 "s_register_operand" ""))]
2190 ;;(define_expand "movti"
2191 ;; [(set (match_operand:TI 0 "general_operand" "")
2192 ;; (match_operand:TI 1 "general_operand" ""))]
2198 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2199 ;; operands[1] = copy_to_reg (operands[1]);
2200 ;; if (GET_CODE (operands[0]) == MEM)
2201 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2202 ;; else if (GET_CODE (operands[1]) == MEM)
2203 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2207 ;; emit_insn (insn);
2211 ;; Recognise garbage generated above.
2214 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2215 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2219 ;; register mem = (which_alternative < 3);
2220 ;; register char *template;
2222 ;; operands[mem] = XEXP (operands[mem], 0);
2223 ;; switch (which_alternative)
2225 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2226 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
2227 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
2228 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
2229 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
2230 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
2232 ;; return (arm_output_asm_insn (template, operands));
2236 (define_insn "movdi"
2237 [(set (match_operand:DI 0 "di_operand" "=r,r,r,o<>,r")
2238 (match_operand:DI 1 "di_operand" "rK,n,o<>,r,F"))]
2241 return (output_move_double (operands));
2243 [(set_attr "length" "2,8,2,2,8")
2244 (set_attr "type" "*,*,load,store2,*")])
2246 (define_expand "movsi"
2247 [(set (match_operand:SI 0 "general_operand" "")
2248 (match_operand:SI 1 "general_operand" ""))]
2251 /* Everything except mem = const or mem = mem can be done easily */
2252 if (GET_CODE (operands[0]) == MEM)
2253 operands[1] = force_reg (SImode, operands[1]);
2254 if (GET_CODE (operands[1]) == CONST_INT
2255 && !(const_ok_for_arm (INTVAL (operands[1]))
2256 || const_ok_for_arm (~INTVAL (operands[1]))))
2258 int n = INTVAL (operands[1]);
2259 rtx tmpreg, tmpreg2;
2260 int i, n_ones = 0, first = 1, last = 0;
2262 if (GET_CODE (operands[0]) != REG
2263 && GET_CODE (operands[0]) != SUBREG)
2265 for (i = 0; i < 32; i++)
2268 /* These loops go the opposite way around to those in arm.c so that
2269 the last constant may be more likely to be eliminted into the
2274 n = (~n) & 0xffffffff;
2275 for (i = 30; i >= 0; i -= 2)
2282 if ((n & (255 << i)) == n)
2288 emit_insn (gen_movsi (tmpreg = (reload_in_progress
2289 || reload_completed)
2291 : gen_reg_rtx (SImode),
2292 equal = gen_rtx (CONST_INT, VOIDmode,
2293 ~(n & (255 << i)))));
2300 emit_insn (gen_subsi3 (tmpreg2 = (reload_in_progress
2304 : gen_reg_rtx (SImode),
2306 constant = gen_rtx (CONST_INT, VOIDmode,
2316 for (i = 30; i >= 0; i -= 2)
2323 if ((n & (255 << i)) == n)
2329 emit_insn (gen_movsi (tmpreg = (reload_in_progress
2330 || reload_completed)
2332 : gen_reg_rtx (SImode),
2333 equal = gen_rtx (CONST_INT, VOIDmode,
2341 emit_insn (gen_addsi3 (tmpreg2 = (reload_in_progress
2345 : gen_reg_rtx (SImode),
2347 constant = gen_rtx (CONST_INT, VOIDmode,
2360 [(set (match_operand:SI 0 "general_operand" "=r,r,r,m,r")
2361 (match_operand:SI 1 "general_operand" "m,K,r,r,S"))]
2362 "(register_operand (operands[0], SImode)
2363 && (GET_CODE (operands[1]) != CONST_INT
2364 || const_ok_for_arm (INTVAL (operands[1]))
2365 || const_ok_for_arm (~INTVAL (operands[1])))
2366 && (GET_CODE (operands[1]) != SYMBOL_REF
2367 || CONSTANT_ADDRESS_P (operands[1])))
2368 || register_operand (operands[1], SImode)"
2370 switch (which_alternative)
2373 return (arm_output_asm_insn (\"mov\\t%0, %1\", operands));
2375 if (!const_ok_for_arm (INTVAL (operands[1])))
2377 operands[1] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[1]));
2378 return arm_output_asm_insn (\"mvn\\t%0, %1\", operands);
2380 return arm_output_asm_insn (\"mov\\t%0, %1\", operands);
2382 if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
2383 && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
2384 return (arm_output_llc (operands));
2386 return (arm_output_asm_insn (\"ldr\\t%0, %1\", operands));
2388 return (arm_output_asm_insn (\"str\\t%1, %0\", operands));
2390 return output_load_symbol (operands);
2393 [(set_attr "length" "2,*,*,*,4")
2394 (set_attr "type" "load,*,*,store1,*")])
2396 ;; If copying one reg to another we can set the condition codes according to
2397 ;; its value. Such a move is common after a return from subroutine and the
2398 ;; result is being tested against zero.
2401 [(set (reg:CC 24) (compare (match_operand:SI 1 "s_register_operand" "r")
2403 (set (match_operand:SI 0 "s_register_operand" "=r") (match_dup 1))]
2406 if (GET_CODE (operands[0]) == REG && GET_CODE (operands[1]) == REG
2407 && REGNO (operands[0]) == REGNO (operands[1]))
2408 return arm_output_asm_insn (\"cmp\\t%0, #0\", operands);
2409 return arm_output_asm_insn (\"subs\\t%0, %1, #0\", operands);
2411 [(set_attr "conds" "set")])
2413 ;; Subroutine to store a half word from a register into memory.
2414 ;; Operand 0 is the source register (HImode)
2415 ;; Operand 1 is the destination address in a register (SImode)
2417 ;; In both this routine and the next, we must be careful not to spill
2418 ;; a memory address of reg+large_const into a seperate PLUS insn, since this
2419 ;; can generate unrecognizable rtl.
2421 (define_expand "storehi"
2422 [;; store the low byte
2423 (set (mem:QI (match_operand:SI 1 "" "")) (match_dup 3))
2424 ;; extract the high byte
2426 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2427 ;; store the high byte
2428 (set (mem:QI (match_dup 4))
2429 (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
2433 enum rtx_code code = GET_CODE (operands[1]);
2435 if ((code == PLUS || code == MINUS)
2436 && (GET_CODE (XEXP (operands[1], 1)) == REG
2437 || GET_CODE (XEXP (operands[1], 0)) != REG))
2438 operands[1] = force_reg (SImode, operands[1]);
2439 operands[4] = plus_constant (operands[1], 1);
2440 operands[3] = gen_lowpart (QImode, operands[0]);
2441 operands[0] = gen_lowpart (SImode, operands[0]);
2442 operands[2] = gen_reg_rtx (SImode);
2446 ;; Subroutine to store a half word integer constant into memory.
2447 ;; Operand 0 is the constant
2448 ;; Operand 1 is the destination address in a register (SImode)
2450 (define_expand "storeinthi"
2451 [;; store the low byte
2452 (set (mem:QI (match_operand:SI 1 "" "")) (match_operand 0 "" ""))
2453 ;; store the high byte
2454 (set (mem:QI (match_dup 3)) (match_dup 2))]
2458 int value = INTVAL (operands[0]);
2459 enum rtx_code code = GET_CODE (operands[1]);
2461 if ((code == PLUS || code == MINUS)
2462 && (GET_CODE (XEXP (operands[1], 1)) == REG
2463 || GET_CODE (XEXP (operands[1], 0)) != REG))
2464 operands[1] = force_reg (SImode, operands[1]);
2466 operands[0] = force_reg (QImode, gen_rtx (CONST_INT, VOIDmode, value & 255));
2467 operands[2] = force_reg (QImode,
2468 gen_rtx (CONST_INT, VOIDmode,(value>>8) & 255));
2469 operands[3] = plus_constant (operands[1], 1);
2473 (define_expand "movhi"
2474 [(set (match_operand:HI 0 "general_operand" "")
2475 (match_operand:HI 1 "general_operand" ""))]
2481 if (reload_in_progress || reload_completed)
2482 insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]);
2485 if (GET_CODE (operands[0]) == MEM)
2487 if (GET_CODE (operands[1]) == CONST_INT)
2489 insn = gen_storeinthi (operands[1], XEXP (operands[0],0));
2493 if (GET_CODE (operands[1]) == MEM)
2494 operands[1] = force_reg (HImode, operands[1]);
2495 insn = gen_storehi (operands[1], XEXP (operands[0], 0));
2498 else if (GET_CODE (operands[1]) == CONST_INT
2499 && !(const_ok_for_arm (INTVAL (operands[1]))
2500 || const_ok_for_arm (~INTVAL (operands[1]))))
2504 /* no need to be clever, this will always take two insns.
2505 The top sixteen bits should be all zeros or all ones. */
2506 if (INTVAL (operands[1]) < 0)
2508 emit_insn (gen_movsi (reg = gen_reg_rtx (SImode),
2509 GEN_INT (INTVAL (operands[1])
2511 emit_insn (gen_addsi3 (reg2 = gen_reg_rtx (SImode), reg,
2512 GEN_INT (-((~INTVAL (operands[1]))
2517 emit_insn (gen_movsi (reg = gen_reg_rtx (SImode),
2518 GEN_INT (INTVAL (operands[1]) & 0xff00)));
2519 emit_insn (gen_addsi3 (reg2 = gen_reg_rtx (SImode), reg,
2520 GEN_INT (INTVAL (operands[1]) & 0x00ff)));
2522 insn = gen_rtx (SET, HImode, operands[0],
2523 gen_rtx (SUBREG, HImode, reg2, 0));
2526 insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]);
2533 ;; Pattern to recognise insn generated default case above
2536 [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
2537 (match_operand:HI 1 "general_operand" "r,K,m,r"))]
2538 "(register_operand (operands[0], HImode)
2539 && (GET_CODE (operands[1]) != CONST_INT
2540 || const_ok_for_arm (INTVAL (operands[1]))
2541 || const_ok_for_arm (~INTVAL (operands[1]))))
2542 || register_operand (operands[1], HImode)"
2544 switch (which_alternative)
2547 if (!const_ok_for_arm (INTVAL (operands[1])))
2549 operands[1] = GEN_INT (~INTVAL (operands[1]));
2550 return arm_output_asm_insn (\"mvn\\t%0, %1\", operands);
2554 return arm_output_asm_insn (\"mov\\t%0, %1\\t@movhi\", operands);
2556 return arm_output_asm_insn (\"ldr\\t%0, %1\\t@movhi\", operands);
2558 return arm_output_asm_insn (\"str\\t%1, %0\\t@movhi\", operands);
2561 [(set_attr "type" "*,*,load,store1")])
2563 (define_expand "reload_outhi"
2564 [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
2565 (match_operand:HI 1 "s_register_operand" "r")
2566 (match_operand:SI 2 "s_register_operand" "=&r")])]
2569 arm_reload_out_hi (operands);
2573 (define_expand "movqi"
2574 [(set (match_operand:QI 0 "general_operand" "")
2575 (match_operand:QI 1 "general_operand" ""))]
2578 /* Everything except mem = const or mem = mem can be done easily */
2580 if (!(reload_in_progress || reload_completed))
2583 if (GET_CODE (operands[1]) == CONST_INT)
2585 emit_insn (gen_movsi (reg = gen_reg_rtx (SImode), operands[1]));
2586 operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
2589 if (GET_CODE (operands[0]) == MEM)
2590 operands[1] = force_reg (QImode, operands[1]);
2595 [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
2596 (match_operand:QI 1 "general_operand" "r,K,m,r"))]
2597 "register_operand (operands[0], QImode)
2598 || register_operand (operands[1], QImode)"
2600 switch (which_alternative)
2603 if (INTVAL (operands[1]) < 0)
2605 operands[1] = GEN_INT (~INTVAL (operands[1]));
2606 return arm_output_asm_insn (\"mvn\\t%0, %1\", operands);
2609 return (arm_output_asm_insn (\"mov\\t%0, %1\", operands));
2611 return (arm_output_asm_insn (\"ldrb\\t%0, %1\", operands));
2613 return (arm_output_asm_insn (\"strb\\t%1, %0\", operands));
2616 [(set_attr "type" "*,*,load,store1")])
2618 (define_insn "movsf"
2619 [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
2620 (match_operand:SF 1 "general_operand" "fG,H,m,f,r,f,r,m,r"))]
2626 switch (which_alternative)
2629 return arm_output_asm_insn (\"mvfs\\t%0, %1\", operands);
2631 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2632 r = REAL_VALUE_NEGATE (r);
2633 operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
2634 return arm_output_asm_insn (\"mnfs\\t%0, %1\", operands);
2636 return arm_output_asm_insn (\"ldfs\\t%0, %1\", operands);
2638 return arm_output_asm_insn (\"stfs\\t%1, %0\", operands);
2640 arm_output_asm_insn(\"stmfd\\tsp!, {%1}\", operands);
2641 return arm_output_asm_insn (\"ldfs\\t%0, [sp],#4\", operands);
2643 arm_output_asm_insn(\"stfs\\t%1, [sp,#-4]!\", operands);
2644 return arm_output_asm_insn (\"ldmfd\\tsp!, {%0}\", operands);
2646 return arm_output_asm_insn (\"mov\\t%0, %1\", operands);
2648 return arm_output_asm_insn (\"ldr\\t%0, %1\\t@ float\", operands);
2650 return arm_output_asm_insn (\"str\\t%1, %0\\t@ float\", operands);
2654 [(set_attr "length" "1,1,1,1,2,2,1,1,1")
2655 (set_attr "type" "float,float,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
2657 (define_expand "movdf"
2658 [(parallel [(set (match_operand:DF 0 "general_operand" "")
2659 (match_operand:DF 1 "general_operand" ""))
2660 (clobber (match_scratch:SI 2 ""))])]
2663 if (GET_CODE (operands[0]) == MEM)
2664 operands[1] = force_reg (DFmode, operands[1]);
2667 ;; Reloading a df mode value stored in integer regs to memory can require a
2669 (define_expand "reload_outdf"
2670 [(parallel [(set (match_operand:DF 0 "reload_memory_operand" "=o")
2671 (match_operand:DF 1 "s_register_operand" "r"))
2672 (clobber (match_operand:SI 2 "s_register_operand" "=&r"))])]
2677 [(set (match_operand:DF 0 "general_operand" "=r,Q,r,o,f,f,f,f,m,!f,!r,r")
2678 (match_operand:DF 1 "general_operand"
2679 "Q,r,?o,?r,?f,!G,!H,m,f,r,f,??r"))
2680 (clobber (match_scratch:SI 2 "=X,X,X,&r,X,X,X,X,X,X,X,X"))]
2681 "GET_CODE (operands[0]) != MEM || register_operand (operands[1], DFmode)"
2687 switch (which_alternative)
2690 operands[1] = XEXP (operands[1], 0);
2691 return arm_output_asm_insn (\"ldmia\\t%1, {%0, %R0}\\t@ double\",
2694 operands[0] = XEXP (operands[0], 0);
2695 return arm_output_asm_insn (\"stmia\\t%0, {%1, %R1}\\t@ double\",
2698 ops[0] = operands[0];
2699 ops[1] = XEXP (XEXP (operands[1], 0), 0);
2700 ops[2] = XEXP (XEXP (operands[1], 0), 1);
2701 if (!INTVAL (ops[2]) || const_ok_for_arm (INTVAL (ops[2])))
2702 arm_output_asm_insn (\"add\\t%0, %1, %2\", ops);
2704 arm_output_asm_insn (\"sub\\t%0, %1, #%n2\", ops);
2705 return arm_output_asm_insn (\"ldmia\\t%0, {%0, %R0}\\t@ double\",
2709 ops[0] = operands[2];
2710 ops[1] = XEXP (XEXP (operands[0], 0), 0);
2711 ops[2] = XEXP (XEXP (operands[0], 0), 1);
2712 if (!INTVAL (ops[2]) || const_ok_for_arm (INTVAL (ops[2])))
2713 arm_output_asm_insn (\"add\\t%0, %1, %2\", ops);
2715 arm_output_asm_insn (\"sub\\t%0, %1, #%n2\", ops);
2716 return arm_output_asm_insn (\"stmia\\t%2, {%1, %R1}\\t@ double\",
2720 return arm_output_asm_insn (\"mvfd\\t%0, %1\", operands);
2722 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2723 r = REAL_VALUE_NEGATE (r);
2724 operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
2725 return arm_output_asm_insn (\"mnfd\\t%0, %1\", operands);
2726 case 7: return arm_output_asm_insn (\"ldfd\\t%0, %1\", operands);
2727 case 8: return arm_output_asm_insn (\"stfd\\t%1, %0\", operands);
2728 case 9: return output_mov_double_fpu_from_arm (operands);
2729 case 10: return output_mov_double_arm_from_fpu (operands);
2730 case 11: return output_move_double (operands);
2734 [(set_attr "length" "1,1,2,2,1,1,1,1,1,2,2,2")
2736 "load,store2,load,store2,float,float,float,f_load,f_store,r_mem_f,f_mem_r,*")])
2738 (define_insn "movxf"
2739 [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
2740 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
2741 "ENABLE_XF_PATTERNS"
2746 switch (which_alternative)
2748 case 0: return arm_output_asm_insn (\"mvfe\\t%0, %1\", operands);
2750 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
2751 r = REAL_VALUE_NEGATE (r);
2752 operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
2753 return arm_output_asm_insn (\"mnfe\\t%0, %1\", operands);
2754 case 2: return arm_output_asm_insn (\"ldfe\\t%0, %1\", operands);
2755 case 3: return arm_output_asm_insn (\"stfe\\t%1, %0\", operands);
2756 case 4: return output_mov_long_double_fpu_from_arm (operands);
2757 case 5: return output_mov_long_double_arm_from_fpu (operands);
2758 case 6: return output_mov_long_double_arm_from_arm (operands);
2762 [(set_attr "length" "1,1,1,1,2,2,3")
2763 (set_attr "type" "float,float,f_load,f_store,r_mem_f,f_mem_r,*")])
2766 ;; load- and store-multiple insns
2767 ;; The arm can load/store any set of registers, provided that they are in
2768 ;; ascending order; but that is beyond GCC so stick with what it knows.
2770 (define_expand "load_multiple"
2771 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2772 (match_operand:SI 1 "" ""))
2773 (use (match_operand:SI 2 "" ""))])]
2776 /* Support only fixed point registers */
2777 if (GET_CODE (operands[2]) != CONST_INT
2778 || INTVAL (operands[2]) > 14
2779 || INTVAL (operands[2]) < 2
2780 || GET_CODE (operands[1]) != MEM
2781 || GET_CODE (operands[0]) != REG
2782 || REGNO (operands[0]) > 14
2783 || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
2787 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
2788 force_reg (SImode, XEXP (operands[1], 0)),
2792 ;; Load multiple with write-back
2795 [(match_parallel 0 "load_multiple_operation"
2796 [(set (match_operand:SI 1 "s_register_operand" "+r")
2797 (plus:SI (match_dup 1)
2798 (match_operand:SI 2 "immediate_operand" "n")))
2799 (set (match_operand:SI 3 "s_register_operand" "=r")
2800 (mem:SI (match_dup 1)))])]
2801 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
2805 int count = XVECLEN (operands[0], 0);
2807 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2808 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
2809 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
2811 return arm_output_asm_insn (\"ldmia\\t%0!, {%1-%2}\\t@ load multiple\", ops);
2814 [(set_attr "type" "load")])
2816 ;; Ordinary load multiple
2819 [(match_parallel 0 "load_multiple_operation"
2820 [(set (match_operand:SI 1 "s_register_operand" "=r")
2821 (match_operand:SI 2 "indirect_operand" "Q"))])]
2826 int count = XVECLEN (operands[0], 0);
2828 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2829 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
2830 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
2832 return arm_output_asm_insn (\"ldmia\\t%0, {%1-%2}\\t@ load multiple\", ops);
2835 [(set_attr "type" "load")])
2837 (define_expand "store_multiple"
2838 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
2839 (match_operand:SI 1 "" ""))
2840 (use (match_operand:SI 2 "" ""))])]
2843 /* Support only fixed point registers */
2844 if (GET_CODE (operands[2]) != CONST_INT
2845 || INTVAL (operands[2]) > 14
2846 || INTVAL (operands[2]) < 2
2847 || GET_CODE (operands[1]) != REG
2848 || GET_CODE (operands[0]) != MEM
2849 || REGNO (operands[1]) > 14
2850 || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
2854 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
2855 force_reg (SImode, XEXP (operands[0], 0)),
2859 ;; Store multiple with write-back
2862 [(match_parallel 0 "store_multiple_operation"
2863 [(set (match_operand:SI 1 "s_register_operand" "+r")
2864 (plus:SI (match_dup 1)
2865 (match_operand:SI 2 "immediate_operand" "n")))
2866 (set (mem:SI (match_dup 1))
2867 (match_operand:SI 3 "s_register_operand" "r"))])]
2868 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
2872 int count = XVECLEN (operands[0], 0);
2874 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
2875 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
2876 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
2878 return arm_output_asm_insn (\"stmia\\t%0!, {%1-%2}\\t@ str multiple\", ops);
2882 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
2883 (const_string "store2")
2884 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
2885 (const_string "store3")]
2886 (const_string "store4")))])
2888 ;; Ordinary store multiple
2891 [(match_parallel 0 "store_multiple_operation"
2892 [(set (match_operand:SI 2 "indirect_operand" "=Q")
2893 (match_operand:SI 1 "s_register_operand" "r"))])]
2898 int count = XVECLEN (operands[0], 0);
2900 ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
2901 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
2902 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
2904 return arm_output_asm_insn (\"stmia\\t%0, {%1-%2}\\t@ str multiple\", ops);
2908 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
2909 (const_string "store2")
2910 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
2911 (const_string "store3")]
2912 (const_string "store4")))])
2914 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
2915 ;; We could let this apply for blocks of less than this, but it clobbers so
2916 ;; many registers that there is then probably a better way.
2918 ;; If optimizing, output redundant moves with REG_NOTES on them, this
2919 ;; produces better code.
2921 (define_expand "movstrsi"
2922 [(set (match_operand:BLK 0 "general_operand" "=m")
2923 (match_operand:BLK 1 "general_operand" "m"))
2924 (use (match_operand:SI 2 "immediate_operand" "n"))
2925 (use (match_operand:SI 3 "immediate_operand" "n"))
2926 (clobber (reg:SI 0))
2927 (clobber (reg:SI 1))
2928 (clobber (reg:SI 2))
2929 (clobber (reg:SI 3))
2930 (clobber (match_scratch:SI 4 "=+r"))
2931 (clobber (match_scratch:SI 5 "=+r"))]
2937 rtx const_sxteen = gen_rtx (CONST_INT, SImode, 16);
2938 rtx src = gen_reg_rtx (SImode);
2939 rtx dst = gen_reg_rtx (SImode);
2940 rtx st_src, st_dst, end_src, end_dst, fin_src, fin_dst;
2941 extern int optimize;
2943 if (GET_CODE (operands[2]) != CONST_INT
2944 || GET_CODE (operands[3]) != CONST_INT
2945 || INTVAL (operands[2]) % 4 != 0
2946 || INTVAL (operands[2]) < 4
2947 || INTVAL (operands[2]) > 64
2948 || INTVAL (operands[3]) < 4
2949 || INTVAL (operands[3]) % 4 != 0)
2951 emit_move_insn (dst, st_dst = force_reg (SImode, XEXP (operands[0], 0)));
2952 emit_move_insn (src, st_src = force_reg (SImode, XEXP (operands[1], 0)));
2956 for (i = 0, words_to_go = INTVAL (operands[2]) / 4; words_to_go >= 2; i+=4)
2958 emit_insn (arm_gen_load_multiple (0, words_to_go > 4 ? 4 : words_to_go,
2960 emit_insn (arm_gen_store_multiple (0, words_to_go > 4 ? 4 : words_to_go,
2963 for (r = (words_to_go > 4) ? 3 : words_to_go - 1; r >= 0; r--)
2966 note = emit_move_insn (gen_reg_rtx (SImode),
2967 gen_rtx (REG, SImode, r));
2968 REG_NOTES (note) = gen_rtx (EXPR_LIST, REG_EQUIV,
2969 gen_rtx (MEM, SImode,
2970 plus_constant (st_src, 4*(i+r))),
2972 REG_NOTES (note) = gen_rtx (EXPR_LIST, REG_EQUIV,
2973 gen_rtx (MEM, SImode,
2974 plus_constant (st_dst, 4*(i+r))),
2977 words_to_go -= words_to_go < 4 ? words_to_go : 4;
2983 emit_move_insn (sreg = gen_reg_rtx (SImode), gen_rtx (MEM, SImode, src));
2984 emit_move_insn (fin_src = gen_reg_rtx (SImode), plus_constant (src, 4));
2985 emit_move_insn (gen_rtx (MEM, SImode, dst), sreg);
2986 emit_move_insn (fin_dst = gen_reg_rtx (SImode), plus_constant (dst, 4));
2990 /* Insns for the REG_NOTES: These notes tell the optimiser where the
2991 index registers have got to so that consecutive block moves of
2992 contiguous data work efficiently */
2994 end_src = emit_move_insn (fin_src, fin_src);
2995 REG_NOTES (end_src) = gen_rtx(EXPR_LIST, REG_EQUAL,
2996 plus_constant (st_src, INTVAL (operands[2])),
2997 REG_NOTES (end_src));
2998 end_dst = emit_move_insn (fin_dst, fin_dst);
2999 REG_NOTES (end_dst) = gen_rtx(EXPR_LIST, REG_EQUAL,
3000 plus_constant (st_dst, INTVAL (operands[2])),
3001 REG_NOTES (end_dst));
3008 ;; Comparison and test insns
3010 (define_expand "cmpsi"
3012 (compare:CC (match_operand:SI 0 "s_register_operand" "")
3013 (match_operand:SI 1 "arm_add_operand" "")))]
3017 arm_compare_op0 = operands[0];
3018 arm_compare_op1 = operands[1];
3024 (define_expand "cmpsf"
3026 (compare:CC (match_operand:SF 0 "s_register_operand" "")
3027 (match_operand:SF 1 "fpu_rhs_operand" "")))]
3031 arm_compare_op0 = operands[0];
3032 arm_compare_op1 = operands[1];
3038 (define_expand "cmpdf"
3040 (compare:CC (match_operand:DF 0 "s_register_operand" "")
3041 (match_operand:DF 1 "fpu_rhs_operand" "")))]
3045 arm_compare_op0 = operands[0];
3046 arm_compare_op1 = operands[1];
3052 (define_expand "cmpxf"
3054 (compare:CC (match_operand:XF 0 "s_register_operand" "")
3055 (match_operand:XF 1 "fpu_rhs_operand" "")))]
3056 "ENABLE_XF_PATTERNS"
3059 arm_compare_op0 = operands[0];
3060 arm_compare_op1 = operands[1];
3067 [(set (match_operand 0 "cc_register" "")
3068 (compare (match_operand:SI 1 "s_register_operand" "r")
3069 (match_operand:SI 2 "arm_add_operand" "rL")))]
3072 if (GET_CODE (operands[2]) == CONST_INT
3073 && !const_ok_for_arm (INTVAL (operands[2])))
3074 return arm_output_asm_insn (\"cmn\\t%1, #%n2\", operands);
3075 return arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
3077 [(set_attr "conds" "set")])
3080 [(set (match_operand 0 "cc_register" "")
3081 (compare (match_operand:SI 1 "s_register_operand" "r")
3082 (neg:SI (match_operand:SI 2 "s_register_operand" "r"))))]
3085 return arm_output_asm_insn (\"cmn\\t%1, %2\", operands);
3087 [(set_attr "conds" "set")])
3090 [(set (match_operand 0 "cc_register" "")
3091 (compare (match_operand:SI 1 "s_register_operand" "r")
3092 (match_operator:SI 2 "shift_operator"
3093 [(match_operand:SI 3 "s_register_operand" "r")
3094 (match_operand:SI 4 "arm_rhs_operand" "rn")])))]
3097 return output_shift_compare (operands, FALSE);
3099 [(set_attr "conds" "set")])
3102 [(set (match_operand 0 "cc_register" "")
3103 (compare (match_operand:SI 1 "s_register_operand" "r")
3104 (neg:SI (match_operator:SI 2 "shift_operator"
3105 [(match_operand:SI 3 "s_register_operand" "r")
3106 (match_operand:SI 4 "arm_rhs_operand" "rn")]))))]
3109 return output_shift_compare (operands, TRUE);
3111 [(set_attr "conds" "set")])
3115 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3116 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3122 switch (which_alternative)
3125 return arm_output_asm_insn (\"cmf\\t%0, %1\", operands);
3127 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3128 r = REAL_VALUE_NEGATE (r);
3129 operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3130 return arm_output_asm_insn (\"cnf\\t%0, %1\", operands);
3134 [(set_attr "conds" "set")
3135 (set_attr "type" "f_2_r")])
3139 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3140 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3146 switch (which_alternative)
3149 return arm_output_asm_insn (\"cmf\\t%0, %1\", operands);
3151 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3152 r = REAL_VALUE_NEGATE (r);
3153 operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3154 return arm_output_asm_insn (\"cnf\\t%0, %1\", operands);
3158 [(set_attr "conds" "set")
3159 (set_attr "type" "f_2_r")])
3163 (compare:CCFP (float_extend:DF
3164 (match_operand:SF 0 "s_register_operand" "f,f"))
3165 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3171 switch (which_alternative)
3174 return arm_output_asm_insn (\"cmf\\t%0, %1\", operands);
3176 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3177 r = REAL_VALUE_NEGATE (r);
3178 operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3179 return arm_output_asm_insn (\"cnf\\t%0, %1\", operands);
3183 [(set_attr "conds" "set")
3184 (set_attr "type" "f_2_r")])
3188 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3190 (match_operand:SF 1 "s_register_operand" "f"))))]
3193 return arm_output_asm_insn (\"cmf\\t%0, %1\", operands);
3195 [(set_attr "conds" "set")
3196 (set_attr "type" "f_2_r")])
3200 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3201 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3202 "ENABLE_XF_PATTERNS"
3207 switch (which_alternative)
3210 return arm_output_asm_insn (\"cmf\\t%0, %1\", operands);
3212 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3213 r = REAL_VALUE_NEGATE (r);
3214 operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3215 return arm_output_asm_insn (\"cnf\\t%0, %1\", operands);
3219 [(set_attr "conds" "set")
3220 (set_attr "type" "f_2_r")])
3223 [(set (reg:CCFPE 24)
3224 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3225 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3231 switch (which_alternative)
3234 return arm_output_asm_insn (\"cmfe\\t%0, %1\", operands);
3236 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3237 r = REAL_VALUE_NEGATE (r);
3238 operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3239 return arm_output_asm_insn (\"cnfe\\t%0, %1\", operands);
3243 [(set_attr "conds" "set")
3244 (set_attr "type" "f_2_r")])
3247 [(set (reg:CCFPE 24)
3248 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3249 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3255 switch (which_alternative)
3258 return arm_output_asm_insn (\"cmfe\\t%0, %1\", operands);
3260 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3261 r = REAL_VALUE_NEGATE (r);
3262 operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3263 return arm_output_asm_insn (\"cnfe\\t%0, %1\", operands);
3267 [(set_attr "conds" "set")
3268 (set_attr "type" "f_2_r")])
3271 [(set (reg:CCFPE 24)
3272 (compare:CCFPE (float_extend:DF
3273 (match_operand:SF 0 "s_register_operand" "f,f"))
3274 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3280 switch (which_alternative)
3283 return arm_output_asm_insn (\"cmfe\\t%0, %1\", operands);
3285 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3286 r = REAL_VALUE_NEGATE (r);
3287 operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3288 return arm_output_asm_insn (\"cnfe\\t%0, %1\", operands);
3292 [(set_attr "conds" "set")
3293 (set_attr "type" "f_2_r")])
3296 [(set (reg:CCFPE 24)
3297 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3299 (match_operand:SF 1 "s_register_operand" "f"))))]
3302 return arm_output_asm_insn (\"cmfe\\t%0, %1\", operands);
3304 [(set_attr "conds" "set")
3305 (set_attr "type" "f_2_r")])
3308 [(set (reg:CCFPE 24)
3309 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3310 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3311 "ENABLE_XF_PATTERNS"
3316 switch (which_alternative)
3319 return arm_output_asm_insn (\"cmfe\\t%0, %1\", operands);
3321 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
3322 r = REAL_VALUE_NEGATE (r);
3323 operands[1] = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (operands[1]));
3324 return arm_output_asm_insn (\"cnfe\\t%0, %1\", operands);
3328 [(set_attr "conds" "set")
3329 (set_attr "type" "f_2_r")])
3331 ; This insn allows redundant compares to be removed by cse, nothing should
3332 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3333 ; is deleted later on. The match_dup will match the mode here, so that
3334 ; mode changes of the condition codes aren't lost by this even though we don't
3335 ; specify what they are.
3338 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3340 "\\t@ deleted compare"
3341 [(set_attr "conds" "set")
3342 (set_attr "length" "0")])
3345 ;; Conditional branch insns
3347 (define_expand "beq"
3349 (if_then_else (eq (match_dup 1) (const_int 0))
3350 (label_ref (match_operand 0 "" ""))
3355 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3360 (define_expand "bne"
3362 (if_then_else (ne (match_dup 1) (const_int 0))
3363 (label_ref (match_operand 0 "" ""))
3368 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3373 (define_expand "bgt"
3375 (if_then_else (gt (match_dup 1) (const_int 0))
3376 (label_ref (match_operand 0 "" ""))
3381 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3386 (define_expand "ble"
3388 (if_then_else (le (match_dup 1) (const_int 0))
3389 (label_ref (match_operand 0 "" ""))
3394 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3399 (define_expand "bge"
3401 (if_then_else (ge (match_dup 1) (const_int 0))
3402 (label_ref (match_operand 0 "" ""))
3407 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3412 (define_expand "blt"
3414 (if_then_else (lt (match_dup 1) (const_int 0))
3415 (label_ref (match_operand 0 "" ""))
3420 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3425 (define_expand "bgtu"
3427 (if_then_else (gtu (match_dup 1) (const_int 0))
3428 (label_ref (match_operand 0 "" ""))
3433 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3438 (define_expand "bleu"
3440 (if_then_else (leu (match_dup 1) (const_int 0))
3441 (label_ref (match_operand 0 "" ""))
3446 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3451 (define_expand "bgeu"
3453 (if_then_else (geu (match_dup 1) (const_int 0))
3454 (label_ref (match_operand 0 "" ""))
3459 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3464 (define_expand "bltu"
3466 (if_then_else (ltu (match_dup 1) (const_int 0))
3467 (label_ref (match_operand 0 "" ""))
3472 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3477 ;; patterns to match conditional branch insns
3481 (if_then_else (match_operator 1 "comparison_operator"
3482 [(reg 24) (const_int 0)])
3483 (label_ref (match_operand 0 "" ""))
3488 extern int arm_ccfsm_state;
3490 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3492 arm_ccfsm_state += 2;
3495 return (arm_output_asm_insn (\"b%d1\\t%l0\", operands));
3497 [(set_attr "conds" "use")])
3501 (if_then_else (match_operator 1 "comparison_operator"
3502 [(reg 24) (const_int 0)])
3504 (label_ref (match_operand 0 "" ""))))]
3508 extern int arm_ccfsm_state;
3510 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3512 arm_ccfsm_state += 2;
3515 return (arm_output_asm_insn (\"b%D1\\t%l0\", operands));
3517 [(set_attr "conds" "use")])
3522 (define_expand "seq"
3523 [(set (match_operand:SI 0 "s_register_operand" "=r")
3524 (eq:SI (match_dup 1) (const_int 0)))]
3528 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3533 (define_expand "sne"
3534 [(set (match_operand:SI 0 "s_register_operand" "=r")
3535 (ne:SI (match_dup 1) (const_int 0)))]
3539 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3544 (define_expand "sgt"
3545 [(set (match_operand:SI 0 "s_register_operand" "=r")
3546 (gt:SI (match_dup 1) (const_int 0)))]
3550 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3555 (define_expand "sle"
3556 [(set (match_operand:SI 0 "s_register_operand" "=r")
3557 (le:SI (match_dup 1) (const_int 0)))]
3561 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3566 (define_expand "sge"
3567 [(set (match_operand:SI 0 "s_register_operand" "=r")
3568 (ge:SI (match_dup 1) (const_int 0)))]
3572 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3577 (define_expand "slt"
3578 [(set (match_operand:SI 0 "s_register_operand" "=r")
3579 (lt:SI (match_dup 1) (const_int 0)))]
3583 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3588 (define_expand "sgtu"
3589 [(set (match_operand:SI 0 "s_register_operand" "=r")
3590 (gtu:SI (match_dup 1) (const_int 0)))]
3594 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3599 (define_expand "sleu"
3600 [(set (match_operand:SI 0 "s_register_operand" "=r")
3601 (leu:SI (match_dup 1) (const_int 0)))]
3605 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3610 (define_expand "sgeu"
3611 [(set (match_operand:SI 0 "s_register_operand" "=r")
3612 (geu:SI (match_dup 1) (const_int 0)))]
3616 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3621 (define_expand "sltu"
3622 [(set (match_operand:SI 0 "s_register_operand" "=r")
3623 (ltu:SI (match_dup 1) (const_int 0)))]
3627 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3633 [(set (match_operand:SI 0 "s_register_operand" "=r")
3634 (match_operator:SI 1 "comparison_operator" [(reg 24) (const_int 0)]))]
3637 arm_output_asm_insn (\"mov%d1\\t%0, #1\", operands);
3638 return arm_output_asm_insn (\"mov%D1\\t%0, #0\", operands);
3640 [(set_attr "conds" "use")
3641 (set_attr "length" "2")])
3644 [(set (match_operand:SI 0 "s_register_operand" "=r")
3645 (neg:SI (match_operator:SI 1 "comparison_operator"
3646 [(reg 24) (const_int 0)])))]
3649 arm_output_asm_insn (\"mvn%d1\\t%0, #0\", operands);
3650 return arm_output_asm_insn (\"mov%D1\\t%0, #0\", operands);
3652 [(set_attr "conds" "use")
3653 (set_attr "length" "2")])
3656 [(set (match_operand:SI 0 "s_register_operand" "=r")
3657 (not:SI (match_operator:SI 1 "comparison_operator"
3658 [(reg 24) (const_int 0)])))]
3661 arm_output_asm_insn (\"mvn%d1\\t%0, #1\", operands);
3662 return arm_output_asm_insn (\"mov%D1\\t%0, #0\", operands);
3664 [(set_attr "conds" "use")
3665 (set_attr "length" "2")])
3668 ;; Jump and linkage insns
3672 (label_ref (match_operand 0 "" "")))]
3676 extern int arm_ccfsm_state;
3678 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3680 arm_ccfsm_state += 2;
3683 return (arm_output_asm_insn (\"b\\t%l0\", operands));
3686 (define_expand "call"
3687 [(parallel [(call (match_operand 0 "memory_operand" "")
3688 (match_operand 1 "general_operand" ""))
3689 (clobber (reg:SI 14))])]
3694 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
3695 (match_operand 1 "" "g"))
3696 (clobber (reg:SI 14))]
3699 return (output_call (operands));
3701 [(set (attr "conds")
3702 (if_then_else (eq_attr "cpu" "arm6")
3703 (const_string "clob")
3704 (const_string "nocond")))
3705 ;; length is worst case, normally it is only two
3706 (set_attr "length" "3")
3707 (set_attr "type" "call")])
3710 [(call (mem:SI (match_operand 0 "memory_operand" "m"))
3711 (match_operand 1 "general_operand" "g"))
3712 (clobber (reg:SI 14))]
3715 return (output_call_mem (operands));
3717 [(set (attr "conds")
3718 (if_then_else (eq_attr "cpu" "arm6")
3719 (const_string "clob")
3720 (const_string "nocond")))
3721 (set_attr "length" "3")
3722 (set_attr "type" "call")])
3724 (define_expand "call_value"
3725 [(parallel [(set (match_operand 0 "" "=rf")
3726 (call (match_operand 1 "memory_operand" "m")
3727 (match_operand 2 "general_operand" "g")))
3728 (clobber (reg:SI 14))])]
3733 [(set (match_operand 0 "" "=rf")
3734 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
3735 (match_operand 2 "general_operand" "g")))
3736 (clobber (reg:SI 14))]
3739 return (output_call (&operands[1]));
3741 [(set (attr "conds")
3742 (if_then_else (eq_attr "cpu" "arm6")
3743 (const_string "clob")
3744 (const_string "nocond")))
3745 (set_attr "length" "3")
3746 (set_attr "type" "call")])
3749 [(set (match_operand 0 "" "=rf")
3750 (call (mem:SI (match_operand 1 "memory_operand" "m"))
3751 (match_operand 2 "general_operand" "g")))
3752 (clobber (reg:SI 14))]
3753 "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
3755 return (output_call_mem (&operands[1]));
3757 [(set (attr "conds")
3758 (if_then_else (eq_attr "cpu" "arm6")
3759 (const_string "clob")
3760 (const_string "nocond")))
3761 (set_attr "length" "3")
3762 (set_attr "type" "call")])
3764 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
3765 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
3768 [(call (mem:SI (match_operand:SI 0 "" "i"))
3769 (match_operand:SI 1 "general_operand" "g"))
3770 (clobber (reg:SI 14))]
3771 "GET_CODE (operands[0]) == SYMBOL_REF"
3773 return (arm_output_asm_insn (\"bl\\t%a0\", operands));
3775 [(set (attr "conds")
3776 (if_then_else (eq_attr "cpu" "arm6")
3777 (const_string "clob")
3778 (const_string "nocond")))
3779 (set_attr "type" "call")])
3782 [(set (match_operand 0 "s_register_operand" "=rf")
3783 (call (mem:SI (match_operand:SI 1 "" "i"))
3784 (match_operand:SI 2 "general_operand" "g")))
3785 (clobber (reg:SI 14))]
3786 "GET_CODE(operands[1]) == SYMBOL_REF"
3788 return (arm_output_asm_insn (\"bl\\t%a1\", operands));
3790 [(set (attr "conds")
3791 (if_then_else (eq_attr "cpu" "arm6")
3792 (const_string "clob")
3793 (const_string "nocond")))
3794 (set_attr "type" "call")])
3796 ;; Often the return insn will be the same as loading from memory, so set attr
3797 (define_insn "return"
3802 extern int arm_ccfsm_state;
3804 if (arm_ccfsm_state == 2)
3806 arm_ccfsm_state += 2;
3809 return output_return_instruction (NULL, TRUE);
3811 [(set_attr "type" "load")])
3815 (if_then_else (match_operator 0 "comparison_operator"
3816 [(reg 24) (const_int 0)])
3822 extern int arm_ccfsm_state;
3824 if (arm_ccfsm_state == 2)
3826 arm_ccfsm_state += 2;
3829 return output_return_instruction (operands[0], TRUE);
3831 [(set_attr "conds" "use")
3832 (set_attr "type" "load")])
3836 (if_then_else (match_operator 0 "comparison_operator"
3837 [(reg 24) (const_int 0)])
3843 extern int arm_ccfsm_state;
3845 if (arm_ccfsm_state == 2)
3847 arm_ccfsm_state += 2;
3850 return output_return_instruction
3851 (gen_rtx (reverse_condition (GET_CODE (operands[0])),
3852 GET_MODE (operands[0]), XEXP (operands[0], 0),
3853 XEXP (operands[0], 1)),
3856 [(set_attr "conds" "use")
3857 (set_attr "type" "load")])
3859 ;; Call subroutine returning any type.
3861 (define_expand "untyped_call"
3862 [(parallel [(call (match_operand 0 "" "")
3864 (match_operand 1 "" "")
3865 (match_operand 2 "" "")])]
3871 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
3873 for (i = 0; i < XVECLEN (operands[2], 0); i++)
3875 rtx set = XVECEXP (operands[2], 0, i);
3876 emit_move_insn (SET_DEST (set), SET_SRC (set));
3879 /* The optimizer does not know that the call sets the function value
3880 registers we stored in the result block. We avoid problems by
3881 claiming that all hard registers are used and clobbered at this
3883 emit_insn (gen_blockage ());
3888 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
3889 ;; all of memory. This blocks insns from being moved across this point.
3891 (define_insn "blockage"
3892 [(unspec_volatile [(const_int 0)] 0)]
3895 [(set_attr "length" "0")
3896 (set_attr "type" "block")])
3898 (define_insn "tablejump"
3900 (match_operand:SI 0 "s_register_operand" "r"))
3901 (use (label_ref (match_operand 1 "" "")))]
3904 return arm_output_asm_insn (\"mov\\tpc, %0\\t@ table jump, label %l1\",
3910 (match_operand:SI 0 "memory_operand" "m"))
3911 (use (label_ref (match_operand 1 "" "")))]
3914 return arm_output_asm_insn (\"ldr\\tpc, %0\\t@ table jump, label %l1\",
3917 [(set_attr "type" "load")])
3919 (define_insn "indirect_jump"
3921 (match_operand:SI 0 "s_register_operand" "r"))]
3924 return arm_output_asm_insn (\"mov\\tpc, %0\\t@ indirect jump\", operands);
3929 (match_operand:SI 0 "memory_operand" "m"))]
3932 return arm_output_asm_insn (\"ldr\\tpc, %0\\t@ indirect jump\", operands);
3934 [(set_attr "type" "load")])
3942 return arm_output_asm_insn (\"mov\\tr0, r0\\t@ nop\", operands);
3945 ;; Patterns to allow combination of arithmetic, cond code and shifts
3948 [(set (match_operand:SI 0 "s_register_operand" "=r")
3949 (match_operator:SI 1 "shiftable_operator"
3950 [(match_operator:SI 3 "shift_operator"
3951 [(match_operand:SI 4 "s_register_operand" "r")
3952 (match_operand:SI 5 "nonmemory_operand" "rI")])
3953 (match_operand:SI 2 "s_register_operand" "r")]))]
3956 return (output_arithmetic_with_shift (operands, TRUE, FALSE));
3960 [(set (reg:CC_NOOV 24)
3961 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
3962 [(match_operator:SI 3 "shift_operator"
3963 [(match_operand:SI 4 "s_register_operand" "r")
3964 (match_operand:SI 5 "nonmemory_operand" "rI")])
3965 (match_operand:SI 2 "s_register_operand" "r")])
3967 (set (match_operand:SI 0 "s_register_operand" "=r")
3968 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
3972 return (output_arithmetic_with_shift (operands, TRUE, TRUE));
3974 [(set_attr "conds" "set")])
3977 [(set (reg:CC_NOOV 24)
3978 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
3979 [(match_operator:SI 3 "shift_operator"
3980 [(match_operand:SI 4 "s_register_operand" "r")
3981 (match_operand:SI 5 "nonmemory_operand" "rI")])
3982 (match_operand:SI 2 "s_register_operand" "r")])
3984 (clobber (match_scratch:SI 0 "=r"))]
3987 return (output_arithmetic_with_shift (operands, TRUE, TRUE));
3989 [(set_attr "conds" "set")])
3992 [(set (match_operand:SI 0 "s_register_operand" "=r")
3993 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
3994 (match_operator:SI 2 "shift_operator"
3995 [(match_operand:SI 3 "s_register_operand" "r")
3996 (match_operand:SI 4 "nonmemory_operand" "rn")])))]
4002 ops[0] = operands[0];
4003 ops[1] = gen_rtx (MINUS, SImode, operands[1], operands[2]);
4004 ops[2] = operands[1];
4005 ops[3] = operands[2];
4006 ops[4] = operands[3];
4007 ops[5] = operands[4];
4008 return output_arithmetic_with_shift (ops, FALSE, FALSE);
4013 [(set (reg:CC_NOOV 24)
4014 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4015 (match_operator:SI 2 "shift_operator"
4016 [(match_operand:SI 3 "s_register_operand" "r")
4017 (match_operand:SI 4 "nonmemory_operand" "rn")]))
4019 (set (match_operand:SI 0 "s_register_operand" "=r")
4020 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4027 ops[0] = operands[0];
4028 ops[1] = gen_rtx (MINUS, SImode, operands[1], operands[2]);
4029 ops[2] = operands[1];
4030 ops[3] = operands[2];
4031 ops[4] = operands[3];
4032 ops[5] = operands[4];
4033 return output_arithmetic_with_shift (ops, FALSE, TRUE);
4036 [(set_attr "conds" "set")])
4039 [(set (reg:CC_NOOV 24)
4040 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4041 (match_operator:SI 2 "shift_operator"
4042 [(match_operand:SI 3 "s_register_operand" "r")
4043 (match_operand:SI 4 "nonmemory_operand" "rn")]))
4045 (clobber (match_scratch:SI 0 "=r"))]
4051 ops[0] = operands[0];
4052 ops[1] = gen_rtx (MINUS, SImode, operands[1], operands[2]);
4053 ops[2] = operands[1];
4054 ops[3] = operands[2];
4055 ops[4] = operands[3];
4056 ops[5] = operands[4];
4057 return output_arithmetic_with_shift (ops, FALSE, TRUE);
4060 [(set_attr "conds" "set")])
4062 ;; These variants of the above insns can occur if the first operand is the
4063 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
4064 ;; seem to be a way around it. Most of the predicates have to be null
4065 ;; because the format can be generated part way through reload, so
4066 ;; if we don't match it as soon as it becomes available, reload doesn't know
4067 ;; how to reload pseudos that haven't got hard registers; the constraints will
4068 ;; sort everything out.
4071 [(set (match_operand:SI 0 "" "=&r")
4072 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4073 [(match_operand:SI 3 "" "r")
4074 (match_operand:SI 4 "" "rn")])
4075 (match_operand:SI 2 "" "r"))
4076 (match_operand:SI 1 "const_int_operand" "n")))]
4077 "reload_in_progress"
4081 sprintf (instr, \"add\\t%%0, %%2, %%3, %s %%4\",
4082 shift_instr (GET_CODE (operands[5]), &operands[4]));
4083 arm_output_asm_insn (instr, operands);
4084 operands[2] = operands[1];
4085 operands[1] = operands[0];
4086 return output_add_immediate (operands);
4088 ; we have no idea how long the add_immediate is, it could be up to 4.
4089 [(set_attr "length" "5")])
4092 [(set (reg:CC_NOOV 24)
4093 (compare:CC_NOOV (plus:SI
4095 (match_operator:SI 5 "shift_operator"
4096 [(match_operand:SI 3 "" "r")
4097 (match_operand:SI 4 "" "rn")])
4098 (match_operand:SI 1 "" "r"))
4099 (match_operand:SI 2 "const_int_operand" "n"))
4101 (set (match_operand:SI 0 "" "=&r")
4102 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4105 "reload_in_progress"
4109 sprintf (instr, \"adds\\t%%0, %%0, %%3, %s %%4\",
4110 shift_instr (GET_CODE (operands[5]), &operands[4]));
4111 output_add_immediate (operands);
4112 return arm_output_asm_insn (instr, operands);
4114 [(set_attr "conds" "set")
4115 (set_attr "length" "5")])
4118 [(set (reg:CC_NOOV 24)
4119 (compare:CC_NOOV (plus:SI
4121 (match_operator:SI 5 "shift_operator"
4122 [(match_operand:SI 3 "" "r")
4123 (match_operand:SI 4 "" "rn")])
4124 (match_operand:SI 1 "" "r"))
4125 (match_operand:SI 2 "const_int_operand" "n"))
4127 (clobber (match_scratch:SI 0 "=&r"))]
4128 "reload_in_progress"
4132 sprintf (instr, \"adds\\t%%0, %%0, %%3, %s %%4\",
4133 shift_instr (GET_CODE (operands[5]), &operands[4]));
4134 output_add_immediate (operands);
4135 return arm_output_asm_insn (instr, operands);
4137 [(set_attr "conds" "set")
4138 (set_attr "length" "5")])
4142 [(set (match_operand:SI 0 "s_register_operand" "=r")
4143 (and:SI (match_operator 1 "comparison_operator"
4144 [(reg 24) (const_int 0)])
4145 (match_operand:SI 2 "s_register_operand" "r")))]
4148 arm_output_asm_insn (\"mov%D1\\t%0, #0\", operands);
4149 return arm_output_asm_insn (\"and%d1\\t%0, %2, #1\", operands);
4151 [(set_attr "conds" "use")
4152 (set_attr "length" "2")])
4155 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4156 (ior:SI (match_operator 2 "comparison_operator"
4157 [(reg 24) (const_int 0)])
4158 (match_operand:SI 1 "s_register_operand" "0,?r")))]
4161 if (which_alternative != 0)
4162 arm_output_asm_insn (\"mov%D2\\t%0, %1\", operands);
4163 return arm_output_asm_insn (\"orr%d2\\t%0, %1, #1\", operands);
4165 [(set_attr "conds" "use")
4166 (set_attr "length" "1,2")])
4169 [(set (match_operand:SI 0 "s_register_operand" "=r")
4170 (match_operator 1 "comparison_operator"
4171 [(match_operand:SI 2 "s_register_operand" "r")
4172 (match_operand:SI 3 "arm_add_operand" "rL")]))
4176 if (GET_CODE (operands[1]) == LT)
4178 if (operands[3] == const0_rtx)
4179 return arm_output_asm_insn (\"mov\\t%0, %2, lsr #31\", operands);
4180 if (GET_CODE (operands[3]) == CONST_INT
4181 && !const_ok_for_arm (INTVAL (operands[3])))
4182 arm_output_asm_insn (\"add\\t%0, %2, #%n3\", operands);
4184 arm_output_asm_insn (\"sub\\t%0, %2, %3\", operands);
4185 return arm_output_asm_insn (\"mov\\t%0, %0, lsr #31\", operands);
4187 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4189 arm_output_asm_insn (\"mvn\\t%0, %2\", operands);
4190 return arm_output_asm_insn (\"mov\\t%0, %0, lsr #31\", operands);
4192 if (GET_CODE (operands[1]) == NE)
4194 if (GET_CODE (operands[3]) == CONST_INT
4195 && !const_ok_for_arm (INTVAL (operands[3])))
4196 arm_output_asm_insn (\"adds\\t%0, %2, #%n3\", operands);
4198 arm_output_asm_insn (\"subs\\t%0, %2, %3\", operands);
4199 return arm_output_asm_insn (\"movne\\t%0, #1\", operands);
4201 if (GET_CODE (operands[3]) == CONST_INT
4202 && !const_ok_for_arm (INTVAL (operands[3])))
4203 arm_output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4205 arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4206 arm_output_asm_insn (\"mov%D1\\t%0, #0\", operands);
4207 return arm_output_asm_insn (\"mov%d1\\t%0, #1\", operands);
4209 [(set_attr "conds" "clob")
4210 (set_attr "length" "3")])
4213 [(set (match_operand:SI 0 "s_register_operand" "=&r")
4214 (ior:SI (match_operator 1 "comparison_operator"
4215 [(match_operand:SI 2 "s_register_operand" "r")
4216 (match_operand:SI 3 "arm_rhs_operand" "rI")])
4217 (match_operator 4 "comparison_operator"
4218 [(match_operand:SI 5 "s_register_operand" "r")
4219 (match_operand:SI 6 "arm_rhs_operand" "rI")])))
4224 int dominant = comparison_dominates_p (GET_CODE (operands[4]),
4225 GET_CODE (operands[1]));
4227 arm_output_asm_insn (dominant ? \"cmp\\t%5, %6\" : \"cmp\\t%2, %3\",
4229 arm_output_asm_insn (\"mov\\t%0, #0\", operands);
4230 if (GET_CODE (operands[1]) == GET_CODE (operands[4])
4231 || comparison_dominates_p (GET_CODE (operands[1]),
4232 GET_CODE (operands[4]))
4235 arm_output_asm_insn (dominant ? \"cmp%D4\\t%2, %3\" : \"cmp%D1\\t%5,%6\",
4240 arm_output_asm_insn (\"mov%d1\\t%0, #1\", operands);
4241 arm_output_asm_insn (\"cmp\\t%5, %6\", operands);
4243 return arm_output_asm_insn (dominant ? \"mov%d1\\t%0, #1\"
4244 : \"mov%d4\\t%0, #1\", operands);
4247 [(set_attr "conds" "clob")
4249 (set_attr "length" "5")])
4253 (if_then_else (match_operator 5 "equality_operator"
4254 [(ior:SI (match_operator 6 "comparison_operator"
4255 [(match_operand:SI 0 "s_register_operand" "r")
4256 (match_operand:SI 1 "arm_add_operand" "rL")])
4257 (match_operator 7 "comparison_operator"
4258 [(match_operand:SI 2 "s_register_operand" "r")
4259 (match_operand:SI 3 "arm_add_operand" "rL")]))
4261 (label_ref (match_operand 4 "" ""))
4264 "(GET_CODE (operands[6]) == GET_CODE (operands[7])
4265 || comparison_dominates_p (GET_CODE (operands[6]), GET_CODE (operands[7]))
4266 || comparison_dominates_p (GET_CODE (operands[7]), GET_CODE (operands[6])))"
4268 (compare:CC (ior:CC (match_op_dup 6
4269 [(match_dup 0) (match_dup 1)])
4271 [(match_dup 2) (match_dup 3)]))
4274 (if_then_else (match_op_dup 5 [(reg:CC 24) (const_int 0)])
4275 (label_ref (match_dup 4))
4279 enum rtx_code code = comparison_dominates_p (GET_CODE (operands[6]),
4280 GET_CODE (operands[7]))
4281 ? GET_CODE (operands[7]) : GET_CODE (operands[6]);
4283 if (GET_CODE (operands[5]) == NE)
4284 operands[5] = gen_rtx (code, CCmode,
4285 XEXP (operands[5], 0), XEXP (operands[5], 1));
4287 operands[5] = gen_rtx (reverse_condition (code), CCmode,
4288 XEXP (operands[5], 0), XEXP (operands[5], 1));
4292 ;; Don't match these patterns if we can use a conditional compare, since they
4293 ;; tell the final prescan branch elimator code that full branch inlining
4299 (ior:SI (match_operator 5 "comparison_operator"
4300 [(match_operand:SI 0 "s_register_operand" "r")
4301 (match_operand:SI 1 "arm_add_operand" "rL")])
4302 (match_operator 6 "comparison_operator"
4303 [(match_operand:SI 2 "s_register_operand" "r")
4304 (match_operand:SI 3 "arm_rhs_operand" "rL")]))
4306 (label_ref (match_operand 4 "" ""))
4309 "!(GET_CODE (operands[5]) == GET_CODE (operands[6])
4310 || comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[6]))
4311 || comparison_dominates_p (GET_CODE (operands[6]), GET_CODE (operands[5])))"
4314 extern int arm_ccfsm_state;
4316 if (GET_CODE (operands[1]) == CONST_INT
4317 && !const_ok_for_arm (INTVAL (operands[1])))
4318 arm_output_asm_insn (\"cmn\\t%0, #%n1\", operands);
4320 arm_output_asm_insn (\"cmp\\t%0, %1\", operands);
4321 arm_output_asm_insn (\"b%d5\\t%l4\", operands);
4322 if (GET_CODE (operands[3]) == CONST_INT
4323 && !const_ok_for_arm (INTVAL (operands[3])))
4324 arm_output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4326 arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4327 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4329 arm_ccfsm_state += 2;
4332 return arm_output_asm_insn (\"b%d6\\t%l4\", operands);
4334 [(set_attr "conds" "jump_clob")
4335 (set_attr "length" "4")])
4339 (compare:CC (ior:CC (match_operator 4 "comparison_operator"
4340 [(match_operand:SI 0 "s_register_operand" "r")
4341 (match_operand:SI 1 "arm_add_operand" "rL")])
4342 (match_operator 5 "comparison_operator"
4343 [(match_operand:SI 2 "s_register_operand" "r")
4344 (match_operand:SI 3 "arm_add_operand" "rL")]))
4346 "(GET_CODE (operands[4]) == GET_CODE (operands[5])
4347 || comparison_dominates_p (GET_CODE (operands[4]), GET_CODE (operands[5]))
4348 || comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])))"
4350 if (comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4])))
4352 if (GET_CODE (operands[3]) == CONST_INT
4353 && !const_ok_for_arm (INTVAL (operands[3])))
4354 arm_output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4356 arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4357 if (GET_CODE (operands[1]) == CONST_INT
4358 && !const_ok_for_arm (INTVAL (operands[1])))
4359 return arm_output_asm_insn (\"cmn%D5\\t%0, #%n1\", operands);
4360 return arm_output_asm_insn (\"cmp%D5\\t%0, %1\", operands);
4362 if (GET_CODE (operands[1]) == CONST_INT
4363 && !const_ok_for_arm (INTVAL (operands[1])))
4364 arm_output_asm_insn (\"cmn\\t%0, #%n1\", operands);
4366 arm_output_asm_insn (\"cmp\\t%0, %1\", operands);
4367 if (GET_CODE (operands[3]) == CONST_INT
4368 && !const_ok_for_arm (INTVAL (operands[3])))
4369 return arm_output_asm_insn (\"cmn%D4\\t%2, #%n3\", operands);
4370 return arm_output_asm_insn (\"cmp%D4\\t%2, %3\", operands);
4372 [(set_attr "conds" "set")
4373 (set_attr "length" "2")])
4376 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4377 (if_then_else (match_operator 3 "equality_operator"
4378 [(match_operator 4 "comparison_operator"
4379 [(reg 24) (const_int 0)])
4381 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4382 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4385 if (GET_CODE (operands[3]) == NE)
4387 if (which_alternative != 0)
4388 arm_output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4389 if (which_alternative != 1)
4390 arm_output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4393 if (which_alternative != 0)
4394 arm_output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4395 if (which_alternative != 1)
4396 arm_output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4399 [(set_attr "conds" "use")
4400 (set_attr "length" "1,1,2")])
4403 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4404 (match_operator:SI 5 "shiftable_operator"
4405 [(match_operator:SI 4 "comparison_operator"
4406 [(match_operand:SI 2 "s_register_operand" "r,r")
4407 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4408 (match_operand:SI 1 "s_register_operand" "0,?r")]))
4413 char *instr = arithmetic_instr (operands[5], TRUE);
4416 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4418 sprintf (pattern, \"%s\\t%%0, %%1, %%2, lsr #31\", instr);
4419 return arm_output_asm_insn (pattern, operands);
4421 arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4422 if (GET_CODE (operands[5]) == AND)
4423 arm_output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4424 else if (which_alternative != 0)
4425 arm_output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4426 sprintf (pattern, \"%s%%d4\\t%%0, %%1, #1\", instr);
4427 return arm_output_asm_insn (pattern, operands);
4430 [(set_attr "conds" "clob")
4431 (set_attr "length" "3")])
4434 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4435 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4436 (match_operator:SI 4 "comparison_operator"
4437 [(match_operand:SI 2 "s_register_operand" "r,r")
4438 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4442 arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4443 if (which_alternative != 0)
4444 arm_output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4445 return arm_output_asm_insn (\"sub%d4\\t%0, %1, #1\", operands);
4447 [(set_attr "conds" "clob")
4448 (set_attr "length" "2,3")])
4451 [(set (match_operand:SI 0 "s_register_operand" "=&r")
4452 (and:SI (match_operator 1 "comparison_operator"
4453 [(match_operand:SI 2 "s_register_operand" "r")
4454 (match_operand:SI 3 "arm_rhs_operand" "rI")])
4455 (match_operator 4 "comparison_operator"
4456 [(match_operand:SI 5 "s_register_operand" "r")
4457 (match_operand:SI 6 "arm_rhs_operand" "rI")])))
4463 comparison_dominates_p (reverse_condition (GET_CODE (operands[1])),
4464 reverse_condition (GET_CODE (operands[4])))
4466 : comparison_dominates_p (reverse_condition (GET_CODE (operands[4])),
4467 reverse_condition (GET_CODE (operands[1])))
4469 arm_output_asm_insn (dominant == 2 ? \"cmp\\t%5, %6\" : \"cmp\\t%2, %3\",
4471 arm_output_asm_insn (\"mov\\t%0, #1\", operands);
4472 if (GET_CODE (operands[1]) == GET_CODE (operands[4]) || dominant)
4474 arm_output_asm_insn (dominant == 2 ? \"cmp%d4\\t%2, %3\"
4475 : \"cmp%d1\\t%5, %6\", operands);
4479 arm_output_asm_insn (\"mov%D1\\t%0, #0\", operands);
4480 arm_output_asm_insn (\"cmp\\t%5, %6\", operands);
4482 return arm_output_asm_insn (dominant == 2 ? \"mov%D1\\t%0, #0\"
4483 : \"mov%D4\\t%0, #0\", operands);
4486 [(set_attr "conds" "clob")
4487 (set_attr "length" "5")])
4491 (if_then_else (match_operator 1 "equality_operator"
4492 [(and:SI (match_operator 2 "comparison_operator"
4493 [(match_operand:SI 3 "s_register_operand" "r")
4494 (match_operand:SI 4 "arm_add_operand" "rL")])
4495 (match_operator 0 "comparison_operator"
4496 [(match_operand:SI 5 "s_register_operand" "r")
4497 (match_operand:SI 6 "arm_add_operand" "rL")]))
4499 (label_ref (match_operand 7 "" ""))
4502 "(GET_CODE (operands[2]) == GET_CODE (operands[0])
4503 || comparison_dominates_p (reverse_condition (GET_CODE (operands[2])),
4504 reverse_condition (GET_CODE (operands[0])))
4505 || comparison_dominates_p (reverse_condition (GET_CODE (operands[0])),
4506 reverse_condition (GET_CODE (operands[2]))))"
4508 (compare:CC (ior:CC (match_op_dup 2
4509 [(match_dup 3) (match_dup 4)])
4511 [(match_dup 5) (match_dup 6)]))
4514 (if_then_else (match_op_dup 1 [(reg:CC 24) (const_int 0)])
4515 (label_ref (match_dup 7))
4519 /* Use DeMorgans law to convert this into an IOR of the inverse conditions
4520 This is safe since we only do it for integer comparisons. */
4521 enum rtx_code code =
4522 comparison_dominates_p (reverse_condition (GET_CODE (operands[2])),
4523 reverse_condition (GET_CODE (operands[0])))
4524 ? GET_CODE (operands[0]) : GET_CODE (operands[2]);
4526 operands[2] = gen_rtx (reverse_condition (GET_CODE (operands[2])),
4527 GET_MODE (operands[2]), operands[3], operands[4]);
4528 operands[0] = gen_rtx (reverse_condition (GET_CODE (operands[0])),
4529 GET_MODE (operands[0]), operands[5], operands[6]);
4530 if (GET_CODE (operands[1]) == NE)
4531 operands[1] = gen_rtx (code, CCmode,
4532 XEXP (operands[1], 0), XEXP (operands[1], 1));
4534 operands[1] = gen_rtx (reverse_condition (code), CCmode,
4535 XEXP (operands[1], 0), XEXP (operands[1], 1));
4539 ;; Don't match these patterns if we can use a conditional compare, since they
4540 ;; tell the final prescan branch elimator code that full branch inlining
4546 (and:SI (match_operator 1 "comparison_operator"
4547 [(match_operand:SI 2 "s_register_operand" "r")
4548 (match_operand:SI 3 "arm_add_operand" "rL")])
4549 (match_operator 4 "comparison_operator"
4550 [(match_operand:SI 5 "s_register_operand" "r")
4551 (match_operand:SI 6 "arm_rhs_operand" "rL")]))
4553 (label_ref (match_operand 0 "" ""))
4556 "!(GET_CODE (operands[1]) == GET_CODE (operands[4])
4557 || comparison_dominates_p (reverse_condition (GET_CODE (operands[1])),
4558 reverse_condition (GET_CODE (operands[4])))
4559 || comparison_dominates_p (reverse_condition (GET_CODE (operands[4])),
4560 reverse_condition (GET_CODE (operands[1]))))"
4563 extern int arm_ccfsm_state;
4565 if (GET_CODE (operands[3]) == CONST_INT
4566 && !const_ok_for_arm (INTVAL (operands[3])))
4567 arm_output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4569 arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4570 arm_output_asm_insn (\"b%D1\\t%l0\", operands);
4571 if (GET_CODE (operands[6]) == CONST_INT
4572 && !const_ok_for_arm (INTVAL (operands[6])))
4573 arm_output_asm_insn (\"cmn\\t%5, #%n6\", operands);
4575 arm_output_asm_insn (\"cmp\\t%5, %6\", operands);
4576 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4578 arm_ccfsm_state += 2;
4581 return arm_output_asm_insn (\"b%D4\\t%l0\", operands);
4583 [(set_attr "conds" "jump_clob")
4584 (set_attr "length" "4")])
4587 [(set (match_operand:SI 0 "s_register_operand" "=r")
4588 (neg:SI (match_operator 3 "comparison_operator"
4589 [(match_operand:SI 1 "s_register_operand" "r")
4590 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4594 if (GET_CODE (operands[3]) == LT)
4596 if (operands[3] == const0_rtx)
4597 return arm_output_asm_insn (\"mov\\t%0, %1, asr #31\", operands);
4598 arm_output_asm_insn (\"sub\\t%0, %1, %2\", operands);
4599 return arm_output_asm_insn (\"mov\\t%0, %0, asr #31\", operands);
4601 if (GET_CODE (operands[3]) == NE)
4603 arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
4604 return arm_output_asm_insn (\"mvnne\\t%0, #0\", operands);
4606 if (GET_CODE (operands[3]) == GT)
4608 arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
4609 return arm_output_asm_insn (\"mvnne\\t%0, %0, asr #31\", operands);
4611 arm_output_asm_insn (\"cmp\\t%1, %2\", operands);
4612 arm_output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4613 return arm_output_asm_insn (\"mvn%d3\\t%0, #0\", operands);
4615 [(set_attr "conds" "clob")
4616 (set_attr "length" "3")])
4618 (define_insn "movcond"
4619 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4620 (if_then_else:SI (match_operator 5 "comparison_operator"
4621 [(match_operand:SI 3 "s_register_operand" "r,r,r")
4622 (match_operand:SI 4 "arm_add_operand" "rL,rL,rL")])
4623 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4624 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4628 if (GET_CODE (operands[5]) == LT
4629 && (operands[4] == const0_rtx))
4631 if (which_alternative != 1 && GET_CODE (operands[4]) == REG)
4633 arm_output_asm_insn (\"ands\\t%0, %1, %3, asr #32\", operands);
4634 if (operands[2] == const0_rtx)
4636 return arm_output_asm_insn (\"movcc\\t%0, %2\", operands);
4638 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4640 arm_output_asm_insn (\"bics\\t%0, %2, %3, asr #32\", operands);
4641 if (operands[1] == const0_rtx)
4643 return arm_output_asm_insn (\"movcs\\t%0, %1\", operands);
4645 /* The only case that falls through to here is when both ops 1 & 2
4648 if (GET_CODE (operands[5]) == GE
4649 && (operands[4] == const0_rtx))
4651 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4653 arm_output_asm_insn (\"bics\\t%0, %1, %3, asr #32\", operands);
4654 if (operands[2] == const0_rtx)
4656 return arm_output_asm_insn (\"movcs\\t%0, %2\", operands);
4658 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4660 arm_output_asm_insn (\"ands\\t%0, %2, %3, asr #32\", operands);
4661 if (operands[1] == const0_rtx)
4663 return arm_output_asm_insn (\"movcc\\t%0, %1\", operands);
4665 /* The only case that falls through to here is when both ops 1 & 2
4668 if (GET_CODE (operands[4]) == CONST_INT
4669 && !const_ok_for_arm (INTVAL (operands[4])))
4670 arm_output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4672 arm_output_asm_insn (\"cmp\\t%3, %4\", operands);
4673 if (which_alternative != 0)
4674 arm_output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4675 if (which_alternative != 1)
4676 arm_output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4679 [(set_attr "conds" "clob")
4680 (set_attr "length" "2,2,3")])
4683 [(set (match_operand:SI 0 "s_register_operand" "=r")
4684 (if_then_else:SI (match_operator 9 "comparison_operator"
4685 [(match_operand:SI 5 "s_register_operand" "r")
4686 (match_operand:SI 6 "arm_add_operand" "rL")])
4687 (match_operator:SI 8 "shiftable_operator"
4688 [(match_operand:SI 1 "s_register_operand" "r")
4689 (match_operand:SI 2 "arm_rhs_operand" "rI")])
4690 (match_operator:SI 7 "shiftable_operator"
4691 [(match_operand:SI 3 "s_register_operand" "r")
4692 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
4699 if (GET_CODE (operands[6]) == CONST_INT
4700 && !const_ok_for_arm (INTVAL (operands[6])))
4701 arm_output_asm_insn (\"cmn\\t%5, #%n6\", operands);
4703 arm_output_asm_insn (\"cmp\\t%5, %6\", operands);
4704 sprintf (pattern, \"%s%%d9\\t%%0, %%1, %%2\", arithmetic_instr (operands[8],
4706 arm_output_asm_insn (pattern, operands);
4707 sprintf (pattern, \"%s%%D9\\t%%0, %%3, %%4\", arithmetic_instr (operands[7],
4709 return arm_output_asm_insn (pattern, operands);
4712 [(set_attr "conds" "clob")
4713 (set_attr "length" "3")])
4716 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4717 (if_then_else:SI (match_operator 6 "comparison_operator"
4718 [(match_operand:SI 2 "s_register_operand" "r,r")
4719 (match_operand:SI 3 "arm_add_operand" "rL,rL")])
4720 (match_operator:SI 7 "shiftable_operator"
4721 [(match_operand:SI 4 "s_register_operand" "r,r")
4722 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
4723 (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4730 /* If we have an operation where (op x 0) is the identity operation and
4731 the condtional operator is LT or GE and we are comparing against zero and
4732 everything is in registers then we can do this in two instructions */
4733 if (operands[3] == const0_rtx
4734 && GET_CODE (operands[7]) != AND
4735 && GET_CODE (operands[5]) == REG
4736 && GET_CODE (operands[1]) == REG
4737 && REGNO (operands[1]) == REGNO (operands[4])
4738 && REGNO (operands[4]) != REGNO (operands[0]))
4740 if (GET_CODE (operands[6]) == LT)
4742 arm_output_asm_insn (\"and\\t%0, %5, %2, asr #31\", operands);
4743 sprintf (pattern, \"%s\\t%%0, %%4, %%0\",
4744 arithmetic_instr (operands[7], FALSE));
4745 return arm_output_asm_insn (pattern, operands);
4747 else if (GET_CODE (operands[6]) == GE)
4749 arm_output_asm_insn (\"bic\\t%0, %5, %2, asr #31\", operands);
4750 sprintf (pattern, \"%s\\t%%0, %%4, %%0\",
4751 arithmetic_instr (operands[7], FALSE));
4752 return arm_output_asm_insn (pattern, operands);
4755 if (GET_CODE (operands[3]) == CONST_INT
4756 && !const_ok_for_arm (INTVAL (operands[3])))
4757 arm_output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4759 arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4760 sprintf (pattern, \"%s%%d6\\t%%0, %%4, %%5\", arithmetic_instr (operands[7],
4762 arm_output_asm_insn (pattern, operands);
4763 if (which_alternative != 0)
4765 if (GET_CODE (operands[1]) == MEM)
4766 arm_output_asm_insn (\"ldr%D6\\t%0, %1\", operands);
4768 arm_output_asm_insn (\"mov%D6\\t%0, %1\", operands);
4773 [(set_attr "conds" "clob")
4774 (set_attr "length" "2,3")])
4777 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4778 (if_then_else:SI (match_operator 6 "comparison_operator"
4779 [(match_operand:SI 4 "s_register_operand" "r,r")
4780 (match_operand:SI 5 "arm_add_operand" "rL,rL")])
4781 (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4782 (match_operator:SI 7 "shiftable_operator"
4783 [(match_operand:SI 2 "s_register_operand" "r,r")
4784 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4791 /* If we have an operation where (op x 0) is the identity operation and
4792 the condtional operator is LT or GE and we are comparing against zero and
4793 everything is in registers then we can do this in two instructions */
4794 if (operands[5] == const0_rtx
4795 && GET_CODE (operands[7]) != AND
4796 && GET_CODE (operands[3]) == REG
4797 && GET_CODE (operands[1]) == REG
4798 && REGNO (operands[1]) == REGNO (operands[2])
4799 && REGNO (operands[2]) != REGNO (operands[0]))
4801 if (GET_CODE (operands[6]) == GE)
4803 arm_output_asm_insn (\"and\\t%0, %3, %4, asr #31\", operands);
4804 sprintf (pattern, \"%s\\t%%0, %%2, %%0\",
4805 arithmetic_instr (operands[7], FALSE));
4806 return arm_output_asm_insn (pattern, operands);
4808 else if (GET_CODE (operands[6]) == LT)
4810 arm_output_asm_insn (\"bic\\t%0, %3, %4, asr #31\", operands);
4811 sprintf (pattern, \"%s\\t%%0, %%2, %%0\",
4812 arithmetic_instr (operands[7], FALSE));
4813 return arm_output_asm_insn (pattern, operands);
4816 if (GET_CODE (operands[5]) == CONST_INT
4817 && !const_ok_for_arm (INTVAL (operands[5])))
4818 arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4820 arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
4821 if (which_alternative != 0)
4823 if (GET_CODE (operands[1]) == MEM)
4824 arm_output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4826 arm_output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4828 sprintf (pattern, \"%s%%D6\\t%%0, %%2, %%3\", arithmetic_instr (operands[7],
4830 return arm_output_asm_insn (pattern, operands);
4833 [(set_attr "conds" "clob")
4834 (set_attr "length" "2,3")])
4837 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4838 (if_then_else:SI (match_operator 6 "comparison_operator"
4839 [(match_operand:SI 4 "s_register_operand" "r,r")
4840 (match_operand:SI 5 "arm_add_operand" "rL,rL")])
4842 (match_operand:SI 2 "s_register_operand" "r,r")
4843 (match_operand:SI 3 "arm_add_operand" "rL,rL"))
4844 (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")))
4849 if (GET_CODE (operands[5]) == CONST_INT
4850 && !const_ok_for_arm (INTVAL (operands[5])))
4851 arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4853 arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
4854 if (GET_CODE (operands[3]) == CONST_INT
4855 && !const_ok_for_arm (INTVAL (operands[3])))
4856 arm_output_asm_insn (\"sub%d6\\t%0, %2, #%n3\", operands);
4858 arm_output_asm_insn (\"add%d6\\t%0, %2, %3\", operands);
4859 if (which_alternative != 0)
4861 if (GET_CODE (operands[1]) == MEM)
4862 arm_output_asm_insn (\"ldr%D6\\t%0, %1\", operands);
4864 arm_output_asm_insn (\"mov%D6\\t%0, %1\", operands);
4869 [(set_attr "conds" "clob")
4870 (set_attr "length" "2,3")])
4873 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4874 (if_then_else:SI (match_operator 6 "comparison_operator"
4875 [(match_operand:SI 4 "s_register_operand" "r,r")
4876 (match_operand:SI 5 "arm_add_operand" "rL,rL")])
4877 (match_operand:SI 1 "arm_rhsm_operand" "0,?rIm")
4879 (match_operand:SI 2 "s_register_operand" "r,r")
4880 (match_operand:SI 3 "arm_add_operand" "rL,rL"))))
4885 if (GET_CODE (operands[5]) == CONST_INT
4886 && !const_ok_for_arm (INTVAL (operands[5])))
4887 arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4889 arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
4890 if (GET_CODE (operands[3]) == CONST_INT
4891 && !const_ok_for_arm (INTVAL (operands[3])))
4892 arm_output_asm_insn (\"sub%D6\\t%0, %2, #%n3\", operands);
4894 arm_output_asm_insn (\"add%D6\\t%0, %2, %3\", operands);
4895 if (which_alternative != 0)
4897 if (GET_CODE (operands[6]) == MEM)
4898 arm_output_asm_insn (\"ldr%d6\\t%0, %1\", operands);
4900 arm_output_asm_insn (\"mov%d6\\t%0, %1\", operands);
4905 [(set_attr "conds" "clob")
4906 (set_attr "length" "2,3")])
4909 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4910 (if_then_else:SI (match_operator 5 "comparison_operator"
4911 [(match_operand:SI 3 "s_register_operand" "r,r")
4912 (match_operand:SI 4 "arm_add_operand" "rL,rL")])
4913 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4915 (match_operand:SI 2 "s_register_operand" "r,r"))))
4919 [(set_attr "conds" "clob")
4920 (set_attr "length" "2,3")])
4922 ;; if (GET_CODE (operands[3]) == CONST_INT
4923 ;; && !const_ok_for_arm (INTVAL (operands[3])))
4924 ;; arm_output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4926 ;; arm_output_asm_insn (\"cmp\\t%2, %3\", operands);
4927 ;; if (which_alternative != 0)
4928 ;; arm_output_asm_insn (\"mov%d1\\t%0, %4\", operands);
4929 ;; return arm_output_asm_insn (\"mvn%D1\\t%0, %5\", operands);
4932 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4933 (if_then_else:SI (match_operator 5 "comparison_operator"
4934 [(match_operand:SI 3 "s_register_operand" "r,r")
4935 (match_operand:SI 4 "arm_add_operand" "rL,rL")])
4937 (match_operand:SI 2 "s_register_operand" "r,r"))
4938 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
4945 if (GET_CODE (operands[30]) == CONST_INT
4946 && !const_ok_for_arm (INTVAL (operands[4])))
4947 arm_output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4949 arm_output_asm_insn (\"cmp\\t%3, %4\", operands);
4950 if (which_alternative != 0)
4951 arm_output_asm_insn (\"mov%D5\\t%0, %1\", operands);
4952 return arm_output_asm_insn (\"mvn%d5\\t%0, %2\", operands);
4956 [(set_attr "conds" "clob")
4957 (set_attr "length" "2,3")])
4960 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4961 (if_then_else:SI (match_operator 6 "comparison_operator"
4962 [(match_operand:SI 4 "s_register_operand" "r,r")
4963 (match_operand:SI 5 "arm_add_operand" "rL,rL")])
4964 (match_operator:SI 7 "shift_operator"
4965 [(match_operand:SI 2 "s_register_operand" "r,r")
4966 (match_operand:SI 3 "arm_rhs_operand" "rn,rn")])
4967 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
4974 if (GET_CODE (operands[5]) == CONST_INT
4975 && !const_ok_for_arm (INTVAL (operands[5])))
4976 arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
4978 arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
4979 if (which_alternative != 0)
4980 arm_output_asm_insn (\"mov%D6\\t%0, %1\", operands);
4981 sprintf (pattern, \"mov%%d6\\t%%0, %%2, %s %%3\",
4982 shift_instr (GET_CODE (operands[7]), &operands[3]));
4983 return arm_output_asm_insn (pattern, operands);
4986 [(set_attr "conds" "clob")
4987 (set_attr "length" "2,3")])
4990 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4991 (if_then_else:SI (match_operator 6 "comparison_operator"
4992 [(match_operand:SI 4 "s_register_operand" "r,r")
4993 (match_operand:SI 5 "arm_add_operand" "rL,rL")])
4994 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4995 (match_operator:SI 7 "shift_operator"
4996 [(match_operand:SI 2 "s_register_operand" "r,r")
4997 (match_operand:SI 3 "arm_rhs_operand" "rn,rn")])))
5004 if (GET_CODE (operands[5]) == CONST_INT
5005 && !const_ok_for_arm (INTVAL (operands[5])))
5006 arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5008 arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
5009 if (which_alternative != 0)
5010 arm_output_asm_insn (\"mov%d6\\t%0, %1\", operands);
5011 sprintf (pattern, \"mov%%D6\\t%%0, %%2, %s %%3\",
5012 shift_instr (GET_CODE (operands[7]), &operands[3]));
5013 return arm_output_asm_insn (pattern, operands);
5016 [(set_attr "conds" "clob")
5017 (set_attr "length" "2,3")])
5020 [(set (match_operand:SI 0 "s_register_operand" "=r")
5021 (if_then_else:SI (match_operator 7 "comparison_operator"
5022 [(match_operand:SI 5 "s_register_operand" "r")
5023 (match_operand:SI 6 "arm_add_operand" "rL")])
5024 (match_operator:SI 8 "shift_operator"
5025 [(match_operand:SI 1 "s_register_operand" "r")
5026 (match_operand:SI 2 "arm_rhs_operand" "rn")])
5027 (match_operator:SI 9 "shift_operator"
5028 [(match_operand:SI 3 "s_register_operand" "r")
5029 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
5036 if (GET_CODE (operands[6]) == CONST_INT
5037 && !const_ok_for_arm (INTVAL (operands[6])))
5038 arm_output_asm_insn (\"cmn\\t%5, #%n6\", operands);
5040 arm_output_asm_insn (\"cmp\\t%5, %6\", operands);
5041 sprintf (pattern, \"mov%%d7\\t%%0, %%1, %s %%2\",
5042 shift_instr (GET_CODE (operands[8]), &operands[2]));
5043 arm_output_asm_insn (pattern, operands);
5044 sprintf (pattern, \"mov%%D7\\t%%0, %%3, %s %%4\",
5045 shift_instr (GET_CODE (operands[9]), &operands[4]));
5046 return arm_output_asm_insn (pattern, operands);
5049 [(set_attr "conds" "clob")
5050 (set_attr "length" "3")])
5053 [(set (match_operand:SI 0 "s_register_operand" "=r")
5054 (if_then_else:SI (match_operator 6 "comparison_operator"
5055 [(match_operand:SI 4 "s_register_operand" "r")
5056 (match_operand:SI 5 "arm_add_operand" "rL")])
5057 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5058 (match_operator:SI 7 "shiftable_operator"
5059 [(match_operand:SI 2 "s_register_operand" "r")
5060 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5067 if (GET_CODE (operands[5]) == CONST_INT
5068 && !const_ok_for_arm (INTVAL (operands[5])))
5069 arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5071 arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
5072 arm_output_asm_insn (\"mvn%d6\\t%0, %1\", operands);
5073 sprintf (pattern, \"%s%%D6\\t%%0, %%2, %%3\", arithmetic_instr (operands[7],
5075 return arm_output_asm_insn (pattern, operands);
5078 [(set_attr "conds" "clob")
5079 (set_attr "length" "3")])
5082 [(set (match_operand:SI 0 "s_register_operand" "=r")
5083 (if_then_else:SI (match_operator 6 "comparison_operator"
5084 [(match_operand:SI 4 "s_register_operand" "r")
5085 (match_operand:SI 5 "arm_add_operand" "rL")])
5086 (match_operator:SI 7 "shiftable_operator"
5087 [(match_operand:SI 2 "s_register_operand" "r")
5088 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5089 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5096 if (GET_CODE (operands[5]) == CONST_INT
5097 && !const_ok_for_arm (INTVAL (operands[5])))
5098 arm_output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5100 arm_output_asm_insn (\"cmp\\t%4, %5\", operands);
5101 arm_output_asm_insn (\"mvn%D6\\t%0, %1\", operands);
5102 sprintf (pattern, \"%s%%d6\\t%%0, %%2, %%3\", arithmetic_instr (operands[7],
5104 return arm_output_asm_insn (pattern, operands);
5107 [(set_attr "conds" "clob")
5108 (set_attr "length" "3")])
5111 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5112 (if_then_else:SI (match_operator 5 "comparison_operator"
5113 [(match_operand:SI 3 "s_register_operand" "r,r")
5114 (match_operand:SI 4 "arm_add_operand" "rL,rL")])
5116 (match_operand:SI 2 "s_register_operand" "r,r"))
5117 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5118 (clobber (reg:CC 24))]
5121 if (GET_CODE (operands[4]) == CONST_INT
5122 && !const_ok_for_arm (INTVAL (operands[4])))
5123 arm_output_asm_insn (\"cmn\\t%3, #%n4\", operands);
5125 arm_output_asm_insn (\"cmp\\t%3, %4\", operands);
5126 if (which_alternative != 0)
5127 arm_output_asm_insn (\"mov%D5\\t%0, %1\", operands);
5128 return arm_output_asm_insn (\"rsb%d5\\t%0, %2, #0\", operands);
5130 [(set_attr "conds" "clob")
5131 (set_attr "length" "2,3")])
5134 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5135 (if_then_else:SI (match_operator 5 "comparison_operator"
5136 [(match_operand:SI 3 "s_register_operand" "r,r")
5137 (match_operand:SI 4 "arm_add_operand" "rL,rL")])
5138 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5140 (match_operand:SI 2 "s_register_operand" "r,r"))))
5141 (clobber (reg:CC 24))]
5144 if (GET_CODE (operands[4]) == CONST_INT
5145 && !const_ok_for_arm (INTVAL (operands[4])))
5146 arm_output_asm_insn (\"cmn\\t%3, #%n4\", operands);
5148 arm_output_asm_insn (\"cmp\\t%3, %4\", operands);
5149 if (which_alternative != 0)
5150 arm_output_asm_insn (\"mov%d5\\t%0, %1\", operands);
5151 return arm_output_asm_insn (\"rsb%D5\\t%0, %2, #0\", operands);
5153 [(set_attr "conds" "clob")
5154 (set_attr "length" "2,3")])
5157 [(set (match_operand:SI 0 "s_register_operand" "=r")
5158 (match_operator:SI 1 "shiftable_operator"
5159 [(match_operand:SI 2 "memory_operand" "m")
5160 (match_operand:SI 3 "memory_operand" "m")]))
5161 (clobber (match_scratch:SI 4 "=r"))]
5162 "adjacent_mem_locations (operands[2], operands[3])"
5168 int val1 = 0, val2 = 0;
5170 sprintf (pattern, \"%s\\t%%0, %%1, %%2\",
5171 arithmetic_instr (operands[1], FALSE));
5172 if (REGNO (operands[0]) > REGNO (operands[4]))
5174 ldm[1] = operands[4];
5175 ldm[2] = operands[0];
5179 ldm[1] = operands[0];
5180 ldm[2] = operands[4];
5182 if (GET_CODE (XEXP (operands[2], 0)) != REG)
5183 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5184 if (GET_CODE (XEXP (operands[3], 0)) != REG)
5185 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5186 arith[0] = operands[0];
5200 ldm[0] = ops[0] = operands[4];
5201 ops[1] = XEXP (XEXP (operands[2], 0), 0);
5202 ops[2] = XEXP (XEXP (operands[2], 0), 1);
5203 output_add_immediate (ops);
5205 arm_output_asm_insn (\"ldmia\\t%0, {%1, %2}\", ldm);
5207 arm_output_asm_insn (\"ldmda\\t%0, {%1, %2}\", ldm);
5211 ldm[0] = XEXP (operands[3], 0);
5213 arm_output_asm_insn (\"ldmda\\t%0, {%1, %2}\", ldm);
5215 arm_output_asm_insn (\"ldmia\\t%0, {%1, %2}\", ldm);
5219 ldm[0] = XEXP (operands[2], 0);
5221 arm_output_asm_insn (\"ldmia\\t%0, {%1, %2}\", ldm);
5223 arm_output_asm_insn (\"ldmda\\t%0, {%1, %2}\", ldm);
5225 return arm_output_asm_insn (pattern, arith);
5228 [(set_attr "length" "3")
5229 (set_attr "type" "load")])
5231 ;; the arm can support extended pre-inc instructions
5233 ;; In all these cases, we use operands 0 and 1 for the register being
5234 ;; incremented because those are the operands that local-alloc will
5235 ;; tie and these are the pair most likely to be tieable (and the ones
5236 ;; that will benefit the most).
5238 ;; We reject the frame pointer if it occurs anywhere in these patterns since
5239 ;; elimination will cause too many headaches.
5242 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5243 (match_operand:SI 2 "index_operand" "rJ")))
5244 (match_operand:QI 3 "s_register_operand" "r"))
5245 (set (match_operand:SI 0 "s_register_operand" "=r")
5246 (plus:SI (match_dup 1) (match_dup 2)))]
5247 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5248 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5249 && (GET_CODE (operands[2]) != REG
5250 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5252 return arm_output_asm_insn (\"strb\\t%3, [%0, %2]!\", operands);
5254 [(set_attr "type" "store1")])
5257 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5258 (match_operand:SI 2 "s_register_operand" "r")))
5259 (match_operand:QI 3 "s_register_operand" "r"))
5260 (set (match_operand:SI 0 "s_register_operand" "=r")
5261 (minus:SI (match_dup 1) (match_dup 2)))]
5262 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5263 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5264 && (GET_CODE (operands[2]) != REG
5265 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5267 return arm_output_asm_insn (\"strb\\t%3, [%0, -%2]!\", operands);
5269 [(set_attr "type" "store1")])
5272 [(set (match_operand:QI 3 "s_register_operand" "=r")
5273 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5274 (match_operand:SI 2 "index_operand" "rJ"))))
5275 (set (match_operand:SI 0 "s_register_operand" "=r")
5276 (plus:SI (match_dup 1) (match_dup 2)))]
5277 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5278 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5279 && (GET_CODE (operands[2]) != REG
5280 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5282 return arm_output_asm_insn (\"ldrb\\t%3, [%0, %2]!\", operands);
5284 [(set_attr "type" "load")])
5287 [(set (match_operand:QI 3 "s_register_operand" "=r")
5288 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5289 (match_operand:SI 2 "s_register_operand" "r"))))
5290 (set (match_operand:SI 0 "s_register_operand" "=r")
5291 (minus:SI (match_dup 1) (match_dup 2)))]
5292 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5293 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5294 && (GET_CODE (operands[2]) != REG
5295 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5297 return arm_output_asm_insn (\"ldrb\\t%3, [%0, -%2]!\", operands);
5299 [(set_attr "type" "load")])
5302 [(set (match_operand:SI 3 "s_register_operand" "=r")
5304 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5305 (match_operand:SI 2 "index_operand" "rJ")))))
5306 (set (match_operand:SI 0 "s_register_operand" "=r")
5307 (plus:SI (match_dup 1) (match_dup 2)))]
5308 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5309 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5310 && (GET_CODE (operands[2]) != REG
5311 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5313 return arm_output_asm_insn (\"ldrb\\t%3, [%0, %2]!\\t@ z_extendqisi\",
5316 [(set_attr "type" "load")])
5319 [(set (match_operand:SI 3 "s_register_operand" "=r")
5321 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5322 (match_operand:SI 2 "s_register_operand" "r")))))
5323 (set (match_operand:SI 0 "s_register_operand" "=r")
5324 (minus:SI (match_dup 1) (match_dup 2)))]
5325 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5326 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5327 && (GET_CODE (operands[2]) != REG
5328 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5330 return arm_output_asm_insn (\"ldrb\\t%3, [%0, -%2]!\\t@ z_extendqisi\",
5333 [(set_attr "type" "load")])
5336 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5337 (match_operand:SI 2 "index_operand" "rJ")))
5338 (match_operand:SI 3 "s_register_operand" "r"))
5339 (set (match_operand:SI 0 "s_register_operand" "=r")
5340 (plus:SI (match_dup 1) (match_dup 2)))]
5341 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5342 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5343 && (GET_CODE (operands[2]) != REG
5344 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5346 return arm_output_asm_insn (\"str\\t%3, [%0, %2]!\", operands);
5348 [(set_attr "type" "store1")])
5351 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5352 (match_operand:SI 2 "s_register_operand" "r")))
5353 (match_operand:SI 3 "s_register_operand" "r"))
5354 (set (match_operand:SI 0 "s_register_operand" "=r")
5355 (minus:SI (match_dup 1) (match_dup 2)))]
5356 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5357 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5358 && (GET_CODE (operands[2]) != REG
5359 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5361 return arm_output_asm_insn (\"str\\t%3, [%0, -%2]!\", operands);
5363 [(set_attr "type" "store1")])
5366 [(set (match_operand:SI 3 "s_register_operand" "=r")
5367 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5368 (match_operand:SI 2 "index_operand" "rJ"))))
5369 (set (match_operand:SI 0 "s_register_operand" "=r")
5370 (plus:SI (match_dup 1) (match_dup 2)))]
5371 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5372 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5373 && (GET_CODE (operands[2]) != REG
5374 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5376 return arm_output_asm_insn (\"ldr\\t%3, [%0, %2]!\", operands);
5378 [(set_attr "type" "load")])
5381 [(set (match_operand:SI 3 "s_register_operand" "=r")
5382 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5383 (match_operand:SI 2 "s_register_operand" "r"))))
5384 (set (match_operand:SI 0 "s_register_operand" "=r")
5385 (minus:SI (match_dup 1) (match_dup 2)))]
5386 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5387 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5388 && (GET_CODE (operands[2]) != REG
5389 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5391 return arm_output_asm_insn (\"ldr\\t%3, [%0, -%2]!\", operands);
5393 [(set_attr "type" "load")])
5396 [(set (match_operand:HI 3 "s_register_operand" "=r")
5397 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5398 (match_operand:SI 2 "index_operand" "rJ"))))
5399 (set (match_operand:SI 0 "s_register_operand" "=r")
5400 (plus:SI (match_dup 1) (match_dup 2)))]
5401 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5402 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5403 && (GET_CODE (operands[2]) != REG
5404 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5406 return arm_output_asm_insn (\"ldr\\t%3, [%0, %2]!\\t@ loadhi\", operands);
5408 [(set_attr "type" "load")])
5411 [(set (match_operand:HI 3 "s_register_operand" "=r")
5412 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5413 (match_operand:SI 2 "s_register_operand" "r"))))
5414 (set (match_operand:SI 0 "s_register_operand" "=r")
5415 (minus:SI (match_dup 1) (match_dup 2)))]
5416 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5417 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5418 && (GET_CODE (operands[2]) != REG
5419 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5421 return arm_output_asm_insn (\"ldr\\t%3, [%0, -%2]!\\t@ loadhi\", operands);
5423 [(set_attr "type" "load")])
5426 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5427 [(match_operand:SI 3 "s_register_operand" "r")
5428 (match_operand:SI 4 "const_shift_operand" "n")])
5429 (match_operand:SI 1 "s_register_operand" "0")))
5430 (match_operand:QI 5 "s_register_operand" "r"))
5431 (set (match_operand:SI 0 "s_register_operand" "=r")
5432 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5434 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5435 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5436 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5441 sprintf (instr, \"strb\\t%%5, [%%0, %%3, %s %%4]!\",
5442 shift_instr (GET_CODE (operands[2]), &operands[4]));
5443 return arm_output_asm_insn (instr, operands);
5446 [(set_attr "type" "store1")])
5449 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5450 (match_operator:SI 2 "shift_operator"
5451 [(match_operand:SI 3 "s_register_operand" "r")
5452 (match_operand:SI 4 "const_shift_operand" "n")])))
5453 (match_operand:QI 5 "s_register_operand" "r"))
5454 (set (match_operand:SI 0 "s_register_operand" "=r")
5455 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5457 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5458 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5459 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5464 sprintf (instr, \"strb\\t%%5, [%%0, -%%3, %s %%4]!\",
5465 shift_instr (GET_CODE (operands[2]), &operands[4]));
5466 return arm_output_asm_insn (instr, operands);
5469 [(set_attr "type" "store1")])
5472 [(set (match_operand:QI 5 "s_register_operand" "=r")
5473 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5474 [(match_operand:SI 3 "s_register_operand" "r")
5475 (match_operand:SI 4 "const_shift_operand" "n")])
5476 (match_operand:SI 1 "s_register_operand" "0"))))
5477 (set (match_operand:SI 0 "s_register_operand" "=r")
5478 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5480 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5481 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5482 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5487 sprintf (instr, \"ldrb\\t%%5, [%%0, %%3, %s %%4]!\",
5488 shift_instr (GET_CODE (operands[2]), &operands[4]));
5489 return arm_output_asm_insn (instr, operands);
5492 [(set_attr "type" "load")])
5495 [(set (match_operand:QI 5 "s_register_operand" "=r")
5496 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5497 (match_operator:SI 2 "shift_operator"
5498 [(match_operand:SI 3 "s_register_operand" "r")
5499 (match_operand:SI 4 "const_shift_operand" "n")]))))
5500 (set (match_operand:SI 0 "s_register_operand" "=r")
5501 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5503 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5504 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5505 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5510 sprintf (instr, \"ldrb\\t%%5, [%%0, -%%3, %s %%4]!\",
5511 shift_instr (GET_CODE (operands[2]), &operands[4]));
5512 return arm_output_asm_insn (instr, operands);
5515 [(set_attr "type" "load")])
5518 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5519 [(match_operand:SI 3 "s_register_operand" "r")
5520 (match_operand:SI 4 "const_shift_operand" "n")])
5521 (match_operand:SI 1 "s_register_operand" "0")))
5522 (match_operand:SI 5 "s_register_operand" "r"))
5523 (set (match_operand:SI 0 "s_register_operand" "=r")
5524 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5526 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5527 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5528 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5533 sprintf (instr, \"str\\t%%5, [%%0, %%3, %s %%4]!\",
5534 shift_instr (GET_CODE (operands[2]), &operands[4]));
5535 return arm_output_asm_insn (instr, operands);
5538 [(set_attr "type" "store1")])
5541 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5542 (match_operator:SI 2 "shift_operator"
5543 [(match_operand:SI 3 "s_register_operand" "r")
5544 (match_operand:SI 4 "const_shift_operand" "n")])))
5545 (match_operand:SI 5 "s_register_operand" "r"))
5546 (set (match_operand:SI 0 "s_register_operand" "=r")
5547 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5549 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5550 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5551 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5556 sprintf (instr, \"str\\t%%5, [%%0, -%%3, %s %%4]!\",
5557 shift_instr (GET_CODE (operands[2]), &operands[4]));
5558 return arm_output_asm_insn (instr, operands);
5561 [(set_attr "type" "store1")])
5564 [(set (match_operand:SI 5 "s_register_operand" "=r")
5565 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5566 [(match_operand:SI 3 "s_register_operand" "r")
5567 (match_operand:SI 4 "const_shift_operand" "n")])
5568 (match_operand:SI 1 "s_register_operand" "0"))))
5569 (set (match_operand:SI 0 "s_register_operand" "=r")
5570 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5572 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5573 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5574 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5579 sprintf (instr, \"ldr\\t%%5, [%%0, %%3, %s %%4]!\",
5580 shift_instr (GET_CODE (operands[2]), &operands[4]));
5581 return arm_output_asm_insn (instr, operands);
5584 [(set_attr "type" "load")])
5587 [(set (match_operand:SI 5 "s_register_operand" "=r")
5588 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5589 (match_operator:SI 2 "shift_operator"
5590 [(match_operand:SI 3 "s_register_operand" "r")
5591 (match_operand:SI 4 "const_shift_operand" "n")]))))
5592 (set (match_operand:SI 0 "s_register_operand" "=r")
5593 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5595 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5596 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5597 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5602 sprintf (instr, \"ldr\\t%%5, [%%0, -%%3, %s %%4]!\",
5603 shift_instr (GET_CODE (operands[2]), &operands[4]));
5604 return arm_output_asm_insn (instr, operands);
5607 [(set_attr "type" "load")])
5610 [(set (match_operand:HI 5 "s_register_operand" "=r")
5611 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5612 [(match_operand:SI 3 "s_register_operand" "r")
5613 (match_operand:SI 4 "const_shift_operand" "n")])
5614 (match_operand:SI 1 "s_register_operand" "0"))))
5615 (set (match_operand:SI 0 "s_register_operand" "=r")
5616 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5618 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5619 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5620 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5625 sprintf (instr, \"ldr\\t%%5, [%%0, %%3, %s %%4]!\\t@ loadhi\",
5626 shift_instr (GET_CODE (operands[2]), &operands[4]));
5627 return arm_output_asm_insn (instr, operands);
5630 [(set_attr "type" "load")])
5633 [(set (match_operand:HI 5 "s_register_operand" "=r")
5634 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5635 (match_operator:SI 2 "shift_operator"
5636 [(match_operand:SI 3 "s_register_operand" "r")
5637 (match_operand:SI 4 "const_shift_operand" "n")]))))
5638 (set (match_operand:SI 0 "s_register_operand" "=r")
5639 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5641 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5642 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5643 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5648 sprintf (instr, \"ldr\\t%%5, [%%0, -%%3, %s %%4]!\\t@ loadhi\",
5649 shift_instr (GET_CODE (operands[2]), &operands[4]));
5650 return arm_output_asm_insn (instr, operands);
5653 [(set_attr "type" "load")])
5655 ; It can also support extended post-inc expressions, but combine doesn't
5657 ; It doesn't seem worth adding peepholes for anything but the most common
5658 ; cases since, unlike combine, the increment must immediately follow the load
5659 ; for this pattern to match.
5660 ; When loading we must watch to see that the base register isn't trampled by
5661 ; the load. In such cases this isn't a post-inc expression.
5664 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5665 (match_operand:QI 2 "s_register_operand" "r"))
5667 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5670 return arm_output_asm_insn (\"strb\\t%2, [%0], %1\", operands);
5674 [(set (match_operand:QI 0 "s_register_operand" "=r")
5675 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5677 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5678 "REGNO(operands[0]) != REGNO(operands[1])
5679 && (GET_CODE (operands[2]) != REG
5680 || REGNO(operands[0]) != REGNO (operands[2]))"
5682 return arm_output_asm_insn (\"ldrb\\t%0, [%1], %2\", operands);
5686 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5687 (match_operand:SI 2 "s_register_operand" "r"))
5689 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5692 return arm_output_asm_insn (\"str\\t%2, [%0], %1\", operands);
5696 [(set (match_operand:HI 0 "s_register_operand" "=r")
5697 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5699 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5700 "REGNO(operands[0]) != REGNO(operands[1])
5701 && (GET_CODE (operands[2]) != REG
5702 || REGNO(operands[0]) != REGNO (operands[2]))"
5704 return arm_output_asm_insn (\"ldr\\t%0, [%1], %2\\t@ loadhi\", operands);
5708 [(set (match_operand:SI 0 "s_register_operand" "=r")
5709 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5711 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5712 "REGNO(operands[0]) != REGNO(operands[1])
5713 && (GET_CODE (operands[2]) != REG
5714 || REGNO(operands[0]) != REGNO (operands[2]))"
5716 return arm_output_asm_insn (\"ldr\\t%0, [%1], %2\", operands);
5719 ; This pattern is never tried by combine, so do it as a peephole
5722 [(set (match_operand:SI 0 "s_register_operand" "=r")
5723 (match_operand:SI 1 "s_register_operand" "r"))
5724 (set (match_operand 2 "cc_register" "")
5725 (compare (match_dup 1) (const_int 0)))]
5728 return arm_output_asm_insn (\"subs\\t%0, %1, #0\", operands);
5730 [(set_attr "conds" "set")])
5732 ; Peepholes to spot possible load- and store-multiples, if the ordering is
5733 ; reversed, check that the memory references aren't volatile.
5736 [(set (match_operand:SI 0 "s_register_operand" "=r")
5737 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5739 (set (match_operand:SI 2 "s_register_operand" "=r")
5740 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5741 (set (match_operand:SI 3 "s_register_operand" "=r")
5742 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5743 (set (match_operand:SI 4 "s_register_operand" "=r")
5744 (mem:SI (match_dup 1)))]
5745 "REGNO (operands[0]) > REGNO (operands[2])
5746 && REGNO (operands[2]) > REGNO (operands[3])
5747 && REGNO (operands[3]) > REGNO (operands[4])
5748 && !(REGNO (operands[1]) == REGNO (operands[0])
5749 || REGNO (operands[1]) == REGNO (operands[2])
5750 || REGNO (operands[1]) == REGNO (operands[3])
5751 || REGNO (operands[1]) == REGNO (operands[4]))
5752 && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5753 && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))
5754 && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5755 (prev_nonnote_insn (insn)))))
5756 && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5758 (prev_nonnote_insn (insn))))))"
5760 return arm_output_asm_insn (\"ldmia\\t%1, {%4, %3, %2, %0}\\t@ phole ldm\",
5765 [(set (match_operand:SI 0 "s_register_operand" "=r")
5766 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5768 (set (match_operand:SI 2 "s_register_operand" "=r")
5769 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5770 (set (match_operand:SI 3 "s_register_operand" "=r")
5771 (mem:SI (match_dup 1)))]
5772 "REGNO (operands[0]) > REGNO (operands[2])
5773 && REGNO (operands[2]) > REGNO (operands[3])
5774 && !(REGNO (operands[1]) == REGNO (operands[0])
5775 || REGNO (operands[1]) == REGNO (operands[2])
5776 || REGNO (operands[1]) == REGNO (operands[3]))
5777 && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5778 && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))
5779 && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn
5780 (prev_nonnote_insn (insn)))))"
5782 return arm_output_asm_insn (\"ldmia\\t%1, {%3, %2, %0}\\t@ phole ldm\",
5787 [(set (match_operand:SI 0 "s_register_operand" "=r")
5788 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5790 (set (match_operand:SI 2 "s_register_operand" "=r")
5791 (mem:SI (match_dup 1)))]
5792 "REGNO (operands[0]) > REGNO (operands[2])
5793 && !(REGNO (operands[1]) == REGNO (operands[0])
5794 || REGNO (operands[1]) == REGNO (operands[2]))
5795 && !MEM_VOLATILE_P (SET_SRC (PATTERN (insn)))
5796 && !MEM_VOLATILE_P (SET_SRC (PATTERN (prev_nonnote_insn (insn))))"
5798 return arm_output_asm_insn (\"ldmia\\t%1, {%2, %0}\\t@ phole ldm\",
5803 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5805 (match_operand:SI 0 "s_register_operand" "r"))
5806 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5807 (match_operand:SI 2 "s_register_operand" "r"))
5808 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5809 (match_operand:SI 3 "s_register_operand" "r"))
5810 (set (mem:SI (match_dup 1))
5811 (match_operand:SI 4 "s_register_operand" "r"))]
5812 "REGNO (operands[0]) > REGNO (operands[2])
5813 && REGNO (operands[2]) > REGNO (operands[3])
5814 && REGNO (operands[3]) > REGNO (operands[4])
5815 && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5816 && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))
5817 && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5818 (prev_nonnote_insn (insn)))))
5819 && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5821 (prev_nonnote_insn (insn))))))"
5823 return arm_output_asm_insn (\"stmia\\t%1, {%4, %3, %2, %0}\\t@ phole stm\",
5828 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5830 (match_operand:SI 0 "s_register_operand" "r"))
5831 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5832 (match_operand:SI 2 "s_register_operand" "r"))
5833 (set (mem:SI (match_dup 1))
5834 (match_operand:SI 3 "s_register_operand" "r"))]
5835 "REGNO (operands[0]) > REGNO (operands[2])
5836 && REGNO (operands[2]) > REGNO (operands[3])
5837 && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5838 && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))
5839 && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn
5840 (prev_nonnote_insn (insn)))))"
5842 return arm_output_asm_insn (\"stmia\\t%1, {%3, %2, %0}\\t@ phole stm\",
5847 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
5849 (match_operand:SI 0 "s_register_operand" "r"))
5850 (set (mem:SI (match_dup 1))
5851 (match_operand:SI 2 "s_register_operand" "r"))]
5852 "REGNO (operands[0]) > REGNO (operands[2])
5853 && !MEM_VOLATILE_P (SET_DEST (PATTERN (insn)))
5854 && !MEM_VOLATILE_P (SET_DEST (PATTERN (prev_nonnote_insn (insn))))"
5856 return arm_output_asm_insn (\"stmia\\t%1, {%2, %0}\\t@ phole stm\",
5860 ;; A call followed by return can be replaced by restoring the regs and
5861 ;; jumping to the subroutine, provided we aren't passing the address of
5862 ;; any of our local variables. If we call alloca then this is unsafe
5863 ;; since restoring the frame frees the memory, which is not what we want.
5864 ;; Sometimes the return might have been targeted by the final prescan:
5865 ;; if so then emit a propper return insn as well.
5866 ;; Unfortunately, if the frame pointer is required, we don't know if the
5867 ;; current function has any implicit stack pointer adjustments that will
5868 ;; be restored by the return: we can't therefore do a tail call.
5869 ;; Another unfortunate that we can't handle is if current_function_args_size
5870 ;; is non-zero: in this case elimination of the argument pointer assumed
5871 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5875 [(parallel [(call (mem:SI (match_operand:SI 0 "" "i"))
5876 (match_operand:SI 1 "general_operand" "g"))
5877 (clobber (reg:SI 14))])
5879 "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN
5880 && !get_frame_size () && !current_function_calls_alloca
5881 && !frame_pointer_needed && !current_function_args_size)"
5884 extern rtx arm_target_insn;
5885 extern int arm_ccfsm_state, arm_current_cc;
5887 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5889 arm_current_cc ^= 1;
5890 output_return_instruction (NULL, TRUE);
5891 arm_ccfsm_state = 0;
5892 arm_target_insn = NULL;
5895 output_return_instruction (NULL, FALSE);
5896 return (arm_output_asm_insn (\"b\\t%a0\", operands));
5898 [(set (attr "conds")
5899 (if_then_else (eq_attr "cpu" "arm6")
5900 (const_string "clob")
5901 (const_string "nocond")))
5902 (set_attr "length" "2")])
5905 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5906 (call (mem:SI (match_operand:SI 1 "" "i"))
5907 (match_operand:SI 2 "general_operand" "g")))
5908 (clobber (reg:SI 14))])
5910 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5911 && !get_frame_size () && !current_function_calls_alloca
5912 && !frame_pointer_needed && !current_function_args_size)"
5915 extern rtx arm_target_insn;
5916 extern int arm_ccfsm_state, arm_current_cc;
5918 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5920 arm_current_cc ^= 1;
5921 output_return_instruction (NULL, TRUE);
5922 arm_ccfsm_state = 0;
5923 arm_target_insn = NULL;
5926 output_return_instruction (NULL, FALSE);
5927 return (arm_output_asm_insn (\"b\\t%a1\", operands));
5929 [(set (attr "conds")
5930 (if_then_else (eq_attr "cpu" "arm6")
5931 (const_string "clob")
5932 (const_string "nocond")))
5933 (set_attr "length" "2")])
5935 ;; As above but when this function is not void, we must be returning the
5936 ;; result of the called subroutine.
5939 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
5940 (call (mem:SI (match_operand:SI 1 "" "i"))
5941 (match_operand:SI 2 "general_operand" "g")))
5942 (clobber (reg:SI 14))])
5945 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN
5946 && !get_frame_size () && !current_function_calls_alloca
5947 && !frame_pointer_needed && !current_function_args_size)"
5950 extern rtx arm_target_insn;
5951 extern int arm_ccfsm_state, arm_current_cc;
5953 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5955 arm_current_cc ^= 1;
5956 output_return_instruction (NULL, TRUE);
5957 arm_ccfsm_state = 0;
5958 arm_target_insn = NULL;
5961 output_return_instruction (NULL, FALSE);
5962 return (arm_output_asm_insn (\"b\\t%a1\", operands));
5964 [(set (attr "conds")
5965 (if_then_else (eq_attr "cpu" "arm6")
5966 (const_string "clob")
5967 (const_string "nocond")))
5968 (set_attr "length" "2")])
5970 ;; If calling a subroutine and then jumping back to somewhere else, but not
5971 ;; too far away, then we can set the link register with the branch address
5972 ;; and jump direct to the subroutine. On return from the subroutine
5973 ;; execution continues at the branch; this avoids a prefetch stall.
5974 ;; We use the length attribute (via short_branch ()) to establish whether or
5975 ;; not this is possible, this is the same asthe sparc does.
5978 [(parallel[(call (mem:SI (match_operand:SI 0 "" "i"))
5979 (match_operand:SI 1 "general_operand" "g"))
5980 (clobber (reg:SI 14))])
5982 (label_ref (match_operand 2 "" "")))]
5983 "GET_CODE (operands[0]) == SYMBOL_REF
5984 && short_branch (INSN_UID (insn), INSN_UID (operands[2]))
5985 && arm_insn_not_targeted (insn)"
5988 int backward = arm_backwards_branch (INSN_UID (insn),
5989 INSN_UID (operands[2]));
5992 /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
5993 * above, leaving it out means that the code will still run on an arm 2 or 3
5998 arm_output_asm_insn (\"sub\\tlr, pc, #(8 + . -%l2)\", operands);
6000 arm_output_asm_insn (\"add\\tlr, pc, #(%l2 - . -8)\", operands);
6005 arm_output_asm_insn (\"mov\\tlr, pc\\t@ protect cc\");
6007 arm_output_asm_insn (\"sub\\tlr, lr, #(4 + . -%l2)\", operands);
6009 arm_output_asm_insn (\"add\\tlr, lr, #(%l2 - . -4)\", operands);
6011 return arm_output_asm_insn (\"b\\t%a0\", operands);
6013 [(set (attr "conds")
6014 (if_then_else (eq_attr "cpu" "arm6")
6015 (const_string "clob")
6016 (const_string "nocond")))
6017 (set (attr "length")
6018 (if_then_else (eq_attr "cpu" "arm6")
6023 [(parallel[(set (match_operand:SI 0 "s_register_operand" "=r")
6024 (call (mem:SI (match_operand:SI 1 "" "i"))
6025 (match_operand:SI 2 "general_operand" "g")))
6026 (clobber (reg:SI 14))])
6028 (label_ref (match_operand 3 "" "")))]
6029 "GET_CODE (operands[0]) == SYMBOL_REF
6030 && short_branch (INSN_UID (insn), INSN_UID (operands[3]))
6031 && arm_insn_not_targeted (insn)"
6034 int backward = arm_backwards_branch (INSN_UID (insn),
6035 INSN_UID (operands[3]));
6038 /* Putting this in means that TARGET_6 code will ONLY run on an arm6 or
6039 * above, leaving it out means that the code will still run on an arm 2 or 3
6044 arm_output_asm_insn (\"sub\\tlr, pc, #(8 + . -%l3)\", operands);
6046 arm_output_asm_insn (\"add\\tlr, pc, #(%l3 - . -8)\", operands);
6051 arm_output_asm_insn (\"mov\\tlr, pc\\t@ protect cc\");
6053 arm_output_asm_insn (\"sub\\tlr, lr, #(4 + . -%l3)\", operands);
6055 arm_output_asm_insn (\"add\\tlr, lr, #(%l3 - . -4)\", operands);
6057 return arm_output_asm_insn (\"b\\t%a1\", operands);
6059 [(set (attr "conds")
6060 (if_then_else (eq_attr "cpu" "arm6")
6061 (const_string "clob")
6062 (const_string "nocond")))
6063 (set (attr "length")
6064 (if_then_else (eq_attr "cpu" "arm6")
6070 (if_then_else (match_operator 0 "comparison_operator"
6071 [(match_operator:SI 1 "shift_operator"
6072 [(match_operand:SI 2 "s_register_operand" "r")
6073 (match_operand:SI 3 "nonmemory_operand" "rn")])
6074 (match_operand:SI 4 "s_register_operand" "r")])
6075 (label_ref (match_operand 5 "" ""))
6080 (compare:CC (match_dup 4)
6081 (match_op_dup 1 [(match_dup 2) (match_dup 3)])))
6083 (if_then_else (match_op_dup 0 [(reg 24) (const_int 0)])
6084 (label_ref (match_dup 5))
6087 operands[0] = gen_rtx (swap_condition (GET_CODE (operands[0])), VOIDmode,
6088 operands[1], operands[2]);
6092 [(set (match_operand:SI 0 "s_register_operand" "")
6093 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
6095 (neg:SI (match_operator:SI 2 "comparison_operator"
6096 [(match_operand:SI 3 "s_register_operand" "")
6097 (match_operand:SI 4 "arm_rhs_operand" "")]))))
6098 (clobber (match_operand:SI 5 "s_register_operand" ""))]
6100 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
6101 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6105 ;; This pattern can be used because cc_noov mode implies that the following
6106 ;; branch will be an equality (EQ or NE), so the sign extension is not
6107 ;; needed. Combine doesn't eliminate these because by the time it sees the
6108 ;; branch it no-longer knows that the data came from memory.
6111 [(set (reg:CC_NOOV 24)
6113 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "m") 0)
6115 (match_operand 1 "immediate_operand" "I")))
6116 (clobber (match_scratch:SI 2 "=r"))]
6117 "((unsigned long) INTVAL (operands[1]))
6118 == (((unsigned long) INTVAL (operands[1])) >> 24) << 24"
6120 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
6121 arm_output_asm_insn (\"ldrb\\t%2, %0\", operands);
6122 return arm_output_asm_insn (\"cmp\\t%2, %1\", operands);
6124 [(set_attr "conds" "set")
6125 (set_attr "length" "2")
6126 (set_attr "type" "load")])
6128 (define_expand "save_stack_nonlocal"
6129 [(match_operand:DI 0 "memory_operand" "")
6130 (match_operand:SI 1 "s_register_operand" "")]
6134 /* We also need to save the frame pointer for non-local gotos */
6135 emit_move_insn (operand_subword (operands[0], 0, 0, DImode),
6136 hard_frame_pointer_rtx);
6137 emit_move_insn (operand_subword (operands[0], 1, 0, DImode), operands[1]);
6141 (define_expand "restore_stack_nonlocal"
6142 [(match_operand:SI 0 "s_register_operand" "")
6143 (match_operand:DI 1 "memory_operand" "")]
6147 /* Restore the frame pointer first, the stack pointer second. */
6148 emit_move_insn (operands[0], operand_subword (operands[1], 1, 0, DImode));
6149 emit_move_insn (hard_frame_pointer_rtx, operand_subword (operands[1], 0, 0,
6154 ;; This split is only used during output to reduce the number of patterns
6155 ;; that need assembler instructions adding to them. We allowed the setting
6156 ;; of the conditions to be implicit during rtl generation so that
6157 ;; the conditional compare patterns would work. However this conflicts to
6158 ;; some extend with the conditional data operations, so we have to split them
6162 [(set (match_operand:SI 0 "s_register_operand" "")
6163 (if_then_else:SI (match_operator 1 "comparison_operator"
6164 [(match_operand 2 "" "") (match_operand 3 "" "")])
6165 (match_operand 4 "" "")
6166 (match_operand 5 "" "")))
6169 [(set (match_dup 6) (match_dup 7))
6171 (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
6176 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
6179 operands[6] = gen_rtx (REG, mode, 24);
6180 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
6186 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6187 (if_then_else:SI (match_operator 4 "comparison_operator"
6188 [(match_operand 3 "cc_register" "") (const_int 0)])
6189 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
6191 (match_operand:SI 2 "s_register_operand" "r,r"))))]
6194 if (which_alternative != 0)
6195 arm_output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6196 return arm_output_asm_insn (\"mvn%D4\\t%0, %2\", operands);
6198 [(set_attr "conds" "use")
6199 (set_attr "length" "1,2")])
6201 ;; The next two patterns occur when an AND operation is followed by a
6202 ;; scc insn sequence
6205 [(set (match_operand:SI 0 "s_register_operand" "=r")
6206 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6208 (match_operand:SI 2 "immediate_operand" "n")))]
6211 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6212 arm_output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6213 return arm_output_asm_insn (\"mvnne\\t%0, #0\", operands);
6215 [(set_attr "conds" "clob")
6216 (set_attr "length" "2")])
6219 [(set (match_operand:SI 0 "s_register_operand" "=r")
6221 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6223 (match_operand:SI 2 "immediate_operand" "n"))))]
6226 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6227 arm_output_asm_insn (\"tst\\t%1, %2\", operands);
6228 arm_output_asm_insn (\"mvneq\\t%0, #0\", operands);
6229 return arm_output_asm_insn (\"movne\\t%0, #0\", operands);
6231 [(set_attr "conds" "clob")
6232 (set_attr "length" "3")])