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, operands[1]),
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),
2453 XEXP (operands[1], 0));
2457 (define_expand "extendqisi2"
2459 (ashift:SI (match_operand:QI 1 "general_operand" "")
2461 (set (match_operand:SI 0 "s_register_operand" "")
2462 (ashiftrt:SI (match_dup 2)
2467 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2469 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2470 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2473 if (! s_register_operand (operands[1], QImode))
2474 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2475 operands[1] = gen_lowpart (SImode, operands[1]);
2476 operands[2] = gen_reg_rtx (SImode);
2479 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2480 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2481 (define_insn "*extendqisi_insn"
2482 [(set (match_operand:SI 0 "s_register_operand" "=r")
2483 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2486 /* If the address is invalid, this will split the instruction into two. */
2487 if (bad_signed_byte_operand(operands[1], QImode))
2489 return \"ldr%?sb\\t%0, %1\";
2491 [(set_attr "type" "load")
2492 (set_attr "length" "8")])
2495 [(set (match_operand:SI 0 "s_register_operand" "")
2496 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2497 "arm_arch4 && reload_completed"
2498 [(set (match_dup 0) (match_dup 1))
2499 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2502 HOST_WIDE_INT offset;
2504 operands[2] = gen_rtx_MEM (QImode, operands[0]);
2505 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2506 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2507 operands[1] = XEXP (operands[1], 0);
2508 if (GET_CODE (operands[1]) == PLUS
2509 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2510 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2511 || const_ok_for_arm (-offset)))
2513 HOST_WIDE_INT low = (offset > 0
2514 ? (offset & 0xff) : -((-offset) & 0xff));
2515 XEXP (operands[2], 0) = plus_constant (operands[0], low);
2516 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2518 /* Ensure the sum is in correct canonical form */
2519 else if (GET_CODE (operands[1]) == PLUS
2520 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2521 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2522 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2523 XEXP (operands[1], 1),
2524 XEXP (operands[1], 0));
2528 (define_insn "extendsfdf2"
2529 [(set (match_operand:DF 0 "s_register_operand" "=f")
2530 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2533 [(set_attr "type" "ffarith")])
2535 (define_insn "extendsfxf2"
2536 [(set (match_operand:XF 0 "s_register_operand" "=f")
2537 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2538 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2540 [(set_attr "type" "ffarith")])
2542 (define_insn "extenddfxf2"
2543 [(set (match_operand:XF 0 "s_register_operand" "=f")
2544 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2545 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2547 [(set_attr "type" "ffarith")])
2550 ;; Move insns (including loads and stores)
2552 ;; XXX Just some ideas about movti.
2553 ;; I don't think these are a good idea on the arm, there just aren't enough
2555 ;;(define_expand "loadti"
2556 ;; [(set (match_operand:TI 0 "s_register_operand" "")
2557 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
2560 ;;(define_expand "storeti"
2561 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2562 ;; (match_operand:TI 1 "s_register_operand" ""))]
2565 ;;(define_expand "movti"
2566 ;; [(set (match_operand:TI 0 "general_operand" "")
2567 ;; (match_operand:TI 1 "general_operand" ""))]
2573 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2574 ;; operands[1] = copy_to_reg (operands[1]);
2575 ;; if (GET_CODE (operands[0]) == MEM)
2576 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2577 ;; else if (GET_CODE (operands[1]) == MEM)
2578 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2582 ;; emit_insn (insn);
2586 ;; Recognise garbage generated above.
2589 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2590 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2594 ;; register mem = (which_alternative < 3);
2595 ;; register char *template;
2597 ;; operands[mem] = XEXP (operands[mem], 0);
2598 ;; switch (which_alternative)
2600 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2601 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
2602 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
2603 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
2604 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
2605 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
2607 ;; output_asm_insn (template, operands);
2612 (define_insn "movdi"
2613 [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2614 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2617 return (output_move_double (operands));
2619 [(set_attr "length" "8,8,8")
2620 (set_attr "type" "*,load,store2")])
2622 (define_expand "movsi"
2623 [(set (match_operand:SI 0 "general_operand" "")
2624 (match_operand:SI 1 "general_operand" ""))]
2627 /* Everything except mem = const or mem = mem can be done easily */
2628 if (GET_CODE (operands[0]) == MEM)
2629 operands[1] = force_reg (SImode, operands[1]);
2630 if (GET_CODE (operands[1]) == CONST_INT
2631 && !(const_ok_for_arm (INTVAL (operands[1]))
2632 || const_ok_for_arm (~INTVAL (operands[1]))))
2634 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2636 (reload_in_progress || reload_completed ? 0
2637 : preserve_subexpressions_p ()));
2640 if (CONSTANT_P (operands[1]) && flag_pic)
2641 operands[1] = legitimize_pic_address (operands[1], SImode,
2642 ((reload_in_progress
2643 || reload_completed)
2644 ? operands[0] : 0));
2647 (define_insn "*movsi_insn"
2648 [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2649 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
2650 "register_operand (operands[0], SImode)
2651 || register_operand (operands[1], SImode)"
2657 [(set_attr "type" "*,*,load,store1")])
2660 [(set (match_operand:SI 0 "s_register_operand" "")
2661 (match_operand:SI 1 "const_int_operand" ""))]
2662 "! (const_ok_for_arm (INTVAL (operands[1]))
2663 || const_ok_for_arm (~INTVAL (operands[1])))"
2664 [(clobber (const_int 0))]
2666 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2671 (define_expand "movaddr"
2672 [(set (match_operand:SI 0 "s_register_operand" "")
2673 (match_operand:DI 1 "address_operand" ""))]
2677 (define_insn "*movaddr_insn"
2678 [(set (match_operand:SI 0 "s_register_operand" "=r")
2679 (match_operand:DI 1 "address_operand" "p"))]
2681 && (GET_CODE (operands[1]) == LABEL_REF
2682 || (GET_CODE (operands[1]) == CONST
2683 && GET_CODE (XEXP (operands[1], 0)) == PLUS
2684 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2685 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2688 /* When generating pic, we need to load the symbol offset into a register.
2689 So that the optimizer does not confuse this with a normal symbol load
2690 we use an unspec. The offset will be loaded from a constant pool entry,
2691 since that is the only type of relocation we can use. */
2693 (define_insn "pic_load_addr"
2694 [(set (match_operand:SI 0 "s_register_operand" "=r")
2695 (unspec:SI [(match_operand 1 "" "")] 3))]
2698 [(set_attr "type" "load")])
2700 ;; This variant is used for AOF assembly, since it needs to mention the
2701 ;; pic register in the rtl.
2702 (define_expand "pic_load_addr_based"
2703 [(set (match_operand:SI 0 "s_register_operand" "=r")
2704 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
2706 "operands[2] = pic_offset_table_rtx;")
2708 (define_insn "*pic_load_addr_based_insn"
2709 [(set (match_operand:SI 0 "s_register_operand" "=r")
2710 (unspec:SI [(match_operand 1 "" "")
2711 (match_operand 2 "s_register_operand" "r")] 3))]
2712 "flag_pic && operands[2] == pic_offset_table_rtx"
2714 #ifdef AOF_ASSEMBLER
2715 operands[1] = aof_pic_entry (operands[1]);
2717 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
2719 " [(set_attr "type" "load")])
2721 (define_insn "pic_add_dot_plus_eight"
2722 [(set (pc) (label_ref (match_operand 0 "" "")))
2723 (set (match_operand 1 "register_operand" "+r")
2724 (plus:SI (match_dup 1) (const (plus:SI (pc) (const_int 8)))))]
2726 "add%?\\t%1, %|pc, %1")
2728 ;; If copying one reg to another we can set the condition codes according to
2729 ;; its value. Such a move is common after a return from subroutine and the
2730 ;; result is being tested against zero.
2732 (define_insn "*movsi_compare0"
2733 [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
2735 (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2739 sub%?s\\t%0, %1, #0"
2740 [(set_attr "conds" "set")])
2742 ;; Subroutine to store a half word from a register into memory.
2743 ;; Operand 0 is the source register (HImode)
2744 ;; Operand 1 is the destination address in a register (SImode)
2746 ;; In both this routine and the next, we must be careful not to spill
2747 ;; a memory address of reg+large_const into a separate PLUS insn, since this
2748 ;; can generate unrecognizable rtl.
2750 (define_expand "storehi"
2751 [;; store the low byte
2752 (set (match_operand 1 "" "") (match_dup 3))
2753 ;; extract the high byte
2755 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2756 ;; store the high byte
2757 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
2761 rtx addr = XEXP (operands[1], 0);
2762 enum rtx_code code = GET_CODE (addr);
2764 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2766 addr = force_reg (SImode, addr);
2768 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2769 operands[1] = change_address (operands[1], QImode, NULL_RTX);
2770 operands[3] = gen_lowpart (QImode, operands[0]);
2771 operands[0] = gen_lowpart (SImode, operands[0]);
2772 operands[2] = gen_reg_rtx (SImode);
2776 (define_expand "storehi_bigend"
2777 [(set (match_dup 4) (match_dup 3))
2779 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2780 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
2784 rtx addr = XEXP (operands[1], 0);
2785 enum rtx_code code = GET_CODE (addr);
2787 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2789 addr = force_reg (SImode, addr);
2791 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2792 operands[1] = change_address (operands[1], QImode, NULL_RTX);
2793 operands[3] = gen_lowpart (QImode, operands[0]);
2794 operands[0] = gen_lowpart (SImode, operands[0]);
2795 operands[2] = gen_reg_rtx (SImode);
2799 ;; Subroutine to store a half word integer constant into memory.
2800 (define_expand "storeinthi"
2801 [(set (match_operand 0 "" "")
2802 (subreg:QI (match_operand 1 "" "") 0))
2803 (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
2807 HOST_WIDE_INT value = INTVAL (operands[1]);
2808 rtx addr = XEXP (operands[0], 0);
2809 enum rtx_code code = GET_CODE (addr);
2811 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2813 addr = force_reg (SImode, addr);
2815 operands[1] = gen_reg_rtx (SImode);
2816 if (BYTES_BIG_ENDIAN)
2818 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2819 if ((value & 255) == ((value >> 8) & 255))
2820 operands[2] = operands[1];
2823 operands[2] = gen_reg_rtx (SImode);
2824 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2829 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2830 if ((value & 255) == ((value >> 8) & 255))
2831 operands[2] = operands[1];
2834 operands[2] = gen_reg_rtx (SImode);
2835 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2839 operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
2840 operands[0] = change_address (operands[0], QImode, NULL_RTX);
2844 (define_expand "storehi_single_op"
2845 [(set (match_operand:HI 0 "memory_operand" "")
2846 (match_operand:HI 1 "general_operand" ""))]
2849 if (! s_register_operand (operands[1], HImode))
2850 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2853 (define_expand "movhi"
2854 [(set (match_operand:HI 0 "general_operand" "")
2855 (match_operand:HI 1 "general_operand" ""))]
2861 if (! (reload_in_progress || reload_completed))
2863 if (GET_CODE (operands[0]) == MEM)
2867 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2870 if (GET_CODE (operands[1]) == CONST_INT)
2871 emit_insn (gen_storeinthi (operands[0], operands[1]));
2874 if (GET_CODE (operands[1]) == MEM)
2875 operands[1] = force_reg (HImode, operands[1]);
2876 if (BYTES_BIG_ENDIAN)
2877 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
2879 emit_insn (gen_storehi (operands[1], operands[0]));
2883 /* Sign extend a constant, and keep it in an SImode reg. */
2884 else if (GET_CODE (operands[1]) == CONST_INT)
2886 rtx reg = gen_reg_rtx (SImode);
2887 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2889 /* If the constant is already valid, leave it alone. */
2890 if (! const_ok_for_arm (val))
2892 /* If setting all the top bits will make the constant
2893 loadable in a single instruction, then set them.
2894 Otherwise, sign extend the number. */
2896 if (const_ok_for_arm (~ (val | ~0xffff)))
2898 else if (val & 0x8000)
2902 emit_insn (gen_movsi (reg, GEN_INT (val)));
2903 operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
2905 else if (! arm_arch4)
2907 if (GET_CODE (operands[1]) == MEM)
2909 if (TARGET_SHORT_BY_BYTES)
2912 rtx offset = const0_rtx;
2913 rtx reg = gen_reg_rtx (SImode);
2915 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2916 || (GET_CODE (base) == PLUS
2917 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2918 && GET_CODE (base = XEXP (base, 0)) == REG))
2919 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2921 HOST_WIDE_INT new_offset = INTVAL (offset) & ~2;
2924 new = gen_rtx_MEM (SImode,
2925 plus_constant (base, new_offset));
2926 MEM_COPY_ATTRIBUTES (new, operands[1]);
2927 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2928 emit_insn (gen_movsi (reg, new));
2929 if (((INTVAL (offset) & 2) != 0)
2930 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
2932 rtx reg2 = gen_reg_rtx (SImode);
2934 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
2939 emit_insn (gen_movhi_bytes (reg, operands[1]));
2941 operands[1] = gen_lowpart (HImode, reg);
2943 else if (BYTES_BIG_ENDIAN)
2946 rtx offset = const0_rtx;
2948 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2949 || (GET_CODE (base) == PLUS
2950 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2951 && GET_CODE (base = XEXP (base, 0)) == REG))
2952 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2954 rtx reg = gen_reg_rtx (SImode);
2957 if ((INTVAL (offset) & 2) == 2)
2959 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
2960 new = gen_rtx_MEM (SImode,
2961 plus_constant (base, new_offset));
2962 MEM_COPY_ATTRIBUTES (new, operands[1]);
2963 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2964 emit_insn (gen_movsi (reg, new));
2968 new = gen_rtx_MEM (SImode, XEXP (operands[1], 0));
2969 MEM_COPY_ATTRIBUTES (new, operands[1]);
2970 RTX_UNCHANGING_P (new)
2971 = RTX_UNCHANGING_P (operands[1]);
2972 emit_insn (gen_rotated_loadsi (reg, new));
2975 operands[1] = gen_lowpart (HImode, reg);
2979 emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2986 /* Handle loading a large integer during reload */
2987 else if (GET_CODE (operands[1]) == CONST_INT
2988 && ! const_ok_for_arm (INTVAL (operands[1]))
2989 && ! const_ok_for_arm (~INTVAL (operands[1])))
2991 /* Writing a constant to memory needs a scratch, which should
2992 be handled with SECONDARY_RELOADs. */
2993 if (GET_CODE (operands[0]) != REG)
2996 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
2997 emit_insn (gen_movsi (operands[0], operands[1]));
3003 (define_insn "rotated_loadsi"
3004 [(set (match_operand:SI 0 "s_register_operand" "=r")
3005 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
3007 "! TARGET_SHORT_BY_BYTES"
3012 ops[0] = operands[0];
3013 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
3014 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
3017 [(set_attr "type" "load")])
3019 (define_expand "movhi_bytes"
3020 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3022 (zero_extend:SI (match_dup 6)))
3023 (set (match_operand:SI 0 "" "")
3024 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
3029 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3031 mem1 = gen_rtx_MEM (QImode, addr);
3032 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3033 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
3034 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3035 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3036 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
3037 operands[0] = gen_lowpart (SImode, operands[0]);
3039 operands[2] = gen_reg_rtx (SImode);
3040 operands[3] = gen_reg_rtx (SImode);
3043 if (BYTES_BIG_ENDIAN)
3045 operands[4] = operands[2];
3046 operands[5] = operands[3];
3050 operands[4] = operands[3];
3051 operands[5] = operands[2];
3056 (define_expand "movhi_bigend"
3058 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
3061 (ashiftrt:SI (match_dup 2) (const_int 16)))
3062 (set (match_operand:HI 0 "s_register_operand" "")
3063 (subreg:HI (match_dup 3) 0))]
3066 operands[2] = gen_reg_rtx (SImode);
3067 operands[3] = gen_reg_rtx (SImode);
3070 ;; Pattern to recognise insn generated default case above
3072 (define_insn "*movhi_insn_arch4"
3073 [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
3074 (match_operand:HI 1 "general_operand" "rI,K,m,r"))]
3076 && (GET_CODE (operands[1]) != CONST_INT
3077 || const_ok_for_arm (INTVAL (operands[1]))
3078 || const_ok_for_arm (~INTVAL (operands[1])))"
3080 mov%?\\t%0, %1\\t%@ movhi
3081 mvn%?\\t%0, #%B1\\t%@ movhi
3082 ldr%?h\\t%0, %1\\t%@ movhi
3083 str%?h\\t%1, %0\\t%@ movhi"
3084 [(set_attr "type" "*,*,load,store1")])
3086 (define_insn "*movhi_insn_littleend"
3087 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3088 (match_operand:HI 1 "general_operand" "rI,K,m"))]
3090 && ! BYTES_BIG_ENDIAN
3091 && ! TARGET_SHORT_BY_BYTES
3092 && (GET_CODE (operands[1]) != CONST_INT
3093 || const_ok_for_arm (INTVAL (operands[1]))
3094 || const_ok_for_arm (~INTVAL (operands[1])))"
3096 mov%?\\t%0, %1\\t%@ movhi
3097 mvn%?\\t%0, #%B1\\t%@ movhi
3098 ldr%?\\t%0, %1\\t%@ movhi"
3099 [(set_attr "type" "*,*,load")])
3101 (define_insn "*movhi_insn_bigend"
3102 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3103 (match_operand:HI 1 "general_operand" "rI,K,m"))]
3106 && ! TARGET_SHORT_BY_BYTES
3107 && (GET_CODE (operands[1]) != CONST_INT
3108 || const_ok_for_arm (INTVAL (operands[1]))
3109 || const_ok_for_arm (~INTVAL (operands[1])))"
3111 mov%?\\t%0, %1\\t%@ movhi
3112 mvn%?\\t%0, #%B1\\t%@ movhi
3113 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
3114 [(set_attr "type" "*,*,load")
3115 (set_attr "length" "4,4,8")])
3117 (define_insn "*loadhi_si_bigend"
3118 [(set (match_operand:SI 0 "s_register_operand" "=r")
3119 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
3122 && ! TARGET_SHORT_BY_BYTES"
3123 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
3124 [(set_attr "type" "load")])
3126 (define_insn "*movhi_bytes"
3127 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
3128 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
3129 "TARGET_SHORT_BY_BYTES"
3131 mov%?\\t%0, %1\\t%@ movhi
3132 mvn%?\\t%0, #%B1\\t%@ movhi")
3135 (define_expand "reload_outhi"
3136 [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
3137 (match_operand:HI 1 "s_register_operand" "r")
3138 (match_operand:SI 2 "s_register_operand" "=&r")])]
3141 arm_reload_out_hi (operands);
3145 (define_expand "reload_inhi"
3146 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
3147 (match_operand:HI 1 "reload_memory_operand" "o")
3148 (match_operand:SI 2 "s_register_operand" "=&r")])]
3149 "TARGET_SHORT_BY_BYTES"
3151 arm_reload_in_hi (operands);
3155 (define_expand "movqi"
3156 [(set (match_operand:QI 0 "general_operand" "")
3157 (match_operand:QI 1 "general_operand" ""))]
3160 /* Everything except mem = const or mem = mem can be done easily */
3162 if (!(reload_in_progress || reload_completed))
3164 if (GET_CODE (operands[1]) == CONST_INT)
3166 rtx reg = gen_reg_rtx (SImode);
3168 emit_insn (gen_movsi (reg, operands[1]));
3169 operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
3171 if (GET_CODE (operands[0]) == MEM)
3172 operands[1] = force_reg (QImode, operands[1]);
3177 (define_insn "*movqi_insn"
3178 [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
3179 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
3180 "register_operand (operands[0], QImode)
3181 || register_operand (operands[1], QImode)"
3187 [(set_attr "type" "*,*,load,store1")])
3189 (define_expand "movsf"
3190 [(set (match_operand:SF 0 "general_operand" "")
3191 (match_operand:SF 1 "general_operand" ""))]
3194 if (GET_CODE (operands[0]) == MEM)
3195 operands[1] = force_reg (SFmode, operands[1]);
3198 (define_insn "*movsf_hard_insn"
3199 [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
3200 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
3202 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3208 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
3209 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
3211 ldr%?\\t%0, %1\\t%@ float
3212 str%?\\t%1, %0\\t%@ float"
3213 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
3215 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
3217 ;; Exactly the same as above, except that all `f' cases are deleted.
3218 ;; This is necessary to prevent reload from ever trying to use a `f' reg
3219 ;; when -msoft-float.
3221 (define_insn "*movsf_soft_insn"
3222 [(set (match_operand:SF 0 "general_operand" "=r,r,m")
3223 (match_operand:SF 1 "general_operand" "r,mE,r"))]
3225 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3228 ldr%?\\t%0, %1\\t%@ float
3229 str%?\\t%1, %0\\t%@ float"
3230 [(set_attr "length" "4,4,4")
3231 (set_attr "type" "*,load,store1")])
3233 (define_expand "movdf"
3234 [(set (match_operand:DF 0 "general_operand" "")
3235 (match_operand:DF 1 "general_operand" ""))]
3238 if (GET_CODE (operands[0]) == MEM)
3239 operands[1] = force_reg (DFmode, operands[1]);
3242 ;; Reloading a df mode value stored in integer regs to memory can require a
3244 (define_expand "reload_outdf"
3245 [(match_operand:DF 0 "reload_memory_operand" "=o")
3246 (match_operand:DF 1 "s_register_operand" "r")
3247 (match_operand:SI 2 "s_register_operand" "=&r")]
3251 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
3254 operands[2] = XEXP (operands[0], 0);
3255 else if (code == POST_INC || code == PRE_DEC)
3257 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
3258 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
3259 emit_insn (gen_movdi (operands[0], operands[1]));
3262 else if (code == PRE_INC)
3264 rtx reg = XEXP (XEXP (operands[0], 0), 0);
3265 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
3268 else if (code == POST_DEC)
3269 operands[2] = XEXP (XEXP (operands[0], 0), 0);
3271 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
3272 XEXP (XEXP (operands[0], 0), 1)));
3274 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
3277 if (code == POST_DEC)
3278 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
3284 (define_insn "*movdf_hard_insn"
3285 [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
3286 (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
3288 && (GET_CODE (operands[0]) != MEM
3289 || register_operand (operands[1], DFmode))"
3294 switch (which_alternative)
3296 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
3297 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
3298 case 2: case 3: case 4: return output_move_double (operands);
3299 case 5: return \"mvf%?d\\t%0, %1\";
3300 case 6: return \"mnf%?d\\t%0, #%N1\";
3301 case 7: return \"ldf%?d\\t%0, %1\";
3302 case 8: return \"stf%?d\\t%1, %0\";
3303 case 9: return output_mov_double_fpu_from_arm (operands);
3304 case 10: return output_mov_double_arm_from_fpu (operands);
3308 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
3310 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
3312 ;; Software floating point version. This is essentially the same as movdi.
3313 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
3316 (define_insn "*movdf_soft_insn"
3317 [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
3318 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
3320 "* return output_move_double (operands);"
3321 [(set_attr "length" "8,8,8")
3322 (set_attr "type" "*,load,store2")])
3324 (define_expand "movxf"
3325 [(set (match_operand:XF 0 "general_operand" "")
3326 (match_operand:XF 1 "general_operand" ""))]
3327 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3330 ;; Even when the XFmode patterns aren't enabled, we enable this after
3331 ;; reloading so that we can push floating point registers in the prologue.
3333 (define_insn "*movxf_hard_insn"
3334 [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
3335 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
3336 "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
3338 switch (which_alternative)
3340 case 0: return \"mvf%?e\\t%0, %1\";
3341 case 1: return \"mnf%?e\\t%0, #%N1\";
3342 case 2: return \"ldf%?e\\t%0, %1\";
3343 case 3: return \"stf%?e\\t%1, %0\";
3344 case 4: return output_mov_long_double_fpu_from_arm (operands);
3345 case 5: return output_mov_long_double_arm_from_fpu (operands);
3346 case 6: return output_mov_long_double_arm_from_arm (operands);
3349 [(set_attr "length" "4,4,4,4,8,8,12")
3350 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
3353 ;; load- and store-multiple insns
3354 ;; The arm can load/store any set of registers, provided that they are in
3355 ;; ascending order; but that is beyond GCC so stick with what it knows.
3357 (define_expand "load_multiple"
3358 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3359 (match_operand:SI 1 "" ""))
3360 (use (match_operand:SI 2 "" ""))])]
3363 /* Support only fixed point registers */
3364 if (GET_CODE (operands[2]) != CONST_INT
3365 || INTVAL (operands[2]) > 14
3366 || INTVAL (operands[2]) < 2
3367 || GET_CODE (operands[1]) != MEM
3368 || GET_CODE (operands[0]) != REG
3369 || REGNO (operands[0]) > 14
3370 || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
3374 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
3375 force_reg (SImode, XEXP (operands[1], 0)),
3376 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
3377 MEM_IN_STRUCT_P(operands[1]),
3378 MEM_SCALAR_P (operands[1]));
3381 ;; Load multiple with write-back
3383 (define_insn "*ldmsi_postinc"
3384 [(match_parallel 0 "load_multiple_operation"
3385 [(set (match_operand:SI 1 "s_register_operand" "+r")
3386 (plus:SI (match_dup 1)
3387 (match_operand:SI 2 "const_int_operand" "n")))
3388 (set (match_operand:SI 3 "s_register_operand" "=r")
3389 (mem:SI (match_dup 1)))])]
3390 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3394 int count = XVECLEN (operands[0], 0);
3396 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3397 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
3398 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
3400 output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
3404 [(set_attr "type" "load")])
3406 ;; Ordinary load multiple
3408 (define_insn "*ldmsi"
3409 [(match_parallel 0 "load_multiple_operation"
3410 [(set (match_operand:SI 1 "s_register_operand" "=r")
3411 (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
3416 int count = XVECLEN (operands[0], 0);
3418 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3419 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
3420 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
3422 output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
3426 [(set_attr "type" "load")])
3428 (define_expand "store_multiple"
3429 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3430 (match_operand:SI 1 "" ""))
3431 (use (match_operand:SI 2 "" ""))])]
3434 /* Support only fixed point registers */
3435 if (GET_CODE (operands[2]) != CONST_INT
3436 || INTVAL (operands[2]) > 14
3437 || INTVAL (operands[2]) < 2
3438 || GET_CODE (operands[1]) != REG
3439 || GET_CODE (operands[0]) != MEM
3440 || REGNO (operands[1]) > 14
3441 || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
3445 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
3446 force_reg (SImode, XEXP (operands[0], 0)),
3447 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
3448 MEM_IN_STRUCT_P(operands[0]),
3449 MEM_SCALAR_P (operands[0]));
3452 ;; Store multiple with write-back
3454 (define_insn "*stmsi_postinc"
3455 [(match_parallel 0 "store_multiple_operation"
3456 [(set (match_operand:SI 1 "s_register_operand" "+r")
3457 (plus:SI (match_dup 1)
3458 (match_operand:SI 2 "const_int_operand" "n")))
3459 (set (mem:SI (match_dup 1))
3460 (match_operand:SI 3 "s_register_operand" "r"))])]
3461 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3465 int count = XVECLEN (operands[0], 0);
3467 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3468 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
3469 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
3471 output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
3476 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3477 (const_string "store2")
3478 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
3479 (const_string "store3")]
3480 (const_string "store4")))])
3482 ;; Ordinary store multiple
3484 (define_insn "*stmsi"
3485 [(match_parallel 0 "store_multiple_operation"
3486 [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
3487 (match_operand:SI 1 "s_register_operand" "r"))])]
3492 int count = XVECLEN (operands[0], 0);
3494 ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
3495 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
3496 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
3498 output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
3503 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
3504 (const_string "store2")
3505 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3506 (const_string "store3")]
3507 (const_string "store4")))])
3509 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
3510 ;; We could let this apply for blocks of less than this, but it clobbers so
3511 ;; many registers that there is then probably a better way.
3513 (define_expand "movstrqi"
3514 [(match_operand:BLK 0 "general_operand" "")
3515 (match_operand:BLK 1 "general_operand" "")
3516 (match_operand:SI 2 "const_int_operand" "")
3517 (match_operand:SI 3 "const_int_operand" "")]
3520 if (arm_gen_movstrqi (operands))
3526 ;; Comparison and test insns
3528 (define_expand "cmpsi"
3529 [(match_operand:SI 0 "s_register_operand" "")
3530 (match_operand:SI 1 "arm_add_operand" "")]
3534 arm_compare_op0 = operands[0];
3535 arm_compare_op1 = operands[1];
3541 (define_expand "cmpsf"
3542 [(match_operand:SF 0 "s_register_operand" "")
3543 (match_operand:SF 1 "fpu_rhs_operand" "")]
3547 arm_compare_op0 = operands[0];
3548 arm_compare_op1 = operands[1];
3554 (define_expand "cmpdf"
3555 [(match_operand:DF 0 "s_register_operand" "")
3556 (match_operand:DF 1 "fpu_rhs_operand" "")]
3560 arm_compare_op0 = operands[0];
3561 arm_compare_op1 = operands[1];
3567 (define_expand "cmpxf"
3568 [(match_operand:XF 0 "s_register_operand" "")
3569 (match_operand:XF 1 "fpu_rhs_operand" "")]
3570 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3573 arm_compare_op0 = operands[0];
3574 arm_compare_op1 = operands[1];
3580 (define_insn "*cmpsi_insn"
3582 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3583 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3588 [(set_attr "conds" "set")])
3590 (define_insn "*cmpsi_shiftsi"
3592 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3593 (match_operator:SI 3 "shift_operator"
3594 [(match_operand:SI 1 "s_register_operand" "r")
3595 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3598 [(set_attr "conds" "set")])
3600 (define_insn "*cmpsi_shiftsi_swp"
3601 [(set (reg:CC_SWP 24)
3602 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
3603 [(match_operand:SI 1 "s_register_operand" "r")
3604 (match_operand:SI 2 "reg_or_int_operand" "rM")])
3605 (match_operand:SI 0 "s_register_operand" "r")))]
3608 [(set_attr "conds" "set")])
3610 (define_insn "*cmpsi_neg_shiftsi"
3612 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3613 (neg:SI (match_operator:SI 3 "shift_operator"
3614 [(match_operand:SI 1 "s_register_operand" "r")
3615 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3618 [(set_attr "conds" "set")])
3620 (define_insn "*cmpsf_insn"
3622 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3623 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3628 [(set_attr "conds" "set")
3629 (set_attr "type" "f_2_r")])
3631 (define_insn "*cmpdf_insn"
3633 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3634 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3639 [(set_attr "conds" "set")
3640 (set_attr "type" "f_2_r")])
3642 (define_insn "*cmpesfdf_df"
3644 (compare:CCFP (float_extend:DF
3645 (match_operand:SF 0 "s_register_operand" "f,f"))
3646 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3651 [(set_attr "conds" "set")
3652 (set_attr "type" "f_2_r")])
3654 (define_insn "*cmpdf_esfdf"
3656 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3658 (match_operand:SF 1 "s_register_operand" "f"))))]
3661 [(set_attr "conds" "set")
3662 (set_attr "type" "f_2_r")])
3664 (define_insn "*cmpxf_insn"
3666 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3667 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3668 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3672 [(set_attr "conds" "set")
3673 (set_attr "type" "f_2_r")])
3675 (define_insn "*cmpsf_trap"
3676 [(set (reg:CCFPE 24)
3677 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3678 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3683 [(set_attr "conds" "set")
3684 (set_attr "type" "f_2_r")])
3686 (define_insn "*cmpdf_trap"
3687 [(set (reg:CCFPE 24)
3688 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3689 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3694 [(set_attr "conds" "set")
3695 (set_attr "type" "f_2_r")])
3697 (define_insn "*cmp_esfdf_df_trap"
3698 [(set (reg:CCFPE 24)
3699 (compare:CCFPE (float_extend:DF
3700 (match_operand:SF 0 "s_register_operand" "f,f"))
3701 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3706 [(set_attr "conds" "set")
3707 (set_attr "type" "f_2_r")])
3709 (define_insn "*cmp_df_esfdf_trap"
3710 [(set (reg:CCFPE 24)
3711 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3713 (match_operand:SF 1 "s_register_operand" "f"))))]
3716 [(set_attr "conds" "set")
3717 (set_attr "type" "f_2_r")])
3719 (define_insn "*cmpxf_trap"
3720 [(set (reg:CCFPE 24)
3721 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3722 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3723 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3727 [(set_attr "conds" "set")
3728 (set_attr "type" "f_2_r")])
3730 ; This insn allows redundant compares to be removed by cse, nothing should
3731 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3732 ; is deleted later on. The match_dup will match the mode here, so that
3733 ; mode changes of the condition codes aren't lost by this even though we don't
3734 ; specify what they are.
3736 (define_insn "*deleted_compare"
3737 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3739 "\\t%@ deleted compare"
3740 [(set_attr "conds" "set")
3741 (set_attr "length" "0")])
3744 ;; Conditional branch insns
3746 (define_expand "beq"
3748 (if_then_else (eq (match_dup 1) (const_int 0))
3749 (label_ref (match_operand 0 "" ""))
3754 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3759 (define_expand "bne"
3761 (if_then_else (ne (match_dup 1) (const_int 0))
3762 (label_ref (match_operand 0 "" ""))
3767 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3772 (define_expand "bgt"
3774 (if_then_else (gt (match_dup 1) (const_int 0))
3775 (label_ref (match_operand 0 "" ""))
3780 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3785 (define_expand "ble"
3787 (if_then_else (le (match_dup 1) (const_int 0))
3788 (label_ref (match_operand 0 "" ""))
3793 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3798 (define_expand "bge"
3800 (if_then_else (ge (match_dup 1) (const_int 0))
3801 (label_ref (match_operand 0 "" ""))
3806 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3811 (define_expand "blt"
3813 (if_then_else (lt (match_dup 1) (const_int 0))
3814 (label_ref (match_operand 0 "" ""))
3819 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3824 (define_expand "bgtu"
3826 (if_then_else (gtu (match_dup 1) (const_int 0))
3827 (label_ref (match_operand 0 "" ""))
3832 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3837 (define_expand "bleu"
3839 (if_then_else (leu (match_dup 1) (const_int 0))
3840 (label_ref (match_operand 0 "" ""))
3845 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3850 (define_expand "bgeu"
3852 (if_then_else (geu (match_dup 1) (const_int 0))
3853 (label_ref (match_operand 0 "" ""))
3858 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3863 (define_expand "bltu"
3865 (if_then_else (ltu (match_dup 1) (const_int 0))
3866 (label_ref (match_operand 0 "" ""))
3871 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3876 ;; patterns to match conditional branch insns
3878 (define_insn "*condbranch"
3880 (if_then_else (match_operator 1 "comparison_operator"
3881 [(match_operand 2 "cc_register" "") (const_int 0)])
3882 (label_ref (match_operand 0 "" ""))
3887 extern int arm_ccfsm_state;
3889 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3891 arm_ccfsm_state += 2;
3894 return \"b%d1\\t%l0\";
3896 [(set_attr "conds" "use")])
3898 (define_insn "*condbranch_reversed"
3900 (if_then_else (match_operator 1 "comparison_operator"
3901 [(match_operand 2 "cc_register" "") (const_int 0)])
3903 (label_ref (match_operand 0 "" ""))))]
3907 extern int arm_ccfsm_state;
3909 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3911 arm_ccfsm_state += 2;
3914 return \"b%D1\\t%l0\";
3916 [(set_attr "conds" "use")])
3921 (define_expand "seq"
3922 [(set (match_operand:SI 0 "s_register_operand" "=r")
3923 (eq:SI (match_dup 1) (const_int 0)))]
3927 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3932 (define_expand "sne"
3933 [(set (match_operand:SI 0 "s_register_operand" "=r")
3934 (ne:SI (match_dup 1) (const_int 0)))]
3938 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3943 (define_expand "sgt"
3944 [(set (match_operand:SI 0 "s_register_operand" "=r")
3945 (gt:SI (match_dup 1) (const_int 0)))]
3949 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3954 (define_expand "sle"
3955 [(set (match_operand:SI 0 "s_register_operand" "=r")
3956 (le:SI (match_dup 1) (const_int 0)))]
3960 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3965 (define_expand "sge"
3966 [(set (match_operand:SI 0 "s_register_operand" "=r")
3967 (ge:SI (match_dup 1) (const_int 0)))]
3971 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3976 (define_expand "slt"
3977 [(set (match_operand:SI 0 "s_register_operand" "=r")
3978 (lt:SI (match_dup 1) (const_int 0)))]
3982 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3987 (define_expand "sgtu"
3988 [(set (match_operand:SI 0 "s_register_operand" "=r")
3989 (gtu:SI (match_dup 1) (const_int 0)))]
3993 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3998 (define_expand "sleu"
3999 [(set (match_operand:SI 0 "s_register_operand" "=r")
4000 (leu:SI (match_dup 1) (const_int 0)))]
4004 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
4009 (define_expand "sgeu"
4010 [(set (match_operand:SI 0 "s_register_operand" "=r")
4011 (geu:SI (match_dup 1) (const_int 0)))]
4015 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
4020 (define_expand "sltu"
4021 [(set (match_operand:SI 0 "s_register_operand" "=r")
4022 (ltu:SI (match_dup 1) (const_int 0)))]
4026 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
4031 (define_insn "*mov_scc"
4032 [(set (match_operand:SI 0 "s_register_operand" "=r")
4033 (match_operator:SI 1 "comparison_operator"
4034 [(match_operand 2 "cc_register" "") (const_int 0)]))]
4036 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
4037 [(set_attr "conds" "use")
4038 (set_attr "length" "8")])
4040 (define_insn "*mov_negscc"
4041 [(set (match_operand:SI 0 "s_register_operand" "=r")
4042 (neg:SI (match_operator:SI 1 "comparison_operator"
4043 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4045 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
4046 [(set_attr "conds" "use")
4047 (set_attr "length" "8")])
4049 (define_insn "*mov_notscc"
4050 [(set (match_operand:SI 0 "s_register_operand" "=r")
4051 (not:SI (match_operator:SI 1 "comparison_operator"
4052 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4054 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
4055 [(set_attr "conds" "use")
4056 (set_attr "length" "8")])
4059 ;; Conditional move insns
4061 (define_expand "movsicc"
4062 [(set (match_operand:SI 0 "s_register_operand" "")
4063 (if_then_else:SI (match_operand 1 "comparison_operator" "")
4064 (match_operand:SI 2 "arm_not_operand" "")
4065 (match_operand:SI 3 "arm_not_operand" "")))]
4069 enum rtx_code code = GET_CODE (operands[1]);
4070 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4073 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4076 (define_expand "movsfcc"
4077 [(set (match_operand:SF 0 "s_register_operand" "")
4078 (if_then_else:SF (match_operand 1 "comparison_operator" "")
4079 (match_operand:SF 2 "s_register_operand" "")
4080 (match_operand:SF 3 "nonmemory_operand" "")))]
4084 enum rtx_code code = GET_CODE (operands[1]);
4087 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
4088 Otherwise, ensure it is a valid FP add operand */
4089 if ((! TARGET_HARD_FLOAT)
4090 || (! fpu_add_operand (operands[3], SFmode)))
4091 operands[3] = force_reg (SFmode, operands[3]);
4093 ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4096 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4099 (define_expand "movdfcc"
4100 [(set (match_operand:DF 0 "s_register_operand" "")
4101 (if_then_else:DF (match_operand 1 "comparison_operator" "")
4102 (match_operand:DF 2 "s_register_operand" "")
4103 (match_operand:DF 3 "fpu_add_operand" "")))]
4107 enum rtx_code code = GET_CODE (operands[1]);
4108 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4111 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4114 (define_insn "*movsicc_insn"
4115 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
4117 (match_operator 3 "comparison_operator"
4118 [(match_operand 4 "cc_register" "") (const_int 0)])
4119 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
4120 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
4127 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
4128 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
4129 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
4130 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
4131 [(set_attr "length" "4,4,4,4,8,8,8,8")
4132 (set_attr "conds" "use")])
4134 (define_insn "*movsfcc_hard_insn"
4135 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4137 (match_operator 3 "comparison_operator"
4138 [(match_operand 4 "cc_register" "") (const_int 0)])
4139 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4140 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4147 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
4148 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
4149 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
4150 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
4151 [(set_attr "length" "4,4,4,4,8,8,8,8")
4152 (set_attr "type" "ffarith")
4153 (set_attr "conds" "use")])
4155 (define_insn "*movsfcc_soft_insn"
4156 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
4157 (if_then_else:SF (match_operator 3 "comparison_operator"
4158 [(match_operand 4 "cc_register" "") (const_int 0)])
4159 (match_operand:SF 1 "s_register_operand" "0,r")
4160 (match_operand:SF 2 "s_register_operand" "r,0")))]
4165 [(set_attr "conds" "use")])
4167 (define_insn "*movdfcc_insn"
4168 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4170 (match_operator 3 "comparison_operator"
4171 [(match_operand 4 "cc_register" "") (const_int 0)])
4172 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4173 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4180 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
4181 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
4182 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
4183 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
4184 [(set_attr "length" "4,4,4,4,8,8,8,8")
4185 (set_attr "type" "ffarith")
4186 (set_attr "conds" "use")])
4188 ;; Jump and linkage insns
4192 (label_ref (match_operand 0 "" "")))]
4196 extern int arm_ccfsm_state;
4198 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4200 arm_ccfsm_state += 2;
4203 return \"b%?\\t%l0\";
4206 (define_expand "call"
4207 [(parallel [(call (match_operand 0 "memory_operand" "")
4208 (match_operand 1 "general_operand" ""))
4209 (clobber (reg:SI 14))])]
4213 (define_insn "*call_reg"
4214 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
4215 (match_operand 1 "" "g"))
4216 (clobber (reg:SI 14))]
4219 return output_call (operands);
4221 ;; length is worst case, normally it is only two
4222 [(set_attr "length" "12")
4223 (set_attr "type" "call")])
4225 (define_insn "*call_mem"
4226 [(call (mem:SI (match_operand 0 "memory_operand" "m"))
4227 (match_operand 1 "general_operand" "g"))
4228 (clobber (reg:SI 14))]
4231 return output_call_mem (operands);
4233 [(set_attr "length" "12")
4234 (set_attr "type" "call")])
4236 (define_expand "call_value"
4237 [(parallel [(set (match_operand 0 "" "=rf")
4238 (call (match_operand 1 "memory_operand" "m")
4239 (match_operand 2 "general_operand" "g")))
4240 (clobber (reg:SI 14))])]
4244 (define_insn "*call_value_reg"
4245 [(set (match_operand 0 "" "=rf")
4246 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4247 (match_operand 2 "general_operand" "g")))
4248 (clobber (reg:SI 14))]
4251 return output_call (&operands[1]);
4253 [(set_attr "length" "12")
4254 (set_attr "type" "call")])
4256 (define_insn "*call_value_mem"
4257 [(set (match_operand 0 "" "=rf")
4258 (call (mem:SI (match_operand 1 "memory_operand" "m"))
4259 (match_operand 2 "general_operand" "g")))
4260 (clobber (reg:SI 14))]
4261 "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
4263 return output_call_mem (&operands[1]);
4265 [(set_attr "length" "12")
4266 (set_attr "type" "call")])
4268 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
4269 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
4271 (define_insn "*call_symbol"
4272 [(call (mem:SI (match_operand:SI 0 "" "X"))
4273 (match_operand:SI 1 "general_operand" "g"))
4274 (clobber (reg:SI 14))]
4275 "GET_CODE (operands[0]) == SYMBOL_REF"
4277 [(set_attr "type" "call")])
4279 (define_insn "*call_value_symbol"
4280 [(set (match_operand 0 "s_register_operand" "=rf")
4281 (call (mem:SI (match_operand:SI 1 "" "X"))
4282 (match_operand:SI 2 "general_operand" "g")))
4283 (clobber (reg:SI 14))]
4284 "GET_CODE(operands[1]) == SYMBOL_REF"
4286 [(set_attr "type" "call")])
4288 ;; Often the return insn will be the same as loading from memory, so set attr
4289 (define_insn "return"
4291 "USE_RETURN_INSN(FALSE)"
4294 extern int arm_ccfsm_state;
4296 if (arm_ccfsm_state == 2)
4298 arm_ccfsm_state += 2;
4301 return output_return_instruction (NULL, TRUE, FALSE);
4303 [(set_attr "type" "load")])
4305 (define_insn "*cond_return"
4307 (if_then_else (match_operator 0 "comparison_operator"
4308 [(match_operand 1 "cc_register" "") (const_int 0)])
4311 "USE_RETURN_INSN(TRUE)"
4314 extern int arm_ccfsm_state;
4316 if (arm_ccfsm_state == 2)
4318 arm_ccfsm_state += 2;
4321 return output_return_instruction (operands[0], TRUE, FALSE);
4323 [(set_attr "conds" "use")
4324 (set_attr "type" "load")])
4326 (define_insn "*cond_return_inverted"
4328 (if_then_else (match_operator 0 "comparison_operator"
4329 [(match_operand 1 "cc_register" "") (const_int 0)])
4332 "USE_RETURN_INSN(TRUE)"
4335 extern int arm_ccfsm_state;
4337 if (arm_ccfsm_state == 2)
4339 arm_ccfsm_state += 2;
4342 return output_return_instruction (operands[0], TRUE, TRUE);
4344 [(set_attr "conds" "use")
4345 (set_attr "type" "load")])
4347 ;; Call subroutine returning any type.
4349 (define_expand "untyped_call"
4350 [(parallel [(call (match_operand 0 "" "")
4352 (match_operand 1 "" "")
4353 (match_operand 2 "" "")])]
4359 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
4361 for (i = 0; i < XVECLEN (operands[2], 0); i++)
4363 rtx set = XVECEXP (operands[2], 0, i);
4364 emit_move_insn (SET_DEST (set), SET_SRC (set));
4367 /* The optimizer does not know that the call sets the function value
4368 registers we stored in the result block. We avoid problems by
4369 claiming that all hard registers are used and clobbered at this
4371 emit_insn (gen_blockage ());
4376 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
4377 ;; all of memory. This blocks insns from being moved across this point.
4379 (define_insn "blockage"
4380 [(unspec_volatile [(const_int 0)] 0)]
4383 [(set_attr "length" "0")
4384 (set_attr "type" "block")])
4386 (define_expand "casesi"
4387 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
4388 (match_operand:SI 1 "const_int_operand" "") ; lower bound
4389 (match_operand:SI 2 "const_int_operand" "") ; total range
4390 (match_operand:SI 3 "" "") ; table label
4391 (match_operand:SI 4 "" "")] ; Out of range label
4396 if (operands[1] != const0_rtx)
4398 reg = gen_reg_rtx (SImode);
4399 emit_insn (gen_addsi3 (reg, operands[0],
4400 GEN_INT (-INTVAL (operands[1]))));
4404 if (! const_ok_for_arm (INTVAL (operands[2])))
4405 operands[2] = force_reg (SImode, operands[2]);
4407 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
4412 ;; The USE in this pattern is needed to tell flow analysis that this is
4413 ;; a CASESI insn. It has no other purpose.
4414 (define_insn "casesi_internal"
4415 [(parallel [(set (pc)
4417 (leu (match_operand:SI 0 "s_register_operand" "r")
4418 (match_operand:SI 1 "arm_rhs_operand" "rI"))
4419 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
4420 (label_ref (match_operand 2 "" ""))))
4421 (label_ref (match_operand 3 "" ""))))
4422 (use (label_ref (match_dup 2)))])]
4426 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
4427 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
4429 [(set_attr "conds" "clob")
4430 (set_attr "length" "12")])
4432 (define_insn "indirect_jump"
4434 (match_operand:SI 0 "s_register_operand" "r"))]
4436 "mov%?\\t%|pc, %0\\t%@ indirect jump")
4438 (define_insn "*load_indirect_jump"
4440 (match_operand:SI 0 "memory_operand" "m"))]
4442 "ldr%?\\t%|pc, %0\\t%@ indirect jump"
4443 [(set_attr "type" "load")])
4450 "mov%?\\tr0, r0\\t%@ nop")
4452 ;; Patterns to allow combination of arithmetic, cond code and shifts
4454 (define_insn "*arith_shiftsi"
4455 [(set (match_operand:SI 0 "s_register_operand" "=r")
4456 (match_operator:SI 1 "shiftable_operator"
4457 [(match_operator:SI 3 "shift_operator"
4458 [(match_operand:SI 4 "s_register_operand" "r")
4459 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4460 (match_operand:SI 2 "s_register_operand" "r")]))]
4462 "%i1%?\\t%0, %2, %4%S3")
4464 (define_insn "*arith_shiftsi_compare0"
4465 [(set (reg:CC_NOOV 24)
4466 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4467 [(match_operator:SI 3 "shift_operator"
4468 [(match_operand:SI 4 "s_register_operand" "r")
4469 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4470 (match_operand:SI 2 "s_register_operand" "r")])
4472 (set (match_operand:SI 0 "s_register_operand" "=r")
4473 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4476 "%i1%?s\\t%0, %2, %4%S3"
4477 [(set_attr "conds" "set")])
4479 (define_insn "*arith_shiftsi_compare0_scratch"
4480 [(set (reg:CC_NOOV 24)
4481 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4482 [(match_operator:SI 3 "shift_operator"
4483 [(match_operand:SI 4 "s_register_operand" "r")
4484 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4485 (match_operand:SI 2 "s_register_operand" "r")])
4487 (clobber (match_scratch:SI 0 "=r"))]
4489 "%i1%?s\\t%0, %2, %4%S3"
4490 [(set_attr "conds" "set")])
4492 (define_insn "*sub_shiftsi"
4493 [(set (match_operand:SI 0 "s_register_operand" "=r")
4494 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4495 (match_operator:SI 2 "shift_operator"
4496 [(match_operand:SI 3 "s_register_operand" "r")
4497 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4499 "sub%?\\t%0, %1, %3%S2")
4501 (define_insn "*sub_shiftsi_compare0"
4502 [(set (reg:CC_NOOV 24)
4504 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4505 (match_operator:SI 2 "shift_operator"
4506 [(match_operand:SI 3 "s_register_operand" "r")
4507 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4509 (set (match_operand:SI 0 "s_register_operand" "=r")
4510 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4513 "sub%?s\\t%0, %1, %3%S2"
4514 [(set_attr "conds" "set")])
4516 (define_insn "*sub_shiftsi_compare0_scratch"
4517 [(set (reg:CC_NOOV 24)
4519 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4520 (match_operator:SI 2 "shift_operator"
4521 [(match_operand:SI 3 "s_register_operand" "r")
4522 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4524 (clobber (match_scratch:SI 0 "=r"))]
4526 "sub%?s\\t%0, %1, %3%S2"
4527 [(set_attr "conds" "set")])
4529 ;; These variants of the above insns can occur if the first operand is the
4530 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
4531 ;; seem to be a way around it. Most of the predicates have to be null
4532 ;; because the format can be generated part way through reload, so
4533 ;; if we don't match it as soon as it becomes available, reload doesn't know
4534 ;; how to reload pseudos that haven't got hard registers; the constraints will
4535 ;; sort everything out.
4537 (define_insn "*reload_mulsi3"
4538 [(set (match_operand:SI 0 "" "=&r")
4539 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4540 [(match_operand:SI 3 "" "r")
4541 (match_operand:SI 4 "" "rM")])
4542 (match_operand:SI 2 "" "r"))
4543 (match_operand:SI 1 "const_int_operand" "n")))]
4544 "reload_in_progress"
4546 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4547 operands[2] = operands[1];
4548 operands[1] = operands[0];
4549 return output_add_immediate (operands);
4551 ; we have no idea how long the add_immediate is, it could be up to 4.
4552 [(set_attr "length" "20")])
4554 (define_insn "*reload_mulsi_compare0"
4555 [(set (reg:CC_NOOV 24)
4556 (compare:CC_NOOV (plus:SI
4558 (match_operator:SI 5 "shift_operator"
4559 [(match_operand:SI 3 "" "r")
4560 (match_operand:SI 4 "" "rM")])
4561 (match_operand:SI 1 "" "r"))
4562 (match_operand:SI 2 "const_int_operand" "n"))
4564 (set (match_operand:SI 0 "" "=&r")
4565 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4568 "reload_in_progress"
4570 output_add_immediate (operands);
4571 return \"add%?s\\t%0, %0, %3%S5\";
4573 [(set_attr "conds" "set")
4574 (set_attr "length" "20")])
4576 (define_insn "*reload_mulsi_compare0_scratch"
4577 [(set (reg:CC_NOOV 24)
4578 (compare:CC_NOOV (plus:SI
4580 (match_operator:SI 5 "shift_operator"
4581 [(match_operand:SI 3 "" "r")
4582 (match_operand:SI 4 "" "rM")])
4583 (match_operand:SI 1 "" "r"))
4584 (match_operand:SI 2 "const_int_operand" "n"))
4586 (clobber (match_scratch:SI 0 "=&r"))]
4587 "reload_in_progress"
4589 output_add_immediate (operands);
4590 return \"add%?s\\t%0, %0, %3%S5\";
4592 [(set_attr "conds" "set")
4593 (set_attr "length" "20")])
4595 ;; These are similar, but are needed when the mla pattern contains the
4596 ;; eliminated register as operand 3.
4598 (define_insn "*reload_muladdsi"
4599 [(set (match_operand:SI 0 "" "=&r,&r")
4600 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4601 (match_operand:SI 2 "" "r,r"))
4602 (match_operand:SI 3 "" "r,r"))
4603 (match_operand:SI 4 "const_int_operand" "n,n")))]
4604 "reload_in_progress"
4606 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4607 operands[2] = operands[4];
4608 operands[1] = operands[0];
4609 return output_add_immediate (operands);
4611 [(set_attr "length" "20")
4612 (set_attr "type" "mult")])
4614 (define_insn "*reload_muladdsi_compare0"
4615 [(set (reg:CC_NOOV 24)
4616 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4617 (match_operand:SI 3 "" "r")
4618 (match_operand:SI 4 "" "r"))
4619 (match_operand:SI 1 "" "r"))
4620 (match_operand:SI 2 "const_int_operand" "n"))
4622 (set (match_operand:SI 0 "" "=&r")
4623 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4625 "reload_in_progress"
4627 output_add_immediate (operands);
4628 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4631 [(set_attr "length" "20")
4632 (set_attr "conds" "set")
4633 (set_attr "type" "mult")])
4635 (define_insn "*reload_muladdsi_compare0_scratch"
4636 [(set (reg:CC_NOOV 24)
4637 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4638 (match_operand:SI 3 "" "r")
4639 (match_operand:SI 4 "" "r"))
4640 (match_operand:SI 1 "" "r"))
4641 (match_operand:SI 2 "const_int_operand" "n"))
4643 (clobber (match_scratch:SI 0 "=&r"))]
4644 "reload_in_progress"
4646 output_add_immediate (operands);
4647 return \"mla%?s\\t%0, %3, %4, %0\";
4649 [(set_attr "length" "20")
4650 (set_attr "conds" "set")
4651 (set_attr "type" "mult")])
4655 (define_insn "*and_scc"
4656 [(set (match_operand:SI 0 "s_register_operand" "=r")
4657 (and:SI (match_operator 1 "comparison_operator"
4658 [(match_operand 3 "cc_register" "") (const_int 0)])
4659 (match_operand:SI 2 "s_register_operand" "r")))]
4661 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
4662 [(set_attr "conds" "use")
4663 (set_attr "length" "8")])
4665 (define_insn "*ior_scc"
4666 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4667 (ior:SI (match_operator 2 "comparison_operator"
4668 [(match_operand 3 "cc_register" "") (const_int 0)])
4669 (match_operand:SI 1 "s_register_operand" "0,?r")))]
4673 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
4674 [(set_attr "conds" "use")
4675 (set_attr "length" "4,8")])
4677 (define_insn "*compare_scc"
4678 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4679 (match_operator 1 "comparison_operator"
4680 [(match_operand:SI 2 "s_register_operand" "r,r")
4681 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
4682 (clobber (reg:CC 24))]
4685 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4686 return \"mov\\t%0, %2, lsr #31\";
4688 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4689 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4691 if (GET_CODE (operands[1]) == NE)
4693 if (which_alternative == 1)
4694 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4695 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4697 if (which_alternative == 1)
4698 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4700 output_asm_insn (\"cmp\\t%2, %3\", operands);
4701 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4703 [(set_attr "conds" "clob")
4704 (set_attr "length" "12")])
4706 (define_insn "*cond_move"
4707 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4708 (if_then_else:SI (match_operator 3 "equality_operator"
4709 [(match_operator 4 "comparison_operator"
4710 [(match_operand 5 "cc_register" "") (const_int 0)])
4712 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4713 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4716 if (GET_CODE (operands[3]) == NE)
4718 if (which_alternative != 1)
4719 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4720 if (which_alternative != 0)
4721 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4724 if (which_alternative != 0)
4725 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4726 if (which_alternative != 1)
4727 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4730 [(set_attr "conds" "use")
4731 (set_attr "length" "4,4,8")])
4733 (define_insn "*cond_arith"
4734 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4735 (match_operator:SI 5 "shiftable_operator"
4736 [(match_operator:SI 4 "comparison_operator"
4737 [(match_operand:SI 2 "s_register_operand" "r,r")
4738 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4739 (match_operand:SI 1 "s_register_operand" "0,?r")]))
4740 (clobber (reg:CC 24))]
4743 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4744 return \"%i5\\t%0, %1, %2, lsr #31\";
4746 output_asm_insn (\"cmp\\t%2, %3\", operands);
4747 if (GET_CODE (operands[5]) == AND)
4748 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4749 else if (GET_CODE (operands[5]) == MINUS)
4750 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4751 else if (which_alternative != 0)
4752 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4753 return \"%i5%d4\\t%0, %1, #1\";
4755 [(set_attr "conds" "clob")
4756 (set_attr "length" "12")])
4758 (define_insn "*cond_sub"
4759 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4760 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4761 (match_operator:SI 4 "comparison_operator"
4762 [(match_operand:SI 2 "s_register_operand" "r,r")
4763 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4764 (clobber (reg:CC 24))]
4767 output_asm_insn (\"cmp\\t%2, %3\", operands);
4768 if (which_alternative != 0)
4769 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4770 return \"sub%d4\\t%0, %1, #1\";
4772 [(set_attr "conds" "clob")
4773 (set_attr "length" "8,12")])
4775 (define_insn "*cmp_ite0"
4776 [(set (match_operand 6 "dominant_cc_register" "")
4779 (match_operator 4 "comparison_operator"
4780 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4781 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4782 (match_operator:SI 5 "comparison_operator"
4783 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4784 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4790 char* opcodes[4][2] =
4792 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
4793 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
4794 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
4795 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
4796 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
4799 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
4801 return opcodes[which_alternative][swap];
4804 [(set_attr "conds" "set")
4805 (set_attr "length" "8")])
4807 (define_insn "*cmp_ite1"
4808 [(set (match_operand 6 "dominant_cc_register" "")
4811 (match_operator 4 "comparison_operator"
4812 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4813 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4814 (match_operator:SI 5 "comparison_operator"
4815 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4816 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4822 char* opcodes[4][2] =
4824 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
4825 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
4826 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
4827 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
4828 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
4831 comparison_dominates_p (GET_CODE (operands[5]),
4832 reverse_condition (GET_CODE (operands[4])));
4834 return opcodes[which_alternative][swap];
4837 [(set_attr "conds" "set")
4838 (set_attr "length" "8")])
4840 (define_insn "*negscc"
4841 [(set (match_operand:SI 0 "s_register_operand" "=r")
4842 (neg:SI (match_operator 3 "comparison_operator"
4843 [(match_operand:SI 1 "s_register_operand" "r")
4844 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4845 (clobber (reg:CC 24))]
4848 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4849 return \"mov\\t%0, %1, asr #31\";
4851 if (GET_CODE (operands[3]) == NE)
4852 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4854 if (GET_CODE (operands[3]) == GT)
4855 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4857 output_asm_insn (\"cmp\\t%1, %2\", operands);
4858 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4859 return \"mvn%d3\\t%0, #0\";
4861 [(set_attr "conds" "clob")
4862 (set_attr "length" "12")])
4864 (define_insn "movcond"
4865 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4867 (match_operator 5 "comparison_operator"
4868 [(match_operand:SI 3 "s_register_operand" "r,r,r")
4869 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4870 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4871 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4872 (clobber (reg:CC 24))]
4875 if (GET_CODE (operands[5]) == LT
4876 && (operands[4] == const0_rtx))
4878 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4880 if (operands[2] == const0_rtx)
4881 return \"and\\t%0, %1, %3, asr #31\";
4882 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4884 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4886 if (operands[1] == const0_rtx)
4887 return \"bic\\t%0, %2, %3, asr #31\";
4888 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4890 /* The only case that falls through to here is when both ops 1 & 2
4894 if (GET_CODE (operands[5]) == GE
4895 && (operands[4] == const0_rtx))
4897 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4899 if (operands[2] == const0_rtx)
4900 return \"bic\\t%0, %1, %3, asr #31\";
4901 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4903 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4905 if (operands[1] == const0_rtx)
4906 return \"and\\t%0, %2, %3, asr #31\";
4907 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4909 /* The only case that falls through to here is when both ops 1 & 2
4912 if (GET_CODE (operands[4]) == CONST_INT
4913 && !const_ok_for_arm (INTVAL (operands[4])))
4914 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4916 output_asm_insn (\"cmp\\t%3, %4\", operands);
4917 if (which_alternative != 0)
4918 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4919 if (which_alternative != 1)
4920 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4923 [(set_attr "conds" "clob")
4924 (set_attr "length" "8,8,12")])
4926 (define_insn "*ifcompare_plus_move"
4927 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4928 (if_then_else:SI (match_operator 6 "comparison_operator"
4929 [(match_operand:SI 4 "s_register_operand" "r,r")
4930 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4932 (match_operand:SI 2 "s_register_operand" "r,r")
4933 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
4934 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
4935 (clobber (reg:CC 24))]
4938 [(set_attr "conds" "clob")
4939 (set_attr "length" "8,12")])
4941 (define_insn "*if_plus_move"
4942 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4944 (match_operator 4 "comparison_operator"
4945 [(match_operand 5 "cc_register" "") (const_int 0)])
4947 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
4948 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
4949 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
4953 sub%d4\\t%0, %2, #%n3
4954 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4955 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
4956 [(set_attr "conds" "use")
4957 (set_attr "length" "4,4,8,8")
4958 (set_attr "type" "*,*,*,*")])
4960 (define_insn "*ifcompare_move_plus"
4961 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4962 (if_then_else:SI (match_operator 6 "comparison_operator"
4963 [(match_operand:SI 4 "s_register_operand" "r,r")
4964 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4965 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4967 (match_operand:SI 2 "s_register_operand" "r,r")
4968 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4969 (clobber (reg:CC 24))]
4972 [(set_attr "conds" "clob")
4973 (set_attr "length" "8,12")])
4975 (define_insn "*if_move_plus"
4976 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4978 (match_operator 4 "comparison_operator"
4979 [(match_operand 5 "cc_register" "") (const_int 0)])
4980 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4982 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
4983 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
4987 sub%D4\\t%0, %2, #%n3
4988 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4989 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
4990 [(set_attr "conds" "use")
4991 (set_attr "length" "4,4,8,8")
4992 (set_attr "type" "*,*,*,*")])
4994 (define_insn "*ifcompare_arith_arith"
4995 [(set (match_operand:SI 0 "s_register_operand" "=r")
4996 (if_then_else:SI (match_operator 9 "comparison_operator"
4997 [(match_operand:SI 5 "s_register_operand" "r")
4998 (match_operand:SI 6 "arm_add_operand" "rIL")])
4999 (match_operator:SI 8 "shiftable_operator"
5000 [(match_operand:SI 1 "s_register_operand" "r")
5001 (match_operand:SI 2 "arm_rhs_operand" "rI")])
5002 (match_operator:SI 7 "shiftable_operator"
5003 [(match_operand:SI 3 "s_register_operand" "r")
5004 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
5005 (clobber (reg:CC 24))]
5008 [(set_attr "conds" "clob")
5009 (set_attr "length" "12")])
5011 (define_insn "*if_arith_arith"
5012 [(set (match_operand:SI 0 "s_register_operand" "=r")
5013 (if_then_else:SI (match_operator 5 "comparison_operator"
5014 [(match_operand 8 "cc_register" "") (const_int 0)])
5015 (match_operator:SI 6 "shiftable_operator"
5016 [(match_operand:SI 1 "s_register_operand" "r")
5017 (match_operand:SI 2 "arm_rhs_operand" "rI")])
5018 (match_operator:SI 7 "shiftable_operator"
5019 [(match_operand:SI 3 "s_register_operand" "r")
5020 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
5022 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
5023 [(set_attr "conds" "use")
5024 (set_attr "length" "8")])
5026 (define_insn "*ifcompare_arith_move"
5027 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5028 (if_then_else:SI (match_operator 6 "comparison_operator"
5029 [(match_operand:SI 2 "s_register_operand" "r,r")
5030 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
5031 (match_operator:SI 7 "shiftable_operator"
5032 [(match_operand:SI 4 "s_register_operand" "r,r")
5033 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
5034 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5035 (clobber (reg:CC 24))]
5038 /* If we have an operation where (op x 0) is the identity operation and
5039 the conditional operator is LT or GE and we are comparing against zero and
5040 everything is in registers then we can do this in two instructions */
5041 if (operands[3] == const0_rtx
5042 && GET_CODE (operands[7]) != AND
5043 && GET_CODE (operands[5]) == REG
5044 && GET_CODE (operands[1]) == REG
5045 && REGNO (operands[1]) == REGNO (operands[4])
5046 && REGNO (operands[4]) != REGNO (operands[0]))
5048 if (GET_CODE (operands[6]) == LT)
5049 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5050 else if (GET_CODE (operands[6]) == GE)
5051 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5053 if (GET_CODE (operands[3]) == CONST_INT
5054 && !const_ok_for_arm (INTVAL (operands[3])))
5055 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
5057 output_asm_insn (\"cmp\\t%2, %3\", operands);
5058 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
5059 if (which_alternative != 0)
5060 return \"mov%D6\\t%0, %1\";
5063 [(set_attr "conds" "clob")
5064 (set_attr "length" "8,12")])
5066 (define_insn "*if_arith_move"
5067 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5068 (if_then_else:SI (match_operator 4 "comparison_operator"
5069 [(match_operand 6 "cc_register" "") (const_int 0)])
5070 (match_operator:SI 5 "shiftable_operator"
5071 [(match_operand:SI 2 "s_register_operand" "r,r")
5072 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
5073 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
5077 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
5078 [(set_attr "conds" "use")
5079 (set_attr "length" "4,8")
5080 (set_attr "type" "*,*")])
5082 (define_insn "*ifcompare_move_arith"
5083 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5084 (if_then_else:SI (match_operator 6 "comparison_operator"
5085 [(match_operand:SI 4 "s_register_operand" "r,r")
5086 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5087 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5088 (match_operator:SI 7 "shiftable_operator"
5089 [(match_operand:SI 2 "s_register_operand" "r,r")
5090 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
5091 (clobber (reg:CC 24))]
5094 /* If we have an operation where (op x 0) is the identity operation and
5095 the conditional operator is LT or GE and we are comparing against zero and
5096 everything is in registers then we can do this in two instructions */
5097 if (operands[5] == const0_rtx
5098 && GET_CODE (operands[7]) != AND
5099 && GET_CODE (operands[3]) == REG
5100 && GET_CODE (operands[1]) == REG
5101 && REGNO (operands[1]) == REGNO (operands[2])
5102 && REGNO (operands[2]) != REGNO (operands[0]))
5104 if (GET_CODE (operands[6]) == GE)
5105 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5106 else if (GET_CODE (operands[6]) == LT)
5107 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5110 if (GET_CODE (operands[5]) == CONST_INT
5111 && !const_ok_for_arm (INTVAL (operands[5])))
5112 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5114 output_asm_insn (\"cmp\\t%4, %5\", operands);
5116 if (which_alternative != 0)
5117 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
5118 return \"%I7%D6\\t%0, %2, %3\";
5120 [(set_attr "conds" "clob")
5121 (set_attr "length" "8,12")])
5123 (define_insn "*if_move_arith"
5124 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5126 (match_operator 4 "comparison_operator"
5127 [(match_operand 6 "cc_register" "") (const_int 0)])
5128 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5129 (match_operator:SI 5 "shiftable_operator"
5130 [(match_operand:SI 2 "s_register_operand" "r,r")
5131 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
5135 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
5136 [(set_attr "conds" "use")
5137 (set_attr "length" "4,8")
5138 (set_attr "type" "*,*")])
5140 (define_insn "*ifcompare_move_not"
5141 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5143 (match_operator 5 "comparison_operator"
5144 [(match_operand:SI 3 "s_register_operand" "r,r")
5145 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5146 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5148 (match_operand:SI 2 "s_register_operand" "r,r"))))
5149 (clobber (reg:CC 24))]
5152 [(set_attr "conds" "clob")
5153 (set_attr "length" "8,12")])
5155 (define_insn "*if_move_not"
5156 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5158 (match_operator 4 "comparison_operator"
5159 [(match_operand 3 "cc_register" "") (const_int 0)])
5160 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5161 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5165 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
5166 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
5167 [(set_attr "conds" "use")
5168 (set_attr "length" "4,8,8")])
5170 (define_insn "*ifcompare_not_move"
5171 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5173 (match_operator 5 "comparison_operator"
5174 [(match_operand:SI 3 "s_register_operand" "r,r")
5175 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5177 (match_operand:SI 2 "s_register_operand" "r,r"))
5178 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5179 (clobber (reg:CC 24))]
5182 [(set_attr "conds" "clob")
5183 (set_attr "length" "8,12")])
5185 (define_insn "*if_not_move"
5186 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5188 (match_operator 4 "comparison_operator"
5189 [(match_operand 3 "cc_register" "") (const_int 0)])
5190 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5191 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5195 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
5196 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
5197 [(set_attr "conds" "use")
5198 (set_attr "length" "4,8,8")])
5200 (define_insn "*ifcompare_shift_move"
5201 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5203 (match_operator 6 "comparison_operator"
5204 [(match_operand:SI 4 "s_register_operand" "r,r")
5205 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5206 (match_operator:SI 7 "shift_operator"
5207 [(match_operand:SI 2 "s_register_operand" "r,r")
5208 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
5209 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5210 (clobber (reg:CC 24))]
5213 [(set_attr "conds" "clob")
5214 (set_attr "length" "8,12")])
5216 (define_insn "*if_shift_move"
5217 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5219 (match_operator 5 "comparison_operator"
5220 [(match_operand 6 "cc_register" "") (const_int 0)])
5221 (match_operator:SI 4 "shift_operator"
5222 [(match_operand:SI 2 "s_register_operand" "r,r,r")
5223 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
5224 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5228 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
5229 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
5230 [(set_attr "conds" "use")
5231 (set_attr "length" "4,8,8")])
5233 (define_insn "*ifcompare_move_shift"
5234 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5236 (match_operator 6 "comparison_operator"
5237 [(match_operand:SI 4 "s_register_operand" "r,r")
5238 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5239 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5240 (match_operator:SI 7 "shift_operator"
5241 [(match_operand:SI 2 "s_register_operand" "r,r")
5242 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
5243 (clobber (reg:CC 24))]
5246 [(set_attr "conds" "clob")
5247 (set_attr "length" "8,12")])
5249 (define_insn "*if_move_shift"
5250 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5252 (match_operator 5 "comparison_operator"
5253 [(match_operand 6 "cc_register" "") (const_int 0)])
5254 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5255 (match_operator:SI 4 "shift_operator"
5256 [(match_operand:SI 2 "s_register_operand" "r,r,r")
5257 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
5261 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
5262 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
5263 [(set_attr "conds" "use")
5264 (set_attr "length" "4,8,8")])
5266 (define_insn "*ifcompare_shift_shift"
5267 [(set (match_operand:SI 0 "s_register_operand" "=r")
5269 (match_operator 7 "comparison_operator"
5270 [(match_operand:SI 5 "s_register_operand" "r")
5271 (match_operand:SI 6 "arm_add_operand" "rIL")])
5272 (match_operator:SI 8 "shift_operator"
5273 [(match_operand:SI 1 "s_register_operand" "r")
5274 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5275 (match_operator:SI 9 "shift_operator"
5276 [(match_operand:SI 3 "s_register_operand" "r")
5277 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
5278 (clobber (reg:CC 24))]
5281 [(set_attr "conds" "clob")
5282 (set_attr "length" "12")])
5284 (define_insn "*if_shift_shift"
5285 [(set (match_operand:SI 0 "s_register_operand" "=r")
5287 (match_operator 5 "comparison_operator"
5288 [(match_operand 8 "cc_register" "") (const_int 0)])
5289 (match_operator:SI 6 "shift_operator"
5290 [(match_operand:SI 1 "s_register_operand" "r")
5291 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5292 (match_operator:SI 7 "shift_operator"
5293 [(match_operand:SI 3 "s_register_operand" "r")
5294 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
5296 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
5297 [(set_attr "conds" "use")
5298 (set_attr "length" "8")])
5300 (define_insn "*ifcompare_not_arith"
5301 [(set (match_operand:SI 0 "s_register_operand" "=r")
5303 (match_operator 6 "comparison_operator"
5304 [(match_operand:SI 4 "s_register_operand" "r")
5305 (match_operand:SI 5 "arm_add_operand" "rIL")])
5306 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5307 (match_operator:SI 7 "shiftable_operator"
5308 [(match_operand:SI 2 "s_register_operand" "r")
5309 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5310 (clobber (reg:CC 24))]
5313 [(set_attr "conds" "clob")
5314 (set_attr "length" "12")])
5316 (define_insn "*if_not_arith"
5317 [(set (match_operand:SI 0 "s_register_operand" "=r")
5319 (match_operator 5 "comparison_operator"
5320 [(match_operand 4 "cc_register" "") (const_int 0)])
5321 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5322 (match_operator:SI 6 "shiftable_operator"
5323 [(match_operand:SI 2 "s_register_operand" "r")
5324 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
5326 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
5327 [(set_attr "conds" "use")
5328 (set_attr "length" "8")])
5330 (define_insn "*ifcompare_arith_not"
5331 [(set (match_operand:SI 0 "s_register_operand" "=r")
5333 (match_operator 6 "comparison_operator"
5334 [(match_operand:SI 4 "s_register_operand" "r")
5335 (match_operand:SI 5 "arm_add_operand" "rIL")])
5336 (match_operator:SI 7 "shiftable_operator"
5337 [(match_operand:SI 2 "s_register_operand" "r")
5338 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5339 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5340 (clobber (reg:CC 24))]
5343 [(set_attr "conds" "clob")
5344 (set_attr "length" "12")])
5346 (define_insn "*if_arith_not"
5347 [(set (match_operand:SI 0 "s_register_operand" "=r")
5349 (match_operator 5 "comparison_operator"
5350 [(match_operand 4 "cc_register" "") (const_int 0)])
5351 (match_operator:SI 6 "shiftable_operator"
5352 [(match_operand:SI 2 "s_register_operand" "r")
5353 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5354 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
5356 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
5357 [(set_attr "conds" "use")
5358 (set_attr "length" "8")])
5360 (define_insn "*ifcompare_neg_move"
5361 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5363 (match_operator 5 "comparison_operator"
5364 [(match_operand:SI 3 "s_register_operand" "r,r")
5365 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5366 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
5367 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5368 (clobber (reg:CC 24))]
5371 [(set_attr "conds" "clob")
5372 (set_attr "length" "8,12")])
5374 (define_insn "*if_neg_move"
5375 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5377 (match_operator 4 "comparison_operator"
5378 [(match_operand 3 "cc_register" "") (const_int 0)])
5379 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5380 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5384 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
5385 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
5386 [(set_attr "conds" "use")
5387 (set_attr "length" "4,8,8")])
5389 (define_insn "*ifcompare_move_neg"
5390 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5392 (match_operator 5 "comparison_operator"
5393 [(match_operand:SI 3 "s_register_operand" "r,r")
5394 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5395 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5396 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
5397 (clobber (reg:CC 24))]
5400 [(set_attr "conds" "clob")
5401 (set_attr "length" "8,12")])
5403 (define_insn "*if_move_neg"
5404 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5406 (match_operator 4 "comparison_operator"
5407 [(match_operand 3 "cc_register" "") (const_int 0)])
5408 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5409 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5413 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
5414 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
5415 [(set_attr "conds" "use")
5416 (set_attr "length" "4,8,8")])
5418 (define_insn "*arith_adjacentmem"
5419 [(set (match_operand:SI 0 "s_register_operand" "=r")
5420 (match_operator:SI 1 "shiftable_operator"
5421 [(match_operand:SI 2 "memory_operand" "m")
5422 (match_operand:SI 3 "memory_operand" "m")]))
5423 (clobber (match_scratch:SI 4 "=r"))]
5424 "adjacent_mem_locations (operands[2], operands[3])"
5429 int val1 = 0, val2 = 0;
5431 if (REGNO (operands[0]) > REGNO (operands[4]))
5433 ldm[1] = operands[4];
5434 ldm[2] = operands[0];
5438 ldm[1] = operands[0];
5439 ldm[2] = operands[4];
5441 if (GET_CODE (XEXP (operands[2], 0)) != REG)
5442 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5443 if (GET_CODE (XEXP (operands[3], 0)) != REG)
5444 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5445 arith[0] = operands[0];
5446 arith[3] = operands[1];
5460 ldm[0] = ops[0] = operands[4];
5461 ops[1] = XEXP (XEXP (operands[2], 0), 0);
5462 ops[2] = XEXP (XEXP (operands[2], 0), 1);
5463 output_add_immediate (ops);
5465 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5467 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5471 ldm[0] = XEXP (operands[3], 0);
5473 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5475 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5479 ldm[0] = XEXP (operands[2], 0);
5481 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5483 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5485 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
5489 [(set_attr "length" "12")
5490 (set_attr "type" "load")])
5492 ;; the arm can support extended pre-inc instructions
5494 ;; In all these cases, we use operands 0 and 1 for the register being
5495 ;; incremented because those are the operands that local-alloc will
5496 ;; tie and these are the pair most likely to be tieable (and the ones
5497 ;; that will benefit the most).
5499 ;; We reject the frame pointer if it occurs anywhere in these patterns since
5500 ;; elimination will cause too many headaches.
5502 (define_insn "*strqi_preinc"
5503 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5504 (match_operand:SI 2 "index_operand" "rJ")))
5505 (match_operand:QI 3 "s_register_operand" "r"))
5506 (set (match_operand:SI 0 "s_register_operand" "=r")
5507 (plus:SI (match_dup 1) (match_dup 2)))]
5508 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5509 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5510 && (GET_CODE (operands[2]) != REG
5511 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5512 "str%?b\\t%3, [%0, %2]!"
5513 [(set_attr "type" "store1")])
5515 (define_insn "*strqi_predec"
5516 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5517 (match_operand:SI 2 "s_register_operand" "r")))
5518 (match_operand:QI 3 "s_register_operand" "r"))
5519 (set (match_operand:SI 0 "s_register_operand" "=r")
5520 (minus:SI (match_dup 1) (match_dup 2)))]
5521 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5522 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5523 && (GET_CODE (operands[2]) != REG
5524 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5525 "str%?b\\t%3, [%0, -%2]!"
5526 [(set_attr "type" "store1")])
5528 (define_insn "*loadqi_preinc"
5529 [(set (match_operand:QI 3 "s_register_operand" "=r")
5530 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5531 (match_operand:SI 2 "index_operand" "rJ"))))
5532 (set (match_operand:SI 0 "s_register_operand" "=r")
5533 (plus:SI (match_dup 1) (match_dup 2)))]
5534 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5535 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5536 && (GET_CODE (operands[2]) != REG
5537 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5538 "ldr%?b\\t%3, [%0, %2]!"
5539 [(set_attr "type" "load")])
5541 (define_insn "*loadqi_predec"
5542 [(set (match_operand:QI 3 "s_register_operand" "=r")
5543 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5544 (match_operand:SI 2 "s_register_operand" "r"))))
5545 (set (match_operand:SI 0 "s_register_operand" "=r")
5546 (minus:SI (match_dup 1) (match_dup 2)))]
5547 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5548 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5549 && (GET_CODE (operands[2]) != REG
5550 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5551 "ldr%?b\\t%3, [%0, -%2]!"
5552 [(set_attr "type" "load")])
5554 (define_insn "*loadqisi_preinc"
5555 [(set (match_operand:SI 3 "s_register_operand" "=r")
5557 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5558 (match_operand:SI 2 "index_operand" "rJ")))))
5559 (set (match_operand:SI 0 "s_register_operand" "=r")
5560 (plus:SI (match_dup 1) (match_dup 2)))]
5561 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5562 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5563 && (GET_CODE (operands[2]) != REG
5564 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5565 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
5566 [(set_attr "type" "load")])
5568 (define_insn "*loadqisi_predec"
5569 [(set (match_operand:SI 3 "s_register_operand" "=r")
5571 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5572 (match_operand:SI 2 "s_register_operand" "r")))))
5573 (set (match_operand:SI 0 "s_register_operand" "=r")
5574 (minus:SI (match_dup 1) (match_dup 2)))]
5575 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5576 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5577 && (GET_CODE (operands[2]) != REG
5578 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5579 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
5580 [(set_attr "type" "load")])
5582 (define_insn "*strsi_preinc"
5583 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5584 (match_operand:SI 2 "index_operand" "rJ")))
5585 (match_operand:SI 3 "s_register_operand" "r"))
5586 (set (match_operand:SI 0 "s_register_operand" "=r")
5587 (plus:SI (match_dup 1) (match_dup 2)))]
5588 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5589 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5590 && (GET_CODE (operands[2]) != REG
5591 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5592 "str%?\\t%3, [%0, %2]!"
5593 [(set_attr "type" "store1")])
5595 (define_insn "*strqi_predec"
5596 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5597 (match_operand:SI 2 "s_register_operand" "r")))
5598 (match_operand:SI 3 "s_register_operand" "r"))
5599 (set (match_operand:SI 0 "s_register_operand" "=r")
5600 (minus:SI (match_dup 1) (match_dup 2)))]
5601 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5602 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5603 && (GET_CODE (operands[2]) != REG
5604 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5605 "str%?\\t%3, [%0, -%2]!"
5606 [(set_attr "type" "store1")])
5608 (define_insn "*loadsi_preinc"
5609 [(set (match_operand:SI 3 "s_register_operand" "=r")
5610 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5611 (match_operand:SI 2 "index_operand" "rJ"))))
5612 (set (match_operand:SI 0 "s_register_operand" "=r")
5613 (plus:SI (match_dup 1) (match_dup 2)))]
5614 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5615 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5616 && (GET_CODE (operands[2]) != REG
5617 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5618 "ldr%?\\t%3, [%0, %2]!"
5619 [(set_attr "type" "load")])
5621 (define_insn "*loadsi_predec"
5622 [(set (match_operand:SI 3 "s_register_operand" "=r")
5623 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5624 (match_operand:SI 2 "s_register_operand" "r"))))
5625 (set (match_operand:SI 0 "s_register_operand" "=r")
5626 (minus:SI (match_dup 1) (match_dup 2)))]
5627 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5628 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5629 && (GET_CODE (operands[2]) != REG
5630 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5631 "ldr%?\\t%3, [%0, -%2]!"
5632 [(set_attr "type" "load")])
5634 (define_insn "*loadhi_preinc"
5635 [(set (match_operand:HI 3 "s_register_operand" "=r")
5636 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5637 (match_operand:SI 2 "index_operand" "rJ"))))
5638 (set (match_operand:SI 0 "s_register_operand" "=r")
5639 (plus:SI (match_dup 1) (match_dup 2)))]
5640 "(! BYTES_BIG_ENDIAN)
5641 && ! TARGET_SHORT_BY_BYTES
5642 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5643 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5644 && (GET_CODE (operands[2]) != REG
5645 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5646 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5647 [(set_attr "type" "load")])
5649 (define_insn "*loadhi_predec"
5650 [(set (match_operand:HI 3 "s_register_operand" "=r")
5651 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5652 (match_operand:SI 2 "s_register_operand" "r"))))
5653 (set (match_operand:SI 0 "s_register_operand" "=r")
5654 (minus:SI (match_dup 1) (match_dup 2)))]
5655 "(!BYTES_BIG_ENDIAN)
5656 && ! TARGET_SHORT_BY_BYTES
5657 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5658 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5659 && (GET_CODE (operands[2]) != REG
5660 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5661 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5662 [(set_attr "type" "load")])
5664 (define_insn "*strqi_shiftpreinc"
5665 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5666 [(match_operand:SI 3 "s_register_operand" "r")
5667 (match_operand:SI 4 "const_shift_operand" "n")])
5668 (match_operand:SI 1 "s_register_operand" "0")))
5669 (match_operand:QI 5 "s_register_operand" "r"))
5670 (set (match_operand:SI 0 "s_register_operand" "=r")
5671 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5673 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5674 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5675 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5676 "str%?b\\t%5, [%0, %3%S2]!"
5677 [(set_attr "type" "store1")])
5679 (define_insn "*strqi_shiftpredec"
5680 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5681 (match_operator:SI 2 "shift_operator"
5682 [(match_operand:SI 3 "s_register_operand" "r")
5683 (match_operand:SI 4 "const_shift_operand" "n")])))
5684 (match_operand:QI 5 "s_register_operand" "r"))
5685 (set (match_operand:SI 0 "s_register_operand" "=r")
5686 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5688 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5689 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5690 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5691 "str%?b\\t%5, [%0, -%3%S2]!"
5692 [(set_attr "type" "store1")])
5694 (define_insn "*loadqi_shiftpreinc"
5695 [(set (match_operand:QI 5 "s_register_operand" "=r")
5696 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5697 [(match_operand:SI 3 "s_register_operand" "r")
5698 (match_operand:SI 4 "const_shift_operand" "n")])
5699 (match_operand:SI 1 "s_register_operand" "0"))))
5700 (set (match_operand:SI 0 "s_register_operand" "=r")
5701 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5703 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5704 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5705 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5706 "ldr%?b\\t%5, [%0, %3%S2]!"
5707 [(set_attr "type" "load")])
5709 (define_insn "*loadqi_shiftpredec"
5710 [(set (match_operand:QI 5 "s_register_operand" "=r")
5711 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5712 (match_operator:SI 2 "shift_operator"
5713 [(match_operand:SI 3 "s_register_operand" "r")
5714 (match_operand:SI 4 "const_shift_operand" "n")]))))
5715 (set (match_operand:SI 0 "s_register_operand" "=r")
5716 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5718 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5719 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5720 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5721 "ldr%?b\\t%5, [%0, -%3%S2]!"
5722 [(set_attr "type" "load")])
5724 (define_insn "*strsi_shiftpreinc"
5725 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5726 [(match_operand:SI 3 "s_register_operand" "r")
5727 (match_operand:SI 4 "const_shift_operand" "n")])
5728 (match_operand:SI 1 "s_register_operand" "0")))
5729 (match_operand:SI 5 "s_register_operand" "r"))
5730 (set (match_operand:SI 0 "s_register_operand" "=r")
5731 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5733 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5734 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5735 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5736 "str%?\\t%5, [%0, %3%S2]!"
5737 [(set_attr "type" "store1")])
5739 (define_insn "*strsi_shiftpredec"
5740 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5741 (match_operator:SI 2 "shift_operator"
5742 [(match_operand:SI 3 "s_register_operand" "r")
5743 (match_operand:SI 4 "const_shift_operand" "n")])))
5744 (match_operand:SI 5 "s_register_operand" "r"))
5745 (set (match_operand:SI 0 "s_register_operand" "=r")
5746 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5748 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5749 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5750 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5751 "str%?\\t%5, [%0, -%3%S2]!"
5752 [(set_attr "type" "store1")])
5754 (define_insn "*loadqi_shiftpreinc"
5755 [(set (match_operand:SI 5 "s_register_operand" "=r")
5756 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5757 [(match_operand:SI 3 "s_register_operand" "r")
5758 (match_operand:SI 4 "const_shift_operand" "n")])
5759 (match_operand:SI 1 "s_register_operand" "0"))))
5760 (set (match_operand:SI 0 "s_register_operand" "=r")
5761 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5763 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5764 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5765 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5766 "ldr%?\\t%5, [%0, %3%S2]!"
5767 [(set_attr "type" "load")])
5769 (define_insn "*loadqi_shiftpredec"
5770 [(set (match_operand:SI 5 "s_register_operand" "=r")
5771 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5772 (match_operator:SI 2 "shift_operator"
5773 [(match_operand:SI 3 "s_register_operand" "r")
5774 (match_operand:SI 4 "const_shift_operand" "n")]))))
5775 (set (match_operand:SI 0 "s_register_operand" "=r")
5776 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5778 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5779 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5780 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5781 "ldr%?\\t%5, [%0, -%3%S2]!"
5782 [(set_attr "type" "load")])
5784 (define_insn "*loadhi_shiftpreinc"
5785 [(set (match_operand:HI 5 "s_register_operand" "=r")
5786 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5787 [(match_operand:SI 3 "s_register_operand" "r")
5788 (match_operand:SI 4 "const_shift_operand" "n")])
5789 (match_operand:SI 1 "s_register_operand" "0"))))
5790 (set (match_operand:SI 0 "s_register_operand" "=r")
5791 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5793 "(! BYTES_BIG_ENDIAN)
5794 && ! TARGET_SHORT_BY_BYTES
5795 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5796 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5797 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5798 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5799 [(set_attr "type" "load")])
5801 (define_insn "*loadhi_shiftpredec"
5802 [(set (match_operand:HI 5 "s_register_operand" "=r")
5803 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5804 (match_operator:SI 2 "shift_operator"
5805 [(match_operand:SI 3 "s_register_operand" "r")
5806 (match_operand:SI 4 "const_shift_operand" "n")]))))
5807 (set (match_operand:SI 0 "s_register_operand" "=r")
5808 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5810 "(! BYTES_BIG_ENDIAN)
5811 && ! TARGET_SHORT_BY_BYTES
5812 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5813 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5814 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5815 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5816 [(set_attr "type" "load")])
5818 ; It can also support extended post-inc expressions, but combine doesn't
5820 ; It doesn't seem worth adding peepholes for anything but the most common
5821 ; cases since, unlike combine, the increment must immediately follow the load
5822 ; for this pattern to match.
5823 ; When loading we must watch to see that the base register isn't trampled by
5824 ; the load. In such cases this isn't a post-inc expression.
5827 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5828 (match_operand:QI 2 "s_register_operand" "r"))
5830 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5832 "str%?b\\t%2, [%0], %1")
5835 [(set (match_operand:QI 0 "s_register_operand" "=r")
5836 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5838 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5839 "REGNO(operands[0]) != REGNO(operands[1])
5840 && (GET_CODE (operands[2]) != REG
5841 || REGNO(operands[0]) != REGNO (operands[2]))"
5842 "ldr%?b\\t%0, [%1], %2")
5845 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5846 (match_operand:SI 2 "s_register_operand" "r"))
5848 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5850 "str%?\\t%2, [%0], %1")
5853 [(set (match_operand:HI 0 "s_register_operand" "=r")
5854 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5856 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5857 "(! BYTES_BIG_ENDIAN)
5858 && ! TARGET_SHORT_BY_BYTES
5859 && REGNO(operands[0]) != REGNO(operands[1])
5860 && (GET_CODE (operands[2]) != REG
5861 || REGNO(operands[0]) != REGNO (operands[2]))"
5862 "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5865 [(set (match_operand:SI 0 "s_register_operand" "=r")
5866 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5868 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5869 "REGNO(operands[0]) != REGNO(operands[1])
5870 && (GET_CODE (operands[2]) != REG
5871 || REGNO(operands[0]) != REGNO (operands[2]))"
5872 "ldr%?\\t%0, [%1], %2")
5875 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5876 (match_operand:SI 1 "index_operand" "rJ")))
5877 (match_operand:QI 2 "s_register_operand" "r"))
5878 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5880 "str%?b\\t%2, [%0, %1]!")
5883 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5884 [(match_operand:SI 0 "s_register_operand" "r")
5885 (match_operand:SI 1 "const_int_operand" "n")])
5886 (match_operand:SI 2 "s_register_operand" "+r")))
5887 (match_operand:QI 3 "s_register_operand" "r"))
5888 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5891 "str%?b\\t%3, [%2, %0%S4]!")
5893 ; This pattern is never tried by combine, so do it as a peephole
5896 [(set (match_operand:SI 0 "s_register_operand" "=r")
5897 (match_operand:SI 1 "s_register_operand" "r"))
5899 (compare:CC (match_dup 1) (const_int 0)))]
5901 "sub%?s\\t%0, %1, #0"
5902 [(set_attr "conds" "set")])
5904 ; Peepholes to spot possible load- and store-multiples, if the ordering is
5905 ; reversed, check that the memory references aren't volatile.
5908 [(set (match_operand:SI 0 "s_register_operand" "=r")
5909 (match_operand:SI 4 "memory_operand" "m"))
5910 (set (match_operand:SI 1 "s_register_operand" "=r")
5911 (match_operand:SI 5 "memory_operand" "m"))
5912 (set (match_operand:SI 2 "s_register_operand" "=r")
5913 (match_operand:SI 6 "memory_operand" "m"))
5914 (set (match_operand:SI 3 "s_register_operand" "=r")
5915 (match_operand:SI 7 "memory_operand" "m"))]
5916 "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5918 return emit_ldm_seq (operands, 4);
5922 [(set (match_operand:SI 0 "s_register_operand" "=r")
5923 (match_operand:SI 3 "memory_operand" "m"))
5924 (set (match_operand:SI 1 "s_register_operand" "=r")
5925 (match_operand:SI 4 "memory_operand" "m"))
5926 (set (match_operand:SI 2 "s_register_operand" "=r")
5927 (match_operand:SI 5 "memory_operand" "m"))]
5928 "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5930 return emit_ldm_seq (operands, 3);
5934 [(set (match_operand:SI 0 "s_register_operand" "=r")
5935 (match_operand:SI 2 "memory_operand" "m"))
5936 (set (match_operand:SI 1 "s_register_operand" "=r")
5937 (match_operand:SI 3 "memory_operand" "m"))]
5938 "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5940 return emit_ldm_seq (operands, 2);
5944 [(set (match_operand:SI 4 "memory_operand" "=m")
5945 (match_operand:SI 0 "s_register_operand" "r"))
5946 (set (match_operand:SI 5 "memory_operand" "=m")
5947 (match_operand:SI 1 "s_register_operand" "r"))
5948 (set (match_operand:SI 6 "memory_operand" "=m")
5949 (match_operand:SI 2 "s_register_operand" "r"))
5950 (set (match_operand:SI 7 "memory_operand" "=m")
5951 (match_operand:SI 3 "s_register_operand" "r"))]
5952 "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5954 return emit_stm_seq (operands, 4);
5958 [(set (match_operand:SI 3 "memory_operand" "=m")
5959 (match_operand:SI 0 "s_register_operand" "r"))
5960 (set (match_operand:SI 4 "memory_operand" "=m")
5961 (match_operand:SI 1 "s_register_operand" "r"))
5962 (set (match_operand:SI 5 "memory_operand" "=m")
5963 (match_operand:SI 2 "s_register_operand" "r"))]
5964 "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5966 return emit_stm_seq (operands, 3);
5970 [(set (match_operand:SI 2 "memory_operand" "=m")
5971 (match_operand:SI 0 "s_register_operand" "r"))
5972 (set (match_operand:SI 3 "memory_operand" "=m")
5973 (match_operand:SI 1 "s_register_operand" "r"))]
5974 "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5976 return emit_stm_seq (operands, 2);
5979 ;; A call followed by return can be replaced by restoring the regs and
5980 ;; jumping to the subroutine, provided we aren't passing the address of
5981 ;; any of our local variables. If we call alloca then this is unsafe
5982 ;; since restoring the frame frees the memory, which is not what we want.
5983 ;; Sometimes the return might have been targeted by the final prescan:
5984 ;; if so then emit a proper return insn as well.
5985 ;; Unfortunately, if the frame pointer is required, we don't know if the
5986 ;; current function has any implicit stack pointer adjustments that will
5987 ;; be restored by the return: we can't therefore do a tail call.
5988 ;; Another unfortunate that we can't handle is if current_function_args_size
5989 ;; is non-zero: in this case elimination of the argument pointer assumed
5990 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5994 [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5995 (match_operand:SI 1 "general_operand" "g"))
5996 (clobber (reg:SI 14))])
5998 "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
5999 && !get_frame_size () && !current_function_calls_alloca
6000 && !frame_pointer_needed && !current_function_args_size)"
6003 extern rtx arm_target_insn;
6004 extern int arm_ccfsm_state;
6006 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6008 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6009 output_return_instruction (NULL, TRUE, FALSE);
6010 arm_ccfsm_state = 0;
6011 arm_target_insn = NULL;
6014 output_return_instruction (NULL, FALSE, FALSE);
6015 return \"b%?\\t%a0\";
6017 [(set_attr "type" "call")
6018 (set_attr "length" "8")])
6021 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6022 (call (mem:SI (match_operand:SI 1 "" "X"))
6023 (match_operand:SI 2 "general_operand" "g")))
6024 (clobber (reg:SI 14))])
6026 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
6027 && !get_frame_size () && !current_function_calls_alloca
6028 && !frame_pointer_needed && !current_function_args_size)"
6031 extern rtx arm_target_insn;
6032 extern int arm_ccfsm_state;
6034 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6036 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6037 output_return_instruction (NULL, TRUE, FALSE);
6038 arm_ccfsm_state = 0;
6039 arm_target_insn = NULL;
6042 output_return_instruction (NULL, FALSE, FALSE);
6043 return \"b%?\\t%a1\";
6045 [(set_attr "type" "call")
6046 (set_attr "length" "8")])
6048 ;; As above but when this function is not void, we must be returning the
6049 ;; result of the called subroutine.
6052 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6053 (call (mem:SI (match_operand:SI 1 "" "X"))
6054 (match_operand:SI 2 "general_operand" "g")))
6055 (clobber (reg:SI 14))])
6058 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
6059 && !get_frame_size () && !current_function_calls_alloca
6060 && !frame_pointer_needed && !current_function_args_size)"
6063 extern rtx arm_target_insn;
6064 extern int arm_ccfsm_state;
6066 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6068 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6069 output_return_instruction (NULL, TRUE, FALSE);
6070 arm_ccfsm_state = 0;
6071 arm_target_insn = NULL;
6074 output_return_instruction (NULL, FALSE, FALSE);
6075 return \"b%?\\t%a1\";
6077 [(set_attr "type" "call")
6078 (set_attr "length" "8")])
6081 [(set (match_operand:SI 0 "s_register_operand" "")
6082 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
6084 (neg:SI (match_operator:SI 2 "comparison_operator"
6085 [(match_operand:SI 3 "s_register_operand" "")
6086 (match_operand:SI 4 "arm_rhs_operand" "")]))))
6087 (clobber (match_operand:SI 5 "s_register_operand" ""))]
6089 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
6090 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6094 ;; This split can be used because CC_Z mode implies that the following
6095 ;; branch will be an equality, or an unsigned inequality, so the sign
6096 ;; extension is not needed.
6101 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
6103 (match_operand 1 "const_int_operand" "")))
6104 (clobber (match_scratch:SI 2 ""))]
6105 "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
6106 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
6107 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
6108 (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
6110 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
6113 (define_expand "prologue"
6114 [(clobber (const_int 0))]
6117 arm_expand_prologue ();
6121 ;; This split is only used during output to reduce the number of patterns
6122 ;; that need assembler instructions adding to them. We allowed the setting
6123 ;; of the conditions to be implicit during rtl generation so that
6124 ;; the conditional compare patterns would work. However this conflicts to
6125 ;; some extent with the conditional data operations, so we have to split them
6129 [(set (match_operand:SI 0 "s_register_operand" "")
6130 (if_then_else:SI (match_operator 1 "comparison_operator"
6131 [(match_operand 2 "" "") (match_operand 3 "" "")])
6132 (match_operand 4 "" "")
6133 (match_operand 5 "" "")))
6134 (clobber (reg:CC 24))]
6136 [(set (match_dup 6) (match_dup 7))
6138 (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
6143 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
6146 operands[6] = gen_rtx_REG (mode, 24);
6147 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
6152 ;; The next two patterns occur when an AND operation is followed by a
6153 ;; scc insn sequence
6155 (define_insn "*sign_extract_onebit"
6156 [(set (match_operand:SI 0 "s_register_operand" "=r")
6157 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6159 (match_operand:SI 2 "const_int_operand" "n")))]
6162 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6163 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6164 return \"mvnne\\t%0, #0\";
6166 [(set_attr "conds" "clob")
6167 (set_attr "length" "8")])
6169 (define_insn "*not_signextract_onebit"
6170 [(set (match_operand:SI 0 "s_register_operand" "=r")
6172 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6174 (match_operand:SI 2 "const_int_operand" "n"))))]
6177 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6178 output_asm_insn (\"tst\\t%1, %2\", operands);
6179 output_asm_insn (\"mvneq\\t%0, #0\", operands);
6180 return \"movne\\t%0, #0\";
6182 [(set_attr "conds" "clob")
6183 (set_attr "length" "12")])
6185 ;; Push multiple registers to the stack. The first register is in the
6186 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
6188 (define_insn "*push_multi"
6189 [(match_parallel 2 "multi_register_push"
6190 [(set (match_operand:BLK 0 "memory_operand" "=m")
6191 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
6197 extern int lr_save_eliminated;
6199 if (lr_save_eliminated)
6201 if (XVECLEN (operands[2], 0) > 1)
6205 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
6206 for (i = 1; i < XVECLEN (operands[2], 0); i++)
6208 strcat (pattern, \", %|\");
6209 strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
6212 strcat (pattern, \"}\");
6213 output_asm_insn (pattern, operands);
6216 [(set_attr "type" "store4")])
6218 ;; Similarly for the floating point registers
6219 (define_insn "*push_fp_multi"
6220 [(match_parallel 2 "multi_register_push"
6221 [(set (match_operand:BLK 0 "memory_operand" "=m")
6222 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
6229 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
6230 output_asm_insn (pattern, operands);
6233 [(set_attr "type" "f_store")])
6235 ;; Special patterns for dealing with the constant pool
6237 (define_insn "consttable_4"
6238 [(unspec_volatile [(match_operand 0 "" "")] 2)]
6242 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6246 union real_extract u;
6247 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6248 assemble_real (u.d, GET_MODE (operands[0]));
6252 assemble_integer (operands[0], 4, 1);
6257 [(set_attr "length" "4")])
6259 (define_insn "consttable_8"
6260 [(unspec_volatile [(match_operand 0 "" "")] 3)]
6264 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6268 union real_extract u;
6269 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6270 assemble_real (u.d, GET_MODE (operands[0]));
6274 assemble_integer (operands[0], 8, 1);
6279 [(set_attr "length" "8")])
6281 (define_insn "consttable_end"
6282 [(unspec_volatile [(const_int 0)] 4)]
6285 /* Nothing to do (currently). */
6289 (define_insn "align_4"
6290 [(unspec_volatile [(const_int 0)] 5)]
6293 assemble_align (32);