1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright (C) 1991, 93-98, 1999 Free Software Foundation, Inc.
3 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
4 ;; and Martin Simmons (@harleqn.co.uk).
5 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
7 ;; This file is part of GNU CC.
9 ;; GNU CC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; GNU CC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU CC; see the file COPYING. If not, write to
21 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
24 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26 ;; There are patterns in this file to support XFmode arithmetic.
27 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
31 ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
32 ;; the mode is MODE_FLOAT
33 ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
34 ;; the mode is MODE_FLOAT
35 ;; 2 `push multiple' operation: operand 0 is the first register. Subsequent
36 ;; registers are in parallel (use...) expressions.
37 ;; 3 A symbol that has been treated properly for pic usage, that is, we
38 ;; will add the pic_register value to it before trying to dereference it.
39 ;; Note: sin and cos are no-longer used.
43 ; PROG_MODE attribute is used to determine whether condition codes are
44 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
45 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
46 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
48 ; CPU attribute is used to determine the best instruction mix for performance
49 ; on the named processor.
50 (define_attr "cpu" "arm2,arm3,arm6,arm7,arm8,arm9,st_arm"
51 (const (symbol_ref "arm_cpu_attr")))
53 ; Floating Point Unit. If we only have floating point emulation, then there
54 ; is no point in scheduling the floating point insns. (Well, for best
55 ; performance we should try and group them together).
57 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
59 ; LENGTH of an instruction (in bytes)
60 (define_attr "length" "" (const_int 4))
62 ; An assembler sequence may clobber the condition codes without us knowing
63 (define_asm_attributes
64 [(set_attr "conds" "clob")
65 (set_attr "length" "4")])
67 ; TYPE attribute is used to detect floating point instructions which, if
68 ; running on a co-processor can run in parallel with other, basic instructions
69 ; If write-buffer scheduling is enabled then it can also be used in the
70 ; scheduling of writes.
72 ; Classification of each insn
73 ; normal any data instruction that doesn't hit memory or fp regs
74 ; mult a multiply instruction
75 ; block blockage insn, this blocks all functional units
76 ; float a floating point arithmetic operation (subject to expansion)
77 ; fdivx XFmode floating point division
78 ; fdivd DFmode floating point division
79 ; fdivs SFmode floating point division
80 ; fmul Floating point multiply
81 ; ffmul Fast floating point multiply
82 ; farith Floating point arithmetic (4 cycle)
83 ; ffarith Fast floating point arithmetic (2 cycle)
84 ; float_em a floating point arithmetic operation that is normally emulated
85 ; even on a machine with an fpa.
86 ; f_load a floating point load from memory
87 ; f_store a floating point store to memory
88 ; f_mem_r a transfer of a floating point register to a real reg via mem
89 ; r_mem_f the reverse of f_mem_r
90 ; f_2_r fast transfer float to arm (no memory needed)
91 ; r_2_f fast transfer arm to float
92 ; call a subroutine call
93 ; load any load from memory
94 ; store1 store 1 word to memory from arm registers
95 ; store2 store 2 words
96 ; store3 store 3 words
97 ; store4 store 4 words
100 "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4"
101 (const_string "normal"))
103 ; Load scheduling, set from the cpu characteristic
104 (define_attr "ldsched" "no,yes"
105 (if_then_else (eq_attr "cpu" "arm8,arm9,st_arm")
107 (const_string "no")))
109 ; condition codes: this one is used by final_prescan_insn to speed up
110 ; conditionalizing instructions. It saves having to scan the rtl to see if
111 ; it uses or alters the condition codes.
113 ; USE means that the condition codes are used by the insn in the process of
114 ; outputting code, this means (at present) that we can't use the insn in
117 ; SET means that the purpose of the insn is to set the condition codes in a
118 ; well defined manner.
120 ; CLOB means that the condition codes are altered in an undefined manner, if
121 ; they are altered at all
123 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
124 ; but are if the branch wasn't taken; the effect is to limit the branch
125 ; elimination scanning.
127 ; NOCOND means that the condition codes are neither altered nor affect the
128 ; output of this insn
130 (define_attr "conds" "use,set,clob,jump_clob,nocond"
131 (if_then_else (eq_attr "type" "call")
132 (if_then_else (eq_attr "prog_mode" "prog32")
133 (const_string "clob") (const_string "nocond"))
134 (const_string "nocond")))
136 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
137 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
138 ; suffer blockages enough to warrent modelling this (and it can adversely
139 ; affect the schedule).
140 (define_attr "model_wbuf" "no,yes"
141 (if_then_else (eq_attr "cpu" "arm6,arm7")
143 (const_string "no")))
145 (define_attr "write_conflict" "no,yes"
146 (if_then_else (eq_attr "type"
147 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
149 (const_string "no")))
151 (define_attr "core_cycles" "single,multi"
152 (if_then_else (eq_attr "type"
153 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
154 (const_string "single")
155 (const_string "multi")))
157 ; The write buffer on some of the arm6 processors is hard to model exactly.
158 ; There is room in the buffer for up to two addresses and up to eight words
159 ; of memory, but the two needn't be split evenly. When writing the two
160 ; addresses are fully pipelined. However, a read from memory that is not
161 ; currently in the cache will block until the writes have completed.
162 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
163 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
164 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
165 ; cycle to add as well.
167 ;; (define_function_unit {name} {num-units} {n-users} {test}
168 ;; {ready-delay} {issue-delay} [{conflict-list}])
169 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
170 (eq_attr "type" "fdivx")) 71 69)
172 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
173 (eq_attr "type" "fdivd")) 59 57)
175 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
176 (eq_attr "type" "fdivs")) 31 29)
178 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
179 (eq_attr "type" "fmul")) 9 7)
181 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
182 (eq_attr "type" "ffmul")) 6 4)
184 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
185 (eq_attr "type" "farith")) 4 2)
187 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
188 (eq_attr "type" "ffarith")) 2 2)
190 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
191 (eq_attr "type" "r_2_f")) 5 3)
193 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
194 (eq_attr "type" "f_2_r")) 1 2)
196 ;; The fpa10 doesn't really have a memory read unit, but it can start to
197 ;; speculatively execute the instruction in the pipeline, provided the data
198 ;; is already loaded, so pretend reads have a delay of 2 (and that the
199 ;; pipeline is infinite.
201 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
202 (eq_attr "type" "f_load")) 3 1)
204 ;;--------------------------------------------------------------------
206 ;;--------------------------------------------------------------------
207 ;; Strictly we should model a 4-deep write buffer for ARM7xx based chips
208 (define_function_unit "write_buf" 1 2
209 (and (eq_attr "model_wbuf" "yes")
210 (eq_attr "type" "store1,r_mem_f")) 5 3)
211 (define_function_unit "write_buf" 1 2
212 (and (eq_attr "model_wbuf" "yes")
213 (eq_attr "type" "store2")) 7 4)
214 (define_function_unit "write_buf" 1 2
215 (and (eq_attr "model_wbuf" "yes")
216 (eq_attr "type" "store3")) 9 5)
217 (define_function_unit "write_buf" 1 2
218 (and (eq_attr "model_wbuf" "yes")
219 (eq_attr "type" "store4")) 11 6)
221 ;;--------------------------------------------------------------------
222 ;; Write blockage unit
223 ;;--------------------------------------------------------------------
224 ;; The write_blockage unit models (partially), the fact that reads will stall
225 ;; until the write buffer empties.
226 ;; The f_mem_r and r_mem_f could also block, but they are to the stack,
227 ;; so we don't model them here
228 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
229 (eq_attr "type" "store1")) 5 5
230 [(eq_attr "write_conflict" "yes")])
231 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
232 (eq_attr "type" "store2")) 7 7
233 [(eq_attr "write_conflict" "yes")])
234 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
235 (eq_attr "type" "store3")) 9 9
236 [(eq_attr "write_conflict" "yes")])
237 (define_function_unit "write_blockage" 1 0
238 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
239 [(eq_attr "write_conflict" "yes")])
240 (define_function_unit "write_blockage" 1 0
241 (and (eq_attr "model_wbuf" "yes")
242 (eq_attr "write_conflict" "yes")) 1 1)
244 ;;--------------------------------------------------------------------
246 ;;--------------------------------------------------------------------
247 ;; Everything must spend at least one cycle in the core unit
248 (define_function_unit "core" 1 0
249 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
251 (define_function_unit "core" 1 0
252 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
254 (define_function_unit "core" 1 0
255 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
257 (define_function_unit "core" 1 0
258 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
260 (define_function_unit "core" 1 0
261 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
263 (define_function_unit "core" 1 0
264 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
266 (define_function_unit "core" 1 0
267 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
269 (define_function_unit "core" 1 0
270 (and (eq_attr "cpu" "!arm8,st_arm") (eq_attr "type" "mult")) 16 16)
272 (define_function_unit "core" 1 0
273 (and (eq_attr "cpu" "arm8") (eq_attr "type" "mult")) 4 4)
275 (define_function_unit "core" 1 0
276 (and (eq_attr "cpu" "st_arm") (eq_attr "type" "mult")) 3 2)
278 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
280 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
282 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
284 ;; Note: For DImode insns, there is normally no reason why operands should
285 ;; not be in the same register, what we don't want is for something being
286 ;; written to partially overlap something that is an input.
290 (define_insn "adddi3"
291 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
292 (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
293 (match_operand:DI 2 "s_register_operand" "r,0")))
294 (clobber (reg:CC 24))]
296 "adds\\t%Q0, %Q1, %Q2\;adc\\t%R0, %R1, %R2"
297 [(set_attr "conds" "clob")
298 (set_attr "length" "8")])
300 (define_insn "*adddi_sesidi_di"
301 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
302 (plus:DI (sign_extend:DI
303 (match_operand:SI 2 "s_register_operand" "r,r"))
304 (match_operand:DI 1 "s_register_operand" "r,0")))
305 (clobber (reg:CC 24))]
307 "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, %2, asr #31"
308 [(set_attr "conds" "clob")
309 (set_attr "length" "8")])
311 (define_insn "*adddi_zesidi_di"
312 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
313 (plus:DI (zero_extend:DI
314 (match_operand:SI 2 "s_register_operand" "r,r"))
315 (match_operand:DI 1 "s_register_operand" "r,0")))
316 (clobber (reg:CC 24))]
318 "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, #0"
319 [(set_attr "conds" "clob")
320 (set_attr "length" "8")])
322 (define_expand "addsi3"
323 [(set (match_operand:SI 0 "s_register_operand" "")
324 (plus:SI (match_operand:SI 1 "s_register_operand" "")
325 (match_operand:SI 2 "reg_or_int_operand" "")))]
328 if (GET_CODE (operands[2]) == CONST_INT)
330 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
332 (reload_in_progress || reload_completed ? 0
333 : preserve_subexpressions_p ()));
339 [(set (match_operand:SI 0 "s_register_operand" "")
340 (plus:SI (match_operand:SI 1 "s_register_operand" "")
341 (match_operand:SI 2 "const_int_operand" "")))]
342 "! (const_ok_for_arm (INTVAL (operands[2]))
343 || const_ok_for_arm (-INTVAL (operands[2])))"
344 [(clobber (const_int 0))]
346 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
351 (define_insn "*addsi3_insn"
352 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
353 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
354 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
360 [(set_attr "length" "4,4,16")])
362 (define_insn "*addsi3_compare0"
363 [(set (reg:CC_NOOV 24)
365 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
366 (match_operand:SI 2 "arm_add_operand" "rI,L"))
368 (set (match_operand:SI 0 "s_register_operand" "=r,r")
369 (plus:SI (match_dup 1) (match_dup 2)))]
373 sub%?s\\t%0, %1, #%n2"
374 [(set_attr "conds" "set")])
376 (define_insn "*addsi3_compare0_scratch"
377 [(set (reg:CC_NOOV 24)
379 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
380 (match_operand:SI 1 "arm_add_operand" "rI,L"))
386 [(set_attr "conds" "set")])
388 ;; The next four insns work because they compare the result with one of
389 ;; the operands, and we know that the use of the condition code is
390 ;; either GEU or LTU, so we can use the carry flag from the addition
391 ;; instead of doing the compare a second time.
392 (define_insn "*addsi3_compare_op1"
395 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
396 (match_operand:SI 2 "arm_add_operand" "rI,L"))
398 (set (match_operand:SI 0 "s_register_operand" "=r,r")
399 (plus:SI (match_dup 1) (match_dup 2)))]
403 sub%?s\\t%0, %1, #%n2"
404 [(set_attr "conds" "set")])
406 (define_insn "*addsi3_compare_op2"
409 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
410 (match_operand:SI 2 "arm_add_operand" "rI,L"))
412 (set (match_operand:SI 0 "s_register_operand" "=r,r")
413 (plus:SI (match_dup 1) (match_dup 2)))]
417 sub%?s\\t%0, %1, #%n2"
418 [(set_attr "conds" "set")])
420 (define_insn "*compare_addsi2_op0"
423 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
424 (match_operand:SI 1 "arm_add_operand" "rI,L"))
430 [(set_attr "conds" "set")])
432 (define_insn "*compare_addsi2_op1"
435 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
436 (match_operand:SI 1 "arm_add_operand" "rI,L"))
442 [(set_attr "conds" "set")])
444 (define_insn "*addsi3_carryin"
445 [(set (match_operand:SI 0 "s_register_operand" "=r")
446 (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
447 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
448 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
451 [(set_attr "conds" "use")])
453 (define_insn "*addsi3_carryin_alt1"
454 [(set (match_operand:SI 0 "s_register_operand" "=r")
455 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
456 (match_operand:SI 2 "arm_rhs_operand" "rI"))
457 (ltu:SI (reg:CC_C 24) (const_int 0))))]
460 [(set_attr "conds" "use")])
462 (define_insn "*addsi3_carryin_alt2"
463 [(set (match_operand:SI 0 "s_register_operand" "=r")
464 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
465 (match_operand:SI 1 "s_register_operand" "r"))
466 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
469 [(set_attr "conds" "use")])
471 (define_insn "*addsi3_carryin_alt3"
472 [(set (match_operand:SI 0 "s_register_operand" "=r")
473 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
474 (match_operand:SI 2 "arm_rhs_operand" "rI"))
475 (match_operand:SI 1 "s_register_operand" "r")))]
478 [(set_attr "conds" "use")])
480 (define_insn "incscc"
481 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
482 (plus:SI (match_operator:SI 2 "comparison_operator"
483 [(match_operand 3 "cc_register" "") (const_int 0)])
484 (match_operand:SI 1 "s_register_operand" "0,?r")))]
488 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
489 [(set_attr "conds" "use")
490 (set_attr "length" "4,8")])
492 ; If a constant is too big to fit in a single instruction then the constant
493 ; will be pre-loaded into a register taking at least two insns, we might be
494 ; able to merge it with an add, but it depends on the exact value.
497 [(set (match_operand:SI 0 "s_register_operand" "=r")
498 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
499 (match_operand:SI 2 "const_int_operand" "n")))]
500 "!(const_ok_for_arm (INTVAL (operands[2]))
501 || const_ok_for_arm (-INTVAL (operands[2])))"
502 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
503 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
506 unsigned int val = (unsigned) INTVAL (operands[2]);
510 /* this code is similar to the approach followed in movsi, but it must
511 generate exactly two insns */
513 for (i = 30; i >= 0; i -= 2)
519 if (const_ok_for_arm (temp = (val & ~(255 << i))))
524 /* we might be able to do this as (larger number - small number) */
525 temp = ((val >> i) & 255) + 1;
526 if (temp > 255 && i < 24)
529 temp = ((val >> i) & 255) + 1;
531 if (const_ok_for_arm ((temp << i) - val))
534 temp = (unsigned) - (int) (i - val);
541 /* if we got here, we have found a way of doing it in two instructions.
542 the two constants are in val and temp */
543 operands[2] = GEN_INT ((int)val);
544 operands[3] = GEN_INT ((int)temp);
548 (define_insn "addsf3"
549 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
550 (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
551 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
555 suf%?s\\t%0, %1, #%N2"
556 [(set_attr "type" "farith")])
558 (define_insn "adddf3"
559 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
560 (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
561 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
565 suf%?d\\t%0, %1, #%N2"
566 [(set_attr "type" "farith")])
568 (define_insn "*adddf_df_esfdf"
569 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
570 (plus:DF (float_extend:DF
571 (match_operand:SF 1 "s_register_operand" "f,f"))
572 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
576 suf%?d\\t%0, %1, #%N2"
577 [(set_attr "type" "farith")])
579 (define_insn "*adddf_df_esfdf"
580 [(set (match_operand:DF 0 "s_register_operand" "=f")
581 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
583 (match_operand:SF 2 "s_register_operand" "f"))))]
585 "adf%?d\\t%0, %1, %2"
586 [(set_attr "type" "farith")])
588 (define_insn "*adddf_esfdf_esfdf"
589 [(set (match_operand:DF 0 "s_register_operand" "=f")
590 (plus:DF (float_extend:DF
591 (match_operand:SF 1 "s_register_operand" "f"))
593 (match_operand:SF 2 "s_register_operand" "f"))))]
595 "adf%?d\\t%0, %1, %2"
596 [(set_attr "type" "farith")])
598 (define_insn "addxf3"
599 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
600 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
601 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
602 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
605 suf%?e\\t%0, %1, #%N2"
606 [(set_attr "type" "farith")])
608 (define_insn "subdi3"
609 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
610 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
611 (match_operand:DI 2 "s_register_operand" "r,0,0")))
612 (clobber (reg:CC 24))]
614 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
615 [(set_attr "conds" "clob")
616 (set_attr "length" "8")])
618 (define_insn "*subdi_di_zesidi"
619 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
620 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
622 (match_operand:SI 2 "s_register_operand" "r,r"))))
623 (clobber (reg:CC 24))]
625 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
626 [(set_attr "conds" "clob")
627 (set_attr "length" "8")])
629 (define_insn "*subdi_di_sesidi"
630 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
631 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
633 (match_operand:SI 2 "s_register_operand" "r,r"))))
634 (clobber (reg:CC 24))]
636 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
637 [(set_attr "conds" "clob")
638 (set_attr "length" "8")])
640 (define_insn "*subdi_zesidi_di"
641 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
642 (minus:DI (zero_extend:DI
643 (match_operand:SI 2 "s_register_operand" "r,r"))
644 (match_operand:DI 1 "s_register_operand" "?r,0")))
645 (clobber (reg:CC 24))]
647 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
648 [(set_attr "conds" "clob")
649 (set_attr "length" "8")])
651 (define_insn "*subdi_sesidi_di"
652 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
653 (minus:DI (sign_extend:DI
654 (match_operand:SI 2 "s_register_operand" "r,r"))
655 (match_operand:DI 1 "s_register_operand" "?r,0")))
656 (clobber (reg:CC 24))]
658 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
659 [(set_attr "conds" "clob")
660 (set_attr "length" "8")])
662 (define_insn "*subdi_zesidi_zesidi"
663 [(set (match_operand:DI 0 "s_register_operand" "=r")
664 (minus:DI (zero_extend:DI
665 (match_operand:SI 1 "s_register_operand" "r"))
667 (match_operand:SI 2 "s_register_operand" "r"))))
668 (clobber (reg:CC 24))]
670 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
671 [(set_attr "conds" "clob")
672 (set_attr "length" "8")])
674 (define_expand "subsi3"
675 [(set (match_operand:SI 0 "s_register_operand" "")
676 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
677 (match_operand:SI 2 "s_register_operand" "")))]
680 if (GET_CODE (operands[1]) == CONST_INT)
682 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
684 (reload_in_progress || reload_completed ? 0
685 : preserve_subexpressions_p ()));
690 (define_insn "*subsi3_insn"
691 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
692 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
693 (match_operand:SI 2 "s_register_operand" "r,r")))]
698 [(set_attr "length" "4,16")])
701 [(set (match_operand:SI 0 "s_register_operand" "")
702 (minus:SI (match_operand:SI 1 "const_int_operand" "")
703 (match_operand:SI 2 "s_register_operand" "")))]
704 "! const_ok_for_arm (INTVAL (operands[1]))"
705 [(clobber (const_int 0))]
707 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
712 (define_insn "*subsi3_compare0"
713 [(set (reg:CC_NOOV 24)
714 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
715 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
717 (set (match_operand:SI 0 "s_register_operand" "=r,r")
718 (minus:SI (match_dup 1) (match_dup 2)))]
723 [(set_attr "conds" "set")])
725 (define_insn "decscc"
726 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
727 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
728 (match_operator:SI 2 "comparison_operator"
729 [(match_operand 3 "cc_register" "") (const_int 0)])))]
733 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
734 [(set_attr "conds" "use")
735 (set_attr "length" "*,8")])
737 (define_insn "subsf3"
738 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
739 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
740 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
745 [(set_attr "type" "farith")])
747 (define_insn "subdf3"
748 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
749 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
750 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
755 [(set_attr "type" "farith")])
757 (define_insn "*subdf_esfdf_df"
758 [(set (match_operand:DF 0 "s_register_operand" "=f")
759 (minus:DF (float_extend:DF
760 (match_operand:SF 1 "s_register_operand" "f"))
761 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
763 "suf%?d\\t%0, %1, %2"
764 [(set_attr "type" "farith")])
766 (define_insn "*subdf_df_esfdf"
767 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
768 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
770 (match_operand:SF 2 "s_register_operand" "f,f"))))]
775 [(set_attr "type" "farith")])
777 (define_insn "*subdf_esfdf_esfdf"
778 [(set (match_operand:DF 0 "s_register_operand" "=f")
779 (minus:DF (float_extend:DF
780 (match_operand:SF 1 "s_register_operand" "f"))
782 (match_operand:SF 2 "s_register_operand" "f"))))]
784 "suf%?d\\t%0, %1, %2"
785 [(set_attr "type" "farith")])
787 (define_insn "subxf3"
788 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
789 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
790 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
791 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
795 [(set_attr "type" "farith")])
797 ;; Multiplication insns
799 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
800 (define_insn "mulsi3"
801 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
802 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
803 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
806 [(set_attr "type" "mult")])
808 (define_insn "*mulsi3_compare0"
809 [(set (reg:CC_NOOV 24)
810 (compare:CC_NOOV (mult:SI
811 (match_operand:SI 2 "s_register_operand" "r,r")
812 (match_operand:SI 1 "s_register_operand" "%?r,0"))
814 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
815 (mult:SI (match_dup 2) (match_dup 1)))]
817 "mul%?s\\t%0, %2, %1"
818 [(set_attr "conds" "set")
819 (set_attr "type" "mult")])
821 (define_insn "*mulsi_compare0_scratch"
822 [(set (reg:CC_NOOV 24)
823 (compare:CC_NOOV (mult:SI
824 (match_operand:SI 2 "s_register_operand" "r,r")
825 (match_operand:SI 1 "s_register_operand" "%?r,0"))
827 (clobber (match_scratch:SI 0 "=&r,&r"))]
829 "mul%?s\\t%0, %2, %1"
830 [(set_attr "conds" "set")
831 (set_attr "type" "mult")])
833 ;; Unnamed templates to match MLA instruction.
835 (define_insn "*mulsi3addsi"
836 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
838 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
839 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
840 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
842 "mla%?\\t%0, %2, %1, %3"
843 [(set_attr "type" "mult")])
845 (define_insn "*mulsi3addsi_compare0"
846 [(set (reg:CC_NOOV 24)
847 (compare:CC_NOOV (plus:SI
849 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
850 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
851 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
853 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
854 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
857 "mla%?s\\t%0, %2, %1, %3"
858 [(set_attr "conds" "set")
859 (set_attr "type" "mult")])
861 (define_insn "*mulsi3addsi_compare0_scratch"
862 [(set (reg:CC_NOOV 24)
863 (compare:CC_NOOV (plus:SI
865 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
866 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
867 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
869 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
871 "mla%?s\\t%0, %2, %1, %3"
872 [(set_attr "conds" "set")
873 (set_attr "type" "mult")])
875 (define_insn "mulsidi3"
876 [(set (match_operand:DI 0 "s_register_operand" "=&r")
877 (mult:DI (sign_extend:DI
878 (match_operand:SI 1 "s_register_operand" "%r"))
880 (match_operand:SI 2 "s_register_operand" "r"))))]
882 "smull%?\\t%Q0, %R0, %1, %2"
883 [(set_attr "type" "mult")])
885 (define_insn "umulsidi3"
886 [(set (match_operand:DI 0 "s_register_operand" "=&r")
887 (mult:DI (zero_extend:DI
888 (match_operand:SI 1 "s_register_operand" "%r"))
890 (match_operand:SI 2 "s_register_operand" "r"))))]
892 "umull%?\\t%Q0, %R0, %1, %2"
893 [(set_attr "type" "mult")])
895 (define_insn "smulsi3_highpart"
896 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
899 (mult:DI (sign_extend:DI
900 (match_operand:SI 1 "s_register_operand" "%r,0"))
902 (match_operand:SI 2 "s_register_operand" "r,r")))
904 (clobber (match_scratch:SI 3 "=&r,&r"))]
906 "smull%?\\t%3, %0, %2, %1"
907 [(set_attr "type" "mult")])
909 (define_insn "umulsi3_highpart"
910 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
913 (mult:DI (zero_extend:DI
914 (match_operand:SI 1 "s_register_operand" "%r,0"))
916 (match_operand:SI 2 "s_register_operand" "r,r")))
918 (clobber (match_scratch:SI 3 "=&r,&r"))]
920 "umull%?\\t%3, %0, %2, %1"
921 [(set_attr "type" "mult")])
923 (define_insn "mulsf3"
924 [(set (match_operand:SF 0 "s_register_operand" "=f")
925 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
926 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
928 "fml%?s\\t%0, %1, %2"
929 [(set_attr "type" "ffmul")])
931 (define_insn "muldf3"
932 [(set (match_operand:DF 0 "s_register_operand" "=f")
933 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
934 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
936 "muf%?d\\t%0, %1, %2"
937 [(set_attr "type" "fmul")])
939 (define_insn "*muldf_esfdf_df"
940 [(set (match_operand:DF 0 "s_register_operand" "=f")
941 (mult:DF (float_extend:DF
942 (match_operand:SF 1 "s_register_operand" "f"))
943 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
945 "muf%?d\\t%0, %1, %2"
946 [(set_attr "type" "fmul")])
948 (define_insn "*muldf_df_esfdf"
949 [(set (match_operand:DF 0 "s_register_operand" "=f")
950 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
952 (match_operand:SF 2 "s_register_operand" "f"))))]
954 "muf%?d\\t%0, %1, %2"
955 [(set_attr "type" "fmul")])
957 (define_insn "*muldf_esfdf_esfdf"
958 [(set (match_operand:DF 0 "s_register_operand" "=f")
959 (mult:DF (float_extend:DF
960 (match_operand:SF 1 "s_register_operand" "f"))
962 (match_operand:SF 2 "s_register_operand" "f"))))]
964 "muf%?d\\t%0, %1, %2"
965 [(set_attr "type" "fmul")])
967 (define_insn "mulxf3"
968 [(set (match_operand:XF 0 "s_register_operand" "=f")
969 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
970 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
971 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
972 "muf%?e\\t%0, %1, %2"
973 [(set_attr "type" "fmul")])
977 (define_insn "divsf3"
978 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
979 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
980 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
985 [(set_attr "type" "fdivs")])
987 (define_insn "divdf3"
988 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
989 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
990 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
995 [(set_attr "type" "fdivd")])
997 (define_insn "*divdf_esfdf_df"
998 [(set (match_operand:DF 0 "s_register_operand" "=f")
999 (div:DF (float_extend:DF
1000 (match_operand:SF 1 "s_register_operand" "f"))
1001 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1003 "dvf%?d\\t%0, %1, %2"
1004 [(set_attr "type" "fdivd")])
1006 (define_insn "*divdf_df_esfdf"
1007 [(set (match_operand:DF 0 "s_register_operand" "=f")
1008 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1010 (match_operand:SF 2 "s_register_operand" "f"))))]
1012 "rdf%?d\\t%0, %2, %1"
1013 [(set_attr "type" "fdivd")])
1015 (define_insn "*divdf_esfdf_esfdf"
1016 [(set (match_operand:DF 0 "s_register_operand" "=f")
1017 (div:DF (float_extend:DF
1018 (match_operand:SF 1 "s_register_operand" "f"))
1020 (match_operand:SF 2 "s_register_operand" "f"))))]
1022 "dvf%?d\\t%0, %1, %2"
1023 [(set_attr "type" "fdivd")])
1025 (define_insn "divxf3"
1026 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1027 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1028 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1029 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1032 rdf%?e\\t%0, %2, %1"
1033 [(set_attr "type" "fdivx")])
1037 (define_insn "modsf3"
1038 [(set (match_operand:SF 0 "s_register_operand" "=f")
1039 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1040 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1042 "rmf%?s\\t%0, %1, %2"
1043 [(set_attr "type" "fdivs")])
1045 (define_insn "moddf3"
1046 [(set (match_operand:DF 0 "s_register_operand" "=f")
1047 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1048 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1050 "rmf%?d\\t%0, %1, %2"
1051 [(set_attr "type" "fdivd")])
1053 (define_insn "*moddf_esfdf_df"
1054 [(set (match_operand:DF 0 "s_register_operand" "=f")
1055 (mod:DF (float_extend:DF
1056 (match_operand:SF 1 "s_register_operand" "f"))
1057 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1059 "rmf%?d\\t%0, %1, %2"
1060 [(set_attr "type" "fdivd")])
1062 (define_insn "*moddf_df_esfdf"
1063 [(set (match_operand:DF 0 "s_register_operand" "=f")
1064 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1066 (match_operand:SF 2 "s_register_operand" "f"))))]
1068 "rmf%?d\\t%0, %1, %2"
1069 [(set_attr "type" "fdivd")])
1071 (define_insn "*moddf_esfdf_esfdf"
1072 [(set (match_operand:DF 0 "s_register_operand" "=f")
1073 (mod:DF (float_extend:DF
1074 (match_operand:SF 1 "s_register_operand" "f"))
1076 (match_operand:SF 2 "s_register_operand" "f"))))]
1078 "rmf%?d\\t%0, %1, %2"
1079 [(set_attr "type" "fdivd")])
1081 (define_insn "modxf3"
1082 [(set (match_operand:XF 0 "s_register_operand" "=f")
1083 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1084 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1085 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1086 "rmf%?e\\t%0, %1, %2"
1087 [(set_attr "type" "fdivx")])
1089 ;; Boolean and,ior,xor insns
1091 (define_insn "anddi3"
1092 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1093 (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1094 (match_operand:DI 2 "s_register_operand" "r,0")))]
1096 "and%?\\t%Q0, %Q1, %Q2\;and%?\\t%R0, %R1, %R2"
1097 [(set_attr "length" "8")])
1099 (define_insn "*anddi_zesidi_di"
1100 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1101 (and:DI (zero_extend:DI
1102 (match_operand:SI 2 "s_register_operand" "r,r"))
1103 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1105 "and%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, #0"
1106 [(set_attr "length" "8")])
1108 (define_insn "*anddi_sesdi_di"
1109 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1110 (and:DI (sign_extend:DI
1111 (match_operand:SI 2 "s_register_operand" "r,r"))
1112 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1114 "and%?\\t%Q0, %Q1, %2\;and%?\\t%R0, %R1, %2, asr #31"
1115 [(set_attr "length" "8")])
1117 (define_expand "andsi3"
1118 [(set (match_operand:SI 0 "s_register_operand" "")
1119 (and:SI (match_operand:SI 1 "s_register_operand" "")
1120 (match_operand:SI 2 "reg_or_int_operand" "")))]
1123 if (GET_CODE (operands[2]) == CONST_INT)
1125 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1127 (reload_in_progress || reload_completed
1128 ? 0 : preserve_subexpressions_p ()));
1133 (define_insn "*andsi3_insn"
1134 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1135 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1136 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1140 bic%?\\t%0, %1, #%B2
1142 [(set_attr "length" "4,4,16")])
1145 [(set (match_operand:SI 0 "s_register_operand" "")
1146 (and:SI (match_operand:SI 1 "s_register_operand" "")
1147 (match_operand:SI 2 "const_int_operand" "")))]
1148 "! (const_ok_for_arm (INTVAL (operands[2]))
1149 || const_ok_for_arm (~ INTVAL (operands[2])))"
1150 [(clobber (const_int 0))]
1152 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1157 (define_insn "*andsi3_compare0"
1158 [(set (reg:CC_NOOV 24)
1160 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1161 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1163 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1164 (and:SI (match_dup 1) (match_dup 2)))]
1168 bic%?s\\t%0, %1, #%B2"
1169 [(set_attr "conds" "set")])
1171 (define_insn "*andsi3_compare0_scratch"
1172 [(set (reg:CC_NOOV 24)
1174 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1175 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1177 (clobber (match_scratch:SI 3 "=X,r"))]
1181 bic%?s\\t%3, %0, #%B1"
1182 [(set_attr "conds" "set")])
1184 (define_insn "*zeroextractsi_compare0_scratch"
1185 [(set (reg:CC_NOOV 24)
1186 (compare:CC_NOOV (zero_extract:SI
1187 (match_operand:SI 0 "s_register_operand" "r")
1188 (match_operand 1 "const_int_operand" "n")
1189 (match_operand 2 "const_int_operand" "n"))
1191 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1192 && INTVAL (operands[1]) > 0
1193 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1194 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1197 unsigned int mask = 0;
1198 int cnt = INTVAL (operands[1]);
1201 mask = (mask << 1) | 1;
1202 operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1203 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1207 [(set_attr "conds" "set")])
1209 (define_insn "*zeroextractqi_compare0_scratch"
1210 [(set (reg:CC_NOOV 24)
1211 (compare:CC_NOOV (zero_extract:SI
1212 (match_operand:QI 0 "memory_operand" "m")
1213 (match_operand 1 "const_int_operand" "n")
1214 (match_operand 2 "const_int_operand" "n"))
1216 (clobber (match_scratch:QI 3 "=r"))]
1217 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 8
1218 && INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8"
1221 unsigned int mask = 0;
1222 int cnt = INTVAL (operands[1]);
1225 mask = (mask << 1) | 1;
1226 operands[1] = GEN_INT (mask << INTVAL (operands[2]));
1227 output_asm_insn (\"ldr%?b\\t%3, %0\", operands);
1228 output_asm_insn (\"tst%?\\t%3, %1\", operands);
1232 [(set_attr "conds" "set")
1233 (set_attr "length" "8")])
1235 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1236 ;;; represented by the bitfield, then this will produce incorrect results.
1237 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1238 ;;; which have a real bitfield insert instruction, the truncation happens
1239 ;;; in the bitfield insert instruction itself. Since arm does not have a
1240 ;;; bitfield insert instruction, we would have to emit code here to truncate
1241 ;;; the value before we insert. This loses some of the advantage of having
1242 ;;; this insv pattern, so this pattern needs to be reevalutated.
1244 (define_expand "insv"
1245 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1246 (match_operand:SI 1 "general_operand" "")
1247 (match_operand:SI 2 "general_operand" ""))
1248 (match_operand:SI 3 "nonmemory_operand" ""))]
1252 int start_bit = INTVAL (operands[2]);
1253 int width = INTVAL (operands[1]);
1254 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1255 rtx target, subtarget;
1257 target = operands[0];
1258 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1259 subreg as the final target. */
1260 if (GET_CODE (target) == SUBREG)
1262 subtarget = gen_reg_rtx (SImode);
1263 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1264 < GET_MODE_SIZE (SImode))
1265 target = SUBREG_REG (target);
1270 if (GET_CODE (operands[3]) == CONST_INT)
1272 /* Since we are inserting a known constant, we may be able to
1273 reduce the number of bits that we have to clear so that
1274 the mask becomes simple. */
1275 /* ??? This code does not check to see if the new mask is actually
1276 simpler. It may not be. */
1277 rtx op1 = gen_reg_rtx (SImode);
1278 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1279 start of this pattern. */
1280 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1281 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1283 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1284 emit_insn (gen_iorsi3 (subtarget, op1,
1285 GEN_INT (op3_value << start_bit)));
1287 else if (start_bit == 0
1288 && ! (const_ok_for_arm (mask)
1289 || const_ok_for_arm (~mask)))
1291 /* A Trick, since we are setting the bottom bits in the word,
1292 we can shift operand[3] up, operand[0] down, OR them together
1293 and rotate the result back again. This takes 3 insns, and
1294 the third might be mergable into another op. */
1295 /* The shift up copes with the possibility that operand[3] is
1296 wider than the bitfield. */
1297 rtx op0 = gen_reg_rtx (SImode);
1298 rtx op1 = gen_reg_rtx (SImode);
1300 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1301 emit_insn (gen_iorsi3 (op1, gen_rtx (LSHIFTRT, SImode, operands[0],
1304 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1306 else if ((width + start_bit == 32)
1307 && ! (const_ok_for_arm (mask)
1308 || const_ok_for_arm (~mask)))
1310 /* Similar trick, but slightly less efficient. */
1312 rtx op0 = gen_reg_rtx (SImode);
1313 rtx op1 = gen_reg_rtx (SImode);
1315 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1316 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1317 emit_insn (gen_iorsi3 (subtarget,
1318 gen_rtx (LSHIFTRT, SImode, op1,
1319 operands[1]), op0));
1323 rtx op0 = GEN_INT (mask);
1324 rtx op1 = gen_reg_rtx (SImode);
1325 rtx op2 = gen_reg_rtx (SImode);
1327 if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1329 rtx tmp = gen_reg_rtx (SImode);
1331 emit_insn (gen_movsi (tmp, op0));
1335 /* Mask out any bits in operand[3] that are not needed. */
1336 emit_insn (gen_andsi3 (op1, operands[3], op0));
1338 if (GET_CODE (op0) == CONST_INT
1339 && (const_ok_for_arm (mask << start_bit)
1340 || const_ok_for_arm (~ (mask << start_bit))))
1342 op0 = GEN_INT (~(mask << start_bit));
1343 emit_insn (gen_andsi3 (op2, operands[0], op0));
1347 if (GET_CODE (op0) == CONST_INT)
1349 rtx tmp = gen_reg_rtx (SImode);
1351 emit_insn (gen_movsi (tmp, op0));
1356 op0 = gen_rtx (ASHIFT, SImode, op0, operands[2]);
1358 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1362 op1 = gen_rtx (ASHIFT, SImode, op1, operands[2]);
1364 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1367 if (subtarget != target)
1369 /* If TARGET is still a SUBREG, then it must be wider than a word,
1370 so we must be careful only to set the subword we were asked to. */
1371 if (GET_CODE (target) == SUBREG)
1372 emit_move_insn (target, subtarget);
1374 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1381 ;; constants for op 2 will never be given to these patterns.
1382 (define_insn "*anddi_notdi_di"
1383 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1384 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1385 (match_operand:DI 1 "s_register_operand" "0,r")))]
1387 "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2"
1388 [(set_attr "length" "8")])
1390 (define_insn "*anddi_notzesidi_di"
1391 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1392 (and:DI (not:DI (zero_extend:DI
1393 (match_operand:SI 2 "s_register_operand" "r,r")))
1394 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1397 bic%?\\t%Q0, %Q1, %2
1398 bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1399 [(set_attr "length" "4,8")])
1401 (define_insn "*anddi_notsesidi_di"
1402 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1403 (and:DI (not:DI (sign_extend:DI
1404 (match_operand:SI 2 "s_register_operand" "r,r")))
1405 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1407 "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
1408 [(set_attr "length" "8")])
1410 (define_insn "andsi_notsi_si"
1411 [(set (match_operand:SI 0 "s_register_operand" "=r")
1412 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1413 (match_operand:SI 1 "s_register_operand" "r")))]
1415 "bic%?\\t%0, %1, %2")
1417 (define_insn "andsi_not_shiftsi_si"
1418 [(set (match_operand:SI 0 "s_register_operand" "=r")
1419 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1420 [(match_operand:SI 2 "s_register_operand" "r")
1421 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1422 (match_operand:SI 1 "s_register_operand" "r")))]
1424 "bic%?\\t%0, %1, %2%S4")
1426 (define_insn "*andsi_notsi_si_compare0"
1427 [(set (reg:CC_NOOV 24)
1429 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1430 (match_operand:SI 1 "s_register_operand" "r"))
1432 (set (match_operand:SI 0 "s_register_operand" "=r")
1433 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1435 "bic%?s\\t%0, %1, %2"
1436 [(set_attr "conds" "set")])
1438 (define_insn "*andsi_notsi_si_compare0_scratch"
1439 [(set (reg:CC_NOOV 24)
1441 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1442 (match_operand:SI 1 "s_register_operand" "r"))
1444 (clobber (match_scratch:SI 0 "=r"))]
1446 "bic%?s\\t%0, %1, %2"
1447 [(set_attr "conds" "set")])
1449 (define_insn "iordi3"
1450 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1451 (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1452 (match_operand:DI 2 "s_register_operand" "r")))]
1454 "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2"
1455 [(set_attr "length" "8")])
1457 (define_insn "*iordi_zesidi_di"
1458 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1459 (ior:DI (zero_extend:DI
1460 (match_operand:SI 2 "s_register_operand" "r,r"))
1461 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1464 orr%?\\t%Q0, %Q1, %2
1465 orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1466 [(set_attr "length" "4,8")])
1468 (define_insn "*iordi_sesidi_di"
1469 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1470 (ior:DI (sign_extend:DI
1471 (match_operand:SI 2 "s_register_operand" "r,r"))
1472 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1474 "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
1475 [(set_attr "length" "8")])
1477 (define_expand "iorsi3"
1478 [(set (match_operand:SI 0 "s_register_operand" "")
1479 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1480 (match_operand:SI 2 "reg_or_int_operand" "")))]
1483 if (GET_CODE (operands[2]) == CONST_INT)
1485 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1487 (reload_in_progress || reload_completed
1488 ? 0 : preserve_subexpressions_p ()));
1493 (define_insn "*iorsi3_insn"
1494 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1495 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1496 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1501 [(set_attr "length" "4,16")])
1504 [(set (match_operand:SI 0 "s_register_operand" "")
1505 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1506 (match_operand:SI 2 "const_int_operand" "")))]
1507 "! const_ok_for_arm (INTVAL (operands[2]))"
1508 [(clobber (const_int 0))]
1510 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1515 (define_insn "*iorsi3_compare0"
1516 [(set (reg:CC_NOOV 24)
1517 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1518 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1520 (set (match_operand:SI 0 "s_register_operand" "=r")
1521 (ior:SI (match_dup 1) (match_dup 2)))]
1523 "orr%?s\\t%0, %1, %2"
1524 [(set_attr "conds" "set")])
1526 (define_insn "*iorsi3_compare0_scratch"
1527 [(set (reg:CC_NOOV 24)
1528 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1529 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1531 (clobber (match_scratch:SI 0 "=r"))]
1533 "orr%?s\\t%0, %1, %2"
1534 [(set_attr "conds" "set")])
1536 (define_insn "xordi3"
1537 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1538 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1539 (match_operand:DI 2 "s_register_operand" "r,0")))]
1541 "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2"
1542 [(set_attr "length" "8")])
1544 (define_insn "*xordi_zesidi_di"
1545 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1546 (xor:DI (zero_extend:DI
1547 (match_operand:SI 2 "s_register_operand" "r,r"))
1548 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1551 eor%?\\t%Q0, %Q1, %2
1552 eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1553 [(set_attr "length" "4,8")])
1555 (define_insn "*xordi_sesidi_di"
1556 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1557 (xor:DI (sign_extend:DI
1558 (match_operand:SI 2 "s_register_operand" "r,r"))
1559 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1561 "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
1562 [(set_attr "length" "8")])
1564 (define_insn "xorsi3"
1565 [(set (match_operand:SI 0 "s_register_operand" "=r")
1566 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1567 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1569 "eor%?\\t%0, %1, %2")
1571 (define_insn "*xorsi3_compare0"
1572 [(set (reg:CC_NOOV 24)
1573 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1574 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1576 (set (match_operand:SI 0 "s_register_operand" "=r")
1577 (xor:SI (match_dup 1) (match_dup 2)))]
1579 "eor%?s\\t%0, %1, %2"
1580 [(set_attr "conds" "set")])
1582 (define_insn "*xorsi3_compare0_scratch"
1583 [(set (reg:CC_NOOV 24)
1584 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1585 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1589 [(set_attr "conds" "set")])
1591 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
1592 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1596 [(set (match_operand:SI 0 "s_register_operand" "=r")
1597 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1598 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1599 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1600 (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1602 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1603 (not:SI (match_dup 3))))
1604 (set (match_dup 0) (not:SI (match_dup 4)))]
1608 (define_insn "*andsi_iorsi3_notsi"
1609 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1610 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1611 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1612 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1614 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1615 [(set_attr "length" "8")])
1619 ;; Minimum and maximum insns
1621 (define_insn "smaxsi3"
1622 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1623 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1624 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1625 (clobber (reg:CC 24))]
1628 cmp\\t%1, %2\;movlt\\t%0, %2
1629 cmp\\t%1, %2\;movge\\t%0, %1
1630 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1631 [(set_attr "conds" "clob")
1632 (set_attr "length" "8,8,12")])
1634 (define_insn "sminsi3"
1635 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1636 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1637 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1638 (clobber (reg:CC 24))]
1641 cmp\\t%1, %2\;movge\\t%0, %2
1642 cmp\\t%1, %2\;movlt\\t%0, %1
1643 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1644 [(set_attr "conds" "clob")
1645 (set_attr "length" "8,8,12")])
1647 (define_insn "umaxsi3"
1648 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1649 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1650 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1651 (clobber (reg:CC 24))]
1654 cmp\\t%1, %2\;movcc\\t%0, %2
1655 cmp\\t%1, %2\;movcs\\t%0, %1
1656 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1657 [(set_attr "conds" "clob")
1658 (set_attr "length" "8,8,12")])
1660 (define_insn "uminsi3"
1661 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1662 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1663 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1664 (clobber (reg:CC 24))]
1667 cmp\\t%1, %2\;movcs\\t%0, %2
1668 cmp\\t%1, %2\;movcc\\t%0, %1
1669 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1670 [(set_attr "conds" "clob")
1671 (set_attr "length" "8,8,12")])
1673 (define_insn "*store_minmaxsi"
1674 [(set (match_operand:SI 0 "memory_operand" "=m")
1675 (match_operator:SI 3 "minmax_operator"
1676 [(match_operand:SI 1 "s_register_operand" "r")
1677 (match_operand:SI 2 "s_register_operand" "r")]))
1678 (clobber (reg:CC 24))]
1681 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1683 output_asm_insn (\"cmp\\t%1, %2\", operands);
1684 output_asm_insn (\"str%d3\\t%1, %0\", operands);
1685 output_asm_insn (\"str%D3\\t%2, %0\", operands);
1688 [(set_attr "conds" "clob")
1689 (set_attr "length" "12")
1690 (set_attr "type" "store1")])
1692 ; Reject the frame pointer in operand[1], since reloading this after
1693 ; it has been eliminated can cause carnage.
1694 (define_insn "*minmax_arithsi"
1695 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1696 (match_operator:SI 4 "shiftable_operator"
1697 [(match_operator:SI 5 "minmax_operator"
1698 [(match_operand:SI 2 "s_register_operand" "r,r")
1699 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1700 (match_operand:SI 1 "s_register_operand" "0,?r")]))
1701 (clobber (reg:CC 24))]
1702 "GET_CODE (operands[1]) != REG
1703 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
1704 && REGNO(operands[1]) != ARG_POINTER_REGNUM)"
1707 enum rtx_code code = GET_CODE (operands[4]);
1709 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1711 output_asm_insn (\"cmp\\t%2, %3\", operands);
1712 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1713 if (which_alternative != 0 || operands[3] != const0_rtx
1714 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1715 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1719 [(set_attr "conds" "clob")
1720 (set_attr "length" "12")])
1723 ;; Shift and rotation insns
1725 (define_expand "ashlsi3"
1726 [(set (match_operand:SI 0 "s_register_operand" "")
1727 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
1728 (match_operand:SI 2 "arm_rhs_operand" "")))]
1731 if (GET_CODE (operands[2]) == CONST_INT
1732 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1734 emit_insn (gen_movsi (operands[0], const0_rtx));
1739 (define_expand "ashrsi3"
1740 [(set (match_operand:SI 0 "s_register_operand" "")
1741 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1742 (match_operand:SI 2 "arm_rhs_operand" "")))]
1745 if (GET_CODE (operands[2]) == CONST_INT
1746 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1747 operands[2] = GEN_INT (31);
1750 (define_expand "lshrsi3"
1751 [(set (match_operand:SI 0 "s_register_operand" "")
1752 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1753 (match_operand:SI 2 "arm_rhs_operand" "")))]
1756 if (GET_CODE (operands[2]) == CONST_INT
1757 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1759 emit_insn (gen_movsi (operands[0], const0_rtx));
1764 (define_expand "rotlsi3"
1765 [(set (match_operand:SI 0 "s_register_operand" "")
1766 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1767 (match_operand:SI 2 "reg_or_int_operand" "")))]
1770 if (GET_CODE (operands[2]) == CONST_INT)
1771 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
1774 rtx reg = gen_reg_rtx (SImode);
1775 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
1780 (define_expand "rotrsi3"
1781 [(set (match_operand:SI 0 "s_register_operand" "")
1782 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1783 (match_operand:SI 2 "arm_rhs_operand" "")))]
1786 if (GET_CODE (operands[2]) == CONST_INT
1787 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1788 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
1791 (define_insn "*shiftsi3"
1792 [(set (match_operand:SI 0 "s_register_operand" "=r")
1793 (match_operator:SI 3 "shift_operator"
1794 [(match_operand:SI 1 "s_register_operand" "r")
1795 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
1797 "mov%?\\t%0, %1%S3")
1799 (define_insn "*shiftsi3_compare0"
1800 [(set (reg:CC_NOOV 24)
1801 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1802 [(match_operand:SI 1 "s_register_operand" "r")
1803 (match_operand:SI 2 "arm_rhs_operand" "rM")])
1805 (set (match_operand:SI 0 "s_register_operand" "=r")
1806 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
1808 "mov%?s\\t%0, %1%S3"
1809 [(set_attr "conds" "set")])
1811 (define_insn "*shiftsi3_compare0_scratch"
1812 [(set (reg:CC_NOOV 24)
1813 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1814 [(match_operand:SI 1 "s_register_operand" "r")
1815 (match_operand:SI 2 "arm_rhs_operand" "rM")])
1817 (clobber (match_scratch:SI 0 "=r"))]
1819 "mov%?s\\t%0, %1%S3"
1820 [(set_attr "conds" "set")])
1822 (define_insn "*notsi_shiftsi"
1823 [(set (match_operand:SI 0 "s_register_operand" "=r")
1824 (not:SI (match_operator:SI 3 "shift_operator"
1825 [(match_operand:SI 1 "s_register_operand" "r")
1826 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
1828 "mvn%?\\t%0, %1%S3")
1830 (define_insn "*notsi_shiftsi_compare0"
1831 [(set (reg:CC_NOOV 24)
1832 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1833 [(match_operand:SI 1 "s_register_operand" "r")
1834 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1836 (set (match_operand:SI 0 "s_register_operand" "=r")
1837 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1839 "mvn%?s\\t%0, %1%S3"
1840 [(set_attr "conds" "set")])
1842 (define_insn "*not_shiftsi_compare0_scratch"
1843 [(set (reg:CC_NOOV 24)
1844 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1845 [(match_operand:SI 1 "s_register_operand" "r")
1846 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1848 (clobber (match_scratch:SI 0 "=r"))]
1850 "mvn%?s\\t%0, %1%S3"
1851 [(set_attr "conds" "set")])
1854 ;; Unary arithmetic insns
1856 (define_insn "negdi2"
1857 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1858 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1860 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
1861 [(set_attr "conds" "clob")
1862 (set_attr "length" "8")])
1864 (define_insn "negsi2"
1865 [(set (match_operand:SI 0 "s_register_operand" "=r")
1866 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1868 "rsb%?\\t%0, %1, #0")
1870 (define_insn "negsf2"
1871 [(set (match_operand:SF 0 "s_register_operand" "=f")
1872 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1875 [(set_attr "type" "ffarith")])
1877 (define_insn "negdf2"
1878 [(set (match_operand:DF 0 "s_register_operand" "=f")
1879 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1882 [(set_attr "type" "ffarith")])
1884 (define_insn "*negdf_esfdf"
1885 [(set (match_operand:DF 0 "s_register_operand" "=f")
1886 (neg:DF (float_extend:DF
1887 (match_operand:SF 1 "s_register_operand" "f"))))]
1890 [(set_attr "type" "ffarith")])
1892 (define_insn "negxf2"
1893 [(set (match_operand:XF 0 "s_register_operand" "=f")
1894 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1895 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1897 [(set_attr "type" "ffarith")])
1899 ;; abssi2 doesn't really clobber the condition codes if a different register
1900 ;; is being set. To keep things simple, assume during rtl manipulations that
1901 ;; it does, but tell the final scan operator the truth. Similarly for
1904 (define_insn "abssi2"
1905 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1906 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1907 (clobber (reg:CC 24))]
1910 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
1911 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
1912 [(set_attr "conds" "clob,*")
1913 (set_attr "length" "8")])
1915 (define_insn "*neg_abssi2"
1916 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1917 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1918 (clobber (reg:CC 24))]
1921 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
1922 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
1923 [(set_attr "conds" "clob,*")
1924 (set_attr "length" "8")])
1926 (define_insn "abssf2"
1927 [(set (match_operand:SF 0 "s_register_operand" "=f")
1928 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1931 [(set_attr "type" "ffarith")])
1933 (define_insn "absdf2"
1934 [(set (match_operand:DF 0 "s_register_operand" "=f")
1935 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1938 [(set_attr "type" "ffarith")])
1940 (define_insn "*absdf_esfdf"
1941 [(set (match_operand:DF 0 "s_register_operand" "=f")
1942 (abs:DF (float_extend:DF
1943 (match_operand:SF 1 "s_register_operand" "f"))))]
1946 [(set_attr "type" "ffarith")])
1948 (define_insn "absxf2"
1949 [(set (match_operand:XF 0 "s_register_operand" "=f")
1950 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1951 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1953 [(set_attr "type" "ffarith")])
1955 (define_insn "sqrtsf2"
1956 [(set (match_operand:SF 0 "s_register_operand" "=f")
1957 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1960 [(set_attr "type" "float_em")])
1962 (define_insn "sqrtdf2"
1963 [(set (match_operand:DF 0 "s_register_operand" "=f")
1964 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1967 [(set_attr "type" "float_em")])
1969 (define_insn "*sqrtdf_esfdf"
1970 [(set (match_operand:DF 0 "s_register_operand" "=f")
1971 (sqrt:DF (float_extend:DF
1972 (match_operand:SF 1 "s_register_operand" "f"))))]
1975 [(set_attr "type" "float_em")])
1977 (define_insn "sqrtxf2"
1978 [(set (match_operand:XF 0 "s_register_operand" "=f")
1979 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1980 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1982 [(set_attr "type" "float_em")])
1984 ;; SIN COS TAN and family are always emulated, so it's probably better
1985 ;; to always call a library function.
1986 ;(define_insn "sinsf2"
1987 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
1988 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1989 ; "TARGET_HARD_FLOAT"
1991 ;[(set_attr "type" "float_em")])
1993 ;(define_insn "sindf2"
1994 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
1995 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1996 ; "TARGET_HARD_FLOAT"
1998 ;[(set_attr "type" "float_em")])
2000 ;(define_insn "*sindf_esfdf"
2001 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2002 ; (unspec:DF [(float_extend:DF
2003 ; (match_operand:SF 1 "s_register_operand" "f"))] 0))]
2004 ; "TARGET_HARD_FLOAT"
2006 ;[(set_attr "type" "float_em")])
2008 ;(define_insn "sinxf2"
2009 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2010 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
2011 ; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2013 ;[(set_attr "type" "float_em")])
2015 ;(define_insn "cossf2"
2016 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2017 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
2018 ; "TARGET_HARD_FLOAT"
2020 ;[(set_attr "type" "float_em")])
2022 ;(define_insn "cosdf2"
2023 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2024 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
2025 ; "TARGET_HARD_FLOAT"
2027 ;[(set_attr "type" "float_em")])
2029 ;(define_insn "*cosdf_esfdf"
2030 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2031 ; (unspec:DF [(float_extend:DF
2032 ; (match_operand:SF 1 "s_register_operand" "f"))] 1))]
2033 ; "TARGET_HARD_FLOAT"
2035 ;[(set_attr "type" "float_em")])
2037 ;(define_insn "cosxf2"
2038 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2039 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
2040 ; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2042 ;[(set_attr "type" "float_em")])
2044 (define_insn "one_cmpldi2"
2045 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2046 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2048 "mvn%?\\t%Q0, %Q1\;mvn%?\\t%R0, %R1"
2049 [(set_attr "length" "8")])
2051 (define_insn "one_cmplsi2"
2052 [(set (match_operand:SI 0 "s_register_operand" "=r")
2053 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2057 (define_insn "*notsi_compare0"
2058 [(set (reg:CC_NOOV 24)
2059 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2061 (set (match_operand:SI 0 "s_register_operand" "=r")
2062 (not:SI (match_dup 1)))]
2065 [(set_attr "conds" "set")])
2067 (define_insn "*notsi_compare0_scratch"
2068 [(set (reg:CC_NOOV 24)
2069 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2071 (clobber (match_scratch:SI 0 "=r"))]
2074 [(set_attr "conds" "set")])
2076 ;; Fixed <--> Floating conversion insns
2078 (define_insn "floatsisf2"
2079 [(set (match_operand:SF 0 "s_register_operand" "=f")
2080 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2083 [(set_attr "type" "r_2_f")])
2085 (define_insn "floatsidf2"
2086 [(set (match_operand:DF 0 "s_register_operand" "=f")
2087 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2090 [(set_attr "type" "r_2_f")])
2092 (define_insn "floatsixf2"
2093 [(set (match_operand:XF 0 "s_register_operand" "=f")
2094 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
2095 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2097 [(set_attr "type" "r_2_f")])
2099 (define_insn "fix_truncsfsi2"
2100 [(set (match_operand:SI 0 "s_register_operand" "=r")
2101 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2104 [(set_attr "type" "f_2_r")])
2106 (define_insn "fix_truncdfsi2"
2107 [(set (match_operand:SI 0 "s_register_operand" "=r")
2108 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2111 [(set_attr "type" "f_2_r")])
2113 (define_insn "fix_truncxfsi2"
2114 [(set (match_operand:SI 0 "s_register_operand" "=r")
2115 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
2116 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2118 [(set_attr "type" "f_2_r")])
2122 (define_insn "truncdfsf2"
2123 [(set (match_operand:SF 0 "s_register_operand" "=f")
2125 (match_operand:DF 1 "s_register_operand" "f")))]
2128 [(set_attr "type" "ffarith")])
2130 (define_insn "truncxfsf2"
2131 [(set (match_operand:SF 0 "s_register_operand" "=f")
2133 (match_operand:XF 1 "s_register_operand" "f")))]
2134 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2136 [(set_attr "type" "ffarith")])
2138 (define_insn "truncxfdf2"
2139 [(set (match_operand:DF 0 "s_register_operand" "=f")
2141 (match_operand:XF 1 "s_register_operand" "f")))]
2142 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2144 [(set_attr "type" "ffarith")])
2146 ;; Zero and sign extension instructions.
2148 (define_insn "zero_extendsidi2"
2149 [(set (match_operand:DI 0 "s_register_operand" "=r")
2150 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2153 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2154 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2155 return \"mov%?\\t%R0, #0\";
2157 [(set_attr "length" "8")])
2159 (define_insn "zero_extendqidi2"
2160 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2161 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2164 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2165 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2166 [(set_attr "length" "8")
2167 (set_attr "type" "*,load")])
2169 (define_insn "extendsidi2"
2170 [(set (match_operand:DI 0 "s_register_operand" "=r")
2171 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2174 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2175 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2176 return \"mov%?\\t%R0, %Q0, asr #31\";
2178 [(set_attr "length" "8")])
2180 (define_expand "zero_extendhisi2"
2181 [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2183 (set (match_operand:SI 0 "s_register_operand" "")
2184 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2188 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2190 emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2191 gen_rtx (ZERO_EXTEND, SImode, operands[1])));
2194 if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2196 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2199 if (! s_register_operand (operands[1], HImode))
2200 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2201 operands[1] = gen_lowpart (SImode, operands[1]);
2202 operands[2] = gen_reg_rtx (SImode);
2205 (define_insn "*zero_extendhisi_insn"
2206 [(set (match_operand:SI 0 "s_register_operand" "=r")
2207 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2210 [(set_attr "type" "load")])
2213 [(set (match_operand:SI 0 "s_register_operand" "")
2214 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2215 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2217 [(set (match_dup 2) (match_dup 1))
2218 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2221 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2226 [(set (match_operand:SI 0 "s_register_operand" "")
2227 (match_operator:SI 3 "shiftable_operator"
2228 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2229 (match_operand:SI 4 "s_register_operand" "")]))
2230 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2232 [(set (match_dup 2) (match_dup 1))
2235 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2238 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2242 (define_expand "zero_extendqisi2"
2243 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2245 (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2248 if (GET_CODE (operands[1]) != MEM)
2250 emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
2256 (define_insn "*load_extendqisi"
2257 [(set (match_operand:SI 0 "s_register_operand" "=r")
2258 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2260 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
2261 [(set_attr "type" "load")])
2264 [(set (match_operand:SI 0 "s_register_operand" "")
2265 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
2266 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2267 "GET_CODE (operands[1]) != MEM"
2268 [(set (match_dup 2) (match_dup 1))
2269 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
2272 (define_insn "*compareqi_eq0"
2274 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
2278 [(set_attr "conds" "set")])
2280 (define_expand "extendhisi2"
2282 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2284 (set (match_operand:SI 0 "s_register_operand" "")
2285 (ashiftrt:SI (match_dup 2)
2290 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2292 emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2293 gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2297 if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2299 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
2302 if (! s_register_operand (operands[1], HImode))
2303 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2304 operands[1] = gen_lowpart (SImode, operands[1]);
2305 operands[2] = gen_reg_rtx (SImode);
2308 (define_expand "extendhisi2_mem"
2309 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
2311 (zero_extend:SI (match_dup 7)))
2312 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
2313 (set (match_operand:SI 0 "" "")
2314 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
2319 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2321 mem1 = gen_rtx (MEM, QImode, addr);
2322 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
2323 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
2324 mem2 = gen_rtx (MEM, QImode, plus_constant (addr, 1));
2325 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
2326 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
2327 operands[0] = gen_lowpart (SImode, operands[0]);
2329 operands[2] = gen_reg_rtx (SImode);
2330 operands[3] = gen_reg_rtx (SImode);
2331 operands[6] = gen_reg_rtx (SImode);
2334 if (BYTES_BIG_ENDIAN)
2336 operands[4] = operands[2];
2337 operands[5] = operands[3];
2341 operands[4] = operands[3];
2342 operands[5] = operands[2];
2347 (define_insn "*extendhisi_insn"
2348 [(set (match_operand:SI 0 "s_register_operand" "=r")
2349 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2352 [(set_attr "type" "load")])
2355 [(set (match_operand:SI 0 "s_register_operand" "")
2356 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2357 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2359 [(set (match_dup 2) (match_dup 1))
2360 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
2363 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2368 [(set (match_operand:SI 0 "s_register_operand" "")
2369 (match_operator:SI 3 "shiftable_operator"
2370 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2371 (match_operand:SI 4 "s_register_operand" "")]))
2372 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2374 [(set (match_dup 2) (match_dup 1))
2377 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2380 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2384 (define_expand "extendqihi2"
2386 (ashift:SI (match_operand:QI 1 "general_operand" "")
2388 (set (match_operand:HI 0 "s_register_operand" "")
2389 (ashiftrt:SI (match_dup 2)
2394 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2396 emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2397 gen_rtx (SIGN_EXTEND, HImode, operands[1])));
2400 if (! s_register_operand (operands[1], QImode))
2401 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2402 operands[0] = gen_lowpart (SImode, operands[0]);
2403 operands[1] = gen_lowpart (SImode, operands[1]);
2404 operands[2] = gen_reg_rtx (SImode);
2407 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2408 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2409 (define_insn "*extendqihi_insn"
2410 [(set (match_operand:HI 0 "s_register_operand" "=r")
2411 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
2414 /* If the address is invalid, this will split the instruction into two. */
2415 if (bad_signed_byte_operand(operands[1], QImode))
2417 return \"ldr%?sb\\t%0, %1\";
2419 [(set_attr "type" "load")
2420 (set_attr "length" "8")])
2423 [(set (match_operand:HI 0 "s_register_operand" "")
2424 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2425 "arm_arch4 && reload_completed"
2426 [(set (match_dup 3) (match_dup 1))
2427 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
2430 HOST_WIDE_INT offset;
2432 operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]));
2433 operands[2] = gen_rtx (MEM, QImode, operands[3]);
2434 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2435 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2436 operands[1] = XEXP (operands[1], 0);
2437 if (GET_CODE (operands[1]) == PLUS
2438 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2439 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2440 || const_ok_for_arm (-offset)))
2442 HOST_WIDE_INT low = (offset > 0
2443 ? (offset & 0xff) : -((-offset) & 0xff));
2444 XEXP (operands[2], 0) = plus_constant (operands[3], low);
2445 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2447 /* Ensure the sum is in correct canonical form */
2448 else if (GET_CODE (operands[1]) == PLUS
2449 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2450 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2451 operands[1] = gen_rtx (PLUS, GET_MODE (operands[1]),
2452 XEXP (operands[1], 1), XEXP (operands[1], 0));
2456 (define_expand "extendqisi2"
2458 (ashift:SI (match_operand:QI 1 "general_operand" "")
2460 (set (match_operand:SI 0 "s_register_operand" "")
2461 (ashiftrt:SI (match_dup 2)
2466 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2468 emit_insn (gen_rtx (SET, VOIDmode, operands[0],
2469 gen_rtx (SIGN_EXTEND, SImode, operands[1])));
2472 if (! s_register_operand (operands[1], QImode))
2473 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2474 operands[1] = gen_lowpart (SImode, operands[1]);
2475 operands[2] = gen_reg_rtx (SImode);
2478 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2479 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2480 (define_insn "*extendqisi_insn"
2481 [(set (match_operand:SI 0 "s_register_operand" "=r")
2482 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2485 /* If the address is invalid, this will split the instruction into two. */
2486 if (bad_signed_byte_operand(operands[1], QImode))
2488 return \"ldr%?sb\\t%0, %1\";
2490 [(set_attr "type" "load")
2491 (set_attr "length" "8")])
2494 [(set (match_operand:SI 0 "s_register_operand" "")
2495 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2496 "arm_arch4 && reload_completed"
2497 [(set (match_dup 0) (match_dup 1))
2498 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2501 HOST_WIDE_INT offset;
2503 operands[2] = gen_rtx (MEM, QImode, operands[0]);
2504 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2505 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2506 operands[1] = XEXP (operands[1], 0);
2507 if (GET_CODE (operands[1]) == PLUS
2508 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2509 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2510 || const_ok_for_arm (-offset)))
2512 HOST_WIDE_INT low = (offset > 0
2513 ? (offset & 0xff) : -((-offset) & 0xff));
2514 XEXP (operands[2], 0) = plus_constant (operands[0], low);
2515 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2517 /* Ensure the sum is in correct canonical form */
2518 else if (GET_CODE (operands[1]) == PLUS
2519 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2520 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2521 operands[1] = gen_rtx (PLUS, GET_MODE (operands[1]),
2522 XEXP (operands[1], 1), XEXP (operands[1], 0));
2526 (define_insn "extendsfdf2"
2527 [(set (match_operand:DF 0 "s_register_operand" "=f")
2528 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2531 [(set_attr "type" "ffarith")])
2533 (define_insn "extendsfxf2"
2534 [(set (match_operand:XF 0 "s_register_operand" "=f")
2535 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2536 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2538 [(set_attr "type" "ffarith")])
2540 (define_insn "extenddfxf2"
2541 [(set (match_operand:XF 0 "s_register_operand" "=f")
2542 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2543 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2545 [(set_attr "type" "ffarith")])
2548 ;; Move insns (including loads and stores)
2550 ;; XXX Just some ideas about movti.
2551 ;; I don't think these are a good idea on the arm, there just aren't enough
2553 ;;(define_expand "loadti"
2554 ;; [(set (match_operand:TI 0 "s_register_operand" "")
2555 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
2558 ;;(define_expand "storeti"
2559 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2560 ;; (match_operand:TI 1 "s_register_operand" ""))]
2563 ;;(define_expand "movti"
2564 ;; [(set (match_operand:TI 0 "general_operand" "")
2565 ;; (match_operand:TI 1 "general_operand" ""))]
2571 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2572 ;; operands[1] = copy_to_reg (operands[1]);
2573 ;; if (GET_CODE (operands[0]) == MEM)
2574 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2575 ;; else if (GET_CODE (operands[1]) == MEM)
2576 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2580 ;; emit_insn (insn);
2584 ;; Recognise garbage generated above.
2587 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2588 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2592 ;; register mem = (which_alternative < 3);
2593 ;; register char *template;
2595 ;; operands[mem] = XEXP (operands[mem], 0);
2596 ;; switch (which_alternative)
2598 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2599 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
2600 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
2601 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
2602 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
2603 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
2605 ;; output_asm_insn (template, operands);
2610 (define_insn "movdi"
2611 [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2612 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2615 return (output_move_double (operands));
2617 [(set_attr "length" "8,8,8")
2618 (set_attr "type" "*,load,store2")])
2620 (define_expand "movsi"
2621 [(set (match_operand:SI 0 "general_operand" "")
2622 (match_operand:SI 1 "general_operand" ""))]
2625 /* Everything except mem = const or mem = mem can be done easily */
2626 if (GET_CODE (operands[0]) == MEM)
2627 operands[1] = force_reg (SImode, operands[1]);
2628 if (GET_CODE (operands[1]) == CONST_INT
2629 && !(const_ok_for_arm (INTVAL (operands[1]))
2630 || const_ok_for_arm (~INTVAL (operands[1]))))
2632 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2634 (reload_in_progress || reload_completed ? 0
2635 : preserve_subexpressions_p ()));
2638 if (CONSTANT_P (operands[1]) && flag_pic)
2639 operands[1] = legitimize_pic_address (operands[1], SImode,
2640 ((reload_in_progress
2641 || reload_completed)
2642 ? operands[0] : 0));
2645 (define_insn "*movsi_insn"
2646 [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2647 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
2648 "register_operand (operands[0], SImode)
2649 || register_operand (operands[1], SImode)"
2655 [(set_attr "type" "*,*,load,store1")])
2658 [(set (match_operand:SI 0 "s_register_operand" "")
2659 (match_operand:SI 1 "const_int_operand" ""))]
2660 "! (const_ok_for_arm (INTVAL (operands[1]))
2661 || const_ok_for_arm (~INTVAL (operands[1])))"
2662 [(clobber (const_int 0))]
2664 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2669 (define_expand "movaddr"
2670 [(set (match_operand:SI 0 "s_register_operand" "")
2671 (match_operand:DI 1 "address_operand" ""))]
2675 (define_insn "*movaddr_insn"
2676 [(set (match_operand:SI 0 "s_register_operand" "=r")
2677 (match_operand:DI 1 "address_operand" "p"))]
2679 && (GET_CODE (operands[1]) == LABEL_REF
2680 || (GET_CODE (operands[1]) == CONST
2681 && GET_CODE (XEXP (operands[1], 0)) == PLUS
2682 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2683 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2686 /* When generating pic, we need to load the symbol offset into a register.
2687 So that the optimizer does not confuse this with a normal symbol load
2688 we use an unspec. The offset will be loaded from a constant pool entry,
2689 since that is the only type of relocation we can use. */
2691 (define_insn "pic_load_addr"
2692 [(set (match_operand:SI 0 "s_register_operand" "=r")
2693 (unspec:SI [(match_operand 1 "" "")] 3))]
2696 [(set_attr "type" "load")])
2698 ;; This variant is used for AOF assembly, since it needs to mention the
2699 ;; pic register in the rtl.
2700 (define_expand "pic_load_addr_based"
2701 [(set (match_operand:SI 0 "s_register_operand" "=r")
2702 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
2704 "operands[2] = pic_offset_table_rtx;")
2706 (define_insn "*pic_load_addr_based_insn"
2707 [(set (match_operand:SI 0 "s_register_operand" "=r")
2708 (unspec:SI [(match_operand 1 "" "")
2709 (match_operand 2 "s_register_operand" "r")] 3))]
2710 "flag_pic && operands[2] == pic_offset_table_rtx"
2712 #ifdef AOF_ASSEMBLER
2713 operands[1] = aof_pic_entry (operands[1]);
2715 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
2717 " [(set_attr "type" "load")])
2719 (define_insn "pic_add_dot_plus_eight"
2720 [(set (pc) (label_ref (match_operand 0 "" "")))
2721 (set (match_operand 1 "register_operand" "+r")
2722 (plus:SI (match_dup 1) (const (plus:SI (pc) (const_int 8)))))]
2724 "add%?\\t%1, %|pc, %1")
2726 ;; If copying one reg to another we can set the condition codes according to
2727 ;; its value. Such a move is common after a return from subroutine and the
2728 ;; result is being tested against zero.
2730 (define_insn "*movsi_compare0"
2731 [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
2733 (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2737 sub%?s\\t%0, %1, #0"
2738 [(set_attr "conds" "set")])
2740 ;; Subroutine to store a half word from a register into memory.
2741 ;; Operand 0 is the source register (HImode)
2742 ;; Operand 1 is the destination address in a register (SImode)
2744 ;; In both this routine and the next, we must be careful not to spill
2745 ;; a memory address of reg+large_const into a separate PLUS insn, since this
2746 ;; can generate unrecognizable rtl.
2748 (define_expand "storehi"
2749 [;; store the low byte
2750 (set (match_operand 1 "" "") (match_dup 3))
2751 ;; extract the high byte
2753 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2754 ;; store the high byte
2755 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
2759 rtx addr = XEXP (operands[1], 0);
2760 enum rtx_code code = GET_CODE (addr);
2762 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2764 addr = force_reg (SImode, addr);
2766 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2767 operands[1] = change_address (operands[1], QImode, NULL_RTX);
2768 operands[3] = gen_lowpart (QImode, operands[0]);
2769 operands[0] = gen_lowpart (SImode, operands[0]);
2770 operands[2] = gen_reg_rtx (SImode);
2774 (define_expand "storehi_bigend"
2775 [(set (match_dup 4) (match_dup 3))
2777 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2778 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
2782 rtx addr = XEXP (operands[1], 0);
2783 enum rtx_code code = GET_CODE (addr);
2785 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2787 addr = force_reg (SImode, addr);
2789 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2790 operands[1] = change_address (operands[1], QImode, NULL_RTX);
2791 operands[3] = gen_lowpart (QImode, operands[0]);
2792 operands[0] = gen_lowpart (SImode, operands[0]);
2793 operands[2] = gen_reg_rtx (SImode);
2797 ;; Subroutine to store a half word integer constant into memory.
2798 (define_expand "storeinthi"
2799 [(set (match_operand 0 "" "")
2800 (subreg:QI (match_operand 1 "" "") 0))
2801 (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
2805 HOST_WIDE_INT value = INTVAL (operands[1]);
2806 rtx addr = XEXP (operands[0], 0);
2807 enum rtx_code code = GET_CODE (addr);
2809 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2811 addr = force_reg (SImode, addr);
2813 operands[1] = gen_reg_rtx (SImode);
2814 if (BYTES_BIG_ENDIAN)
2816 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2817 if ((value & 255) == ((value >> 8) & 255))
2818 operands[2] = operands[1];
2821 operands[2] = gen_reg_rtx (SImode);
2822 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2827 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2828 if ((value & 255) == ((value >> 8) & 255))
2829 operands[2] = operands[1];
2832 operands[2] = gen_reg_rtx (SImode);
2833 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2837 operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
2838 operands[0] = change_address (operands[0], QImode, NULL_RTX);
2842 (define_expand "storehi_single_op"
2843 [(set (match_operand:HI 0 "memory_operand" "")
2844 (match_operand:HI 1 "general_operand" ""))]
2847 if (! s_register_operand (operands[1], HImode))
2848 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2851 (define_expand "movhi"
2852 [(set (match_operand:HI 0 "general_operand" "")
2853 (match_operand:HI 1 "general_operand" ""))]
2859 if (! (reload_in_progress || reload_completed))
2861 if (GET_CODE (operands[0]) == MEM)
2865 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2868 if (GET_CODE (operands[1]) == CONST_INT)
2869 emit_insn (gen_storeinthi (operands[0], operands[1]));
2872 if (GET_CODE (operands[1]) == MEM)
2873 operands[1] = force_reg (HImode, operands[1]);
2874 if (BYTES_BIG_ENDIAN)
2875 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
2877 emit_insn (gen_storehi (operands[1], operands[0]));
2881 /* Sign extend a constant, and keep it in an SImode reg. */
2882 else if (GET_CODE (operands[1]) == CONST_INT)
2884 rtx reg = gen_reg_rtx (SImode);
2885 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2887 /* If the constant is already valid, leave it alone. */
2888 if (! const_ok_for_arm (val))
2890 /* If setting all the top bits will make the constant
2891 loadable in a single instruction, then set them.
2892 Otherwise, sign extend the number. */
2894 if (const_ok_for_arm (~ (val | ~0xffff)))
2896 else if (val & 0x8000)
2900 emit_insn (gen_movsi (reg, GEN_INT (val)));
2901 operands[1] = gen_rtx (SUBREG, HImode, reg, 0);
2903 else if (! arm_arch4)
2905 if (GET_CODE (operands[1]) == MEM)
2907 if (TARGET_SHORT_BY_BYTES)
2910 rtx offset = const0_rtx;
2911 rtx reg = gen_reg_rtx (SImode);
2913 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2914 || (GET_CODE (base) == PLUS
2915 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2916 && GET_CODE (base = XEXP (base, 0)) == REG))
2917 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2919 HOST_WIDE_INT new_offset = INTVAL (offset) & ~2;
2922 new = gen_rtx (MEM, SImode,
2923 plus_constant (base, new_offset));
2924 MEM_COPY_ATTRIBUTES (new, operands[1]);
2925 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2926 emit_insn (gen_movsi (reg, new));
2927 if (((INTVAL (offset) & 2) != 0)
2928 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
2930 rtx reg2 = gen_reg_rtx (SImode);
2932 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
2937 emit_insn (gen_movhi_bytes (reg, operands[1]));
2939 operands[1] = gen_lowpart (HImode, reg);
2941 else if (BYTES_BIG_ENDIAN)
2944 rtx offset = const0_rtx;
2946 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2947 || (GET_CODE (base) == PLUS
2948 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2949 && GET_CODE (base = XEXP (base, 0)) == REG))
2950 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2952 rtx reg = gen_reg_rtx (SImode);
2955 if ((INTVAL (offset) & 2) == 2)
2957 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
2958 new = gen_rtx (MEM, SImode,
2959 plus_constant (base, new_offset));
2960 MEM_COPY_ATTRIBUTES (new, operands[1]);
2961 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2962 emit_insn (gen_movsi (reg, new));
2966 new = gen_rtx (MEM, SImode, XEXP (operands[1], 0));
2967 MEM_COPY_ATTRIBUTES (new, operands[1]);
2968 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2969 emit_insn (gen_rotated_loadsi (reg, new));
2972 operands[1] = gen_lowpart (HImode, reg);
2976 emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2983 /* Handle loading a large integer during reload */
2984 else if (GET_CODE (operands[1]) == CONST_INT
2985 && ! const_ok_for_arm (INTVAL (operands[1]))
2986 && ! const_ok_for_arm (~INTVAL (operands[1])))
2988 /* Writing a constant to memory needs a scratch, which should
2989 be handled with SECONDARY_RELOADs. */
2990 if (GET_CODE (operands[0]) != REG)
2993 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
2994 emit_insn (gen_movsi (operands[0], operands[1]));
3000 (define_insn "rotated_loadsi"
3001 [(set (match_operand:SI 0 "s_register_operand" "=r")
3002 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
3004 "! TARGET_SHORT_BY_BYTES"
3009 ops[0] = operands[0];
3010 ops[1] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[1], 0), 2));
3011 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
3014 [(set_attr "type" "load")])
3016 (define_expand "movhi_bytes"
3017 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3019 (zero_extend:SI (match_dup 6)))
3020 (set (match_operand:SI 0 "" "")
3021 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
3026 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3028 mem1 = gen_rtx (MEM, QImode, addr);
3029 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3030 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
3031 mem2 = gen_rtx (MEM, QImode, plus_constant (addr, 1));
3032 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3033 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
3034 operands[0] = gen_lowpart (SImode, operands[0]);
3036 operands[2] = gen_reg_rtx (SImode);
3037 operands[3] = gen_reg_rtx (SImode);
3040 if (BYTES_BIG_ENDIAN)
3042 operands[4] = operands[2];
3043 operands[5] = operands[3];
3047 operands[4] = operands[3];
3048 operands[5] = operands[2];
3053 (define_expand "movhi_bigend"
3055 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
3058 (ashiftrt:SI (match_dup 2) (const_int 16)))
3059 (set (match_operand:HI 0 "s_register_operand" "")
3060 (subreg:HI (match_dup 3) 0))]
3063 operands[2] = gen_reg_rtx (SImode);
3064 operands[3] = gen_reg_rtx (SImode);
3067 ;; Pattern to recognise insn generated default case above
3069 (define_insn "*movhi_insn_arch4"
3070 [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
3071 (match_operand:HI 1 "general_operand" "rI,K,m,r"))]
3073 && (GET_CODE (operands[1]) != CONST_INT
3074 || const_ok_for_arm (INTVAL (operands[1]))
3075 || const_ok_for_arm (~INTVAL (operands[1])))"
3077 mov%?\\t%0, %1\\t%@ movhi
3078 mvn%?\\t%0, #%B1\\t%@ movhi
3079 ldr%?h\\t%0, %1\\t%@ movhi
3080 str%?h\\t%1, %0\\t%@ movhi"
3081 [(set_attr "type" "*,*,load,store1")])
3083 (define_insn "*movhi_insn_littleend"
3084 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3085 (match_operand:HI 1 "general_operand" "rI,K,m"))]
3087 && ! BYTES_BIG_ENDIAN
3088 && ! TARGET_SHORT_BY_BYTES
3089 && (GET_CODE (operands[1]) != CONST_INT
3090 || const_ok_for_arm (INTVAL (operands[1]))
3091 || const_ok_for_arm (~INTVAL (operands[1])))"
3093 mov%?\\t%0, %1\\t%@ movhi
3094 mvn%?\\t%0, #%B1\\t%@ movhi
3095 ldr%?\\t%0, %1\\t%@ movhi"
3096 [(set_attr "type" "*,*,load")])
3098 (define_insn "*movhi_insn_bigend"
3099 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3100 (match_operand:HI 1 "general_operand" "rI,K,m"))]
3103 && ! TARGET_SHORT_BY_BYTES
3104 && (GET_CODE (operands[1]) != CONST_INT
3105 || const_ok_for_arm (INTVAL (operands[1]))
3106 || const_ok_for_arm (~INTVAL (operands[1])))"
3108 mov%?\\t%0, %1\\t%@ movhi
3109 mvn%?\\t%0, #%B1\\t%@ movhi
3110 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
3111 [(set_attr "type" "*,*,load")
3112 (set_attr "length" "4,4,8")])
3114 (define_insn "*loadhi_si_bigend"
3115 [(set (match_operand:SI 0 "s_register_operand" "=r")
3116 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
3119 && ! TARGET_SHORT_BY_BYTES"
3120 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
3121 [(set_attr "type" "load")])
3123 (define_insn "*movhi_bytes"
3124 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
3125 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
3126 "TARGET_SHORT_BY_BYTES"
3128 mov%?\\t%0, %1\\t%@ movhi
3129 mvn%?\\t%0, #%B1\\t%@ movhi")
3132 (define_expand "reload_outhi"
3133 [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
3134 (match_operand:HI 1 "s_register_operand" "r")
3135 (match_operand:SI 2 "s_register_operand" "=&r")])]
3138 arm_reload_out_hi (operands);
3142 (define_expand "reload_inhi"
3143 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
3144 (match_operand:HI 1 "reload_memory_operand" "o")
3145 (match_operand:SI 2 "s_register_operand" "=&r")])]
3146 "TARGET_SHORT_BY_BYTES"
3148 arm_reload_in_hi (operands);
3152 (define_expand "movqi"
3153 [(set (match_operand:QI 0 "general_operand" "")
3154 (match_operand:QI 1 "general_operand" ""))]
3157 /* Everything except mem = const or mem = mem can be done easily */
3159 if (!(reload_in_progress || reload_completed))
3161 if (GET_CODE (operands[1]) == CONST_INT)
3163 rtx reg = gen_reg_rtx (SImode);
3165 emit_insn (gen_movsi (reg, operands[1]));
3166 operands[1] = gen_rtx (SUBREG, QImode, reg, 0);
3168 if (GET_CODE (operands[0]) == MEM)
3169 operands[1] = force_reg (QImode, operands[1]);
3174 (define_insn "*movqi_insn"
3175 [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
3176 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
3177 "register_operand (operands[0], QImode)
3178 || register_operand (operands[1], QImode)"
3184 [(set_attr "type" "*,*,load,store1")])
3186 (define_expand "movsf"
3187 [(set (match_operand:SF 0 "general_operand" "")
3188 (match_operand:SF 1 "general_operand" ""))]
3191 if (GET_CODE (operands[0]) == MEM)
3192 operands[1] = force_reg (SFmode, operands[1]);
3195 (define_insn "*movsf_hard_insn"
3196 [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
3197 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
3199 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3205 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
3206 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
3208 ldr%?\\t%0, %1\\t%@ float
3209 str%?\\t%1, %0\\t%@ float"
3210 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
3212 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
3214 ;; Exactly the same as above, except that all `f' cases are deleted.
3215 ;; This is necessary to prevent reload from ever trying to use a `f' reg
3216 ;; when -msoft-float.
3218 (define_insn "*movsf_soft_insn"
3219 [(set (match_operand:SF 0 "general_operand" "=r,r,m")
3220 (match_operand:SF 1 "general_operand" "r,mE,r"))]
3222 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3225 ldr%?\\t%0, %1\\t%@ float
3226 str%?\\t%1, %0\\t%@ float"
3227 [(set_attr "length" "4,4,4")
3228 (set_attr "type" "*,load,store1")])
3230 (define_expand "movdf"
3231 [(set (match_operand:DF 0 "general_operand" "")
3232 (match_operand:DF 1 "general_operand" ""))]
3235 if (GET_CODE (operands[0]) == MEM)
3236 operands[1] = force_reg (DFmode, operands[1]);
3239 ;; Reloading a df mode value stored in integer regs to memory can require a
3241 (define_expand "reload_outdf"
3242 [(match_operand:DF 0 "reload_memory_operand" "=o")
3243 (match_operand:DF 1 "s_register_operand" "r")
3244 (match_operand:SI 2 "s_register_operand" "=&r")]
3248 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
3251 operands[2] = XEXP (operands[0], 0);
3252 else if (code == POST_INC || code == PRE_DEC)
3254 operands[0] = gen_rtx (SUBREG, DImode, operands[0], 0);
3255 operands[1] = gen_rtx (SUBREG, DImode, operands[1], 0);
3256 emit_insn (gen_movdi (operands[0], operands[1]));
3259 else if (code == PRE_INC)
3261 rtx reg = XEXP (XEXP (operands[0], 0), 0);
3262 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
3265 else if (code == POST_DEC)
3266 operands[2] = XEXP (XEXP (operands[0], 0), 0);
3268 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
3269 XEXP (XEXP (operands[0], 0), 1)));
3271 emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, DFmode, operands[2]),
3274 if (code == POST_DEC)
3275 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
3281 (define_insn "*movdf_hard_insn"
3282 [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
3283 (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
3285 && (GET_CODE (operands[0]) != MEM
3286 || register_operand (operands[1], DFmode))"
3291 switch (which_alternative)
3293 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
3294 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
3295 case 2: case 3: case 4: return output_move_double (operands);
3296 case 5: return \"mvf%?d\\t%0, %1\";
3297 case 6: return \"mnf%?d\\t%0, #%N1\";
3298 case 7: return \"ldf%?d\\t%0, %1\";
3299 case 8: return \"stf%?d\\t%1, %0\";
3300 case 9: return output_mov_double_fpu_from_arm (operands);
3301 case 10: return output_mov_double_arm_from_fpu (operands);
3305 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
3307 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
3309 ;; Software floating point version. This is essentially the same as movdi.
3310 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
3313 (define_insn "*movdf_soft_insn"
3314 [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
3315 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
3317 "* return output_move_double (operands);"
3318 [(set_attr "length" "8,8,8")
3319 (set_attr "type" "*,load,store2")])
3321 (define_expand "movxf"
3322 [(set (match_operand:XF 0 "general_operand" "")
3323 (match_operand:XF 1 "general_operand" ""))]
3324 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3327 ;; Even when the XFmode patterns aren't enabled, we enable this after
3328 ;; reloading so that we can push floating point registers in the prologue.
3330 (define_insn "*movxf_hard_insn"
3331 [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
3332 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
3333 "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
3335 switch (which_alternative)
3337 case 0: return \"mvf%?e\\t%0, %1\";
3338 case 1: return \"mnf%?e\\t%0, #%N1\";
3339 case 2: return \"ldf%?e\\t%0, %1\";
3340 case 3: return \"stf%?e\\t%1, %0\";
3341 case 4: return output_mov_long_double_fpu_from_arm (operands);
3342 case 5: return output_mov_long_double_arm_from_fpu (operands);
3343 case 6: return output_mov_long_double_arm_from_arm (operands);
3346 [(set_attr "length" "4,4,4,4,8,8,12")
3347 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
3350 ;; load- and store-multiple insns
3351 ;; The arm can load/store any set of registers, provided that they are in
3352 ;; ascending order; but that is beyond GCC so stick with what it knows.
3354 (define_expand "load_multiple"
3355 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3356 (match_operand:SI 1 "" ""))
3357 (use (match_operand:SI 2 "" ""))])]
3360 /* Support only fixed point registers */
3361 if (GET_CODE (operands[2]) != CONST_INT
3362 || INTVAL (operands[2]) > 14
3363 || INTVAL (operands[2]) < 2
3364 || GET_CODE (operands[1]) != MEM
3365 || GET_CODE (operands[0]) != REG
3366 || REGNO (operands[0]) > 14
3367 || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
3371 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
3372 force_reg (SImode, XEXP (operands[1], 0)),
3373 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
3374 MEM_IN_STRUCT_P(operands[1]),
3375 MEM_SCALAR_P (operands[1]));
3378 ;; Load multiple with write-back
3380 (define_insn "*ldmsi_postinc"
3381 [(match_parallel 0 "load_multiple_operation"
3382 [(set (match_operand:SI 1 "s_register_operand" "+r")
3383 (plus:SI (match_dup 1)
3384 (match_operand:SI 2 "const_int_operand" "n")))
3385 (set (match_operand:SI 3 "s_register_operand" "=r")
3386 (mem:SI (match_dup 1)))])]
3387 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3391 int count = XVECLEN (operands[0], 0);
3393 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3394 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
3395 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
3397 output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
3401 [(set_attr "type" "load")])
3403 ;; Ordinary load multiple
3405 (define_insn "*ldmsi"
3406 [(match_parallel 0 "load_multiple_operation"
3407 [(set (match_operand:SI 1 "s_register_operand" "=r")
3408 (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
3413 int count = XVECLEN (operands[0], 0);
3415 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3416 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
3417 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
3419 output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
3423 [(set_attr "type" "load")])
3425 (define_expand "store_multiple"
3426 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3427 (match_operand:SI 1 "" ""))
3428 (use (match_operand:SI 2 "" ""))])]
3431 /* Support only fixed point registers */
3432 if (GET_CODE (operands[2]) != CONST_INT
3433 || INTVAL (operands[2]) > 14
3434 || INTVAL (operands[2]) < 2
3435 || GET_CODE (operands[1]) != REG
3436 || GET_CODE (operands[0]) != MEM
3437 || REGNO (operands[1]) > 14
3438 || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
3442 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
3443 force_reg (SImode, XEXP (operands[0], 0)),
3444 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
3445 MEM_IN_STRUCT_P(operands[0]),
3446 MEM_SCALAR_P (operands[0]));
3449 ;; Store multiple with write-back
3451 (define_insn "*stmsi_postinc"
3452 [(match_parallel 0 "store_multiple_operation"
3453 [(set (match_operand:SI 1 "s_register_operand" "+r")
3454 (plus:SI (match_dup 1)
3455 (match_operand:SI 2 "const_int_operand" "n")))
3456 (set (mem:SI (match_dup 1))
3457 (match_operand:SI 3 "s_register_operand" "r"))])]
3458 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3462 int count = XVECLEN (operands[0], 0);
3464 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3465 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
3466 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
3468 output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
3473 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3474 (const_string "store2")
3475 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
3476 (const_string "store3")]
3477 (const_string "store4")))])
3479 ;; Ordinary store multiple
3481 (define_insn "*stmsi"
3482 [(match_parallel 0 "store_multiple_operation"
3483 [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
3484 (match_operand:SI 1 "s_register_operand" "r"))])]
3489 int count = XVECLEN (operands[0], 0);
3491 ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
3492 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
3493 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
3495 output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
3500 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
3501 (const_string "store2")
3502 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3503 (const_string "store3")]
3504 (const_string "store4")))])
3506 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
3507 ;; We could let this apply for blocks of less than this, but it clobbers so
3508 ;; many registers that there is then probably a better way.
3510 (define_expand "movstrqi"
3511 [(match_operand:BLK 0 "general_operand" "")
3512 (match_operand:BLK 1 "general_operand" "")
3513 (match_operand:SI 2 "const_int_operand" "")
3514 (match_operand:SI 3 "const_int_operand" "")]
3517 if (arm_gen_movstrqi (operands))
3523 ;; Comparison and test insns
3525 (define_expand "cmpsi"
3526 [(match_operand:SI 0 "s_register_operand" "")
3527 (match_operand:SI 1 "arm_add_operand" "")]
3531 arm_compare_op0 = operands[0];
3532 arm_compare_op1 = operands[1];
3538 (define_expand "cmpsf"
3539 [(match_operand:SF 0 "s_register_operand" "")
3540 (match_operand:SF 1 "fpu_rhs_operand" "")]
3544 arm_compare_op0 = operands[0];
3545 arm_compare_op1 = operands[1];
3551 (define_expand "cmpdf"
3552 [(match_operand:DF 0 "s_register_operand" "")
3553 (match_operand:DF 1 "fpu_rhs_operand" "")]
3557 arm_compare_op0 = operands[0];
3558 arm_compare_op1 = operands[1];
3564 (define_expand "cmpxf"
3565 [(match_operand:XF 0 "s_register_operand" "")
3566 (match_operand:XF 1 "fpu_rhs_operand" "")]
3567 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3570 arm_compare_op0 = operands[0];
3571 arm_compare_op1 = operands[1];
3577 (define_insn "*cmpsi_insn"
3579 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3580 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3585 [(set_attr "conds" "set")])
3587 (define_insn "*cmpsi_shiftsi"
3589 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3590 (match_operator:SI 3 "shift_operator"
3591 [(match_operand:SI 1 "s_register_operand" "r")
3592 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3595 [(set_attr "conds" "set")])
3597 (define_insn "*cmpsi_shiftsi_swp"
3598 [(set (reg:CC_SWP 24)
3599 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
3600 [(match_operand:SI 1 "s_register_operand" "r")
3601 (match_operand:SI 2 "reg_or_int_operand" "rM")])
3602 (match_operand:SI 0 "s_register_operand" "r")))]
3605 [(set_attr "conds" "set")])
3607 (define_insn "*cmpsi_neg_shiftsi"
3609 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3610 (neg:SI (match_operator:SI 3 "shift_operator"
3611 [(match_operand:SI 1 "s_register_operand" "r")
3612 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3615 [(set_attr "conds" "set")])
3617 (define_insn "*cmpsf_insn"
3619 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3620 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3625 [(set_attr "conds" "set")
3626 (set_attr "type" "f_2_r")])
3628 (define_insn "*cmpdf_insn"
3630 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3631 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3636 [(set_attr "conds" "set")
3637 (set_attr "type" "f_2_r")])
3639 (define_insn "*cmpesfdf_df"
3641 (compare:CCFP (float_extend:DF
3642 (match_operand:SF 0 "s_register_operand" "f,f"))
3643 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3648 [(set_attr "conds" "set")
3649 (set_attr "type" "f_2_r")])
3651 (define_insn "*cmpdf_esfdf"
3653 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3655 (match_operand:SF 1 "s_register_operand" "f"))))]
3658 [(set_attr "conds" "set")
3659 (set_attr "type" "f_2_r")])
3661 (define_insn "*cmpxf_insn"
3663 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3664 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3665 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3669 [(set_attr "conds" "set")
3670 (set_attr "type" "f_2_r")])
3672 (define_insn "*cmpsf_trap"
3673 [(set (reg:CCFPE 24)
3674 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3675 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3680 [(set_attr "conds" "set")
3681 (set_attr "type" "f_2_r")])
3683 (define_insn "*cmpdf_trap"
3684 [(set (reg:CCFPE 24)
3685 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3686 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3691 [(set_attr "conds" "set")
3692 (set_attr "type" "f_2_r")])
3694 (define_insn "*cmp_esfdf_df_trap"
3695 [(set (reg:CCFPE 24)
3696 (compare:CCFPE (float_extend:DF
3697 (match_operand:SF 0 "s_register_operand" "f,f"))
3698 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3703 [(set_attr "conds" "set")
3704 (set_attr "type" "f_2_r")])
3706 (define_insn "*cmp_df_esfdf_trap"
3707 [(set (reg:CCFPE 24)
3708 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3710 (match_operand:SF 1 "s_register_operand" "f"))))]
3713 [(set_attr "conds" "set")
3714 (set_attr "type" "f_2_r")])
3716 (define_insn "*cmpxf_trap"
3717 [(set (reg:CCFPE 24)
3718 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3719 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3720 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3724 [(set_attr "conds" "set")
3725 (set_attr "type" "f_2_r")])
3727 ; This insn allows redundant compares to be removed by cse, nothing should
3728 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3729 ; is deleted later on. The match_dup will match the mode here, so that
3730 ; mode changes of the condition codes aren't lost by this even though we don't
3731 ; specify what they are.
3733 (define_insn "*deleted_compare"
3734 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3736 "\\t%@ deleted compare"
3737 [(set_attr "conds" "set")
3738 (set_attr "length" "0")])
3741 ;; Conditional branch insns
3743 (define_expand "beq"
3745 (if_then_else (eq (match_dup 1) (const_int 0))
3746 (label_ref (match_operand 0 "" ""))
3751 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3756 (define_expand "bne"
3758 (if_then_else (ne (match_dup 1) (const_int 0))
3759 (label_ref (match_operand 0 "" ""))
3764 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3769 (define_expand "bgt"
3771 (if_then_else (gt (match_dup 1) (const_int 0))
3772 (label_ref (match_operand 0 "" ""))
3777 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3782 (define_expand "ble"
3784 (if_then_else (le (match_dup 1) (const_int 0))
3785 (label_ref (match_operand 0 "" ""))
3790 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3795 (define_expand "bge"
3797 (if_then_else (ge (match_dup 1) (const_int 0))
3798 (label_ref (match_operand 0 "" ""))
3803 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3808 (define_expand "blt"
3810 (if_then_else (lt (match_dup 1) (const_int 0))
3811 (label_ref (match_operand 0 "" ""))
3816 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3821 (define_expand "bgtu"
3823 (if_then_else (gtu (match_dup 1) (const_int 0))
3824 (label_ref (match_operand 0 "" ""))
3829 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3834 (define_expand "bleu"
3836 (if_then_else (leu (match_dup 1) (const_int 0))
3837 (label_ref (match_operand 0 "" ""))
3842 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3847 (define_expand "bgeu"
3849 (if_then_else (geu (match_dup 1) (const_int 0))
3850 (label_ref (match_operand 0 "" ""))
3855 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3860 (define_expand "bltu"
3862 (if_then_else (ltu (match_dup 1) (const_int 0))
3863 (label_ref (match_operand 0 "" ""))
3868 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3873 ;; patterns to match conditional branch insns
3875 (define_insn "*condbranch"
3877 (if_then_else (match_operator 1 "comparison_operator"
3878 [(match_operand 2 "cc_register" "") (const_int 0)])
3879 (label_ref (match_operand 0 "" ""))
3884 extern int arm_ccfsm_state;
3886 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3888 arm_ccfsm_state += 2;
3891 return \"b%d1\\t%l0\";
3893 [(set_attr "conds" "use")])
3895 (define_insn "*condbranch_reversed"
3897 (if_then_else (match_operator 1 "comparison_operator"
3898 [(match_operand 2 "cc_register" "") (const_int 0)])
3900 (label_ref (match_operand 0 "" ""))))]
3904 extern int arm_ccfsm_state;
3906 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3908 arm_ccfsm_state += 2;
3911 return \"b%D1\\t%l0\";
3913 [(set_attr "conds" "use")])
3918 (define_expand "seq"
3919 [(set (match_operand:SI 0 "s_register_operand" "=r")
3920 (eq:SI (match_dup 1) (const_int 0)))]
3924 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3929 (define_expand "sne"
3930 [(set (match_operand:SI 0 "s_register_operand" "=r")
3931 (ne:SI (match_dup 1) (const_int 0)))]
3935 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3940 (define_expand "sgt"
3941 [(set (match_operand:SI 0 "s_register_operand" "=r")
3942 (gt:SI (match_dup 1) (const_int 0)))]
3946 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3951 (define_expand "sle"
3952 [(set (match_operand:SI 0 "s_register_operand" "=r")
3953 (le:SI (match_dup 1) (const_int 0)))]
3957 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3962 (define_expand "sge"
3963 [(set (match_operand:SI 0 "s_register_operand" "=r")
3964 (ge:SI (match_dup 1) (const_int 0)))]
3968 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3973 (define_expand "slt"
3974 [(set (match_operand:SI 0 "s_register_operand" "=r")
3975 (lt:SI (match_dup 1) (const_int 0)))]
3979 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3984 (define_expand "sgtu"
3985 [(set (match_operand:SI 0 "s_register_operand" "=r")
3986 (gtu:SI (match_dup 1) (const_int 0)))]
3990 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3995 (define_expand "sleu"
3996 [(set (match_operand:SI 0 "s_register_operand" "=r")
3997 (leu:SI (match_dup 1) (const_int 0)))]
4001 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
4006 (define_expand "sgeu"
4007 [(set (match_operand:SI 0 "s_register_operand" "=r")
4008 (geu:SI (match_dup 1) (const_int 0)))]
4012 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
4017 (define_expand "sltu"
4018 [(set (match_operand:SI 0 "s_register_operand" "=r")
4019 (ltu:SI (match_dup 1) (const_int 0)))]
4023 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
4028 (define_insn "*mov_scc"
4029 [(set (match_operand:SI 0 "s_register_operand" "=r")
4030 (match_operator:SI 1 "comparison_operator"
4031 [(match_operand 2 "cc_register" "") (const_int 0)]))]
4033 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
4034 [(set_attr "conds" "use")
4035 (set_attr "length" "8")])
4037 (define_insn "*mov_negscc"
4038 [(set (match_operand:SI 0 "s_register_operand" "=r")
4039 (neg:SI (match_operator:SI 1 "comparison_operator"
4040 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4042 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
4043 [(set_attr "conds" "use")
4044 (set_attr "length" "8")])
4046 (define_insn "*mov_notscc"
4047 [(set (match_operand:SI 0 "s_register_operand" "=r")
4048 (not:SI (match_operator:SI 1 "comparison_operator"
4049 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4051 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
4052 [(set_attr "conds" "use")
4053 (set_attr "length" "8")])
4056 ;; Conditional move insns
4058 (define_expand "movsicc"
4059 [(set (match_operand:SI 0 "s_register_operand" "")
4060 (if_then_else:SI (match_operand 1 "comparison_operator" "")
4061 (match_operand:SI 2 "arm_not_operand" "")
4062 (match_operand:SI 3 "arm_not_operand" "")))]
4066 enum rtx_code code = GET_CODE (operands[1]);
4067 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4070 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4073 (define_expand "movsfcc"
4074 [(set (match_operand:SF 0 "s_register_operand" "")
4075 (if_then_else:SF (match_operand 1 "comparison_operator" "")
4076 (match_operand:SF 2 "s_register_operand" "")
4077 (match_operand:SF 3 "nonmemory_operand" "")))]
4081 enum rtx_code code = GET_CODE (operands[1]);
4084 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
4085 Otherwise, ensure it is a valid FP add operand */
4086 if ((! TARGET_HARD_FLOAT)
4087 || (! fpu_add_operand (operands[3], SFmode)))
4088 operands[3] = force_reg (SFmode, operands[3]);
4090 ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4093 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4096 (define_expand "movdfcc"
4097 [(set (match_operand:DF 0 "s_register_operand" "")
4098 (if_then_else:DF (match_operand 1 "comparison_operator" "")
4099 (match_operand:DF 2 "s_register_operand" "")
4100 (match_operand:DF 3 "fpu_add_operand" "")))]
4104 enum rtx_code code = GET_CODE (operands[1]);
4105 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4108 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4111 (define_insn "*movsicc_insn"
4112 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
4114 (match_operator 3 "comparison_operator"
4115 [(match_operand 4 "cc_register" "") (const_int 0)])
4116 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
4117 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
4124 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
4125 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
4126 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
4127 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
4128 [(set_attr "length" "4,4,4,4,8,8,8,8")
4129 (set_attr "conds" "use")])
4131 (define_insn "*movsfcc_hard_insn"
4132 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4134 (match_operator 3 "comparison_operator"
4135 [(match_operand 4 "cc_register" "") (const_int 0)])
4136 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4137 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4144 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
4145 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
4146 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
4147 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
4148 [(set_attr "length" "4,4,4,4,8,8,8,8")
4149 (set_attr "type" "ffarith")
4150 (set_attr "conds" "use")])
4152 (define_insn "*movsfcc_soft_insn"
4153 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
4154 (if_then_else:SF (match_operator 3 "comparison_operator"
4155 [(match_operand 4 "cc_register" "") (const_int 0)])
4156 (match_operand:SF 1 "s_register_operand" "0,r")
4157 (match_operand:SF 2 "s_register_operand" "r,0")))]
4162 [(set_attr "conds" "use")])
4164 (define_insn "*movdfcc_insn"
4165 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4167 (match_operator 3 "comparison_operator"
4168 [(match_operand 4 "cc_register" "") (const_int 0)])
4169 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4170 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4177 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
4178 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
4179 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
4180 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
4181 [(set_attr "length" "4,4,4,4,8,8,8,8")
4182 (set_attr "type" "ffarith")
4183 (set_attr "conds" "use")])
4185 ;; Jump and linkage insns
4189 (label_ref (match_operand 0 "" "")))]
4193 extern int arm_ccfsm_state;
4195 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4197 arm_ccfsm_state += 2;
4200 return \"b%?\\t%l0\";
4203 (define_expand "call"
4204 [(parallel [(call (match_operand 0 "memory_operand" "")
4205 (match_operand 1 "general_operand" ""))
4206 (clobber (reg:SI 14))])]
4210 (define_insn "*call_reg"
4211 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
4212 (match_operand 1 "" "g"))
4213 (clobber (reg:SI 14))]
4216 return output_call (operands);
4218 ;; length is worst case, normally it is only two
4219 [(set_attr "length" "12")
4220 (set_attr "type" "call")])
4222 (define_insn "*call_mem"
4223 [(call (mem:SI (match_operand 0 "memory_operand" "m"))
4224 (match_operand 1 "general_operand" "g"))
4225 (clobber (reg:SI 14))]
4228 return output_call_mem (operands);
4230 [(set_attr "length" "12")
4231 (set_attr "type" "call")])
4233 (define_expand "call_value"
4234 [(parallel [(set (match_operand 0 "" "=rf")
4235 (call (match_operand 1 "memory_operand" "m")
4236 (match_operand 2 "general_operand" "g")))
4237 (clobber (reg:SI 14))])]
4241 (define_insn "*call_value_reg"
4242 [(set (match_operand 0 "" "=rf")
4243 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4244 (match_operand 2 "general_operand" "g")))
4245 (clobber (reg:SI 14))]
4248 return output_call (&operands[1]);
4250 [(set_attr "length" "12")
4251 (set_attr "type" "call")])
4253 (define_insn "*call_value_mem"
4254 [(set (match_operand 0 "" "=rf")
4255 (call (mem:SI (match_operand 1 "memory_operand" "m"))
4256 (match_operand 2 "general_operand" "g")))
4257 (clobber (reg:SI 14))]
4258 "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
4260 return output_call_mem (&operands[1]);
4262 [(set_attr "length" "12")
4263 (set_attr "type" "call")])
4265 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
4266 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
4268 (define_insn "*call_symbol"
4269 [(call (mem:SI (match_operand:SI 0 "" "X"))
4270 (match_operand:SI 1 "general_operand" "g"))
4271 (clobber (reg:SI 14))]
4272 "GET_CODE (operands[0]) == SYMBOL_REF"
4274 [(set_attr "type" "call")])
4276 (define_insn "*call_value_symbol"
4277 [(set (match_operand 0 "s_register_operand" "=rf")
4278 (call (mem:SI (match_operand:SI 1 "" "X"))
4279 (match_operand:SI 2 "general_operand" "g")))
4280 (clobber (reg:SI 14))]
4281 "GET_CODE(operands[1]) == SYMBOL_REF"
4283 [(set_attr "type" "call")])
4285 ;; Often the return insn will be the same as loading from memory, so set attr
4286 (define_insn "return"
4288 "USE_RETURN_INSN(FALSE)"
4291 extern int arm_ccfsm_state;
4293 if (arm_ccfsm_state == 2)
4295 arm_ccfsm_state += 2;
4298 return output_return_instruction (NULL, TRUE, FALSE);
4300 [(set_attr "type" "load")])
4302 (define_insn "*cond_return"
4304 (if_then_else (match_operator 0 "comparison_operator"
4305 [(match_operand 1 "cc_register" "") (const_int 0)])
4308 "USE_RETURN_INSN(TRUE)"
4311 extern int arm_ccfsm_state;
4313 if (arm_ccfsm_state == 2)
4315 arm_ccfsm_state += 2;
4318 return output_return_instruction (operands[0], TRUE, FALSE);
4320 [(set_attr "conds" "use")
4321 (set_attr "type" "load")])
4323 (define_insn "*cond_return_inverted"
4325 (if_then_else (match_operator 0 "comparison_operator"
4326 [(match_operand 1 "cc_register" "") (const_int 0)])
4329 "USE_RETURN_INSN(TRUE)"
4332 extern int arm_ccfsm_state;
4334 if (arm_ccfsm_state == 2)
4336 arm_ccfsm_state += 2;
4339 return output_return_instruction (operands[0], TRUE, TRUE);
4341 [(set_attr "conds" "use")
4342 (set_attr "type" "load")])
4344 ;; Call subroutine returning any type.
4346 (define_expand "untyped_call"
4347 [(parallel [(call (match_operand 0 "" "")
4349 (match_operand 1 "" "")
4350 (match_operand 2 "" "")])]
4356 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
4358 for (i = 0; i < XVECLEN (operands[2], 0); i++)
4360 rtx set = XVECEXP (operands[2], 0, i);
4361 emit_move_insn (SET_DEST (set), SET_SRC (set));
4364 /* The optimizer does not know that the call sets the function value
4365 registers we stored in the result block. We avoid problems by
4366 claiming that all hard registers are used and clobbered at this
4368 emit_insn (gen_blockage ());
4373 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
4374 ;; all of memory. This blocks insns from being moved across this point.
4376 (define_insn "blockage"
4377 [(unspec_volatile [(const_int 0)] 0)]
4380 [(set_attr "length" "0")
4381 (set_attr "type" "block")])
4383 (define_expand "casesi"
4384 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
4385 (match_operand:SI 1 "const_int_operand" "") ; lower bound
4386 (match_operand:SI 2 "const_int_operand" "") ; total range
4387 (match_operand:SI 3 "" "") ; table label
4388 (match_operand:SI 4 "" "")] ; Out of range label
4393 if (operands[1] != const0_rtx)
4395 reg = gen_reg_rtx (SImode);
4396 emit_insn (gen_addsi3 (reg, operands[0],
4397 GEN_INT (-INTVAL (operands[1]))));
4401 if (! const_ok_for_arm (INTVAL (operands[2])))
4402 operands[2] = force_reg (SImode, operands[2]);
4404 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
4409 ;; The USE in this pattern is needed to tell flow analysis that this is
4410 ;; a CASESI insn. It has no other purpose.
4411 (define_insn "casesi_internal"
4412 [(parallel [(set (pc)
4414 (leu (match_operand:SI 0 "s_register_operand" "r")
4415 (match_operand:SI 1 "arm_rhs_operand" "rI"))
4416 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
4417 (label_ref (match_operand 2 "" ""))))
4418 (label_ref (match_operand 3 "" ""))))
4419 (use (label_ref (match_dup 2)))])]
4423 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
4424 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
4426 [(set_attr "conds" "clob")
4427 (set_attr "length" "12")])
4429 (define_insn "indirect_jump"
4431 (match_operand:SI 0 "s_register_operand" "r"))]
4433 "mov%?\\t%|pc, %0\\t%@ indirect jump")
4435 (define_insn "*load_indirect_jump"
4437 (match_operand:SI 0 "memory_operand" "m"))]
4439 "ldr%?\\t%|pc, %0\\t%@ indirect jump"
4440 [(set_attr "type" "load")])
4447 "mov%?\\tr0, r0\\t%@ nop")
4449 ;; Patterns to allow combination of arithmetic, cond code and shifts
4451 (define_insn "*arith_shiftsi"
4452 [(set (match_operand:SI 0 "s_register_operand" "=r")
4453 (match_operator:SI 1 "shiftable_operator"
4454 [(match_operator:SI 3 "shift_operator"
4455 [(match_operand:SI 4 "s_register_operand" "r")
4456 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4457 (match_operand:SI 2 "s_register_operand" "r")]))]
4459 "%i1%?\\t%0, %2, %4%S3")
4461 (define_insn "*arith_shiftsi_compare0"
4462 [(set (reg:CC_NOOV 24)
4463 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4464 [(match_operator:SI 3 "shift_operator"
4465 [(match_operand:SI 4 "s_register_operand" "r")
4466 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4467 (match_operand:SI 2 "s_register_operand" "r")])
4469 (set (match_operand:SI 0 "s_register_operand" "=r")
4470 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4473 "%i1%?s\\t%0, %2, %4%S3"
4474 [(set_attr "conds" "set")])
4476 (define_insn "*arith_shiftsi_compare0_scratch"
4477 [(set (reg:CC_NOOV 24)
4478 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4479 [(match_operator:SI 3 "shift_operator"
4480 [(match_operand:SI 4 "s_register_operand" "r")
4481 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4482 (match_operand:SI 2 "s_register_operand" "r")])
4484 (clobber (match_scratch:SI 0 "=r"))]
4486 "%i1%?s\\t%0, %2, %4%S3"
4487 [(set_attr "conds" "set")])
4489 (define_insn "*sub_shiftsi"
4490 [(set (match_operand:SI 0 "s_register_operand" "=r")
4491 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4492 (match_operator:SI 2 "shift_operator"
4493 [(match_operand:SI 3 "s_register_operand" "r")
4494 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4496 "sub%?\\t%0, %1, %3%S2")
4498 (define_insn "*sub_shiftsi_compare0"
4499 [(set (reg:CC_NOOV 24)
4501 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4502 (match_operator:SI 2 "shift_operator"
4503 [(match_operand:SI 3 "s_register_operand" "r")
4504 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4506 (set (match_operand:SI 0 "s_register_operand" "=r")
4507 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4510 "sub%?s\\t%0, %1, %3%S2"
4511 [(set_attr "conds" "set")])
4513 (define_insn "*sub_shiftsi_compare0_scratch"
4514 [(set (reg:CC_NOOV 24)
4516 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4517 (match_operator:SI 2 "shift_operator"
4518 [(match_operand:SI 3 "s_register_operand" "r")
4519 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4521 (clobber (match_scratch:SI 0 "=r"))]
4523 "sub%?s\\t%0, %1, %3%S2"
4524 [(set_attr "conds" "set")])
4526 ;; These variants of the above insns can occur if the first operand is the
4527 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
4528 ;; seem to be a way around it. Most of the predicates have to be null
4529 ;; because the format can be generated part way through reload, so
4530 ;; if we don't match it as soon as it becomes available, reload doesn't know
4531 ;; how to reload pseudos that haven't got hard registers; the constraints will
4532 ;; sort everything out.
4534 (define_insn "*reload_mulsi3"
4535 [(set (match_operand:SI 0 "" "=&r")
4536 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4537 [(match_operand:SI 3 "" "r")
4538 (match_operand:SI 4 "" "rM")])
4539 (match_operand:SI 2 "" "r"))
4540 (match_operand:SI 1 "const_int_operand" "n")))]
4541 "reload_in_progress"
4543 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4544 operands[2] = operands[1];
4545 operands[1] = operands[0];
4546 return output_add_immediate (operands);
4548 ; we have no idea how long the add_immediate is, it could be up to 4.
4549 [(set_attr "length" "20")])
4551 (define_insn "*reload_mulsi_compare0"
4552 [(set (reg:CC_NOOV 24)
4553 (compare:CC_NOOV (plus:SI
4555 (match_operator:SI 5 "shift_operator"
4556 [(match_operand:SI 3 "" "r")
4557 (match_operand:SI 4 "" "rM")])
4558 (match_operand:SI 1 "" "r"))
4559 (match_operand:SI 2 "const_int_operand" "n"))
4561 (set (match_operand:SI 0 "" "=&r")
4562 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4565 "reload_in_progress"
4567 output_add_immediate (operands);
4568 return \"add%?s\\t%0, %0, %3%S5\";
4570 [(set_attr "conds" "set")
4571 (set_attr "length" "20")])
4573 (define_insn "*reload_mulsi_compare0_scratch"
4574 [(set (reg:CC_NOOV 24)
4575 (compare:CC_NOOV (plus:SI
4577 (match_operator:SI 5 "shift_operator"
4578 [(match_operand:SI 3 "" "r")
4579 (match_operand:SI 4 "" "rM")])
4580 (match_operand:SI 1 "" "r"))
4581 (match_operand:SI 2 "const_int_operand" "n"))
4583 (clobber (match_scratch:SI 0 "=&r"))]
4584 "reload_in_progress"
4586 output_add_immediate (operands);
4587 return \"add%?s\\t%0, %0, %3%S5\";
4589 [(set_attr "conds" "set")
4590 (set_attr "length" "20")])
4592 ;; These are similar, but are needed when the mla pattern contains the
4593 ;; eliminated register as operand 3.
4595 (define_insn "*reload_muladdsi"
4596 [(set (match_operand:SI 0 "" "=&r,&r")
4597 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4598 (match_operand:SI 2 "" "r,r"))
4599 (match_operand:SI 3 "" "r,r"))
4600 (match_operand:SI 4 "const_int_operand" "n,n")))]
4601 "reload_in_progress"
4603 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4604 operands[2] = operands[4];
4605 operands[1] = operands[0];
4606 return output_add_immediate (operands);
4608 [(set_attr "length" "20")
4609 (set_attr "type" "mult")])
4611 (define_insn "*reload_muladdsi_compare0"
4612 [(set (reg:CC_NOOV 24)
4613 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4614 (match_operand:SI 3 "" "r")
4615 (match_operand:SI 4 "" "r"))
4616 (match_operand:SI 1 "" "r"))
4617 (match_operand:SI 2 "const_int_operand" "n"))
4619 (set (match_operand:SI 0 "" "=&r")
4620 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4622 "reload_in_progress"
4624 output_add_immediate (operands);
4625 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4628 [(set_attr "length" "20")
4629 (set_attr "conds" "set")
4630 (set_attr "type" "mult")])
4632 (define_insn "*reload_muladdsi_compare0_scratch"
4633 [(set (reg:CC_NOOV 24)
4634 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4635 (match_operand:SI 3 "" "r")
4636 (match_operand:SI 4 "" "r"))
4637 (match_operand:SI 1 "" "r"))
4638 (match_operand:SI 2 "const_int_operand" "n"))
4640 (clobber (match_scratch:SI 0 "=&r"))]
4641 "reload_in_progress"
4643 output_add_immediate (operands);
4644 return \"mla%?s\\t%0, %3, %4, %0\";
4646 [(set_attr "length" "20")
4647 (set_attr "conds" "set")
4648 (set_attr "type" "mult")])
4652 (define_insn "*and_scc"
4653 [(set (match_operand:SI 0 "s_register_operand" "=r")
4654 (and:SI (match_operator 1 "comparison_operator"
4655 [(match_operand 3 "cc_register" "") (const_int 0)])
4656 (match_operand:SI 2 "s_register_operand" "r")))]
4658 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
4659 [(set_attr "conds" "use")
4660 (set_attr "length" "8")])
4662 (define_insn "*ior_scc"
4663 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4664 (ior:SI (match_operator 2 "comparison_operator"
4665 [(match_operand 3 "cc_register" "") (const_int 0)])
4666 (match_operand:SI 1 "s_register_operand" "0,?r")))]
4670 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
4671 [(set_attr "conds" "use")
4672 (set_attr "length" "4,8")])
4674 (define_insn "*compare_scc"
4675 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4676 (match_operator 1 "comparison_operator"
4677 [(match_operand:SI 2 "s_register_operand" "r,r")
4678 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
4679 (clobber (reg:CC 24))]
4682 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4683 return \"mov\\t%0, %2, lsr #31\";
4685 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4686 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4688 if (GET_CODE (operands[1]) == NE)
4690 if (which_alternative == 1)
4691 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4692 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4694 if (which_alternative == 1)
4695 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4697 output_asm_insn (\"cmp\\t%2, %3\", operands);
4698 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4700 [(set_attr "conds" "clob")
4701 (set_attr "length" "12")])
4703 (define_insn "*cond_move"
4704 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4705 (if_then_else:SI (match_operator 3 "equality_operator"
4706 [(match_operator 4 "comparison_operator"
4707 [(match_operand 5 "cc_register" "") (const_int 0)])
4709 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4710 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4713 if (GET_CODE (operands[3]) == NE)
4715 if (which_alternative != 1)
4716 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4717 if (which_alternative != 0)
4718 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4721 if (which_alternative != 0)
4722 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4723 if (which_alternative != 1)
4724 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4727 [(set_attr "conds" "use")
4728 (set_attr "length" "4,4,8")])
4730 (define_insn "*cond_arith"
4731 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4732 (match_operator:SI 5 "shiftable_operator"
4733 [(match_operator:SI 4 "comparison_operator"
4734 [(match_operand:SI 2 "s_register_operand" "r,r")
4735 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4736 (match_operand:SI 1 "s_register_operand" "0,?r")]))
4737 (clobber (reg:CC 24))]
4740 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4741 return \"%i5\\t%0, %1, %2, lsr #31\";
4743 output_asm_insn (\"cmp\\t%2, %3\", operands);
4744 if (GET_CODE (operands[5]) == AND)
4745 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4746 else if (GET_CODE (operands[5]) == MINUS)
4747 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4748 else if (which_alternative != 0)
4749 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4750 return \"%i5%d4\\t%0, %1, #1\";
4752 [(set_attr "conds" "clob")
4753 (set_attr "length" "12")])
4755 (define_insn "*cond_sub"
4756 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4757 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4758 (match_operator:SI 4 "comparison_operator"
4759 [(match_operand:SI 2 "s_register_operand" "r,r")
4760 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4761 (clobber (reg:CC 24))]
4764 output_asm_insn (\"cmp\\t%2, %3\", operands);
4765 if (which_alternative != 0)
4766 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4767 return \"sub%d4\\t%0, %1, #1\";
4769 [(set_attr "conds" "clob")
4770 (set_attr "length" "8,12")])
4772 (define_insn "*cmp_ite0"
4773 [(set (match_operand 6 "dominant_cc_register" "")
4776 (match_operator 4 "comparison_operator"
4777 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4778 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4779 (match_operator:SI 5 "comparison_operator"
4780 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4781 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4787 char* opcodes[4][2] =
4789 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
4790 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
4791 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
4792 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
4793 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
4796 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
4798 return opcodes[which_alternative][swap];
4801 [(set_attr "conds" "set")
4802 (set_attr "length" "8")])
4804 (define_insn "*cmp_ite1"
4805 [(set (match_operand 6 "dominant_cc_register" "")
4808 (match_operator 4 "comparison_operator"
4809 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4810 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4811 (match_operator:SI 5 "comparison_operator"
4812 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4813 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4819 char* opcodes[4][2] =
4821 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
4822 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
4823 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
4824 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
4825 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
4828 comparison_dominates_p (GET_CODE (operands[5]),
4829 reverse_condition (GET_CODE (operands[4])));
4831 return opcodes[which_alternative][swap];
4834 [(set_attr "conds" "set")
4835 (set_attr "length" "8")])
4837 (define_insn "*negscc"
4838 [(set (match_operand:SI 0 "s_register_operand" "=r")
4839 (neg:SI (match_operator 3 "comparison_operator"
4840 [(match_operand:SI 1 "s_register_operand" "r")
4841 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4842 (clobber (reg:CC 24))]
4845 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4846 return \"mov\\t%0, %1, asr #31\";
4848 if (GET_CODE (operands[3]) == NE)
4849 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4851 if (GET_CODE (operands[3]) == GT)
4852 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4854 output_asm_insn (\"cmp\\t%1, %2\", operands);
4855 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4856 return \"mvn%d3\\t%0, #0\";
4858 [(set_attr "conds" "clob")
4859 (set_attr "length" "12")])
4861 (define_insn "movcond"
4862 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4864 (match_operator 5 "comparison_operator"
4865 [(match_operand:SI 3 "s_register_operand" "r,r,r")
4866 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4867 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4868 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4869 (clobber (reg:CC 24))]
4872 if (GET_CODE (operands[5]) == LT
4873 && (operands[4] == const0_rtx))
4875 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4877 if (operands[2] == const0_rtx)
4878 return \"and\\t%0, %1, %3, asr #31\";
4879 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4881 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4883 if (operands[1] == const0_rtx)
4884 return \"bic\\t%0, %2, %3, asr #31\";
4885 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4887 /* The only case that falls through to here is when both ops 1 & 2
4891 if (GET_CODE (operands[5]) == GE
4892 && (operands[4] == const0_rtx))
4894 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4896 if (operands[2] == const0_rtx)
4897 return \"bic\\t%0, %1, %3, asr #31\";
4898 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4900 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4902 if (operands[1] == const0_rtx)
4903 return \"and\\t%0, %2, %3, asr #31\";
4904 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4906 /* The only case that falls through to here is when both ops 1 & 2
4909 if (GET_CODE (operands[4]) == CONST_INT
4910 && !const_ok_for_arm (INTVAL (operands[4])))
4911 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4913 output_asm_insn (\"cmp\\t%3, %4\", operands);
4914 if (which_alternative != 0)
4915 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4916 if (which_alternative != 1)
4917 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4920 [(set_attr "conds" "clob")
4921 (set_attr "length" "8,8,12")])
4923 (define_insn "*ifcompare_plus_move"
4924 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4925 (if_then_else:SI (match_operator 6 "comparison_operator"
4926 [(match_operand:SI 4 "s_register_operand" "r,r")
4927 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4929 (match_operand:SI 2 "s_register_operand" "r,r")
4930 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
4931 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
4932 (clobber (reg:CC 24))]
4935 [(set_attr "conds" "clob")
4936 (set_attr "length" "8,12")])
4938 (define_insn "*if_plus_move"
4939 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4941 (match_operator 4 "comparison_operator"
4942 [(match_operand 5 "cc_register" "") (const_int 0)])
4944 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
4945 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
4946 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
4950 sub%d4\\t%0, %2, #%n3
4951 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4952 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
4953 [(set_attr "conds" "use")
4954 (set_attr "length" "4,4,8,8")
4955 (set_attr "type" "*,*,*,*")])
4957 (define_insn "*ifcompare_move_plus"
4958 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4959 (if_then_else:SI (match_operator 6 "comparison_operator"
4960 [(match_operand:SI 4 "s_register_operand" "r,r")
4961 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4962 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4964 (match_operand:SI 2 "s_register_operand" "r,r")
4965 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4966 (clobber (reg:CC 24))]
4969 [(set_attr "conds" "clob")
4970 (set_attr "length" "8,12")])
4972 (define_insn "*if_move_plus"
4973 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4975 (match_operator 4 "comparison_operator"
4976 [(match_operand 5 "cc_register" "") (const_int 0)])
4977 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4979 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
4980 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
4984 sub%D4\\t%0, %2, #%n3
4985 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4986 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
4987 [(set_attr "conds" "use")
4988 (set_attr "length" "4,4,8,8")
4989 (set_attr "type" "*,*,*,*")])
4991 (define_insn "*ifcompare_arith_arith"
4992 [(set (match_operand:SI 0 "s_register_operand" "=r")
4993 (if_then_else:SI (match_operator 9 "comparison_operator"
4994 [(match_operand:SI 5 "s_register_operand" "r")
4995 (match_operand:SI 6 "arm_add_operand" "rIL")])
4996 (match_operator:SI 8 "shiftable_operator"
4997 [(match_operand:SI 1 "s_register_operand" "r")
4998 (match_operand:SI 2 "arm_rhs_operand" "rI")])
4999 (match_operator:SI 7 "shiftable_operator"
5000 [(match_operand:SI 3 "s_register_operand" "r")
5001 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
5002 (clobber (reg:CC 24))]
5005 [(set_attr "conds" "clob")
5006 (set_attr "length" "12")])
5008 (define_insn "*if_arith_arith"
5009 [(set (match_operand:SI 0 "s_register_operand" "=r")
5010 (if_then_else:SI (match_operator 5 "comparison_operator"
5011 [(match_operand 8 "cc_register" "") (const_int 0)])
5012 (match_operator:SI 6 "shiftable_operator"
5013 [(match_operand:SI 1 "s_register_operand" "r")
5014 (match_operand:SI 2 "arm_rhs_operand" "rI")])
5015 (match_operator:SI 7 "shiftable_operator"
5016 [(match_operand:SI 3 "s_register_operand" "r")
5017 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
5019 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
5020 [(set_attr "conds" "use")
5021 (set_attr "length" "8")])
5023 (define_insn "*ifcompare_arith_move"
5024 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5025 (if_then_else:SI (match_operator 6 "comparison_operator"
5026 [(match_operand:SI 2 "s_register_operand" "r,r")
5027 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
5028 (match_operator:SI 7 "shiftable_operator"
5029 [(match_operand:SI 4 "s_register_operand" "r,r")
5030 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
5031 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5032 (clobber (reg:CC 24))]
5035 /* If we have an operation where (op x 0) is the identity operation and
5036 the conditional operator is LT or GE and we are comparing against zero and
5037 everything is in registers then we can do this in two instructions */
5038 if (operands[3] == const0_rtx
5039 && GET_CODE (operands[7]) != AND
5040 && GET_CODE (operands[5]) == REG
5041 && GET_CODE (operands[1]) == REG
5042 && REGNO (operands[1]) == REGNO (operands[4])
5043 && REGNO (operands[4]) != REGNO (operands[0]))
5045 if (GET_CODE (operands[6]) == LT)
5046 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5047 else if (GET_CODE (operands[6]) == GE)
5048 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5050 if (GET_CODE (operands[3]) == CONST_INT
5051 && !const_ok_for_arm (INTVAL (operands[3])))
5052 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
5054 output_asm_insn (\"cmp\\t%2, %3\", operands);
5055 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
5056 if (which_alternative != 0)
5057 return \"mov%D6\\t%0, %1\";
5060 [(set_attr "conds" "clob")
5061 (set_attr "length" "8,12")])
5063 (define_insn "*if_arith_move"
5064 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5065 (if_then_else:SI (match_operator 4 "comparison_operator"
5066 [(match_operand 6 "cc_register" "") (const_int 0)])
5067 (match_operator:SI 5 "shiftable_operator"
5068 [(match_operand:SI 2 "s_register_operand" "r,r")
5069 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
5070 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
5074 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
5075 [(set_attr "conds" "use")
5076 (set_attr "length" "4,8")
5077 (set_attr "type" "*,*")])
5079 (define_insn "*ifcompare_move_arith"
5080 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5081 (if_then_else:SI (match_operator 6 "comparison_operator"
5082 [(match_operand:SI 4 "s_register_operand" "r,r")
5083 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5084 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5085 (match_operator:SI 7 "shiftable_operator"
5086 [(match_operand:SI 2 "s_register_operand" "r,r")
5087 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
5088 (clobber (reg:CC 24))]
5091 /* If we have an operation where (op x 0) is the identity operation and
5092 the conditional operator is LT or GE and we are comparing against zero and
5093 everything is in registers then we can do this in two instructions */
5094 if (operands[5] == const0_rtx
5095 && GET_CODE (operands[7]) != AND
5096 && GET_CODE (operands[3]) == REG
5097 && GET_CODE (operands[1]) == REG
5098 && REGNO (operands[1]) == REGNO (operands[2])
5099 && REGNO (operands[2]) != REGNO (operands[0]))
5101 if (GET_CODE (operands[6]) == GE)
5102 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5103 else if (GET_CODE (operands[6]) == LT)
5104 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5107 if (GET_CODE (operands[5]) == CONST_INT
5108 && !const_ok_for_arm (INTVAL (operands[5])))
5109 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5111 output_asm_insn (\"cmp\\t%4, %5\", operands);
5113 if (which_alternative != 0)
5114 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
5115 return \"%I7%D6\\t%0, %2, %3\";
5117 [(set_attr "conds" "clob")
5118 (set_attr "length" "8,12")])
5120 (define_insn "*if_move_arith"
5121 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5123 (match_operator 4 "comparison_operator"
5124 [(match_operand 6 "cc_register" "") (const_int 0)])
5125 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5126 (match_operator:SI 5 "shiftable_operator"
5127 [(match_operand:SI 2 "s_register_operand" "r,r")
5128 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
5132 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
5133 [(set_attr "conds" "use")
5134 (set_attr "length" "4,8")
5135 (set_attr "type" "*,*")])
5137 (define_insn "*ifcompare_move_not"
5138 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5140 (match_operator 5 "comparison_operator"
5141 [(match_operand:SI 3 "s_register_operand" "r,r")
5142 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5143 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5145 (match_operand:SI 2 "s_register_operand" "r,r"))))
5146 (clobber (reg:CC 24))]
5149 [(set_attr "conds" "clob")
5150 (set_attr "length" "8,12")])
5152 (define_insn "*if_move_not"
5153 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5155 (match_operator 4 "comparison_operator"
5156 [(match_operand 3 "cc_register" "") (const_int 0)])
5157 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5158 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5162 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
5163 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
5164 [(set_attr "conds" "use")
5165 (set_attr "length" "4,8,8")])
5167 (define_insn "*ifcompare_not_move"
5168 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5170 (match_operator 5 "comparison_operator"
5171 [(match_operand:SI 3 "s_register_operand" "r,r")
5172 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5174 (match_operand:SI 2 "s_register_operand" "r,r"))
5175 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5176 (clobber (reg:CC 24))]
5179 [(set_attr "conds" "clob")
5180 (set_attr "length" "8,12")])
5182 (define_insn "*if_not_move"
5183 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5185 (match_operator 4 "comparison_operator"
5186 [(match_operand 3 "cc_register" "") (const_int 0)])
5187 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5188 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5192 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
5193 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
5194 [(set_attr "conds" "use")
5195 (set_attr "length" "4,8,8")])
5197 (define_insn "*ifcompare_shift_move"
5198 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5200 (match_operator 6 "comparison_operator"
5201 [(match_operand:SI 4 "s_register_operand" "r,r")
5202 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5203 (match_operator:SI 7 "shift_operator"
5204 [(match_operand:SI 2 "s_register_operand" "r,r")
5205 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
5206 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5207 (clobber (reg:CC 24))]
5210 [(set_attr "conds" "clob")
5211 (set_attr "length" "8,12")])
5213 (define_insn "*if_shift_move"
5214 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5216 (match_operator 5 "comparison_operator"
5217 [(match_operand 6 "cc_register" "") (const_int 0)])
5218 (match_operator:SI 4 "shift_operator"
5219 [(match_operand:SI 2 "s_register_operand" "r,r,r")
5220 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
5221 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5225 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
5226 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
5227 [(set_attr "conds" "use")
5228 (set_attr "length" "4,8,8")])
5230 (define_insn "*ifcompare_move_shift"
5231 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5233 (match_operator 6 "comparison_operator"
5234 [(match_operand:SI 4 "s_register_operand" "r,r")
5235 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5236 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5237 (match_operator:SI 7 "shift_operator"
5238 [(match_operand:SI 2 "s_register_operand" "r,r")
5239 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
5240 (clobber (reg:CC 24))]
5243 [(set_attr "conds" "clob")
5244 (set_attr "length" "8,12")])
5246 (define_insn "*if_move_shift"
5247 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5249 (match_operator 5 "comparison_operator"
5250 [(match_operand 6 "cc_register" "") (const_int 0)])
5251 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5252 (match_operator:SI 4 "shift_operator"
5253 [(match_operand:SI 2 "s_register_operand" "r,r,r")
5254 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
5258 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
5259 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
5260 [(set_attr "conds" "use")
5261 (set_attr "length" "4,8,8")])
5263 (define_insn "*ifcompare_shift_shift"
5264 [(set (match_operand:SI 0 "s_register_operand" "=r")
5266 (match_operator 7 "comparison_operator"
5267 [(match_operand:SI 5 "s_register_operand" "r")
5268 (match_operand:SI 6 "arm_add_operand" "rIL")])
5269 (match_operator:SI 8 "shift_operator"
5270 [(match_operand:SI 1 "s_register_operand" "r")
5271 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5272 (match_operator:SI 9 "shift_operator"
5273 [(match_operand:SI 3 "s_register_operand" "r")
5274 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
5275 (clobber (reg:CC 24))]
5278 [(set_attr "conds" "clob")
5279 (set_attr "length" "12")])
5281 (define_insn "*if_shift_shift"
5282 [(set (match_operand:SI 0 "s_register_operand" "=r")
5284 (match_operator 5 "comparison_operator"
5285 [(match_operand 8 "cc_register" "") (const_int 0)])
5286 (match_operator:SI 6 "shift_operator"
5287 [(match_operand:SI 1 "s_register_operand" "r")
5288 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5289 (match_operator:SI 7 "shift_operator"
5290 [(match_operand:SI 3 "s_register_operand" "r")
5291 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
5293 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
5294 [(set_attr "conds" "use")
5295 (set_attr "length" "8")])
5297 (define_insn "*ifcompare_not_arith"
5298 [(set (match_operand:SI 0 "s_register_operand" "=r")
5300 (match_operator 6 "comparison_operator"
5301 [(match_operand:SI 4 "s_register_operand" "r")
5302 (match_operand:SI 5 "arm_add_operand" "rIL")])
5303 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5304 (match_operator:SI 7 "shiftable_operator"
5305 [(match_operand:SI 2 "s_register_operand" "r")
5306 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5307 (clobber (reg:CC 24))]
5310 [(set_attr "conds" "clob")
5311 (set_attr "length" "12")])
5313 (define_insn "*if_not_arith"
5314 [(set (match_operand:SI 0 "s_register_operand" "=r")
5316 (match_operator 5 "comparison_operator"
5317 [(match_operand 4 "cc_register" "") (const_int 0)])
5318 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5319 (match_operator:SI 6 "shiftable_operator"
5320 [(match_operand:SI 2 "s_register_operand" "r")
5321 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
5323 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
5324 [(set_attr "conds" "use")
5325 (set_attr "length" "8")])
5327 (define_insn "*ifcompare_arith_not"
5328 [(set (match_operand:SI 0 "s_register_operand" "=r")
5330 (match_operator 6 "comparison_operator"
5331 [(match_operand:SI 4 "s_register_operand" "r")
5332 (match_operand:SI 5 "arm_add_operand" "rIL")])
5333 (match_operator:SI 7 "shiftable_operator"
5334 [(match_operand:SI 2 "s_register_operand" "r")
5335 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5336 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5337 (clobber (reg:CC 24))]
5340 [(set_attr "conds" "clob")
5341 (set_attr "length" "12")])
5343 (define_insn "*if_arith_not"
5344 [(set (match_operand:SI 0 "s_register_operand" "=r")
5346 (match_operator 5 "comparison_operator"
5347 [(match_operand 4 "cc_register" "") (const_int 0)])
5348 (match_operator:SI 6 "shiftable_operator"
5349 [(match_operand:SI 2 "s_register_operand" "r")
5350 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5351 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
5353 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
5354 [(set_attr "conds" "use")
5355 (set_attr "length" "8")])
5357 (define_insn "*ifcompare_neg_move"
5358 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5360 (match_operator 5 "comparison_operator"
5361 [(match_operand:SI 3 "s_register_operand" "r,r")
5362 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5363 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
5364 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5365 (clobber (reg:CC 24))]
5368 [(set_attr "conds" "clob")
5369 (set_attr "length" "8,12")])
5371 (define_insn "*if_neg_move"
5372 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5374 (match_operator 4 "comparison_operator"
5375 [(match_operand 3 "cc_register" "") (const_int 0)])
5376 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5377 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5381 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
5382 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
5383 [(set_attr "conds" "use")
5384 (set_attr "length" "4,8,8")])
5386 (define_insn "*ifcompare_move_neg"
5387 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5389 (match_operator 5 "comparison_operator"
5390 [(match_operand:SI 3 "s_register_operand" "r,r")
5391 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5392 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5393 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
5394 (clobber (reg:CC 24))]
5397 [(set_attr "conds" "clob")
5398 (set_attr "length" "8,12")])
5400 (define_insn "*if_move_neg"
5401 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5403 (match_operator 4 "comparison_operator"
5404 [(match_operand 3 "cc_register" "") (const_int 0)])
5405 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5406 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5410 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
5411 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
5412 [(set_attr "conds" "use")
5413 (set_attr "length" "4,8,8")])
5415 (define_insn "*arith_adjacentmem"
5416 [(set (match_operand:SI 0 "s_register_operand" "=r")
5417 (match_operator:SI 1 "shiftable_operator"
5418 [(match_operand:SI 2 "memory_operand" "m")
5419 (match_operand:SI 3 "memory_operand" "m")]))
5420 (clobber (match_scratch:SI 4 "=r"))]
5421 "adjacent_mem_locations (operands[2], operands[3])"
5426 int val1 = 0, val2 = 0;
5428 if (REGNO (operands[0]) > REGNO (operands[4]))
5430 ldm[1] = operands[4];
5431 ldm[2] = operands[0];
5435 ldm[1] = operands[0];
5436 ldm[2] = operands[4];
5438 if (GET_CODE (XEXP (operands[2], 0)) != REG)
5439 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5440 if (GET_CODE (XEXP (operands[3], 0)) != REG)
5441 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5442 arith[0] = operands[0];
5443 arith[3] = operands[1];
5457 ldm[0] = ops[0] = operands[4];
5458 ops[1] = XEXP (XEXP (operands[2], 0), 0);
5459 ops[2] = XEXP (XEXP (operands[2], 0), 1);
5460 output_add_immediate (ops);
5462 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5464 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5468 ldm[0] = XEXP (operands[3], 0);
5470 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5472 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5476 ldm[0] = XEXP (operands[2], 0);
5478 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5480 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5482 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
5486 [(set_attr "length" "12")
5487 (set_attr "type" "load")])
5489 ;; the arm can support extended pre-inc instructions
5491 ;; In all these cases, we use operands 0 and 1 for the register being
5492 ;; incremented because those are the operands that local-alloc will
5493 ;; tie and these are the pair most likely to be tieable (and the ones
5494 ;; that will benefit the most).
5496 ;; We reject the frame pointer if it occurs anywhere in these patterns since
5497 ;; elimination will cause too many headaches.
5499 (define_insn "*strqi_preinc"
5500 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5501 (match_operand:SI 2 "index_operand" "rJ")))
5502 (match_operand:QI 3 "s_register_operand" "r"))
5503 (set (match_operand:SI 0 "s_register_operand" "=r")
5504 (plus:SI (match_dup 1) (match_dup 2)))]
5505 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5506 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5507 && (GET_CODE (operands[2]) != REG
5508 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5509 "str%?b\\t%3, [%0, %2]!"
5510 [(set_attr "type" "store1")])
5512 (define_insn "*strqi_predec"
5513 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5514 (match_operand:SI 2 "s_register_operand" "r")))
5515 (match_operand:QI 3 "s_register_operand" "r"))
5516 (set (match_operand:SI 0 "s_register_operand" "=r")
5517 (minus:SI (match_dup 1) (match_dup 2)))]
5518 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5519 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5520 && (GET_CODE (operands[2]) != REG
5521 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5522 "str%?b\\t%3, [%0, -%2]!"
5523 [(set_attr "type" "store1")])
5525 (define_insn "*loadqi_preinc"
5526 [(set (match_operand:QI 3 "s_register_operand" "=r")
5527 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5528 (match_operand:SI 2 "index_operand" "rJ"))))
5529 (set (match_operand:SI 0 "s_register_operand" "=r")
5530 (plus:SI (match_dup 1) (match_dup 2)))]
5531 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5532 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5533 && (GET_CODE (operands[2]) != REG
5534 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5535 "ldr%?b\\t%3, [%0, %2]!"
5536 [(set_attr "type" "load")])
5538 (define_insn "*loadqi_predec"
5539 [(set (match_operand:QI 3 "s_register_operand" "=r")
5540 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5541 (match_operand:SI 2 "s_register_operand" "r"))))
5542 (set (match_operand:SI 0 "s_register_operand" "=r")
5543 (minus:SI (match_dup 1) (match_dup 2)))]
5544 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5545 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5546 && (GET_CODE (operands[2]) != REG
5547 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5548 "ldr%?b\\t%3, [%0, -%2]!"
5549 [(set_attr "type" "load")])
5551 (define_insn "*loadqisi_preinc"
5552 [(set (match_operand:SI 3 "s_register_operand" "=r")
5554 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5555 (match_operand:SI 2 "index_operand" "rJ")))))
5556 (set (match_operand:SI 0 "s_register_operand" "=r")
5557 (plus:SI (match_dup 1) (match_dup 2)))]
5558 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5559 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5560 && (GET_CODE (operands[2]) != REG
5561 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5562 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
5563 [(set_attr "type" "load")])
5565 (define_insn "*loadqisi_predec"
5566 [(set (match_operand:SI 3 "s_register_operand" "=r")
5568 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5569 (match_operand:SI 2 "s_register_operand" "r")))))
5570 (set (match_operand:SI 0 "s_register_operand" "=r")
5571 (minus:SI (match_dup 1) (match_dup 2)))]
5572 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5573 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5574 && (GET_CODE (operands[2]) != REG
5575 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5576 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
5577 [(set_attr "type" "load")])
5579 (define_insn "*strsi_preinc"
5580 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5581 (match_operand:SI 2 "index_operand" "rJ")))
5582 (match_operand:SI 3 "s_register_operand" "r"))
5583 (set (match_operand:SI 0 "s_register_operand" "=r")
5584 (plus:SI (match_dup 1) (match_dup 2)))]
5585 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5586 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5587 && (GET_CODE (operands[2]) != REG
5588 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5589 "str%?\\t%3, [%0, %2]!"
5590 [(set_attr "type" "store1")])
5592 (define_insn "*strqi_predec"
5593 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5594 (match_operand:SI 2 "s_register_operand" "r")))
5595 (match_operand:SI 3 "s_register_operand" "r"))
5596 (set (match_operand:SI 0 "s_register_operand" "=r")
5597 (minus:SI (match_dup 1) (match_dup 2)))]
5598 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5599 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5600 && (GET_CODE (operands[2]) != REG
5601 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5602 "str%?\\t%3, [%0, -%2]!"
5603 [(set_attr "type" "store1")])
5605 (define_insn "*loadsi_preinc"
5606 [(set (match_operand:SI 3 "s_register_operand" "=r")
5607 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5608 (match_operand:SI 2 "index_operand" "rJ"))))
5609 (set (match_operand:SI 0 "s_register_operand" "=r")
5610 (plus:SI (match_dup 1) (match_dup 2)))]
5611 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5612 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5613 && (GET_CODE (operands[2]) != REG
5614 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5615 "ldr%?\\t%3, [%0, %2]!"
5616 [(set_attr "type" "load")])
5618 (define_insn "*loadsi_predec"
5619 [(set (match_operand:SI 3 "s_register_operand" "=r")
5620 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5621 (match_operand:SI 2 "s_register_operand" "r"))))
5622 (set (match_operand:SI 0 "s_register_operand" "=r")
5623 (minus:SI (match_dup 1) (match_dup 2)))]
5624 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5625 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5626 && (GET_CODE (operands[2]) != REG
5627 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5628 "ldr%?\\t%3, [%0, -%2]!"
5629 [(set_attr "type" "load")])
5631 (define_insn "*loadhi_preinc"
5632 [(set (match_operand:HI 3 "s_register_operand" "=r")
5633 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5634 (match_operand:SI 2 "index_operand" "rJ"))))
5635 (set (match_operand:SI 0 "s_register_operand" "=r")
5636 (plus:SI (match_dup 1) (match_dup 2)))]
5637 "(! BYTES_BIG_ENDIAN)
5638 && ! TARGET_SHORT_BY_BYTES
5639 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5640 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5641 && (GET_CODE (operands[2]) != REG
5642 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5643 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5644 [(set_attr "type" "load")])
5646 (define_insn "*loadhi_predec"
5647 [(set (match_operand:HI 3 "s_register_operand" "=r")
5648 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5649 (match_operand:SI 2 "s_register_operand" "r"))))
5650 (set (match_operand:SI 0 "s_register_operand" "=r")
5651 (minus:SI (match_dup 1) (match_dup 2)))]
5652 "(!BYTES_BIG_ENDIAN)
5653 && ! TARGET_SHORT_BY_BYTES
5654 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5655 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5656 && (GET_CODE (operands[2]) != REG
5657 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5658 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5659 [(set_attr "type" "load")])
5661 (define_insn "*strqi_shiftpreinc"
5662 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5663 [(match_operand:SI 3 "s_register_operand" "r")
5664 (match_operand:SI 4 "const_shift_operand" "n")])
5665 (match_operand:SI 1 "s_register_operand" "0")))
5666 (match_operand:QI 5 "s_register_operand" "r"))
5667 (set (match_operand:SI 0 "s_register_operand" "=r")
5668 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5670 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5671 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5672 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5673 "str%?b\\t%5, [%0, %3%S2]!"
5674 [(set_attr "type" "store1")])
5676 (define_insn "*strqi_shiftpredec"
5677 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5678 (match_operator:SI 2 "shift_operator"
5679 [(match_operand:SI 3 "s_register_operand" "r")
5680 (match_operand:SI 4 "const_shift_operand" "n")])))
5681 (match_operand:QI 5 "s_register_operand" "r"))
5682 (set (match_operand:SI 0 "s_register_operand" "=r")
5683 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5685 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5686 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5687 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5688 "str%?b\\t%5, [%0, -%3%S2]!"
5689 [(set_attr "type" "store1")])
5691 (define_insn "*loadqi_shiftpreinc"
5692 [(set (match_operand:QI 5 "s_register_operand" "=r")
5693 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5694 [(match_operand:SI 3 "s_register_operand" "r")
5695 (match_operand:SI 4 "const_shift_operand" "n")])
5696 (match_operand:SI 1 "s_register_operand" "0"))))
5697 (set (match_operand:SI 0 "s_register_operand" "=r")
5698 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5700 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5701 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5702 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5703 "ldr%?b\\t%5, [%0, %3%S2]!"
5704 [(set_attr "type" "load")])
5706 (define_insn "*loadqi_shiftpredec"
5707 [(set (match_operand:QI 5 "s_register_operand" "=r")
5708 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5709 (match_operator:SI 2 "shift_operator"
5710 [(match_operand:SI 3 "s_register_operand" "r")
5711 (match_operand:SI 4 "const_shift_operand" "n")]))))
5712 (set (match_operand:SI 0 "s_register_operand" "=r")
5713 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5715 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5716 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5717 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5718 "ldr%?b\\t%5, [%0, -%3%S2]!"
5719 [(set_attr "type" "load")])
5721 (define_insn "*strsi_shiftpreinc"
5722 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5723 [(match_operand:SI 3 "s_register_operand" "r")
5724 (match_operand:SI 4 "const_shift_operand" "n")])
5725 (match_operand:SI 1 "s_register_operand" "0")))
5726 (match_operand:SI 5 "s_register_operand" "r"))
5727 (set (match_operand:SI 0 "s_register_operand" "=r")
5728 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5730 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5731 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5732 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5733 "str%?\\t%5, [%0, %3%S2]!"
5734 [(set_attr "type" "store1")])
5736 (define_insn "*strsi_shiftpredec"
5737 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5738 (match_operator:SI 2 "shift_operator"
5739 [(match_operand:SI 3 "s_register_operand" "r")
5740 (match_operand:SI 4 "const_shift_operand" "n")])))
5741 (match_operand:SI 5 "s_register_operand" "r"))
5742 (set (match_operand:SI 0 "s_register_operand" "=r")
5743 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5745 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5746 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5747 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5748 "str%?\\t%5, [%0, -%3%S2]!"
5749 [(set_attr "type" "store1")])
5751 (define_insn "*loadqi_shiftpreinc"
5752 [(set (match_operand:SI 5 "s_register_operand" "=r")
5753 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5754 [(match_operand:SI 3 "s_register_operand" "r")
5755 (match_operand:SI 4 "const_shift_operand" "n")])
5756 (match_operand:SI 1 "s_register_operand" "0"))))
5757 (set (match_operand:SI 0 "s_register_operand" "=r")
5758 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5760 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5761 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5762 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5763 "ldr%?\\t%5, [%0, %3%S2]!"
5764 [(set_attr "type" "load")])
5766 (define_insn "*loadqi_shiftpredec"
5767 [(set (match_operand:SI 5 "s_register_operand" "=r")
5768 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5769 (match_operator:SI 2 "shift_operator"
5770 [(match_operand:SI 3 "s_register_operand" "r")
5771 (match_operand:SI 4 "const_shift_operand" "n")]))))
5772 (set (match_operand:SI 0 "s_register_operand" "=r")
5773 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5775 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5776 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5777 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5778 "ldr%?\\t%5, [%0, -%3%S2]!"
5779 [(set_attr "type" "load")])
5781 (define_insn "*loadhi_shiftpreinc"
5782 [(set (match_operand:HI 5 "s_register_operand" "=r")
5783 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5784 [(match_operand:SI 3 "s_register_operand" "r")
5785 (match_operand:SI 4 "const_shift_operand" "n")])
5786 (match_operand:SI 1 "s_register_operand" "0"))))
5787 (set (match_operand:SI 0 "s_register_operand" "=r")
5788 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5790 "(! BYTES_BIG_ENDIAN)
5791 && ! TARGET_SHORT_BY_BYTES
5792 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5793 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5794 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5795 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5796 [(set_attr "type" "load")])
5798 (define_insn "*loadhi_shiftpredec"
5799 [(set (match_operand:HI 5 "s_register_operand" "=r")
5800 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5801 (match_operator:SI 2 "shift_operator"
5802 [(match_operand:SI 3 "s_register_operand" "r")
5803 (match_operand:SI 4 "const_shift_operand" "n")]))))
5804 (set (match_operand:SI 0 "s_register_operand" "=r")
5805 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5807 "(! BYTES_BIG_ENDIAN)
5808 && ! TARGET_SHORT_BY_BYTES
5809 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5810 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5811 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5812 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5813 [(set_attr "type" "load")])
5815 ; It can also support extended post-inc expressions, but combine doesn't
5817 ; It doesn't seem worth adding peepholes for anything but the most common
5818 ; cases since, unlike combine, the increment must immediately follow the load
5819 ; for this pattern to match.
5820 ; When loading we must watch to see that the base register isn't trampled by
5821 ; the load. In such cases this isn't a post-inc expression.
5824 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5825 (match_operand:QI 2 "s_register_operand" "r"))
5827 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5829 "str%?b\\t%2, [%0], %1")
5832 [(set (match_operand:QI 0 "s_register_operand" "=r")
5833 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5835 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5836 "REGNO(operands[0]) != REGNO(operands[1])
5837 && (GET_CODE (operands[2]) != REG
5838 || REGNO(operands[0]) != REGNO (operands[2]))"
5839 "ldr%?b\\t%0, [%1], %2")
5842 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5843 (match_operand:SI 2 "s_register_operand" "r"))
5845 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5847 "str%?\\t%2, [%0], %1")
5850 [(set (match_operand:HI 0 "s_register_operand" "=r")
5851 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5853 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5854 "(! BYTES_BIG_ENDIAN)
5855 && ! TARGET_SHORT_BY_BYTES
5856 && REGNO(operands[0]) != REGNO(operands[1])
5857 && (GET_CODE (operands[2]) != REG
5858 || REGNO(operands[0]) != REGNO (operands[2]))"
5859 "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5862 [(set (match_operand:SI 0 "s_register_operand" "=r")
5863 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5865 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5866 "REGNO(operands[0]) != REGNO(operands[1])
5867 && (GET_CODE (operands[2]) != REG
5868 || REGNO(operands[0]) != REGNO (operands[2]))"
5869 "ldr%?\\t%0, [%1], %2")
5872 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5873 (match_operand:SI 1 "index_operand" "rJ")))
5874 (match_operand:QI 2 "s_register_operand" "r"))
5875 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5877 "str%?b\\t%2, [%0, %1]!")
5880 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5881 [(match_operand:SI 0 "s_register_operand" "r")
5882 (match_operand:SI 1 "const_int_operand" "n")])
5883 (match_operand:SI 2 "s_register_operand" "+r")))
5884 (match_operand:QI 3 "s_register_operand" "r"))
5885 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5888 "str%?b\\t%3, [%2, %0%S4]!")
5890 ; This pattern is never tried by combine, so do it as a peephole
5893 [(set (match_operand:SI 0 "s_register_operand" "=r")
5894 (match_operand:SI 1 "s_register_operand" "r"))
5896 (compare:CC (match_dup 1) (const_int 0)))]
5898 "sub%?s\\t%0, %1, #0"
5899 [(set_attr "conds" "set")])
5901 ; Peepholes to spot possible load- and store-multiples, if the ordering is
5902 ; reversed, check that the memory references aren't volatile.
5905 [(set (match_operand:SI 0 "s_register_operand" "=r")
5906 (match_operand:SI 4 "memory_operand" "m"))
5907 (set (match_operand:SI 1 "s_register_operand" "=r")
5908 (match_operand:SI 5 "memory_operand" "m"))
5909 (set (match_operand:SI 2 "s_register_operand" "=r")
5910 (match_operand:SI 6 "memory_operand" "m"))
5911 (set (match_operand:SI 3 "s_register_operand" "=r")
5912 (match_operand:SI 7 "memory_operand" "m"))]
5913 "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5915 return emit_ldm_seq (operands, 4);
5919 [(set (match_operand:SI 0 "s_register_operand" "=r")
5920 (match_operand:SI 3 "memory_operand" "m"))
5921 (set (match_operand:SI 1 "s_register_operand" "=r")
5922 (match_operand:SI 4 "memory_operand" "m"))
5923 (set (match_operand:SI 2 "s_register_operand" "=r")
5924 (match_operand:SI 5 "memory_operand" "m"))]
5925 "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5927 return emit_ldm_seq (operands, 3);
5931 [(set (match_operand:SI 0 "s_register_operand" "=r")
5932 (match_operand:SI 2 "memory_operand" "m"))
5933 (set (match_operand:SI 1 "s_register_operand" "=r")
5934 (match_operand:SI 3 "memory_operand" "m"))]
5935 "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5937 return emit_ldm_seq (operands, 2);
5941 [(set (match_operand:SI 4 "memory_operand" "=m")
5942 (match_operand:SI 0 "s_register_operand" "r"))
5943 (set (match_operand:SI 5 "memory_operand" "=m")
5944 (match_operand:SI 1 "s_register_operand" "r"))
5945 (set (match_operand:SI 6 "memory_operand" "=m")
5946 (match_operand:SI 2 "s_register_operand" "r"))
5947 (set (match_operand:SI 7 "memory_operand" "=m")
5948 (match_operand:SI 3 "s_register_operand" "r"))]
5949 "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5951 return emit_stm_seq (operands, 4);
5955 [(set (match_operand:SI 3 "memory_operand" "=m")
5956 (match_operand:SI 0 "s_register_operand" "r"))
5957 (set (match_operand:SI 4 "memory_operand" "=m")
5958 (match_operand:SI 1 "s_register_operand" "r"))
5959 (set (match_operand:SI 5 "memory_operand" "=m")
5960 (match_operand:SI 2 "s_register_operand" "r"))]
5961 "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5963 return emit_stm_seq (operands, 3);
5967 [(set (match_operand:SI 2 "memory_operand" "=m")
5968 (match_operand:SI 0 "s_register_operand" "r"))
5969 (set (match_operand:SI 3 "memory_operand" "=m")
5970 (match_operand:SI 1 "s_register_operand" "r"))]
5971 "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5973 return emit_stm_seq (operands, 2);
5976 ;; A call followed by return can be replaced by restoring the regs and
5977 ;; jumping to the subroutine, provided we aren't passing the address of
5978 ;; any of our local variables. If we call alloca then this is unsafe
5979 ;; since restoring the frame frees the memory, which is not what we want.
5980 ;; Sometimes the return might have been targeted by the final prescan:
5981 ;; if so then emit a proper return insn as well.
5982 ;; Unfortunately, if the frame pointer is required, we don't know if the
5983 ;; current function has any implicit stack pointer adjustments that will
5984 ;; be restored by the return: we can't therefore do a tail call.
5985 ;; Another unfortunate that we can't handle is if current_function_args_size
5986 ;; is non-zero: in this case elimination of the argument pointer assumed
5987 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5991 [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5992 (match_operand:SI 1 "general_operand" "g"))
5993 (clobber (reg:SI 14))])
5995 "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
5996 && !get_frame_size () && !current_function_calls_alloca
5997 && !frame_pointer_needed && !current_function_args_size)"
6000 extern rtx arm_target_insn;
6001 extern int arm_ccfsm_state;
6003 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6005 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6006 output_return_instruction (NULL, TRUE, FALSE);
6007 arm_ccfsm_state = 0;
6008 arm_target_insn = NULL;
6011 output_return_instruction (NULL, FALSE, FALSE);
6012 return \"b%?\\t%a0\";
6014 [(set_attr "type" "call")
6015 (set_attr "length" "8")])
6018 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6019 (call (mem:SI (match_operand:SI 1 "" "X"))
6020 (match_operand:SI 2 "general_operand" "g")))
6021 (clobber (reg:SI 14))])
6023 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
6024 && !get_frame_size () && !current_function_calls_alloca
6025 && !frame_pointer_needed && !current_function_args_size)"
6028 extern rtx arm_target_insn;
6029 extern int arm_ccfsm_state;
6031 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6033 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6034 output_return_instruction (NULL, TRUE, FALSE);
6035 arm_ccfsm_state = 0;
6036 arm_target_insn = NULL;
6039 output_return_instruction (NULL, FALSE, FALSE);
6040 return \"b%?\\t%a1\";
6042 [(set_attr "type" "call")
6043 (set_attr "length" "8")])
6045 ;; As above but when this function is not void, we must be returning the
6046 ;; result of the called subroutine.
6049 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6050 (call (mem:SI (match_operand:SI 1 "" "X"))
6051 (match_operand:SI 2 "general_operand" "g")))
6052 (clobber (reg:SI 14))])
6055 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
6056 && !get_frame_size () && !current_function_calls_alloca
6057 && !frame_pointer_needed && !current_function_args_size)"
6060 extern rtx arm_target_insn;
6061 extern int arm_ccfsm_state;
6063 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6065 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6066 output_return_instruction (NULL, TRUE, FALSE);
6067 arm_ccfsm_state = 0;
6068 arm_target_insn = NULL;
6071 output_return_instruction (NULL, FALSE, FALSE);
6072 return \"b%?\\t%a1\";
6074 [(set_attr "type" "call")
6075 (set_attr "length" "8")])
6078 [(set (match_operand:SI 0 "s_register_operand" "")
6079 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
6081 (neg:SI (match_operator:SI 2 "comparison_operator"
6082 [(match_operand:SI 3 "s_register_operand" "")
6083 (match_operand:SI 4 "arm_rhs_operand" "")]))))
6084 (clobber (match_operand:SI 5 "s_register_operand" ""))]
6086 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
6087 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6091 ;; This split can be used because CC_Z mode implies that the following
6092 ;; branch will be an equality, or an unsigned inequality, so the sign
6093 ;; extension is not needed.
6098 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
6100 (match_operand 1 "const_int_operand" "")))
6101 (clobber (match_scratch:SI 2 ""))]
6102 "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
6103 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
6104 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
6105 (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
6107 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
6110 (define_expand "prologue"
6111 [(clobber (const_int 0))]
6114 arm_expand_prologue ();
6118 ;; This split is only used during output to reduce the number of patterns
6119 ;; that need assembler instructions adding to them. We allowed the setting
6120 ;; of the conditions to be implicit during rtl generation so that
6121 ;; the conditional compare patterns would work. However this conflicts to
6122 ;; some extent with the conditional data operations, so we have to split them
6126 [(set (match_operand:SI 0 "s_register_operand" "")
6127 (if_then_else:SI (match_operator 1 "comparison_operator"
6128 [(match_operand 2 "" "") (match_operand 3 "" "")])
6129 (match_operand 4 "" "")
6130 (match_operand 5 "" "")))
6131 (clobber (reg:CC 24))]
6133 [(set (match_dup 6) (match_dup 7))
6135 (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
6140 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
6143 operands[6] = gen_rtx (REG, mode, 24);
6144 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
6149 ;; The next two patterns occur when an AND operation is followed by a
6150 ;; scc insn sequence
6152 (define_insn "*sign_extract_onebit"
6153 [(set (match_operand:SI 0 "s_register_operand" "=r")
6154 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6156 (match_operand:SI 2 "const_int_operand" "n")))]
6159 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6160 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6161 return \"mvnne\\t%0, #0\";
6163 [(set_attr "conds" "clob")
6164 (set_attr "length" "8")])
6166 (define_insn "*not_signextract_onebit"
6167 [(set (match_operand:SI 0 "s_register_operand" "=r")
6169 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6171 (match_operand:SI 2 "const_int_operand" "n"))))]
6174 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6175 output_asm_insn (\"tst\\t%1, %2\", operands);
6176 output_asm_insn (\"mvneq\\t%0, #0\", operands);
6177 return \"movne\\t%0, #0\";
6179 [(set_attr "conds" "clob")
6180 (set_attr "length" "12")])
6182 ;; Push multiple registers to the stack. The first register is in the
6183 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
6185 (define_insn "*push_multi"
6186 [(match_parallel 2 "multi_register_push"
6187 [(set (match_operand:BLK 0 "memory_operand" "=m")
6188 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
6194 extern int lr_save_eliminated;
6196 if (lr_save_eliminated)
6198 if (XVECLEN (operands[2], 0) > 1)
6202 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
6203 for (i = 1; i < XVECLEN (operands[2], 0); i++)
6205 strcat (pattern, \", %|\");
6206 strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
6209 strcat (pattern, \"}\");
6210 output_asm_insn (pattern, operands);
6213 [(set_attr "type" "store4")])
6215 ;; Similarly for the floating point registers
6216 (define_insn "*push_fp_multi"
6217 [(match_parallel 2 "multi_register_push"
6218 [(set (match_operand:BLK 0 "memory_operand" "=m")
6219 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
6226 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
6227 output_asm_insn (pattern, operands);
6230 [(set_attr "type" "f_store")])
6232 ;; Special patterns for dealing with the constant pool
6234 (define_insn "consttable_4"
6235 [(unspec_volatile [(match_operand 0 "" "")] 2)]
6239 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6243 union real_extract u;
6244 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6245 assemble_real (u.d, GET_MODE (operands[0]));
6249 assemble_integer (operands[0], 4, 1);
6254 [(set_attr "length" "4")])
6256 (define_insn "consttable_8"
6257 [(unspec_volatile [(match_operand 0 "" "")] 3)]
6261 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6265 union real_extract u;
6266 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6267 assemble_real (u.d, GET_MODE (operands[0]));
6271 assemble_integer (operands[0], 8, 1);
6276 [(set_attr "length" "8")])
6278 (define_insn "consttable_end"
6279 [(unspec_volatile [(const_int 0)] 4)]
6282 /* Nothing to do (currently). */
6286 (define_insn "align_4"
6287 [(unspec_volatile [(const_int 0)] 5)]
6290 assemble_align (32);