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 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
50 ; Floating Point Unit. If we only have floating point emulation, then there
51 ; is no point in scheduling the floating point insns. (Well, for best
52 ; performance we should try and group them together).
54 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
56 ; LENGTH of an instruction (in bytes)
57 (define_attr "length" "" (const_int 4))
59 ; An assembler sequence may clobber the condition codes without us knowing
60 (define_asm_attributes
61 [(set_attr "conds" "clob")
62 (set_attr "length" "4")])
64 ; TYPE attribute is used to detect floating point instructions which, if
65 ; running on a co-processor can run in parallel with other, basic instructions
66 ; If write-buffer scheduling is enabled then it can also be used in the
67 ; scheduling of writes.
69 ; Classification of each insn
70 ; normal any data instruction that doesn't hit memory or fp regs
71 ; mult a multiply instruction
72 ; block blockage insn, this blocks all functional units
73 ; float a floating point arithmetic operation (subject to expansion)
74 ; fdivx XFmode floating point division
75 ; fdivd DFmode floating point division
76 ; fdivs SFmode floating point division
77 ; fmul Floating point multiply
78 ; ffmul Fast floating point multiply
79 ; farith Floating point arithmetic (4 cycle)
80 ; ffarith Fast floating point arithmetic (2 cycle)
81 ; float_em a floating point arithmetic operation that is normally emulated
82 ; even on a machine with an fpa.
83 ; f_load a floating point load from memory
84 ; f_store a floating point store to memory
85 ; f_mem_r a transfer of a floating point register to a real reg via mem
86 ; r_mem_f the reverse of f_mem_r
87 ; f_2_r fast transfer float to arm (no memory needed)
88 ; r_2_f fast transfer arm to float
89 ; call a subroutine call
90 ; load any load from memory
91 ; store1 store 1 word to memory from arm registers
92 ; store2 store 2 words
93 ; store3 store 3 words
94 ; store4 store 4 words
97 "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"
98 (const_string "normal"))
100 ; Load scheduling, set from the arm_ld_sched variable
101 ; initialised by arm_override_options()
102 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
104 ; condition codes: this one is used by final_prescan_insn to speed up
105 ; conditionalizing instructions. It saves having to scan the rtl to see if
106 ; it uses or alters the condition codes.
108 ; USE means that the condition codes are used by the insn in the process of
109 ; outputting code, this means (at present) that we can't use the insn in
112 ; SET means that the purpose of the insn is to set the condition codes in a
113 ; well defined manner.
115 ; CLOB means that the condition codes are altered in an undefined manner, if
116 ; they are altered at all
118 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
119 ; but are if the branch wasn't taken; the effect is to limit the branch
120 ; elimination scanning.
122 ; NOCOND means that the condition codes are neither altered nor affect the
123 ; output of this insn
125 (define_attr "conds" "use,set,clob,jump_clob,nocond"
126 (if_then_else (eq_attr "type" "call")
127 (if_then_else (eq_attr "prog_mode" "prog32")
128 (const_string "clob") (const_string "nocond"))
129 (const_string "nocond")))
131 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
132 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
133 ; suffer blockages enough to warrent modelling this (and it can adversely
134 ; affect the schedule).
135 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
137 (define_attr "write_conflict" "no,yes"
138 (if_then_else (eq_attr "type"
139 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
141 (const_string "no")))
143 (define_attr "core_cycles" "single,multi"
144 (if_then_else (eq_attr "type"
145 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
146 (const_string "single")
147 (const_string "multi")))
149 ; The write buffer on some of the arm6 processors is hard to model exactly.
150 ; There is room in the buffer for up to two addresses and up to eight words
151 ; of memory, but the two needn't be split evenly. When writing the two
152 ; addresses are fully pipelined. However, a read from memory that is not
153 ; currently in the cache will block until the writes have completed.
154 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
155 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
156 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
157 ; cycle to add as well.
159 ;; (define_function_unit {name} {num-units} {n-users} {test}
160 ;; {ready-delay} {issue-delay} [{conflict-list}])
161 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
162 (eq_attr "type" "fdivx")) 71 69)
164 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
165 (eq_attr "type" "fdivd")) 59 57)
167 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
168 (eq_attr "type" "fdivs")) 31 29)
170 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
171 (eq_attr "type" "fmul")) 9 7)
173 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
174 (eq_attr "type" "ffmul")) 6 4)
176 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
177 (eq_attr "type" "farith")) 4 2)
179 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
180 (eq_attr "type" "ffarith")) 2 2)
182 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
183 (eq_attr "type" "r_2_f")) 5 3)
185 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
186 (eq_attr "type" "f_2_r")) 1 2)
188 ;; The fpa10 doesn't really have a memory read unit, but it can start to
189 ;; speculatively execute the instruction in the pipeline, provided the data
190 ;; is already loaded, so pretend reads have a delay of 2 (and that the
191 ;; pipeline is infinite.
193 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
194 (eq_attr "type" "f_load")) 3 1)
196 ;;--------------------------------------------------------------------
198 ;;--------------------------------------------------------------------
199 ;; Strictly we should model a 4-deep write buffer for ARM7xx based chips
200 (define_function_unit "write_buf" 1 2
201 (and (eq_attr "model_wbuf" "yes")
202 (eq_attr "type" "store1,r_mem_f")) 5 3)
203 (define_function_unit "write_buf" 1 2
204 (and (eq_attr "model_wbuf" "yes")
205 (eq_attr "type" "store2")) 7 4)
206 (define_function_unit "write_buf" 1 2
207 (and (eq_attr "model_wbuf" "yes")
208 (eq_attr "type" "store3")) 9 5)
209 (define_function_unit "write_buf" 1 2
210 (and (eq_attr "model_wbuf" "yes")
211 (eq_attr "type" "store4")) 11 6)
213 ;;--------------------------------------------------------------------
214 ;; Write blockage unit
215 ;;--------------------------------------------------------------------
216 ;; The write_blockage unit models (partially), the fact that reads will stall
217 ;; until the write buffer empties.
218 ;; The f_mem_r and r_mem_f could also block, but they are to the stack,
219 ;; so we don't model them here
220 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
221 (eq_attr "type" "store1")) 5 5
222 [(eq_attr "write_conflict" "yes")])
223 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
224 (eq_attr "type" "store2")) 7 7
225 [(eq_attr "write_conflict" "yes")])
226 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
227 (eq_attr "type" "store3")) 9 9
228 [(eq_attr "write_conflict" "yes")])
229 (define_function_unit "write_blockage" 1 0
230 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
231 [(eq_attr "write_conflict" "yes")])
232 (define_function_unit "write_blockage" 1 0
233 (and (eq_attr "model_wbuf" "yes")
234 (eq_attr "write_conflict" "yes")) 1 1)
236 ;;--------------------------------------------------------------------
238 ;;--------------------------------------------------------------------
239 ;; Everything must spend at least one cycle in the core unit
240 (define_function_unit "core" 1 0
241 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
243 (define_function_unit "core" 1 0
244 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
246 (define_function_unit "core" 1 0
247 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
249 (define_function_unit "core" 1 0
250 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
252 (define_function_unit "core" 1 0
253 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
255 (define_function_unit "core" 1 0
256 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
258 (define_function_unit "core" 1 0
259 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
261 (define_function_unit "core" 1 0
262 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
264 (define_function_unit "core" 1 0
265 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
266 (eq_attr "type" "mult")) 4 4)
268 (define_function_unit "core" 1 0
269 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
270 (eq_attr "type" "mult")) 3 2)
272 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
274 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
276 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
278 ;; Note: For DImode insns, there is normally no reason why operands should
279 ;; not be in the same register, what we don't want is for something being
280 ;; written to partially overlap something that is an input.
284 (define_insn "adddi3"
285 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
286 (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
287 (match_operand:DI 2 "s_register_operand" "r,0")))
288 (clobber (reg:CC 24))]
290 "adds\\t%Q0, %Q1, %Q2\;adc\\t%R0, %R1, %R2"
291 [(set_attr "conds" "clob")
292 (set_attr "length" "8")])
294 (define_insn "*adddi_sesidi_di"
295 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
296 (plus:DI (sign_extend:DI
297 (match_operand:SI 2 "s_register_operand" "r,r"))
298 (match_operand:DI 1 "s_register_operand" "r,0")))
299 (clobber (reg:CC 24))]
301 "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, %2, asr #31"
302 [(set_attr "conds" "clob")
303 (set_attr "length" "8")])
305 (define_insn "*adddi_zesidi_di"
306 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
307 (plus:DI (zero_extend:DI
308 (match_operand:SI 2 "s_register_operand" "r,r"))
309 (match_operand:DI 1 "s_register_operand" "r,0")))
310 (clobber (reg:CC 24))]
312 "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, #0"
313 [(set_attr "conds" "clob")
314 (set_attr "length" "8")])
316 (define_expand "addsi3"
317 [(set (match_operand:SI 0 "s_register_operand" "")
318 (plus:SI (match_operand:SI 1 "s_register_operand" "")
319 (match_operand:SI 2 "reg_or_int_operand" "")))]
322 if (GET_CODE (operands[2]) == CONST_INT)
324 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
326 (reload_in_progress || reload_completed ? 0
327 : preserve_subexpressions_p ()));
333 [(set (match_operand:SI 0 "s_register_operand" "")
334 (plus:SI (match_operand:SI 1 "s_register_operand" "")
335 (match_operand:SI 2 "const_int_operand" "")))]
336 "! (const_ok_for_arm (INTVAL (operands[2]))
337 || const_ok_for_arm (-INTVAL (operands[2])))"
338 [(clobber (const_int 0))]
340 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
345 (define_insn "*addsi3_insn"
346 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
347 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
348 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
354 [(set_attr "length" "4,4,16")])
356 (define_insn "*addsi3_compare0"
357 [(set (reg:CC_NOOV 24)
359 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
360 (match_operand:SI 2 "arm_add_operand" "rI,L"))
362 (set (match_operand:SI 0 "s_register_operand" "=r,r")
363 (plus:SI (match_dup 1) (match_dup 2)))]
367 sub%?s\\t%0, %1, #%n2"
368 [(set_attr "conds" "set")])
370 (define_insn "*addsi3_compare0_scratch"
371 [(set (reg:CC_NOOV 24)
373 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
374 (match_operand:SI 1 "arm_add_operand" "rI,L"))
380 [(set_attr "conds" "set")])
382 ;; The next four insns work because they compare the result with one of
383 ;; the operands, and we know that the use of the condition code is
384 ;; either GEU or LTU, so we can use the carry flag from the addition
385 ;; instead of doing the compare a second time.
386 (define_insn "*addsi3_compare_op1"
389 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
390 (match_operand:SI 2 "arm_add_operand" "rI,L"))
392 (set (match_operand:SI 0 "s_register_operand" "=r,r")
393 (plus:SI (match_dup 1) (match_dup 2)))]
397 sub%?s\\t%0, %1, #%n2"
398 [(set_attr "conds" "set")])
400 (define_insn "*addsi3_compare_op2"
403 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
404 (match_operand:SI 2 "arm_add_operand" "rI,L"))
406 (set (match_operand:SI 0 "s_register_operand" "=r,r")
407 (plus:SI (match_dup 1) (match_dup 2)))]
411 sub%?s\\t%0, %1, #%n2"
412 [(set_attr "conds" "set")])
414 (define_insn "*compare_addsi2_op0"
417 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
418 (match_operand:SI 1 "arm_add_operand" "rI,L"))
424 [(set_attr "conds" "set")])
426 (define_insn "*compare_addsi2_op1"
429 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
430 (match_operand:SI 1 "arm_add_operand" "rI,L"))
436 [(set_attr "conds" "set")])
438 (define_insn "*addsi3_carryin"
439 [(set (match_operand:SI 0 "s_register_operand" "=r")
440 (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
441 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
442 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
445 [(set_attr "conds" "use")])
447 (define_insn "*addsi3_carryin_alt1"
448 [(set (match_operand:SI 0 "s_register_operand" "=r")
449 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
450 (match_operand:SI 2 "arm_rhs_operand" "rI"))
451 (ltu:SI (reg:CC_C 24) (const_int 0))))]
454 [(set_attr "conds" "use")])
456 (define_insn "*addsi3_carryin_alt2"
457 [(set (match_operand:SI 0 "s_register_operand" "=r")
458 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
459 (match_operand:SI 1 "s_register_operand" "r"))
460 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
463 [(set_attr "conds" "use")])
465 (define_insn "*addsi3_carryin_alt3"
466 [(set (match_operand:SI 0 "s_register_operand" "=r")
467 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
468 (match_operand:SI 2 "arm_rhs_operand" "rI"))
469 (match_operand:SI 1 "s_register_operand" "r")))]
472 [(set_attr "conds" "use")])
474 (define_insn "incscc"
475 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
476 (plus:SI (match_operator:SI 2 "comparison_operator"
477 [(match_operand 3 "cc_register" "") (const_int 0)])
478 (match_operand:SI 1 "s_register_operand" "0,?r")))]
482 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
483 [(set_attr "conds" "use")
484 (set_attr "length" "4,8")])
486 ; If a constant is too big to fit in a single instruction then the constant
487 ; will be pre-loaded into a register taking at least two insns, we might be
488 ; able to merge it with an add, but it depends on the exact value.
491 [(set (match_operand:SI 0 "s_register_operand" "=r")
492 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
493 (match_operand:SI 2 "const_int_operand" "n")))]
494 "!(const_ok_for_arm (INTVAL (operands[2]))
495 || const_ok_for_arm (-INTVAL (operands[2])))"
496 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
497 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
500 unsigned int val = (unsigned) INTVAL (operands[2]);
504 /* this code is similar to the approach followed in movsi, but it must
505 generate exactly two insns */
507 for (i = 30; i >= 0; i -= 2)
513 if (const_ok_for_arm (temp = (val & ~(255 << i))))
518 /* we might be able to do this as (larger number - small number) */
519 temp = ((val >> i) & 255) + 1;
520 if (temp > 255 && i < 24)
523 temp = ((val >> i) & 255) + 1;
525 if (const_ok_for_arm ((temp << i) - val))
528 temp = (unsigned) - (int) (i - val);
535 /* if we got here, we have found a way of doing it in two instructions.
536 the two constants are in val and temp */
537 operands[2] = GEN_INT ((int)val);
538 operands[3] = GEN_INT ((int)temp);
542 (define_insn "addsf3"
543 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
544 (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
545 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
549 suf%?s\\t%0, %1, #%N2"
550 [(set_attr "type" "farith")])
552 (define_insn "adddf3"
553 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
554 (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
555 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
559 suf%?d\\t%0, %1, #%N2"
560 [(set_attr "type" "farith")])
562 (define_insn "*adddf_esfdf_df"
563 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
564 (plus:DF (float_extend:DF
565 (match_operand:SF 1 "s_register_operand" "f,f"))
566 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
570 suf%?d\\t%0, %1, #%N2"
571 [(set_attr "type" "farith")])
573 (define_insn "*adddf_df_esfdf"
574 [(set (match_operand:DF 0 "s_register_operand" "=f")
575 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
577 (match_operand:SF 2 "s_register_operand" "f"))))]
579 "adf%?d\\t%0, %1, %2"
580 [(set_attr "type" "farith")])
582 (define_insn "*adddf_esfdf_esfdf"
583 [(set (match_operand:DF 0 "s_register_operand" "=f")
584 (plus:DF (float_extend:DF
585 (match_operand:SF 1 "s_register_operand" "f"))
587 (match_operand:SF 2 "s_register_operand" "f"))))]
589 "adf%?d\\t%0, %1, %2"
590 [(set_attr "type" "farith")])
592 (define_insn "addxf3"
593 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
594 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
595 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
596 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
599 suf%?e\\t%0, %1, #%N2"
600 [(set_attr "type" "farith")])
602 (define_insn "subdi3"
603 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
604 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
605 (match_operand:DI 2 "s_register_operand" "r,0,0")))
606 (clobber (reg:CC 24))]
608 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
609 [(set_attr "conds" "clob")
610 (set_attr "length" "8")])
612 (define_insn "*subdi_di_zesidi"
613 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
614 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
616 (match_operand:SI 2 "s_register_operand" "r,r"))))
617 (clobber (reg:CC 24))]
619 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
620 [(set_attr "conds" "clob")
621 (set_attr "length" "8")])
623 (define_insn "*subdi_di_sesidi"
624 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
625 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
627 (match_operand:SI 2 "s_register_operand" "r,r"))))
628 (clobber (reg:CC 24))]
630 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
631 [(set_attr "conds" "clob")
632 (set_attr "length" "8")])
634 (define_insn "*subdi_zesidi_di"
635 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
636 (minus:DI (zero_extend:DI
637 (match_operand:SI 2 "s_register_operand" "r,r"))
638 (match_operand:DI 1 "s_register_operand" "?r,0")))
639 (clobber (reg:CC 24))]
641 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
642 [(set_attr "conds" "clob")
643 (set_attr "length" "8")])
645 (define_insn "*subdi_sesidi_di"
646 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
647 (minus:DI (sign_extend:DI
648 (match_operand:SI 2 "s_register_operand" "r,r"))
649 (match_operand:DI 1 "s_register_operand" "?r,0")))
650 (clobber (reg:CC 24))]
652 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
653 [(set_attr "conds" "clob")
654 (set_attr "length" "8")])
656 (define_insn "*subdi_zesidi_zesidi"
657 [(set (match_operand:DI 0 "s_register_operand" "=r")
658 (minus:DI (zero_extend:DI
659 (match_operand:SI 1 "s_register_operand" "r"))
661 (match_operand:SI 2 "s_register_operand" "r"))))
662 (clobber (reg:CC 24))]
664 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
665 [(set_attr "conds" "clob")
666 (set_attr "length" "8")])
668 (define_expand "subsi3"
669 [(set (match_operand:SI 0 "s_register_operand" "")
670 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
671 (match_operand:SI 2 "s_register_operand" "")))]
674 if (GET_CODE (operands[1]) == CONST_INT)
676 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
678 (reload_in_progress || reload_completed ? 0
679 : preserve_subexpressions_p ()));
684 (define_insn "*subsi3_insn"
685 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
686 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
687 (match_operand:SI 2 "s_register_operand" "r,r")))]
692 [(set_attr "length" "4,16")])
695 [(set (match_operand:SI 0 "s_register_operand" "")
696 (minus:SI (match_operand:SI 1 "const_int_operand" "")
697 (match_operand:SI 2 "s_register_operand" "")))]
698 "! const_ok_for_arm (INTVAL (operands[1]))"
699 [(clobber (const_int 0))]
701 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
706 (define_insn "*subsi3_compare0"
707 [(set (reg:CC_NOOV 24)
708 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
709 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
711 (set (match_operand:SI 0 "s_register_operand" "=r,r")
712 (minus:SI (match_dup 1) (match_dup 2)))]
717 [(set_attr "conds" "set")])
719 (define_insn "decscc"
720 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
721 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
722 (match_operator:SI 2 "comparison_operator"
723 [(match_operand 3 "cc_register" "") (const_int 0)])))]
727 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
728 [(set_attr "conds" "use")
729 (set_attr "length" "*,8")])
731 (define_insn "subsf3"
732 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
733 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
734 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
739 [(set_attr "type" "farith")])
741 (define_insn "subdf3"
742 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
743 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
744 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
749 [(set_attr "type" "farith")])
751 (define_insn "*subdf_esfdf_df"
752 [(set (match_operand:DF 0 "s_register_operand" "=f")
753 (minus:DF (float_extend:DF
754 (match_operand:SF 1 "s_register_operand" "f"))
755 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
757 "suf%?d\\t%0, %1, %2"
758 [(set_attr "type" "farith")])
760 (define_insn "*subdf_df_esfdf"
761 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
762 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
764 (match_operand:SF 2 "s_register_operand" "f,f"))))]
769 [(set_attr "type" "farith")])
771 (define_insn "*subdf_esfdf_esfdf"
772 [(set (match_operand:DF 0 "s_register_operand" "=f")
773 (minus:DF (float_extend:DF
774 (match_operand:SF 1 "s_register_operand" "f"))
776 (match_operand:SF 2 "s_register_operand" "f"))))]
778 "suf%?d\\t%0, %1, %2"
779 [(set_attr "type" "farith")])
781 (define_insn "subxf3"
782 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
783 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
784 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
785 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
789 [(set_attr "type" "farith")])
791 ;; Multiplication insns
793 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
794 (define_insn "mulsi3"
795 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
796 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
797 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
800 [(set_attr "type" "mult")])
802 (define_insn "*mulsi3_compare0"
803 [(set (reg:CC_NOOV 24)
804 (compare:CC_NOOV (mult:SI
805 (match_operand:SI 2 "s_register_operand" "r,r")
806 (match_operand:SI 1 "s_register_operand" "%?r,0"))
808 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
809 (mult:SI (match_dup 2) (match_dup 1)))]
811 "mul%?s\\t%0, %2, %1"
812 [(set_attr "conds" "set")
813 (set_attr "type" "mult")])
815 (define_insn "*mulsi_compare0_scratch"
816 [(set (reg:CC_NOOV 24)
817 (compare:CC_NOOV (mult:SI
818 (match_operand:SI 2 "s_register_operand" "r,r")
819 (match_operand:SI 1 "s_register_operand" "%?r,0"))
821 (clobber (match_scratch:SI 0 "=&r,&r"))]
823 "mul%?s\\t%0, %2, %1"
824 [(set_attr "conds" "set")
825 (set_attr "type" "mult")])
827 ;; Unnamed templates to match MLA instruction.
829 (define_insn "*mulsi3addsi"
830 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
832 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
833 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
834 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
836 "mla%?\\t%0, %2, %1, %3"
837 [(set_attr "type" "mult")])
839 (define_insn "*mulsi3addsi_compare0"
840 [(set (reg:CC_NOOV 24)
841 (compare:CC_NOOV (plus:SI
843 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
844 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
845 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
847 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
848 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
851 "mla%?s\\t%0, %2, %1, %3"
852 [(set_attr "conds" "set")
853 (set_attr "type" "mult")])
855 (define_insn "*mulsi3addsi_compare0_scratch"
856 [(set (reg:CC_NOOV 24)
857 (compare:CC_NOOV (plus:SI
859 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
860 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
861 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
863 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
865 "mla%?s\\t%0, %2, %1, %3"
866 [(set_attr "conds" "set")
867 (set_attr "type" "mult")])
869 (define_insn "mulsidi3"
870 [(set (match_operand:DI 0 "s_register_operand" "=&r")
871 (mult:DI (sign_extend:DI
872 (match_operand:SI 1 "s_register_operand" "%r"))
874 (match_operand:SI 2 "s_register_operand" "r"))))]
876 "smull%?\\t%Q0, %R0, %1, %2"
877 [(set_attr "type" "mult")])
879 (define_insn "umulsidi3"
880 [(set (match_operand:DI 0 "s_register_operand" "=&r")
881 (mult:DI (zero_extend:DI
882 (match_operand:SI 1 "s_register_operand" "%r"))
884 (match_operand:SI 2 "s_register_operand" "r"))))]
886 "umull%?\\t%Q0, %R0, %1, %2"
887 [(set_attr "type" "mult")])
889 (define_insn "smulsi3_highpart"
890 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
893 (mult:DI (sign_extend:DI
894 (match_operand:SI 1 "s_register_operand" "%r,0"))
896 (match_operand:SI 2 "s_register_operand" "r,r")))
898 (clobber (match_scratch:SI 3 "=&r,&r"))]
900 "smull%?\\t%3, %0, %2, %1"
901 [(set_attr "type" "mult")])
903 (define_insn "umulsi3_highpart"
904 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
907 (mult:DI (zero_extend:DI
908 (match_operand:SI 1 "s_register_operand" "%r,0"))
910 (match_operand:SI 2 "s_register_operand" "r,r")))
912 (clobber (match_scratch:SI 3 "=&r,&r"))]
914 "umull%?\\t%3, %0, %2, %1"
915 [(set_attr "type" "mult")])
917 (define_insn "mulsf3"
918 [(set (match_operand:SF 0 "s_register_operand" "=f")
919 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
920 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
922 "fml%?s\\t%0, %1, %2"
923 [(set_attr "type" "ffmul")])
925 (define_insn "muldf3"
926 [(set (match_operand:DF 0 "s_register_operand" "=f")
927 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
928 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
930 "muf%?d\\t%0, %1, %2"
931 [(set_attr "type" "fmul")])
933 (define_insn "*muldf_esfdf_df"
934 [(set (match_operand:DF 0 "s_register_operand" "=f")
935 (mult:DF (float_extend:DF
936 (match_operand:SF 1 "s_register_operand" "f"))
937 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
939 "muf%?d\\t%0, %1, %2"
940 [(set_attr "type" "fmul")])
942 (define_insn "*muldf_df_esfdf"
943 [(set (match_operand:DF 0 "s_register_operand" "=f")
944 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
946 (match_operand:SF 2 "s_register_operand" "f"))))]
948 "muf%?d\\t%0, %1, %2"
949 [(set_attr "type" "fmul")])
951 (define_insn "*muldf_esfdf_esfdf"
952 [(set (match_operand:DF 0 "s_register_operand" "=f")
953 (mult:DF (float_extend:DF
954 (match_operand:SF 1 "s_register_operand" "f"))
956 (match_operand:SF 2 "s_register_operand" "f"))))]
958 "muf%?d\\t%0, %1, %2"
959 [(set_attr "type" "fmul")])
961 (define_insn "mulxf3"
962 [(set (match_operand:XF 0 "s_register_operand" "=f")
963 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
964 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
965 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
966 "muf%?e\\t%0, %1, %2"
967 [(set_attr "type" "fmul")])
971 (define_insn "divsf3"
972 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
973 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
974 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
979 [(set_attr "type" "fdivs")])
981 (define_insn "divdf3"
982 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
983 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
984 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
989 [(set_attr "type" "fdivd")])
991 (define_insn "*divdf_esfdf_df"
992 [(set (match_operand:DF 0 "s_register_operand" "=f")
993 (div:DF (float_extend:DF
994 (match_operand:SF 1 "s_register_operand" "f"))
995 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
997 "dvf%?d\\t%0, %1, %2"
998 [(set_attr "type" "fdivd")])
1000 (define_insn "*divdf_df_esfdf"
1001 [(set (match_operand:DF 0 "s_register_operand" "=f")
1002 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1004 (match_operand:SF 2 "s_register_operand" "f"))))]
1006 "rdf%?d\\t%0, %2, %1"
1007 [(set_attr "type" "fdivd")])
1009 (define_insn "*divdf_esfdf_esfdf"
1010 [(set (match_operand:DF 0 "s_register_operand" "=f")
1011 (div:DF (float_extend:DF
1012 (match_operand:SF 1 "s_register_operand" "f"))
1014 (match_operand:SF 2 "s_register_operand" "f"))))]
1016 "dvf%?d\\t%0, %1, %2"
1017 [(set_attr "type" "fdivd")])
1019 (define_insn "divxf3"
1020 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1021 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1022 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1023 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1026 rdf%?e\\t%0, %2, %1"
1027 [(set_attr "type" "fdivx")])
1031 (define_insn "modsf3"
1032 [(set (match_operand:SF 0 "s_register_operand" "=f")
1033 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1034 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1036 "rmf%?s\\t%0, %1, %2"
1037 [(set_attr "type" "fdivs")])
1039 (define_insn "moddf3"
1040 [(set (match_operand:DF 0 "s_register_operand" "=f")
1041 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1042 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1044 "rmf%?d\\t%0, %1, %2"
1045 [(set_attr "type" "fdivd")])
1047 (define_insn "*moddf_esfdf_df"
1048 [(set (match_operand:DF 0 "s_register_operand" "=f")
1049 (mod:DF (float_extend:DF
1050 (match_operand:SF 1 "s_register_operand" "f"))
1051 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1053 "rmf%?d\\t%0, %1, %2"
1054 [(set_attr "type" "fdivd")])
1056 (define_insn "*moddf_df_esfdf"
1057 [(set (match_operand:DF 0 "s_register_operand" "=f")
1058 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1060 (match_operand:SF 2 "s_register_operand" "f"))))]
1062 "rmf%?d\\t%0, %1, %2"
1063 [(set_attr "type" "fdivd")])
1065 (define_insn "*moddf_esfdf_esfdf"
1066 [(set (match_operand:DF 0 "s_register_operand" "=f")
1067 (mod:DF (float_extend:DF
1068 (match_operand:SF 1 "s_register_operand" "f"))
1070 (match_operand:SF 2 "s_register_operand" "f"))))]
1072 "rmf%?d\\t%0, %1, %2"
1073 [(set_attr "type" "fdivd")])
1075 (define_insn "modxf3"
1076 [(set (match_operand:XF 0 "s_register_operand" "=f")
1077 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1078 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1079 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1080 "rmf%?e\\t%0, %1, %2"
1081 [(set_attr "type" "fdivx")])
1083 ;; Boolean and,ior,xor insns
1085 (define_insn "anddi3"
1086 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1087 (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1088 (match_operand:DI 2 "s_register_operand" "r,0")))]
1090 "and%?\\t%Q0, %Q1, %Q2\;and%?\\t%R0, %R1, %R2"
1091 [(set_attr "length" "8")])
1093 (define_insn "*anddi_zesidi_di"
1094 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1095 (and:DI (zero_extend:DI
1096 (match_operand:SI 2 "s_register_operand" "r,r"))
1097 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1099 "and%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, #0"
1100 [(set_attr "length" "8")])
1102 (define_insn "*anddi_sesdi_di"
1103 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1104 (and:DI (sign_extend:DI
1105 (match_operand:SI 2 "s_register_operand" "r,r"))
1106 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1108 "and%?\\t%Q0, %Q1, %2\;and%?\\t%R0, %R1, %2, asr #31"
1109 [(set_attr "length" "8")])
1111 (define_expand "andsi3"
1112 [(set (match_operand:SI 0 "s_register_operand" "")
1113 (and:SI (match_operand:SI 1 "s_register_operand" "")
1114 (match_operand:SI 2 "reg_or_int_operand" "")))]
1117 if (GET_CODE (operands[2]) == CONST_INT)
1119 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1121 (reload_in_progress || reload_completed
1122 ? 0 : preserve_subexpressions_p ()));
1127 (define_insn "*andsi3_insn"
1128 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1129 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1130 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1134 bic%?\\t%0, %1, #%B2
1136 [(set_attr "length" "4,4,16")])
1139 [(set (match_operand:SI 0 "s_register_operand" "")
1140 (and:SI (match_operand:SI 1 "s_register_operand" "")
1141 (match_operand:SI 2 "const_int_operand" "")))]
1142 "! (const_ok_for_arm (INTVAL (operands[2]))
1143 || const_ok_for_arm (~ INTVAL (operands[2])))"
1144 [(clobber (const_int 0))]
1146 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1151 (define_insn "*andsi3_compare0"
1152 [(set (reg:CC_NOOV 24)
1154 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1155 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1157 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1158 (and:SI (match_dup 1) (match_dup 2)))]
1162 bic%?s\\t%0, %1, #%B2"
1163 [(set_attr "conds" "set")])
1165 (define_insn "*andsi3_compare0_scratch"
1166 [(set (reg:CC_NOOV 24)
1168 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1169 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1171 (clobber (match_scratch:SI 3 "=X,r"))]
1175 bic%?s\\t%3, %0, #%B1"
1176 [(set_attr "conds" "set")])
1178 (define_insn "*zeroextractsi_compare0_scratch"
1179 [(set (reg:CC_NOOV 24)
1180 (compare:CC_NOOV (zero_extract:SI
1181 (match_operand:SI 0 "s_register_operand" "r")
1182 (match_operand 1 "const_int_operand" "n")
1183 (match_operand 2 "const_int_operand" "n"))
1185 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1186 && INTVAL (operands[1]) > 0
1187 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1188 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1190 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1191 << INTVAL (operands[2]));
1192 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1195 [(set_attr "conds" "set")])
1197 (define_insn "*ne_zeroextractsi"
1198 [(set (match_operand:SI 0 "s_register_operand" "=r")
1199 (ne:SI (zero_extract:SI
1200 (match_operand:SI 1 "s_register_operand" "r")
1201 (match_operand:SI 2 "const_int_operand" "n")
1202 (match_operand:SI 3 "const_int_operand" "n"))
1204 "INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1205 && INTVAL (operands[2]) > 0
1206 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1207 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32"
1209 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1210 << INTVAL (operands[3]));
1211 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1212 return \"movne\\t%0, #1\";
1214 [(set_attr "conds" "clob")
1215 (set_attr "length" "8")])
1217 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1218 ;;; represented by the bitfield, then this will produce incorrect results.
1219 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1220 ;;; which have a real bitfield insert instruction, the truncation happens
1221 ;;; in the bitfield insert instruction itself. Since arm does not have a
1222 ;;; bitfield insert instruction, we would have to emit code here to truncate
1223 ;;; the value before we insert. This loses some of the advantage of having
1224 ;;; this insv pattern, so this pattern needs to be reevalutated.
1226 (define_expand "insv"
1227 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1228 (match_operand:SI 1 "general_operand" "")
1229 (match_operand:SI 2 "general_operand" ""))
1230 (match_operand:SI 3 "nonmemory_operand" ""))]
1234 int start_bit = INTVAL (operands[2]);
1235 int width = INTVAL (operands[1]);
1236 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1237 rtx target, subtarget;
1239 target = operands[0];
1240 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1241 subreg as the final target. */
1242 if (GET_CODE (target) == SUBREG)
1244 subtarget = gen_reg_rtx (SImode);
1245 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1246 < GET_MODE_SIZE (SImode))
1247 target = SUBREG_REG (target);
1252 if (GET_CODE (operands[3]) == CONST_INT)
1254 /* Since we are inserting a known constant, we may be able to
1255 reduce the number of bits that we have to clear so that
1256 the mask becomes simple. */
1257 /* ??? This code does not check to see if the new mask is actually
1258 simpler. It may not be. */
1259 rtx op1 = gen_reg_rtx (SImode);
1260 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1261 start of this pattern. */
1262 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1263 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1265 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1266 emit_insn (gen_iorsi3 (subtarget, op1,
1267 GEN_INT (op3_value << start_bit)));
1269 else if (start_bit == 0
1270 && ! (const_ok_for_arm (mask)
1271 || const_ok_for_arm (~mask)))
1273 /* A Trick, since we are setting the bottom bits in the word,
1274 we can shift operand[3] up, operand[0] down, OR them together
1275 and rotate the result back again. This takes 3 insns, and
1276 the third might be mergable into another op. */
1277 /* The shift up copes with the possibility that operand[3] is
1278 wider than the bitfield. */
1279 rtx op0 = gen_reg_rtx (SImode);
1280 rtx op1 = gen_reg_rtx (SImode);
1282 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1283 emit_insn (gen_iorsi3 (op1, gen_rtx_LSHIFTRT (SImode, operands[0],
1286 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1288 else if ((width + start_bit == 32)
1289 && ! (const_ok_for_arm (mask)
1290 || const_ok_for_arm (~mask)))
1292 /* Similar trick, but slightly less efficient. */
1294 rtx op0 = gen_reg_rtx (SImode);
1295 rtx op1 = gen_reg_rtx (SImode);
1297 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1298 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1299 emit_insn (gen_iorsi3 (subtarget,
1300 gen_rtx_LSHIFTRT (SImode, op1, operands[1]),
1305 rtx op0 = GEN_INT (mask);
1306 rtx op1 = gen_reg_rtx (SImode);
1307 rtx op2 = gen_reg_rtx (SImode);
1309 if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1311 rtx tmp = gen_reg_rtx (SImode);
1313 emit_insn (gen_movsi (tmp, op0));
1317 /* Mask out any bits in operand[3] that are not needed. */
1318 emit_insn (gen_andsi3 (op1, operands[3], op0));
1320 if (GET_CODE (op0) == CONST_INT
1321 && (const_ok_for_arm (mask << start_bit)
1322 || const_ok_for_arm (~ (mask << start_bit))))
1324 op0 = GEN_INT (~(mask << start_bit));
1325 emit_insn (gen_andsi3 (op2, operands[0], op0));
1329 if (GET_CODE (op0) == CONST_INT)
1331 rtx tmp = gen_reg_rtx (SImode);
1333 emit_insn (gen_movsi (tmp, op0));
1338 op0 = gen_rtx_ASHIFT (SImode, op0, operands[2]);
1340 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1344 op1 = gen_rtx_ASHIFT (SImode, op1, operands[2]);
1346 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1349 if (subtarget != target)
1351 /* If TARGET is still a SUBREG, then it must be wider than a word,
1352 so we must be careful only to set the subword we were asked to. */
1353 if (GET_CODE (target) == SUBREG)
1354 emit_move_insn (target, subtarget);
1356 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1363 ;; constants for op 2 will never be given to these patterns.
1364 (define_insn "*anddi_notdi_di"
1365 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1366 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1367 (match_operand:DI 1 "s_register_operand" "0,r")))]
1369 "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2"
1370 [(set_attr "length" "8")])
1372 (define_insn "*anddi_notzesidi_di"
1373 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1374 (and:DI (not:DI (zero_extend:DI
1375 (match_operand:SI 2 "s_register_operand" "r,r")))
1376 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1379 bic%?\\t%Q0, %Q1, %2
1380 bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1381 [(set_attr "length" "4,8")])
1383 (define_insn "*anddi_notsesidi_di"
1384 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1385 (and:DI (not:DI (sign_extend:DI
1386 (match_operand:SI 2 "s_register_operand" "r,r")))
1387 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1389 "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
1390 [(set_attr "length" "8")])
1392 (define_insn "andsi_notsi_si"
1393 [(set (match_operand:SI 0 "s_register_operand" "=r")
1394 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1395 (match_operand:SI 1 "s_register_operand" "r")))]
1397 "bic%?\\t%0, %1, %2")
1399 (define_insn "andsi_not_shiftsi_si"
1400 [(set (match_operand:SI 0 "s_register_operand" "=r")
1401 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1402 [(match_operand:SI 2 "s_register_operand" "r")
1403 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1404 (match_operand:SI 1 "s_register_operand" "r")))]
1406 "bic%?\\t%0, %1, %2%S4")
1408 (define_insn "*andsi_notsi_si_compare0"
1409 [(set (reg:CC_NOOV 24)
1411 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1412 (match_operand:SI 1 "s_register_operand" "r"))
1414 (set (match_operand:SI 0 "s_register_operand" "=r")
1415 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1417 "bic%?s\\t%0, %1, %2"
1418 [(set_attr "conds" "set")])
1420 (define_insn "*andsi_notsi_si_compare0_scratch"
1421 [(set (reg:CC_NOOV 24)
1423 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1424 (match_operand:SI 1 "s_register_operand" "r"))
1426 (clobber (match_scratch:SI 0 "=r"))]
1428 "bic%?s\\t%0, %1, %2"
1429 [(set_attr "conds" "set")])
1431 (define_insn "iordi3"
1432 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1433 (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1434 (match_operand:DI 2 "s_register_operand" "r")))]
1436 "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2"
1437 [(set_attr "length" "8")])
1439 (define_insn "*iordi_zesidi_di"
1440 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1441 (ior:DI (zero_extend:DI
1442 (match_operand:SI 2 "s_register_operand" "r,r"))
1443 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1446 orr%?\\t%Q0, %Q1, %2
1447 orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1448 [(set_attr "length" "4,8")])
1450 (define_insn "*iordi_sesidi_di"
1451 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1452 (ior:DI (sign_extend:DI
1453 (match_operand:SI 2 "s_register_operand" "r,r"))
1454 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1456 "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
1457 [(set_attr "length" "8")])
1459 (define_expand "iorsi3"
1460 [(set (match_operand:SI 0 "s_register_operand" "")
1461 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1462 (match_operand:SI 2 "reg_or_int_operand" "")))]
1465 if (GET_CODE (operands[2]) == CONST_INT)
1467 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1469 (reload_in_progress || reload_completed
1470 ? 0 : preserve_subexpressions_p ()));
1475 (define_insn "*iorsi3_insn"
1476 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1477 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1478 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1483 [(set_attr "length" "4,16")])
1486 [(set (match_operand:SI 0 "s_register_operand" "")
1487 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1488 (match_operand:SI 2 "const_int_operand" "")))]
1489 "! const_ok_for_arm (INTVAL (operands[2]))"
1490 [(clobber (const_int 0))]
1492 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1497 (define_insn "*iorsi3_compare0"
1498 [(set (reg:CC_NOOV 24)
1499 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1500 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1502 (set (match_operand:SI 0 "s_register_operand" "=r")
1503 (ior:SI (match_dup 1) (match_dup 2)))]
1505 "orr%?s\\t%0, %1, %2"
1506 [(set_attr "conds" "set")])
1508 (define_insn "*iorsi3_compare0_scratch"
1509 [(set (reg:CC_NOOV 24)
1510 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1511 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1513 (clobber (match_scratch:SI 0 "=r"))]
1515 "orr%?s\\t%0, %1, %2"
1516 [(set_attr "conds" "set")])
1518 (define_insn "xordi3"
1519 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1520 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1521 (match_operand:DI 2 "s_register_operand" "r,0")))]
1523 "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2"
1524 [(set_attr "length" "8")])
1526 (define_insn "*xordi_zesidi_di"
1527 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1528 (xor:DI (zero_extend:DI
1529 (match_operand:SI 2 "s_register_operand" "r,r"))
1530 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1533 eor%?\\t%Q0, %Q1, %2
1534 eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1535 [(set_attr "length" "4,8")])
1537 (define_insn "*xordi_sesidi_di"
1538 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1539 (xor:DI (sign_extend:DI
1540 (match_operand:SI 2 "s_register_operand" "r,r"))
1541 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1543 "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
1544 [(set_attr "length" "8")])
1546 (define_insn "xorsi3"
1547 [(set (match_operand:SI 0 "s_register_operand" "=r")
1548 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1549 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1551 "eor%?\\t%0, %1, %2")
1553 (define_insn "*xorsi3_compare0"
1554 [(set (reg:CC_NOOV 24)
1555 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1556 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1558 (set (match_operand:SI 0 "s_register_operand" "=r")
1559 (xor:SI (match_dup 1) (match_dup 2)))]
1561 "eor%?s\\t%0, %1, %2"
1562 [(set_attr "conds" "set")])
1564 (define_insn "*xorsi3_compare0_scratch"
1565 [(set (reg:CC_NOOV 24)
1566 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1567 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1571 [(set_attr "conds" "set")])
1573 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
1574 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1578 [(set (match_operand:SI 0 "s_register_operand" "=r")
1579 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1580 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1581 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1582 (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1584 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1585 (not:SI (match_dup 3))))
1586 (set (match_dup 0) (not:SI (match_dup 4)))]
1590 (define_insn "*andsi_iorsi3_notsi"
1591 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1592 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1593 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1594 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1596 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1597 [(set_attr "length" "8")])
1601 ;; Minimum and maximum insns
1603 (define_insn "smaxsi3"
1604 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1605 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1606 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1607 (clobber (reg:CC 24))]
1610 cmp\\t%1, %2\;movlt\\t%0, %2
1611 cmp\\t%1, %2\;movge\\t%0, %1
1612 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1613 [(set_attr "conds" "clob")
1614 (set_attr "length" "8,8,12")])
1616 (define_insn "sminsi3"
1617 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1618 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1619 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1620 (clobber (reg:CC 24))]
1623 cmp\\t%1, %2\;movge\\t%0, %2
1624 cmp\\t%1, %2\;movlt\\t%0, %1
1625 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1626 [(set_attr "conds" "clob")
1627 (set_attr "length" "8,8,12")])
1629 (define_insn "umaxsi3"
1630 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1631 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1632 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1633 (clobber (reg:CC 24))]
1636 cmp\\t%1, %2\;movcc\\t%0, %2
1637 cmp\\t%1, %2\;movcs\\t%0, %1
1638 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1639 [(set_attr "conds" "clob")
1640 (set_attr "length" "8,8,12")])
1642 (define_insn "uminsi3"
1643 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1644 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1645 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1646 (clobber (reg:CC 24))]
1649 cmp\\t%1, %2\;movcs\\t%0, %2
1650 cmp\\t%1, %2\;movcc\\t%0, %1
1651 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1652 [(set_attr "conds" "clob")
1653 (set_attr "length" "8,8,12")])
1655 (define_insn "*store_minmaxsi"
1656 [(set (match_operand:SI 0 "memory_operand" "=m")
1657 (match_operator:SI 3 "minmax_operator"
1658 [(match_operand:SI 1 "s_register_operand" "r")
1659 (match_operand:SI 2 "s_register_operand" "r")]))
1660 (clobber (reg:CC 24))]
1663 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1665 output_asm_insn (\"cmp\\t%1, %2\", operands);
1666 output_asm_insn (\"str%d3\\t%1, %0\", operands);
1667 output_asm_insn (\"str%D3\\t%2, %0\", operands);
1670 [(set_attr "conds" "clob")
1671 (set_attr "length" "12")
1672 (set_attr "type" "store1")])
1674 ; Reject the frame pointer in operand[1], since reloading this after
1675 ; it has been eliminated can cause carnage.
1676 (define_insn "*minmax_arithsi"
1677 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1678 (match_operator:SI 4 "shiftable_operator"
1679 [(match_operator:SI 5 "minmax_operator"
1680 [(match_operand:SI 2 "s_register_operand" "r,r")
1681 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1682 (match_operand:SI 1 "s_register_operand" "0,?r")]))
1683 (clobber (reg:CC 24))]
1684 "GET_CODE (operands[1]) != REG
1685 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
1686 && REGNO(operands[1]) != ARG_POINTER_REGNUM)"
1689 enum rtx_code code = GET_CODE (operands[4]);
1691 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1693 output_asm_insn (\"cmp\\t%2, %3\", operands);
1694 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1695 if (which_alternative != 0 || operands[3] != const0_rtx
1696 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1697 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1701 [(set_attr "conds" "clob")
1702 (set_attr "length" "12")])
1705 ;; Shift and rotation insns
1707 (define_expand "ashlsi3"
1708 [(set (match_operand:SI 0 "s_register_operand" "")
1709 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
1710 (match_operand:SI 2 "arm_rhs_operand" "")))]
1713 if (GET_CODE (operands[2]) == CONST_INT
1714 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1716 emit_insn (gen_movsi (operands[0], const0_rtx));
1721 (define_expand "ashrsi3"
1722 [(set (match_operand:SI 0 "s_register_operand" "")
1723 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1724 (match_operand:SI 2 "arm_rhs_operand" "")))]
1727 if (GET_CODE (operands[2]) == CONST_INT
1728 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1729 operands[2] = GEN_INT (31);
1732 (define_expand "lshrsi3"
1733 [(set (match_operand:SI 0 "s_register_operand" "")
1734 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1735 (match_operand:SI 2 "arm_rhs_operand" "")))]
1738 if (GET_CODE (operands[2]) == CONST_INT
1739 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1741 emit_insn (gen_movsi (operands[0], const0_rtx));
1746 (define_expand "rotlsi3"
1747 [(set (match_operand:SI 0 "s_register_operand" "")
1748 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1749 (match_operand:SI 2 "reg_or_int_operand" "")))]
1752 if (GET_CODE (operands[2]) == CONST_INT)
1753 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
1756 rtx reg = gen_reg_rtx (SImode);
1757 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
1762 (define_expand "rotrsi3"
1763 [(set (match_operand:SI 0 "s_register_operand" "")
1764 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1765 (match_operand:SI 2 "arm_rhs_operand" "")))]
1768 if (GET_CODE (operands[2]) == CONST_INT
1769 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1770 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
1773 (define_insn "*shiftsi3"
1774 [(set (match_operand:SI 0 "s_register_operand" "=r")
1775 (match_operator:SI 3 "shift_operator"
1776 [(match_operand:SI 1 "s_register_operand" "r")
1777 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
1779 "mov%?\\t%0, %1%S3")
1781 (define_insn "*shiftsi3_compare0"
1782 [(set (reg:CC_NOOV 24)
1783 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1784 [(match_operand:SI 1 "s_register_operand" "r")
1785 (match_operand:SI 2 "arm_rhs_operand" "rM")])
1787 (set (match_operand:SI 0 "s_register_operand" "=r")
1788 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
1790 "mov%?s\\t%0, %1%S3"
1791 [(set_attr "conds" "set")])
1793 (define_insn "*shiftsi3_compare0_scratch"
1794 [(set (reg:CC_NOOV 24)
1795 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1796 [(match_operand:SI 1 "s_register_operand" "r")
1797 (match_operand:SI 2 "arm_rhs_operand" "rM")])
1799 (clobber (match_scratch:SI 0 "=r"))]
1801 "mov%?s\\t%0, %1%S3"
1802 [(set_attr "conds" "set")])
1804 (define_insn "*notsi_shiftsi"
1805 [(set (match_operand:SI 0 "s_register_operand" "=r")
1806 (not:SI (match_operator:SI 3 "shift_operator"
1807 [(match_operand:SI 1 "s_register_operand" "r")
1808 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
1810 "mvn%?\\t%0, %1%S3")
1812 (define_insn "*notsi_shiftsi_compare0"
1813 [(set (reg:CC_NOOV 24)
1814 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1815 [(match_operand:SI 1 "s_register_operand" "r")
1816 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1818 (set (match_operand:SI 0 "s_register_operand" "=r")
1819 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1821 "mvn%?s\\t%0, %1%S3"
1822 [(set_attr "conds" "set")])
1824 (define_insn "*not_shiftsi_compare0_scratch"
1825 [(set (reg:CC_NOOV 24)
1826 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1827 [(match_operand:SI 1 "s_register_operand" "r")
1828 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1830 (clobber (match_scratch:SI 0 "=r"))]
1832 "mvn%?s\\t%0, %1%S3"
1833 [(set_attr "conds" "set")])
1836 ;; Unary arithmetic insns
1838 (define_insn "negdi2"
1839 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1840 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1842 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
1843 [(set_attr "conds" "clob")
1844 (set_attr "length" "8")])
1846 (define_insn "negsi2"
1847 [(set (match_operand:SI 0 "s_register_operand" "=r")
1848 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1850 "rsb%?\\t%0, %1, #0")
1852 (define_insn "negsf2"
1853 [(set (match_operand:SF 0 "s_register_operand" "=f")
1854 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1857 [(set_attr "type" "ffarith")])
1859 (define_insn "negdf2"
1860 [(set (match_operand:DF 0 "s_register_operand" "=f")
1861 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1864 [(set_attr "type" "ffarith")])
1866 (define_insn "*negdf_esfdf"
1867 [(set (match_operand:DF 0 "s_register_operand" "=f")
1868 (neg:DF (float_extend:DF
1869 (match_operand:SF 1 "s_register_operand" "f"))))]
1872 [(set_attr "type" "ffarith")])
1874 (define_insn "negxf2"
1875 [(set (match_operand:XF 0 "s_register_operand" "=f")
1876 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1877 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1879 [(set_attr "type" "ffarith")])
1881 ;; abssi2 doesn't really clobber the condition codes if a different register
1882 ;; is being set. To keep things simple, assume during rtl manipulations that
1883 ;; it does, but tell the final scan operator the truth. Similarly for
1886 (define_insn "abssi2"
1887 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1888 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1889 (clobber (reg:CC 24))]
1892 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
1893 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
1894 [(set_attr "conds" "clob,*")
1895 (set_attr "length" "8")])
1897 (define_insn "*neg_abssi2"
1898 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1899 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1900 (clobber (reg:CC 24))]
1903 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
1904 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
1905 [(set_attr "conds" "clob,*")
1906 (set_attr "length" "8")])
1908 (define_insn "abssf2"
1909 [(set (match_operand:SF 0 "s_register_operand" "=f")
1910 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1913 [(set_attr "type" "ffarith")])
1915 (define_insn "absdf2"
1916 [(set (match_operand:DF 0 "s_register_operand" "=f")
1917 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1920 [(set_attr "type" "ffarith")])
1922 (define_insn "*absdf_esfdf"
1923 [(set (match_operand:DF 0 "s_register_operand" "=f")
1924 (abs:DF (float_extend:DF
1925 (match_operand:SF 1 "s_register_operand" "f"))))]
1928 [(set_attr "type" "ffarith")])
1930 (define_insn "absxf2"
1931 [(set (match_operand:XF 0 "s_register_operand" "=f")
1932 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1933 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1935 [(set_attr "type" "ffarith")])
1937 (define_insn "sqrtsf2"
1938 [(set (match_operand:SF 0 "s_register_operand" "=f")
1939 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1942 [(set_attr "type" "float_em")])
1944 (define_insn "sqrtdf2"
1945 [(set (match_operand:DF 0 "s_register_operand" "=f")
1946 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1949 [(set_attr "type" "float_em")])
1951 (define_insn "*sqrtdf_esfdf"
1952 [(set (match_operand:DF 0 "s_register_operand" "=f")
1953 (sqrt:DF (float_extend:DF
1954 (match_operand:SF 1 "s_register_operand" "f"))))]
1957 [(set_attr "type" "float_em")])
1959 (define_insn "sqrtxf2"
1960 [(set (match_operand:XF 0 "s_register_operand" "=f")
1961 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1962 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1964 [(set_attr "type" "float_em")])
1966 ;; SIN COS TAN and family are always emulated, so it's probably better
1967 ;; to always call a library function.
1968 ;(define_insn "sinsf2"
1969 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
1970 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1971 ; "TARGET_HARD_FLOAT"
1973 ;[(set_attr "type" "float_em")])
1975 ;(define_insn "sindf2"
1976 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
1977 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1978 ; "TARGET_HARD_FLOAT"
1980 ;[(set_attr "type" "float_em")])
1982 ;(define_insn "*sindf_esfdf"
1983 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
1984 ; (unspec:DF [(float_extend:DF
1985 ; (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1986 ; "TARGET_HARD_FLOAT"
1988 ;[(set_attr "type" "float_em")])
1990 ;(define_insn "sinxf2"
1991 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
1992 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1993 ; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1995 ;[(set_attr "type" "float_em")])
1997 ;(define_insn "cossf2"
1998 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
1999 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
2000 ; "TARGET_HARD_FLOAT"
2002 ;[(set_attr "type" "float_em")])
2004 ;(define_insn "cosdf2"
2005 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2006 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
2007 ; "TARGET_HARD_FLOAT"
2009 ;[(set_attr "type" "float_em")])
2011 ;(define_insn "*cosdf_esfdf"
2012 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2013 ; (unspec:DF [(float_extend:DF
2014 ; (match_operand:SF 1 "s_register_operand" "f"))] 1))]
2015 ; "TARGET_HARD_FLOAT"
2017 ;[(set_attr "type" "float_em")])
2019 ;(define_insn "cosxf2"
2020 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2021 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
2022 ; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2024 ;[(set_attr "type" "float_em")])
2026 (define_insn "one_cmpldi2"
2027 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2028 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2030 "mvn%?\\t%Q0, %Q1\;mvn%?\\t%R0, %R1"
2031 [(set_attr "length" "8")])
2033 (define_insn "one_cmplsi2"
2034 [(set (match_operand:SI 0 "s_register_operand" "=r")
2035 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2039 (define_insn "*notsi_compare0"
2040 [(set (reg:CC_NOOV 24)
2041 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2043 (set (match_operand:SI 0 "s_register_operand" "=r")
2044 (not:SI (match_dup 1)))]
2047 [(set_attr "conds" "set")])
2049 (define_insn "*notsi_compare0_scratch"
2050 [(set (reg:CC_NOOV 24)
2051 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2053 (clobber (match_scratch:SI 0 "=r"))]
2056 [(set_attr "conds" "set")])
2058 ;; Fixed <--> Floating conversion insns
2060 (define_insn "floatsisf2"
2061 [(set (match_operand:SF 0 "s_register_operand" "=f")
2062 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2065 [(set_attr "type" "r_2_f")])
2067 (define_insn "floatsidf2"
2068 [(set (match_operand:DF 0 "s_register_operand" "=f")
2069 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2072 [(set_attr "type" "r_2_f")])
2074 (define_insn "floatsixf2"
2075 [(set (match_operand:XF 0 "s_register_operand" "=f")
2076 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
2077 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2079 [(set_attr "type" "r_2_f")])
2081 (define_insn "fix_truncsfsi2"
2082 [(set (match_operand:SI 0 "s_register_operand" "=r")
2083 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2086 [(set_attr "type" "f_2_r")])
2088 (define_insn "fix_truncdfsi2"
2089 [(set (match_operand:SI 0 "s_register_operand" "=r")
2090 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2093 [(set_attr "type" "f_2_r")])
2095 (define_insn "fix_truncxfsi2"
2096 [(set (match_operand:SI 0 "s_register_operand" "=r")
2097 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
2098 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2100 [(set_attr "type" "f_2_r")])
2104 (define_insn "truncdfsf2"
2105 [(set (match_operand:SF 0 "s_register_operand" "=f")
2107 (match_operand:DF 1 "s_register_operand" "f")))]
2110 [(set_attr "type" "ffarith")])
2112 (define_insn "truncxfsf2"
2113 [(set (match_operand:SF 0 "s_register_operand" "=f")
2115 (match_operand:XF 1 "s_register_operand" "f")))]
2116 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2118 [(set_attr "type" "ffarith")])
2120 (define_insn "truncxfdf2"
2121 [(set (match_operand:DF 0 "s_register_operand" "=f")
2123 (match_operand:XF 1 "s_register_operand" "f")))]
2124 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2126 [(set_attr "type" "ffarith")])
2128 ;; Zero and sign extension instructions.
2130 (define_insn "zero_extendsidi2"
2131 [(set (match_operand:DI 0 "s_register_operand" "=r")
2132 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2135 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2136 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2137 return \"mov%?\\t%R0, #0\";
2139 [(set_attr "length" "8")])
2141 (define_insn "zero_extendqidi2"
2142 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2143 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2146 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2147 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2148 [(set_attr "length" "8")
2149 (set_attr "type" "*,load")])
2151 (define_insn "extendsidi2"
2152 [(set (match_operand:DI 0 "s_register_operand" "=r")
2153 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2156 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2157 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2158 return \"mov%?\\t%R0, %Q0, asr #31\";
2160 [(set_attr "length" "8")])
2162 (define_expand "zero_extendhisi2"
2163 [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2165 (set (match_operand:SI 0 "s_register_operand" "")
2166 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2170 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2172 /* Note: We do not have to worry about TARGET_SHORT_BY_BYTES
2173 here because the insn below will generate an LDRH instruction
2174 rather than an LDR instruction, so we cannot get an unaligned
2176 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2177 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
2180 if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2182 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2185 if (! s_register_operand (operands[1], HImode))
2186 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2187 operands[1] = gen_lowpart (SImode, operands[1]);
2188 operands[2] = gen_reg_rtx (SImode);
2191 (define_insn "*zero_extendhisi_insn"
2192 [(set (match_operand:SI 0 "s_register_operand" "=r")
2193 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2196 [(set_attr "type" "load")])
2199 [(set (match_operand:SI 0 "s_register_operand" "")
2200 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2201 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2203 [(set (match_dup 2) (match_dup 1))
2204 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2207 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2212 [(set (match_operand:SI 0 "s_register_operand" "")
2213 (match_operator:SI 3 "shiftable_operator"
2214 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2215 (match_operand:SI 4 "s_register_operand" "")]))
2216 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2218 [(set (match_dup 2) (match_dup 1))
2221 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2224 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2228 (define_expand "zero_extendqisi2"
2229 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2231 (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2234 if (GET_CODE (operands[1]) != MEM)
2236 emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
2242 (define_insn "*load_extendqisi"
2243 [(set (match_operand:SI 0 "s_register_operand" "=r")
2244 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2246 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
2247 [(set_attr "type" "load")])
2250 [(set (match_operand:SI 0 "s_register_operand" "")
2251 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
2252 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2253 "GET_CODE (operands[1]) != MEM"
2254 [(set (match_dup 2) (match_dup 1))
2255 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
2258 (define_insn "*compareqi_eq0"
2260 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
2264 [(set_attr "conds" "set")])
2266 (define_expand "extendhisi2"
2268 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2270 (set (match_operand:SI 0 "s_register_operand" "")
2271 (ashiftrt:SI (match_dup 2)
2276 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2278 /* Note: We do not have to worry about TARGET_SHORT_BY_BYTES
2279 here because the insn below will generate an LDRH instruction
2280 rather than an LDR instruction, so we cannot get an unaligned
2282 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2283 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2287 if (TARGET_SHORT_BY_BYTES && GET_CODE (operands[1]) == MEM)
2289 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
2292 if (! s_register_operand (operands[1], HImode))
2293 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2294 operands[1] = gen_lowpart (SImode, operands[1]);
2295 operands[2] = gen_reg_rtx (SImode);
2298 (define_expand "extendhisi2_mem"
2299 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
2301 (zero_extend:SI (match_dup 7)))
2302 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
2303 (set (match_operand:SI 0 "" "")
2304 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
2309 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2311 mem1 = gen_rtx_MEM (QImode, addr);
2312 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
2313 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
2314 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
2315 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
2316 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
2317 operands[0] = gen_lowpart (SImode, operands[0]);
2319 operands[2] = gen_reg_rtx (SImode);
2320 operands[3] = gen_reg_rtx (SImode);
2321 operands[6] = gen_reg_rtx (SImode);
2324 if (BYTES_BIG_ENDIAN)
2326 operands[4] = operands[2];
2327 operands[5] = operands[3];
2331 operands[4] = operands[3];
2332 operands[5] = operands[2];
2337 (define_insn "*extendhisi_insn"
2338 [(set (match_operand:SI 0 "s_register_operand" "=r")
2339 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2342 [(set_attr "type" "load")])
2345 [(set (match_operand:SI 0 "s_register_operand" "")
2346 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2347 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2349 [(set (match_dup 2) (match_dup 1))
2350 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
2353 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2358 [(set (match_operand:SI 0 "s_register_operand" "")
2359 (match_operator:SI 3 "shiftable_operator"
2360 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2361 (match_operand:SI 4 "s_register_operand" "")]))
2362 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2364 [(set (match_dup 2) (match_dup 1))
2367 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2370 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2374 (define_expand "extendqihi2"
2376 (ashift:SI (match_operand:QI 1 "general_operand" "")
2378 (set (match_operand:HI 0 "s_register_operand" "")
2379 (ashiftrt:SI (match_dup 2)
2384 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2386 emit_insn (gen_rtx_SET (VOIDmode,
2388 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
2391 if (! s_register_operand (operands[1], QImode))
2392 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2393 operands[0] = gen_lowpart (SImode, operands[0]);
2394 operands[1] = gen_lowpart (SImode, operands[1]);
2395 operands[2] = gen_reg_rtx (SImode);
2398 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2399 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2400 (define_insn "*extendqihi_insn"
2401 [(set (match_operand:HI 0 "s_register_operand" "=r")
2402 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
2405 /* If the address is invalid, this will split the instruction into two. */
2406 if (bad_signed_byte_operand (operands[1], QImode))
2408 return \"ldr%?sb\\t%0, %1\";
2410 [(set_attr "type" "load")
2411 (set_attr "length" "8")])
2414 [(set (match_operand:HI 0 "s_register_operand" "")
2415 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2416 "arm_arch4 && reload_completed"
2417 [(set (match_dup 3) (match_dup 1))
2418 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
2421 HOST_WIDE_INT offset;
2423 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
2424 operands[2] = gen_rtx_MEM (QImode, operands[3]);
2425 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2426 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2427 operands[1] = XEXP (operands[1], 0);
2428 if (GET_CODE (operands[1]) == PLUS
2429 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2430 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2431 || const_ok_for_arm (-offset)))
2433 HOST_WIDE_INT low = (offset > 0
2434 ? (offset & 0xff) : -((-offset) & 0xff));
2435 XEXP (operands[2], 0) = plus_constant (operands[3], low);
2436 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2438 /* Ensure the sum is in correct canonical form */
2439 else if (GET_CODE (operands[1]) == PLUS
2440 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2441 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2442 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2443 XEXP (operands[1], 1),
2444 XEXP (operands[1], 0));
2448 (define_expand "extendqisi2"
2450 (ashift:SI (match_operand:QI 1 "general_operand" "")
2452 (set (match_operand:SI 0 "s_register_operand" "")
2453 (ashiftrt:SI (match_dup 2)
2458 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2460 emit_insn (gen_rtx_SET (VOIDmode,
2462 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2465 if (! s_register_operand (operands[1], QImode))
2466 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2467 operands[1] = gen_lowpart (SImode, operands[1]);
2468 operands[2] = gen_reg_rtx (SImode);
2471 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2472 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2473 (define_insn "*extendqisi_insn"
2474 [(set (match_operand:SI 0 "s_register_operand" "=r")
2475 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2478 /* If the address is invalid, this will split the instruction into two. */
2479 if (bad_signed_byte_operand (operands[1], QImode))
2481 return \"ldr%?sb\\t%0, %1\";
2483 [(set_attr "type" "load")
2484 (set_attr "length" "8")])
2487 [(set (match_operand:SI 0 "s_register_operand" "")
2488 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2489 "arm_arch4 && reload_completed"
2490 [(set (match_dup 0) (match_dup 1))
2491 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2494 HOST_WIDE_INT offset;
2496 operands[2] = gen_rtx_MEM (QImode, operands[0]);
2497 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2498 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2499 operands[1] = XEXP (operands[1], 0);
2500 if (GET_CODE (operands[1]) == PLUS
2501 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2502 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2503 || const_ok_for_arm (-offset)))
2505 HOST_WIDE_INT low = (offset > 0
2506 ? (offset & 0xff) : -((-offset) & 0xff));
2507 XEXP (operands[2], 0) = plus_constant (operands[0], low);
2508 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2510 /* Ensure the sum is in correct canonical form */
2511 else if (GET_CODE (operands[1]) == PLUS
2512 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2513 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2514 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2515 XEXP (operands[1], 1),
2516 XEXP (operands[1], 0));
2520 (define_insn "extendsfdf2"
2521 [(set (match_operand:DF 0 "s_register_operand" "=f")
2522 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2525 [(set_attr "type" "ffarith")])
2527 (define_insn "extendsfxf2"
2528 [(set (match_operand:XF 0 "s_register_operand" "=f")
2529 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2530 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2532 [(set_attr "type" "ffarith")])
2534 (define_insn "extenddfxf2"
2535 [(set (match_operand:XF 0 "s_register_operand" "=f")
2536 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2537 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2539 [(set_attr "type" "ffarith")])
2542 ;; Move insns (including loads and stores)
2544 ;; XXX Just some ideas about movti.
2545 ;; I don't think these are a good idea on the arm, there just aren't enough
2547 ;;(define_expand "loadti"
2548 ;; [(set (match_operand:TI 0 "s_register_operand" "")
2549 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
2552 ;;(define_expand "storeti"
2553 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2554 ;; (match_operand:TI 1 "s_register_operand" ""))]
2557 ;;(define_expand "movti"
2558 ;; [(set (match_operand:TI 0 "general_operand" "")
2559 ;; (match_operand:TI 1 "general_operand" ""))]
2565 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2566 ;; operands[1] = copy_to_reg (operands[1]);
2567 ;; if (GET_CODE (operands[0]) == MEM)
2568 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2569 ;; else if (GET_CODE (operands[1]) == MEM)
2570 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2574 ;; emit_insn (insn);
2578 ;; Recognise garbage generated above.
2581 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2582 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2586 ;; register mem = (which_alternative < 3);
2587 ;; register char *template;
2589 ;; operands[mem] = XEXP (operands[mem], 0);
2590 ;; switch (which_alternative)
2592 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2593 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
2594 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
2595 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
2596 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
2597 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
2599 ;; output_asm_insn (template, operands);
2604 (define_insn "movdi"
2605 [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2606 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2609 return (output_move_double (operands));
2611 [(set_attr "length" "8,8,8")
2612 (set_attr "type" "*,load,store2")])
2614 (define_expand "movsi"
2615 [(set (match_operand:SI 0 "general_operand" "")
2616 (match_operand:SI 1 "general_operand" ""))]
2619 /* Everything except mem = const or mem = mem can be done easily */
2620 if (GET_CODE (operands[0]) == MEM)
2621 operands[1] = force_reg (SImode, operands[1]);
2622 if (GET_CODE (operands[1]) == CONST_INT
2623 && !(const_ok_for_arm (INTVAL (operands[1]))
2624 || const_ok_for_arm (~INTVAL (operands[1]))))
2626 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2628 (reload_in_progress || reload_completed ? 0
2629 : preserve_subexpressions_p ()));
2632 if (CONSTANT_P (operands[1]) && flag_pic)
2633 operands[1] = legitimize_pic_address (operands[1], SImode,
2634 ((reload_in_progress
2635 || reload_completed)
2636 ? operands[0] : 0));
2639 (define_insn "*movsi_insn"
2640 [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2641 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
2642 "register_operand (operands[0], SImode)
2643 || register_operand (operands[1], SImode)"
2649 [(set_attr "type" "*,*,load,store1")])
2652 [(set (match_operand:SI 0 "s_register_operand" "")
2653 (match_operand:SI 1 "const_int_operand" ""))]
2654 "! (const_ok_for_arm (INTVAL (operands[1]))
2655 || const_ok_for_arm (~INTVAL (operands[1])))"
2656 [(clobber (const_int 0))]
2658 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2663 (define_expand "movaddr"
2664 [(set (match_operand:SI 0 "s_register_operand" "")
2665 (match_operand:DI 1 "address_operand" ""))]
2669 (define_insn "*movaddr_insn"
2670 [(set (match_operand:SI 0 "s_register_operand" "=r")
2671 (match_operand:DI 1 "address_operand" "p"))]
2673 && (GET_CODE (operands[1]) == LABEL_REF
2674 || (GET_CODE (operands[1]) == CONST
2675 && GET_CODE (XEXP (operands[1], 0)) == PLUS
2676 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2677 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2680 /* When generating pic, we need to load the symbol offset into a register.
2681 So that the optimizer does not confuse this with a normal symbol load
2682 we use an unspec. The offset will be loaded from a constant pool entry,
2683 since that is the only type of relocation we can use. */
2685 (define_insn "pic_load_addr"
2686 [(set (match_operand:SI 0 "s_register_operand" "=r")
2687 (unspec:SI [(match_operand 1 "" "")] 3))]
2690 [(set_attr "type" "load")])
2692 ;; This variant is used for AOF assembly, since it needs to mention the
2693 ;; pic register in the rtl.
2694 (define_expand "pic_load_addr_based"
2695 [(set (match_operand:SI 0 "s_register_operand" "=r")
2696 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
2698 "operands[2] = pic_offset_table_rtx;")
2700 (define_insn "*pic_load_addr_based_insn"
2701 [(set (match_operand:SI 0 "s_register_operand" "=r")
2702 (unspec:SI [(match_operand 1 "" "")
2703 (match_operand 2 "s_register_operand" "r")] 3))]
2704 "flag_pic && operands[2] == pic_offset_table_rtx"
2706 #ifdef AOF_ASSEMBLER
2707 operands[1] = aof_pic_entry (operands[1]);
2709 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
2711 " [(set_attr "type" "load")])
2713 (define_insn "pic_add_dot_plus_eight"
2714 [(set (match_operand 0 "register_operand" "+r")
2715 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
2716 (use (label_ref (match_operand 1 "" "")))]
2719 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
2720 CODE_LABEL_NUMBER (operands[1]));
2721 return \"add%?\\t%0, %|pc, %0\";
2724 ;; If copying one reg to another we can set the condition codes according to
2725 ;; its value. Such a move is common after a return from subroutine and the
2726 ;; result is being tested against zero.
2728 (define_insn "*movsi_compare0"
2729 [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
2731 (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2735 sub%?s\\t%0, %1, #0"
2736 [(set_attr "conds" "set")])
2738 ;; Subroutine to store a half word from a register into memory.
2739 ;; Operand 0 is the source register (HImode)
2740 ;; Operand 1 is the destination address in a register (SImode)
2742 ;; In both this routine and the next, we must be careful not to spill
2743 ;; a memory address of reg+large_const into a separate PLUS insn, since this
2744 ;; can generate unrecognizable rtl.
2746 (define_expand "storehi"
2747 [;; store the low byte
2748 (set (match_operand 1 "" "") (match_dup 3))
2749 ;; extract the high byte
2751 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2752 ;; store the high byte
2753 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
2757 rtx addr = XEXP (operands[1], 0);
2758 enum rtx_code code = GET_CODE (addr);
2760 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2762 addr = force_reg (SImode, addr);
2764 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2765 operands[1] = change_address (operands[1], QImode, NULL_RTX);
2766 operands[3] = gen_lowpart (QImode, operands[0]);
2767 operands[0] = gen_lowpart (SImode, operands[0]);
2768 operands[2] = gen_reg_rtx (SImode);
2772 (define_expand "storehi_bigend"
2773 [(set (match_dup 4) (match_dup 3))
2775 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2776 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
2780 rtx addr = XEXP (operands[1], 0);
2781 enum rtx_code code = GET_CODE (addr);
2783 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2785 addr = force_reg (SImode, addr);
2787 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2788 operands[1] = change_address (operands[1], QImode, NULL_RTX);
2789 operands[3] = gen_lowpart (QImode, operands[0]);
2790 operands[0] = gen_lowpart (SImode, operands[0]);
2791 operands[2] = gen_reg_rtx (SImode);
2795 ;; Subroutine to store a half word integer constant into memory.
2796 (define_expand "storeinthi"
2797 [(set (match_operand 0 "" "")
2798 (subreg:QI (match_operand 1 "" "") 0))
2799 (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
2803 HOST_WIDE_INT value = INTVAL (operands[1]);
2804 rtx addr = XEXP (operands[0], 0);
2805 enum rtx_code code = GET_CODE (addr);
2807 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2809 addr = force_reg (SImode, addr);
2811 operands[1] = gen_reg_rtx (SImode);
2812 if (BYTES_BIG_ENDIAN)
2814 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2815 if ((value & 255) == ((value >> 8) & 255))
2816 operands[2] = operands[1];
2819 operands[2] = gen_reg_rtx (SImode);
2820 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2825 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2826 if ((value & 255) == ((value >> 8) & 255))
2827 operands[2] = operands[1];
2830 operands[2] = gen_reg_rtx (SImode);
2831 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2835 operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
2836 operands[0] = change_address (operands[0], QImode, NULL_RTX);
2840 (define_expand "storehi_single_op"
2841 [(set (match_operand:HI 0 "memory_operand" "")
2842 (match_operand:HI 1 "general_operand" ""))]
2845 if (! s_register_operand (operands[1], HImode))
2846 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2849 (define_expand "movhi"
2850 [(set (match_operand:HI 0 "general_operand" "")
2851 (match_operand:HI 1 "general_operand" ""))]
2855 if (! (reload_in_progress || reload_completed))
2857 if (GET_CODE (operands[0]) == MEM)
2861 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2864 if (GET_CODE (operands[1]) == CONST_INT)
2865 emit_insn (gen_storeinthi (operands[0], operands[1]));
2868 if (GET_CODE (operands[1]) == MEM)
2869 operands[1] = force_reg (HImode, operands[1]);
2870 if (BYTES_BIG_ENDIAN)
2871 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
2873 emit_insn (gen_storehi (operands[1], operands[0]));
2877 /* Sign extend a constant, and keep it in an SImode reg. */
2878 else if (GET_CODE (operands[1]) == CONST_INT)
2880 rtx reg = gen_reg_rtx (SImode);
2881 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2883 /* If the constant is already valid, leave it alone. */
2884 if (! const_ok_for_arm (val))
2886 /* If setting all the top bits will make the constant
2887 loadable in a single instruction, then set them.
2888 Otherwise, sign extend the number. */
2890 if (const_ok_for_arm (~ (val | ~0xffff)))
2892 else if (val & 0x8000)
2896 emit_insn (gen_movsi (reg, GEN_INT (val)));
2897 operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
2899 else if (! arm_arch4)
2901 /* Note: We do not have to worry about TARGET_SHORT_BY_BYTES
2902 for v4 and up architectures because LDRH instructions will
2903 be used to access the HI values, and these cannot generate
2904 unaligned word access faults in the MMU. */
2905 if (GET_CODE (operands[1]) == MEM)
2907 if (TARGET_SHORT_BY_BYTES)
2910 rtx offset = const0_rtx;
2911 rtx reg = gen_reg_rtx (SImode);
2913 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2914 || (GET_CODE (base) == PLUS
2915 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2916 && ((INTVAL(offset) & 1) != 1)
2917 && GET_CODE (base = XEXP (base, 0)) == REG))
2918 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2920 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
2923 new = gen_rtx_MEM (SImode,
2924 plus_constant (base, new_offset));
2925 MEM_COPY_ATTRIBUTES (new, operands[1]);
2926 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2927 emit_insn (gen_movsi (reg, new));
2928 if (((INTVAL (offset) & 2) != 0)
2929 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
2931 rtx reg2 = gen_reg_rtx (SImode);
2933 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
2938 emit_insn (gen_movhi_bytes (reg, operands[1]));
2940 operands[1] = gen_lowpart (HImode, reg);
2942 else if (BYTES_BIG_ENDIAN)
2945 rtx offset = const0_rtx;
2947 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2948 || (GET_CODE (base) == PLUS
2949 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2950 && GET_CODE (base = XEXP (base, 0)) == REG))
2951 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2953 rtx reg = gen_reg_rtx (SImode);
2956 if ((INTVAL (offset) & 2) == 2)
2958 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
2959 new = gen_rtx_MEM (SImode,
2960 plus_constant (base, new_offset));
2961 MEM_COPY_ATTRIBUTES (new, operands[1]);
2962 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2963 emit_insn (gen_movsi (reg, new));
2967 new = gen_rtx_MEM (SImode, XEXP (operands[1], 0));
2968 MEM_COPY_ATTRIBUTES (new, operands[1]);
2969 RTX_UNCHANGING_P (new)
2970 = RTX_UNCHANGING_P (operands[1]);
2971 emit_insn (gen_rotated_loadsi (reg, new));
2974 operands[1] = gen_lowpart (HImode, reg);
2978 emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2985 /* Handle loading a large integer during reload */
2986 else if (GET_CODE (operands[1]) == CONST_INT
2987 && ! const_ok_for_arm (INTVAL (operands[1]))
2988 && ! const_ok_for_arm (~INTVAL (operands[1])))
2990 /* Writing a constant to memory needs a scratch, which should
2991 be handled with SECONDARY_RELOADs. */
2992 if (GET_CODE (operands[0]) != REG)
2995 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
2996 emit_insn (gen_movsi (operands[0], operands[1]));
3002 (define_insn "rotated_loadsi"
3003 [(set (match_operand:SI 0 "s_register_operand" "=r")
3004 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
3006 "! TARGET_SHORT_BY_BYTES"
3011 ops[0] = operands[0];
3012 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
3013 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
3016 [(set_attr "type" "load")])
3018 (define_expand "movhi_bytes"
3019 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3021 (zero_extend:SI (match_dup 6)))
3022 (set (match_operand:SI 0 "" "")
3023 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
3028 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3030 mem1 = gen_rtx_MEM (QImode, addr);
3031 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3032 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
3033 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3034 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3035 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
3036 operands[0] = gen_lowpart (SImode, operands[0]);
3038 operands[2] = gen_reg_rtx (SImode);
3039 operands[3] = gen_reg_rtx (SImode);
3042 if (BYTES_BIG_ENDIAN)
3044 operands[4] = operands[2];
3045 operands[5] = operands[3];
3049 operands[4] = operands[3];
3050 operands[5] = operands[2];
3055 (define_expand "movhi_bigend"
3057 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
3060 (ashiftrt:SI (match_dup 2) (const_int 16)))
3061 (set (match_operand:HI 0 "s_register_operand" "")
3062 (subreg:HI (match_dup 3) 0))]
3065 operands[2] = gen_reg_rtx (SImode);
3066 operands[3] = gen_reg_rtx (SImode);
3069 ;; Pattern to recognise insn generated default case above
3070 (define_insn "*movhi_insn_arch4"
3071 [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
3072 (match_operand:HI 1 "general_operand" "rI,K,m,r"))]
3074 && (GET_CODE (operands[1]) != CONST_INT
3075 || const_ok_for_arm (INTVAL (operands[1]))
3076 || const_ok_for_arm (~INTVAL (operands[1])))"
3078 mov%?\\t%0, %1\\t%@ movhi
3079 mvn%?\\t%0, #%B1\\t%@ movhi
3080 ldr%?h\\t%0, %1\\t%@ movhi
3081 str%?h\\t%1, %0\\t%@ movhi"
3082 [(set_attr "type" "*,*,load,store1")])
3084 (define_insn "*movhi_insn_littleend"
3085 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3086 (match_operand:HI 1 "general_operand" "rI,K,m"))]
3088 && ! BYTES_BIG_ENDIAN
3089 && ! TARGET_SHORT_BY_BYTES
3090 && (GET_CODE (operands[1]) != CONST_INT
3091 || const_ok_for_arm (INTVAL (operands[1]))
3092 || const_ok_for_arm (~INTVAL (operands[1])))"
3094 mov%?\\t%0, %1\\t%@ movhi
3095 mvn%?\\t%0, #%B1\\t%@ movhi
3096 ldr%?\\t%0, %1\\t%@ movhi"
3097 [(set_attr "type" "*,*,load")])
3099 (define_insn "*movhi_insn_bigend"
3100 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3101 (match_operand:HI 1 "general_operand" "rI,K,m"))]
3104 && ! TARGET_SHORT_BY_BYTES
3105 && (GET_CODE (operands[1]) != CONST_INT
3106 || const_ok_for_arm (INTVAL (operands[1]))
3107 || const_ok_for_arm (~INTVAL (operands[1])))"
3109 mov%?\\t%0, %1\\t%@ movhi
3110 mvn%?\\t%0, #%B1\\t%@ movhi
3111 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
3112 [(set_attr "type" "*,*,load")
3113 (set_attr "length" "4,4,8")])
3115 (define_insn "*loadhi_si_bigend"
3116 [(set (match_operand:SI 0 "s_register_operand" "=r")
3117 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
3120 && ! TARGET_SHORT_BY_BYTES"
3121 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
3122 [(set_attr "type" "load")])
3124 (define_insn "*movhi_bytes"
3125 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
3126 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
3127 "TARGET_SHORT_BY_BYTES"
3129 mov%?\\t%0, %1\\t%@ movhi
3130 mvn%?\\t%0, #%B1\\t%@ movhi")
3132 ;; We use a DImode scratch because we may occasionally need an additional
3133 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
3134 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
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:DI 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:DI 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))"
3292 switch (which_alternative)
3295 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
3296 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
3297 case 2: case 3: case 4: return output_move_double (operands);
3298 case 5: return \"mvf%?d\\t%0, %1\";
3299 case 6: return \"mnf%?d\\t%0, #%N1\";
3300 case 7: return \"ldf%?d\\t%0, %1\";
3301 case 8: return \"stf%?d\\t%1, %0\";
3302 case 9: return output_mov_double_fpu_from_arm (operands);
3303 case 10: return output_mov_double_arm_from_fpu (operands);
3307 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
3309 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
3311 ;; Software floating point version. This is essentially the same as movdi.
3312 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
3315 (define_insn "*movdf_soft_insn"
3316 [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
3317 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
3319 "* return output_move_double (operands);"
3320 [(set_attr "length" "8,8,8")
3321 (set_attr "type" "*,load,store2")])
3323 (define_expand "movxf"
3324 [(set (match_operand:XF 0 "general_operand" "")
3325 (match_operand:XF 1 "general_operand" ""))]
3326 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3329 ;; Even when the XFmode patterns aren't enabled, we enable this after
3330 ;; reloading so that we can push floating point registers in the prologue.
3332 (define_insn "*movxf_hard_insn"
3333 [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
3334 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
3335 "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
3337 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];
3540 (define_expand "cmpsf"
3541 [(match_operand:SF 0 "s_register_operand" "")
3542 (match_operand:SF 1 "fpu_rhs_operand" "")]
3546 arm_compare_op0 = operands[0];
3547 arm_compare_op1 = operands[1];
3552 (define_expand "cmpdf"
3553 [(match_operand:DF 0 "s_register_operand" "")
3554 (match_operand:DF 1 "fpu_rhs_operand" "")]
3558 arm_compare_op0 = operands[0];
3559 arm_compare_op1 = operands[1];
3564 (define_expand "cmpxf"
3565 [(match_operand:XF 0 "s_register_operand" "")
3566 (match_operand:XF 1 "fpu_rhs_operand" "")]
3567 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3570 arm_compare_op0 = operands[0];
3571 arm_compare_op1 = operands[1];
3576 (define_insn "*cmpsi_insn"
3578 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3579 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3584 [(set_attr "conds" "set")])
3586 (define_insn "*cmpsi_shiftsi"
3588 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3589 (match_operator:SI 3 "shift_operator"
3590 [(match_operand:SI 1 "s_register_operand" "r")
3591 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3594 [(set_attr "conds" "set")])
3596 (define_insn "*cmpsi_shiftsi_swp"
3597 [(set (reg:CC_SWP 24)
3598 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
3599 [(match_operand:SI 1 "s_register_operand" "r")
3600 (match_operand:SI 2 "reg_or_int_operand" "rM")])
3601 (match_operand:SI 0 "s_register_operand" "r")))]
3604 [(set_attr "conds" "set")])
3606 (define_insn "*cmpsi_neg_shiftsi"
3608 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3609 (neg:SI (match_operator:SI 3 "shift_operator"
3610 [(match_operand:SI 1 "s_register_operand" "r")
3611 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3614 [(set_attr "conds" "set")])
3616 (define_insn "*cmpsf_insn"
3618 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3619 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3624 [(set_attr "conds" "set")
3625 (set_attr "type" "f_2_r")])
3627 (define_insn "*cmpdf_insn"
3629 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3630 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3635 [(set_attr "conds" "set")
3636 (set_attr "type" "f_2_r")])
3638 (define_insn "*cmpesfdf_df"
3640 (compare:CCFP (float_extend:DF
3641 (match_operand:SF 0 "s_register_operand" "f,f"))
3642 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3647 [(set_attr "conds" "set")
3648 (set_attr "type" "f_2_r")])
3650 (define_insn "*cmpdf_esfdf"
3652 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3654 (match_operand:SF 1 "s_register_operand" "f"))))]
3657 [(set_attr "conds" "set")
3658 (set_attr "type" "f_2_r")])
3660 (define_insn "*cmpxf_insn"
3662 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3663 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3664 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3668 [(set_attr "conds" "set")
3669 (set_attr "type" "f_2_r")])
3671 (define_insn "*cmpsf_trap"
3672 [(set (reg:CCFPE 24)
3673 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3674 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3679 [(set_attr "conds" "set")
3680 (set_attr "type" "f_2_r")])
3682 (define_insn "*cmpdf_trap"
3683 [(set (reg:CCFPE 24)
3684 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3685 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3690 [(set_attr "conds" "set")
3691 (set_attr "type" "f_2_r")])
3693 (define_insn "*cmp_esfdf_df_trap"
3694 [(set (reg:CCFPE 24)
3695 (compare:CCFPE (float_extend:DF
3696 (match_operand:SF 0 "s_register_operand" "f,f"))
3697 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3702 [(set_attr "conds" "set")
3703 (set_attr "type" "f_2_r")])
3705 (define_insn "*cmp_df_esfdf_trap"
3706 [(set (reg:CCFPE 24)
3707 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3709 (match_operand:SF 1 "s_register_operand" "f"))))]
3712 [(set_attr "conds" "set")
3713 (set_attr "type" "f_2_r")])
3715 (define_insn "*cmpxf_trap"
3716 [(set (reg:CCFPE 24)
3717 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3718 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3719 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3723 [(set_attr "conds" "set")
3724 (set_attr "type" "f_2_r")])
3726 ; This insn allows redundant compares to be removed by cse, nothing should
3727 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3728 ; is deleted later on. The match_dup will match the mode here, so that
3729 ; mode changes of the condition codes aren't lost by this even though we don't
3730 ; specify what they are.
3732 (define_insn "*deleted_compare"
3733 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3735 "\\t%@ deleted compare"
3736 [(set_attr "conds" "set")
3737 (set_attr "length" "0")])
3740 ;; Conditional branch insns
3742 (define_expand "beq"
3744 (if_then_else (eq (match_dup 1) (const_int 0))
3745 (label_ref (match_operand 0 "" ""))
3750 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);
3754 (define_expand "bne"
3756 (if_then_else (ne (match_dup 1) (const_int 0))
3757 (label_ref (match_operand 0 "" ""))
3762 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);
3766 (define_expand "bgt"
3768 (if_then_else (gt (match_dup 1) (const_int 0))
3769 (label_ref (match_operand 0 "" ""))
3774 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);
3778 (define_expand "ble"
3780 (if_then_else (le (match_dup 1) (const_int 0))
3781 (label_ref (match_operand 0 "" ""))
3786 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);
3790 (define_expand "bge"
3792 (if_then_else (ge (match_dup 1) (const_int 0))
3793 (label_ref (match_operand 0 "" ""))
3798 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);
3802 (define_expand "blt"
3804 (if_then_else (lt (match_dup 1) (const_int 0))
3805 (label_ref (match_operand 0 "" ""))
3810 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);
3814 (define_expand "bgtu"
3816 (if_then_else (gtu (match_dup 1) (const_int 0))
3817 (label_ref (match_operand 0 "" ""))
3822 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);
3826 (define_expand "bleu"
3828 (if_then_else (leu (match_dup 1) (const_int 0))
3829 (label_ref (match_operand 0 "" ""))
3834 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);
3838 (define_expand "bgeu"
3840 (if_then_else (geu (match_dup 1) (const_int 0))
3841 (label_ref (match_operand 0 "" ""))
3846 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);
3850 (define_expand "bltu"
3852 (if_then_else (ltu (match_dup 1) (const_int 0))
3853 (label_ref (match_operand 0 "" ""))
3858 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);
3862 ;; patterns to match conditional branch insns
3864 (define_insn "*condbranch"
3866 (if_then_else (match_operator 1 "comparison_operator"
3867 [(match_operand 2 "cc_register" "") (const_int 0)])
3868 (label_ref (match_operand 0 "" ""))
3873 extern int arm_ccfsm_state;
3875 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3877 arm_ccfsm_state += 2;
3880 return \"b%d1\\t%l0\";
3882 [(set_attr "conds" "use")])
3884 (define_insn "*condbranch_reversed"
3886 (if_then_else (match_operator 1 "comparison_operator"
3887 [(match_operand 2 "cc_register" "") (const_int 0)])
3889 (label_ref (match_operand 0 "" ""))))]
3893 extern int arm_ccfsm_state;
3895 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3897 arm_ccfsm_state += 2;
3900 return \"b%D1\\t%l0\";
3902 [(set_attr "conds" "use")])
3907 (define_expand "seq"
3908 [(set (match_operand:SI 0 "s_register_operand" "=r")
3909 (eq:SI (match_dup 1) (const_int 0)))]
3913 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);
3917 (define_expand "sne"
3918 [(set (match_operand:SI 0 "s_register_operand" "=r")
3919 (ne:SI (match_dup 1) (const_int 0)))]
3923 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);
3927 (define_expand "sgt"
3928 [(set (match_operand:SI 0 "s_register_operand" "=r")
3929 (gt:SI (match_dup 1) (const_int 0)))]
3933 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);
3937 (define_expand "sle"
3938 [(set (match_operand:SI 0 "s_register_operand" "=r")
3939 (le:SI (match_dup 1) (const_int 0)))]
3943 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);
3947 (define_expand "sge"
3948 [(set (match_operand:SI 0 "s_register_operand" "=r")
3949 (ge:SI (match_dup 1) (const_int 0)))]
3953 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);
3957 (define_expand "slt"
3958 [(set (match_operand:SI 0 "s_register_operand" "=r")
3959 (lt:SI (match_dup 1) (const_int 0)))]
3963 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);
3967 (define_expand "sgtu"
3968 [(set (match_operand:SI 0 "s_register_operand" "=r")
3969 (gtu:SI (match_dup 1) (const_int 0)))]
3973 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);
3977 (define_expand "sleu"
3978 [(set (match_operand:SI 0 "s_register_operand" "=r")
3979 (leu:SI (match_dup 1) (const_int 0)))]
3983 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);
3987 (define_expand "sgeu"
3988 [(set (match_operand:SI 0 "s_register_operand" "=r")
3989 (geu:SI (match_dup 1) (const_int 0)))]
3993 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);
3997 (define_expand "sltu"
3998 [(set (match_operand:SI 0 "s_register_operand" "=r")
3999 (ltu:SI (match_dup 1) (const_int 0)))]
4003 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);
4007 (define_insn "*mov_scc"
4008 [(set (match_operand:SI 0 "s_register_operand" "=r")
4009 (match_operator:SI 1 "comparison_operator"
4010 [(match_operand 2 "cc_register" "") (const_int 0)]))]
4012 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
4013 [(set_attr "conds" "use")
4014 (set_attr "length" "8")])
4016 (define_insn "*mov_negscc"
4017 [(set (match_operand:SI 0 "s_register_operand" "=r")
4018 (neg:SI (match_operator:SI 1 "comparison_operator"
4019 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4021 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
4022 [(set_attr "conds" "use")
4023 (set_attr "length" "8")])
4025 (define_insn "*mov_notscc"
4026 [(set (match_operand:SI 0 "s_register_operand" "=r")
4027 (not:SI (match_operator:SI 1 "comparison_operator"
4028 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4030 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
4031 [(set_attr "conds" "use")
4032 (set_attr "length" "8")])
4035 ;; Conditional move insns
4037 (define_expand "movsicc"
4038 [(set (match_operand:SI 0 "s_register_operand" "")
4039 (if_then_else:SI (match_operand 1 "comparison_operator" "")
4040 (match_operand:SI 2 "arm_not_operand" "")
4041 (match_operand:SI 3 "arm_not_operand" "")))]
4045 enum rtx_code code = GET_CODE (operands[1]);
4046 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
4048 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4051 (define_expand "movsfcc"
4052 [(set (match_operand:SF 0 "s_register_operand" "")
4053 (if_then_else:SF (match_operand 1 "comparison_operator" "")
4054 (match_operand:SF 2 "s_register_operand" "")
4055 (match_operand:SF 3 "nonmemory_operand" "")))]
4059 enum rtx_code code = GET_CODE (operands[1]);
4062 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
4063 Otherwise, ensure it is a valid FP add operand */
4064 if ((! TARGET_HARD_FLOAT)
4065 || (! fpu_add_operand (operands[3], SFmode)))
4066 operands[3] = force_reg (SFmode, operands[3]);
4068 ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
4070 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4073 (define_expand "movdfcc"
4074 [(set (match_operand:DF 0 "s_register_operand" "")
4075 (if_then_else:DF (match_operand 1 "comparison_operator" "")
4076 (match_operand:DF 2 "s_register_operand" "")
4077 (match_operand:DF 3 "fpu_add_operand" "")))]
4081 enum rtx_code code = GET_CODE (operands[1]);
4082 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
4084 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4087 (define_insn "*movsicc_insn"
4088 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
4090 (match_operator 3 "comparison_operator"
4091 [(match_operand 4 "cc_register" "") (const_int 0)])
4092 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
4093 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
4100 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
4101 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
4102 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
4103 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
4104 [(set_attr "length" "4,4,4,4,8,8,8,8")
4105 (set_attr "conds" "use")])
4107 (define_insn "*movsfcc_hard_insn"
4108 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4110 (match_operator 3 "comparison_operator"
4111 [(match_operand 4 "cc_register" "") (const_int 0)])
4112 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4113 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4120 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
4121 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
4122 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
4123 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
4124 [(set_attr "length" "4,4,4,4,8,8,8,8")
4125 (set_attr "type" "ffarith")
4126 (set_attr "conds" "use")])
4128 (define_insn "*movsfcc_soft_insn"
4129 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
4130 (if_then_else:SF (match_operator 3 "comparison_operator"
4131 [(match_operand 4 "cc_register" "") (const_int 0)])
4132 (match_operand:SF 1 "s_register_operand" "0,r")
4133 (match_operand:SF 2 "s_register_operand" "r,0")))]
4138 [(set_attr "conds" "use")])
4140 (define_insn "*movdfcc_insn"
4141 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4143 (match_operator 3 "comparison_operator"
4144 [(match_operand 4 "cc_register" "") (const_int 0)])
4145 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4146 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4153 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
4154 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
4155 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
4156 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
4157 [(set_attr "length" "4,4,4,4,8,8,8,8")
4158 (set_attr "type" "ffarith")
4159 (set_attr "conds" "use")])
4161 ;; Jump and linkage insns
4165 (label_ref (match_operand 0 "" "")))]
4169 extern int arm_ccfsm_state;
4171 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4173 arm_ccfsm_state += 2;
4176 return \"b%?\\t%l0\";
4179 (define_expand "call"
4180 [(parallel [(call (match_operand 0 "memory_operand" "")
4181 (match_operand 1 "general_operand" ""))
4182 (clobber (reg:SI 14))])]
4186 (define_insn "*call_reg"
4187 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
4188 (match_operand 1 "" "g"))
4189 (clobber (reg:SI 14))]
4192 return output_call (operands);
4194 ;; length is worst case, normally it is only two
4195 [(set_attr "length" "12")
4196 (set_attr "type" "call")])
4198 (define_insn "*call_mem"
4199 [(call (mem:SI (match_operand 0 "memory_operand" "m"))
4200 (match_operand 1 "general_operand" "g"))
4201 (clobber (reg:SI 14))]
4204 return output_call_mem (operands);
4206 [(set_attr "length" "12")
4207 (set_attr "type" "call")])
4209 (define_expand "call_value"
4210 [(parallel [(set (match_operand 0 "" "=rf")
4211 (call (match_operand 1 "memory_operand" "m")
4212 (match_operand 2 "general_operand" "g")))
4213 (clobber (reg:SI 14))])]
4217 (define_insn "*call_value_reg"
4218 [(set (match_operand 0 "" "=rf")
4219 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4220 (match_operand 2 "general_operand" "g")))
4221 (clobber (reg:SI 14))]
4224 return output_call (&operands[1]);
4226 [(set_attr "length" "12")
4227 (set_attr "type" "call")])
4229 (define_insn "*call_value_mem"
4230 [(set (match_operand 0 "" "=rf")
4231 (call (mem:SI (match_operand 1 "memory_operand" "m"))
4232 (match_operand 2 "general_operand" "g")))
4233 (clobber (reg:SI 14))]
4234 "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
4236 return output_call_mem (&operands[1]);
4238 [(set_attr "length" "12")
4239 (set_attr "type" "call")])
4241 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
4242 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
4244 (define_insn "*call_symbol"
4245 [(call (mem:SI (match_operand:SI 0 "" "X"))
4246 (match_operand:SI 1 "general_operand" "g"))
4247 (clobber (reg:SI 14))]
4248 "GET_CODE (operands[0]) == SYMBOL_REF"
4251 return NEED_PLT_GOT ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
4253 [(set_attr "type" "call")])
4255 (define_insn "*call_value_symbol"
4256 [(set (match_operand 0 "s_register_operand" "=rf")
4257 (call (mem:SI (match_operand:SI 1 "" "X"))
4258 (match_operand:SI 2 "general_operand" "g")))
4259 (clobber (reg:SI 14))]
4260 "GET_CODE(operands[1]) == SYMBOL_REF"
4263 return NEED_PLT_GOT ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
4265 [(set_attr "type" "call")])
4267 ;; Often the return insn will be the same as loading from memory, so set attr
4268 (define_insn "return"
4270 "USE_RETURN_INSN(FALSE)"
4273 extern int arm_ccfsm_state;
4275 if (arm_ccfsm_state == 2)
4277 arm_ccfsm_state += 2;
4280 return output_return_instruction (NULL, TRUE, FALSE);
4282 [(set_attr "type" "load")])
4284 (define_insn "*cond_return"
4286 (if_then_else (match_operator 0 "comparison_operator"
4287 [(match_operand 1 "cc_register" "") (const_int 0)])
4290 "USE_RETURN_INSN(TRUE)"
4293 extern int arm_ccfsm_state;
4295 if (arm_ccfsm_state == 2)
4297 arm_ccfsm_state += 2;
4300 return output_return_instruction (operands[0], TRUE, FALSE);
4302 [(set_attr "conds" "use")
4303 (set_attr "type" "load")])
4305 (define_insn "*cond_return_inverted"
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, TRUE);
4323 [(set_attr "conds" "use")
4324 (set_attr "type" "load")])
4326 ;; Call subroutine returning any type.
4328 (define_expand "untyped_call"
4329 [(parallel [(call (match_operand 0 "" "")
4331 (match_operand 1 "" "")
4332 (match_operand 2 "" "")])]
4338 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
4340 for (i = 0; i < XVECLEN (operands[2], 0); i++)
4342 rtx set = XVECEXP (operands[2], 0, i);
4343 emit_move_insn (SET_DEST (set), SET_SRC (set));
4346 /* The optimizer does not know that the call sets the function value
4347 registers we stored in the result block. We avoid problems by
4348 claiming that all hard registers are used and clobbered at this
4350 emit_insn (gen_blockage ());
4355 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
4356 ;; all of memory. This blocks insns from being moved across this point.
4358 (define_insn "blockage"
4359 [(unspec_volatile [(const_int 0)] 0)]
4362 [(set_attr "length" "0")
4363 (set_attr "type" "block")])
4365 (define_expand "casesi"
4366 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
4367 (match_operand:SI 1 "const_int_operand" "") ; lower bound
4368 (match_operand:SI 2 "const_int_operand" "") ; total range
4369 (match_operand:SI 3 "" "") ; table label
4370 (match_operand:SI 4 "" "")] ; Out of range label
4375 if (operands[1] != const0_rtx)
4377 reg = gen_reg_rtx (SImode);
4378 emit_insn (gen_addsi3 (reg, operands[0],
4379 GEN_INT (-INTVAL (operands[1]))));
4383 if (! const_ok_for_arm (INTVAL (operands[2])))
4384 operands[2] = force_reg (SImode, operands[2]);
4386 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
4391 ;; The USE in this pattern is needed to tell flow analysis that this is
4392 ;; a CASESI insn. It has no other purpose.
4393 (define_insn "casesi_internal"
4394 [(parallel [(set (pc)
4396 (leu (match_operand:SI 0 "s_register_operand" "r")
4397 (match_operand:SI 1 "arm_rhs_operand" "rI"))
4398 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
4399 (label_ref (match_operand 2 "" ""))))
4400 (label_ref (match_operand 3 "" ""))))
4401 (use (label_ref (match_dup 2)))])]
4405 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
4406 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
4408 [(set_attr "conds" "clob")
4409 (set_attr "length" "12")])
4411 (define_insn "indirect_jump"
4413 (match_operand:SI 0 "s_register_operand" "r"))]
4415 "mov%?\\t%|pc, %0\\t%@ indirect jump")
4417 (define_insn "*load_indirect_jump"
4419 (match_operand:SI 0 "memory_operand" "m"))]
4421 "ldr%?\\t%|pc, %0\\t%@ indirect jump"
4422 [(set_attr "type" "load")])
4429 "mov%?\\t%|r0, %|r0\\t%@ nop")
4431 ;; Patterns to allow combination of arithmetic, cond code and shifts
4433 (define_insn "*arith_shiftsi"
4434 [(set (match_operand:SI 0 "s_register_operand" "=r")
4435 (match_operator:SI 1 "shiftable_operator"
4436 [(match_operator:SI 3 "shift_operator"
4437 [(match_operand:SI 4 "s_register_operand" "r")
4438 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4439 (match_operand:SI 2 "s_register_operand" "r")]))]
4441 "%i1%?\\t%0, %2, %4%S3")
4443 (define_insn "*arith_shiftsi_compare0"
4444 [(set (reg:CC_NOOV 24)
4445 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4446 [(match_operator:SI 3 "shift_operator"
4447 [(match_operand:SI 4 "s_register_operand" "r")
4448 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4449 (match_operand:SI 2 "s_register_operand" "r")])
4451 (set (match_operand:SI 0 "s_register_operand" "=r")
4452 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4455 "%i1%?s\\t%0, %2, %4%S3"
4456 [(set_attr "conds" "set")])
4458 (define_insn "*arith_shiftsi_compare0_scratch"
4459 [(set (reg:CC_NOOV 24)
4460 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4461 [(match_operator:SI 3 "shift_operator"
4462 [(match_operand:SI 4 "s_register_operand" "r")
4463 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4464 (match_operand:SI 2 "s_register_operand" "r")])
4466 (clobber (match_scratch:SI 0 "=r"))]
4468 "%i1%?s\\t%0, %2, %4%S3"
4469 [(set_attr "conds" "set")])
4471 (define_insn "*sub_shiftsi"
4472 [(set (match_operand:SI 0 "s_register_operand" "=r")
4473 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4474 (match_operator:SI 2 "shift_operator"
4475 [(match_operand:SI 3 "s_register_operand" "r")
4476 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4478 "sub%?\\t%0, %1, %3%S2")
4480 (define_insn "*sub_shiftsi_compare0"
4481 [(set (reg:CC_NOOV 24)
4483 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4484 (match_operator:SI 2 "shift_operator"
4485 [(match_operand:SI 3 "s_register_operand" "r")
4486 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4488 (set (match_operand:SI 0 "s_register_operand" "=r")
4489 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4492 "sub%?s\\t%0, %1, %3%S2"
4493 [(set_attr "conds" "set")])
4495 (define_insn "*sub_shiftsi_compare0_scratch"
4496 [(set (reg:CC_NOOV 24)
4498 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4499 (match_operator:SI 2 "shift_operator"
4500 [(match_operand:SI 3 "s_register_operand" "r")
4501 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4503 (clobber (match_scratch:SI 0 "=r"))]
4505 "sub%?s\\t%0, %1, %3%S2"
4506 [(set_attr "conds" "set")])
4508 ;; These variants of the above insns can occur if the first operand is the
4509 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
4510 ;; seem to be a way around it. Most of the predicates have to be null
4511 ;; because the format can be generated part way through reload, so
4512 ;; if we don't match it as soon as it becomes available, reload doesn't know
4513 ;; how to reload pseudos that haven't got hard registers; the constraints will
4514 ;; sort everything out.
4516 (define_insn "*reload_mulsi3"
4517 [(set (match_operand:SI 0 "" "=&r")
4518 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4519 [(match_operand:SI 3 "" "r")
4520 (match_operand:SI 4 "" "rM")])
4521 (match_operand:SI 2 "" "r"))
4522 (match_operand:SI 1 "const_int_operand" "n")))]
4523 "reload_in_progress"
4525 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4526 operands[2] = operands[1];
4527 operands[1] = operands[0];
4528 return output_add_immediate (operands);
4530 ; we have no idea how long the add_immediate is, it could be up to 4.
4531 [(set_attr "length" "20")])
4533 (define_insn "*reload_mulsi_compare0"
4534 [(set (reg:CC_NOOV 24)
4535 (compare:CC_NOOV (plus:SI
4537 (match_operator:SI 5 "shift_operator"
4538 [(match_operand:SI 3 "" "r")
4539 (match_operand:SI 4 "" "rM")])
4540 (match_operand:SI 1 "" "r"))
4541 (match_operand:SI 2 "const_int_operand" "n"))
4543 (set (match_operand:SI 0 "" "=&r")
4544 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4547 "reload_in_progress"
4549 output_add_immediate (operands);
4550 return \"add%?s\\t%0, %0, %3%S5\";
4552 [(set_attr "conds" "set")
4553 (set_attr "length" "20")])
4555 (define_insn "*reload_mulsi_compare0_scratch"
4556 [(set (reg:CC_NOOV 24)
4557 (compare:CC_NOOV (plus:SI
4559 (match_operator:SI 5 "shift_operator"
4560 [(match_operand:SI 3 "" "r")
4561 (match_operand:SI 4 "" "rM")])
4562 (match_operand:SI 1 "" "r"))
4563 (match_operand:SI 2 "const_int_operand" "n"))
4565 (clobber (match_scratch:SI 0 "=&r"))]
4566 "reload_in_progress"
4568 output_add_immediate (operands);
4569 return \"add%?s\\t%0, %0, %3%S5\";
4571 [(set_attr "conds" "set")
4572 (set_attr "length" "20")])
4574 ;; These are similar, but are needed when the mla pattern contains the
4575 ;; eliminated register as operand 3.
4577 (define_insn "*reload_muladdsi"
4578 [(set (match_operand:SI 0 "" "=&r,&r")
4579 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4580 (match_operand:SI 2 "" "r,r"))
4581 (match_operand:SI 3 "" "r,r"))
4582 (match_operand:SI 4 "const_int_operand" "n,n")))]
4583 "reload_in_progress"
4585 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4586 operands[2] = operands[4];
4587 operands[1] = operands[0];
4588 return output_add_immediate (operands);
4590 [(set_attr "length" "20")
4591 (set_attr "type" "mult")])
4593 (define_insn "*reload_muladdsi_compare0"
4594 [(set (reg:CC_NOOV 24)
4595 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4596 (match_operand:SI 3 "" "r")
4597 (match_operand:SI 4 "" "r"))
4598 (match_operand:SI 1 "" "r"))
4599 (match_operand:SI 2 "const_int_operand" "n"))
4601 (set (match_operand:SI 0 "" "=&r")
4602 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4604 "reload_in_progress"
4606 output_add_immediate (operands);
4607 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4610 [(set_attr "length" "20")
4611 (set_attr "conds" "set")
4612 (set_attr "type" "mult")])
4614 (define_insn "*reload_muladdsi_compare0_scratch"
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 (clobber (match_scratch:SI 0 "=&r"))]
4623 "reload_in_progress"
4625 output_add_immediate (operands);
4626 return \"mla%?s\\t%0, %3, %4, %0\";
4628 [(set_attr "length" "20")
4629 (set_attr "conds" "set")
4630 (set_attr "type" "mult")])
4634 (define_insn "*and_scc"
4635 [(set (match_operand:SI 0 "s_register_operand" "=r")
4636 (and:SI (match_operator 1 "comparison_operator"
4637 [(match_operand 3 "cc_register" "") (const_int 0)])
4638 (match_operand:SI 2 "s_register_operand" "r")))]
4640 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
4641 [(set_attr "conds" "use")
4642 (set_attr "length" "8")])
4644 (define_insn "*ior_scc"
4645 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4646 (ior:SI (match_operator 2 "comparison_operator"
4647 [(match_operand 3 "cc_register" "") (const_int 0)])
4648 (match_operand:SI 1 "s_register_operand" "0,?r")))]
4652 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
4653 [(set_attr "conds" "use")
4654 (set_attr "length" "4,8")])
4656 (define_insn "*compare_scc"
4657 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4658 (match_operator 1 "comparison_operator"
4659 [(match_operand:SI 2 "s_register_operand" "r,r")
4660 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
4661 (clobber (reg:CC 24))]
4664 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4665 return \"mov\\t%0, %2, lsr #31\";
4667 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4668 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4670 if (GET_CODE (operands[1]) == NE)
4672 if (which_alternative == 1)
4673 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4674 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4676 if (which_alternative == 1)
4677 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4679 output_asm_insn (\"cmp\\t%2, %3\", operands);
4680 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4682 [(set_attr "conds" "clob")
4683 (set_attr "length" "12")])
4685 (define_insn "*cond_move"
4686 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4687 (if_then_else:SI (match_operator 3 "equality_operator"
4688 [(match_operator 4 "comparison_operator"
4689 [(match_operand 5 "cc_register" "") (const_int 0)])
4691 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4692 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4695 if (GET_CODE (operands[3]) == NE)
4697 if (which_alternative != 1)
4698 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4699 if (which_alternative != 0)
4700 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4703 if (which_alternative != 0)
4704 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4705 if (which_alternative != 1)
4706 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4709 [(set_attr "conds" "use")
4710 (set_attr "length" "4,4,8")])
4712 (define_insn "*cond_arith"
4713 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4714 (match_operator:SI 5 "shiftable_operator"
4715 [(match_operator:SI 4 "comparison_operator"
4716 [(match_operand:SI 2 "s_register_operand" "r,r")
4717 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4718 (match_operand:SI 1 "s_register_operand" "0,?r")]))
4719 (clobber (reg:CC 24))]
4722 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4723 return \"%i5\\t%0, %1, %2, lsr #31\";
4725 output_asm_insn (\"cmp\\t%2, %3\", operands);
4726 if (GET_CODE (operands[5]) == AND)
4727 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4728 else if (GET_CODE (operands[5]) == MINUS)
4729 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4730 else if (which_alternative != 0)
4731 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4732 return \"%i5%d4\\t%0, %1, #1\";
4734 [(set_attr "conds" "clob")
4735 (set_attr "length" "12")])
4737 (define_insn "*cond_sub"
4738 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4739 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4740 (match_operator:SI 4 "comparison_operator"
4741 [(match_operand:SI 2 "s_register_operand" "r,r")
4742 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4743 (clobber (reg:CC 24))]
4746 output_asm_insn (\"cmp\\t%2, %3\", operands);
4747 if (which_alternative != 0)
4748 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4749 return \"sub%d4\\t%0, %1, #1\";
4751 [(set_attr "conds" "clob")
4752 (set_attr "length" "8,12")])
4754 (define_insn "*cmp_ite0"
4755 [(set (match_operand 6 "dominant_cc_register" "")
4758 (match_operator 4 "comparison_operator"
4759 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4760 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4761 (match_operator:SI 5 "comparison_operator"
4762 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4763 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4769 char* opcodes[4][2] =
4771 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
4772 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
4773 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
4774 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
4775 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
4778 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
4780 return opcodes[which_alternative][swap];
4783 [(set_attr "conds" "set")
4784 (set_attr "length" "8")])
4786 (define_insn "*cmp_ite1"
4787 [(set (match_operand 6 "dominant_cc_register" "")
4790 (match_operator 4 "comparison_operator"
4791 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4792 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4793 (match_operator:SI 5 "comparison_operator"
4794 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4795 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4801 char* opcodes[4][2] =
4803 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
4804 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
4805 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
4806 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
4807 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
4810 comparison_dominates_p (GET_CODE (operands[5]),
4811 reverse_condition (GET_CODE (operands[4])));
4813 return opcodes[which_alternative][swap];
4816 [(set_attr "conds" "set")
4817 (set_attr "length" "8")])
4819 (define_insn "*negscc"
4820 [(set (match_operand:SI 0 "s_register_operand" "=r")
4821 (neg:SI (match_operator 3 "comparison_operator"
4822 [(match_operand:SI 1 "s_register_operand" "r")
4823 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4824 (clobber (reg:CC 24))]
4827 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4828 return \"mov\\t%0, %1, asr #31\";
4830 if (GET_CODE (operands[3]) == NE)
4831 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4833 if (GET_CODE (operands[3]) == GT)
4834 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4836 output_asm_insn (\"cmp\\t%1, %2\", operands);
4837 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4838 return \"mvn%d3\\t%0, #0\";
4840 [(set_attr "conds" "clob")
4841 (set_attr "length" "12")])
4843 (define_insn "movcond"
4844 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4846 (match_operator 5 "comparison_operator"
4847 [(match_operand:SI 3 "s_register_operand" "r,r,r")
4848 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4849 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4850 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4851 (clobber (reg:CC 24))]
4854 if (GET_CODE (operands[5]) == LT
4855 && (operands[4] == const0_rtx))
4857 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4859 if (operands[2] == const0_rtx)
4860 return \"and\\t%0, %1, %3, asr #31\";
4861 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4863 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4865 if (operands[1] == const0_rtx)
4866 return \"bic\\t%0, %2, %3, asr #31\";
4867 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4869 /* The only case that falls through to here is when both ops 1 & 2
4873 if (GET_CODE (operands[5]) == GE
4874 && (operands[4] == const0_rtx))
4876 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4878 if (operands[2] == const0_rtx)
4879 return \"bic\\t%0, %1, %3, asr #31\";
4880 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4882 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4884 if (operands[1] == const0_rtx)
4885 return \"and\\t%0, %2, %3, asr #31\";
4886 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4888 /* The only case that falls through to here is when both ops 1 & 2
4891 if (GET_CODE (operands[4]) == CONST_INT
4892 && !const_ok_for_arm (INTVAL (operands[4])))
4893 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4895 output_asm_insn (\"cmp\\t%3, %4\", operands);
4896 if (which_alternative != 0)
4897 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4898 if (which_alternative != 1)
4899 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4902 [(set_attr "conds" "clob")
4903 (set_attr "length" "8,8,12")])
4905 (define_insn "*ifcompare_plus_move"
4906 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4907 (if_then_else:SI (match_operator 6 "comparison_operator"
4908 [(match_operand:SI 4 "s_register_operand" "r,r")
4909 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4911 (match_operand:SI 2 "s_register_operand" "r,r")
4912 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
4913 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
4914 (clobber (reg:CC 24))]
4917 [(set_attr "conds" "clob")
4918 (set_attr "length" "8,12")])
4920 (define_insn "*if_plus_move"
4921 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4923 (match_operator 4 "comparison_operator"
4924 [(match_operand 5 "cc_register" "") (const_int 0)])
4926 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
4927 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
4928 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
4932 sub%d4\\t%0, %2, #%n3
4933 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4934 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
4935 [(set_attr "conds" "use")
4936 (set_attr "length" "4,4,8,8")
4937 (set_attr "type" "*,*,*,*")])
4939 (define_insn "*ifcompare_move_plus"
4940 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4941 (if_then_else:SI (match_operator 6 "comparison_operator"
4942 [(match_operand:SI 4 "s_register_operand" "r,r")
4943 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4944 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4946 (match_operand:SI 2 "s_register_operand" "r,r")
4947 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4948 (clobber (reg:CC 24))]
4951 [(set_attr "conds" "clob")
4952 (set_attr "length" "8,12")])
4954 (define_insn "*if_move_plus"
4955 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4957 (match_operator 4 "comparison_operator"
4958 [(match_operand 5 "cc_register" "") (const_int 0)])
4959 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4961 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
4962 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
4966 sub%D4\\t%0, %2, #%n3
4967 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4968 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
4969 [(set_attr "conds" "use")
4970 (set_attr "length" "4,4,8,8")
4971 (set_attr "type" "*,*,*,*")])
4973 (define_insn "*ifcompare_arith_arith"
4974 [(set (match_operand:SI 0 "s_register_operand" "=r")
4975 (if_then_else:SI (match_operator 9 "comparison_operator"
4976 [(match_operand:SI 5 "s_register_operand" "r")
4977 (match_operand:SI 6 "arm_add_operand" "rIL")])
4978 (match_operator:SI 8 "shiftable_operator"
4979 [(match_operand:SI 1 "s_register_operand" "r")
4980 (match_operand:SI 2 "arm_rhs_operand" "rI")])
4981 (match_operator:SI 7 "shiftable_operator"
4982 [(match_operand:SI 3 "s_register_operand" "r")
4983 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
4984 (clobber (reg:CC 24))]
4987 [(set_attr "conds" "clob")
4988 (set_attr "length" "12")])
4990 (define_insn "*if_arith_arith"
4991 [(set (match_operand:SI 0 "s_register_operand" "=r")
4992 (if_then_else:SI (match_operator 5 "comparison_operator"
4993 [(match_operand 8 "cc_register" "") (const_int 0)])
4994 (match_operator:SI 6 "shiftable_operator"
4995 [(match_operand:SI 1 "s_register_operand" "r")
4996 (match_operand:SI 2 "arm_rhs_operand" "rI")])
4997 (match_operator:SI 7 "shiftable_operator"
4998 [(match_operand:SI 3 "s_register_operand" "r")
4999 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
5001 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
5002 [(set_attr "conds" "use")
5003 (set_attr "length" "8")])
5005 (define_insn "*ifcompare_arith_move"
5006 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5007 (if_then_else:SI (match_operator 6 "comparison_operator"
5008 [(match_operand:SI 2 "s_register_operand" "r,r")
5009 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
5010 (match_operator:SI 7 "shiftable_operator"
5011 [(match_operand:SI 4 "s_register_operand" "r,r")
5012 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
5013 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5014 (clobber (reg:CC 24))]
5017 /* If we have an operation where (op x 0) is the identity operation and
5018 the conditional operator is LT or GE and we are comparing against zero and
5019 everything is in registers then we can do this in two instructions */
5020 if (operands[3] == const0_rtx
5021 && GET_CODE (operands[7]) != AND
5022 && GET_CODE (operands[5]) == REG
5023 && GET_CODE (operands[1]) == REG
5024 && REGNO (operands[1]) == REGNO (operands[4])
5025 && REGNO (operands[4]) != REGNO (operands[0]))
5027 if (GET_CODE (operands[6]) == LT)
5028 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5029 else if (GET_CODE (operands[6]) == GE)
5030 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5032 if (GET_CODE (operands[3]) == CONST_INT
5033 && !const_ok_for_arm (INTVAL (operands[3])))
5034 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
5036 output_asm_insn (\"cmp\\t%2, %3\", operands);
5037 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
5038 if (which_alternative != 0)
5039 return \"mov%D6\\t%0, %1\";
5042 [(set_attr "conds" "clob")
5043 (set_attr "length" "8,12")])
5045 (define_insn "*if_arith_move"
5046 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5047 (if_then_else:SI (match_operator 4 "comparison_operator"
5048 [(match_operand 6 "cc_register" "") (const_int 0)])
5049 (match_operator:SI 5 "shiftable_operator"
5050 [(match_operand:SI 2 "s_register_operand" "r,r")
5051 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
5052 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
5056 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
5057 [(set_attr "conds" "use")
5058 (set_attr "length" "4,8")
5059 (set_attr "type" "*,*")])
5061 (define_insn "*ifcompare_move_arith"
5062 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5063 (if_then_else:SI (match_operator 6 "comparison_operator"
5064 [(match_operand:SI 4 "s_register_operand" "r,r")
5065 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5066 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5067 (match_operator:SI 7 "shiftable_operator"
5068 [(match_operand:SI 2 "s_register_operand" "r,r")
5069 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
5070 (clobber (reg:CC 24))]
5073 /* If we have an operation where (op x 0) is the identity operation and
5074 the conditional operator is LT or GE and we are comparing against zero and
5075 everything is in registers then we can do this in two instructions */
5076 if (operands[5] == const0_rtx
5077 && GET_CODE (operands[7]) != AND
5078 && GET_CODE (operands[3]) == REG
5079 && GET_CODE (operands[1]) == REG
5080 && REGNO (operands[1]) == REGNO (operands[2])
5081 && REGNO (operands[2]) != REGNO (operands[0]))
5083 if (GET_CODE (operands[6]) == GE)
5084 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5085 else if (GET_CODE (operands[6]) == LT)
5086 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5089 if (GET_CODE (operands[5]) == CONST_INT
5090 && !const_ok_for_arm (INTVAL (operands[5])))
5091 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5093 output_asm_insn (\"cmp\\t%4, %5\", operands);
5095 if (which_alternative != 0)
5096 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
5097 return \"%I7%D6\\t%0, %2, %3\";
5099 [(set_attr "conds" "clob")
5100 (set_attr "length" "8,12")])
5102 (define_insn "*if_move_arith"
5103 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5105 (match_operator 4 "comparison_operator"
5106 [(match_operand 6 "cc_register" "") (const_int 0)])
5107 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5108 (match_operator:SI 5 "shiftable_operator"
5109 [(match_operand:SI 2 "s_register_operand" "r,r")
5110 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
5114 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
5115 [(set_attr "conds" "use")
5116 (set_attr "length" "4,8")
5117 (set_attr "type" "*,*")])
5119 (define_insn "*ifcompare_move_not"
5120 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5122 (match_operator 5 "comparison_operator"
5123 [(match_operand:SI 3 "s_register_operand" "r,r")
5124 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5125 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5127 (match_operand:SI 2 "s_register_operand" "r,r"))))
5128 (clobber (reg:CC 24))]
5131 [(set_attr "conds" "clob")
5132 (set_attr "length" "8,12")])
5134 (define_insn "*if_move_not"
5135 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5137 (match_operator 4 "comparison_operator"
5138 [(match_operand 3 "cc_register" "") (const_int 0)])
5139 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5140 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5144 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
5145 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
5146 [(set_attr "conds" "use")
5147 (set_attr "length" "4,8,8")])
5149 (define_insn "*ifcompare_not_move"
5150 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5152 (match_operator 5 "comparison_operator"
5153 [(match_operand:SI 3 "s_register_operand" "r,r")
5154 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5156 (match_operand:SI 2 "s_register_operand" "r,r"))
5157 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5158 (clobber (reg:CC 24))]
5161 [(set_attr "conds" "clob")
5162 (set_attr "length" "8,12")])
5164 (define_insn "*if_not_move"
5165 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5167 (match_operator 4 "comparison_operator"
5168 [(match_operand 3 "cc_register" "") (const_int 0)])
5169 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5170 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5174 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
5175 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
5176 [(set_attr "conds" "use")
5177 (set_attr "length" "4,8,8")])
5179 (define_insn "*ifcompare_shift_move"
5180 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5182 (match_operator 6 "comparison_operator"
5183 [(match_operand:SI 4 "s_register_operand" "r,r")
5184 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5185 (match_operator:SI 7 "shift_operator"
5186 [(match_operand:SI 2 "s_register_operand" "r,r")
5187 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
5188 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5189 (clobber (reg:CC 24))]
5192 [(set_attr "conds" "clob")
5193 (set_attr "length" "8,12")])
5195 (define_insn "*if_shift_move"
5196 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5198 (match_operator 5 "comparison_operator"
5199 [(match_operand 6 "cc_register" "") (const_int 0)])
5200 (match_operator:SI 4 "shift_operator"
5201 [(match_operand:SI 2 "s_register_operand" "r,r,r")
5202 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
5203 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5207 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
5208 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
5209 [(set_attr "conds" "use")
5210 (set_attr "length" "4,8,8")])
5212 (define_insn "*ifcompare_move_shift"
5213 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5215 (match_operator 6 "comparison_operator"
5216 [(match_operand:SI 4 "s_register_operand" "r,r")
5217 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5218 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5219 (match_operator:SI 7 "shift_operator"
5220 [(match_operand:SI 2 "s_register_operand" "r,r")
5221 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
5222 (clobber (reg:CC 24))]
5225 [(set_attr "conds" "clob")
5226 (set_attr "length" "8,12")])
5228 (define_insn "*if_move_shift"
5229 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5231 (match_operator 5 "comparison_operator"
5232 [(match_operand 6 "cc_register" "") (const_int 0)])
5233 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5234 (match_operator:SI 4 "shift_operator"
5235 [(match_operand:SI 2 "s_register_operand" "r,r,r")
5236 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
5240 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
5241 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
5242 [(set_attr "conds" "use")
5243 (set_attr "length" "4,8,8")])
5245 (define_insn "*ifcompare_shift_shift"
5246 [(set (match_operand:SI 0 "s_register_operand" "=r")
5248 (match_operator 7 "comparison_operator"
5249 [(match_operand:SI 5 "s_register_operand" "r")
5250 (match_operand:SI 6 "arm_add_operand" "rIL")])
5251 (match_operator:SI 8 "shift_operator"
5252 [(match_operand:SI 1 "s_register_operand" "r")
5253 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5254 (match_operator:SI 9 "shift_operator"
5255 [(match_operand:SI 3 "s_register_operand" "r")
5256 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
5257 (clobber (reg:CC 24))]
5260 [(set_attr "conds" "clob")
5261 (set_attr "length" "12")])
5263 (define_insn "*if_shift_shift"
5264 [(set (match_operand:SI 0 "s_register_operand" "=r")
5266 (match_operator 5 "comparison_operator"
5267 [(match_operand 8 "cc_register" "") (const_int 0)])
5268 (match_operator:SI 6 "shift_operator"
5269 [(match_operand:SI 1 "s_register_operand" "r")
5270 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5271 (match_operator:SI 7 "shift_operator"
5272 [(match_operand:SI 3 "s_register_operand" "r")
5273 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
5275 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
5276 [(set_attr "conds" "use")
5277 (set_attr "length" "8")])
5279 (define_insn "*ifcompare_not_arith"
5280 [(set (match_operand:SI 0 "s_register_operand" "=r")
5282 (match_operator 6 "comparison_operator"
5283 [(match_operand:SI 4 "s_register_operand" "r")
5284 (match_operand:SI 5 "arm_add_operand" "rIL")])
5285 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5286 (match_operator:SI 7 "shiftable_operator"
5287 [(match_operand:SI 2 "s_register_operand" "r")
5288 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5289 (clobber (reg:CC 24))]
5292 [(set_attr "conds" "clob")
5293 (set_attr "length" "12")])
5295 (define_insn "*if_not_arith"
5296 [(set (match_operand:SI 0 "s_register_operand" "=r")
5298 (match_operator 5 "comparison_operator"
5299 [(match_operand 4 "cc_register" "") (const_int 0)])
5300 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5301 (match_operator:SI 6 "shiftable_operator"
5302 [(match_operand:SI 2 "s_register_operand" "r")
5303 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
5305 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
5306 [(set_attr "conds" "use")
5307 (set_attr "length" "8")])
5309 (define_insn "*ifcompare_arith_not"
5310 [(set (match_operand:SI 0 "s_register_operand" "=r")
5312 (match_operator 6 "comparison_operator"
5313 [(match_operand:SI 4 "s_register_operand" "r")
5314 (match_operand:SI 5 "arm_add_operand" "rIL")])
5315 (match_operator:SI 7 "shiftable_operator"
5316 [(match_operand:SI 2 "s_register_operand" "r")
5317 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5318 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5319 (clobber (reg:CC 24))]
5322 [(set_attr "conds" "clob")
5323 (set_attr "length" "12")])
5325 (define_insn "*if_arith_not"
5326 [(set (match_operand:SI 0 "s_register_operand" "=r")
5328 (match_operator 5 "comparison_operator"
5329 [(match_operand 4 "cc_register" "") (const_int 0)])
5330 (match_operator:SI 6 "shiftable_operator"
5331 [(match_operand:SI 2 "s_register_operand" "r")
5332 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5333 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
5335 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
5336 [(set_attr "conds" "use")
5337 (set_attr "length" "8")])
5339 (define_insn "*ifcompare_neg_move"
5340 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5342 (match_operator 5 "comparison_operator"
5343 [(match_operand:SI 3 "s_register_operand" "r,r")
5344 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5345 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
5346 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5347 (clobber (reg:CC 24))]
5350 [(set_attr "conds" "clob")
5351 (set_attr "length" "8,12")])
5353 (define_insn "*if_neg_move"
5354 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5356 (match_operator 4 "comparison_operator"
5357 [(match_operand 3 "cc_register" "") (const_int 0)])
5358 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5359 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5363 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
5364 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
5365 [(set_attr "conds" "use")
5366 (set_attr "length" "4,8,8")])
5368 (define_insn "*ifcompare_move_neg"
5369 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5371 (match_operator 5 "comparison_operator"
5372 [(match_operand:SI 3 "s_register_operand" "r,r")
5373 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5374 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5375 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
5376 (clobber (reg:CC 24))]
5379 [(set_attr "conds" "clob")
5380 (set_attr "length" "8,12")])
5382 (define_insn "*if_move_neg"
5383 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5385 (match_operator 4 "comparison_operator"
5386 [(match_operand 3 "cc_register" "") (const_int 0)])
5387 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5388 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5392 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
5393 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
5394 [(set_attr "conds" "use")
5395 (set_attr "length" "4,8,8")])
5397 (define_insn "*arith_adjacentmem"
5398 [(set (match_operand:SI 0 "s_register_operand" "=r")
5399 (match_operator:SI 1 "shiftable_operator"
5400 [(match_operand:SI 2 "memory_operand" "m")
5401 (match_operand:SI 3 "memory_operand" "m")]))
5402 (clobber (match_scratch:SI 4 "=r"))]
5403 "adjacent_mem_locations (operands[2], operands[3])"
5408 int val1 = 0, val2 = 0;
5410 if (REGNO (operands[0]) > REGNO (operands[4]))
5412 ldm[1] = operands[4];
5413 ldm[2] = operands[0];
5417 ldm[1] = operands[0];
5418 ldm[2] = operands[4];
5420 if (GET_CODE (XEXP (operands[2], 0)) != REG)
5421 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5422 if (GET_CODE (XEXP (operands[3], 0)) != REG)
5423 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5424 arith[0] = operands[0];
5425 arith[3] = operands[1];
5439 ldm[0] = ops[0] = operands[4];
5440 ops[1] = XEXP (XEXP (operands[2], 0), 0);
5441 ops[2] = XEXP (XEXP (operands[2], 0), 1);
5442 output_add_immediate (ops);
5444 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5446 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5450 ldm[0] = XEXP (operands[3], 0);
5452 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5454 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5458 ldm[0] = XEXP (operands[2], 0);
5460 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5462 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5464 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
5468 [(set_attr "length" "12")
5469 (set_attr "type" "load")])
5471 ;; the arm can support extended pre-inc instructions
5473 ;; In all these cases, we use operands 0 and 1 for the register being
5474 ;; incremented because those are the operands that local-alloc will
5475 ;; tie and these are the pair most likely to be tieable (and the ones
5476 ;; that will benefit the most).
5478 ;; We reject the frame pointer if it occurs anywhere in these patterns since
5479 ;; elimination will cause too many headaches.
5481 (define_insn "*strqi_preinc"
5482 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5483 (match_operand:SI 2 "index_operand" "rJ")))
5484 (match_operand:QI 3 "s_register_operand" "r"))
5485 (set (match_operand:SI 0 "s_register_operand" "=r")
5486 (plus:SI (match_dup 1) (match_dup 2)))]
5487 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5488 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5489 && (GET_CODE (operands[2]) != REG
5490 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5491 "str%?b\\t%3, [%0, %2]!"
5492 [(set_attr "type" "store1")])
5494 (define_insn "*strqi_predec"
5495 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5496 (match_operand:SI 2 "s_register_operand" "r")))
5497 (match_operand:QI 3 "s_register_operand" "r"))
5498 (set (match_operand:SI 0 "s_register_operand" "=r")
5499 (minus:SI (match_dup 1) (match_dup 2)))]
5500 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5501 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5502 && (GET_CODE (operands[2]) != REG
5503 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5504 "str%?b\\t%3, [%0, -%2]!"
5505 [(set_attr "type" "store1")])
5507 (define_insn "*loadqi_preinc"
5508 [(set (match_operand:QI 3 "s_register_operand" "=r")
5509 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5510 (match_operand:SI 2 "index_operand" "rJ"))))
5511 (set (match_operand:SI 0 "s_register_operand" "=r")
5512 (plus:SI (match_dup 1) (match_dup 2)))]
5513 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5514 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5515 && (GET_CODE (operands[2]) != REG
5516 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5517 "ldr%?b\\t%3, [%0, %2]!"
5518 [(set_attr "type" "load")])
5520 (define_insn "*loadqi_predec"
5521 [(set (match_operand:QI 3 "s_register_operand" "=r")
5522 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5523 (match_operand:SI 2 "s_register_operand" "r"))))
5524 (set (match_operand:SI 0 "s_register_operand" "=r")
5525 (minus:SI (match_dup 1) (match_dup 2)))]
5526 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5527 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5528 && (GET_CODE (operands[2]) != REG
5529 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5530 "ldr%?b\\t%3, [%0, -%2]!"
5531 [(set_attr "type" "load")])
5533 (define_insn "*loadqisi_preinc"
5534 [(set (match_operand:SI 3 "s_register_operand" "=r")
5536 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5537 (match_operand:SI 2 "index_operand" "rJ")))))
5538 (set (match_operand:SI 0 "s_register_operand" "=r")
5539 (plus:SI (match_dup 1) (match_dup 2)))]
5540 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5541 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5542 && (GET_CODE (operands[2]) != REG
5543 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5544 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
5545 [(set_attr "type" "load")])
5547 (define_insn "*loadqisi_predec"
5548 [(set (match_operand:SI 3 "s_register_operand" "=r")
5550 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5551 (match_operand:SI 2 "s_register_operand" "r")))))
5552 (set (match_operand:SI 0 "s_register_operand" "=r")
5553 (minus:SI (match_dup 1) (match_dup 2)))]
5554 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5555 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5556 && (GET_CODE (operands[2]) != REG
5557 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5558 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
5559 [(set_attr "type" "load")])
5561 (define_insn "*strsi_preinc"
5562 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5563 (match_operand:SI 2 "index_operand" "rJ")))
5564 (match_operand:SI 3 "s_register_operand" "r"))
5565 (set (match_operand:SI 0 "s_register_operand" "=r")
5566 (plus:SI (match_dup 1) (match_dup 2)))]
5567 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5568 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5569 && (GET_CODE (operands[2]) != REG
5570 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5571 "str%?\\t%3, [%0, %2]!"
5572 [(set_attr "type" "store1")])
5574 (define_insn "*strsi_predec"
5575 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5576 (match_operand:SI 2 "s_register_operand" "r")))
5577 (match_operand:SI 3 "s_register_operand" "r"))
5578 (set (match_operand:SI 0 "s_register_operand" "=r")
5579 (minus:SI (match_dup 1) (match_dup 2)))]
5580 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5581 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5582 && (GET_CODE (operands[2]) != REG
5583 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5584 "str%?\\t%3, [%0, -%2]!"
5585 [(set_attr "type" "store1")])
5587 (define_insn "*loadsi_preinc"
5588 [(set (match_operand:SI 3 "s_register_operand" "=r")
5589 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5590 (match_operand:SI 2 "index_operand" "rJ"))))
5591 (set (match_operand:SI 0 "s_register_operand" "=r")
5592 (plus:SI (match_dup 1) (match_dup 2)))]
5593 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5594 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5595 && (GET_CODE (operands[2]) != REG
5596 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5597 "ldr%?\\t%3, [%0, %2]!"
5598 [(set_attr "type" "load")])
5600 (define_insn "*loadsi_predec"
5601 [(set (match_operand:SI 3 "s_register_operand" "=r")
5602 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5603 (match_operand:SI 2 "s_register_operand" "r"))))
5604 (set (match_operand:SI 0 "s_register_operand" "=r")
5605 (minus:SI (match_dup 1) (match_dup 2)))]
5606 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5607 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5608 && (GET_CODE (operands[2]) != REG
5609 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5610 "ldr%?\\t%3, [%0, -%2]!"
5611 [(set_attr "type" "load")])
5613 (define_insn "*loadhi_preinc"
5614 [(set (match_operand:HI 3 "s_register_operand" "=r")
5615 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5616 (match_operand:SI 2 "index_operand" "rJ"))))
5617 (set (match_operand:SI 0 "s_register_operand" "=r")
5618 (plus:SI (match_dup 1) (match_dup 2)))]
5619 "(! BYTES_BIG_ENDIAN)
5620 && ! TARGET_SHORT_BY_BYTES
5621 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5622 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5623 && (GET_CODE (operands[2]) != REG
5624 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5625 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5626 [(set_attr "type" "load")])
5628 (define_insn "*loadhi_predec"
5629 [(set (match_operand:HI 3 "s_register_operand" "=r")
5630 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5631 (match_operand:SI 2 "s_register_operand" "r"))))
5632 (set (match_operand:SI 0 "s_register_operand" "=r")
5633 (minus:SI (match_dup 1) (match_dup 2)))]
5634 "(!BYTES_BIG_ENDIAN)
5635 && ! TARGET_SHORT_BY_BYTES
5636 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5637 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5638 && (GET_CODE (operands[2]) != REG
5639 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5640 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5641 [(set_attr "type" "load")])
5643 (define_insn "*strqi_shiftpreinc"
5644 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5645 [(match_operand:SI 3 "s_register_operand" "r")
5646 (match_operand:SI 4 "const_shift_operand" "n")])
5647 (match_operand:SI 1 "s_register_operand" "0")))
5648 (match_operand:QI 5 "s_register_operand" "r"))
5649 (set (match_operand:SI 0 "s_register_operand" "=r")
5650 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5652 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5653 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5654 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5655 "str%?b\\t%5, [%0, %3%S2]!"
5656 [(set_attr "type" "store1")])
5658 (define_insn "*strqi_shiftpredec"
5659 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5660 (match_operator:SI 2 "shift_operator"
5661 [(match_operand:SI 3 "s_register_operand" "r")
5662 (match_operand:SI 4 "const_shift_operand" "n")])))
5663 (match_operand:QI 5 "s_register_operand" "r"))
5664 (set (match_operand:SI 0 "s_register_operand" "=r")
5665 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5667 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5668 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5669 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5670 "str%?b\\t%5, [%0, -%3%S2]!"
5671 [(set_attr "type" "store1")])
5673 (define_insn "*loadqi_shiftpreinc"
5674 [(set (match_operand:QI 5 "s_register_operand" "=r")
5675 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5676 [(match_operand:SI 3 "s_register_operand" "r")
5677 (match_operand:SI 4 "const_shift_operand" "n")])
5678 (match_operand:SI 1 "s_register_operand" "0"))))
5679 (set (match_operand:SI 0 "s_register_operand" "=r")
5680 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5682 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5683 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5684 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5685 "ldr%?b\\t%5, [%0, %3%S2]!"
5686 [(set_attr "type" "load")])
5688 (define_insn "*loadqi_shiftpredec"
5689 [(set (match_operand:QI 5 "s_register_operand" "=r")
5690 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5691 (match_operator:SI 2 "shift_operator"
5692 [(match_operand:SI 3 "s_register_operand" "r")
5693 (match_operand:SI 4 "const_shift_operand" "n")]))))
5694 (set (match_operand:SI 0 "s_register_operand" "=r")
5695 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5697 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5698 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5699 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5700 "ldr%?b\\t%5, [%0, -%3%S2]!"
5701 [(set_attr "type" "load")])
5703 (define_insn "*strsi_shiftpreinc"
5704 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5705 [(match_operand:SI 3 "s_register_operand" "r")
5706 (match_operand:SI 4 "const_shift_operand" "n")])
5707 (match_operand:SI 1 "s_register_operand" "0")))
5708 (match_operand:SI 5 "s_register_operand" "r"))
5709 (set (match_operand:SI 0 "s_register_operand" "=r")
5710 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5712 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5713 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5714 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5715 "str%?\\t%5, [%0, %3%S2]!"
5716 [(set_attr "type" "store1")])
5718 (define_insn "*strsi_shiftpredec"
5719 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5720 (match_operator:SI 2 "shift_operator"
5721 [(match_operand:SI 3 "s_register_operand" "r")
5722 (match_operand:SI 4 "const_shift_operand" "n")])))
5723 (match_operand:SI 5 "s_register_operand" "r"))
5724 (set (match_operand:SI 0 "s_register_operand" "=r")
5725 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5727 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5728 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5729 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5730 "str%?\\t%5, [%0, -%3%S2]!"
5731 [(set_attr "type" "store1")])
5733 (define_insn "*loadsi_shiftpreinc"
5734 [(set (match_operand:SI 5 "s_register_operand" "=r")
5735 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5736 [(match_operand:SI 3 "s_register_operand" "r")
5737 (match_operand:SI 4 "const_shift_operand" "n")])
5738 (match_operand:SI 1 "s_register_operand" "0"))))
5739 (set (match_operand:SI 0 "s_register_operand" "=r")
5740 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5742 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5743 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5744 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5745 "ldr%?\\t%5, [%0, %3%S2]!"
5746 [(set_attr "type" "load")])
5748 (define_insn "*loadsi_shiftpredec"
5749 [(set (match_operand:SI 5 "s_register_operand" "=r")
5750 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5751 (match_operator:SI 2 "shift_operator"
5752 [(match_operand:SI 3 "s_register_operand" "r")
5753 (match_operand:SI 4 "const_shift_operand" "n")]))))
5754 (set (match_operand:SI 0 "s_register_operand" "=r")
5755 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5757 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5758 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5759 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5760 "ldr%?\\t%5, [%0, -%3%S2]!"
5761 [(set_attr "type" "load")])
5763 (define_insn "*loadhi_shiftpreinc"
5764 [(set (match_operand:HI 5 "s_register_operand" "=r")
5765 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5766 [(match_operand:SI 3 "s_register_operand" "r")
5767 (match_operand:SI 4 "const_shift_operand" "n")])
5768 (match_operand:SI 1 "s_register_operand" "0"))))
5769 (set (match_operand:SI 0 "s_register_operand" "=r")
5770 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5772 "(! BYTES_BIG_ENDIAN)
5773 && ! TARGET_SHORT_BY_BYTES
5774 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5775 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5776 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5777 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5778 [(set_attr "type" "load")])
5780 (define_insn "*loadhi_shiftpredec"
5781 [(set (match_operand:HI 5 "s_register_operand" "=r")
5782 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5783 (match_operator:SI 2 "shift_operator"
5784 [(match_operand:SI 3 "s_register_operand" "r")
5785 (match_operand:SI 4 "const_shift_operand" "n")]))))
5786 (set (match_operand:SI 0 "s_register_operand" "=r")
5787 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5789 "(! BYTES_BIG_ENDIAN)
5790 && ! TARGET_SHORT_BY_BYTES
5791 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5792 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5793 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5794 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5795 [(set_attr "type" "load")])
5797 ; It can also support extended post-inc expressions, but combine doesn't
5799 ; It doesn't seem worth adding peepholes for anything but the most common
5800 ; cases since, unlike combine, the increment must immediately follow the load
5801 ; for this pattern to match.
5802 ; When loading we must watch to see that the base register isn't trampled by
5803 ; the load. In such cases this isn't a post-inc expression.
5806 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5807 (match_operand:QI 2 "s_register_operand" "r"))
5809 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5811 "str%?b\\t%2, [%0], %1")
5814 [(set (match_operand:QI 0 "s_register_operand" "=r")
5815 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5817 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5818 "REGNO(operands[0]) != REGNO(operands[1])
5819 && (GET_CODE (operands[2]) != REG
5820 || REGNO(operands[0]) != REGNO (operands[2]))"
5821 "ldr%?b\\t%0, [%1], %2")
5824 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5825 (match_operand:SI 2 "s_register_operand" "r"))
5827 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5829 "str%?\\t%2, [%0], %1")
5832 [(set (match_operand:HI 0 "s_register_operand" "=r")
5833 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5835 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5836 "(! BYTES_BIG_ENDIAN)
5837 && ! TARGET_SHORT_BY_BYTES
5838 && REGNO(operands[0]) != REGNO(operands[1])
5839 && (GET_CODE (operands[2]) != REG
5840 || REGNO(operands[0]) != REGNO (operands[2]))"
5841 "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5844 [(set (match_operand:SI 0 "s_register_operand" "=r")
5845 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5847 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5848 "REGNO(operands[0]) != REGNO(operands[1])
5849 && (GET_CODE (operands[2]) != REG
5850 || REGNO(operands[0]) != REGNO (operands[2]))"
5851 "ldr%?\\t%0, [%1], %2")
5854 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5855 (match_operand:SI 1 "index_operand" "rJ")))
5856 (match_operand:QI 2 "s_register_operand" "r"))
5857 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5859 "str%?b\\t%2, [%0, %1]!")
5862 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5863 [(match_operand:SI 0 "s_register_operand" "r")
5864 (match_operand:SI 1 "const_int_operand" "n")])
5865 (match_operand:SI 2 "s_register_operand" "+r")))
5866 (match_operand:QI 3 "s_register_operand" "r"))
5867 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5870 "str%?b\\t%3, [%2, %0%S4]!")
5872 ; This pattern is never tried by combine, so do it as a peephole
5875 [(set (match_operand:SI 0 "s_register_operand" "=r")
5876 (match_operand:SI 1 "s_register_operand" "r"))
5878 (compare:CC (match_dup 1) (const_int 0)))]
5880 "sub%?s\\t%0, %1, #0"
5881 [(set_attr "conds" "set")])
5883 ; Peepholes to spot possible load- and store-multiples, if the ordering is
5884 ; reversed, check that the memory references aren't volatile.
5887 [(set (match_operand:SI 0 "s_register_operand" "=r")
5888 (match_operand:SI 4 "memory_operand" "m"))
5889 (set (match_operand:SI 1 "s_register_operand" "=r")
5890 (match_operand:SI 5 "memory_operand" "m"))
5891 (set (match_operand:SI 2 "s_register_operand" "=r")
5892 (match_operand:SI 6 "memory_operand" "m"))
5893 (set (match_operand:SI 3 "s_register_operand" "=r")
5894 (match_operand:SI 7 "memory_operand" "m"))]
5895 "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5897 return emit_ldm_seq (operands, 4);
5901 [(set (match_operand:SI 0 "s_register_operand" "=r")
5902 (match_operand:SI 3 "memory_operand" "m"))
5903 (set (match_operand:SI 1 "s_register_operand" "=r")
5904 (match_operand:SI 4 "memory_operand" "m"))
5905 (set (match_operand:SI 2 "s_register_operand" "=r")
5906 (match_operand:SI 5 "memory_operand" "m"))]
5907 "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5909 return emit_ldm_seq (operands, 3);
5913 [(set (match_operand:SI 0 "s_register_operand" "=r")
5914 (match_operand:SI 2 "memory_operand" "m"))
5915 (set (match_operand:SI 1 "s_register_operand" "=r")
5916 (match_operand:SI 3 "memory_operand" "m"))]
5917 "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5919 return emit_ldm_seq (operands, 2);
5923 [(set (match_operand:SI 4 "memory_operand" "=m")
5924 (match_operand:SI 0 "s_register_operand" "r"))
5925 (set (match_operand:SI 5 "memory_operand" "=m")
5926 (match_operand:SI 1 "s_register_operand" "r"))
5927 (set (match_operand:SI 6 "memory_operand" "=m")
5928 (match_operand:SI 2 "s_register_operand" "r"))
5929 (set (match_operand:SI 7 "memory_operand" "=m")
5930 (match_operand:SI 3 "s_register_operand" "r"))]
5931 "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5933 return emit_stm_seq (operands, 4);
5937 [(set (match_operand:SI 3 "memory_operand" "=m")
5938 (match_operand:SI 0 "s_register_operand" "r"))
5939 (set (match_operand:SI 4 "memory_operand" "=m")
5940 (match_operand:SI 1 "s_register_operand" "r"))
5941 (set (match_operand:SI 5 "memory_operand" "=m")
5942 (match_operand:SI 2 "s_register_operand" "r"))]
5943 "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5945 return emit_stm_seq (operands, 3);
5949 [(set (match_operand:SI 2 "memory_operand" "=m")
5950 (match_operand:SI 0 "s_register_operand" "r"))
5951 (set (match_operand:SI 3 "memory_operand" "=m")
5952 (match_operand:SI 1 "s_register_operand" "r"))]
5953 "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5955 return emit_stm_seq (operands, 2);
5958 ;; A call followed by return can be replaced by restoring the regs and
5959 ;; jumping to the subroutine, provided we aren't passing the address of
5960 ;; any of our local variables. If we call alloca then this is unsafe
5961 ;; since restoring the frame frees the memory, which is not what we want.
5962 ;; Sometimes the return might have been targeted by the final prescan:
5963 ;; if so then emit a proper return insn as well.
5964 ;; Unfortunately, if the frame pointer is required, we don't know if the
5965 ;; current function has any implicit stack pointer adjustments that will
5966 ;; be restored by the return: we can't therefore do a tail call.
5967 ;; Another unfortunate that we can't handle is if current_function_args_size
5968 ;; is non-zero: in this case elimination of the argument pointer assumed
5969 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5973 [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5974 (match_operand:SI 1 "general_operand" "g"))
5975 (clobber (reg:SI 14))])
5977 "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
5978 && !get_frame_size () && !current_function_calls_alloca
5979 && !frame_pointer_needed && !current_function_args_size)"
5982 extern rtx arm_target_insn;
5983 extern int arm_ccfsm_state;
5985 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5987 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5988 output_return_instruction (NULL, TRUE, FALSE);
5989 arm_ccfsm_state = 0;
5990 arm_target_insn = NULL;
5993 output_return_instruction (NULL, FALSE, FALSE);
5994 return NEED_PLT_GOT ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
5996 [(set_attr "type" "call")
5997 (set_attr "length" "8")])
6000 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6001 (call (mem:SI (match_operand:SI 1 "" "X"))
6002 (match_operand:SI 2 "general_operand" "g")))
6003 (clobber (reg:SI 14))])
6005 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
6006 && !get_frame_size () && !current_function_calls_alloca
6007 && !frame_pointer_needed && !current_function_args_size)"
6010 extern rtx arm_target_insn;
6011 extern int arm_ccfsm_state;
6013 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6015 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6016 output_return_instruction (NULL, TRUE, FALSE);
6017 arm_ccfsm_state = 0;
6018 arm_target_insn = NULL;
6021 output_return_instruction (NULL, FALSE, FALSE);
6022 return NEED_PLT_GOT ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6024 [(set_attr "type" "call")
6025 (set_attr "length" "8")])
6027 ;; As above but when this function is not void, we must be returning the
6028 ;; result of the called subroutine.
6031 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6032 (call (mem:SI (match_operand:SI 1 "" "X"))
6033 (match_operand:SI 2 "general_operand" "g")))
6034 (clobber (reg:SI 14))])
6037 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
6038 && !get_frame_size () && !current_function_calls_alloca
6039 && !frame_pointer_needed && !current_function_args_size)"
6042 extern rtx arm_target_insn;
6043 extern int arm_ccfsm_state;
6045 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6047 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6048 output_return_instruction (NULL, TRUE, FALSE);
6049 arm_ccfsm_state = 0;
6050 arm_target_insn = NULL;
6053 output_return_instruction (NULL, FALSE, FALSE);
6054 return \"b%?\\t%a1\";
6056 [(set_attr "type" "call")
6057 (set_attr "length" "8")])
6060 [(set (match_operand:SI 0 "s_register_operand" "")
6061 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
6063 (neg:SI (match_operator:SI 2 "comparison_operator"
6064 [(match_operand:SI 3 "s_register_operand" "")
6065 (match_operand:SI 4 "arm_rhs_operand" "")]))))
6066 (clobber (match_operand:SI 5 "s_register_operand" ""))]
6068 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
6069 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6073 ;; This split can be used because CC_Z mode implies that the following
6074 ;; branch will be an equality, or an unsigned inequality, so the sign
6075 ;; extension is not needed.
6080 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
6082 (match_operand 1 "const_int_operand" "")))
6083 (clobber (match_scratch:SI 2 ""))]
6084 "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
6085 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
6086 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
6087 (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
6089 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
6092 (define_expand "prologue"
6093 [(clobber (const_int 0))]
6096 arm_expand_prologue ();
6100 ;; This split is only used during output to reduce the number of patterns
6101 ;; that need assembler instructions adding to them. We allowed the setting
6102 ;; of the conditions to be implicit during rtl generation so that
6103 ;; the conditional compare patterns would work. However this conflicts to
6104 ;; some extent with the conditional data operations, so we have to split them
6108 [(set (match_operand:SI 0 "s_register_operand" "")
6109 (if_then_else:SI (match_operator 1 "comparison_operator"
6110 [(match_operand 2 "" "") (match_operand 3 "" "")])
6111 (match_operand 4 "" "")
6112 (match_operand 5 "" "")))
6113 (clobber (reg:CC 24))]
6115 [(set (match_dup 6) (match_dup 7))
6117 (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
6122 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
6125 operands[6] = gen_rtx_REG (mode, 24);
6126 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
6130 ;; The next two patterns occur when an AND operation is followed by a
6131 ;; scc insn sequence
6133 (define_insn "*sign_extract_onebit"
6134 [(set (match_operand:SI 0 "s_register_operand" "=r")
6135 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6137 (match_operand:SI 2 "const_int_operand" "n")))]
6140 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6141 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6142 return \"mvnne\\t%0, #0\";
6144 [(set_attr "conds" "clob")
6145 (set_attr "length" "8")])
6147 (define_insn "*not_signextract_onebit"
6148 [(set (match_operand:SI 0 "s_register_operand" "=r")
6150 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6152 (match_operand:SI 2 "const_int_operand" "n"))))]
6155 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6156 output_asm_insn (\"tst\\t%1, %2\", operands);
6157 output_asm_insn (\"mvneq\\t%0, #0\", operands);
6158 return \"movne\\t%0, #0\";
6160 [(set_attr "conds" "clob")
6161 (set_attr "length" "12")])
6163 ;; Push multiple registers to the stack. The first register is in the
6164 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
6166 (define_insn "*push_multi"
6167 [(match_parallel 2 "multi_register_push"
6168 [(set (match_operand:BLK 0 "memory_operand" "=m")
6169 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
6175 extern int lr_save_eliminated;
6177 if (lr_save_eliminated)
6179 if (XVECLEN (operands[2], 0) > 1)
6183 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
6184 for (i = 1; i < XVECLEN (operands[2], 0); i++)
6186 strcat (pattern, \", %|\");
6187 strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
6190 strcat (pattern, \"}\");
6191 output_asm_insn (pattern, operands);
6194 [(set_attr "type" "store4")])
6196 ;; Similarly for the floating point registers
6197 (define_insn "*push_fp_multi"
6198 [(match_parallel 2 "multi_register_push"
6199 [(set (match_operand:BLK 0 "memory_operand" "=m")
6200 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
6206 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
6207 output_asm_insn (pattern, operands);
6210 [(set_attr "type" "f_store")])
6212 ;; Special patterns for dealing with the constant pool
6214 (define_insn "consttable_4"
6215 [(unspec_volatile [(match_operand 0 "" "")] 2)]
6219 making_const_table = TRUE;
6220 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6224 union real_extract u;
6225 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6226 assemble_real (u.d, GET_MODE (operands[0]));
6230 assemble_integer (operands[0], 4, 1);
6235 [(set_attr "length" "4")])
6237 (define_insn "consttable_8"
6238 [(unspec_volatile [(match_operand 0 "" "")] 3)]
6242 making_const_table = TRUE;
6243 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6247 union real_extract u;
6248 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6249 assemble_real (u.d, GET_MODE (operands[0]));
6253 assemble_integer (operands[0], 8, 1);
6258 [(set_attr "length" "8")])
6260 (define_insn "consttable_end"
6261 [(unspec_volatile [(const_int 0)] 4)]
6264 making_const_table = FALSE;
6268 (define_insn "align_4"
6269 [(unspec_volatile [(const_int 0)] 5)]
6272 assemble_align (32);