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 ; POOL_RANGE is how far away from a constant pool entry that this insn
60 ; can be placed. If the distance is zero, then this insn will never
62 (define_attr "pool_range" "" (const_int 0))
64 ; An assembler sequence may clobber the condition codes without us knowing
65 ; If such an insn references the pool, then we have no way of knowing how,
66 ; so use the most conservative value for pool_range.
67 (define_asm_attributes
68 [(set_attr "conds" "clob")
69 (set_attr "length" "4")
70 (set_attr "pool_range" "250")])
72 ; TYPE attribute is used to detect floating point instructions which, if
73 ; running on a co-processor can run in parallel with other, basic instructions
74 ; If write-buffer scheduling is enabled then it can also be used in the
75 ; scheduling of writes.
77 ; Classification of each insn
78 ; normal any data instruction that doesn't hit memory or fp regs
79 ; mult a multiply instruction
80 ; block blockage insn, this blocks all functional units
81 ; float a floating point arithmetic operation (subject to expansion)
82 ; fdivx XFmode floating point division
83 ; fdivd DFmode floating point division
84 ; fdivs SFmode floating point division
85 ; fmul Floating point multiply
86 ; ffmul Fast floating point multiply
87 ; farith Floating point arithmetic (4 cycle)
88 ; ffarith Fast floating point arithmetic (2 cycle)
89 ; float_em a floating point arithmetic operation that is normally emulated
90 ; even on a machine with an fpa.
91 ; f_load a floating point load from memory
92 ; f_store a floating point store to memory
93 ; f_mem_r a transfer of a floating point register to a real reg via mem
94 ; r_mem_f the reverse of f_mem_r
95 ; f_2_r fast transfer float to arm (no memory needed)
96 ; r_2_f fast transfer arm to float
97 ; call a subroutine call
98 ; load any load from memory
99 ; store1 store 1 word to memory from arm registers
100 ; store2 store 2 words
101 ; store3 store 3 words
102 ; store4 store 4 words
105 "normal,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"
106 (const_string "normal"))
108 ; Load scheduling, set from the arm_ld_sched variable
109 ; initialised by arm_override_options()
110 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
112 ; condition codes: this one is used by final_prescan_insn to speed up
113 ; conditionalizing instructions. It saves having to scan the rtl to see if
114 ; it uses or alters the condition codes.
116 ; USE means that the condition codes are used by the insn in the process of
117 ; outputting code, this means (at present) that we can't use the insn in
120 ; SET means that the purpose of the insn is to set the condition codes in a
121 ; well defined manner.
123 ; CLOB means that the condition codes are altered in an undefined manner, if
124 ; they are altered at all
126 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
127 ; but are if the branch wasn't taken; the effect is to limit the branch
128 ; elimination scanning.
130 ; NOCOND means that the condition codes are neither altered nor affect the
131 ; output of this insn
133 (define_attr "conds" "use,set,clob,jump_clob,nocond"
134 (if_then_else (eq_attr "type" "call")
135 (if_then_else (eq_attr "prog_mode" "prog32")
136 (const_string "clob") (const_string "nocond"))
137 (const_string "nocond")))
139 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
140 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
141 ; suffer blockages enough to warrent modelling this (and it can adversely
142 ; affect the schedule).
143 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
145 (define_attr "write_conflict" "no,yes"
146 (if_then_else (eq_attr "type"
147 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
149 (const_string "no")))
151 (define_attr "core_cycles" "single,multi"
152 (if_then_else (eq_attr "type"
153 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
154 (const_string "single")
155 (const_string "multi")))
157 ; The write buffer on some of the arm6 processors is hard to model exactly.
158 ; There is room in the buffer for up to two addresses and up to eight words
159 ; of memory, but the two needn't be split evenly. When writing the two
160 ; addresses are fully pipelined. However, a read from memory that is not
161 ; currently in the cache will block until the writes have completed.
162 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
163 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
164 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
165 ; cycle to add as well.
167 ;; (define_function_unit {name} {num-units} {n-users} {test}
168 ;; {ready-delay} {issue-delay} [{conflict-list}])
169 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
170 (eq_attr "type" "fdivx")) 71 69)
172 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
173 (eq_attr "type" "fdivd")) 59 57)
175 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
176 (eq_attr "type" "fdivs")) 31 29)
178 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
179 (eq_attr "type" "fmul")) 9 7)
181 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
182 (eq_attr "type" "ffmul")) 6 4)
184 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
185 (eq_attr "type" "farith")) 4 2)
187 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
188 (eq_attr "type" "ffarith")) 2 2)
190 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
191 (eq_attr "type" "r_2_f")) 5 3)
193 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
194 (eq_attr "type" "f_2_r")) 1 2)
196 ;; The fpa10 doesn't really have a memory read unit, but it can start to
197 ;; speculatively execute the instruction in the pipeline, provided the data
198 ;; is already loaded, so pretend reads have a delay of 2 (and that the
199 ;; pipeline is infinite.
201 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
202 (eq_attr "type" "f_load")) 3 1)
204 ;;--------------------------------------------------------------------
206 ;;--------------------------------------------------------------------
207 ;; Strictly we should model a 4-deep write buffer for ARM7xx based chips
208 (define_function_unit "write_buf" 1 2
209 (and (eq_attr "model_wbuf" "yes")
210 (eq_attr "type" "store1,r_mem_f")) 5 3)
211 (define_function_unit "write_buf" 1 2
212 (and (eq_attr "model_wbuf" "yes")
213 (eq_attr "type" "store2")) 7 4)
214 (define_function_unit "write_buf" 1 2
215 (and (eq_attr "model_wbuf" "yes")
216 (eq_attr "type" "store3")) 9 5)
217 (define_function_unit "write_buf" 1 2
218 (and (eq_attr "model_wbuf" "yes")
219 (eq_attr "type" "store4")) 11 6)
221 ;;--------------------------------------------------------------------
222 ;; Write blockage unit
223 ;;--------------------------------------------------------------------
224 ;; The write_blockage unit models (partially), the fact that reads will stall
225 ;; until the write buffer empties.
226 ;; The f_mem_r and r_mem_f could also block, but they are to the stack,
227 ;; so we don't model them here
228 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
229 (eq_attr "type" "store1")) 5 5
230 [(eq_attr "write_conflict" "yes")])
231 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
232 (eq_attr "type" "store2")) 7 7
233 [(eq_attr "write_conflict" "yes")])
234 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
235 (eq_attr "type" "store3")) 9 9
236 [(eq_attr "write_conflict" "yes")])
237 (define_function_unit "write_blockage" 1 0
238 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
239 [(eq_attr "write_conflict" "yes")])
240 (define_function_unit "write_blockage" 1 0
241 (and (eq_attr "model_wbuf" "yes")
242 (eq_attr "write_conflict" "yes")) 1 1)
244 ;;--------------------------------------------------------------------
246 ;;--------------------------------------------------------------------
247 ;; Everything must spend at least one cycle in the core unit
248 (define_function_unit "core" 1 0
249 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
251 (define_function_unit "core" 1 0
252 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
254 (define_function_unit "core" 1 0
255 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
257 (define_function_unit "core" 1 0
258 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
260 (define_function_unit "core" 1 0
261 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
263 (define_function_unit "core" 1 0
264 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
266 (define_function_unit "core" 1 0
267 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
269 (define_function_unit "core" 1 0
270 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
272 (define_function_unit "core" 1 0
273 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
274 (eq_attr "type" "mult")) 4 4)
276 (define_function_unit "core" 1 0
277 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
278 (eq_attr "type" "mult")) 3 2)
280 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
282 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
284 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
286 ;; Note: For DImode insns, there is normally no reason why operands should
287 ;; not be in the same register, what we don't want is for something being
288 ;; written to partially overlap something that is an input.
290 ;; Split up 64bit addition so that the component insns can schedule
293 [(set (match_operand:DI 0 "s_register_operand" "")
294 (plus:DI (match_operand:DI 1 "s_register_operand" "")
295 (match_operand:DI 2 "s_register_operand" "")))
296 (clobber (reg:CC 24))]
298 [(parallel [(set (reg:CC_C 24)
299 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
301 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
302 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
303 (plus:SI (match_dup 4) (match_dup 5))))]
306 operands[3] = gen_highpart (SImode, operands[0]);
307 operands[0] = gen_lowpart (SImode, operands[0]);
308 operands[4] = gen_highpart (SImode, operands[1]);
309 operands[1] = gen_lowpart (SImode, operands[1]);
310 operands[5] = gen_highpart (SImode, operands[2]);
311 operands[2] = gen_lowpart (SImode, operands[2]);
314 ;; The first insn created by this splitter must set the low part of
315 ;; operand0 as well as the carry bit in the CC register. The second
316 ;; insn must compute the sum of the carry bit, the sign extension of
317 ;; operand 2 from 32 to 64 bits and the high part of operand 1.
319 [(set (match_operand:DI 0 "s_register_operand" "")
320 (plus:DI (sign_extend:DI
321 (match_operand:SI 2 "s_register_operand" ""))
322 (match_operand:DI 1 "s_register_operand" "")))
323 (clobber (reg:CC 24))]
325 [(parallel [(set (reg:CC_C 24)
326 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
328 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
329 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
330 (plus:SI (ashiftrt:SI (match_dup 2)
335 operands[3] = gen_highpart (SImode, operands[0]);
336 operands[0] = gen_lowpart (SImode, operands[0]);
337 operands[4] = gen_highpart (SImode, operands[1]);
338 operands[1] = gen_lowpart (SImode, operands[1]);
339 operands[2] = gen_lowpart (SImode, operands[2]);
342 ;; The first insn created by this splitter must set the low part of
343 ;; operand0 as well as the carry bit in the CC register. The second
344 ;; insn must compute the sum of the carry bit and the high bits from
347 [(set (match_operand:DI 0 "s_register_operand" "")
348 (plus:DI (zero_extend:DI
349 (match_operand:SI 2 "s_register_operand" ""))
350 (match_operand:DI 1 "s_register_operand" "")))
351 (clobber (reg:CC 24))]
353 [(parallel [(set (reg:CC_C 24)
354 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
356 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
357 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
358 (plus:SI (match_dup 4) (const_int 0))))]
361 operands[3] = gen_highpart (SImode, operands[0]);
362 operands[0] = gen_lowpart (SImode, operands[0]);
363 operands[4] = gen_highpart (SImode, operands[1]);
364 operands[1] = gen_lowpart (SImode, operands[1]);
365 operands[2] = gen_lowpart (SImode, operands[2]);
370 (define_insn "adddi3"
371 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
372 (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
373 (match_operand:DI 2 "s_register_operand" "r,0")))
374 (clobber (reg:CC 24))]
377 [(set_attr "conds" "clob")
378 (set_attr "length" "8")])
380 (define_insn "*adddi_sesidi_di"
381 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
382 (plus:DI (sign_extend:DI
383 (match_operand:SI 2 "s_register_operand" "r,r"))
384 (match_operand:DI 1 "s_register_operand" "r,0")))
385 (clobber (reg:CC 24))]
388 [(set_attr "conds" "clob")
389 (set_attr "length" "8")])
391 (define_insn "*adddi_zesidi_di"
392 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
393 (plus:DI (zero_extend:DI
394 (match_operand:SI 2 "s_register_operand" "r,r"))
395 (match_operand:DI 1 "s_register_operand" "r,0")))
396 (clobber (reg:CC 24))]
399 [(set_attr "conds" "clob")
400 (set_attr "length" "8")])
402 (define_expand "addsi3"
403 [(set (match_operand:SI 0 "s_register_operand" "")
404 (plus:SI (match_operand:SI 1 "s_register_operand" "")
405 (match_operand:SI 2 "reg_or_int_operand" "")))]
408 if (GET_CODE (operands[2]) == CONST_INT)
410 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
412 (reload_in_progress || reload_completed ? 0
413 : preserve_subexpressions_p ()));
419 [(set (match_operand:SI 0 "s_register_operand" "")
420 (plus:SI (match_operand:SI 1 "s_register_operand" "")
421 (match_operand:SI 2 "const_int_operand" "")))]
422 "! (const_ok_for_arm (INTVAL (operands[2]))
423 || const_ok_for_arm (-INTVAL (operands[2])))"
424 [(clobber (const_int 0))]
426 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
431 (define_insn "*addsi3_insn"
432 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
433 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
434 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
440 [(set_attr "length" "4,4,16")])
442 (define_insn "*addsi3_compare0"
443 [(set (reg:CC_NOOV 24)
445 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
446 (match_operand:SI 2 "arm_add_operand" "rI,L"))
448 (set (match_operand:SI 0 "s_register_operand" "=r,r")
449 (plus:SI (match_dup 1) (match_dup 2)))]
453 sub%?s\\t%0, %1, #%n2"
454 [(set_attr "conds" "set")])
456 (define_insn "*addsi3_compare0_scratch"
457 [(set (reg:CC_NOOV 24)
459 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
460 (match_operand:SI 1 "arm_add_operand" "rI,L"))
466 [(set_attr "conds" "set")])
468 ;; The next four insns work because they compare the result with one of
469 ;; the operands, and we know that the use of the condition code is
470 ;; either GEU or LTU, so we can use the carry flag from the addition
471 ;; instead of doing the compare a second time.
472 (define_insn "*addsi3_compare_op1"
475 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
476 (match_operand:SI 2 "arm_add_operand" "rI,L"))
478 (set (match_operand:SI 0 "s_register_operand" "=r,r")
479 (plus:SI (match_dup 1) (match_dup 2)))]
483 sub%?s\\t%0, %1, #%n2"
484 [(set_attr "conds" "set")])
486 (define_insn "*addsi3_compare_op2"
489 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
490 (match_operand:SI 2 "arm_add_operand" "rI,L"))
492 (set (match_operand:SI 0 "s_register_operand" "=r,r")
493 (plus:SI (match_dup 1) (match_dup 2)))]
497 sub%?s\\t%0, %1, #%n2"
498 [(set_attr "conds" "set")])
500 (define_insn "*compare_addsi2_op0"
503 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
504 (match_operand:SI 1 "arm_add_operand" "rI,L"))
510 [(set_attr "conds" "set")])
512 (define_insn "*compare_addsi2_op1"
515 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
516 (match_operand:SI 1 "arm_add_operand" "rI,L"))
522 [(set_attr "conds" "set")])
524 (define_insn "*addsi3_carryin"
525 [(set (match_operand:SI 0 "s_register_operand" "=r")
526 (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
527 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
528 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
531 [(set_attr "conds" "use")])
533 (define_insn "*addsi3_carryin_shift"
534 [(set (match_operand:SI 0 "s_register_operand" "")
535 (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
537 (match_operator:SI 2 "shift_operator"
538 [(match_operand:SI 3 "s_register_operand" "")
539 (match_operand:SI 4 "reg_or_int_operand" "")])
540 (match_operand:SI 1 "s_register_operand" ""))))]
542 "adc%?\\t%0, %1, %3%S2"
543 [(set_attr "conds" "use")]
546 (define_insn "*addsi3_carryin_alt1"
547 [(set (match_operand:SI 0 "s_register_operand" "=r")
548 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
549 (match_operand:SI 2 "arm_rhs_operand" "rI"))
550 (ltu:SI (reg:CC_C 24) (const_int 0))))]
553 [(set_attr "conds" "use")])
555 (define_insn "*addsi3_carryin_alt2"
556 [(set (match_operand:SI 0 "s_register_operand" "=r")
557 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
558 (match_operand:SI 1 "s_register_operand" "r"))
559 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
562 [(set_attr "conds" "use")])
564 (define_insn "*addsi3_carryin_alt3"
565 [(set (match_operand:SI 0 "s_register_operand" "=r")
566 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
567 (match_operand:SI 2 "arm_rhs_operand" "rI"))
568 (match_operand:SI 1 "s_register_operand" "r")))]
571 [(set_attr "conds" "use")])
573 (define_insn "incscc"
574 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
575 (plus:SI (match_operator:SI 2 "comparison_operator"
576 [(match_operand 3 "cc_register" "") (const_int 0)])
577 (match_operand:SI 1 "s_register_operand" "0,?r")))]
581 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
582 [(set_attr "conds" "use")
583 (set_attr "length" "4,8")])
585 ; If a constant is too big to fit in a single instruction then the constant
586 ; will be pre-loaded into a register taking at least two insns, we might be
587 ; able to merge it with an add, but it depends on the exact value.
590 [(set (match_operand:SI 0 "s_register_operand" "=r")
591 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
592 (match_operand:SI 2 "const_int_operand" "n")))]
593 "!(const_ok_for_arm (INTVAL (operands[2]))
594 || const_ok_for_arm (-INTVAL (operands[2])))"
595 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
596 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
599 unsigned int val = (unsigned) INTVAL (operands[2]);
603 /* this code is similar to the approach followed in movsi, but it must
604 generate exactly two insns */
606 for (i = 30; i >= 0; i -= 2)
612 if (const_ok_for_arm (temp = (val & ~(255 << i))))
617 /* we might be able to do this as (larger number - small number) */
618 temp = ((val >> i) & 255) + 1;
619 if (temp > 255 && i < 24)
622 temp = ((val >> i) & 255) + 1;
624 if (const_ok_for_arm ((temp << i) - val))
627 temp = (unsigned) - (int) (i - val);
634 /* if we got here, we have found a way of doing it in two instructions.
635 the two constants are in val and temp */
636 operands[2] = GEN_INT ((int)val);
637 operands[3] = GEN_INT ((int)temp);
641 (define_insn "addsf3"
642 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
643 (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
644 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
648 suf%?s\\t%0, %1, #%N2"
649 [(set_attr "type" "farith")])
651 (define_insn "adddf3"
652 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
653 (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
654 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
658 suf%?d\\t%0, %1, #%N2"
659 [(set_attr "type" "farith")])
661 (define_insn "*adddf_esfdf_df"
662 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
663 (plus:DF (float_extend:DF
664 (match_operand:SF 1 "s_register_operand" "f,f"))
665 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
669 suf%?d\\t%0, %1, #%N2"
670 [(set_attr "type" "farith")])
672 (define_insn "*adddf_df_esfdf"
673 [(set (match_operand:DF 0 "s_register_operand" "=f")
674 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
676 (match_operand:SF 2 "s_register_operand" "f"))))]
678 "adf%?d\\t%0, %1, %2"
679 [(set_attr "type" "farith")])
681 (define_insn "*adddf_esfdf_esfdf"
682 [(set (match_operand:DF 0 "s_register_operand" "=f")
683 (plus:DF (float_extend:DF
684 (match_operand:SF 1 "s_register_operand" "f"))
686 (match_operand:SF 2 "s_register_operand" "f"))))]
688 "adf%?d\\t%0, %1, %2"
689 [(set_attr "type" "farith")])
691 (define_insn "addxf3"
692 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
693 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
694 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
695 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
698 suf%?e\\t%0, %1, #%N2"
699 [(set_attr "type" "farith")])
701 (define_insn "subdi3"
702 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
703 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
704 (match_operand:DI 2 "s_register_operand" "r,0,0")))
705 (clobber (reg:CC 24))]
707 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
708 [(set_attr "conds" "clob")
709 (set_attr "length" "8")])
711 (define_insn "*subdi_di_zesidi"
712 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
713 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
715 (match_operand:SI 2 "s_register_operand" "r,r"))))
716 (clobber (reg:CC 24))]
718 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
719 [(set_attr "conds" "clob")
720 (set_attr "length" "8")])
722 (define_insn "*subdi_di_sesidi"
723 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
724 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
726 (match_operand:SI 2 "s_register_operand" "r,r"))))
727 (clobber (reg:CC 24))]
729 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
730 [(set_attr "conds" "clob")
731 (set_attr "length" "8")])
733 (define_insn "*subdi_zesidi_di"
734 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
735 (minus:DI (zero_extend:DI
736 (match_operand:SI 2 "s_register_operand" "r,r"))
737 (match_operand:DI 1 "s_register_operand" "?r,0")))
738 (clobber (reg:CC 24))]
740 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
741 [(set_attr "conds" "clob")
742 (set_attr "length" "8")])
744 (define_insn "*subdi_sesidi_di"
745 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
746 (minus:DI (sign_extend:DI
747 (match_operand:SI 2 "s_register_operand" "r,r"))
748 (match_operand:DI 1 "s_register_operand" "?r,0")))
749 (clobber (reg:CC 24))]
751 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
752 [(set_attr "conds" "clob")
753 (set_attr "length" "8")])
755 (define_insn "*subdi_zesidi_zesidi"
756 [(set (match_operand:DI 0 "s_register_operand" "=r")
757 (minus:DI (zero_extend:DI
758 (match_operand:SI 1 "s_register_operand" "r"))
760 (match_operand:SI 2 "s_register_operand" "r"))))
761 (clobber (reg:CC 24))]
763 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
764 [(set_attr "conds" "clob")
765 (set_attr "length" "8")])
767 (define_expand "subsi3"
768 [(set (match_operand:SI 0 "s_register_operand" "")
769 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
770 (match_operand:SI 2 "s_register_operand" "")))]
773 if (GET_CODE (operands[1]) == CONST_INT)
775 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
777 (reload_in_progress || reload_completed ? 0
778 : preserve_subexpressions_p ()));
783 (define_insn "*subsi3_insn"
784 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
785 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
786 (match_operand:SI 2 "s_register_operand" "r,r")))]
791 [(set_attr "length" "4,16")])
794 [(set (match_operand:SI 0 "s_register_operand" "")
795 (minus:SI (match_operand:SI 1 "const_int_operand" "")
796 (match_operand:SI 2 "s_register_operand" "")))]
797 "! const_ok_for_arm (INTVAL (operands[1]))"
798 [(clobber (const_int 0))]
800 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
805 (define_insn "*subsi3_compare0"
806 [(set (reg:CC_NOOV 24)
807 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
808 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
810 (set (match_operand:SI 0 "s_register_operand" "=r,r")
811 (minus:SI (match_dup 1) (match_dup 2)))]
816 [(set_attr "conds" "set")])
818 (define_insn "decscc"
819 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
820 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
821 (match_operator:SI 2 "comparison_operator"
822 [(match_operand 3 "cc_register" "") (const_int 0)])))]
826 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
827 [(set_attr "conds" "use")
828 (set_attr "length" "*,8")])
830 (define_insn "subsf3"
831 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
832 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
833 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
838 [(set_attr "type" "farith")])
840 (define_insn "subdf3"
841 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
842 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
843 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
848 [(set_attr "type" "farith")])
850 (define_insn "*subdf_esfdf_df"
851 [(set (match_operand:DF 0 "s_register_operand" "=f")
852 (minus:DF (float_extend:DF
853 (match_operand:SF 1 "s_register_operand" "f"))
854 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
856 "suf%?d\\t%0, %1, %2"
857 [(set_attr "type" "farith")])
859 (define_insn "*subdf_df_esfdf"
860 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
861 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
863 (match_operand:SF 2 "s_register_operand" "f,f"))))]
868 [(set_attr "type" "farith")])
870 (define_insn "*subdf_esfdf_esfdf"
871 [(set (match_operand:DF 0 "s_register_operand" "=f")
872 (minus:DF (float_extend:DF
873 (match_operand:SF 1 "s_register_operand" "f"))
875 (match_operand:SF 2 "s_register_operand" "f"))))]
877 "suf%?d\\t%0, %1, %2"
878 [(set_attr "type" "farith")])
880 (define_insn "subxf3"
881 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
882 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
883 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
884 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
888 [(set_attr "type" "farith")])
890 ;; Multiplication insns
892 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
893 (define_insn "mulsi3"
894 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
895 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
896 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
899 [(set_attr "type" "mult")])
901 (define_insn "*mulsi3_compare0"
902 [(set (reg:CC_NOOV 24)
903 (compare:CC_NOOV (mult:SI
904 (match_operand:SI 2 "s_register_operand" "r,r")
905 (match_operand:SI 1 "s_register_operand" "%?r,0"))
907 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
908 (mult:SI (match_dup 2) (match_dup 1)))]
910 "mul%?s\\t%0, %2, %1"
911 [(set_attr "conds" "set")
912 (set_attr "type" "mult")])
914 (define_insn "*mulsi_compare0_scratch"
915 [(set (reg:CC_NOOV 24)
916 (compare:CC_NOOV (mult:SI
917 (match_operand:SI 2 "s_register_operand" "r,r")
918 (match_operand:SI 1 "s_register_operand" "%?r,0"))
920 (clobber (match_scratch:SI 0 "=&r,&r"))]
922 "mul%?s\\t%0, %2, %1"
923 [(set_attr "conds" "set")
924 (set_attr "type" "mult")])
926 ;; Unnamed templates to match MLA instruction.
928 (define_insn "*mulsi3addsi"
929 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
931 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
932 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
933 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
935 "mla%?\\t%0, %2, %1, %3"
936 [(set_attr "type" "mult")])
938 (define_insn "*mulsi3addsi_compare0"
939 [(set (reg:CC_NOOV 24)
940 (compare:CC_NOOV (plus:SI
942 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
943 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
944 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
946 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
947 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
950 "mla%?s\\t%0, %2, %1, %3"
951 [(set_attr "conds" "set")
952 (set_attr "type" "mult")])
954 (define_insn "*mulsi3addsi_compare0_scratch"
955 [(set (reg:CC_NOOV 24)
956 (compare:CC_NOOV (plus:SI
958 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
959 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
960 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
962 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
964 "mla%?s\\t%0, %2, %1, %3"
965 [(set_attr "conds" "set")
966 (set_attr "type" "mult")])
968 ;; Unnamed template to match long long multiply-accumlate (smlal)
970 (define_insn "*mulsidi3adddi"
971 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
973 (mult:DI (sign_extend:DI
974 (match_operand:SI 2 "s_register_operand" "r,0,1"))
976 (match_operand:SI 1 "s_register_operand" "%r,r,r")))
979 "smlal%?\\t%Q0, %R0, %1, %2"
980 [(set_attr "type" "mult")])
982 (define_insn "mulsidi3"
983 [(set (match_operand:DI 0 "s_register_operand" "=&r")
984 (mult:DI (sign_extend:DI
985 (match_operand:SI 1 "s_register_operand" "%r"))
987 (match_operand:SI 2 "s_register_operand" "r"))))]
989 "smull%?\\t%Q0, %R0, %1, %2"
990 [(set_attr "type" "mult")])
992 (define_insn "umulsidi3"
993 [(set (match_operand:DI 0 "s_register_operand" "=&r")
994 (mult:DI (zero_extend:DI
995 (match_operand:SI 1 "s_register_operand" "%r"))
997 (match_operand:SI 2 "s_register_operand" "r"))))]
999 "umull%?\\t%Q0, %R0, %1, %2"
1000 [(set_attr "type" "mult")])
1002 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1004 (define_insn "*umulsidi3adddi"
1005 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
1007 (mult:DI (zero_extend:DI
1008 (match_operand:SI 2 "s_register_operand" "r,0,1"))
1010 (match_operand:SI 1 "s_register_operand" "%r,r,r")))
1013 "umlal%?\\t%Q0, %R0, %1, %2"
1014 [(set_attr "type" "mult")])
1016 (define_insn "smulsi3_highpart"
1017 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1020 (mult:DI (sign_extend:DI
1021 (match_operand:SI 1 "s_register_operand" "%r,0"))
1023 (match_operand:SI 2 "s_register_operand" "r,r")))
1025 (clobber (match_scratch:SI 3 "=&r,&r"))]
1027 "smull%?\\t%3, %0, %2, %1"
1028 [(set_attr "type" "mult")])
1030 (define_insn "umulsi3_highpart"
1031 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1034 (mult:DI (zero_extend:DI
1035 (match_operand:SI 1 "s_register_operand" "%r,0"))
1037 (match_operand:SI 2 "s_register_operand" "r,r")))
1039 (clobber (match_scratch:SI 3 "=&r,&r"))]
1041 "umull%?\\t%3, %0, %2, %1"
1042 [(set_attr "type" "mult")])
1044 (define_insn "mulsf3"
1045 [(set (match_operand:SF 0 "s_register_operand" "=f")
1046 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1047 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1049 "fml%?s\\t%0, %1, %2"
1050 [(set_attr "type" "ffmul")])
1052 (define_insn "muldf3"
1053 [(set (match_operand:DF 0 "s_register_operand" "=f")
1054 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1055 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1057 "muf%?d\\t%0, %1, %2"
1058 [(set_attr "type" "fmul")])
1060 (define_insn "*muldf_esfdf_df"
1061 [(set (match_operand:DF 0 "s_register_operand" "=f")
1062 (mult:DF (float_extend:DF
1063 (match_operand:SF 1 "s_register_operand" "f"))
1064 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1066 "muf%?d\\t%0, %1, %2"
1067 [(set_attr "type" "fmul")])
1069 (define_insn "*muldf_df_esfdf"
1070 [(set (match_operand:DF 0 "s_register_operand" "=f")
1071 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1073 (match_operand:SF 2 "s_register_operand" "f"))))]
1075 "muf%?d\\t%0, %1, %2"
1076 [(set_attr "type" "fmul")])
1078 (define_insn "*muldf_esfdf_esfdf"
1079 [(set (match_operand:DF 0 "s_register_operand" "=f")
1080 (mult:DF (float_extend:DF
1081 (match_operand:SF 1 "s_register_operand" "f"))
1083 (match_operand:SF 2 "s_register_operand" "f"))))]
1085 "muf%?d\\t%0, %1, %2"
1086 [(set_attr "type" "fmul")])
1088 (define_insn "mulxf3"
1089 [(set (match_operand:XF 0 "s_register_operand" "=f")
1090 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1091 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1092 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1093 "muf%?e\\t%0, %1, %2"
1094 [(set_attr "type" "fmul")])
1098 (define_insn "divsf3"
1099 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1100 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1101 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1105 frd%?s\\t%0, %2, %1"
1106 [(set_attr "type" "fdivs")])
1108 (define_insn "divdf3"
1109 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1110 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1111 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1115 rdf%?d\\t%0, %2, %1"
1116 [(set_attr "type" "fdivd")])
1118 (define_insn "*divdf_esfdf_df"
1119 [(set (match_operand:DF 0 "s_register_operand" "=f")
1120 (div:DF (float_extend:DF
1121 (match_operand:SF 1 "s_register_operand" "f"))
1122 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1124 "dvf%?d\\t%0, %1, %2"
1125 [(set_attr "type" "fdivd")])
1127 (define_insn "*divdf_df_esfdf"
1128 [(set (match_operand:DF 0 "s_register_operand" "=f")
1129 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1131 (match_operand:SF 2 "s_register_operand" "f"))))]
1133 "rdf%?d\\t%0, %2, %1"
1134 [(set_attr "type" "fdivd")])
1136 (define_insn "*divdf_esfdf_esfdf"
1137 [(set (match_operand:DF 0 "s_register_operand" "=f")
1138 (div:DF (float_extend:DF
1139 (match_operand:SF 1 "s_register_operand" "f"))
1141 (match_operand:SF 2 "s_register_operand" "f"))))]
1143 "dvf%?d\\t%0, %1, %2"
1144 [(set_attr "type" "fdivd")])
1146 (define_insn "divxf3"
1147 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1148 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1149 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1150 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1153 rdf%?e\\t%0, %2, %1"
1154 [(set_attr "type" "fdivx")])
1158 (define_insn "modsf3"
1159 [(set (match_operand:SF 0 "s_register_operand" "=f")
1160 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1161 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1163 "rmf%?s\\t%0, %1, %2"
1164 [(set_attr "type" "fdivs")])
1166 (define_insn "moddf3"
1167 [(set (match_operand:DF 0 "s_register_operand" "=f")
1168 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1169 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1171 "rmf%?d\\t%0, %1, %2"
1172 [(set_attr "type" "fdivd")])
1174 (define_insn "*moddf_esfdf_df"
1175 [(set (match_operand:DF 0 "s_register_operand" "=f")
1176 (mod:DF (float_extend:DF
1177 (match_operand:SF 1 "s_register_operand" "f"))
1178 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1180 "rmf%?d\\t%0, %1, %2"
1181 [(set_attr "type" "fdivd")])
1183 (define_insn "*moddf_df_esfdf"
1184 [(set (match_operand:DF 0 "s_register_operand" "=f")
1185 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1187 (match_operand:SF 2 "s_register_operand" "f"))))]
1189 "rmf%?d\\t%0, %1, %2"
1190 [(set_attr "type" "fdivd")])
1192 (define_insn "*moddf_esfdf_esfdf"
1193 [(set (match_operand:DF 0 "s_register_operand" "=f")
1194 (mod:DF (float_extend:DF
1195 (match_operand:SF 1 "s_register_operand" "f"))
1197 (match_operand:SF 2 "s_register_operand" "f"))))]
1199 "rmf%?d\\t%0, %1, %2"
1200 [(set_attr "type" "fdivd")])
1202 (define_insn "modxf3"
1203 [(set (match_operand:XF 0 "s_register_operand" "=f")
1204 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1205 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1206 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1207 "rmf%?e\\t%0, %1, %2"
1208 [(set_attr "type" "fdivx")])
1210 ;; Boolean and,ior,xor insns
1212 ;; Split up double word logical operations
1214 ;; Split up simple DImode logical operations. Simply perform the logical
1215 ;; operation on the upper and lower halves of the registers.
1217 [(set (match_operand:DI 0 "s_register_operand" "")
1218 (match_operator:DI 6 "logical_binary_operator"
1219 [(match_operand:DI 1 "s_register_operand" "")
1220 (match_operand:DI 2 "s_register_operand" "")]))]
1222 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1223 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1226 operands[3] = gen_highpart (SImode, operands[0]);
1227 operands[0] = gen_lowpart (SImode, operands[0]);
1228 operands[4] = gen_highpart (SImode, operands[1]);
1229 operands[1] = gen_lowpart (SImode, operands[1]);
1230 operands[5] = gen_highpart (SImode, operands[2]);
1231 operands[2] = gen_lowpart (SImode, operands[2]);
1235 [(set (match_operand:DI 0 "s_register_operand" "")
1236 (not:DI (match_operand:DI 1 "s_register_operand" "")))]
1238 [(set (match_dup 0) (not:SI (match_dup 1)))
1239 (set (match_dup 2) (not:SI (match_dup 3)))]
1242 operands[2] = gen_highpart (SImode, operands[0]);
1243 operands[0] = gen_lowpart (SImode, operands[0]);
1244 operands[3] = gen_highpart (SImode, operands[1]);
1245 operands[1] = gen_lowpart (SImode, operands[1]);
1249 [(set (match_operand:DI 0 "s_register_operand" "")
1251 (not:DI (match_operand:DI 1 "s_register_operand" ""))
1252 (match_operand:DI 2 "s_register_operand" "")))]
1254 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1255 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1258 operands[3] = gen_highpart (SImode, operands[0]);
1259 operands[0] = gen_lowpart (SImode, operands[0]);
1260 operands[4] = gen_highpart (SImode, operands[1]);
1261 operands[1] = gen_lowpart (SImode, operands[1]);
1262 operands[5] = gen_highpart (SImode, operands[2]);
1263 operands[2] = gen_lowpart (SImode, operands[2]);
1267 [(set (match_operand:DI 0 "s_register_operand" "")
1268 (match_operator:DI 6 "logical_binary_operator"
1269 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1270 (match_operand:DI 1 "s_register_operand" "")]))]
1272 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1273 (set (match_dup 3) (match_op_dup:SI 6
1274 [(ashiftrt:SI (match_dup 2) (const_int 31))
1278 operands[3] = gen_highpart (SImode, operands[0]);
1279 operands[0] = gen_lowpart (SImode, operands[0]);
1280 operands[4] = gen_highpart (SImode, operands[1]);
1281 operands[1] = gen_lowpart (SImode, operands[1]);
1282 operands[5] = gen_highpart (SImode, operands[2]);
1283 operands[2] = gen_lowpart (SImode, operands[2]);
1287 [(set (match_operand:DI 0 "s_register_operand" "")
1288 (and:DI (not:DI (sign_extend:DI
1289 (match_operand:SI 2 "s_register_operand" "")))
1290 (match_operand:DI 1 "s_register_operand" "")))]
1292 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1293 (set (match_dup 3) (and:SI (not:SI
1294 (ashiftrt:SI (match_dup 2) (const_int 31)))
1298 operands[3] = gen_highpart (SImode, operands[0]);
1299 operands[0] = gen_lowpart (SImode, operands[0]);
1300 operands[4] = gen_highpart (SImode, operands[1]);
1301 operands[1] = gen_lowpart (SImode, operands[1]);
1302 operands[2] = gen_lowpart (SImode, operands[2]);
1305 ;; The zero extend of operand 2 clears the high word of the output
1308 [(set (match_operand:DI 0 "s_register_operand" "")
1310 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1311 (match_operand:DI 1 "s_register_operand" "")))]
1313 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1314 (set (match_dup 3) (const_int 0))]
1317 operands[3] = gen_highpart (SImode, operands[0]);
1318 operands[0] = gen_lowpart (SImode, operands[0]);
1319 operands[1] = gen_lowpart (SImode, operands[1]);
1322 ;; The zero extend of operand 2 means we can just copy the high part of
1323 ;; operand1 into operand0.
1325 [(set (match_operand:DI 0 "s_register_operand" "")
1327 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1328 (match_operand:DI 1 "s_register_operand" "")))]
1329 "operands[0] != operands[1] && reload_completed"
1330 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1331 (set (match_dup 3) (match_dup 4))]
1334 operands[4] = gen_highpart (SImode, operands[1]);
1335 operands[3] = gen_highpart (SImode, operands[0]);
1336 operands[0] = gen_lowpart (SImode, operands[0]);
1337 operands[1] = gen_lowpart (SImode, operands[1]);
1340 ;; The zero extend of operand 2 means we can just copy the high part of
1341 ;; operand1 into operand0.
1343 [(set (match_operand:DI 0 "s_register_operand" "")
1345 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1346 (match_operand:DI 1 "s_register_operand" "")))]
1347 "operands[0] != operands[1] && reload_completed"
1348 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1349 (set (match_dup 3) (match_dup 4))]
1352 operands[4] = gen_highpart (SImode, operands[1]);
1353 operands[3] = gen_highpart (SImode, operands[0]);
1354 operands[0] = gen_lowpart (SImode, operands[0]);
1355 operands[1] = gen_lowpart (SImode, operands[1]);
1358 ;; (not (zero_extend ...)) allows us to just copy the high word from
1359 ;; operand1 to operand0.
1361 [(set (match_operand:DI 0 "s_register_operand" "")
1362 (and:DI (not:DI (zero_extend:DI
1363 (match_operand:SI 2 "s_register_operand" "")))
1364 (match_operand:DI 1 "s_register_operand" "")))]
1365 "operands[0] != operands[1] && reload_completed"
1366 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1367 (set (match_dup 3) (match_dup 4))]
1370 operands[3] = gen_highpart (SImode, operands[0]);
1371 operands[0] = gen_lowpart (SImode, operands[0]);
1372 operands[4] = gen_highpart (SImode, operands[1]);
1373 operands[1] = gen_lowpart (SImode, operands[1]);
1374 operands[2] = gen_lowpart (SImode, operands[2]);
1377 (define_insn "anddi3"
1378 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1379 (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1380 (match_operand:DI 2 "s_register_operand" "r,0")))]
1383 [(set_attr "length" "8")])
1385 (define_insn "*anddi_zesidi_di"
1386 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1387 (and:DI (zero_extend:DI
1388 (match_operand:SI 2 "s_register_operand" "r,r"))
1389 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1392 [(set_attr "length" "8")])
1394 (define_insn "*anddi_sesdi_di"
1395 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1396 (and:DI (sign_extend:DI
1397 (match_operand:SI 2 "s_register_operand" "r,r"))
1398 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1401 [(set_attr "length" "8")])
1403 (define_expand "andsi3"
1404 [(set (match_operand:SI 0 "s_register_operand" "")
1405 (and:SI (match_operand:SI 1 "s_register_operand" "")
1406 (match_operand:SI 2 "reg_or_int_operand" "")))]
1409 if (GET_CODE (operands[2]) == CONST_INT)
1411 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1413 (reload_in_progress || reload_completed
1414 ? 0 : preserve_subexpressions_p ()));
1419 (define_insn "*andsi3_insn"
1420 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1421 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1422 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1426 bic%?\\t%0, %1, #%B2
1428 [(set_attr "length" "4,4,16")])
1431 [(set (match_operand:SI 0 "s_register_operand" "")
1432 (and:SI (match_operand:SI 1 "s_register_operand" "")
1433 (match_operand:SI 2 "const_int_operand" "")))]
1434 "! (const_ok_for_arm (INTVAL (operands[2]))
1435 || const_ok_for_arm (~ INTVAL (operands[2])))"
1436 [(clobber (const_int 0))]
1438 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1443 (define_insn "*andsi3_compare0"
1444 [(set (reg:CC_NOOV 24)
1446 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1447 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1449 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1450 (and:SI (match_dup 1) (match_dup 2)))]
1454 bic%?s\\t%0, %1, #%B2"
1455 [(set_attr "conds" "set")])
1457 (define_insn "*andsi3_compare0_scratch"
1458 [(set (reg:CC_NOOV 24)
1460 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1461 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1463 (clobber (match_scratch:SI 3 "=X,r"))]
1467 bic%?s\\t%3, %0, #%B1"
1468 [(set_attr "conds" "set")])
1470 (define_insn "*zeroextractsi_compare0_scratch"
1471 [(set (reg:CC_NOOV 24)
1472 (compare:CC_NOOV (zero_extract:SI
1473 (match_operand:SI 0 "s_register_operand" "r")
1474 (match_operand 1 "const_int_operand" "n")
1475 (match_operand 2 "const_int_operand" "n"))
1477 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1478 && INTVAL (operands[1]) > 0
1479 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1480 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1482 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1483 << INTVAL (operands[2]));
1484 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1487 [(set_attr "conds" "set")])
1489 (define_insn "*ne_zeroextractsi"
1490 [(set (match_operand:SI 0 "s_register_operand" "=r")
1491 (ne:SI (zero_extract:SI
1492 (match_operand:SI 1 "s_register_operand" "r")
1493 (match_operand:SI 2 "const_int_operand" "n")
1494 (match_operand:SI 3 "const_int_operand" "n"))
1496 "INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1497 && INTVAL (operands[2]) > 0
1498 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1499 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32"
1501 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1502 << INTVAL (operands[3]));
1503 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1504 return \"movne\\t%0, #1\";
1506 [(set_attr "conds" "clob")
1507 (set_attr "length" "8")])
1509 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1510 ;;; represented by the bitfield, then this will produce incorrect results.
1511 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1512 ;;; which have a real bitfield insert instruction, the truncation happens
1513 ;;; in the bitfield insert instruction itself. Since arm does not have a
1514 ;;; bitfield insert instruction, we would have to emit code here to truncate
1515 ;;; the value before we insert. This loses some of the advantage of having
1516 ;;; this insv pattern, so this pattern needs to be reevalutated.
1518 (define_expand "insv"
1519 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1520 (match_operand:SI 1 "general_operand" "")
1521 (match_operand:SI 2 "general_operand" ""))
1522 (match_operand:SI 3 "nonmemory_operand" ""))]
1526 int start_bit = INTVAL (operands[2]);
1527 int width = INTVAL (operands[1]);
1528 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1529 rtx target, subtarget;
1531 target = operands[0];
1532 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1533 subreg as the final target. */
1534 if (GET_CODE (target) == SUBREG)
1536 subtarget = gen_reg_rtx (SImode);
1537 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1538 < GET_MODE_SIZE (SImode))
1539 target = SUBREG_REG (target);
1544 if (GET_CODE (operands[3]) == CONST_INT)
1546 /* Since we are inserting a known constant, we may be able to
1547 reduce the number of bits that we have to clear so that
1548 the mask becomes simple. */
1549 /* ??? This code does not check to see if the new mask is actually
1550 simpler. It may not be. */
1551 rtx op1 = gen_reg_rtx (SImode);
1552 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1553 start of this pattern. */
1554 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1555 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1557 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1558 emit_insn (gen_iorsi3 (subtarget, op1,
1559 GEN_INT (op3_value << start_bit)));
1561 else if (start_bit == 0
1562 && ! (const_ok_for_arm (mask)
1563 || const_ok_for_arm (~mask)))
1565 /* A Trick, since we are setting the bottom bits in the word,
1566 we can shift operand[3] up, operand[0] down, OR them together
1567 and rotate the result back again. This takes 3 insns, and
1568 the third might be mergable into another op. */
1569 /* The shift up copes with the possibility that operand[3] is
1570 wider than the bitfield. */
1571 rtx op0 = gen_reg_rtx (SImode);
1572 rtx op1 = gen_reg_rtx (SImode);
1574 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1575 emit_insn (gen_iorsi3 (op1, gen_rtx_LSHIFTRT (SImode, operands[0],
1578 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1580 else if ((width + start_bit == 32)
1581 && ! (const_ok_for_arm (mask)
1582 || const_ok_for_arm (~mask)))
1584 /* Similar trick, but slightly less efficient. */
1586 rtx op0 = gen_reg_rtx (SImode);
1587 rtx op1 = gen_reg_rtx (SImode);
1589 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1590 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1591 emit_insn (gen_iorsi3 (subtarget,
1592 gen_rtx_LSHIFTRT (SImode, op1, operands[1]),
1597 rtx op0 = GEN_INT (mask);
1598 rtx op1 = gen_reg_rtx (SImode);
1599 rtx op2 = gen_reg_rtx (SImode);
1601 if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1603 rtx tmp = gen_reg_rtx (SImode);
1605 emit_insn (gen_movsi (tmp, op0));
1609 /* Mask out any bits in operand[3] that are not needed. */
1610 emit_insn (gen_andsi3 (op1, operands[3], op0));
1612 if (GET_CODE (op0) == CONST_INT
1613 && (const_ok_for_arm (mask << start_bit)
1614 || const_ok_for_arm (~ (mask << start_bit))))
1616 op0 = GEN_INT (~(mask << start_bit));
1617 emit_insn (gen_andsi3 (op2, operands[0], op0));
1621 if (GET_CODE (op0) == CONST_INT)
1623 rtx tmp = gen_reg_rtx (SImode);
1625 emit_insn (gen_movsi (tmp, op0));
1630 op0 = gen_rtx_ASHIFT (SImode, op0, operands[2]);
1632 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1636 op1 = gen_rtx_ASHIFT (SImode, op1, operands[2]);
1638 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1641 if (subtarget != target)
1643 /* If TARGET is still a SUBREG, then it must be wider than a word,
1644 so we must be careful only to set the subword we were asked to. */
1645 if (GET_CODE (target) == SUBREG)
1646 emit_move_insn (target, subtarget);
1648 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1655 ;; constants for op 2 will never be given to these patterns.
1656 (define_insn "*anddi_notdi_di"
1657 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1658 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1659 (match_operand:DI 1 "s_register_operand" "0,r")))]
1662 [(set_attr "length" "8")])
1664 (define_insn "*anddi_notzesidi_di"
1665 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1666 (and:DI (not:DI (zero_extend:DI
1667 (match_operand:SI 2 "s_register_operand" "r,r")))
1668 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1671 bic%?\\t%Q0, %Q1, %2
1673 [(set_attr "length" "4,8")])
1675 (define_insn "*anddi_notsesidi_di"
1676 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1677 (and:DI (not:DI (sign_extend:DI
1678 (match_operand:SI 2 "s_register_operand" "r,r")))
1679 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1682 [(set_attr "length" "8")])
1684 (define_insn "andsi_notsi_si"
1685 [(set (match_operand:SI 0 "s_register_operand" "=r")
1686 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1687 (match_operand:SI 1 "s_register_operand" "r")))]
1689 "bic%?\\t%0, %1, %2")
1691 (define_insn "andsi_not_shiftsi_si"
1692 [(set (match_operand:SI 0 "s_register_operand" "=r")
1693 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1694 [(match_operand:SI 2 "s_register_operand" "r")
1695 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1696 (match_operand:SI 1 "s_register_operand" "r")))]
1698 "bic%?\\t%0, %1, %2%S4"
1701 (define_insn "*andsi_notsi_si_compare0"
1702 [(set (reg:CC_NOOV 24)
1704 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1705 (match_operand:SI 1 "s_register_operand" "r"))
1707 (set (match_operand:SI 0 "s_register_operand" "=r")
1708 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1710 "bic%?s\\t%0, %1, %2"
1711 [(set_attr "conds" "set")])
1713 (define_insn "*andsi_notsi_si_compare0_scratch"
1714 [(set (reg:CC_NOOV 24)
1716 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1717 (match_operand:SI 1 "s_register_operand" "r"))
1719 (clobber (match_scratch:SI 0 "=r"))]
1721 "bic%?s\\t%0, %1, %2"
1722 [(set_attr "conds" "set")])
1724 (define_insn "iordi3"
1725 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1726 (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1727 (match_operand:DI 2 "s_register_operand" "r")))]
1730 [(set_attr "length" "8")])
1732 (define_insn "*iordi_zesidi_di"
1733 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1734 (ior:DI (zero_extend:DI
1735 (match_operand:SI 2 "s_register_operand" "r,r"))
1736 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1739 orr%?\\t%Q0, %Q1, %2
1741 [(set_attr "length" "4,8")])
1743 (define_insn "*iordi_sesidi_di"
1744 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1745 (ior:DI (sign_extend:DI
1746 (match_operand:SI 2 "s_register_operand" "r,r"))
1747 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1750 [(set_attr "length" "8")])
1752 (define_expand "iorsi3"
1753 [(set (match_operand:SI 0 "s_register_operand" "")
1754 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1755 (match_operand:SI 2 "reg_or_int_operand" "")))]
1758 if (GET_CODE (operands[2]) == CONST_INT)
1760 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1762 (reload_in_progress || reload_completed
1763 ? 0 : preserve_subexpressions_p ()));
1768 (define_insn "*iorsi3_insn"
1769 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1770 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1771 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1776 [(set_attr "length" "4,16")])
1779 [(set (match_operand:SI 0 "s_register_operand" "")
1780 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1781 (match_operand:SI 2 "const_int_operand" "")))]
1782 "! const_ok_for_arm (INTVAL (operands[2]))"
1783 [(clobber (const_int 0))]
1785 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1790 (define_insn "*iorsi3_compare0"
1791 [(set (reg:CC_NOOV 24)
1792 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1793 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1795 (set (match_operand:SI 0 "s_register_operand" "=r")
1796 (ior:SI (match_dup 1) (match_dup 2)))]
1798 "orr%?s\\t%0, %1, %2"
1799 [(set_attr "conds" "set")])
1801 (define_insn "*iorsi3_compare0_scratch"
1802 [(set (reg:CC_NOOV 24)
1803 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1804 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1806 (clobber (match_scratch:SI 0 "=r"))]
1808 "orr%?s\\t%0, %1, %2"
1809 [(set_attr "conds" "set")])
1811 (define_insn "xordi3"
1812 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1813 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1814 (match_operand:DI 2 "s_register_operand" "r,0")))]
1817 [(set_attr "length" "8")])
1819 (define_insn "*xordi_zesidi_di"
1820 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1821 (xor:DI (zero_extend:DI
1822 (match_operand:SI 2 "s_register_operand" "r,r"))
1823 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1826 eor%?\\t%Q0, %Q1, %2
1828 [(set_attr "length" "4,8")])
1830 (define_insn "*xordi_sesidi_di"
1831 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1832 (xor:DI (sign_extend:DI
1833 (match_operand:SI 2 "s_register_operand" "r,r"))
1834 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1837 [(set_attr "length" "8")])
1839 (define_insn "xorsi3"
1840 [(set (match_operand:SI 0 "s_register_operand" "=r")
1841 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1842 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1844 "eor%?\\t%0, %1, %2")
1846 (define_insn "*xorsi3_compare0"
1847 [(set (reg:CC_NOOV 24)
1848 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1849 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1851 (set (match_operand:SI 0 "s_register_operand" "=r")
1852 (xor:SI (match_dup 1) (match_dup 2)))]
1854 "eor%?s\\t%0, %1, %2"
1855 [(set_attr "conds" "set")])
1857 (define_insn "*xorsi3_compare0_scratch"
1858 [(set (reg:CC_NOOV 24)
1859 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1860 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1864 [(set_attr "conds" "set")])
1866 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
1867 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1871 [(set (match_operand:SI 0 "s_register_operand" "=r")
1872 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1873 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1874 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1875 (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1877 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1878 (not:SI (match_dup 3))))
1879 (set (match_dup 0) (not:SI (match_dup 4)))]
1883 (define_insn "*andsi_iorsi3_notsi"
1884 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1885 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1886 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1887 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1889 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1890 [(set_attr "length" "8")])
1894 ;; Minimum and maximum insns
1896 (define_insn "smaxsi3"
1897 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1898 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1899 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1900 (clobber (reg:CC 24))]
1903 cmp\\t%1, %2\;movlt\\t%0, %2
1904 cmp\\t%1, %2\;movge\\t%0, %1
1905 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1906 [(set_attr "conds" "clob")
1907 (set_attr "length" "8,8,12")])
1909 (define_insn "sminsi3"
1910 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1911 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1912 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1913 (clobber (reg:CC 24))]
1916 cmp\\t%1, %2\;movge\\t%0, %2
1917 cmp\\t%1, %2\;movlt\\t%0, %1
1918 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1919 [(set_attr "conds" "clob")
1920 (set_attr "length" "8,8,12")])
1922 (define_insn "umaxsi3"
1923 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1924 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1925 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1926 (clobber (reg:CC 24))]
1929 cmp\\t%1, %2\;movcc\\t%0, %2
1930 cmp\\t%1, %2\;movcs\\t%0, %1
1931 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1932 [(set_attr "conds" "clob")
1933 (set_attr "length" "8,8,12")])
1935 (define_insn "uminsi3"
1936 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1937 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1938 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1939 (clobber (reg:CC 24))]
1942 cmp\\t%1, %2\;movcs\\t%0, %2
1943 cmp\\t%1, %2\;movcc\\t%0, %1
1944 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1945 [(set_attr "conds" "clob")
1946 (set_attr "length" "8,8,12")])
1948 (define_insn "*store_minmaxsi"
1949 [(set (match_operand:SI 0 "memory_operand" "=m")
1950 (match_operator:SI 3 "minmax_operator"
1951 [(match_operand:SI 1 "s_register_operand" "r")
1952 (match_operand:SI 2 "s_register_operand" "r")]))
1953 (clobber (reg:CC 24))]
1956 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1958 output_asm_insn (\"cmp\\t%1, %2\", operands);
1959 output_asm_insn (\"str%d3\\t%1, %0\", operands);
1960 output_asm_insn (\"str%D3\\t%2, %0\", operands);
1963 [(set_attr "conds" "clob")
1964 (set_attr "length" "12")
1965 (set_attr "type" "store1")])
1967 ; Reject the frame pointer in operand[1], since reloading this after
1968 ; it has been eliminated can cause carnage.
1969 (define_insn "*minmax_arithsi"
1970 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1971 (match_operator:SI 4 "shiftable_operator"
1972 [(match_operator:SI 5 "minmax_operator"
1973 [(match_operand:SI 2 "s_register_operand" "r,r")
1974 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1975 (match_operand:SI 1 "s_register_operand" "0,?r")]))
1976 (clobber (reg:CC 24))]
1977 "GET_CODE (operands[1]) != REG
1978 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
1979 && REGNO(operands[1]) != ARG_POINTER_REGNUM)"
1982 enum rtx_code code = GET_CODE (operands[4]);
1984 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1986 output_asm_insn (\"cmp\\t%2, %3\", operands);
1987 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1988 if (which_alternative != 0 || operands[3] != const0_rtx
1989 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1990 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1994 [(set_attr "conds" "clob")
1995 (set_attr "length" "12")])
1998 ;; Shift and rotation insns
2000 (define_expand "ashlsi3"
2001 [(set (match_operand:SI 0 "s_register_operand" "")
2002 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2003 (match_operand:SI 2 "arm_rhs_operand" "")))]
2006 if (GET_CODE (operands[2]) == CONST_INT
2007 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2009 emit_insn (gen_movsi (operands[0], const0_rtx));
2014 (define_expand "ashrsi3"
2015 [(set (match_operand:SI 0 "s_register_operand" "")
2016 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2017 (match_operand:SI 2 "arm_rhs_operand" "")))]
2020 if (GET_CODE (operands[2]) == CONST_INT
2021 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2022 operands[2] = GEN_INT (31);
2025 (define_expand "lshrsi3"
2026 [(set (match_operand:SI 0 "s_register_operand" "")
2027 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2028 (match_operand:SI 2 "arm_rhs_operand" "")))]
2031 if (GET_CODE (operands[2]) == CONST_INT
2032 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2034 emit_insn (gen_movsi (operands[0], const0_rtx));
2039 (define_expand "rotlsi3"
2040 [(set (match_operand:SI 0 "s_register_operand" "")
2041 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2042 (match_operand:SI 2 "reg_or_int_operand" "")))]
2045 if (GET_CODE (operands[2]) == CONST_INT)
2046 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2049 rtx reg = gen_reg_rtx (SImode);
2050 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2055 (define_expand "rotrsi3"
2056 [(set (match_operand:SI 0 "s_register_operand" "")
2057 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2058 (match_operand:SI 2 "arm_rhs_operand" "")))]
2061 if (GET_CODE (operands[2]) == CONST_INT
2062 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2063 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2066 (define_insn "*shiftsi3"
2067 [(set (match_operand:SI 0 "s_register_operand" "=r")
2068 (match_operator:SI 3 "shift_operator"
2069 [(match_operand:SI 1 "s_register_operand" "r")
2070 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2075 (define_insn "*shiftsi3_compare0"
2076 [(set (reg:CC_NOOV 24)
2077 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2078 [(match_operand:SI 1 "s_register_operand" "r")
2079 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2081 (set (match_operand:SI 0 "s_register_operand" "=r")
2082 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2084 "mov%?s\\t%0, %1%S3"
2085 [(set_attr "conds" "set")
2088 (define_insn "*shiftsi3_compare0_scratch"
2089 [(set (reg:CC_NOOV 24)
2090 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2091 [(match_operand:SI 1 "s_register_operand" "r")
2092 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2094 (clobber (match_scratch:SI 0 "=r"))]
2096 "mov%?s\\t%0, %1%S3"
2097 [(set_attr "conds" "set")
2100 (define_insn "*notsi_shiftsi"
2101 [(set (match_operand:SI 0 "s_register_operand" "=r")
2102 (not:SI (match_operator:SI 3 "shift_operator"
2103 [(match_operand:SI 1 "s_register_operand" "r")
2104 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2109 (define_insn "*notsi_shiftsi_compare0"
2110 [(set (reg:CC_NOOV 24)
2111 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2112 [(match_operand:SI 1 "s_register_operand" "r")
2113 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2115 (set (match_operand:SI 0 "s_register_operand" "=r")
2116 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2118 "mvn%?s\\t%0, %1%S3"
2119 [(set_attr "conds" "set")
2122 (define_insn "*not_shiftsi_compare0_scratch"
2123 [(set (reg:CC_NOOV 24)
2124 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2125 [(match_operand:SI 1 "s_register_operand" "r")
2126 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2128 (clobber (match_scratch:SI 0 "=r"))]
2130 "mvn%?s\\t%0, %1%S3"
2131 [(set_attr "conds" "set")
2135 ;; Unary arithmetic insns
2137 (define_insn "negdi2"
2138 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2139 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2141 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2142 [(set_attr "conds" "clob")
2143 (set_attr "length" "8")])
2145 (define_insn "negsi2"
2146 [(set (match_operand:SI 0 "s_register_operand" "=r")
2147 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2149 "rsb%?\\t%0, %1, #0")
2151 (define_insn "negsf2"
2152 [(set (match_operand:SF 0 "s_register_operand" "=f")
2153 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2156 [(set_attr "type" "ffarith")])
2158 (define_insn "negdf2"
2159 [(set (match_operand:DF 0 "s_register_operand" "=f")
2160 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2163 [(set_attr "type" "ffarith")])
2165 (define_insn "*negdf_esfdf"
2166 [(set (match_operand:DF 0 "s_register_operand" "=f")
2167 (neg:DF (float_extend:DF
2168 (match_operand:SF 1 "s_register_operand" "f"))))]
2171 [(set_attr "type" "ffarith")])
2173 (define_insn "negxf2"
2174 [(set (match_operand:XF 0 "s_register_operand" "=f")
2175 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2176 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2178 [(set_attr "type" "ffarith")])
2180 ;; abssi2 doesn't really clobber the condition codes if a different register
2181 ;; is being set. To keep things simple, assume during rtl manipulations that
2182 ;; it does, but tell the final scan operator the truth. Similarly for
2185 (define_insn "abssi2"
2186 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2187 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2188 (clobber (reg:CC 24))]
2191 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2192 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2193 [(set_attr "conds" "clob,*")
2194 (set_attr "length" "8")])
2196 (define_insn "*neg_abssi2"
2197 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2198 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2199 (clobber (reg:CC 24))]
2202 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2203 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2204 [(set_attr "conds" "clob,*")
2205 (set_attr "length" "8")])
2207 (define_insn "abssf2"
2208 [(set (match_operand:SF 0 "s_register_operand" "=f")
2209 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2212 [(set_attr "type" "ffarith")])
2214 (define_insn "absdf2"
2215 [(set (match_operand:DF 0 "s_register_operand" "=f")
2216 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2219 [(set_attr "type" "ffarith")])
2221 (define_insn "*absdf_esfdf"
2222 [(set (match_operand:DF 0 "s_register_operand" "=f")
2223 (abs:DF (float_extend:DF
2224 (match_operand:SF 1 "s_register_operand" "f"))))]
2227 [(set_attr "type" "ffarith")])
2229 (define_insn "absxf2"
2230 [(set (match_operand:XF 0 "s_register_operand" "=f")
2231 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2232 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2234 [(set_attr "type" "ffarith")])
2236 (define_insn "sqrtsf2"
2237 [(set (match_operand:SF 0 "s_register_operand" "=f")
2238 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2241 [(set_attr "type" "float_em")])
2243 (define_insn "sqrtdf2"
2244 [(set (match_operand:DF 0 "s_register_operand" "=f")
2245 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2248 [(set_attr "type" "float_em")])
2250 (define_insn "*sqrtdf_esfdf"
2251 [(set (match_operand:DF 0 "s_register_operand" "=f")
2252 (sqrt:DF (float_extend:DF
2253 (match_operand:SF 1 "s_register_operand" "f"))))]
2256 [(set_attr "type" "float_em")])
2258 (define_insn "sqrtxf2"
2259 [(set (match_operand:XF 0 "s_register_operand" "=f")
2260 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2261 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2263 [(set_attr "type" "float_em")])
2265 ;; SIN COS TAN and family are always emulated, so it's probably better
2266 ;; to always call a library function.
2267 ;(define_insn "sinsf2"
2268 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2269 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
2270 ; "TARGET_HARD_FLOAT"
2272 ;[(set_attr "type" "float_em")])
2274 ;(define_insn "sindf2"
2275 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2276 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
2277 ; "TARGET_HARD_FLOAT"
2279 ;[(set_attr "type" "float_em")])
2281 ;(define_insn "*sindf_esfdf"
2282 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2283 ; (unspec:DF [(float_extend:DF
2284 ; (match_operand:SF 1 "s_register_operand" "f"))] 0))]
2285 ; "TARGET_HARD_FLOAT"
2287 ;[(set_attr "type" "float_em")])
2289 ;(define_insn "sinxf2"
2290 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2291 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
2292 ; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2294 ;[(set_attr "type" "float_em")])
2296 ;(define_insn "cossf2"
2297 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2298 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
2299 ; "TARGET_HARD_FLOAT"
2301 ;[(set_attr "type" "float_em")])
2303 ;(define_insn "cosdf2"
2304 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2305 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
2306 ; "TARGET_HARD_FLOAT"
2308 ;[(set_attr "type" "float_em")])
2310 ;(define_insn "*cosdf_esfdf"
2311 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2312 ; (unspec:DF [(float_extend:DF
2313 ; (match_operand:SF 1 "s_register_operand" "f"))] 1))]
2314 ; "TARGET_HARD_FLOAT"
2316 ;[(set_attr "type" "float_em")])
2318 ;(define_insn "cosxf2"
2319 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2320 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
2321 ; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2323 ;[(set_attr "type" "float_em")])
2325 (define_insn "one_cmpldi2"
2326 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2327 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2330 [(set_attr "length" "8")])
2332 (define_insn "one_cmplsi2"
2333 [(set (match_operand:SI 0 "s_register_operand" "=r")
2334 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2338 (define_insn "*notsi_compare0"
2339 [(set (reg:CC_NOOV 24)
2340 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2342 (set (match_operand:SI 0 "s_register_operand" "=r")
2343 (not:SI (match_dup 1)))]
2346 [(set_attr "conds" "set")])
2348 (define_insn "*notsi_compare0_scratch"
2349 [(set (reg:CC_NOOV 24)
2350 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2352 (clobber (match_scratch:SI 0 "=r"))]
2355 [(set_attr "conds" "set")])
2357 ;; Fixed <--> Floating conversion insns
2359 (define_insn "floatsisf2"
2360 [(set (match_operand:SF 0 "s_register_operand" "=f")
2361 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2364 [(set_attr "type" "r_2_f")])
2366 (define_insn "floatsidf2"
2367 [(set (match_operand:DF 0 "s_register_operand" "=f")
2368 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2371 [(set_attr "type" "r_2_f")])
2373 (define_insn "floatsixf2"
2374 [(set (match_operand:XF 0 "s_register_operand" "=f")
2375 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
2376 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2378 [(set_attr "type" "r_2_f")])
2380 (define_insn "fix_truncsfsi2"
2381 [(set (match_operand:SI 0 "s_register_operand" "=r")
2382 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2385 [(set_attr "type" "f_2_r")])
2387 (define_insn "fix_truncdfsi2"
2388 [(set (match_operand:SI 0 "s_register_operand" "=r")
2389 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2392 [(set_attr "type" "f_2_r")])
2394 (define_insn "fix_truncxfsi2"
2395 [(set (match_operand:SI 0 "s_register_operand" "=r")
2396 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
2397 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2399 [(set_attr "type" "f_2_r")])
2403 (define_insn "truncdfsf2"
2404 [(set (match_operand:SF 0 "s_register_operand" "=f")
2406 (match_operand:DF 1 "s_register_operand" "f")))]
2409 [(set_attr "type" "ffarith")])
2411 (define_insn "truncxfsf2"
2412 [(set (match_operand:SF 0 "s_register_operand" "=f")
2414 (match_operand:XF 1 "s_register_operand" "f")))]
2415 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2417 [(set_attr "type" "ffarith")])
2419 (define_insn "truncxfdf2"
2420 [(set (match_operand:DF 0 "s_register_operand" "=f")
2422 (match_operand:XF 1 "s_register_operand" "f")))]
2423 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2425 [(set_attr "type" "ffarith")])
2427 ;; Zero and sign extension instructions.
2429 (define_insn "zero_extendsidi2"
2430 [(set (match_operand:DI 0 "s_register_operand" "=r")
2431 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2434 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2435 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2436 return \"mov%?\\t%R0, #0\";
2438 [(set_attr "length" "8")])
2440 (define_insn "zero_extendqidi2"
2441 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2442 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2445 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2446 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2447 [(set_attr "length" "8")
2448 (set_attr "type" "*,load")
2449 (set_attr "pool_range" "*,4096")])
2451 (define_insn "extendsidi2"
2452 [(set (match_operand:DI 0 "s_register_operand" "=r")
2453 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2456 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2457 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2458 return \"mov%?\\t%R0, %Q0, asr #31\";
2460 [(set_attr "length" "8")])
2462 (define_expand "zero_extendhisi2"
2463 [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2465 (set (match_operand:SI 0 "s_register_operand" "")
2466 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2470 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2472 /* Note: We do not have to worry about TARGET_MMU_TRAPS
2473 here because the insn below will generate an LDRH instruction
2474 rather than an LDR instruction, so we cannot get an unaligned
2476 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2477 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
2480 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2482 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2485 if (! s_register_operand (operands[1], HImode))
2486 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2487 operands[1] = gen_lowpart (SImode, operands[1]);
2488 operands[2] = gen_reg_rtx (SImode);
2491 (define_insn "*zero_extendhisi_insn"
2492 [(set (match_operand:SI 0 "s_register_operand" "=r")
2493 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2496 [(set_attr "type" "load")
2497 (set_attr "pool_range" "256")])
2500 [(set (match_operand:SI 0 "s_register_operand" "")
2501 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2502 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2504 [(set (match_dup 2) (match_dup 1))
2505 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2508 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2513 [(set (match_operand:SI 0 "s_register_operand" "")
2514 (match_operator:SI 3 "shiftable_operator"
2515 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2516 (match_operand:SI 4 "s_register_operand" "")]))
2517 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2519 [(set (match_dup 2) (match_dup 1))
2522 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2525 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2529 (define_expand "zero_extendqisi2"
2530 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2532 (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2535 if (GET_CODE (operands[1]) != MEM)
2537 emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
2543 (define_insn "*load_extendqisi"
2544 [(set (match_operand:SI 0 "s_register_operand" "=r")
2545 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2547 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
2548 [(set_attr "type" "load")
2549 (set_attr "pool_range" "4096")])
2552 [(set (match_operand:SI 0 "s_register_operand" "")
2553 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
2554 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2555 "GET_CODE (operands[1]) != MEM"
2556 [(set (match_dup 2) (match_dup 1))
2557 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
2560 (define_insn "*compareqi_eq0"
2562 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
2566 [(set_attr "conds" "set")])
2568 (define_expand "extendhisi2"
2570 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2572 (set (match_operand:SI 0 "s_register_operand" "")
2573 (ashiftrt:SI (match_dup 2)
2578 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2580 /* Note: We do not have to worry about TARGET_MMU_TRAPS
2581 here because the insn below will generate an LDRH instruction
2582 rather than an LDR instruction, so we cannot get an unaligned
2584 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2585 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2589 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2591 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
2594 if (! s_register_operand (operands[1], HImode))
2595 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2596 operands[1] = gen_lowpart (SImode, operands[1]);
2597 operands[2] = gen_reg_rtx (SImode);
2600 (define_expand "extendhisi2_mem"
2601 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
2603 (zero_extend:SI (match_dup 7)))
2604 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
2605 (set (match_operand:SI 0 "" "")
2606 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
2611 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2613 mem1 = gen_rtx_MEM (QImode, addr);
2614 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
2615 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
2616 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
2617 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
2618 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
2619 operands[0] = gen_lowpart (SImode, operands[0]);
2621 operands[2] = gen_reg_rtx (SImode);
2622 operands[3] = gen_reg_rtx (SImode);
2623 operands[6] = gen_reg_rtx (SImode);
2626 if (BYTES_BIG_ENDIAN)
2628 operands[4] = operands[2];
2629 operands[5] = operands[3];
2633 operands[4] = operands[3];
2634 operands[5] = operands[2];
2639 (define_insn "*extendhisi_insn"
2640 [(set (match_operand:SI 0 "s_register_operand" "=r")
2641 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2644 [(set_attr "type" "load")
2645 (set_attr "pool_range" "256")])
2648 [(set (match_operand:SI 0 "s_register_operand" "")
2649 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2650 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2652 [(set (match_dup 2) (match_dup 1))
2653 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
2656 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2661 [(set (match_operand:SI 0 "s_register_operand" "")
2662 (match_operator:SI 3 "shiftable_operator"
2663 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2664 (match_operand:SI 4 "s_register_operand" "")]))
2665 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2667 [(set (match_dup 2) (match_dup 1))
2670 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2673 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2677 (define_expand "extendqihi2"
2679 (ashift:SI (match_operand:QI 1 "general_operand" "")
2681 (set (match_operand:HI 0 "s_register_operand" "")
2682 (ashiftrt:SI (match_dup 2)
2687 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2689 emit_insn (gen_rtx_SET (VOIDmode,
2691 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
2694 if (! s_register_operand (operands[1], QImode))
2695 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2696 operands[0] = gen_lowpart (SImode, operands[0]);
2697 operands[1] = gen_lowpart (SImode, operands[1]);
2698 operands[2] = gen_reg_rtx (SImode);
2701 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2702 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2703 (define_insn "*extendqihi_insn"
2704 [(set (match_operand:HI 0 "s_register_operand" "=r")
2705 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
2708 /* If the address is invalid, this will split the instruction into two. */
2709 if (bad_signed_byte_operand (operands[1], QImode))
2711 return \"ldr%?sb\\t%0, %1\";
2713 [(set_attr "type" "load")
2714 (set_attr "length" "8")
2715 (set_attr "pool_range" "256")])
2718 [(set (match_operand:HI 0 "s_register_operand" "")
2719 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2720 "arm_arch4 && reload_completed"
2721 [(set (match_dup 3) (match_dup 1))
2722 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
2725 HOST_WIDE_INT offset;
2727 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
2728 operands[2] = gen_rtx_MEM (QImode, operands[3]);
2729 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2730 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2731 operands[1] = XEXP (operands[1], 0);
2732 if (GET_CODE (operands[1]) == PLUS
2733 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2734 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2735 || const_ok_for_arm (-offset)))
2737 HOST_WIDE_INT low = (offset > 0
2738 ? (offset & 0xff) : -((-offset) & 0xff));
2739 XEXP (operands[2], 0) = plus_constant (operands[3], low);
2740 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2742 /* Ensure the sum is in correct canonical form */
2743 else if (GET_CODE (operands[1]) == PLUS
2744 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2745 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2746 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2747 XEXP (operands[1], 1),
2748 XEXP (operands[1], 0));
2752 (define_expand "extendqisi2"
2754 (ashift:SI (match_operand:QI 1 "general_operand" "")
2756 (set (match_operand:SI 0 "s_register_operand" "")
2757 (ashiftrt:SI (match_dup 2)
2762 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2764 emit_insn (gen_rtx_SET (VOIDmode,
2766 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2769 if (! s_register_operand (operands[1], QImode))
2770 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2771 operands[1] = gen_lowpart (SImode, operands[1]);
2772 operands[2] = gen_reg_rtx (SImode);
2775 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2776 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2777 (define_insn "*extendqisi_insn"
2778 [(set (match_operand:SI 0 "s_register_operand" "=r")
2779 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2782 /* If the address is invalid, this will split the instruction into two. */
2783 if (bad_signed_byte_operand (operands[1], QImode))
2785 return \"ldr%?sb\\t%0, %1\";
2787 [(set_attr "type" "load")
2788 (set_attr "length" "8")
2789 (set_attr "pool_range" "256")])
2792 [(set (match_operand:SI 0 "s_register_operand" "")
2793 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2794 "arm_arch4 && reload_completed"
2795 [(set (match_dup 0) (match_dup 1))
2796 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2799 HOST_WIDE_INT offset;
2801 operands[2] = gen_rtx_MEM (QImode, operands[0]);
2802 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2803 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2804 operands[1] = XEXP (operands[1], 0);
2805 if (GET_CODE (operands[1]) == PLUS
2806 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2807 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2808 || const_ok_for_arm (-offset)))
2810 HOST_WIDE_INT low = (offset > 0
2811 ? (offset & 0xff) : -((-offset) & 0xff));
2812 XEXP (operands[2], 0) = plus_constant (operands[0], low);
2813 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2815 /* Ensure the sum is in correct canonical form */
2816 else if (GET_CODE (operands[1]) == PLUS
2817 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2818 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2819 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2820 XEXP (operands[1], 1),
2821 XEXP (operands[1], 0));
2825 (define_insn "extendsfdf2"
2826 [(set (match_operand:DF 0 "s_register_operand" "=f")
2827 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2830 [(set_attr "type" "ffarith")])
2832 (define_insn "extendsfxf2"
2833 [(set (match_operand:XF 0 "s_register_operand" "=f")
2834 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2835 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2837 [(set_attr "type" "ffarith")])
2839 (define_insn "extenddfxf2"
2840 [(set (match_operand:XF 0 "s_register_operand" "=f")
2841 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2842 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2844 [(set_attr "type" "ffarith")])
2847 ;; Move insns (including loads and stores)
2849 ;; XXX Just some ideas about movti.
2850 ;; I don't think these are a good idea on the arm, there just aren't enough
2852 ;;(define_expand "loadti"
2853 ;; [(set (match_operand:TI 0 "s_register_operand" "")
2854 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
2857 ;;(define_expand "storeti"
2858 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2859 ;; (match_operand:TI 1 "s_register_operand" ""))]
2862 ;;(define_expand "movti"
2863 ;; [(set (match_operand:TI 0 "general_operand" "")
2864 ;; (match_operand:TI 1 "general_operand" ""))]
2870 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2871 ;; operands[1] = copy_to_reg (operands[1]);
2872 ;; if (GET_CODE (operands[0]) == MEM)
2873 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2874 ;; else if (GET_CODE (operands[1]) == MEM)
2875 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2879 ;; emit_insn (insn);
2883 ;; Recognise garbage generated above.
2886 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2887 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2891 ;; register mem = (which_alternative < 3);
2892 ;; register char *template;
2894 ;; operands[mem] = XEXP (operands[mem], 0);
2895 ;; switch (which_alternative)
2897 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2898 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
2899 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
2900 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
2901 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
2902 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
2904 ;; output_asm_insn (template, operands);
2909 (define_insn "movdi"
2910 [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2911 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2914 return (output_move_double (operands));
2916 [(set_attr "length" "8,8,8")
2917 (set_attr "type" "*,load,store2")
2918 (set_attr "pool_range" "0,1020,0")])
2920 (define_expand "movsi"
2921 [(set (match_operand:SI 0 "general_operand" "")
2922 (match_operand:SI 1 "general_operand" ""))]
2925 /* Everything except mem = const or mem = mem can be done easily */
2926 if (GET_CODE (operands[0]) == MEM)
2927 operands[1] = force_reg (SImode, operands[1]);
2928 if (GET_CODE (operands[1]) == CONST_INT
2929 && !(const_ok_for_arm (INTVAL (operands[1]))
2930 || const_ok_for_arm (~INTVAL (operands[1]))))
2932 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2934 (reload_in_progress || reload_completed ? 0
2935 : preserve_subexpressions_p ()));
2940 && (CONSTANT_P (operands[1])
2941 || symbol_mentioned_p (operands[1])
2942 || label_mentioned_p (operands[1])))
2943 operands[1] = legitimize_pic_address (operands[1], SImode,
2944 ((reload_in_progress
2945 || reload_completed)
2946 ? operands[0] : 0));
2949 (define_insn "*movsi_insn"
2950 [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2951 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
2952 "register_operand (operands[0], SImode)
2953 || register_operand (operands[1], SImode)"
2959 [(set_attr "type" "*,*,load,store1")
2960 (set_attr "pool_range" "*,*,4096,*")])
2963 [(set (match_operand:SI 0 "s_register_operand" "")
2964 (match_operand:SI 1 "const_int_operand" ""))]
2965 "! (const_ok_for_arm (INTVAL (operands[1]))
2966 || const_ok_for_arm (~INTVAL (operands[1])))"
2967 [(clobber (const_int 0))]
2969 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2974 (define_expand "movaddr"
2975 [(set (match_operand:SI 0 "s_register_operand" "")
2976 (match_operand:DI 1 "address_operand" ""))]
2980 (define_insn "*movaddr_insn"
2981 [(set (match_operand:SI 0 "s_register_operand" "=r")
2982 (match_operand:DI 1 "address_operand" "p"))]
2984 && (GET_CODE (operands[1]) == LABEL_REF
2985 || (GET_CODE (operands[1]) == CONST
2986 && GET_CODE (XEXP (operands[1], 0)) == PLUS
2987 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2988 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2991 ;; When generating pic, we need to load the symbol offset into a register.
2992 ;; So that the optimizer does not confuse this with a normal symbol load
2993 ;; we use an unspec. The offset will be loaded from a constant pool entry,
2994 ;; since that is the only type of relocation we can use.
2996 ;; The rather odd constraints on the following are to force reload to leave
2997 ;; the insn alone, and to force the minipool generation pass to then move
2998 ;; the GOT symbol to memory.
3000 (define_insn "pic_load_addr"
3001 [(set (match_operand:SI 0 "s_register_operand" "=r")
3002 (unspec:SI [(match_operand:SI 1 "" "mX")] 3))]
3005 [(set_attr "type" "load")
3006 (set_attr "pool_range" "4096")])
3008 ;; This variant is used for AOF assembly, since it needs to mention the
3009 ;; pic register in the rtl.
3010 (define_expand "pic_load_addr_based"
3011 [(set (match_operand:SI 0 "s_register_operand" "=r")
3012 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
3014 "operands[2] = pic_offset_table_rtx;")
3016 (define_insn "*pic_load_addr_based_insn"
3017 [(set (match_operand:SI 0 "s_register_operand" "=r")
3018 (unspec:SI [(match_operand 1 "" "")
3019 (match_operand 2 "s_register_operand" "r")] 3))]
3020 "flag_pic && operands[2] == pic_offset_table_rtx"
3022 #ifdef AOF_ASSEMBLER
3023 operands[1] = aof_pic_entry (operands[1]);
3025 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3028 [(set_attr "type" "load")
3029 (set_attr "pool_range" "4096")])
3031 (define_insn "pic_add_dot_plus_eight"
3032 [(set (match_operand:SI 0 "register_operand" "+r")
3033 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
3034 (use (label_ref (match_operand 1 "" "")))]
3037 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
3038 CODE_LABEL_NUMBER (operands[1]));
3039 return \"add%?\\t%0, %|pc, %0\";
3042 ;; If copying one reg to another we can set the condition codes according to
3043 ;; its value. Such a move is common after a return from subroutine and the
3044 ;; result is being tested against zero.
3046 (define_insn "*movsi_compare0"
3047 [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
3049 (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
3053 sub%?s\\t%0, %1, #0"
3054 [(set_attr "conds" "set")])
3056 ;; Subroutine to store a half word from a register into memory.
3057 ;; Operand 0 is the source register (HImode)
3058 ;; Operand 1 is the destination address in a register (SImode)
3060 ;; In both this routine and the next, we must be careful not to spill
3061 ;; a memory address of reg+large_const into a separate PLUS insn, since this
3062 ;; can generate unrecognizable rtl.
3064 (define_expand "storehi"
3065 [;; store the low byte
3066 (set (match_operand 1 "" "") (match_dup 3))
3067 ;; extract the high byte
3069 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3070 ;; store the high byte
3071 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
3075 rtx addr = XEXP (operands[1], 0);
3076 enum rtx_code code = GET_CODE (addr);
3078 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3080 addr = force_reg (SImode, addr);
3082 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
3083 operands[1] = change_address (operands[1], QImode, NULL_RTX);
3084 operands[3] = gen_lowpart (QImode, operands[0]);
3085 operands[0] = gen_lowpart (SImode, operands[0]);
3086 operands[2] = gen_reg_rtx (SImode);
3090 (define_expand "storehi_bigend"
3091 [(set (match_dup 4) (match_dup 3))
3093 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3094 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
3098 rtx addr = XEXP (operands[1], 0);
3099 enum rtx_code code = GET_CODE (addr);
3101 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3103 addr = force_reg (SImode, addr);
3105 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
3106 operands[1] = change_address (operands[1], QImode, NULL_RTX);
3107 operands[3] = gen_lowpart (QImode, operands[0]);
3108 operands[0] = gen_lowpart (SImode, operands[0]);
3109 operands[2] = gen_reg_rtx (SImode);
3113 ;; Subroutine to store a half word integer constant into memory.
3114 (define_expand "storeinthi"
3115 [(set (match_operand 0 "" "")
3116 (subreg:QI (match_operand 1 "" "") 0))
3117 (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
3121 HOST_WIDE_INT value = INTVAL (operands[1]);
3122 rtx addr = XEXP (operands[0], 0);
3123 enum rtx_code code = GET_CODE (addr);
3125 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3127 addr = force_reg (SImode, addr);
3129 operands[1] = gen_reg_rtx (SImode);
3130 if (BYTES_BIG_ENDIAN)
3132 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
3133 if ((value & 255) == ((value >> 8) & 255))
3134 operands[2] = operands[1];
3137 operands[2] = gen_reg_rtx (SImode);
3138 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
3143 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
3144 if ((value & 255) == ((value >> 8) & 255))
3145 operands[2] = operands[1];
3148 operands[2] = gen_reg_rtx (SImode);
3149 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
3153 operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
3154 operands[0] = change_address (operands[0], QImode, NULL_RTX);
3158 (define_expand "storehi_single_op"
3159 [(set (match_operand:HI 0 "memory_operand" "")
3160 (match_operand:HI 1 "general_operand" ""))]
3163 if (! s_register_operand (operands[1], HImode))
3164 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3167 (define_expand "movhi"
3168 [(set (match_operand:HI 0 "general_operand" "")
3169 (match_operand:HI 1 "general_operand" ""))]
3173 if (! (reload_in_progress || reload_completed))
3175 if (GET_CODE (operands[0]) == MEM)
3179 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
3182 if (GET_CODE (operands[1]) == CONST_INT)
3183 emit_insn (gen_storeinthi (operands[0], operands[1]));
3186 if (GET_CODE (operands[1]) == MEM)
3187 operands[1] = force_reg (HImode, operands[1]);
3188 if (BYTES_BIG_ENDIAN)
3189 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
3191 emit_insn (gen_storehi (operands[1], operands[0]));
3195 /* Sign extend a constant, and keep it in an SImode reg. */
3196 else if (GET_CODE (operands[1]) == CONST_INT)
3198 rtx reg = gen_reg_rtx (SImode);
3199 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
3201 /* If the constant is already valid, leave it alone. */
3202 if (! const_ok_for_arm (val))
3204 /* If setting all the top bits will make the constant
3205 loadable in a single instruction, then set them.
3206 Otherwise, sign extend the number. */
3208 if (const_ok_for_arm (~ (val | ~0xffff)))
3210 else if (val & 0x8000)
3214 emit_insn (gen_movsi (reg, GEN_INT (val)));
3215 operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
3217 else if (! arm_arch4)
3219 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3220 for v4 and up architectures because LDRH instructions will
3221 be used to access the HI values, and these cannot generate
3222 unaligned word access faults in the MMU. */
3223 if (GET_CODE (operands[1]) == MEM)
3225 if (TARGET_MMU_TRAPS)
3228 rtx offset = const0_rtx;
3229 rtx reg = gen_reg_rtx (SImode);
3231 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
3232 || (GET_CODE (base) == PLUS
3233 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
3234 && ((INTVAL(offset) & 1) != 1)
3235 && GET_CODE (base = XEXP (base, 0)) == REG))
3236 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
3238 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
3241 new = gen_rtx_MEM (SImode,
3242 plus_constant (base, new_offset));
3243 MEM_COPY_ATTRIBUTES (new, operands[1]);
3244 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
3245 emit_insn (gen_movsi (reg, new));
3246 if (((INTVAL (offset) & 2) != 0)
3247 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
3249 rtx reg2 = gen_reg_rtx (SImode);
3251 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
3256 emit_insn (gen_movhi_bytes (reg, operands[1]));
3258 operands[1] = gen_lowpart (HImode, reg);
3260 else if (BYTES_BIG_ENDIAN)
3263 rtx offset = const0_rtx;
3265 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
3266 || (GET_CODE (base) == PLUS
3267 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
3268 && GET_CODE (base = XEXP (base, 0)) == REG))
3269 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
3271 rtx reg = gen_reg_rtx (SImode);
3274 if ((INTVAL (offset) & 2) == 2)
3276 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
3277 new = gen_rtx_MEM (SImode,
3278 plus_constant (base, new_offset));
3279 MEM_COPY_ATTRIBUTES (new, operands[1]);
3280 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
3281 emit_insn (gen_movsi (reg, new));
3285 new = gen_rtx_MEM (SImode, XEXP (operands[1], 0));
3286 MEM_COPY_ATTRIBUTES (new, operands[1]);
3287 RTX_UNCHANGING_P (new)
3288 = RTX_UNCHANGING_P (operands[1]);
3289 emit_insn (gen_rotated_loadsi (reg, new));
3292 operands[1] = gen_lowpart (HImode, reg);
3296 emit_insn (gen_movhi_bigend (operands[0], operands[1]));
3303 /* Handle loading a large integer during reload */
3304 else if (GET_CODE (operands[1]) == CONST_INT
3305 && ! const_ok_for_arm (INTVAL (operands[1]))
3306 && ! const_ok_for_arm (~INTVAL (operands[1])))
3308 /* Writing a constant to memory needs a scratch, which should
3309 be handled with SECONDARY_RELOADs. */
3310 if (GET_CODE (operands[0]) != REG)
3313 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
3314 emit_insn (gen_movsi (operands[0], operands[1]));
3320 (define_insn "rotated_loadsi"
3321 [(set (match_operand:SI 0 "s_register_operand" "=r")
3322 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
3324 "! TARGET_MMU_TRAPS"
3329 ops[0] = operands[0];
3330 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
3331 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
3334 [(set_attr "type" "load")])
3336 (define_expand "movhi_bytes"
3337 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3339 (zero_extend:SI (match_dup 6)))
3340 (set (match_operand:SI 0 "" "")
3341 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
3346 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3348 mem1 = gen_rtx_MEM (QImode, addr);
3349 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3350 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
3351 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3352 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3353 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
3354 operands[0] = gen_lowpart (SImode, operands[0]);
3356 operands[2] = gen_reg_rtx (SImode);
3357 operands[3] = gen_reg_rtx (SImode);
3360 if (BYTES_BIG_ENDIAN)
3362 operands[4] = operands[2];
3363 operands[5] = operands[3];
3367 operands[4] = operands[3];
3368 operands[5] = operands[2];
3373 (define_expand "movhi_bigend"
3375 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
3378 (ashiftrt:SI (match_dup 2) (const_int 16)))
3379 (set (match_operand:HI 0 "s_register_operand" "")
3380 (subreg:HI (match_dup 3) 0))]
3383 operands[2] = gen_reg_rtx (SImode);
3384 operands[3] = gen_reg_rtx (SImode);
3387 ;; Pattern to recognise insn generated default case above
3388 (define_insn "*movhi_insn_arch4"
3389 [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
3390 (match_operand:HI 1 "general_operand" "rI,K,m,r"))]
3392 && (GET_CODE (operands[1]) != CONST_INT
3393 || const_ok_for_arm (INTVAL (operands[1]))
3394 || const_ok_for_arm (~INTVAL (operands[1])))"
3396 mov%?\\t%0, %1\\t%@ movhi
3397 mvn%?\\t%0, #%B1\\t%@ movhi
3398 ldr%?h\\t%0, %1\\t%@ movhi
3399 str%?h\\t%1, %0\\t%@ movhi"
3400 [(set_attr "type" "*,*,load,store1")
3401 (set_attr "pool_range" "*,*,256,*")])
3403 (define_insn "*movhi_insn_littleend"
3404 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3405 (match_operand:HI 1 "general_operand" "rI,K,m"))]
3407 && ! BYTES_BIG_ENDIAN
3408 && ! TARGET_MMU_TRAPS
3409 && (GET_CODE (operands[1]) != CONST_INT
3410 || const_ok_for_arm (INTVAL (operands[1]))
3411 || const_ok_for_arm (~INTVAL (operands[1])))"
3413 mov%?\\t%0, %1\\t%@ movhi
3414 mvn%?\\t%0, #%B1\\t%@ movhi
3415 ldr%?\\t%0, %1\\t%@ movhi"
3416 [(set_attr "type" "*,*,load")
3417 (set_attr "pool_range" "4096")])
3419 (define_insn "*movhi_insn_bigend"
3420 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3421 (match_operand:HI 1 "general_operand" "rI,K,m"))]
3424 && ! TARGET_MMU_TRAPS
3425 && (GET_CODE (operands[1]) != CONST_INT
3426 || const_ok_for_arm (INTVAL (operands[1]))
3427 || const_ok_for_arm (~INTVAL (operands[1])))"
3429 mov%?\\t%0, %1\\t%@ movhi
3430 mvn%?\\t%0, #%B1\\t%@ movhi
3431 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
3432 [(set_attr "type" "*,*,load")
3433 (set_attr "length" "4,4,8")
3434 (set_attr "pool_range" "*,*,4092")])
3436 (define_insn "*loadhi_si_bigend"
3437 [(set (match_operand:SI 0 "s_register_operand" "=r")
3438 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
3441 && ! TARGET_MMU_TRAPS"
3442 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
3443 [(set_attr "type" "load")
3444 (set_attr "pool_range" "4096")])
3446 (define_insn "*movhi_bytes"
3447 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
3448 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
3451 mov%?\\t%0, %1\\t%@ movhi
3452 mvn%?\\t%0, #%B1\\t%@ movhi")
3454 ;; We use a DImode scratch because we may occasionally need an additional
3455 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
3456 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
3457 (define_expand "reload_outhi"
3458 [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
3459 (match_operand:HI 1 "s_register_operand" "r")
3460 (match_operand:DI 2 "s_register_operand" "=&r")])]
3463 arm_reload_out_hi (operands);
3467 (define_expand "reload_inhi"
3468 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
3469 (match_operand:HI 1 "reload_memory_operand" "o")
3470 (match_operand:DI 2 "s_register_operand" "=&r")])]
3473 arm_reload_in_hi (operands);
3477 (define_expand "movqi"
3478 [(set (match_operand:QI 0 "general_operand" "")
3479 (match_operand:QI 1 "general_operand" ""))]
3482 /* Everything except mem = const or mem = mem can be done easily */
3484 if (!(reload_in_progress || reload_completed))
3486 if (GET_CODE (operands[1]) == CONST_INT)
3488 rtx reg = gen_reg_rtx (SImode);
3490 emit_insn (gen_movsi (reg, operands[1]));
3491 operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
3493 if (GET_CODE (operands[0]) == MEM)
3494 operands[1] = force_reg (QImode, operands[1]);
3499 (define_insn "*movqi_insn"
3500 [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
3501 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
3502 "register_operand (operands[0], QImode)
3503 || register_operand (operands[1], QImode)"
3509 [(set_attr "type" "*,*,load,store1")])
3511 (define_expand "movsf"
3512 [(set (match_operand:SF 0 "general_operand" "")
3513 (match_operand:SF 1 "general_operand" ""))]
3516 if (GET_CODE (operands[0]) == MEM)
3517 operands[1] = force_reg (SFmode, operands[1]);
3520 (define_insn "*movsf_hard_insn"
3521 [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
3522 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
3524 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3530 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
3531 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
3533 ldr%?\\t%0, %1\\t%@ float
3534 str%?\\t%1, %0\\t%@ float"
3535 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
3537 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
3538 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")])
3540 ;; Exactly the same as above, except that all `f' cases are deleted.
3541 ;; This is necessary to prevent reload from ever trying to use a `f' reg
3542 ;; when -msoft-float.
3544 (define_insn "*movsf_soft_insn"
3545 [(set (match_operand:SF 0 "general_operand" "=r,r,m")
3546 (match_operand:SF 1 "general_operand" "r,mE,r"))]
3548 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3551 ldr%?\\t%0, %1\\t%@ float
3552 str%?\\t%1, %0\\t%@ float"
3553 [(set_attr "length" "4,4,4")
3554 (set_attr "type" "*,load,store1")
3555 (set_attr "pool_range" "*,4096,*")])
3557 (define_expand "movdf"
3558 [(set (match_operand:DF 0 "general_operand" "")
3559 (match_operand:DF 1 "general_operand" ""))]
3562 if (GET_CODE (operands[0]) == MEM)
3563 operands[1] = force_reg (DFmode, operands[1]);
3566 ;; Reloading a df mode value stored in integer regs to memory can require a
3568 (define_expand "reload_outdf"
3569 [(match_operand:DF 0 "reload_memory_operand" "=o")
3570 (match_operand:DF 1 "s_register_operand" "r")
3571 (match_operand:SI 2 "s_register_operand" "=&r")]
3575 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
3578 operands[2] = XEXP (operands[0], 0);
3579 else if (code == POST_INC || code == PRE_DEC)
3581 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
3582 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
3583 emit_insn (gen_movdi (operands[0], operands[1]));
3586 else if (code == PRE_INC)
3588 rtx reg = XEXP (XEXP (operands[0], 0), 0);
3589 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
3592 else if (code == POST_DEC)
3593 operands[2] = XEXP (XEXP (operands[0], 0), 0);
3595 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
3596 XEXP (XEXP (operands[0], 0), 1)));
3598 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
3601 if (code == POST_DEC)
3602 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
3608 (define_insn "*movdf_hard_insn"
3609 [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
3610 (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
3612 && (GET_CODE (operands[0]) != MEM
3613 || register_operand (operands[1], DFmode))"
3616 switch (which_alternative)
3619 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
3620 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
3621 case 2: case 3: case 4: return output_move_double (operands);
3622 case 5: return \"mvf%?d\\t%0, %1\";
3623 case 6: return \"mnf%?d\\t%0, #%N1\";
3624 case 7: return \"ldf%?d\\t%0, %1\";
3625 case 8: return \"stf%?d\\t%1, %0\";
3626 case 9: return output_mov_double_fpu_from_arm (operands);
3627 case 10: return output_mov_double_arm_from_fpu (operands);
3631 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
3633 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
3634 (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")])
3636 ;; Software floating point version. This is essentially the same as movdi.
3637 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
3640 (define_insn "*movdf_soft_insn"
3641 [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
3642 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
3644 "* return output_move_double (operands);"
3645 [(set_attr "length" "8,8,8")
3646 (set_attr "type" "*,load,store2")
3647 (set_attr "pool_range" "252")])
3649 (define_expand "movxf"
3650 [(set (match_operand:XF 0 "general_operand" "")
3651 (match_operand:XF 1 "general_operand" ""))]
3652 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3655 ;; Even when the XFmode patterns aren't enabled, we enable this after
3656 ;; reloading so that we can push floating point registers in the prologue.
3658 (define_insn "*movxf_hard_insn"
3659 [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
3660 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
3661 "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
3663 switch (which_alternative)
3666 case 0: return \"mvf%?e\\t%0, %1\";
3667 case 1: return \"mnf%?e\\t%0, #%N1\";
3668 case 2: return \"ldf%?e\\t%0, %1\";
3669 case 3: return \"stf%?e\\t%1, %0\";
3670 case 4: return output_mov_long_double_fpu_from_arm (operands);
3671 case 5: return output_mov_long_double_arm_from_fpu (operands);
3672 case 6: return output_mov_long_double_arm_from_arm (operands);
3675 [(set_attr "length" "4,4,4,4,8,8,12")
3676 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
3677 (set_attr "pool_range" "*,*,1024,*,*,*,*")])
3680 ;; load- and store-multiple insns
3681 ;; The arm can load/store any set of registers, provided that they are in
3682 ;; ascending order; but that is beyond GCC so stick with what it knows.
3684 (define_expand "load_multiple"
3685 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3686 (match_operand:SI 1 "" ""))
3687 (use (match_operand:SI 2 "" ""))])]
3690 /* Support only fixed point registers */
3691 if (GET_CODE (operands[2]) != CONST_INT
3692 || INTVAL (operands[2]) > 14
3693 || INTVAL (operands[2]) < 2
3694 || GET_CODE (operands[1]) != MEM
3695 || GET_CODE (operands[0]) != REG
3696 || REGNO (operands[0]) > 14
3697 || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
3701 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
3702 force_reg (SImode, XEXP (operands[1], 0)),
3703 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
3704 MEM_IN_STRUCT_P(operands[1]),
3705 MEM_SCALAR_P (operands[1]));
3708 ;; Load multiple with write-back
3710 (define_insn "*ldmsi_postinc"
3711 [(match_parallel 0 "load_multiple_operation"
3712 [(set (match_operand:SI 1 "s_register_operand" "+r")
3713 (plus:SI (match_dup 1)
3714 (match_operand:SI 2 "const_int_operand" "n")))
3715 (set (match_operand:SI 3 "s_register_operand" "=r")
3716 (mem:SI (match_dup 1)))])]
3717 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3721 int count = XVECLEN (operands[0], 0);
3723 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3724 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
3725 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
3727 output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
3731 [(set_attr "type" "load")])
3733 ;; Ordinary load multiple
3735 (define_insn "*ldmsi"
3736 [(match_parallel 0 "load_multiple_operation"
3737 [(set (match_operand:SI 1 "s_register_operand" "=r")
3738 (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
3743 int count = XVECLEN (operands[0], 0);
3745 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3746 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
3747 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
3749 output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
3753 [(set_attr "type" "load")])
3755 (define_expand "store_multiple"
3756 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3757 (match_operand:SI 1 "" ""))
3758 (use (match_operand:SI 2 "" ""))])]
3761 /* Support only fixed point registers */
3762 if (GET_CODE (operands[2]) != CONST_INT
3763 || INTVAL (operands[2]) > 14
3764 || INTVAL (operands[2]) < 2
3765 || GET_CODE (operands[1]) != REG
3766 || GET_CODE (operands[0]) != MEM
3767 || REGNO (operands[1]) > 14
3768 || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
3772 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
3773 force_reg (SImode, XEXP (operands[0], 0)),
3774 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
3775 MEM_IN_STRUCT_P(operands[0]),
3776 MEM_SCALAR_P (operands[0]));
3779 ;; Store multiple with write-back
3781 (define_insn "*stmsi_postinc"
3782 [(match_parallel 0 "store_multiple_operation"
3783 [(set (match_operand:SI 1 "s_register_operand" "+r")
3784 (plus:SI (match_dup 1)
3785 (match_operand:SI 2 "const_int_operand" "n")))
3786 (set (mem:SI (match_dup 1))
3787 (match_operand:SI 3 "s_register_operand" "r"))])]
3788 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3792 int count = XVECLEN (operands[0], 0);
3794 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3795 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
3796 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
3798 output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
3803 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3804 (const_string "store2")
3805 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
3806 (const_string "store3")]
3807 (const_string "store4")))])
3809 ;; Ordinary store multiple
3811 (define_insn "*stmsi"
3812 [(match_parallel 0 "store_multiple_operation"
3813 [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
3814 (match_operand:SI 1 "s_register_operand" "r"))])]
3819 int count = XVECLEN (operands[0], 0);
3821 ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
3822 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
3823 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
3825 output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
3830 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
3831 (const_string "store2")
3832 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3833 (const_string "store3")]
3834 (const_string "store4")))])
3836 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
3837 ;; We could let this apply for blocks of less than this, but it clobbers so
3838 ;; many registers that there is then probably a better way.
3840 (define_expand "movstrqi"
3841 [(match_operand:BLK 0 "general_operand" "")
3842 (match_operand:BLK 1 "general_operand" "")
3843 (match_operand:SI 2 "const_int_operand" "")
3844 (match_operand:SI 3 "const_int_operand" "")]
3847 if (arm_gen_movstrqi (operands))
3853 ;; Comparison and test insns
3855 (define_expand "cmpsi"
3856 [(match_operand:SI 0 "s_register_operand" "")
3857 (match_operand:SI 1 "arm_add_operand" "")]
3861 arm_compare_op0 = operands[0];
3862 arm_compare_op1 = operands[1];
3867 (define_expand "cmpsf"
3868 [(match_operand:SF 0 "s_register_operand" "")
3869 (match_operand:SF 1 "fpu_rhs_operand" "")]
3873 arm_compare_op0 = operands[0];
3874 arm_compare_op1 = operands[1];
3879 (define_expand "cmpdf"
3880 [(match_operand:DF 0 "s_register_operand" "")
3881 (match_operand:DF 1 "fpu_rhs_operand" "")]
3885 arm_compare_op0 = operands[0];
3886 arm_compare_op1 = operands[1];
3891 (define_expand "cmpxf"
3892 [(match_operand:XF 0 "s_register_operand" "")
3893 (match_operand:XF 1 "fpu_rhs_operand" "")]
3894 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3897 arm_compare_op0 = operands[0];
3898 arm_compare_op1 = operands[1];
3903 (define_insn "*cmpsi_insn"
3905 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3906 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3911 [(set_attr "conds" "set")])
3913 (define_insn "*cmpsi_shiftsi"
3915 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3916 (match_operator:SI 3 "shift_operator"
3917 [(match_operand:SI 1 "s_register_operand" "r")
3918 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3921 [(set_attr "conds" "set")
3924 (define_insn "*cmpsi_shiftsi_swp"
3925 [(set (reg:CC_SWP 24)
3926 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
3927 [(match_operand:SI 1 "s_register_operand" "r")
3928 (match_operand:SI 2 "reg_or_int_operand" "rM")])
3929 (match_operand:SI 0 "s_register_operand" "r")))]
3932 [(set_attr "conds" "set")
3935 (define_insn "*cmpsi_neg_shiftsi"
3937 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3938 (neg:SI (match_operator:SI 3 "shift_operator"
3939 [(match_operand:SI 1 "s_register_operand" "r")
3940 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3943 [(set_attr "conds" "set")
3946 (define_insn "*cmpsf_insn"
3948 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3949 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3954 [(set_attr "conds" "set")
3955 (set_attr "type" "f_2_r")])
3957 (define_insn "*cmpdf_insn"
3959 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3960 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3965 [(set_attr "conds" "set")
3966 (set_attr "type" "f_2_r")])
3968 (define_insn "*cmpesfdf_df"
3970 (compare:CCFP (float_extend:DF
3971 (match_operand:SF 0 "s_register_operand" "f,f"))
3972 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3977 [(set_attr "conds" "set")
3978 (set_attr "type" "f_2_r")])
3980 (define_insn "*cmpdf_esfdf"
3982 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3984 (match_operand:SF 1 "s_register_operand" "f"))))]
3987 [(set_attr "conds" "set")
3988 (set_attr "type" "f_2_r")])
3990 (define_insn "*cmpxf_insn"
3992 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3993 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3994 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3998 [(set_attr "conds" "set")
3999 (set_attr "type" "f_2_r")])
4001 (define_insn "*cmpsf_trap"
4002 [(set (reg:CCFPE 24)
4003 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
4004 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
4009 [(set_attr "conds" "set")
4010 (set_attr "type" "f_2_r")])
4012 (define_insn "*cmpdf_trap"
4013 [(set (reg:CCFPE 24)
4014 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
4015 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
4020 [(set_attr "conds" "set")
4021 (set_attr "type" "f_2_r")])
4023 (define_insn "*cmp_esfdf_df_trap"
4024 [(set (reg:CCFPE 24)
4025 (compare:CCFPE (float_extend:DF
4026 (match_operand:SF 0 "s_register_operand" "f,f"))
4027 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
4032 [(set_attr "conds" "set")
4033 (set_attr "type" "f_2_r")])
4035 (define_insn "*cmp_df_esfdf_trap"
4036 [(set (reg:CCFPE 24)
4037 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
4039 (match_operand:SF 1 "s_register_operand" "f"))))]
4042 [(set_attr "conds" "set")
4043 (set_attr "type" "f_2_r")])
4045 (define_insn "*cmpxf_trap"
4046 [(set (reg:CCFPE 24)
4047 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
4048 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
4049 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
4053 [(set_attr "conds" "set")
4054 (set_attr "type" "f_2_r")])
4056 ; This insn allows redundant compares to be removed by cse, nothing should
4057 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
4058 ; is deleted later on. The match_dup will match the mode here, so that
4059 ; mode changes of the condition codes aren't lost by this even though we don't
4060 ; specify what they are.
4062 (define_insn "*deleted_compare"
4063 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
4065 "\\t%@ deleted compare"
4066 [(set_attr "conds" "set")
4067 (set_attr "length" "0")])
4070 ;; Conditional branch insns
4072 (define_expand "beq"
4074 (if_then_else (eq (match_dup 1) (const_int 0))
4075 (label_ref (match_operand 0 "" ""))
4080 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);
4084 (define_expand "bne"
4086 (if_then_else (ne (match_dup 1) (const_int 0))
4087 (label_ref (match_operand 0 "" ""))
4092 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);
4096 (define_expand "bgt"
4098 (if_then_else (gt (match_dup 1) (const_int 0))
4099 (label_ref (match_operand 0 "" ""))
4104 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);
4108 (define_expand "ble"
4110 (if_then_else (le (match_dup 1) (const_int 0))
4111 (label_ref (match_operand 0 "" ""))
4116 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);
4120 (define_expand "bge"
4122 (if_then_else (ge (match_dup 1) (const_int 0))
4123 (label_ref (match_operand 0 "" ""))
4128 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);
4132 (define_expand "blt"
4134 (if_then_else (lt (match_dup 1) (const_int 0))
4135 (label_ref (match_operand 0 "" ""))
4140 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);
4144 (define_expand "bgtu"
4146 (if_then_else (gtu (match_dup 1) (const_int 0))
4147 (label_ref (match_operand 0 "" ""))
4152 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);
4156 (define_expand "bleu"
4158 (if_then_else (leu (match_dup 1) (const_int 0))
4159 (label_ref (match_operand 0 "" ""))
4164 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);
4168 (define_expand "bgeu"
4170 (if_then_else (geu (match_dup 1) (const_int 0))
4171 (label_ref (match_operand 0 "" ""))
4176 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);
4180 (define_expand "bltu"
4182 (if_then_else (ltu (match_dup 1) (const_int 0))
4183 (label_ref (match_operand 0 "" ""))
4188 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);
4192 ;; patterns to match conditional branch insns
4194 (define_insn "*condbranch"
4196 (if_then_else (match_operator 1 "comparison_operator"
4197 [(match_operand 2 "cc_register" "") (const_int 0)])
4198 (label_ref (match_operand 0 "" ""))
4203 extern int arm_ccfsm_state;
4205 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4207 arm_ccfsm_state += 2;
4210 return \"b%d1\\t%l0\";
4212 [(set_attr "conds" "use")])
4214 (define_insn "*condbranch_reversed"
4216 (if_then_else (match_operator 1 "comparison_operator"
4217 [(match_operand 2 "cc_register" "") (const_int 0)])
4219 (label_ref (match_operand 0 "" ""))))]
4223 extern int arm_ccfsm_state;
4225 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4227 arm_ccfsm_state += 2;
4230 return \"b%D1\\t%l0\";
4232 [(set_attr "conds" "use")])
4237 (define_expand "seq"
4238 [(set (match_operand:SI 0 "s_register_operand" "=r")
4239 (eq:SI (match_dup 1) (const_int 0)))]
4243 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);
4247 (define_expand "sne"
4248 [(set (match_operand:SI 0 "s_register_operand" "=r")
4249 (ne:SI (match_dup 1) (const_int 0)))]
4253 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);
4257 (define_expand "sgt"
4258 [(set (match_operand:SI 0 "s_register_operand" "=r")
4259 (gt:SI (match_dup 1) (const_int 0)))]
4263 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);
4267 (define_expand "sle"
4268 [(set (match_operand:SI 0 "s_register_operand" "=r")
4269 (le:SI (match_dup 1) (const_int 0)))]
4273 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);
4277 (define_expand "sge"
4278 [(set (match_operand:SI 0 "s_register_operand" "=r")
4279 (ge:SI (match_dup 1) (const_int 0)))]
4283 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);
4287 (define_expand "slt"
4288 [(set (match_operand:SI 0 "s_register_operand" "=r")
4289 (lt:SI (match_dup 1) (const_int 0)))]
4293 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);
4297 (define_expand "sgtu"
4298 [(set (match_operand:SI 0 "s_register_operand" "=r")
4299 (gtu:SI (match_dup 1) (const_int 0)))]
4303 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);
4307 (define_expand "sleu"
4308 [(set (match_operand:SI 0 "s_register_operand" "=r")
4309 (leu:SI (match_dup 1) (const_int 0)))]
4313 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);
4317 (define_expand "sgeu"
4318 [(set (match_operand:SI 0 "s_register_operand" "=r")
4319 (geu:SI (match_dup 1) (const_int 0)))]
4323 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);
4327 (define_expand "sltu"
4328 [(set (match_operand:SI 0 "s_register_operand" "=r")
4329 (ltu:SI (match_dup 1) (const_int 0)))]
4333 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);
4337 (define_insn "*mov_scc"
4338 [(set (match_operand:SI 0 "s_register_operand" "=r")
4339 (match_operator:SI 1 "comparison_operator"
4340 [(match_operand 2 "cc_register" "") (const_int 0)]))]
4342 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
4343 [(set_attr "conds" "use")
4344 (set_attr "length" "8")])
4346 (define_insn "*mov_negscc"
4347 [(set (match_operand:SI 0 "s_register_operand" "=r")
4348 (neg:SI (match_operator:SI 1 "comparison_operator"
4349 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4351 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
4352 [(set_attr "conds" "use")
4353 (set_attr "length" "8")])
4355 (define_insn "*mov_notscc"
4356 [(set (match_operand:SI 0 "s_register_operand" "=r")
4357 (not:SI (match_operator:SI 1 "comparison_operator"
4358 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4360 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
4361 [(set_attr "conds" "use")
4362 (set_attr "length" "8")])
4365 ;; Conditional move insns
4367 (define_expand "movsicc"
4368 [(set (match_operand:SI 0 "s_register_operand" "")
4369 (if_then_else:SI (match_operand 1 "comparison_operator" "")
4370 (match_operand:SI 2 "arm_not_operand" "")
4371 (match_operand:SI 3 "arm_not_operand" "")))]
4375 enum rtx_code code = GET_CODE (operands[1]);
4376 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
4378 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4381 (define_expand "movsfcc"
4382 [(set (match_operand:SF 0 "s_register_operand" "")
4383 (if_then_else:SF (match_operand 1 "comparison_operator" "")
4384 (match_operand:SF 2 "s_register_operand" "")
4385 (match_operand:SF 3 "nonmemory_operand" "")))]
4389 enum rtx_code code = GET_CODE (operands[1]);
4392 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
4393 Otherwise, ensure it is a valid FP add operand */
4394 if ((! TARGET_HARD_FLOAT)
4395 || (! fpu_add_operand (operands[3], SFmode)))
4396 operands[3] = force_reg (SFmode, operands[3]);
4398 ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
4400 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4403 (define_expand "movdfcc"
4404 [(set (match_operand:DF 0 "s_register_operand" "")
4405 (if_then_else:DF (match_operand 1 "comparison_operator" "")
4406 (match_operand:DF 2 "s_register_operand" "")
4407 (match_operand:DF 3 "fpu_add_operand" "")))]
4411 enum rtx_code code = GET_CODE (operands[1]);
4412 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
4414 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4417 (define_insn "*movsicc_insn"
4418 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
4420 (match_operator 3 "comparison_operator"
4421 [(match_operand 4 "cc_register" "") (const_int 0)])
4422 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
4423 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
4430 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
4431 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
4432 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
4433 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
4434 [(set_attr "length" "4,4,4,4,8,8,8,8")
4435 (set_attr "conds" "use")])
4437 (define_insn "*movsfcc_hard_insn"
4438 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4440 (match_operator 3 "comparison_operator"
4441 [(match_operand 4 "cc_register" "") (const_int 0)])
4442 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4443 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4450 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
4451 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
4452 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
4453 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
4454 [(set_attr "length" "4,4,4,4,8,8,8,8")
4455 (set_attr "type" "ffarith")
4456 (set_attr "conds" "use")])
4458 (define_insn "*movsfcc_soft_insn"
4459 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
4460 (if_then_else:SF (match_operator 3 "comparison_operator"
4461 [(match_operand 4 "cc_register" "") (const_int 0)])
4462 (match_operand:SF 1 "s_register_operand" "0,r")
4463 (match_operand:SF 2 "s_register_operand" "r,0")))]
4468 [(set_attr "conds" "use")])
4470 (define_insn "*movdfcc_insn"
4471 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4473 (match_operator 3 "comparison_operator"
4474 [(match_operand 4 "cc_register" "") (const_int 0)])
4475 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4476 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4483 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
4484 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
4485 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
4486 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
4487 [(set_attr "length" "4,4,4,4,8,8,8,8")
4488 (set_attr "type" "ffarith")
4489 (set_attr "conds" "use")])
4491 ;; Jump and linkage insns
4495 (label_ref (match_operand 0 "" "")))]
4499 extern int arm_ccfsm_state;
4501 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4503 arm_ccfsm_state += 2;
4506 return \"b%?\\t%l0\";
4509 (define_expand "call"
4510 [(parallel [(call (match_operand 0 "memory_operand" "")
4511 (match_operand 1 "general_operand" ""))
4512 (use (match_operand 2 "" ""))
4513 (clobber (reg:SI 14))])]
4519 /* In an untyped call, we can get NULL for operand 2. */
4520 if (operands[2] == NULL_RTX)
4521 operands[2] = const0_rtx;
4523 /* This is to decide if we should generate indirect calls by loading the
4524 32 bit address of the callee into a register before performing the
4525 branch and link. operand[2] encodes the long_call/short_call
4526 attribute of the function being called. This attribute is set whenever
4527 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
4528 is used, and the short_call attribute can also be set if function is
4529 declared as static or if it has already been defined in the current
4530 compilation unit. See arm.c and arm.h for info about this. The third
4531 parameter to arm_is_longcall_p is used to tell it which pattern
4533 callee = XEXP (operands[0], 0);
4535 if (GET_CODE (callee) != REG
4536 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
4537 XEXP (operands[0], 0) = force_reg (Pmode, callee);
4541 (define_insn "*call_reg"
4542 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
4543 (match_operand 1 "" "g"))
4544 (use (match_operand:SI 2 "immediate_operand" "n"))
4545 (clobber (reg:SI 14))]
4548 return output_call (operands);
4550 ;; length is worst case, normally it is only two
4551 [(set_attr "length" "12")
4552 (set_attr "type" "call")])
4554 (define_insn "*call_mem"
4555 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
4556 (match_operand 1 "general_operand" "g"))
4557 (use (match_operand:SI 2 "" ""))
4558 (clobber (reg:SI 14))]
4561 return output_call_mem (operands);
4563 [(set_attr "length" "12")
4564 (set_attr "type" "call")])
4566 (define_expand "call_value"
4567 [(parallel [(set (match_operand 0 "" "=rf")
4568 (call (match_operand 1 "memory_operand" "m")
4569 (match_operand 2 "general_operand" "g")))
4570 (use (match_operand:SI 3 "" ""))
4571 (clobber (reg:SI 14))])]
4575 rtx callee = XEXP (operands[1], 0);
4577 /* In an untyped call, we can get NULL for operand 2. */
4578 if (operands[3] == 0)
4579 operands[3] = const0_rtx;
4581 /* See the comment in define_expand \"call\". */
4582 if (GET_CODE (callee) != REG
4583 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
4584 XEXP (operands[1], 0) = force_reg (Pmode, callee);
4588 (define_insn "*call_value_reg"
4589 [(set (match_operand 0 "" "=rf")
4590 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4591 (match_operand 2 "general_operand" "g")))
4592 (use (match_operand 3 "" ""))
4593 (clobber (reg:SI 14))]
4596 return output_call (&operands[1]);
4598 [(set_attr "length" "12")
4599 (set_attr "type" "call")])
4601 (define_insn "*call_value_mem"
4602 [(set (match_operand 0 "" "=rf")
4603 (call (mem:SI (match_operand 1 "memory_operand" "m"))
4604 (match_operand 2 "general_operand" "g")))
4605 (use (match_operand 3 "" ""))
4606 (clobber (reg:SI 14))]
4607 "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
4609 return output_call_mem (&operands[1]);
4611 [(set_attr "length" "12")
4612 (set_attr "type" "call")])
4614 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
4615 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
4617 (define_insn "*call_symbol"
4618 [(call (mem:SI (match_operand:SI 0 "" "X"))
4619 (match_operand:SI 1 "general_operand" "g"))
4620 (use (match_operand 2 "" ""))
4621 (clobber (reg:SI 14))]
4622 "(GET_CODE (operands[0]) == SYMBOL_REF)
4623 && ! arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
4626 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
4628 [(set_attr "type" "call")])
4630 (define_insn "*call_value_symbol"
4631 [(set (match_operand 0 "s_register_operand" "=rf")
4632 (call (mem:SI (match_operand:SI 1 "" "X"))
4633 (match_operand:SI 2 "general_operand" "g")))
4634 (use (match_operand 3 "" ""))
4635 (clobber (reg:SI 14))]
4636 "(GET_CODE (operands[1]) == SYMBOL_REF)
4637 && ! arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
4640 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
4642 [(set_attr "type" "call")])
4644 ;; Often the return insn will be the same as loading from memory, so set attr
4645 (define_insn "return"
4647 "USE_RETURN_INSN (FALSE)"
4650 extern int arm_ccfsm_state;
4652 if (arm_ccfsm_state == 2)
4654 arm_ccfsm_state += 2;
4657 return output_return_instruction (NULL, TRUE, FALSE);
4659 [(set_attr "type" "load")])
4661 (define_insn "*cond_return"
4663 (if_then_else (match_operator 0 "comparison_operator"
4664 [(match_operand 1 "cc_register" "") (const_int 0)])
4667 "USE_RETURN_INSN (TRUE)"
4670 extern int arm_ccfsm_state;
4672 if (arm_ccfsm_state == 2)
4674 arm_ccfsm_state += 2;
4677 return output_return_instruction (operands[0], TRUE, FALSE);
4679 [(set_attr "conds" "use")
4680 (set_attr "type" "load")])
4682 (define_insn "*cond_return_inverted"
4684 (if_then_else (match_operator 0 "comparison_operator"
4685 [(match_operand 1 "cc_register" "") (const_int 0)])
4688 "USE_RETURN_INSN (TRUE)"
4691 extern int arm_ccfsm_state;
4693 if (arm_ccfsm_state == 2)
4695 arm_ccfsm_state += 2;
4698 return output_return_instruction (operands[0], TRUE, TRUE);
4700 [(set_attr "conds" "use")
4701 (set_attr "type" "load")])
4703 ;; Call subroutine returning any type.
4705 (define_expand "untyped_call"
4706 [(parallel [(call (match_operand 0 "" "")
4708 (match_operand 1 "" "")
4709 (match_operand 2 "" "")])]
4715 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
4717 for (i = 0; i < XVECLEN (operands[2], 0); i++)
4719 rtx set = XVECEXP (operands[2], 0, i);
4720 emit_move_insn (SET_DEST (set), SET_SRC (set));
4723 /* The optimizer does not know that the call sets the function value
4724 registers we stored in the result block. We avoid problems by
4725 claiming that all hard registers are used and clobbered at this
4727 emit_insn (gen_blockage ());
4732 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
4733 ;; all of memory. This blocks insns from being moved across this point.
4735 (define_insn "blockage"
4736 [(unspec_volatile [(const_int 0)] 0)]
4739 [(set_attr "length" "0")
4740 (set_attr "type" "block")])
4742 (define_expand "casesi"
4743 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
4744 (match_operand:SI 1 "const_int_operand" "") ; lower bound
4745 (match_operand:SI 2 "const_int_operand" "") ; total range
4746 (match_operand:SI 3 "" "") ; table label
4747 (match_operand:SI 4 "" "")] ; Out of range label
4752 if (operands[1] != const0_rtx)
4754 reg = gen_reg_rtx (SImode);
4755 emit_insn (gen_addsi3 (reg, operands[0],
4756 GEN_INT (-INTVAL (operands[1]))));
4760 if (! const_ok_for_arm (INTVAL (operands[2])))
4761 operands[2] = force_reg (SImode, operands[2]);
4763 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
4768 ;; The USE in this pattern is needed to tell flow analysis that this is
4769 ;; a CASESI insn. It has no other purpose.
4770 (define_insn "casesi_internal"
4771 [(parallel [(set (pc)
4773 (leu (match_operand:SI 0 "s_register_operand" "r")
4774 (match_operand:SI 1 "arm_rhs_operand" "rI"))
4775 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
4776 (label_ref (match_operand 2 "" ""))))
4777 (label_ref (match_operand 3 "" ""))))
4778 (clobber (reg:CC 24))
4779 (use (label_ref (match_dup 2)))])]
4783 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
4784 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
4786 [(set_attr "conds" "clob")
4787 (set_attr "length" "12")])
4789 (define_insn "indirect_jump"
4791 (match_operand:SI 0 "s_register_operand" "r"))]
4793 "mov%?\\t%|pc, %0\\t%@ indirect jump")
4795 (define_insn "*load_indirect_jump"
4797 (match_operand:SI 0 "memory_operand" "m"))]
4799 "ldr%?\\t%|pc, %0\\t%@ indirect jump"
4800 [(set_attr "type" "load")])
4807 "mov%?\\t%|r0, %|r0\\t%@ nop")
4809 ;; Patterns to allow combination of arithmetic, cond code and shifts
4811 (define_insn "*arith_shiftsi"
4812 [(set (match_operand:SI 0 "s_register_operand" "=r")
4813 (match_operator:SI 1 "shiftable_operator"
4814 [(match_operator:SI 3 "shift_operator"
4815 [(match_operand:SI 4 "s_register_operand" "r")
4816 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4817 (match_operand:SI 2 "s_register_operand" "r")]))]
4819 "%i1%?\\t%0, %2, %4%S3"
4822 (define_insn "*arith_shiftsi_compare0"
4823 [(set (reg:CC_NOOV 24)
4824 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4825 [(match_operator:SI 3 "shift_operator"
4826 [(match_operand:SI 4 "s_register_operand" "r")
4827 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4828 (match_operand:SI 2 "s_register_operand" "r")])
4830 (set (match_operand:SI 0 "s_register_operand" "=r")
4831 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4834 "%i1%?s\\t%0, %2, %4%S3"
4835 [(set_attr "conds" "set")
4838 (define_insn "*arith_shiftsi_compare0_scratch"
4839 [(set (reg:CC_NOOV 24)
4840 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4841 [(match_operator:SI 3 "shift_operator"
4842 [(match_operand:SI 4 "s_register_operand" "r")
4843 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4844 (match_operand:SI 2 "s_register_operand" "r")])
4846 (clobber (match_scratch:SI 0 "=r"))]
4848 "%i1%?s\\t%0, %2, %4%S3"
4849 [(set_attr "conds" "set")
4852 (define_insn "*sub_shiftsi"
4853 [(set (match_operand:SI 0 "s_register_operand" "=r")
4854 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4855 (match_operator:SI 2 "shift_operator"
4856 [(match_operand:SI 3 "s_register_operand" "r")
4857 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4859 "sub%?\\t%0, %1, %3%S2"
4862 (define_insn "*sub_shiftsi_compare0"
4863 [(set (reg:CC_NOOV 24)
4865 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4866 (match_operator:SI 2 "shift_operator"
4867 [(match_operand:SI 3 "s_register_operand" "r")
4868 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4870 (set (match_operand:SI 0 "s_register_operand" "=r")
4871 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4874 "sub%?s\\t%0, %1, %3%S2"
4875 [(set_attr "conds" "set")
4878 (define_insn "*sub_shiftsi_compare0_scratch"
4879 [(set (reg:CC_NOOV 24)
4881 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4882 (match_operator:SI 2 "shift_operator"
4883 [(match_operand:SI 3 "s_register_operand" "r")
4884 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4886 (clobber (match_scratch:SI 0 "=r"))]
4888 "sub%?s\\t%0, %1, %3%S2"
4889 [(set_attr "conds" "set")
4892 ;; These variants of the above insns can occur if the first operand is the
4893 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
4894 ;; seem to be a way around it. Most of the predicates have to be null
4895 ;; because the format can be generated part way through reload, so
4896 ;; if we don't match it as soon as it becomes available, reload doesn't know
4897 ;; how to reload pseudos that haven't got hard registers; the constraints will
4898 ;; sort everything out.
4900 (define_insn "*reload_mulsi3"
4901 [(set (match_operand:SI 0 "" "=&r")
4902 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4903 [(match_operand:SI 3 "" "r")
4904 (match_operand:SI 4 "" "rM")])
4905 (match_operand:SI 2 "" "r"))
4906 (match_operand:SI 1 "const_int_operand" "n")))]
4907 "reload_in_progress"
4909 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4910 operands[2] = operands[1];
4911 operands[1] = operands[0];
4912 return output_add_immediate (operands);
4914 ; we have no idea how long the add_immediate is, it could be up to 4.
4915 [(set_attr "length" "20")])
4917 (define_insn "*reload_mulsi_compare0"
4918 [(set (reg:CC_NOOV 24)
4919 (compare:CC_NOOV (plus:SI
4921 (match_operator:SI 5 "shift_operator"
4922 [(match_operand:SI 3 "" "r")
4923 (match_operand:SI 4 "" "rM")])
4924 (match_operand:SI 1 "" "r"))
4925 (match_operand:SI 2 "const_int_operand" "n"))
4927 (set (match_operand:SI 0 "" "=&r")
4928 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4931 "reload_in_progress"
4933 output_add_immediate (operands);
4934 return \"add%?s\\t%0, %0, %3%S5\";
4936 [(set_attr "conds" "set")
4937 (set_attr "length" "20")])
4939 (define_insn "*reload_mulsi_compare0_scratch"
4940 [(set (reg:CC_NOOV 24)
4941 (compare:CC_NOOV (plus:SI
4943 (match_operator:SI 5 "shift_operator"
4944 [(match_operand:SI 3 "" "r")
4945 (match_operand:SI 4 "" "rM")])
4946 (match_operand:SI 1 "" "r"))
4947 (match_operand:SI 2 "const_int_operand" "n"))
4949 (clobber (match_scratch:SI 0 "=&r"))]
4950 "reload_in_progress"
4952 output_add_immediate (operands);
4953 return \"add%?s\\t%0, %0, %3%S5\";
4955 [(set_attr "conds" "set")
4956 (set_attr "length" "20")])
4958 ;; These are similar, but are needed when the mla pattern contains the
4959 ;; eliminated register as operand 3.
4961 (define_insn "*reload_muladdsi"
4962 [(set (match_operand:SI 0 "" "=&r,&r")
4963 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4964 (match_operand:SI 2 "" "r,r"))
4965 (match_operand:SI 3 "" "r,r"))
4966 (match_operand:SI 4 "const_int_operand" "n,n")))]
4967 "reload_in_progress"
4969 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4970 operands[2] = operands[4];
4971 operands[1] = operands[0];
4972 return output_add_immediate (operands);
4974 [(set_attr "length" "20")
4975 (set_attr "type" "mult")])
4977 (define_insn "*reload_muladdsi_compare0"
4978 [(set (reg:CC_NOOV 24)
4979 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4980 (match_operand:SI 3 "" "r")
4981 (match_operand:SI 4 "" "r"))
4982 (match_operand:SI 1 "" "r"))
4983 (match_operand:SI 2 "const_int_operand" "n"))
4985 (set (match_operand:SI 0 "" "=&r")
4986 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4988 "reload_in_progress"
4990 output_add_immediate (operands);
4991 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4994 [(set_attr "length" "20")
4995 (set_attr "conds" "set")
4996 (set_attr "type" "mult")])
4998 (define_insn "*reload_muladdsi_compare0_scratch"
4999 [(set (reg:CC_NOOV 24)
5000 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
5001 (match_operand:SI 3 "" "r")
5002 (match_operand:SI 4 "" "r"))
5003 (match_operand:SI 1 "" "r"))
5004 (match_operand:SI 2 "const_int_operand" "n"))
5006 (clobber (match_scratch:SI 0 "=&r"))]
5007 "reload_in_progress"
5009 output_add_immediate (operands);
5010 return \"mla%?s\\t%0, %3, %4, %0\";
5012 [(set_attr "length" "20")
5013 (set_attr "conds" "set")
5014 (set_attr "type" "mult")])
5018 (define_insn "*and_scc"
5019 [(set (match_operand:SI 0 "s_register_operand" "=r")
5020 (and:SI (match_operator 1 "comparison_operator"
5021 [(match_operand 3 "cc_register" "") (const_int 0)])
5022 (match_operand:SI 2 "s_register_operand" "r")))]
5024 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
5025 [(set_attr "conds" "use")
5026 (set_attr "length" "8")])
5028 (define_insn "*ior_scc"
5029 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5030 (ior:SI (match_operator 2 "comparison_operator"
5031 [(match_operand 3 "cc_register" "") (const_int 0)])
5032 (match_operand:SI 1 "s_register_operand" "0,?r")))]
5036 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
5037 [(set_attr "conds" "use")
5038 (set_attr "length" "4,8")])
5040 (define_insn "*compare_scc"
5041 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5042 (match_operator 1 "comparison_operator"
5043 [(match_operand:SI 2 "s_register_operand" "r,r")
5044 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
5045 (clobber (reg:CC 24))]
5048 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
5049 return \"mov\\t%0, %2, lsr #31\";
5051 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
5052 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
5054 if (GET_CODE (operands[1]) == NE)
5056 if (which_alternative == 1)
5057 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
5058 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
5060 if (which_alternative == 1)
5061 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
5063 output_asm_insn (\"cmp\\t%2, %3\", operands);
5064 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
5066 [(set_attr "conds" "clob")
5067 (set_attr "length" "12")])
5069 (define_insn "*cond_move"
5070 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5071 (if_then_else:SI (match_operator 3 "equality_operator"
5072 [(match_operator 4 "comparison_operator"
5073 [(match_operand 5 "cc_register" "") (const_int 0)])
5075 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
5076 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
5079 if (GET_CODE (operands[3]) == NE)
5081 if (which_alternative != 1)
5082 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
5083 if (which_alternative != 0)
5084 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
5087 if (which_alternative != 0)
5088 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
5089 if (which_alternative != 1)
5090 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
5093 [(set_attr "conds" "use")
5094 (set_attr "length" "4,4,8")])
5096 (define_insn "*cond_arith"
5097 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5098 (match_operator:SI 5 "shiftable_operator"
5099 [(match_operator:SI 4 "comparison_operator"
5100 [(match_operand:SI 2 "s_register_operand" "r,r")
5101 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
5102 (match_operand:SI 1 "s_register_operand" "0,?r")]))
5103 (clobber (reg:CC 24))]
5106 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
5107 return \"%i5\\t%0, %1, %2, lsr #31\";
5109 output_asm_insn (\"cmp\\t%2, %3\", operands);
5110 if (GET_CODE (operands[5]) == AND)
5111 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
5112 else if (GET_CODE (operands[5]) == MINUS)
5113 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
5114 else if (which_alternative != 0)
5115 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
5116 return \"%i5%d4\\t%0, %1, #1\";
5118 [(set_attr "conds" "clob")
5119 (set_attr "length" "12")])
5121 (define_insn "*cond_sub"
5122 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5123 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
5124 (match_operator:SI 4 "comparison_operator"
5125 [(match_operand:SI 2 "s_register_operand" "r,r")
5126 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
5127 (clobber (reg:CC 24))]
5130 output_asm_insn (\"cmp\\t%2, %3\", operands);
5131 if (which_alternative != 0)
5132 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
5133 return \"sub%d4\\t%0, %1, #1\";
5135 [(set_attr "conds" "clob")
5136 (set_attr "length" "8,12")])
5138 (define_insn "*cmp_ite0"
5139 [(set (match_operand:CC 6 "dominant_cc_register" "")
5142 (match_operator 4 "comparison_operator"
5143 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
5144 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
5145 (match_operator:SI 5 "comparison_operator"
5146 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
5147 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
5153 char* opcodes[4][2] =
5155 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
5156 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
5157 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
5158 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
5159 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
5162 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
5164 return opcodes[which_alternative][swap];
5167 [(set_attr "conds" "set")
5168 (set_attr "length" "8")])
5170 (define_insn "*cmp_ite1"
5171 [(set (match_operand:CC 6 "dominant_cc_register" "")
5174 (match_operator 4 "comparison_operator"
5175 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
5176 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
5177 (match_operator:SI 5 "comparison_operator"
5178 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
5179 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
5185 char* opcodes[4][2] =
5187 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
5188 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
5189 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
5190 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
5191 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
5194 comparison_dominates_p (GET_CODE (operands[5]),
5195 reverse_condition (GET_CODE (operands[4])));
5197 return opcodes[which_alternative][swap];
5200 [(set_attr "conds" "set")
5201 (set_attr "length" "8")])
5203 (define_insn "*negscc"
5204 [(set (match_operand:SI 0 "s_register_operand" "=r")
5205 (neg:SI (match_operator 3 "comparison_operator"
5206 [(match_operand:SI 1 "s_register_operand" "r")
5207 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
5208 (clobber (reg:CC 24))]
5211 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
5212 return \"mov\\t%0, %1, asr #31\";
5214 if (GET_CODE (operands[3]) == NE)
5215 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
5217 if (GET_CODE (operands[3]) == GT)
5218 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
5220 output_asm_insn (\"cmp\\t%1, %2\", operands);
5221 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
5222 return \"mvn%d3\\t%0, #0\";
5224 [(set_attr "conds" "clob")
5225 (set_attr "length" "12")])
5227 (define_insn "movcond"
5228 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5230 (match_operator 5 "comparison_operator"
5231 [(match_operand:SI 3 "s_register_operand" "r,r,r")
5232 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
5233 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
5234 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
5235 (clobber (reg:CC 24))]
5238 if (GET_CODE (operands[5]) == LT
5239 && (operands[4] == const0_rtx))
5241 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
5243 if (operands[2] == const0_rtx)
5244 return \"and\\t%0, %1, %3, asr #31\";
5245 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
5247 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
5249 if (operands[1] == const0_rtx)
5250 return \"bic\\t%0, %2, %3, asr #31\";
5251 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
5253 /* The only case that falls through to here is when both ops 1 & 2
5257 if (GET_CODE (operands[5]) == GE
5258 && (operands[4] == const0_rtx))
5260 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
5262 if (operands[2] == const0_rtx)
5263 return \"bic\\t%0, %1, %3, asr #31\";
5264 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
5266 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
5268 if (operands[1] == const0_rtx)
5269 return \"and\\t%0, %2, %3, asr #31\";
5270 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
5272 /* The only case that falls through to here is when both ops 1 & 2
5275 if (GET_CODE (operands[4]) == CONST_INT
5276 && !const_ok_for_arm (INTVAL (operands[4])))
5277 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
5279 output_asm_insn (\"cmp\\t%3, %4\", operands);
5280 if (which_alternative != 0)
5281 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
5282 if (which_alternative != 1)
5283 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
5286 [(set_attr "conds" "clob")
5287 (set_attr "length" "8,8,12")])
5289 (define_insn "*ifcompare_plus_move"
5290 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5291 (if_then_else:SI (match_operator 6 "comparison_operator"
5292 [(match_operand:SI 4 "s_register_operand" "r,r")
5293 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5295 (match_operand:SI 2 "s_register_operand" "r,r")
5296 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
5297 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5298 (clobber (reg:CC 24))]
5301 [(set_attr "conds" "clob")
5302 (set_attr "length" "8,12")])
5304 (define_insn "*if_plus_move"
5305 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
5307 (match_operator 4 "comparison_operator"
5308 [(match_operand 5 "cc_register" "") (const_int 0)])
5310 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
5311 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
5312 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
5316 sub%d4\\t%0, %2, #%n3
5317 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
5318 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
5319 [(set_attr "conds" "use")
5320 (set_attr "length" "4,4,8,8")
5321 (set_attr "type" "*,*,*,*")])
5323 (define_insn "*ifcompare_move_plus"
5324 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5325 (if_then_else:SI (match_operator 6 "comparison_operator"
5326 [(match_operand:SI 4 "s_register_operand" "r,r")
5327 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5328 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5330 (match_operand:SI 2 "s_register_operand" "r,r")
5331 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
5332 (clobber (reg:CC 24))]
5335 [(set_attr "conds" "clob")
5336 (set_attr "length" "8,12")])
5338 (define_insn "*if_move_plus"
5339 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
5341 (match_operator 4 "comparison_operator"
5342 [(match_operand 5 "cc_register" "") (const_int 0)])
5343 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
5345 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
5346 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
5350 sub%D4\\t%0, %2, #%n3
5351 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
5352 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
5353 [(set_attr "conds" "use")
5354 (set_attr "length" "4,4,8,8")
5355 (set_attr "type" "*,*,*,*")])
5357 (define_insn "*ifcompare_arith_arith"
5358 [(set (match_operand:SI 0 "s_register_operand" "=r")
5359 (if_then_else:SI (match_operator 9 "comparison_operator"
5360 [(match_operand:SI 5 "s_register_operand" "r")
5361 (match_operand:SI 6 "arm_add_operand" "rIL")])
5362 (match_operator:SI 8 "shiftable_operator"
5363 [(match_operand:SI 1 "s_register_operand" "r")
5364 (match_operand:SI 2 "arm_rhs_operand" "rI")])
5365 (match_operator:SI 7 "shiftable_operator"
5366 [(match_operand:SI 3 "s_register_operand" "r")
5367 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
5368 (clobber (reg:CC 24))]
5371 [(set_attr "conds" "clob")
5372 (set_attr "length" "12")])
5374 (define_insn "*if_arith_arith"
5375 [(set (match_operand:SI 0 "s_register_operand" "=r")
5376 (if_then_else:SI (match_operator 5 "comparison_operator"
5377 [(match_operand 8 "cc_register" "") (const_int 0)])
5378 (match_operator:SI 6 "shiftable_operator"
5379 [(match_operand:SI 1 "s_register_operand" "r")
5380 (match_operand:SI 2 "arm_rhs_operand" "rI")])
5381 (match_operator:SI 7 "shiftable_operator"
5382 [(match_operand:SI 3 "s_register_operand" "r")
5383 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
5385 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
5386 [(set_attr "conds" "use")
5387 (set_attr "length" "8")])
5389 (define_insn "*ifcompare_arith_move"
5390 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5391 (if_then_else:SI (match_operator 6 "comparison_operator"
5392 [(match_operand:SI 2 "s_register_operand" "r,r")
5393 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
5394 (match_operator:SI 7 "shiftable_operator"
5395 [(match_operand:SI 4 "s_register_operand" "r,r")
5396 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
5397 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5398 (clobber (reg:CC 24))]
5401 /* If we have an operation where (op x 0) is the identity operation and
5402 the conditional operator is LT or GE and we are comparing against zero and
5403 everything is in registers then we can do this in two instructions */
5404 if (operands[3] == const0_rtx
5405 && GET_CODE (operands[7]) != AND
5406 && GET_CODE (operands[5]) == REG
5407 && GET_CODE (operands[1]) == REG
5408 && REGNO (operands[1]) == REGNO (operands[4])
5409 && REGNO (operands[4]) != REGNO (operands[0]))
5411 if (GET_CODE (operands[6]) == LT)
5412 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5413 else if (GET_CODE (operands[6]) == GE)
5414 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5416 if (GET_CODE (operands[3]) == CONST_INT
5417 && !const_ok_for_arm (INTVAL (operands[3])))
5418 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
5420 output_asm_insn (\"cmp\\t%2, %3\", operands);
5421 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
5422 if (which_alternative != 0)
5423 return \"mov%D6\\t%0, %1\";
5426 [(set_attr "conds" "clob")
5427 (set_attr "length" "8,12")])
5429 (define_insn "*if_arith_move"
5430 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5431 (if_then_else:SI (match_operator 4 "comparison_operator"
5432 [(match_operand 6 "cc_register" "") (const_int 0)])
5433 (match_operator:SI 5 "shiftable_operator"
5434 [(match_operand:SI 2 "s_register_operand" "r,r")
5435 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
5436 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
5440 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
5441 [(set_attr "conds" "use")
5442 (set_attr "length" "4,8")
5443 (set_attr "type" "*,*")])
5445 (define_insn "*ifcompare_move_arith"
5446 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5447 (if_then_else:SI (match_operator 6 "comparison_operator"
5448 [(match_operand:SI 4 "s_register_operand" "r,r")
5449 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5450 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5451 (match_operator:SI 7 "shiftable_operator"
5452 [(match_operand:SI 2 "s_register_operand" "r,r")
5453 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
5454 (clobber (reg:CC 24))]
5457 /* If we have an operation where (op x 0) is the identity operation and
5458 the conditional operator is LT or GE and we are comparing against zero and
5459 everything is in registers then we can do this in two instructions */
5460 if (operands[5] == const0_rtx
5461 && GET_CODE (operands[7]) != AND
5462 && GET_CODE (operands[3]) == REG
5463 && GET_CODE (operands[1]) == REG
5464 && REGNO (operands[1]) == REGNO (operands[2])
5465 && REGNO (operands[2]) != REGNO (operands[0]))
5467 if (GET_CODE (operands[6]) == GE)
5468 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5469 else if (GET_CODE (operands[6]) == LT)
5470 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5473 if (GET_CODE (operands[5]) == CONST_INT
5474 && !const_ok_for_arm (INTVAL (operands[5])))
5475 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5477 output_asm_insn (\"cmp\\t%4, %5\", operands);
5479 if (which_alternative != 0)
5480 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
5481 return \"%I7%D6\\t%0, %2, %3\";
5483 [(set_attr "conds" "clob")
5484 (set_attr "length" "8,12")])
5486 (define_insn "*if_move_arith"
5487 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5489 (match_operator 4 "comparison_operator"
5490 [(match_operand 6 "cc_register" "") (const_int 0)])
5491 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5492 (match_operator:SI 5 "shiftable_operator"
5493 [(match_operand:SI 2 "s_register_operand" "r,r")
5494 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
5498 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
5499 [(set_attr "conds" "use")
5500 (set_attr "length" "4,8")
5501 (set_attr "type" "*,*")])
5503 (define_insn "*ifcompare_move_not"
5504 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5506 (match_operator 5 "comparison_operator"
5507 [(match_operand:SI 3 "s_register_operand" "r,r")
5508 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5509 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5511 (match_operand:SI 2 "s_register_operand" "r,r"))))
5512 (clobber (reg:CC 24))]
5515 [(set_attr "conds" "clob")
5516 (set_attr "length" "8,12")])
5518 (define_insn "*if_move_not"
5519 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5521 (match_operator 4 "comparison_operator"
5522 [(match_operand 3 "cc_register" "") (const_int 0)])
5523 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5524 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5528 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
5529 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
5530 [(set_attr "conds" "use")
5531 (set_attr "length" "4,8,8")])
5533 (define_insn "*ifcompare_not_move"
5534 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5536 (match_operator 5 "comparison_operator"
5537 [(match_operand:SI 3 "s_register_operand" "r,r")
5538 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5540 (match_operand:SI 2 "s_register_operand" "r,r"))
5541 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5542 (clobber (reg:CC 24))]
5545 [(set_attr "conds" "clob")
5546 (set_attr "length" "8,12")])
5548 (define_insn "*if_not_move"
5549 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5551 (match_operator 4 "comparison_operator"
5552 [(match_operand 3 "cc_register" "") (const_int 0)])
5553 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5554 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5558 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
5559 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
5560 [(set_attr "conds" "use")
5561 (set_attr "length" "4,8,8")])
5563 (define_insn "*ifcompare_shift_move"
5564 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5566 (match_operator 6 "comparison_operator"
5567 [(match_operand:SI 4 "s_register_operand" "r,r")
5568 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5569 (match_operator:SI 7 "shift_operator"
5570 [(match_operand:SI 2 "s_register_operand" "r,r")
5571 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
5572 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5573 (clobber (reg:CC 24))]
5576 [(set_attr "conds" "clob")
5577 (set_attr "length" "8,12")])
5579 (define_insn "*if_shift_move"
5580 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5582 (match_operator 5 "comparison_operator"
5583 [(match_operand 6 "cc_register" "") (const_int 0)])
5584 (match_operator:SI 4 "shift_operator"
5585 [(match_operand:SI 2 "s_register_operand" "r,r,r")
5586 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
5587 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5591 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
5592 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
5593 [(set_attr "conds" "use")
5594 (set_attr "length" "4,8,8")])
5596 (define_insn "*ifcompare_move_shift"
5597 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5599 (match_operator 6 "comparison_operator"
5600 [(match_operand:SI 4 "s_register_operand" "r,r")
5601 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5602 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5603 (match_operator:SI 7 "shift_operator"
5604 [(match_operand:SI 2 "s_register_operand" "r,r")
5605 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
5606 (clobber (reg:CC 24))]
5609 [(set_attr "conds" "clob")
5610 (set_attr "length" "8,12")])
5612 (define_insn "*if_move_shift"
5613 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5615 (match_operator 5 "comparison_operator"
5616 [(match_operand 6 "cc_register" "") (const_int 0)])
5617 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5618 (match_operator:SI 4 "shift_operator"
5619 [(match_operand:SI 2 "s_register_operand" "r,r,r")
5620 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
5624 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
5625 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
5626 [(set_attr "conds" "use")
5627 (set_attr "length" "4,8,8")])
5629 (define_insn "*ifcompare_shift_shift"
5630 [(set (match_operand:SI 0 "s_register_operand" "=r")
5632 (match_operator 7 "comparison_operator"
5633 [(match_operand:SI 5 "s_register_operand" "r")
5634 (match_operand:SI 6 "arm_add_operand" "rIL")])
5635 (match_operator:SI 8 "shift_operator"
5636 [(match_operand:SI 1 "s_register_operand" "r")
5637 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5638 (match_operator:SI 9 "shift_operator"
5639 [(match_operand:SI 3 "s_register_operand" "r")
5640 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
5641 (clobber (reg:CC 24))]
5644 [(set_attr "conds" "clob")
5645 (set_attr "length" "12")])
5647 (define_insn "*if_shift_shift"
5648 [(set (match_operand:SI 0 "s_register_operand" "=r")
5650 (match_operator 5 "comparison_operator"
5651 [(match_operand 8 "cc_register" "") (const_int 0)])
5652 (match_operator:SI 6 "shift_operator"
5653 [(match_operand:SI 1 "s_register_operand" "r")
5654 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5655 (match_operator:SI 7 "shift_operator"
5656 [(match_operand:SI 3 "s_register_operand" "r")
5657 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
5659 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
5660 [(set_attr "conds" "use")
5661 (set_attr "length" "8")])
5663 (define_insn "*ifcompare_not_arith"
5664 [(set (match_operand:SI 0 "s_register_operand" "=r")
5666 (match_operator 6 "comparison_operator"
5667 [(match_operand:SI 4 "s_register_operand" "r")
5668 (match_operand:SI 5 "arm_add_operand" "rIL")])
5669 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5670 (match_operator:SI 7 "shiftable_operator"
5671 [(match_operand:SI 2 "s_register_operand" "r")
5672 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5673 (clobber (reg:CC 24))]
5676 [(set_attr "conds" "clob")
5677 (set_attr "length" "12")])
5679 (define_insn "*if_not_arith"
5680 [(set (match_operand:SI 0 "s_register_operand" "=r")
5682 (match_operator 5 "comparison_operator"
5683 [(match_operand 4 "cc_register" "") (const_int 0)])
5684 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5685 (match_operator:SI 6 "shiftable_operator"
5686 [(match_operand:SI 2 "s_register_operand" "r")
5687 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
5689 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
5690 [(set_attr "conds" "use")
5691 (set_attr "length" "8")])
5693 (define_insn "*ifcompare_arith_not"
5694 [(set (match_operand:SI 0 "s_register_operand" "=r")
5696 (match_operator 6 "comparison_operator"
5697 [(match_operand:SI 4 "s_register_operand" "r")
5698 (match_operand:SI 5 "arm_add_operand" "rIL")])
5699 (match_operator:SI 7 "shiftable_operator"
5700 [(match_operand:SI 2 "s_register_operand" "r")
5701 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5702 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5703 (clobber (reg:CC 24))]
5706 [(set_attr "conds" "clob")
5707 (set_attr "length" "12")])
5709 (define_insn "*if_arith_not"
5710 [(set (match_operand:SI 0 "s_register_operand" "=r")
5712 (match_operator 5 "comparison_operator"
5713 [(match_operand 4 "cc_register" "") (const_int 0)])
5714 (match_operator:SI 6 "shiftable_operator"
5715 [(match_operand:SI 2 "s_register_operand" "r")
5716 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5717 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
5719 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
5720 [(set_attr "conds" "use")
5721 (set_attr "length" "8")])
5723 (define_insn "*ifcompare_neg_move"
5724 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5726 (match_operator 5 "comparison_operator"
5727 [(match_operand:SI 3 "s_register_operand" "r,r")
5728 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5729 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
5730 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5731 (clobber (reg:CC 24))]
5734 [(set_attr "conds" "clob")
5735 (set_attr "length" "8,12")])
5737 (define_insn "*if_neg_move"
5738 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5740 (match_operator 4 "comparison_operator"
5741 [(match_operand 3 "cc_register" "") (const_int 0)])
5742 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5743 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5747 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
5748 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
5749 [(set_attr "conds" "use")
5750 (set_attr "length" "4,8,8")])
5752 (define_insn "*ifcompare_move_neg"
5753 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5755 (match_operator 5 "comparison_operator"
5756 [(match_operand:SI 3 "s_register_operand" "r,r")
5757 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5758 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5759 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
5760 (clobber (reg:CC 24))]
5763 [(set_attr "conds" "clob")
5764 (set_attr "length" "8,12")])
5766 (define_insn "*if_move_neg"
5767 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5769 (match_operator 4 "comparison_operator"
5770 [(match_operand 3 "cc_register" "") (const_int 0)])
5771 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5772 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5776 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
5777 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
5778 [(set_attr "conds" "use")
5779 (set_attr "length" "4,8,8")])
5781 (define_insn "*arith_adjacentmem"
5782 [(set (match_operand:SI 0 "s_register_operand" "=r")
5783 (match_operator:SI 1 "shiftable_operator"
5784 [(match_operand:SI 2 "memory_operand" "m")
5785 (match_operand:SI 3 "memory_operand" "m")]))
5786 (clobber (match_scratch:SI 4 "=r"))]
5787 "adjacent_mem_locations (operands[2], operands[3])"
5792 int val1 = 0, val2 = 0;
5794 if (REGNO (operands[0]) > REGNO (operands[4]))
5796 ldm[1] = operands[4];
5797 ldm[2] = operands[0];
5801 ldm[1] = operands[0];
5802 ldm[2] = operands[4];
5804 if (GET_CODE (XEXP (operands[2], 0)) != REG)
5805 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5806 if (GET_CODE (XEXP (operands[3], 0)) != REG)
5807 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5808 arith[0] = operands[0];
5809 arith[3] = operands[1];
5823 ldm[0] = ops[0] = operands[4];
5824 ops[1] = XEXP (XEXP (operands[2], 0), 0);
5825 ops[2] = XEXP (XEXP (operands[2], 0), 1);
5826 output_add_immediate (ops);
5828 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5830 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5834 ldm[0] = XEXP (operands[3], 0);
5836 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5838 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5842 ldm[0] = XEXP (operands[2], 0);
5844 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5846 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5848 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
5852 [(set_attr "length" "12")
5853 (set_attr "type" "load")])
5855 ;; the arm can support extended pre-inc instructions
5857 ;; In all these cases, we use operands 0 and 1 for the register being
5858 ;; incremented because those are the operands that local-alloc will
5859 ;; tie and these are the pair most likely to be tieable (and the ones
5860 ;; that will benefit the most).
5862 ;; We reject the frame pointer if it occurs anywhere in these patterns since
5863 ;; elimination will cause too many headaches.
5865 (define_insn "*strqi_preinc"
5866 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5867 (match_operand:SI 2 "index_operand" "rJ")))
5868 (match_operand:QI 3 "s_register_operand" "r"))
5869 (set (match_operand:SI 0 "s_register_operand" "=r")
5870 (plus:SI (match_dup 1) (match_dup 2)))]
5871 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5872 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5873 && (GET_CODE (operands[2]) != REG
5874 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5875 "str%?b\\t%3, [%0, %2]!"
5876 [(set_attr "type" "store1")])
5878 (define_insn "*strqi_predec"
5879 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5880 (match_operand:SI 2 "s_register_operand" "r")))
5881 (match_operand:QI 3 "s_register_operand" "r"))
5882 (set (match_operand:SI 0 "s_register_operand" "=r")
5883 (minus:SI (match_dup 1) (match_dup 2)))]
5884 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5885 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5886 && (GET_CODE (operands[2]) != REG
5887 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5888 "str%?b\\t%3, [%0, -%2]!"
5889 [(set_attr "type" "store1")])
5891 (define_insn "*loadqi_preinc"
5892 [(set (match_operand:QI 3 "s_register_operand" "=r")
5893 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5894 (match_operand:SI 2 "index_operand" "rJ"))))
5895 (set (match_operand:SI 0 "s_register_operand" "=r")
5896 (plus:SI (match_dup 1) (match_dup 2)))]
5897 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5898 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5899 && (GET_CODE (operands[2]) != REG
5900 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5901 "ldr%?b\\t%3, [%0, %2]!"
5902 [(set_attr "type" "load")])
5904 (define_insn "*loadqi_predec"
5905 [(set (match_operand:QI 3 "s_register_operand" "=r")
5906 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5907 (match_operand:SI 2 "s_register_operand" "r"))))
5908 (set (match_operand:SI 0 "s_register_operand" "=r")
5909 (minus:SI (match_dup 1) (match_dup 2)))]
5910 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5911 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5912 && (GET_CODE (operands[2]) != REG
5913 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5914 "ldr%?b\\t%3, [%0, -%2]!"
5915 [(set_attr "type" "load")])
5917 (define_insn "*loadqisi_preinc"
5918 [(set (match_operand:SI 3 "s_register_operand" "=r")
5920 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5921 (match_operand:SI 2 "index_operand" "rJ")))))
5922 (set (match_operand:SI 0 "s_register_operand" "=r")
5923 (plus:SI (match_dup 1) (match_dup 2)))]
5924 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5925 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5926 && (GET_CODE (operands[2]) != REG
5927 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5928 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
5929 [(set_attr "type" "load")])
5931 (define_insn "*loadqisi_predec"
5932 [(set (match_operand:SI 3 "s_register_operand" "=r")
5934 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5935 (match_operand:SI 2 "s_register_operand" "r")))))
5936 (set (match_operand:SI 0 "s_register_operand" "=r")
5937 (minus:SI (match_dup 1) (match_dup 2)))]
5938 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5939 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5940 && (GET_CODE (operands[2]) != REG
5941 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5942 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
5943 [(set_attr "type" "load")])
5945 (define_insn "*strsi_preinc"
5946 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5947 (match_operand:SI 2 "index_operand" "rJ")))
5948 (match_operand:SI 3 "s_register_operand" "r"))
5949 (set (match_operand:SI 0 "s_register_operand" "=r")
5950 (plus:SI (match_dup 1) (match_dup 2)))]
5951 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5952 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5953 && (GET_CODE (operands[2]) != REG
5954 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5955 "str%?\\t%3, [%0, %2]!"
5956 [(set_attr "type" "store1")])
5958 (define_insn "*strsi_predec"
5959 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5960 (match_operand:SI 2 "s_register_operand" "r")))
5961 (match_operand:SI 3 "s_register_operand" "r"))
5962 (set (match_operand:SI 0 "s_register_operand" "=r")
5963 (minus:SI (match_dup 1) (match_dup 2)))]
5964 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5965 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5966 && (GET_CODE (operands[2]) != REG
5967 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5968 "str%?\\t%3, [%0, -%2]!"
5969 [(set_attr "type" "store1")])
5971 (define_insn "*loadsi_preinc"
5972 [(set (match_operand:SI 3 "s_register_operand" "=r")
5973 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5974 (match_operand:SI 2 "index_operand" "rJ"))))
5975 (set (match_operand:SI 0 "s_register_operand" "=r")
5976 (plus:SI (match_dup 1) (match_dup 2)))]
5977 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5978 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5979 && (GET_CODE (operands[2]) != REG
5980 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5981 "ldr%?\\t%3, [%0, %2]!"
5982 [(set_attr "type" "load")])
5984 (define_insn "*loadsi_predec"
5985 [(set (match_operand:SI 3 "s_register_operand" "=r")
5986 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5987 (match_operand:SI 2 "s_register_operand" "r"))))
5988 (set (match_operand:SI 0 "s_register_operand" "=r")
5989 (minus:SI (match_dup 1) (match_dup 2)))]
5990 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5991 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5992 && (GET_CODE (operands[2]) != REG
5993 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5994 "ldr%?\\t%3, [%0, -%2]!"
5995 [(set_attr "type" "load")])
5997 (define_insn "*loadhi_preinc"
5998 [(set (match_operand:HI 3 "s_register_operand" "=r")
5999 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
6000 (match_operand:SI 2 "index_operand" "rJ"))))
6001 (set (match_operand:SI 0 "s_register_operand" "=r")
6002 (plus:SI (match_dup 1) (match_dup 2)))]
6003 "(! BYTES_BIG_ENDIAN)
6004 && ! TARGET_MMU_TRAPS
6005 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
6006 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6007 && (GET_CODE (operands[2]) != REG
6008 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
6009 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
6010 [(set_attr "type" "load")])
6012 (define_insn "*loadhi_predec"
6013 [(set (match_operand:HI 3 "s_register_operand" "=r")
6014 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
6015 (match_operand:SI 2 "s_register_operand" "r"))))
6016 (set (match_operand:SI 0 "s_register_operand" "=r")
6017 (minus:SI (match_dup 1) (match_dup 2)))]
6018 "(!BYTES_BIG_ENDIAN)
6019 && ! TARGET_MMU_TRAPS
6020 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
6021 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6022 && (GET_CODE (operands[2]) != REG
6023 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
6024 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
6025 [(set_attr "type" "load")])
6027 (define_insn "*strqi_shiftpreinc"
6028 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
6029 [(match_operand:SI 3 "s_register_operand" "r")
6030 (match_operand:SI 4 "const_shift_operand" "n")])
6031 (match_operand:SI 1 "s_register_operand" "0")))
6032 (match_operand:QI 5 "s_register_operand" "r"))
6033 (set (match_operand:SI 0 "s_register_operand" "=r")
6034 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6036 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6037 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6038 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6039 "str%?b\\t%5, [%0, %3%S2]!"
6040 [(set_attr "type" "store1")])
6042 (define_insn "*strqi_shiftpredec"
6043 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
6044 (match_operator:SI 2 "shift_operator"
6045 [(match_operand:SI 3 "s_register_operand" "r")
6046 (match_operand:SI 4 "const_shift_operand" "n")])))
6047 (match_operand:QI 5 "s_register_operand" "r"))
6048 (set (match_operand:SI 0 "s_register_operand" "=r")
6049 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6051 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6052 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6053 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6054 "str%?b\\t%5, [%0, -%3%S2]!"
6055 [(set_attr "type" "store1")])
6057 (define_insn "*loadqi_shiftpreinc"
6058 [(set (match_operand:QI 5 "s_register_operand" "=r")
6059 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
6060 [(match_operand:SI 3 "s_register_operand" "r")
6061 (match_operand:SI 4 "const_shift_operand" "n")])
6062 (match_operand:SI 1 "s_register_operand" "0"))))
6063 (set (match_operand:SI 0 "s_register_operand" "=r")
6064 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6066 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6067 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6068 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6069 "ldr%?b\\t%5, [%0, %3%S2]!"
6070 [(set_attr "type" "load")])
6072 (define_insn "*loadqi_shiftpredec"
6073 [(set (match_operand:QI 5 "s_register_operand" "=r")
6074 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
6075 (match_operator:SI 2 "shift_operator"
6076 [(match_operand:SI 3 "s_register_operand" "r")
6077 (match_operand:SI 4 "const_shift_operand" "n")]))))
6078 (set (match_operand:SI 0 "s_register_operand" "=r")
6079 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6081 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6082 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6083 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6084 "ldr%?b\\t%5, [%0, -%3%S2]!"
6085 [(set_attr "type" "load")])
6087 (define_insn "*strsi_shiftpreinc"
6088 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
6089 [(match_operand:SI 3 "s_register_operand" "r")
6090 (match_operand:SI 4 "const_shift_operand" "n")])
6091 (match_operand:SI 1 "s_register_operand" "0")))
6092 (match_operand:SI 5 "s_register_operand" "r"))
6093 (set (match_operand:SI 0 "s_register_operand" "=r")
6094 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6096 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6097 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6098 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6099 "str%?\\t%5, [%0, %3%S2]!"
6100 [(set_attr "type" "store1")])
6102 (define_insn "*strsi_shiftpredec"
6103 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
6104 (match_operator:SI 2 "shift_operator"
6105 [(match_operand:SI 3 "s_register_operand" "r")
6106 (match_operand:SI 4 "const_shift_operand" "n")])))
6107 (match_operand:SI 5 "s_register_operand" "r"))
6108 (set (match_operand:SI 0 "s_register_operand" "=r")
6109 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6111 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6112 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6113 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6114 "str%?\\t%5, [%0, -%3%S2]!"
6115 [(set_attr "type" "store1")])
6117 (define_insn "*loadsi_shiftpreinc"
6118 [(set (match_operand:SI 5 "s_register_operand" "=r")
6119 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
6120 [(match_operand:SI 3 "s_register_operand" "r")
6121 (match_operand:SI 4 "const_shift_operand" "n")])
6122 (match_operand:SI 1 "s_register_operand" "0"))))
6123 (set (match_operand:SI 0 "s_register_operand" "=r")
6124 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6126 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6127 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6128 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6129 "ldr%?\\t%5, [%0, %3%S2]!"
6130 [(set_attr "type" "load")])
6132 (define_insn "*loadsi_shiftpredec"
6133 [(set (match_operand:SI 5 "s_register_operand" "=r")
6134 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
6135 (match_operator:SI 2 "shift_operator"
6136 [(match_operand:SI 3 "s_register_operand" "r")
6137 (match_operand:SI 4 "const_shift_operand" "n")]))))
6138 (set (match_operand:SI 0 "s_register_operand" "=r")
6139 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6141 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
6142 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6143 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6144 "ldr%?\\t%5, [%0, -%3%S2]!"
6145 [(set_attr "type" "load")])
6147 (define_insn "*loadhi_shiftpreinc"
6148 [(set (match_operand:HI 5 "s_register_operand" "=r")
6149 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
6150 [(match_operand:SI 3 "s_register_operand" "r")
6151 (match_operand:SI 4 "const_shift_operand" "n")])
6152 (match_operand:SI 1 "s_register_operand" "0"))))
6153 (set (match_operand:SI 0 "s_register_operand" "=r")
6154 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6156 "(! BYTES_BIG_ENDIAN)
6157 && ! TARGET_MMU_TRAPS
6158 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
6159 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6160 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6161 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
6162 [(set_attr "type" "load")])
6164 (define_insn "*loadhi_shiftpredec"
6165 [(set (match_operand:HI 5 "s_register_operand" "=r")
6166 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
6167 (match_operator:SI 2 "shift_operator"
6168 [(match_operand:SI 3 "s_register_operand" "r")
6169 (match_operand:SI 4 "const_shift_operand" "n")]))))
6170 (set (match_operand:SI 0 "s_register_operand" "=r")
6171 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6173 "(! BYTES_BIG_ENDIAN)
6174 && ! TARGET_MMU_TRAPS
6175 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
6176 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
6177 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
6178 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
6179 [(set_attr "type" "load")])
6181 ; It can also support extended post-inc expressions, but combine doesn't
6183 ; It doesn't seem worth adding peepholes for anything but the most common
6184 ; cases since, unlike combine, the increment must immediately follow the load
6185 ; for this pattern to match.
6186 ; When loading we must watch to see that the base register isn't trampled by
6187 ; the load. In such cases this isn't a post-inc expression.
6190 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
6191 (match_operand:QI 2 "s_register_operand" "r"))
6193 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
6195 "str%?b\\t%2, [%0], %1")
6198 [(set (match_operand:QI 0 "s_register_operand" "=r")
6199 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
6201 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
6202 "REGNO(operands[0]) != REGNO(operands[1])
6203 && (GET_CODE (operands[2]) != REG
6204 || REGNO(operands[0]) != REGNO (operands[2]))"
6205 "ldr%?b\\t%0, [%1], %2")
6208 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
6209 (match_operand:SI 2 "s_register_operand" "r"))
6211 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
6213 "str%?\\t%2, [%0], %1")
6216 [(set (match_operand:HI 0 "s_register_operand" "=r")
6217 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
6219 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
6220 "(! BYTES_BIG_ENDIAN)
6221 && ! TARGET_MMU_TRAPS
6222 && REGNO(operands[0]) != REGNO(operands[1])
6223 && (GET_CODE (operands[2]) != REG
6224 || REGNO(operands[0]) != REGNO (operands[2]))"
6225 "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
6228 [(set (match_operand:SI 0 "s_register_operand" "=r")
6229 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
6231 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
6232 "REGNO(operands[0]) != REGNO(operands[1])
6233 && (GET_CODE (operands[2]) != REG
6234 || REGNO(operands[0]) != REGNO (operands[2]))"
6235 "ldr%?\\t%0, [%1], %2")
6238 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
6239 (match_operand:SI 1 "index_operand" "rJ")))
6240 (match_operand:QI 2 "s_register_operand" "r"))
6241 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
6243 "str%?b\\t%2, [%0, %1]!")
6246 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
6247 [(match_operand:SI 0 "s_register_operand" "r")
6248 (match_operand:SI 1 "const_int_operand" "n")])
6249 (match_operand:SI 2 "s_register_operand" "+r")))
6250 (match_operand:QI 3 "s_register_operand" "r"))
6251 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
6254 "str%?b\\t%3, [%2, %0%S4]!")
6256 ; This pattern is never tried by combine, so do it as a peephole
6259 [(set (match_operand:SI 0 "s_register_operand" "=r")
6260 (match_operand:SI 1 "s_register_operand" "r"))
6262 (compare:CC (match_dup 1) (const_int 0)))]
6264 "sub%?s\\t%0, %1, #0"
6265 [(set_attr "conds" "set")])
6267 ; Peepholes to spot possible load- and store-multiples, if the ordering is
6268 ; reversed, check that the memory references aren't volatile.
6271 [(set (match_operand:SI 0 "s_register_operand" "=r")
6272 (match_operand:SI 4 "memory_operand" "m"))
6273 (set (match_operand:SI 1 "s_register_operand" "=r")
6274 (match_operand:SI 5 "memory_operand" "m"))
6275 (set (match_operand:SI 2 "s_register_operand" "=r")
6276 (match_operand:SI 6 "memory_operand" "m"))
6277 (set (match_operand:SI 3 "s_register_operand" "=r")
6278 (match_operand:SI 7 "memory_operand" "m"))]
6279 "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
6281 return emit_ldm_seq (operands, 4);
6285 [(set (match_operand:SI 0 "s_register_operand" "=r")
6286 (match_operand:SI 3 "memory_operand" "m"))
6287 (set (match_operand:SI 1 "s_register_operand" "=r")
6288 (match_operand:SI 4 "memory_operand" "m"))
6289 (set (match_operand:SI 2 "s_register_operand" "=r")
6290 (match_operand:SI 5 "memory_operand" "m"))]
6291 "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
6293 return emit_ldm_seq (operands, 3);
6297 [(set (match_operand:SI 0 "s_register_operand" "=r")
6298 (match_operand:SI 2 "memory_operand" "m"))
6299 (set (match_operand:SI 1 "s_register_operand" "=r")
6300 (match_operand:SI 3 "memory_operand" "m"))]
6301 "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
6303 return emit_ldm_seq (operands, 2);
6307 [(set (match_operand:SI 4 "memory_operand" "=m")
6308 (match_operand:SI 0 "s_register_operand" "r"))
6309 (set (match_operand:SI 5 "memory_operand" "=m")
6310 (match_operand:SI 1 "s_register_operand" "r"))
6311 (set (match_operand:SI 6 "memory_operand" "=m")
6312 (match_operand:SI 2 "s_register_operand" "r"))
6313 (set (match_operand:SI 7 "memory_operand" "=m")
6314 (match_operand:SI 3 "s_register_operand" "r"))]
6315 "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
6317 return emit_stm_seq (operands, 4);
6321 [(set (match_operand:SI 3 "memory_operand" "=m")
6322 (match_operand:SI 0 "s_register_operand" "r"))
6323 (set (match_operand:SI 4 "memory_operand" "=m")
6324 (match_operand:SI 1 "s_register_operand" "r"))
6325 (set (match_operand:SI 5 "memory_operand" "=m")
6326 (match_operand:SI 2 "s_register_operand" "r"))]
6327 "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
6329 return emit_stm_seq (operands, 3);
6333 [(set (match_operand:SI 2 "memory_operand" "=m")
6334 (match_operand:SI 0 "s_register_operand" "r"))
6335 (set (match_operand:SI 3 "memory_operand" "=m")
6336 (match_operand:SI 1 "s_register_operand" "r"))]
6337 "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
6339 return emit_stm_seq (operands, 2);
6342 ;; A call followed by return can be replaced by restoring the regs and
6343 ;; jumping to the subroutine, provided we aren't passing the address of
6344 ;; any of our local variables. If we call alloca then this is unsafe
6345 ;; since restoring the frame frees the memory, which is not what we want.
6346 ;; Sometimes the return might have been targeted by the final prescan:
6347 ;; if so then emit a proper return insn as well.
6348 ;; Unfortunately, if the frame pointer is required, we don't know if the
6349 ;; current function has any implicit stack pointer adjustments that will
6350 ;; be restored by the return: we can't therefore do a tail call.
6351 ;; Another unfortunate that we can't handle is if current_function_args_size
6352 ;; is non-zero: in this case elimination of the argument pointer assumed
6353 ;; that lr was pushed onto the stack, so eliminating upsets the offset
6357 [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
6358 (match_operand:SI 1 "general_operand" "g"))
6359 (use (match_operand:SI 2 "" ""))
6360 (clobber (reg:SI 14))])
6362 "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN (FALSE)
6363 && !get_frame_size () && !current_function_calls_alloca
6364 && !frame_pointer_needed && !current_function_args_size)"
6367 extern rtx arm_target_insn;
6368 extern int arm_ccfsm_state;
6370 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6372 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6373 output_return_instruction (NULL, TRUE, FALSE);
6374 arm_ccfsm_state = 0;
6375 arm_target_insn = NULL;
6378 output_return_instruction (NULL, FALSE, FALSE);
6379 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6381 [(set_attr "type" "call")
6382 (set_attr "length" "8")])
6385 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6386 (call (mem:SI (match_operand:SI 1 "" "X"))
6387 (match_operand:SI 2 "general_operand" "g")))
6388 (use (match_operand:SI 3 "" ""))
6389 (clobber (reg:SI 14))])
6391 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN (FALSE)
6392 && !get_frame_size () && !current_function_calls_alloca
6393 && !frame_pointer_needed && !current_function_args_size)"
6396 extern rtx arm_target_insn;
6397 extern int arm_ccfsm_state;
6399 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6401 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6402 output_return_instruction (NULL, TRUE, FALSE);
6403 arm_ccfsm_state = 0;
6404 arm_target_insn = NULL;
6407 output_return_instruction (NULL, FALSE, FALSE);
6408 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6410 [(set_attr "type" "call")
6411 (set_attr "length" "8")])
6413 ;; As above but when this function is not void, we must be returning the
6414 ;; result of the called subroutine.
6417 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6418 (call (mem:SI (match_operand:SI 1 "" "X"))
6419 (match_operand:SI 2 "general_operand" "g")))
6420 (use (match_operand:SI 3 "" ""))
6421 (clobber (reg:SI 14))])
6424 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN (FALSE)
6425 && !get_frame_size () && !current_function_calls_alloca
6426 && !frame_pointer_needed && !current_function_args_size)"
6429 extern rtx arm_target_insn;
6430 extern int arm_ccfsm_state;
6432 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6434 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6435 output_return_instruction (NULL, TRUE, FALSE);
6436 arm_ccfsm_state = 0;
6437 arm_target_insn = NULL;
6440 output_return_instruction (NULL, FALSE, FALSE);
6441 return \"b%?\\t%a1\";
6443 [(set_attr "type" "call")
6444 (set_attr "length" "8")])
6447 [(set (match_operand:SI 0 "s_register_operand" "")
6448 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
6450 (neg:SI (match_operator:SI 2 "comparison_operator"
6451 [(match_operand:SI 3 "s_register_operand" "")
6452 (match_operand:SI 4 "arm_rhs_operand" "")]))))
6453 (clobber (match_operand:SI 5 "s_register_operand" ""))]
6455 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
6456 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6460 ;; This split can be used because CC_Z mode implies that the following
6461 ;; branch will be an equality, or an unsigned inequality, so the sign
6462 ;; extension is not needed.
6467 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
6469 (match_operand 1 "const_int_operand" "")))
6470 (clobber (match_scratch:SI 2 ""))]
6471 "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
6472 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
6473 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
6474 (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
6476 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
6479 (define_expand "prologue"
6480 [(clobber (const_int 0))]
6483 arm_expand_prologue ();
6487 (define_expand "epilogue"
6488 [(unspec_volatile [(return)] 6)]
6491 if (USE_RETURN_INSN (FALSE))
6493 emit_jump_insn (gen_return ());
6498 (define_insn "*epilogue_insn"
6499 [(unspec_volatile [(return)] 6)]
6502 return arm_output_epilogue ();
6504 ;; Length is absolute worst case
6505 [(set_attr "length" "44")
6506 (set_attr "type" "block")])
6508 ;; This split is only used during output to reduce the number of patterns
6509 ;; that need assembler instructions adding to them. We allowed the setting
6510 ;; of the conditions to be implicit during rtl generation so that
6511 ;; the conditional compare patterns would work. However this conflicts to
6512 ;; some extent with the conditional data operations, so we have to split them
6516 [(set (match_operand:SI 0 "s_register_operand" "")
6517 (if_then_else:SI (match_operator 1 "comparison_operator"
6518 [(match_operand 2 "" "") (match_operand 3 "" "")])
6519 (match_operand 4 "" "")
6520 (match_operand 5 "" "")))
6521 (clobber (reg:CC 24))]
6523 [(set (match_dup 6) (match_dup 7))
6525 (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
6530 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
6533 operands[6] = gen_rtx_REG (mode, 24);
6534 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
6538 ;; The next two patterns occur when an AND operation is followed by a
6539 ;; scc insn sequence
6541 (define_insn "*sign_extract_onebit"
6542 [(set (match_operand:SI 0 "s_register_operand" "=r")
6543 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6545 (match_operand:SI 2 "const_int_operand" "n")))]
6548 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6549 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6550 return \"mvnne\\t%0, #0\";
6552 [(set_attr "conds" "clob")
6553 (set_attr "length" "8")])
6555 (define_insn "*not_signextract_onebit"
6556 [(set (match_operand:SI 0 "s_register_operand" "=r")
6558 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6560 (match_operand:SI 2 "const_int_operand" "n"))))]
6563 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6564 output_asm_insn (\"tst\\t%1, %2\", operands);
6565 output_asm_insn (\"mvneq\\t%0, #0\", operands);
6566 return \"movne\\t%0, #0\";
6568 [(set_attr "conds" "clob")
6569 (set_attr "length" "12")])
6571 ;; Push multiple registers to the stack. The first register is in the
6572 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
6574 (define_insn "*push_multi"
6575 [(match_parallel 2 "multi_register_push"
6576 [(set (match_operand:BLK 0 "memory_operand" "=m")
6577 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
6581 extern int lr_save_eliminated;
6582 int num_saves = XVECLEN (operands[2], 0);
6584 if (lr_save_eliminated)
6589 /* For the StrongARM at least it is faster to
6590 use STR to store only a single register. */
6591 else if (num_saves == 1)
6592 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
6598 if (lr_save_eliminated)
6601 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
6603 for (i = 1; i < num_saves; i++)
6605 strcat (pattern, \", %|\");
6606 strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
6610 strcat (pattern, \"}\");
6611 output_asm_insn (pattern, operands);
6616 [(set_attr "type" "store4")])
6618 ;; Similarly for the floating point registers
6619 (define_insn "*push_fp_multi"
6620 [(match_parallel 2 "multi_register_push"
6621 [(set (match_operand:BLK 0 "memory_operand" "=m")
6622 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
6628 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
6629 output_asm_insn (pattern, operands);
6632 [(set_attr "type" "f_store")])
6634 ;; Special patterns for dealing with the constant pool
6636 (define_insn "consttable_4"
6637 [(unspec_volatile [(match_operand 0 "" "")] 2)]
6641 making_const_table = TRUE;
6642 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6646 union real_extract u;
6647 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6648 assemble_real (u.d, GET_MODE (operands[0]));
6652 assemble_integer (operands[0], 4, 1);
6657 [(set_attr "length" "4")])
6659 (define_insn "consttable_8"
6660 [(unspec_volatile [(match_operand 0 "" "")] 3)]
6664 making_const_table = TRUE;
6665 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6669 union real_extract u;
6670 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6671 assemble_real (u.d, GET_MODE (operands[0]));
6675 assemble_integer (operands[0], 8, 1);
6680 [(set_attr "length" "8")])
6682 (define_insn "consttable_end"
6683 [(unspec_volatile [(const_int 0)] 4)]
6686 making_const_table = FALSE;
6690 (define_insn "align_4"
6691 [(unspec_volatile [(const_int 0)] 5)]
6694 assemble_align (32);