1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000, 2001
3 ;; Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GNU CC.
10 ;; GNU CC is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; GNU CC is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU CC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
27 ;; There are patterns in this file to support XFmode arithmetic.
28 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
31 ;;---------------------------------------------------------------------------
36 [(IP_REGNUM 12) ; Scratch register
37 (SP_REGNUM 13) ; Stack pointer
38 (LR_REGNUM 14) ; Return address register
39 (PC_REGNUM 15) ; Program counter
40 (CC_REGNUM 24) ; Condition code pseudo register
46 ;; Note: sin and cos are no-longer used.
49 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
50 ; operand 0 is the result,
51 ; operand 1 the parameter.
52 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
53 ; operand 0 is the result,
54 ; operand 1 the parameter.
55 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
56 ; operand 0 is the first register,
57 ; subsequent registers are in parallel (use ...)
59 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
60 ; usage, that is, we will add the pic_register
61 ; value to it before trying to dereference it.
62 (UNSPEC_PRLG_STK 4) ; A special barrier that prevents frame accesses
63 ; being scheduled before the stack adjustment insn.
64 (UNSPEC_CLZ 5) ; `clz' instruction, count leading zeros (SImode):
65 ; operand 0 is the result,
66 ; operand 1 is the parameter.
70 ;; UNSPEC_VOLATILE Usage:
73 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
75 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
76 ; instruction epilogue sequence that isn't expanded
77 ; into normal RTL. Used for both normal and sibcall
79 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
80 ; for inlined constants.
81 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
83 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
85 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
87 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
89 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
91 (VUNSPEC_PREFETCH 8) ; `pld' insn to prefetch a cache line:
92 ; operand 0 is the address to fetch.
96 ;;---------------------------------------------------------------------------
99 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
100 ; generating ARM code. This is used to control the length of some insn
101 ; patterns that share the same RTL in both ARM and Thumb code.
102 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
104 ; PROG_MODE attribute is used to determine whether condition codes are
105 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
106 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
107 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
109 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
110 ; scheduling decisions for the load unit and the multiplier.
111 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
113 ;; Operand number of an input operand that is shifted. Zero if the
114 ;; given instruction does not shift one of its input operands.
115 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_is_xscale")))
116 (define_attr "shift" "" (const_int 0))
118 ; Floating Point Unit. If we only have floating point emulation, then there
119 ; is no point in scheduling the floating point insns. (Well, for best
120 ; performance we should try and group them together).
121 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
123 ; LENGTH of an instruction (in bytes)
124 (define_attr "length" "" (const_int 4))
126 ; POOL_RANGE is how far away from a constant pool entry that this insn
127 ; can be placed. If the distance is zero, then this insn will never
128 ; reference the pool.
129 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
130 ; before its address.
131 (define_attr "pool_range" "" (const_int 0))
132 (define_attr "neg_pool_range" "" (const_int 0))
134 ; An assembler sequence may clobber the condition codes without us knowing.
135 (define_asm_attributes
136 [(set_attr "conds" "clob")])
138 ; TYPE attribute is used to detect floating point instructions which, if
139 ; running on a co-processor can run in parallel with other, basic instructions
140 ; If write-buffer scheduling is enabled then it can also be used in the
141 ; scheduling of writes.
143 ; Classification of each insn
144 ; normal any data instruction that doesn't hit memory or fp regs
145 ; mult a multiply instruction
146 ; block blockage insn, this blocks all functional units
147 ; float a floating point arithmetic operation (subject to expansion)
148 ; fdivx XFmode floating point division
149 ; fdivd DFmode floating point division
150 ; fdivs SFmode floating point division
151 ; fmul Floating point multiply
152 ; ffmul Fast floating point multiply
153 ; farith Floating point arithmetic (4 cycle)
154 ; ffarith Fast floating point arithmetic (2 cycle)
155 ; float_em a floating point arithmetic operation that is normally emulated
156 ; even on a machine with an fpa.
157 ; f_load a floating point load from memory
158 ; f_store a floating point store to memory
159 ; f_mem_r a transfer of a floating point register to a real reg via mem
160 ; r_mem_f the reverse of f_mem_r
161 ; f_2_r fast transfer float to arm (no memory needed)
162 ; r_2_f fast transfer arm to float
163 ; call a subroutine call
164 ; load any load from memory
165 ; store1 store 1 word to memory from arm registers
166 ; store2 store 2 words
167 ; store3 store 3 words
168 ; store4 store 4 words
171 "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"
172 (const_string "normal"))
174 ; Load scheduling, set from the arm_ld_sched variable
175 ; initialised by arm_override_options()
176 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
178 ; condition codes: this one is used by final_prescan_insn to speed up
179 ; conditionalizing instructions. It saves having to scan the rtl to see if
180 ; it uses or alters the condition codes.
182 ; USE means that the condition codes are used by the insn in the process of
183 ; outputting code, this means (at present) that we can't use the insn in
186 ; SET means that the purpose of the insn is to set the condition codes in a
187 ; well defined manner.
189 ; CLOB means that the condition codes are altered in an undefined manner, if
190 ; they are altered at all
192 ; JUMP_CLOB is used when the condition cannot be represented by a single
193 ; instruction (UNEQ and LTGT). These cannot be predicated.
195 ; NOCOND means that the condition codes are neither altered nor affect the
196 ; output of this insn
198 (define_attr "conds" "use,set,clob,jump_clob,nocond"
199 (if_then_else (eq_attr "type" "call")
200 (if_then_else (eq_attr "prog_mode" "prog32")
201 (const_string "clob") (const_string "nocond"))
202 (const_string "nocond")))
204 ; Predicable means that the insn can be conditionally executed based on
205 ; an automatically added predicate (additional patterns are generated by
206 ; gen...). We default to 'no' because no Thumb patterns match this rule
207 ; and not all ARM patterns do.
208 (define_attr "predicable" "no,yes" (const_string "no"))
210 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
211 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
212 ; suffer blockages enough to warrent modelling this (and it can adversely
213 ; affect the schedule).
214 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
216 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
217 ; to stall the processor. Used with model_wbuf above.
218 (define_attr "write_conflict" "no,yes"
219 (if_then_else (eq_attr "type"
220 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
222 (const_string "no")))
224 ; Classify the insns into those that take one cycle and those that take more
225 ; than one on the main cpu execution unit.
226 (define_attr "core_cycles" "single,multi"
227 (if_then_else (eq_attr "type"
228 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
229 (const_string "single")
230 (const_string "multi")))
232 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
233 ;; distant label. Only applicable to Thumb code.
234 (define_attr "far_jump" "yes,no" (const_string "no"))
236 ;; (define_function_unit {name} {num-units} {n-users} {test}
237 ;; {ready-delay} {issue-delay} [{conflict-list}])
239 ;;--------------------------------------------------------------------
240 ;; Floating point unit (FPA)
241 ;;--------------------------------------------------------------------
242 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
243 (eq_attr "type" "fdivx")) 71 69)
245 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
246 (eq_attr "type" "fdivd")) 59 57)
248 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
249 (eq_attr "type" "fdivs")) 31 29)
251 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
252 (eq_attr "type" "fmul")) 9 7)
254 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
255 (eq_attr "type" "ffmul")) 6 4)
257 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
258 (eq_attr "type" "farith")) 4 2)
260 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
261 (eq_attr "type" "ffarith")) 2 2)
263 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
264 (eq_attr "type" "r_2_f")) 5 3)
266 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
267 (eq_attr "type" "f_2_r")) 1 2)
269 ; The fpa10 doesn't really have a memory read unit, but it can start to
270 ; speculatively execute the instruction in the pipeline, provided the data
271 ; is already loaded, so pretend reads have a delay of 2 (and that the
272 ; pipeline is infinite).
274 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
275 (eq_attr "type" "f_load")) 3 1)
277 ;;--------------------------------------------------------------------
279 ;;--------------------------------------------------------------------
280 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
282 ; The write buffer on some of the arm6 processors is hard to model exactly.
283 ; There is room in the buffer for up to two addresses and up to eight words
284 ; of memory, but the two needn't be split evenly. When writing the two
285 ; addresses are fully pipelined. However, a read from memory that is not
286 ; currently in the cache will block until the writes have completed.
287 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
288 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
289 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
290 ; cycle to add as well.
292 (define_function_unit "write_buf" 1 2
293 (and (eq_attr "model_wbuf" "yes")
294 (eq_attr "type" "store1,r_mem_f")) 5 3)
295 (define_function_unit "write_buf" 1 2
296 (and (eq_attr "model_wbuf" "yes")
297 (eq_attr "type" "store2")) 7 4)
298 (define_function_unit "write_buf" 1 2
299 (and (eq_attr "model_wbuf" "yes")
300 (eq_attr "type" "store3")) 9 5)
301 (define_function_unit "write_buf" 1 2
302 (and (eq_attr "model_wbuf" "yes")
303 (eq_attr "type" "store4")) 11 6)
305 ;;--------------------------------------------------------------------
306 ;; Write blockage unit
307 ;;--------------------------------------------------------------------
308 ; The write_blockage unit models (partially), the fact that reads will stall
309 ; until the write buffer empties.
310 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
311 ; so we don't model them here
312 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
313 (eq_attr "type" "store1")) 5 5
314 [(eq_attr "write_conflict" "yes")])
315 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
316 (eq_attr "type" "store2")) 7 7
317 [(eq_attr "write_conflict" "yes")])
318 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
319 (eq_attr "type" "store3")) 9 9
320 [(eq_attr "write_conflict" "yes")])
321 (define_function_unit "write_blockage" 1 0
322 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
323 [(eq_attr "write_conflict" "yes")])
324 (define_function_unit "write_blockage" 1 0
325 (and (eq_attr "model_wbuf" "yes")
326 (eq_attr "write_conflict" "yes")) 1 1)
328 ;;--------------------------------------------------------------------
330 ;;--------------------------------------------------------------------
331 ; Everything must spend at least one cycle in the core unit
332 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
334 (define_function_unit "core" 1 0
335 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
337 (define_function_unit "core" 1 0
338 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
340 ;; We do not need to conditionalize the define_function_unit immediately
341 ;; above. This one will be ignored for anything other than xscale
342 ;; compiles and for xscale compiles it provides a larger delay
343 ;; and the scheduler will DTRT.
344 ;; FIXME: this test needs to be revamped to not depend on this feature
347 (define_function_unit "core" 1 0
348 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
349 (eq_attr "is_xscale" "yes"))
352 (define_function_unit "core" 1 0
353 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
355 (define_function_unit "core" 1 0
356 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
358 (define_function_unit "core" 1 0
359 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
361 (define_function_unit "core" 1 0
362 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
364 (define_function_unit "core" 1 0
365 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
367 (define_function_unit "core" 1 0
368 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
370 (define_function_unit "core" 1 0
371 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
372 (eq_attr "type" "mult")) 4 4)
374 (define_function_unit "core" 1 0
375 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
376 (eq_attr "type" "mult")) 3 2)
378 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
380 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
382 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
384 (define_function_unit "core" 1 0
385 (and (eq_attr "core_cycles" "multi")
386 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
388 ;;---------------------------------------------------------------------------
393 ;; Note: For DImode insns, there is normally no reason why operands should
394 ;; not be in the same register, what we don't want is for something being
395 ;; written to partially overlap something that is an input.
397 (define_expand "adddi3"
399 [(set (match_operand:DI 0 "s_register_operand" "")
400 (plus:DI (match_operand:DI 1 "s_register_operand" "")
401 (match_operand:DI 2 "s_register_operand" "")))
402 (clobber (reg:CC CC_REGNUM))])]
407 if (GET_CODE (operands[1]) != REG)
408 operands[1] = force_reg (SImode, operands[1]);
409 if (GET_CODE (operands[2]) != REG)
410 operands[2] = force_reg (SImode, operands[2]);
415 (define_insn "*thumb_adddi3"
416 [(set (match_operand:DI 0 "register_operand" "=l")
417 (plus:DI (match_operand:DI 1 "register_operand" "%0")
418 (match_operand:DI 2 "register_operand" "l")))
419 (clobber (reg:CC CC_REGNUM))
422 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
423 [(set_attr "length" "4")]
426 (define_insn_and_split "*arm_adddi3"
427 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
428 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
429 (match_operand:DI 2 "s_register_operand" "r, 0")))
430 (clobber (reg:CC CC_REGNUM))]
433 "TARGET_ARM && reload_completed"
434 [(parallel [(set (reg:CC_C CC_REGNUM)
435 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
437 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
438 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
439 (plus:SI (match_dup 4) (match_dup 5))))]
442 operands[3] = gen_highpart (SImode, operands[0]);
443 operands[0] = gen_lowpart (SImode, operands[0]);
444 operands[4] = gen_highpart (SImode, operands[1]);
445 operands[1] = gen_lowpart (SImode, operands[1]);
446 operands[5] = gen_highpart (SImode, operands[2]);
447 operands[2] = gen_lowpart (SImode, operands[2]);
449 [(set_attr "conds" "clob")
450 (set_attr "length" "8")]
453 (define_insn_and_split "*adddi_sesidi_di"
454 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
455 (plus:DI (sign_extend:DI
456 (match_operand:SI 2 "s_register_operand" "r,r"))
457 (match_operand:DI 1 "s_register_operand" "r,0")))
458 (clobber (reg:CC CC_REGNUM))]
461 "TARGET_ARM && reload_completed"
462 [(parallel [(set (reg:CC_C CC_REGNUM)
463 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
465 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
466 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
467 (plus:SI (ashiftrt:SI (match_dup 2)
472 operands[3] = gen_highpart (SImode, operands[0]);
473 operands[0] = gen_lowpart (SImode, operands[0]);
474 operands[4] = gen_highpart (SImode, operands[1]);
475 operands[1] = gen_lowpart (SImode, operands[1]);
476 operands[2] = gen_lowpart (SImode, operands[2]);
478 [(set_attr "conds" "clob")
479 (set_attr "length" "8")]
482 (define_insn_and_split "*adddi_zesidi_di"
483 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
484 (plus:DI (zero_extend:DI
485 (match_operand:SI 2 "s_register_operand" "r,r"))
486 (match_operand:DI 1 "s_register_operand" "r,0")))
487 (clobber (reg:CC CC_REGNUM))]
490 "TARGET_ARM && reload_completed"
491 [(parallel [(set (reg:CC_C CC_REGNUM)
492 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
494 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
495 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
496 (plus:SI (match_dup 4) (const_int 0))))]
499 operands[3] = gen_highpart (SImode, operands[0]);
500 operands[0] = gen_lowpart (SImode, operands[0]);
501 operands[4] = gen_highpart (SImode, operands[1]);
502 operands[1] = gen_lowpart (SImode, operands[1]);
503 operands[2] = gen_lowpart (SImode, operands[2]);
505 [(set_attr "conds" "clob")
506 (set_attr "length" "8")]
509 (define_expand "addsi3"
510 [(set (match_operand:SI 0 "s_register_operand" "")
511 (plus:SI (match_operand:SI 1 "s_register_operand" "")
512 (match_operand:SI 2 "reg_or_int_operand" "")))]
515 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
517 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
519 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
525 ; If there is a scratch available, this will be faster than synthesising the
528 [(match_scratch:SI 3 "r")
529 (set (match_operand:SI 0 "s_register_operand" "")
530 (plus:SI (match_operand:SI 1 "s_register_operand" "")
531 (match_operand:SI 2 "const_int_operand" "")))]
533 !(const_ok_for_arm (INTVAL (operands[2]))
534 || const_ok_for_arm (-INTVAL (operands[2])))
535 && const_ok_for_arm (~INTVAL (operands[2]))"
536 [(set (match_dup 3) (match_dup 2))
537 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
541 (define_insn_and_split "*arm_addsi3"
542 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
543 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
544 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
551 GET_CODE (operands[2]) == CONST_INT
552 && !(const_ok_for_arm (INTVAL (operands[2]))
553 || const_ok_for_arm (-INTVAL (operands[2])))"
554 [(clobber (const_int 0))]
556 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
560 [(set_attr "length" "4,4,16")
561 (set_attr "predicable" "yes")]
564 ;; Register group 'k' is a single register group containing only the stack
565 ;; register. Trying to reload it will always fail catastrophically,
566 ;; so never allow those alternatives to match if reloading is needed.
568 (define_insn "*thumb_addsi3"
569 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
570 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
571 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
574 static const char * const asms[] =
576 \"add\\t%0, %0, %2\",
577 \"sub\\t%0, %0, #%n2\",
578 \"add\\t%0, %1, %2\",
579 \"add\\t%0, %0, %2\",
580 \"add\\t%0, %0, %2\",
581 \"add\\t%0, %1, %2\",
584 if ((which_alternative == 2 || which_alternative == 6)
585 && GET_CODE (operands[2]) == CONST_INT
586 && INTVAL (operands[2]) < 0)
587 return \"sub\\t%0, %1, #%n2\";
588 return asms[which_alternative];
590 [(set_attr "length" "2")]
593 ;; Reloading and elimination of the frame pointer can
594 ;; sometimes cause this optimization to be missed.
596 [(set (match_operand:SI 0 "register_operand" "=l")
597 (match_operand:SI 1 "const_int_operand" "M"))
599 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
601 && REGNO (operands[2]) == STACK_POINTER_REGNUM
602 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
603 && (INTVAL (operands[1]) & 3) == 0"
604 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
608 (define_insn "*addsi3_compare0"
609 [(set (reg:CC_NOOV CC_REGNUM)
611 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
612 (match_operand:SI 2 "arm_add_operand" "rI,L"))
614 (set (match_operand:SI 0 "s_register_operand" "=r,r")
615 (plus:SI (match_dup 1) (match_dup 2)))]
619 sub%?s\\t%0, %1, #%n2"
620 [(set_attr "conds" "set")]
623 (define_insn "*addsi3_compare0_scratch"
624 [(set (reg:CC_NOOV CC_REGNUM)
626 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
627 (match_operand:SI 1 "arm_add_operand" "rI,L"))
633 [(set_attr "conds" "set")]
636 ;; These patterns are the same ones as the two regular addsi3_compare0
637 ;; patterns, except we write them slightly different - the combiner
638 ;; tends to generate them this way.
639 (define_insn "*addsi3_compare0_for_combiner"
640 [(set (reg:CC CC_REGNUM)
642 (match_operand:SI 1 "s_register_operand" "r,r")
643 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
644 (set (match_operand:SI 0 "s_register_operand" "=r,r")
645 (plus:SI (match_dup 1) (match_dup 2)))]
649 sub%?s\\t%0, %1, #%n2"
650 [(set_attr "conds" "set")]
653 (define_insn "*addsi3_compare0_scratch_for_combiner"
654 [(set (reg:CC CC_REGNUM)
656 (match_operand:SI 0 "s_register_operand" "r,r")
657 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
662 [(set_attr "conds" "set")]
665 ;; The next four insns work because they compare the result with one of
666 ;; the operands, and we know that the use of the condition code is
667 ;; either GEU or LTU, so we can use the carry flag from the addition
668 ;; instead of doing the compare a second time.
669 (define_insn "*addsi3_compare_op1"
670 [(set (reg:CC_C CC_REGNUM)
672 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
673 (match_operand:SI 2 "arm_add_operand" "rI,L"))
675 (set (match_operand:SI 0 "s_register_operand" "=r,r")
676 (plus:SI (match_dup 1) (match_dup 2)))]
680 sub%?s\\t%0, %1, #%n2"
681 [(set_attr "conds" "set")]
684 (define_insn "*addsi3_compare_op2"
685 [(set (reg:CC_C CC_REGNUM)
687 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
688 (match_operand:SI 2 "arm_add_operand" "rI,L"))
690 (set (match_operand:SI 0 "s_register_operand" "=r,r")
691 (plus:SI (match_dup 1) (match_dup 2)))]
695 sub%?s\\t%0, %1, #%n2"
696 [(set_attr "conds" "set")]
699 (define_insn "*compare_addsi2_op0"
700 [(set (reg:CC_C CC_REGNUM)
702 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
703 (match_operand:SI 1 "arm_add_operand" "rI,L"))
709 [(set_attr "conds" "set")]
712 (define_insn "*compare_addsi2_op1"
713 [(set (reg:CC_C CC_REGNUM)
715 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
716 (match_operand:SI 1 "arm_add_operand" "rI,L"))
722 [(set_attr "conds" "set")]
725 (define_insn "*addsi3_carryin"
726 [(set (match_operand:SI 0 "s_register_operand" "=r")
727 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
728 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
729 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
732 [(set_attr "conds" "use")]
735 (define_insn "*addsi3_carryin_shift"
736 [(set (match_operand:SI 0 "s_register_operand" "")
737 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
739 (match_operator:SI 2 "shift_operator"
740 [(match_operand:SI 3 "s_register_operand" "")
741 (match_operand:SI 4 "reg_or_int_operand" "")])
742 (match_operand:SI 1 "s_register_operand" ""))))]
744 "adc%?\\t%0, %1, %3%S2"
745 [(set_attr "conds" "use")]
748 (define_insn "*addsi3_carryin_alt1"
749 [(set (match_operand:SI 0 "s_register_operand" "=r")
750 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
751 (match_operand:SI 2 "arm_rhs_operand" "rI"))
752 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
755 [(set_attr "conds" "use")]
758 (define_insn "*addsi3_carryin_alt2"
759 [(set (match_operand:SI 0 "s_register_operand" "=r")
760 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
761 (match_operand:SI 1 "s_register_operand" "r"))
762 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
765 [(set_attr "conds" "use")]
768 (define_insn "*addsi3_carryin_alt3"
769 [(set (match_operand:SI 0 "s_register_operand" "=r")
770 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
771 (match_operand:SI 2 "arm_rhs_operand" "rI"))
772 (match_operand:SI 1 "s_register_operand" "r")))]
775 [(set_attr "conds" "use")]
778 (define_insn "incscc"
779 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
780 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
781 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
782 (match_operand:SI 1 "s_register_operand" "0,?r")))]
786 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
787 [(set_attr "conds" "use")
788 (set_attr "length" "4,8")]
791 (define_insn "addsf3"
792 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
793 (plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
794 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
795 "TARGET_ARM && TARGET_HARD_FLOAT"
798 suf%?s\\t%0, %1, #%N2"
799 [(set_attr "type" "farith")
800 (set_attr "predicable" "yes")]
803 (define_insn "adddf3"
804 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
805 (plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
806 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
807 "TARGET_ARM && TARGET_HARD_FLOAT"
810 suf%?d\\t%0, %1, #%N2"
811 [(set_attr "type" "farith")
812 (set_attr "predicable" "yes")]
815 (define_insn "*adddf_esfdf_df"
816 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
817 (plus:DF (float_extend:DF
818 (match_operand:SF 1 "s_register_operand" "f,f"))
819 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
820 "TARGET_ARM && TARGET_HARD_FLOAT"
823 suf%?d\\t%0, %1, #%N2"
824 [(set_attr "type" "farith")
825 (set_attr "predicable" "yes")]
828 (define_insn "*adddf_df_esfdf"
829 [(set (match_operand:DF 0 "s_register_operand" "=f")
830 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
832 (match_operand:SF 2 "s_register_operand" "f"))))]
833 "TARGET_ARM && TARGET_HARD_FLOAT"
834 "adf%?d\\t%0, %1, %2"
835 [(set_attr "type" "farith")
836 (set_attr "predicable" "yes")]
839 (define_insn "*adddf_esfdf_esfdf"
840 [(set (match_operand:DF 0 "s_register_operand" "=f")
841 (plus:DF (float_extend:DF
842 (match_operand:SF 1 "s_register_operand" "f"))
844 (match_operand:SF 2 "s_register_operand" "f"))))]
845 "TARGET_ARM && TARGET_HARD_FLOAT"
846 "adf%?d\\t%0, %1, %2"
847 [(set_attr "type" "farith")
848 (set_attr "predicable" "yes")]
851 (define_insn "addxf3"
852 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
853 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
854 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
855 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
858 suf%?e\\t%0, %1, #%N2"
859 [(set_attr "type" "farith")
860 (set_attr "predicable" "yes")]
863 (define_expand "subdi3"
865 [(set (match_operand:DI 0 "s_register_operand" "")
866 (minus:DI (match_operand:DI 1 "s_register_operand" "")
867 (match_operand:DI 2 "s_register_operand" "")))
868 (clobber (reg:CC CC_REGNUM))])]
873 if (GET_CODE (operands[1]) != REG)
874 operands[1] = force_reg (SImode, operands[1]);
875 if (GET_CODE (operands[2]) != REG)
876 operands[2] = force_reg (SImode, operands[2]);
881 (define_insn "*arm_subdi3"
882 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
883 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
884 (match_operand:DI 2 "s_register_operand" "r,0,0")))
885 (clobber (reg:CC CC_REGNUM))]
887 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
888 [(set_attr "conds" "clob")
889 (set_attr "length" "8")]
892 (define_insn "*thumb_subdi3"
893 [(set (match_operand:DI 0 "register_operand" "=l")
894 (minus:DI (match_operand:DI 1 "register_operand" "0")
895 (match_operand:DI 2 "register_operand" "l")))
896 (clobber (reg:CC CC_REGNUM))]
898 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
899 [(set_attr "length" "4")]
902 (define_insn "*subdi_di_zesidi"
903 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
904 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
906 (match_operand:SI 2 "s_register_operand" "r,r"))))
907 (clobber (reg:CC CC_REGNUM))]
909 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
910 [(set_attr "conds" "clob")
911 (set_attr "length" "8")]
914 (define_insn "*subdi_di_sesidi"
915 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
916 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
918 (match_operand:SI 2 "s_register_operand" "r,r"))))
919 (clobber (reg:CC CC_REGNUM))]
921 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
922 [(set_attr "conds" "clob")
923 (set_attr "length" "8")]
926 (define_insn "*subdi_zesidi_di"
927 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
928 (minus:DI (zero_extend:DI
929 (match_operand:SI 2 "s_register_operand" "r,r"))
930 (match_operand:DI 1 "s_register_operand" "?r,0")))
931 (clobber (reg:CC CC_REGNUM))]
933 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
934 [(set_attr "conds" "clob")
935 (set_attr "length" "8")]
938 (define_insn "*subdi_sesidi_di"
939 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
940 (minus:DI (sign_extend:DI
941 (match_operand:SI 2 "s_register_operand" "r,r"))
942 (match_operand:DI 1 "s_register_operand" "?r,0")))
943 (clobber (reg:CC CC_REGNUM))]
945 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
946 [(set_attr "conds" "clob")
947 (set_attr "length" "8")]
950 (define_insn "*subdi_zesidi_zesidi"
951 [(set (match_operand:DI 0 "s_register_operand" "=r")
952 (minus:DI (zero_extend:DI
953 (match_operand:SI 1 "s_register_operand" "r"))
955 (match_operand:SI 2 "s_register_operand" "r"))))
956 (clobber (reg:CC CC_REGNUM))]
958 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
959 [(set_attr "conds" "clob")
960 (set_attr "length" "8")]
963 (define_expand "subsi3"
964 [(set (match_operand:SI 0 "s_register_operand" "")
965 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
966 (match_operand:SI 2 "s_register_operand" "")))]
969 if (GET_CODE (operands[1]) == CONST_INT)
973 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
976 : preserve_subexpressions_p ()));
979 else /* TARGET_THUMB */
980 operands[1] = force_reg (SImode, operands[1]);
985 (define_insn "*thumb_subsi3_insn"
986 [(set (match_operand:SI 0 "register_operand" "=l")
987 (minus:SI (match_operand:SI 1 "register_operand" "l")
988 (match_operand:SI 2 "register_operand" "l")))]
991 [(set_attr "length" "2")]
994 (define_insn_and_split "*arm_subsi3_insn"
995 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
996 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
997 (match_operand:SI 2 "s_register_operand" "r,r")))]
1003 && GET_CODE (operands[1]) == CONST_INT
1004 && !const_ok_for_arm (INTVAL (operands[1]))"
1005 [(clobber (const_int 0))]
1007 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1011 [(set_attr "length" "4,16")
1012 (set_attr "predicable" "yes")]
1016 [(match_scratch:SI 3 "r")
1017 (set (match_operand:SI 0 "s_register_operand" "")
1018 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1019 (match_operand:SI 2 "s_register_operand" "")))]
1021 && !const_ok_for_arm (INTVAL (operands[1]))
1022 && const_ok_for_arm (~INTVAL (operands[1]))"
1023 [(set (match_dup 3) (match_dup 1))
1024 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1028 (define_insn "*subsi3_compare0"
1029 [(set (reg:CC_NOOV CC_REGNUM)
1031 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1032 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1034 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1035 (minus:SI (match_dup 1) (match_dup 2)))]
1039 rsb%?s\\t%0, %2, %1"
1040 [(set_attr "conds" "set")]
1043 (define_insn "decscc"
1044 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1045 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1046 (match_operator:SI 2 "arm_comparison_operator"
1047 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1051 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1052 [(set_attr "conds" "use")
1053 (set_attr "length" "*,8")]
1056 (define_insn "subsf3"
1057 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1058 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1059 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1060 "TARGET_ARM && TARGET_HARD_FLOAT"
1063 rsf%?s\\t%0, %2, %1"
1064 [(set_attr "type" "farith")]
1067 (define_insn "subdf3"
1068 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1069 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1070 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1071 "TARGET_ARM && TARGET_HARD_FLOAT"
1074 rsf%?d\\t%0, %2, %1"
1075 [(set_attr "type" "farith")
1076 (set_attr "predicable" "yes")]
1079 (define_insn "*subdf_esfdf_df"
1080 [(set (match_operand:DF 0 "s_register_operand" "=f")
1081 (minus:DF (float_extend:DF
1082 (match_operand:SF 1 "s_register_operand" "f"))
1083 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1084 "TARGET_ARM && TARGET_HARD_FLOAT"
1085 "suf%?d\\t%0, %1, %2"
1086 [(set_attr "type" "farith")
1087 (set_attr "predicable" "yes")]
1090 (define_insn "*subdf_df_esfdf"
1091 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1092 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1094 (match_operand:SF 2 "s_register_operand" "f,f"))))]
1095 "TARGET_ARM && TARGET_HARD_FLOAT"
1098 rsf%?d\\t%0, %2, %1"
1099 [(set_attr "type" "farith")
1100 (set_attr "predicable" "yes")]
1103 (define_insn "*subdf_esfdf_esfdf"
1104 [(set (match_operand:DF 0 "s_register_operand" "=f")
1105 (minus:DF (float_extend:DF
1106 (match_operand:SF 1 "s_register_operand" "f"))
1108 (match_operand:SF 2 "s_register_operand" "f"))))]
1109 "TARGET_ARM && TARGET_HARD_FLOAT"
1110 "suf%?d\\t%0, %1, %2"
1111 [(set_attr "type" "farith")
1112 (set_attr "predicable" "yes")]
1115 (define_insn "subxf3"
1116 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1117 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1118 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1119 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1122 rsf%?e\\t%0, %2, %1"
1123 [(set_attr "type" "farith")
1124 (set_attr "predicable" "yes")]
1127 ;; Multiplication insns
1129 (define_expand "mulsi3"
1130 [(set (match_operand:SI 0 "s_register_operand" "")
1131 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1132 (match_operand:SI 1 "s_register_operand" "")))]
1137 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1138 (define_insn "*arm_mulsi3"
1139 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1140 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1141 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1143 "mul%?\\t%0, %2, %1"
1144 [(set_attr "type" "mult")
1145 (set_attr "predicable" "yes")]
1148 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1149 ; 1 and 2; are the same, because reload will make operand 0 match
1150 ; operand 1 without realizing that this conflicts with operand 2. We fix
1151 ; this by adding another alternative to match this case, and then `reload'
1152 ; it ourselves. This alternative must come first.
1153 (define_insn "*thumb_mulsi3"
1154 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1155 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1156 (match_operand:SI 2 "register_operand" "l,l,l")))]
1159 if (which_alternative < 2)
1160 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1162 return \"mul\\t%0, %0, %2\";
1164 [(set_attr "length" "4,4,2")
1165 (set_attr "type" "mult")]
1168 (define_insn "*mulsi3_compare0"
1169 [(set (reg:CC_NOOV CC_REGNUM)
1170 (compare:CC_NOOV (mult:SI
1171 (match_operand:SI 2 "s_register_operand" "r,r")
1172 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1174 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1175 (mult:SI (match_dup 2) (match_dup 1)))]
1176 "TARGET_ARM && !arm_is_xscale"
1177 "mul%?s\\t%0, %2, %1"
1178 [(set_attr "conds" "set")
1179 (set_attr "type" "mult")]
1182 (define_insn "*mulsi_compare0_scratch"
1183 [(set (reg:CC_NOOV CC_REGNUM)
1184 (compare:CC_NOOV (mult:SI
1185 (match_operand:SI 2 "s_register_operand" "r,r")
1186 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1188 (clobber (match_scratch:SI 0 "=&r,&r"))]
1189 "TARGET_ARM && !arm_is_xscale"
1190 "mul%?s\\t%0, %2, %1"
1191 [(set_attr "conds" "set")
1192 (set_attr "type" "mult")]
1195 ;; Unnamed templates to match MLA instruction.
1197 (define_insn "*mulsi3addsi"
1198 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1200 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1201 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1202 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1204 "mla%?\\t%0, %2, %1, %3"
1205 [(set_attr "type" "mult")
1206 (set_attr "predicable" "yes")]
1209 (define_insn "*mulsi3addsi_compare0"
1210 [(set (reg:CC_NOOV CC_REGNUM)
1213 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1214 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1215 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1217 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1218 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1220 "TARGET_ARM && !arm_is_xscale"
1221 "mla%?s\\t%0, %2, %1, %3"
1222 [(set_attr "conds" "set")
1223 (set_attr "type" "mult")]
1226 (define_insn "*mulsi3addsi_compare0_scratch"
1227 [(set (reg:CC_NOOV CC_REGNUM)
1230 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1231 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1232 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1234 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1235 "TARGET_ARM && !arm_is_xscale"
1236 "mla%?s\\t%0, %2, %1, %3"
1237 [(set_attr "conds" "set")
1238 (set_attr "type" "mult")]
1241 ;; Unnamed template to match long long multiply-accumlate (smlal)
1243 (define_insn "*mulsidi3adddi"
1244 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1247 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1248 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1249 (match_operand:DI 1 "s_register_operand" "0")))]
1250 "TARGET_ARM && arm_fast_multiply"
1251 "smlal%?\\t%Q0, %R0, %3, %2"
1252 [(set_attr "type" "mult")
1253 (set_attr "predicable" "yes")]
1256 (define_insn "mulsidi3"
1257 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1259 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1260 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1261 "TARGET_ARM && arm_fast_multiply"
1262 "smull%?\\t%Q0, %R0, %1, %2"
1263 [(set_attr "type" "mult")
1264 (set_attr "predicable" "yes")]
1267 (define_insn "umulsidi3"
1268 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1270 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1271 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1272 "TARGET_ARM && arm_fast_multiply"
1273 "umull%?\\t%Q0, %R0, %1, %2"
1274 [(set_attr "type" "mult")
1275 (set_attr "predicable" "yes")]
1278 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1280 (define_insn "*umulsidi3adddi"
1281 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1284 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1285 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1286 (match_operand:DI 1 "s_register_operand" "0")))]
1287 "TARGET_ARM && arm_fast_multiply"
1288 "umlal%?\\t%Q0, %R0, %3, %2"
1289 [(set_attr "type" "mult")
1290 (set_attr "predicable" "yes")]
1293 (define_insn "smulsi3_highpart"
1294 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1298 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1299 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1301 (clobber (match_scratch:SI 3 "=&r,&r"))]
1302 "TARGET_ARM && arm_fast_multiply"
1303 "smull%?\\t%3, %0, %2, %1"
1304 [(set_attr "type" "mult")
1305 (set_attr "predicable" "yes")]
1308 (define_insn "umulsi3_highpart"
1309 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1313 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1314 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1316 (clobber (match_scratch:SI 3 "=&r,&r"))]
1317 "TARGET_ARM && arm_fast_multiply"
1318 "umull%?\\t%3, %0, %2, %1"
1319 [(set_attr "type" "mult")
1320 (set_attr "predicable" "yes")]
1323 (define_insn "mulhisi3"
1324 [(set (match_operand:SI 0 "s_register_operand" "=r")
1325 (mult:SI (sign_extend:SI
1326 (match_operand:HI 1 "s_register_operand" "%r"))
1328 (match_operand:HI 2 "s_register_operand" "r"))))]
1329 "TARGET_ARM && arm_is_xscale"
1330 "smulbb%?\\t%0, %1, %2"
1331 [(set_attr "type" "mult")]
1334 (define_insn "*mulhisi3addsi"
1335 [(set (match_operand:SI 0 "s_register_operand" "=r")
1336 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1337 (mult:SI (sign_extend:SI
1338 (match_operand:HI 2 "s_register_operand" "%r"))
1340 (match_operand:HI 3 "s_register_operand" "r")))))]
1341 "TARGET_ARM && arm_is_xscale"
1342 "smlabb%?\\t%0, %2, %3, %1"
1343 [(set_attr "type" "mult")]
1346 (define_insn "*mulhidi3adddi"
1347 [(set (match_operand:DI 0 "s_register_operand" "=r")
1349 (match_operand:DI 1 "s_register_operand" "0")
1350 (mult:DI (sign_extend:DI
1351 (match_operand:HI 2 "s_register_operand" "%r"))
1353 (match_operand:HI 3 "s_register_operand" "r")))))]
1354 "TARGET_ARM && arm_is_xscale"
1355 "smlalbb%?\\t%Q0, %R0, %2, %3"
1356 [(set_attr "type" "mult")])
1358 (define_insn "mulsf3"
1359 [(set (match_operand:SF 0 "s_register_operand" "=f")
1360 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1361 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1362 "TARGET_ARM && TARGET_HARD_FLOAT"
1363 "fml%?s\\t%0, %1, %2"
1364 [(set_attr "type" "ffmul")
1365 (set_attr "predicable" "yes")]
1368 (define_insn "muldf3"
1369 [(set (match_operand:DF 0 "s_register_operand" "=f")
1370 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1371 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1372 "TARGET_ARM && TARGET_HARD_FLOAT"
1373 "muf%?d\\t%0, %1, %2"
1374 [(set_attr "type" "fmul")
1375 (set_attr "predicable" "yes")]
1378 (define_insn "*muldf_esfdf_df"
1379 [(set (match_operand:DF 0 "s_register_operand" "=f")
1380 (mult:DF (float_extend:DF
1381 (match_operand:SF 1 "s_register_operand" "f"))
1382 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1383 "TARGET_ARM && TARGET_HARD_FLOAT"
1384 "muf%?d\\t%0, %1, %2"
1385 [(set_attr "type" "fmul")
1386 (set_attr "predicable" "yes")]
1389 (define_insn "*muldf_df_esfdf"
1390 [(set (match_operand:DF 0 "s_register_operand" "=f")
1391 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1393 (match_operand:SF 2 "s_register_operand" "f"))))]
1394 "TARGET_ARM && TARGET_HARD_FLOAT"
1395 "muf%?d\\t%0, %1, %2"
1396 [(set_attr "type" "fmul")
1397 (set_attr "predicable" "yes")]
1400 (define_insn "*muldf_esfdf_esfdf"
1401 [(set (match_operand:DF 0 "s_register_operand" "=f")
1403 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
1404 (float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
1405 "TARGET_ARM && TARGET_HARD_FLOAT"
1406 "muf%?d\\t%0, %1, %2"
1407 [(set_attr "type" "fmul")
1408 (set_attr "predicable" "yes")]
1411 (define_insn "mulxf3"
1412 [(set (match_operand:XF 0 "s_register_operand" "=f")
1413 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1414 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1415 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1416 "muf%?e\\t%0, %1, %2"
1417 [(set_attr "type" "fmul")
1418 (set_attr "predicable" "yes")]
1423 (define_insn "divsf3"
1424 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1425 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1426 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1427 "TARGET_ARM && TARGET_HARD_FLOAT"
1430 frd%?s\\t%0, %2, %1"
1431 [(set_attr "type" "fdivs")
1432 (set_attr "predicable" "yes")]
1435 (define_insn "divdf3"
1436 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1437 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1438 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1439 "TARGET_ARM && TARGET_HARD_FLOAT"
1442 rdf%?d\\t%0, %2, %1"
1443 [(set_attr "type" "fdivd")
1444 (set_attr "predicable" "yes")]
1447 (define_insn "*divdf_esfdf_df"
1448 [(set (match_operand:DF 0 "s_register_operand" "=f")
1449 (div:DF (float_extend:DF
1450 (match_operand:SF 1 "s_register_operand" "f"))
1451 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1452 "TARGET_ARM && TARGET_HARD_FLOAT"
1453 "dvf%?d\\t%0, %1, %2"
1454 [(set_attr "type" "fdivd")
1455 (set_attr "predicable" "yes")]
1458 (define_insn "*divdf_df_esfdf"
1459 [(set (match_operand:DF 0 "s_register_operand" "=f")
1460 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1462 (match_operand:SF 2 "s_register_operand" "f"))))]
1463 "TARGET_ARM && TARGET_HARD_FLOAT"
1464 "rdf%?d\\t%0, %2, %1"
1465 [(set_attr "type" "fdivd")
1466 (set_attr "predicable" "yes")]
1469 (define_insn "*divdf_esfdf_esfdf"
1470 [(set (match_operand:DF 0 "s_register_operand" "=f")
1471 (div:DF (float_extend:DF
1472 (match_operand:SF 1 "s_register_operand" "f"))
1474 (match_operand:SF 2 "s_register_operand" "f"))))]
1475 "TARGET_ARM && TARGET_HARD_FLOAT"
1476 "dvf%?d\\t%0, %1, %2"
1477 [(set_attr "type" "fdivd")
1478 (set_attr "predicable" "yes")]
1481 (define_insn "divxf3"
1482 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1483 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1484 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1485 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1488 rdf%?e\\t%0, %2, %1"
1489 [(set_attr "type" "fdivx")
1490 (set_attr "predicable" "yes")]
1495 (define_insn "modsf3"
1496 [(set (match_operand:SF 0 "s_register_operand" "=f")
1497 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1498 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1499 "TARGET_ARM && TARGET_HARD_FLOAT"
1500 "rmf%?s\\t%0, %1, %2"
1501 [(set_attr "type" "fdivs")
1502 (set_attr "predicable" "yes")]
1505 (define_insn "moddf3"
1506 [(set (match_operand:DF 0 "s_register_operand" "=f")
1507 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1508 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1509 "TARGET_ARM && TARGET_HARD_FLOAT"
1510 "rmf%?d\\t%0, %1, %2"
1511 [(set_attr "type" "fdivd")
1512 (set_attr "predicable" "yes")]
1515 (define_insn "*moddf_esfdf_df"
1516 [(set (match_operand:DF 0 "s_register_operand" "=f")
1517 (mod:DF (float_extend:DF
1518 (match_operand:SF 1 "s_register_operand" "f"))
1519 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1520 "TARGET_ARM && TARGET_HARD_FLOAT"
1521 "rmf%?d\\t%0, %1, %2"
1522 [(set_attr "type" "fdivd")
1523 (set_attr "predicable" "yes")]
1526 (define_insn "*moddf_df_esfdf"
1527 [(set (match_operand:DF 0 "s_register_operand" "=f")
1528 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1530 (match_operand:SF 2 "s_register_operand" "f"))))]
1531 "TARGET_ARM && TARGET_HARD_FLOAT"
1532 "rmf%?d\\t%0, %1, %2"
1533 [(set_attr "type" "fdivd")
1534 (set_attr "predicable" "yes")]
1537 (define_insn "*moddf_esfdf_esfdf"
1538 [(set (match_operand:DF 0 "s_register_operand" "=f")
1539 (mod:DF (float_extend:DF
1540 (match_operand:SF 1 "s_register_operand" "f"))
1542 (match_operand:SF 2 "s_register_operand" "f"))))]
1543 "TARGET_ARM && TARGET_HARD_FLOAT"
1544 "rmf%?d\\t%0, %1, %2"
1545 [(set_attr "type" "fdivd")
1546 (set_attr "predicable" "yes")]
1549 (define_insn "modxf3"
1550 [(set (match_operand:XF 0 "s_register_operand" "=f")
1551 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1552 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1553 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1554 "rmf%?e\\t%0, %1, %2"
1555 [(set_attr "type" "fdivx")
1556 (set_attr "predicable" "yes")]
1559 ;; Boolean and,ior,xor insns
1561 ;; Split up double word logical operations
1563 ;; Split up simple DImode logical operations. Simply perform the logical
1564 ;; operation on the upper and lower halves of the registers.
1566 [(set (match_operand:DI 0 "s_register_operand" "")
1567 (match_operator:DI 6 "logical_binary_operator"
1568 [(match_operand:DI 1 "s_register_operand" "")
1569 (match_operand:DI 2 "s_register_operand" "")]))]
1570 "TARGET_ARM && reload_completed"
1571 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1572 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1575 operands[3] = gen_highpart (SImode, operands[0]);
1576 operands[0] = gen_lowpart (SImode, operands[0]);
1577 operands[4] = gen_highpart (SImode, operands[1]);
1578 operands[1] = gen_lowpart (SImode, operands[1]);
1579 operands[5] = gen_highpart (SImode, operands[2]);
1580 operands[2] = gen_lowpart (SImode, operands[2]);
1585 [(set (match_operand:DI 0 "s_register_operand" "")
1586 (match_operator:DI 6 "logical_binary_operator"
1587 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1588 (match_operand:DI 1 "s_register_operand" "")]))]
1589 "TARGET_ARM && reload_completed"
1590 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1591 (set (match_dup 3) (match_op_dup:SI 6
1592 [(ashiftrt:SI (match_dup 2) (const_int 31))
1596 operands[3] = gen_highpart (SImode, operands[0]);
1597 operands[0] = gen_lowpart (SImode, operands[0]);
1598 operands[4] = gen_highpart (SImode, operands[1]);
1599 operands[1] = gen_lowpart (SImode, operands[1]);
1600 operands[5] = gen_highpart (SImode, operands[2]);
1601 operands[2] = gen_lowpart (SImode, operands[2]);
1605 ;; The zero extend of operand 2 means we can just copy the high part of
1606 ;; operand1 into operand0.
1608 [(set (match_operand:DI 0 "s_register_operand" "")
1610 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1611 (match_operand:DI 1 "s_register_operand" "")))]
1612 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1613 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1614 (set (match_dup 3) (match_dup 4))]
1617 operands[4] = gen_highpart (SImode, operands[1]);
1618 operands[3] = gen_highpart (SImode, operands[0]);
1619 operands[0] = gen_lowpart (SImode, operands[0]);
1620 operands[1] = gen_lowpart (SImode, operands[1]);
1624 ;; The zero extend of operand 2 means we can just copy the high part of
1625 ;; operand1 into operand0.
1627 [(set (match_operand:DI 0 "s_register_operand" "")
1629 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1630 (match_operand:DI 1 "s_register_operand" "")))]
1631 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1632 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1633 (set (match_dup 3) (match_dup 4))]
1636 operands[4] = gen_highpart (SImode, operands[1]);
1637 operands[3] = gen_highpart (SImode, operands[0]);
1638 operands[0] = gen_lowpart (SImode, operands[0]);
1639 operands[1] = gen_lowpart (SImode, operands[1]);
1643 (define_insn "anddi3"
1644 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1645 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1646 (match_operand:DI 2 "s_register_operand" "r,r")))]
1649 [(set_attr "length" "8")]
1652 (define_insn_and_split "*anddi_zesidi_di"
1653 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1654 (and:DI (zero_extend:DI
1655 (match_operand:SI 2 "s_register_operand" "r,r"))
1656 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1659 "TARGET_ARM && reload_completed"
1660 ; The zero extend of operand 2 clears the high word of the output
1662 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1663 (set (match_dup 3) (const_int 0))]
1666 operands[3] = gen_highpart (SImode, operands[0]);
1667 operands[0] = gen_lowpart (SImode, operands[0]);
1668 operands[1] = gen_lowpart (SImode, operands[1]);
1670 [(set_attr "length" "8")]
1673 (define_insn "*anddi_sesdi_di"
1674 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1675 (and:DI (sign_extend:DI
1676 (match_operand:SI 2 "s_register_operand" "r,r"))
1677 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1680 [(set_attr "length" "8")]
1683 (define_expand "andsi3"
1684 [(set (match_operand:SI 0 "s_register_operand" "")
1685 (and:SI (match_operand:SI 1 "s_register_operand" "")
1686 (match_operand:SI 2 "reg_or_int_operand" "")))]
1691 if (GET_CODE (operands[2]) == CONST_INT)
1693 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1696 ? 0 : preserve_subexpressions_p ()));
1700 else /* TARGET_THUMB */
1702 if (GET_CODE (operands[2]) != CONST_INT)
1703 operands[2] = force_reg (SImode, operands[2]);
1708 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1710 operands[2] = force_reg (SImode,
1711 GEN_INT (~INTVAL (operands[2])));
1713 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1718 for (i = 9; i <= 31; i++)
1720 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1722 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1726 else if ((((HOST_WIDE_INT) 1) << i) - 1
1727 == ~INTVAL (operands[2]))
1729 rtx shift = GEN_INT (i);
1730 rtx reg = gen_reg_rtx (SImode);
1732 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1733 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1739 operands[2] = force_reg (SImode, operands[2]);
1745 (define_insn_and_split "*arm_andsi3_insn"
1746 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1747 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1748 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1752 bic%?\\t%0, %1, #%B2
1755 && GET_CODE (operands[2]) == CONST_INT
1756 && !(const_ok_for_arm (INTVAL (operands[2]))
1757 || const_ok_for_arm (~INTVAL (operands[2])))"
1758 [(clobber (const_int 0))]
1760 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1764 [(set_attr "length" "4,4,16")
1765 (set_attr "predicable" "yes")]
1768 (define_insn "*thumb_andsi3_insn"
1769 [(set (match_operand:SI 0 "register_operand" "=l")
1770 (and:SI (match_operand:SI 1 "register_operand" "%0")
1771 (match_operand:SI 2 "register_operand" "l")))]
1774 [(set_attr "length" "2")]
1777 (define_insn "*andsi3_compare0"
1778 [(set (reg:CC_NOOV CC_REGNUM)
1780 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1781 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1783 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1784 (and:SI (match_dup 1) (match_dup 2)))]
1788 bic%?s\\t%0, %1, #%B2"
1789 [(set_attr "conds" "set")]
1792 (define_insn "*andsi3_compare0_scratch"
1793 [(set (reg:CC_NOOV CC_REGNUM)
1795 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1796 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1798 (clobber (match_scratch:SI 2 "=X,r"))]
1802 bic%?s\\t%2, %0, #%B1"
1803 [(set_attr "conds" "set")]
1806 (define_insn "*zeroextractsi_compare0_scratch"
1807 [(set (reg:CC_NOOV CC_REGNUM)
1808 (compare:CC_NOOV (zero_extract:SI
1809 (match_operand:SI 0 "s_register_operand" "r")
1810 (match_operand 1 "const_int_operand" "n")
1811 (match_operand 2 "const_int_operand" "n"))
1814 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1815 && INTVAL (operands[1]) > 0
1816 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1817 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1819 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1820 << INTVAL (operands[2]));
1821 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1824 [(set_attr "conds" "set")]
1827 (define_insn "*ne_zeroextractsi"
1828 [(set (match_operand:SI 0 "s_register_operand" "=r")
1829 (ne:SI (zero_extract:SI
1830 (match_operand:SI 1 "s_register_operand" "r")
1831 (match_operand:SI 2 "const_int_operand" "n")
1832 (match_operand:SI 3 "const_int_operand" "n"))
1835 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1836 && INTVAL (operands[2]) > 0
1837 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1838 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1840 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1841 << INTVAL (operands[3]));
1842 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1843 return \"movne\\t%0, #1\";
1845 [(set_attr "conds" "clob")
1846 (set_attr "length" "8")]
1849 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1850 ;;; represented by the bitfield, then this will produce incorrect results.
1851 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1852 ;;; which have a real bitfield insert instruction, the truncation happens
1853 ;;; in the bitfield insert instruction itself. Since arm does not have a
1854 ;;; bitfield insert instruction, we would have to emit code here to truncate
1855 ;;; the value before we insert. This loses some of the advantage of having
1856 ;;; this insv pattern, so this pattern needs to be reevalutated.
1858 (define_expand "insv"
1859 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1860 (match_operand:SI 1 "general_operand" "")
1861 (match_operand:SI 2 "general_operand" ""))
1862 (match_operand:SI 3 "nonmemory_operand" ""))]
1866 int start_bit = INTVAL (operands[2]);
1867 int width = INTVAL (operands[1]);
1868 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1869 rtx target, subtarget;
1871 target = operands[0];
1872 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1873 subreg as the final target. */
1874 if (GET_CODE (target) == SUBREG)
1876 subtarget = gen_reg_rtx (SImode);
1877 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1878 < GET_MODE_SIZE (SImode))
1879 target = SUBREG_REG (target);
1884 if (GET_CODE (operands[3]) == CONST_INT)
1886 /* Since we are inserting a known constant, we may be able to
1887 reduce the number of bits that we have to clear so that
1888 the mask becomes simple. */
1889 /* ??? This code does not check to see if the new mask is actually
1890 simpler. It may not be. */
1891 rtx op1 = gen_reg_rtx (SImode);
1892 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1893 start of this pattern. */
1894 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1895 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1897 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1898 emit_insn (gen_iorsi3 (subtarget, op1,
1899 GEN_INT (op3_value << start_bit)));
1901 else if (start_bit == 0
1902 && !(const_ok_for_arm (mask)
1903 || const_ok_for_arm (~mask)))
1905 /* A Trick, since we are setting the bottom bits in the word,
1906 we can shift operand[3] up, operand[0] down, OR them together
1907 and rotate the result back again. This takes 3 insns, and
1908 the third might be mergable into another op. */
1909 /* The shift up copes with the possibility that operand[3] is
1910 wider than the bitfield. */
1911 rtx op0 = gen_reg_rtx (SImode);
1912 rtx op1 = gen_reg_rtx (SImode);
1914 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1915 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1916 emit_insn (gen_iorsi3 (op1, op1, op0));
1917 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1919 else if ((width + start_bit == 32)
1920 && !(const_ok_for_arm (mask)
1921 || const_ok_for_arm (~mask)))
1923 /* Similar trick, but slightly less efficient. */
1925 rtx op0 = gen_reg_rtx (SImode);
1926 rtx op1 = gen_reg_rtx (SImode);
1928 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1929 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1930 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1931 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1935 rtx op0 = GEN_INT (mask);
1936 rtx op1 = gen_reg_rtx (SImode);
1937 rtx op2 = gen_reg_rtx (SImode);
1939 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1941 rtx tmp = gen_reg_rtx (SImode);
1943 emit_insn (gen_movsi (tmp, op0));
1947 /* Mask out any bits in operand[3] that are not needed. */
1948 emit_insn (gen_andsi3 (op1, operands[3], op0));
1950 if (GET_CODE (op0) == CONST_INT
1951 && (const_ok_for_arm (mask << start_bit)
1952 || const_ok_for_arm (~(mask << start_bit))))
1954 op0 = GEN_INT (~(mask << start_bit));
1955 emit_insn (gen_andsi3 (op2, operands[0], op0));
1959 if (GET_CODE (op0) == CONST_INT)
1961 rtx tmp = gen_reg_rtx (SImode);
1963 emit_insn (gen_movsi (tmp, op0));
1968 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1970 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1974 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1976 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1979 if (subtarget != target)
1981 /* If TARGET is still a SUBREG, then it must be wider than a word,
1982 so we must be careful only to set the subword we were asked to. */
1983 if (GET_CODE (target) == SUBREG)
1984 emit_move_insn (target, subtarget);
1986 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1993 ; constants for op 2 will never be given to these patterns.
1994 (define_insn_and_split "*anddi_notdi_di"
1995 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1996 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1997 (match_operand:DI 2 "s_register_operand" "0,r")))]
2000 "TARGET_ARM && reload_completed"
2001 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2002 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
2005 operands[3] = gen_highpart (SImode, operands[0]);
2006 operands[0] = gen_lowpart (SImode, operands[0]);
2007 operands[4] = gen_highpart (SImode, operands[1]);
2008 operands[1] = gen_lowpart (SImode, operands[1]);
2009 operands[5] = gen_highpart (SImode, operands[2]);
2010 operands[2] = gen_lowpart (SImode, operands[2]);
2012 [(set_attr "length" "8")
2013 (set_attr "predicable" "yes")]
2016 (define_insn_and_split "*anddi_notzesidi_di"
2017 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2018 (and:DI (not:DI (zero_extend:DI
2019 (match_operand:SI 2 "s_register_operand" "r,r")))
2020 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2023 bic%?\\t%Q0, %Q1, %2
2025 ; (not (zero_extend ...)) allows us to just copy the high word from
2026 ; operand1 to operand0.
2029 && operands[0] != operands[1]"
2030 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2031 (set (match_dup 3) (match_dup 4))]
2034 operands[3] = gen_highpart (SImode, operands[0]);
2035 operands[0] = gen_lowpart (SImode, operands[0]);
2036 operands[4] = gen_highpart (SImode, operands[1]);
2037 operands[1] = gen_lowpart (SImode, operands[1]);
2039 [(set_attr "length" "4,8")
2040 (set_attr "predicable" "yes")]
2043 (define_insn_and_split "*anddi_notsesidi_di"
2044 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2045 (and:DI (not:DI (sign_extend:DI
2046 (match_operand:SI 2 "s_register_operand" "r,r")))
2047 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2050 "TARGET_ARM && reload_completed"
2051 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
2052 (set (match_dup 3) (and:SI (not:SI
2053 (ashiftrt:SI (match_dup 2) (const_int 31)))
2057 operands[3] = gen_highpart (SImode, operands[0]);
2058 operands[0] = gen_lowpart (SImode, operands[0]);
2059 operands[4] = gen_highpart (SImode, operands[1]);
2060 operands[1] = gen_lowpart (SImode, operands[1]);
2062 [(set_attr "length" "8")
2063 (set_attr "predicable" "yes")]
2066 (define_insn "andsi_notsi_si"
2067 [(set (match_operand:SI 0 "s_register_operand" "=r")
2068 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2069 (match_operand:SI 1 "s_register_operand" "r")))]
2071 "bic%?\\t%0, %1, %2"
2072 [(set_attr "predicable" "yes")]
2075 (define_insn "bicsi3"
2076 [(set (match_operand:SI 0 "register_operand" "=l")
2077 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2078 (match_operand:SI 2 "register_operand" "0")))]
2081 [(set_attr "length" "2")]
2084 (define_insn "andsi_not_shiftsi_si"
2085 [(set (match_operand:SI 0 "s_register_operand" "=r")
2086 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2087 [(match_operand:SI 2 "s_register_operand" "r")
2088 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2089 (match_operand:SI 1 "s_register_operand" "r")))]
2091 "bic%?\\t%0, %1, %2%S4"
2092 [(set_attr "predicable" "yes")
2093 (set_attr "shift" "2")
2097 (define_insn "*andsi_notsi_si_compare0"
2098 [(set (reg:CC_NOOV CC_REGNUM)
2100 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2101 (match_operand:SI 1 "s_register_operand" "r"))
2103 (set (match_operand:SI 0 "s_register_operand" "=r")
2104 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2106 "bic%?s\\t%0, %1, %2"
2107 [(set_attr "conds" "set")]
2110 (define_insn "*andsi_notsi_si_compare0_scratch"
2111 [(set (reg:CC_NOOV CC_REGNUM)
2113 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2114 (match_operand:SI 1 "s_register_operand" "r"))
2116 (clobber (match_scratch:SI 0 "=r"))]
2118 "bic%?s\\t%0, %1, %2"
2119 [(set_attr "conds" "set")]
2122 (define_insn "iordi3"
2123 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2124 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2125 (match_operand:DI 2 "s_register_operand" "r,r")))]
2128 [(set_attr "length" "8")
2129 (set_attr "predicable" "yes")]
2132 (define_insn "*iordi_zesidi_di"
2133 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2134 (ior:DI (zero_extend:DI
2135 (match_operand:SI 2 "s_register_operand" "r,r"))
2136 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2139 orr%?\\t%Q0, %Q1, %2
2141 [(set_attr "length" "4,8")
2142 (set_attr "predicable" "yes")]
2145 (define_insn "*iordi_sesidi_di"
2146 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2147 (ior:DI (sign_extend:DI
2148 (match_operand:SI 2 "s_register_operand" "r,r"))
2149 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2152 [(set_attr "length" "8")
2153 (set_attr "predicable" "yes")]
2156 (define_expand "iorsi3"
2157 [(set (match_operand:SI 0 "s_register_operand" "")
2158 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2159 (match_operand:SI 2 "reg_or_int_operand" "")))]
2162 if (GET_CODE (operands[2]) == CONST_INT)
2166 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2169 ? 0 : preserve_subexpressions_p ()));
2172 else /* TARGET_THUMB */
2173 operands [2] = force_reg (SImode, operands [2]);
2178 (define_insn_and_split "*arm_iorsi3"
2179 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2180 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2181 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2187 && GET_CODE (operands[2]) == CONST_INT
2188 && !const_ok_for_arm (INTVAL (operands[2]))"
2189 [(clobber (const_int 0))]
2191 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2195 [(set_attr "length" "4,16")
2196 (set_attr "predicable" "yes")]
2199 (define_insn "*thumb_iorsi3"
2200 [(set (match_operand:SI 0 "register_operand" "=l")
2201 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2202 (match_operand:SI 2 "register_operand" "l")))]
2205 [(set_attr "length" "2")]
2209 [(match_scratch:SI 3 "r")
2210 (set (match_operand:SI 0 "s_register_operand" "")
2211 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2212 (match_operand:SI 2 "const_int_operand" "")))]
2214 && !const_ok_for_arm (INTVAL (operands[2]))
2215 && const_ok_for_arm (~INTVAL (operands[2]))"
2216 [(set (match_dup 3) (match_dup 2))
2217 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2221 (define_insn "*iorsi3_compare0"
2222 [(set (reg:CC_NOOV CC_REGNUM)
2223 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2224 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2226 (set (match_operand:SI 0 "s_register_operand" "=r")
2227 (ior:SI (match_dup 1) (match_dup 2)))]
2229 "orr%?s\\t%0, %1, %2"
2230 [(set_attr "conds" "set")]
2233 (define_insn "*iorsi3_compare0_scratch"
2234 [(set (reg:CC_NOOV CC_REGNUM)
2235 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2236 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2238 (clobber (match_scratch:SI 0 "=r"))]
2240 "orr%?s\\t%0, %1, %2"
2241 [(set_attr "conds" "set")]
2244 (define_insn "xordi3"
2245 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2246 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2247 (match_operand:DI 2 "s_register_operand" "r,r")))]
2250 [(set_attr "length" "8")
2251 (set_attr "predicable" "yes")]
2254 (define_insn "*xordi_zesidi_di"
2255 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2256 (xor:DI (zero_extend:DI
2257 (match_operand:SI 2 "s_register_operand" "r,r"))
2258 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2261 eor%?\\t%Q0, %Q1, %2
2263 [(set_attr "length" "4,8")
2264 (set_attr "predicable" "yes")]
2267 (define_insn "*xordi_sesidi_di"
2268 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2269 (xor:DI (sign_extend:DI
2270 (match_operand:SI 2 "s_register_operand" "r,r"))
2271 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2274 [(set_attr "length" "8")
2275 (set_attr "predicable" "yes")]
2278 (define_expand "xorsi3"
2279 [(set (match_operand:SI 0 "s_register_operand" "")
2280 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2281 (match_operand:SI 2 "arm_rhs_operand" "")))]
2284 if (GET_CODE (operands[2]) == CONST_INT)
2285 operands[2] = force_reg (SImode, operands[2]);
2289 (define_insn "*arm_xorsi3"
2290 [(set (match_operand:SI 0 "s_register_operand" "=r")
2291 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2292 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2294 "eor%?\\t%0, %1, %2"
2295 [(set_attr "predicable" "yes")]
2298 (define_insn "*thumb_xorsi3"
2299 [(set (match_operand:SI 0 "register_operand" "=l")
2300 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2301 (match_operand:SI 2 "register_operand" "l")))]
2304 [(set_attr "length" "2")]
2307 (define_insn "*xorsi3_compare0"
2308 [(set (reg:CC_NOOV CC_REGNUM)
2309 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2310 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2312 (set (match_operand:SI 0 "s_register_operand" "=r")
2313 (xor:SI (match_dup 1) (match_dup 2)))]
2315 "eor%?s\\t%0, %1, %2"
2316 [(set_attr "conds" "set")]
2319 (define_insn "*xorsi3_compare0_scratch"
2320 [(set (reg:CC_NOOV CC_REGNUM)
2321 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2322 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2326 [(set_attr "conds" "set")]
2329 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2330 ; (NOT D) we can sometimes merge the final NOT into one of the following
2334 [(set (match_operand:SI 0 "s_register_operand" "=r")
2335 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2336 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
2337 (match_operand:SI 3 "arm_rhs_operand" "rI")))
2338 (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
2340 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2341 (not:SI (match_dup 3))))
2342 (set (match_dup 0) (not:SI (match_dup 4)))]
2346 (define_insn "*andsi_iorsi3_notsi"
2347 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2348 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2349 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2350 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2352 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2353 [(set_attr "length" "8")
2354 (set_attr "predicable" "yes")]
2359 ;; Minimum and maximum insns
2361 (define_insn "smaxsi3"
2362 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2363 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2364 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2365 (clobber (reg:CC CC_REGNUM))]
2368 cmp\\t%1, %2\;movlt\\t%0, %2
2369 cmp\\t%1, %2\;movge\\t%0, %1
2370 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2371 [(set_attr "conds" "clob")
2372 (set_attr "length" "8,8,12")]
2375 (define_insn "sminsi3"
2376 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2377 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2378 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2379 (clobber (reg:CC CC_REGNUM))]
2382 cmp\\t%1, %2\;movge\\t%0, %2
2383 cmp\\t%1, %2\;movlt\\t%0, %1
2384 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2385 [(set_attr "conds" "clob")
2386 (set_attr "length" "8,8,12")]
2389 (define_insn "umaxsi3"
2390 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2391 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2392 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2393 (clobber (reg:CC CC_REGNUM))]
2396 cmp\\t%1, %2\;movcc\\t%0, %2
2397 cmp\\t%1, %2\;movcs\\t%0, %1
2398 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2399 [(set_attr "conds" "clob")
2400 (set_attr "length" "8,8,12")]
2403 (define_insn "uminsi3"
2404 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2405 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2406 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2407 (clobber (reg:CC CC_REGNUM))]
2410 cmp\\t%1, %2\;movcs\\t%0, %2
2411 cmp\\t%1, %2\;movcc\\t%0, %1
2412 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2413 [(set_attr "conds" "clob")
2414 (set_attr "length" "8,8,12")]
2417 (define_insn "*store_minmaxsi"
2418 [(set (match_operand:SI 0 "memory_operand" "=m")
2419 (match_operator:SI 3 "minmax_operator"
2420 [(match_operand:SI 1 "s_register_operand" "r")
2421 (match_operand:SI 2 "s_register_operand" "r")]))
2422 (clobber (reg:CC CC_REGNUM))]
2425 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2427 output_asm_insn (\"cmp\\t%1, %2\", operands);
2428 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2429 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2432 [(set_attr "conds" "clob")
2433 (set_attr "length" "12")
2434 (set_attr "type" "store1")]
2437 ; Reject the frame pointer in operand[1], since reloading this after
2438 ; it has been eliminated can cause carnage.
2439 (define_insn "*minmax_arithsi"
2440 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2441 (match_operator:SI 4 "shiftable_operator"
2442 [(match_operator:SI 5 "minmax_operator"
2443 [(match_operand:SI 2 "s_register_operand" "r,r")
2444 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2445 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2446 (clobber (reg:CC CC_REGNUM))]
2448 && (GET_CODE (operands[1]) != REG
2449 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2450 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2453 enum rtx_code code = GET_CODE (operands[4]);
2455 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2457 output_asm_insn (\"cmp\\t%2, %3\", operands);
2458 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2459 if (which_alternative != 0 || operands[3] != const0_rtx
2460 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2461 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2464 [(set_attr "conds" "clob")
2465 (set_attr "length" "12")]
2469 ;; Shift and rotation insns
2471 (define_expand "ashlsi3"
2472 [(set (match_operand:SI 0 "s_register_operand" "")
2473 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2474 (match_operand:SI 2 "arm_rhs_operand" "")))]
2477 if (GET_CODE (operands[2]) == CONST_INT
2478 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2480 emit_insn (gen_movsi (operands[0], const0_rtx));
2486 (define_insn "*thumb_ashlsi3"
2487 [(set (match_operand:SI 0 "register_operand" "=l,l")
2488 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2489 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2492 [(set_attr "length" "2")]
2495 (define_expand "ashrsi3"
2496 [(set (match_operand:SI 0 "s_register_operand" "")
2497 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2498 (match_operand:SI 2 "arm_rhs_operand" "")))]
2501 if (GET_CODE (operands[2]) == CONST_INT
2502 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2503 operands[2] = GEN_INT (31);
2507 (define_insn "*thumb_ashrsi3"
2508 [(set (match_operand:SI 0 "register_operand" "=l,l")
2509 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2510 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2513 [(set_attr "length" "2")]
2516 (define_expand "lshrsi3"
2517 [(set (match_operand:SI 0 "s_register_operand" "")
2518 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2519 (match_operand:SI 2 "arm_rhs_operand" "")))]
2522 if (GET_CODE (operands[2]) == CONST_INT
2523 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2525 emit_insn (gen_movsi (operands[0], const0_rtx));
2531 (define_insn "*thumb_lshrsi3"
2532 [(set (match_operand:SI 0 "register_operand" "=l,l")
2533 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2534 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2537 [(set_attr "length" "2")]
2540 (define_expand "rotlsi3"
2541 [(set (match_operand:SI 0 "s_register_operand" "")
2542 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2543 (match_operand:SI 2 "reg_or_int_operand" "")))]
2546 if (GET_CODE (operands[2]) == CONST_INT)
2547 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2550 rtx reg = gen_reg_rtx (SImode);
2551 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2557 (define_expand "rotrsi3"
2558 [(set (match_operand:SI 0 "s_register_operand" "")
2559 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2560 (match_operand:SI 2 "arm_rhs_operand" "")))]
2565 if (GET_CODE (operands[2]) == CONST_INT
2566 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2567 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2569 else /* TARGET_THUMB */
2571 if (GET_CODE (operands [2]) == CONST_INT)
2572 operands [2] = force_reg (SImode, operands[2]);
2577 (define_insn "*thumb_rotrsi3"
2578 [(set (match_operand:SI 0 "register_operand" "=l")
2579 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2580 (match_operand:SI 2 "register_operand" "l")))]
2583 [(set_attr "length" "2")]
2586 (define_insn "*arm_shiftsi3"
2587 [(set (match_operand:SI 0 "s_register_operand" "=r")
2588 (match_operator:SI 3 "shift_operator"
2589 [(match_operand:SI 1 "s_register_operand" "r")
2590 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2593 [(set_attr "predicable" "yes")
2594 (set_attr "shift" "1")
2598 (define_insn "*shiftsi3_compare0"
2599 [(set (reg:CC_NOOV CC_REGNUM)
2600 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2601 [(match_operand:SI 1 "s_register_operand" "r")
2602 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2604 (set (match_operand:SI 0 "s_register_operand" "=r")
2605 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2607 "mov%?s\\t%0, %1%S3"
2608 [(set_attr "conds" "set")
2609 (set_attr "shift" "1")
2613 (define_insn "*shiftsi3_compare0_scratch"
2614 [(set (reg:CC_NOOV CC_REGNUM)
2615 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2616 [(match_operand:SI 1 "s_register_operand" "r")
2617 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2619 (clobber (match_scratch:SI 0 "=r"))]
2621 "mov%?s\\t%0, %1%S3"
2622 [(set_attr "conds" "set")
2623 (set_attr "shift" "1")
2627 (define_insn "*notsi_shiftsi"
2628 [(set (match_operand:SI 0 "s_register_operand" "=r")
2629 (not:SI (match_operator:SI 3 "shift_operator"
2630 [(match_operand:SI 1 "s_register_operand" "r")
2631 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2634 [(set_attr "predicable" "yes")
2635 (set_attr "shift" "1")
2639 (define_insn "*notsi_shiftsi_compare0"
2640 [(set (reg:CC_NOOV CC_REGNUM)
2641 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2642 [(match_operand:SI 1 "s_register_operand" "r")
2643 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2645 (set (match_operand:SI 0 "s_register_operand" "=r")
2646 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2648 "mvn%?s\\t%0, %1%S3"
2649 [(set_attr "conds" "set")
2650 (set_attr "shift" "1")
2654 (define_insn "*not_shiftsi_compare0_scratch"
2655 [(set (reg:CC_NOOV CC_REGNUM)
2656 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2657 [(match_operand:SI 1 "s_register_operand" "r")
2658 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2660 (clobber (match_scratch:SI 0 "=r"))]
2662 "mvn%?s\\t%0, %1%S3"
2663 [(set_attr "conds" "set")
2664 (set_attr "shift" "1")
2668 ;; We don't really have extzv, but defining this using shifts helps
2669 ;; to reduce register pressure later on.
2671 (define_expand "extzv"
2673 (ashift:SI (match_operand:SI 1 "register_operand" "")
2674 (match_operand:SI 2 "const_int_operand" "")))
2675 (set (match_operand:SI 0 "register_operand" "")
2676 (lshiftrt:SI (match_dup 4)
2677 (match_operand:SI 3 "const_int_operand" "")))]
2681 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2682 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2684 operands[3] = GEN_INT (rshift);
2688 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2692 operands[2] = GEN_INT (lshift);
2693 operands[4] = gen_reg_rtx (SImode);
2698 ;; Unary arithmetic insns
2700 (define_expand "negdi2"
2702 [(set (match_operand:DI 0 "s_register_operand" "")
2703 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2704 (clobber (reg:CC CC_REGNUM))])]
2709 if (GET_CODE (operands[1]) != REG)
2710 operands[1] = force_reg (SImode, operands[1]);
2715 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2716 ;; The second alternative is to allow the common case of a *full* overlap.
2717 (define_insn "*arm_negdi2"
2718 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2719 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2720 (clobber (reg:CC CC_REGNUM))]
2722 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2723 [(set_attr "conds" "clob")
2724 (set_attr "length" "8")]
2727 (define_insn "*thumb_negdi2"
2728 [(set (match_operand:DI 0 "register_operand" "=&l")
2729 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2730 (clobber (reg:CC CC_REGNUM))]
2732 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2733 [(set_attr "length" "6")]
2736 (define_expand "negsi2"
2737 [(set (match_operand:SI 0 "s_register_operand" "")
2738 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2743 (define_insn "*arm_negsi2"
2744 [(set (match_operand:SI 0 "s_register_operand" "=r")
2745 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2747 "rsb%?\\t%0, %1, #0"
2748 [(set_attr "predicable" "yes")]
2751 (define_insn "*thumb_negsi2"
2752 [(set (match_operand:SI 0 "register_operand" "=l")
2753 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2756 [(set_attr "length" "2")]
2759 (define_insn "negsf2"
2760 [(set (match_operand:SF 0 "s_register_operand" "=f")
2761 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2762 "TARGET_ARM && TARGET_HARD_FLOAT"
2764 [(set_attr "type" "ffarith")
2765 (set_attr "predicable" "yes")]
2768 (define_insn "negdf2"
2769 [(set (match_operand:DF 0 "s_register_operand" "=f")
2770 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2771 "TARGET_ARM && TARGET_HARD_FLOAT"
2773 [(set_attr "type" "ffarith")
2774 (set_attr "predicable" "yes")]
2777 (define_insn "*negdf_esfdf"
2778 [(set (match_operand:DF 0 "s_register_operand" "=f")
2779 (neg:DF (float_extend:DF
2780 (match_operand:SF 1 "s_register_operand" "f"))))]
2781 "TARGET_ARM && TARGET_HARD_FLOAT"
2783 [(set_attr "type" "ffarith")
2784 (set_attr "predicable" "yes")]
2787 (define_insn "negxf2"
2788 [(set (match_operand:XF 0 "s_register_operand" "=f")
2789 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2790 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2792 [(set_attr "type" "ffarith")
2793 (set_attr "predicable" "yes")]
2796 ;; abssi2 doesn't really clobber the condition codes if a different register
2797 ;; is being set. To keep things simple, assume during rtl manipulations that
2798 ;; it does, but tell the final scan operator the truth. Similarly for
2801 (define_insn "abssi2"
2802 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2803 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2804 (clobber (reg:CC CC_REGNUM))]
2807 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2808 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2809 [(set_attr "conds" "clob,*")
2810 (set_attr "shift" "1")
2811 ;; predicable can't be set based on the variant, so left as no
2812 (set_attr "length" "8")]
2815 (define_insn "*neg_abssi2"
2816 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2817 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2818 (clobber (reg:CC CC_REGNUM))]
2821 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2822 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2823 [(set_attr "conds" "clob,*")
2824 (set_attr "shift" "1")
2825 ;; predicable can't be set based on the variant, so left as no
2826 (set_attr "length" "8")]
2829 (define_insn "abssf2"
2830 [(set (match_operand:SF 0 "s_register_operand" "=f")
2831 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2832 "TARGET_ARM && TARGET_HARD_FLOAT"
2834 [(set_attr "type" "ffarith")
2835 (set_attr "predicable" "yes")]
2838 (define_insn "absdf2"
2839 [(set (match_operand:DF 0 "s_register_operand" "=f")
2840 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2841 "TARGET_ARM && TARGET_HARD_FLOAT"
2843 [(set_attr "type" "ffarith")
2844 (set_attr "predicable" "yes")]
2847 (define_insn "*absdf_esfdf"
2848 [(set (match_operand:DF 0 "s_register_operand" "=f")
2849 (abs:DF (float_extend:DF
2850 (match_operand:SF 1 "s_register_operand" "f"))))]
2851 "TARGET_ARM && TARGET_HARD_FLOAT"
2853 [(set_attr "type" "ffarith")
2854 (set_attr "predicable" "yes")]
2857 (define_insn "absxf2"
2858 [(set (match_operand:XF 0 "s_register_operand" "=f")
2859 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2860 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2862 [(set_attr "type" "ffarith")
2863 (set_attr "predicable" "yes")]
2866 (define_insn "sqrtsf2"
2867 [(set (match_operand:SF 0 "s_register_operand" "=f")
2868 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2869 "TARGET_ARM && TARGET_HARD_FLOAT"
2871 [(set_attr "type" "float_em")
2872 (set_attr "predicable" "yes")]
2875 (define_insn "sqrtdf2"
2876 [(set (match_operand:DF 0 "s_register_operand" "=f")
2877 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2878 "TARGET_ARM && TARGET_HARD_FLOAT"
2880 [(set_attr "type" "float_em")
2881 (set_attr "predicable" "yes")]
2884 (define_insn "*sqrtdf_esfdf"
2885 [(set (match_operand:DF 0 "s_register_operand" "=f")
2886 (sqrt:DF (float_extend:DF
2887 (match_operand:SF 1 "s_register_operand" "f"))))]
2888 "TARGET_ARM && TARGET_HARD_FLOAT"
2890 [(set_attr "type" "float_em")
2891 (set_attr "predicable" "yes")]
2894 (define_insn "sqrtxf2"
2895 [(set (match_operand:XF 0 "s_register_operand" "=f")
2896 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2897 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2899 [(set_attr "type" "float_em")
2900 (set_attr "predicable" "yes")]
2903 ;; SIN COS TAN and family are always emulated, so it's probably better
2904 ;; to always call a library function.
2905 ;(define_insn "sinsf2"
2906 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2907 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2909 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2911 ;[(set_attr "type" "float_em")])
2913 ;(define_insn "sindf2"
2914 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2915 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2917 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2919 ;[(set_attr "type" "float_em")])
2921 ;(define_insn "*sindf_esfdf"
2922 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2923 ; (unspec:DF [(float_extend:DF
2924 ; (match_operand:SF 1 "s_register_operand" "f"))]
2926 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2928 ;[(set_attr "type" "float_em")])
2930 ;(define_insn "sinxf2"
2931 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2932 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2934 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2936 ;[(set_attr "type" "float_em")])
2938 ;(define_insn "cossf2"
2939 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2940 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")]
2942 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2944 ;[(set_attr "type" "float_em")])
2946 ;(define_insn "cosdf2"
2947 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2948 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")]
2950 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2952 ;[(set_attr "type" "float_em")])
2954 ;(define_insn "*cosdf_esfdf"
2955 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2956 ; (unspec:DF [(float_extend:DF
2957 ; (match_operand:SF 1 "s_register_operand" "f"))]
2959 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2961 ;[(set_attr "type" "float_em")])
2963 ;(define_insn "cosxf2"
2964 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2965 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")]
2967 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2969 ;[(set_attr "type" "float_em")])
2971 (define_insn_and_split "one_cmpldi2"
2972 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2973 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2976 "TARGET_ARM && reload_completed"
2977 [(set (match_dup 0) (not:SI (match_dup 1)))
2978 (set (match_dup 2) (not:SI (match_dup 3)))]
2981 operands[2] = gen_highpart (SImode, operands[0]);
2982 operands[0] = gen_lowpart (SImode, operands[0]);
2983 operands[3] = gen_highpart (SImode, operands[1]);
2984 operands[1] = gen_lowpart (SImode, operands[1]);
2986 [(set_attr "length" "8")
2987 (set_attr "predicable" "yes")]
2990 (define_expand "one_cmplsi2"
2991 [(set (match_operand:SI 0 "s_register_operand" "")
2992 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2997 (define_insn "*arm_one_cmplsi2"
2998 [(set (match_operand:SI 0 "s_register_operand" "=r")
2999 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
3002 [(set_attr "predicable" "yes")]
3005 (define_insn "*thumb_one_cmplsi2"
3006 [(set (match_operand:SI 0 "register_operand" "=l")
3007 (not:SI (match_operand:SI 1 "register_operand" "l")))]
3010 [(set_attr "length" "2")]
3013 (define_insn "*notsi_compare0"
3014 [(set (reg:CC_NOOV CC_REGNUM)
3015 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3017 (set (match_operand:SI 0 "s_register_operand" "=r")
3018 (not:SI (match_dup 1)))]
3021 [(set_attr "conds" "set")]
3024 (define_insn "*notsi_compare0_scratch"
3025 [(set (reg:CC_NOOV CC_REGNUM)
3026 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
3028 (clobber (match_scratch:SI 0 "=r"))]
3031 [(set_attr "conds" "set")]
3034 ;; Fixed <--> Floating conversion insns
3036 (define_insn "floatsisf2"
3037 [(set (match_operand:SF 0 "s_register_operand" "=f")
3038 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
3039 "TARGET_ARM && TARGET_HARD_FLOAT"
3041 [(set_attr "type" "r_2_f")
3042 (set_attr "predicable" "yes")]
3045 (define_insn "floatsidf2"
3046 [(set (match_operand:DF 0 "s_register_operand" "=f")
3047 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
3048 "TARGET_ARM && TARGET_HARD_FLOAT"
3050 [(set_attr "type" "r_2_f")
3051 (set_attr "predicable" "yes")]
3054 (define_insn "floatsixf2"
3055 [(set (match_operand:XF 0 "s_register_operand" "=f")
3056 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
3057 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3059 [(set_attr "type" "r_2_f")
3060 (set_attr "predicable" "yes")]
3063 (define_insn "fix_truncsfsi2"
3064 [(set (match_operand:SI 0 "s_register_operand" "=r")
3065 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
3066 "TARGET_ARM && TARGET_HARD_FLOAT"
3068 [(set_attr "type" "f_2_r")
3069 (set_attr "predicable" "yes")]
3072 (define_insn "fix_truncdfsi2"
3073 [(set (match_operand:SI 0 "s_register_operand" "=r")
3074 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
3075 "TARGET_ARM && TARGET_HARD_FLOAT"
3077 [(set_attr "type" "f_2_r")
3078 (set_attr "predicable" "yes")]
3081 (define_insn "fix_truncxfsi2"
3082 [(set (match_operand:SI 0 "s_register_operand" "=r")
3083 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
3084 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3086 [(set_attr "type" "f_2_r")
3087 (set_attr "predicable" "yes")]
3092 (define_insn "truncdfsf2"
3093 [(set (match_operand:SF 0 "s_register_operand" "=f")
3095 (match_operand:DF 1 "s_register_operand" "f")))]
3096 "TARGET_ARM && TARGET_HARD_FLOAT"
3098 [(set_attr "type" "ffarith")
3099 (set_attr "predicable" "yes")]
3102 (define_insn "truncxfsf2"
3103 [(set (match_operand:SF 0 "s_register_operand" "=f")
3105 (match_operand:XF 1 "s_register_operand" "f")))]
3106 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3108 [(set_attr "type" "ffarith")
3109 (set_attr "predicable" "yes")]
3112 (define_insn "truncxfdf2"
3113 [(set (match_operand:DF 0 "s_register_operand" "=f")
3115 (match_operand:XF 1 "s_register_operand" "f")))]
3116 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3118 [(set_attr "type" "ffarith")
3119 (set_attr "predicable" "yes")]
3122 ;; Zero and sign extension instructions.
3124 (define_insn "zero_extendsidi2"
3125 [(set (match_operand:DI 0 "s_register_operand" "=r")
3126 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3129 if (REGNO (operands[1])
3130 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3131 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3132 return \"mov%?\\t%R0, #0\";
3134 [(set_attr "length" "8")
3135 (set_attr "predicable" "yes")]
3138 (define_insn "zero_extendqidi2"
3139 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3140 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3143 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3144 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3145 [(set_attr "length" "8")
3146 (set_attr "predicable" "yes")
3147 (set_attr "type" "*,load")
3148 (set_attr "pool_range" "*,4092")
3149 (set_attr "neg_pool_range" "*,4084")]
3152 (define_insn "extendsidi2"
3153 [(set (match_operand:DI 0 "s_register_operand" "=r")
3154 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3157 if (REGNO (operands[1])
3158 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3159 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3160 return \"mov%?\\t%R0, %Q0, asr #31\";
3162 [(set_attr "length" "8")
3163 (set_attr "shift" "1")
3164 (set_attr "predicable" "yes")]
3167 (define_expand "zero_extendhisi2"
3169 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3171 (set (match_operand:SI 0 "s_register_operand" "")
3172 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3178 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3180 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3181 here because the insn below will generate an LDRH instruction
3182 rather than an LDR instruction, so we cannot get an unaligned
3184 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3185 gen_rtx_ZERO_EXTEND (SImode,
3189 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3191 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3194 if (!s_register_operand (operands[1], HImode))
3195 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3196 operands[1] = gen_lowpart (SImode, operands[1]);
3197 operands[2] = gen_reg_rtx (SImode);
3199 else /* TARGET_THUMB */
3201 if (GET_CODE (operands[1]) == MEM)
3205 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3206 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3213 if (!s_register_operand (operands[1], HImode))
3214 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3215 operands[1] = gen_lowpart (SImode, operands[1]);
3216 operands[2] = gen_reg_rtx (SImode);
3218 ops[0] = operands[2];
3219 ops[1] = operands[1];
3220 ops[2] = GEN_INT (16);
3222 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3223 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3225 ops[0] = operands[0];
3226 ops[1] = operands[2];
3227 ops[2] = GEN_INT (16);
3229 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3230 gen_rtx_LSHIFTRT (SImode, ops[1],
3238 (define_insn "*thumb_zero_extendhisi2"
3239 [(set (match_operand:SI 0 "register_operand" "=l")
3240 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3243 rtx mem = XEXP (operands[1], 0);
3245 if (GET_CODE (mem) == CONST)
3246 mem = XEXP (mem, 0);
3248 if (GET_CODE (mem) == LABEL_REF)
3249 return \"ldr\\t%0, %1\";
3251 if (GET_CODE (mem) == PLUS)
3253 rtx a = XEXP (mem, 0);
3254 rtx b = XEXP (mem, 1);
3256 /* This can happen due to bugs in reload. */
3257 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3260 ops[0] = operands[0];
3263 output_asm_insn (\"mov %0, %1\", ops);
3265 XEXP (mem, 0) = operands[0];
3268 else if ( GET_CODE (a) == LABEL_REF
3269 && GET_CODE (b) == CONST_INT)
3270 return \"ldr\\t%0, %1\";
3273 return \"ldrh\\t%0, %1\";
3275 [(set_attr "length" "4")
3276 (set_attr "type" "load")
3277 (set_attr "pool_range" "60")]
3280 (define_insn "*arm_zero_extendhisi2"
3281 [(set (match_operand:SI 0 "s_register_operand" "=r")
3282 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3283 "TARGET_ARM && arm_arch4"
3285 [(set_attr "type" "load")
3286 (set_attr "predicable" "yes")
3287 (set_attr "pool_range" "256")
3288 (set_attr "neg_pool_range" "244")]
3292 [(set (match_operand:SI 0 "s_register_operand" "")
3293 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3294 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3295 "TARGET_ARM && (!arm_arch4)"
3296 [(set (match_dup 2) (match_dup 1))
3297 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3299 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3305 [(set (match_operand:SI 0 "s_register_operand" "")
3306 (match_operator:SI 3 "shiftable_operator"
3307 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3308 (match_operand:SI 4 "s_register_operand" "")]))
3309 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3310 "TARGET_ARM && (!arm_arch4)"
3311 [(set (match_dup 2) (match_dup 1))
3314 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3316 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3321 (define_expand "zero_extendqisi2"
3322 [(set (match_operand:SI 0 "s_register_operand" "")
3323 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3326 if (GET_CODE (operands[1]) != MEM)
3330 emit_insn (gen_andsi3 (operands[0],
3331 gen_lowpart (SImode, operands[1]),
3334 else /* TARGET_THUMB */
3336 rtx temp = gen_reg_rtx (SImode);
3339 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3340 operands[1] = gen_lowpart (SImode, operands[1]);
3343 ops[1] = operands[1];
3344 ops[2] = GEN_INT (24);
3346 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3347 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3349 ops[0] = operands[0];
3351 ops[2] = GEN_INT (24);
3353 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3354 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3361 (define_insn "*thumb_zero_extendqisi2"
3362 [(set (match_operand:SI 0 "register_operand" "=l")
3363 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3366 [(set_attr "length" "2")
3367 (set_attr "type" "load")
3368 (set_attr "pool_range" "32")]
3371 (define_insn "*arm_zero_extendqisi2"
3372 [(set (match_operand:SI 0 "s_register_operand" "=r")
3373 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3375 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3376 [(set_attr "type" "load")
3377 (set_attr "predicable" "yes")
3378 (set_attr "pool_range" "4096")
3379 (set_attr "neg_pool_range" "4084")]
3383 [(set (match_operand:SI 0 "s_register_operand" "")
3384 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3385 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3386 "TARGET_ARM && (GET_CODE (operands[1]) != MEM)"
3387 [(set (match_dup 2) (match_dup 1))
3388 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3392 (define_insn "*compareqi_eq0"
3393 [(set (reg:CC_Z CC_REGNUM)
3394 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3398 [(set_attr "conds" "set")]
3401 (define_expand "extendhisi2"
3403 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3405 (set (match_operand:SI 0 "s_register_operand" "")
3406 (ashiftrt:SI (match_dup 2)
3411 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3413 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3414 here because the insn below will generate an LDRH instruction
3415 rather than an LDR instruction, so we cannot get an unaligned
3417 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3418 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3422 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3424 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3427 if (!s_register_operand (operands[1], HImode))
3428 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3429 operands[1] = gen_lowpart (SImode, operands[1]);
3430 operands[2] = gen_reg_rtx (SImode);
3436 ops[0] = operands[2];
3437 ops[1] = operands[1];
3438 ops[2] = GEN_INT (16);
3440 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3441 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3443 ops[0] = operands[0];
3444 ops[1] = operands[2];
3445 ops[2] = GEN_INT (16);
3447 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3448 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3455 (define_insn "*thumb_extendhisi2_insn"
3456 [(set (match_operand:SI 0 "register_operand" "=l")
3457 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3458 (clobber (match_scratch:SI 2 "=&l"))]
3463 rtx mem = XEXP (operands[1], 0);
3465 /* This code used to try to use 'V', and fix the address only if it was
3466 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3467 range of QImode offsets, and offsettable_address_p does a QImode
3470 if (GET_CODE (mem) == CONST)
3471 mem = XEXP (mem, 0);
3473 if (GET_CODE (mem) == LABEL_REF)
3474 return \"ldr\\t%0, %1\";
3476 if (GET_CODE (mem) == PLUS)
3478 rtx a = XEXP (mem, 0);
3479 rtx b = XEXP (mem, 1);
3481 if (GET_CODE (a) == LABEL_REF
3482 && GET_CODE (b) == CONST_INT)
3483 return \"ldr\\t%0, %1\";
3485 if (GET_CODE (b) == REG)
3486 return \"ldrsh\\t%0, %1\";
3494 ops[2] = const0_rtx;
3497 if (GET_CODE (ops[1]) != REG)
3503 ops[0] = operands[0];
3504 ops[3] = operands[2];
3505 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3508 [(set_attr "length" "4")
3509 (set_attr "type" "load")
3510 (set_attr "pool_range" "1020")]
3513 (define_expand "extendhisi2_mem"
3514 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3516 (zero_extend:SI (match_dup 7)))
3517 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3518 (set (match_operand:SI 0 "" "")
3519 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3524 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3526 mem1 = gen_rtx_MEM (QImode, addr);
3527 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3528 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3529 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3530 operands[0] = gen_lowpart (SImode, operands[0]);
3532 operands[2] = gen_reg_rtx (SImode);
3533 operands[3] = gen_reg_rtx (SImode);
3534 operands[6] = gen_reg_rtx (SImode);
3537 if (BYTES_BIG_ENDIAN)
3539 operands[4] = operands[2];
3540 operands[5] = operands[3];
3544 operands[4] = operands[3];
3545 operands[5] = operands[2];
3550 (define_insn "*arm_extendhisi_insn"
3551 [(set (match_operand:SI 0 "s_register_operand" "=r")
3552 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3553 "TARGET_ARM && arm_arch4"
3555 [(set_attr "type" "load")
3556 (set_attr "predicable" "yes")
3557 (set_attr "pool_range" "256")
3558 (set_attr "neg_pool_range" "244")]
3562 [(set (match_operand:SI 0 "s_register_operand" "")
3563 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3564 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3565 "TARGET_ARM && (!arm_arch4)"
3566 [(set (match_dup 2) (match_dup 1))
3567 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3569 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3575 [(set (match_operand:SI 0 "s_register_operand" "")
3576 (match_operator:SI 3 "shiftable_operator"
3577 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3578 (match_operand:SI 4 "s_register_operand" "")]))
3579 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3580 "TARGET_ARM && (!arm_arch4)"
3581 [(set (match_dup 2) (match_dup 1))
3584 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3585 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3590 (define_expand "extendqihi2"
3592 (ashift:SI (match_operand:QI 1 "general_operand" "")
3594 (set (match_operand:HI 0 "s_register_operand" "")
3595 (ashiftrt:SI (match_dup 2)
3600 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3602 emit_insn (gen_rtx_SET (VOIDmode,
3604 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3607 if (!s_register_operand (operands[1], QImode))
3608 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3609 operands[0] = gen_lowpart (SImode, operands[0]);
3610 operands[1] = gen_lowpart (SImode, operands[1]);
3611 operands[2] = gen_reg_rtx (SImode);
3615 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3616 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3617 (define_insn "*extendqihi_insn"
3618 [(set (match_operand:HI 0 "s_register_operand" "=r")
3619 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3620 "TARGET_ARM && arm_arch4"
3622 /* If the address is invalid, this will split the instruction into two. */
3623 if (bad_signed_byte_operand (operands[1], VOIDmode))
3625 return \"ldr%?sb\\t%0, %1\";
3627 [(set_attr "type" "load")
3628 (set_attr "predicable" "yes")
3629 (set_attr "length" "8")
3630 (set_attr "pool_range" "256")
3631 (set_attr "neg_pool_range" "244")]
3635 [(set (match_operand:HI 0 "s_register_operand" "")
3636 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3637 "TARGET_ARM && arm_arch4 && reload_completed"
3638 [(set (match_dup 3) (match_dup 1))
3639 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3642 HOST_WIDE_INT offset;
3644 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3645 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3646 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3647 operands[1] = XEXP (operands[1], 0);
3648 if (GET_CODE (operands[1]) == PLUS
3649 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3650 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3651 || const_ok_for_arm (-offset)))
3653 HOST_WIDE_INT low = (offset > 0
3654 ? (offset & 0xff) : -((-offset) & 0xff));
3655 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3656 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3658 /* Ensure the sum is in correct canonical form */
3659 else if (GET_CODE (operands[1]) == PLUS
3660 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3661 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3662 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3663 XEXP (operands[1], 1),
3664 XEXP (operands[1], 0));
3668 (define_expand "extendqisi2"
3670 (ashift:SI (match_operand:QI 1 "general_operand" "")
3672 (set (match_operand:SI 0 "s_register_operand" "")
3673 (ashiftrt:SI (match_dup 2)
3678 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3680 emit_insn (gen_rtx_SET (VOIDmode,
3682 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3685 if (!s_register_operand (operands[1], QImode))
3686 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3687 operands[1] = gen_lowpart (SImode, operands[1]);
3688 operands[2] = gen_reg_rtx (SImode);
3694 ops[0] = operands[2];
3695 ops[1] = operands[1];
3696 ops[2] = GEN_INT (24);
3698 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3699 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3701 ops[0] = operands[0];
3702 ops[1] = operands[2];
3703 ops[2] = GEN_INT (24);
3705 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3706 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3713 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3714 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3715 (define_insn "*arm_extendqisi_insn"
3716 [(set (match_operand:SI 0 "s_register_operand" "=r")
3717 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3718 "TARGET_ARM && arm_arch4"
3720 /* If the address is invalid, this will split the instruction into two. */
3721 if (bad_signed_byte_operand (operands[1], VOIDmode))
3723 return \"ldr%?sb\\t%0, %1\";
3725 [(set_attr "type" "load")
3726 (set_attr "predicable" "yes")
3727 (set_attr "length" "8")
3728 (set_attr "pool_range" "256")
3729 (set_attr "neg_pool_range" "244")]
3733 [(set (match_operand:SI 0 "s_register_operand" "")
3734 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3735 "TARGET_ARM && arm_arch4 && reload_completed"
3736 [(set (match_dup 0) (match_dup 1))
3737 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3740 HOST_WIDE_INT offset;
3742 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3743 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3744 operands[1] = XEXP (operands[1], 0);
3745 if (GET_CODE (operands[1]) == PLUS
3746 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3747 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3748 || const_ok_for_arm (-offset)))
3750 HOST_WIDE_INT low = (offset > 0
3751 ? (offset & 0xff) : -((-offset) & 0xff));
3752 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3753 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3755 /* Ensure the sum is in correct canonical form */
3756 else if (GET_CODE (operands[1]) == PLUS
3757 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3758 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3759 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3760 XEXP (operands[1], 1),
3761 XEXP (operands[1], 0));
3765 (define_insn "*thumb_extendqisi2_insn"
3766 [(set (match_operand:SI 0 "register_operand" "=l,l")
3767 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3772 rtx mem = XEXP (operands[1], 0);
3774 if (GET_CODE (mem) == CONST)
3775 mem = XEXP (mem, 0);
3777 if (GET_CODE (mem) == LABEL_REF)
3778 return \"ldr\\t%0, %1\";
3780 if (GET_CODE (mem) == PLUS
3781 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3782 return \"ldr\\t%0, %1\";
3784 if (which_alternative == 0)
3785 return \"ldrsb\\t%0, %1\";
3787 ops[0] = operands[0];
3789 if (GET_CODE (mem) == PLUS)
3791 rtx a = XEXP (mem, 0);
3792 rtx b = XEXP (mem, 1);
3797 if (GET_CODE (a) == REG)
3799 if (GET_CODE (b) == REG)
3800 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3801 else if (REGNO (a) == REGNO (ops[0]))
3803 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3804 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3805 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3808 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3810 else if (GET_CODE (b) != REG)
3814 if (REGNO (b) == REGNO (ops[0]))
3816 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3817 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3818 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3821 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3824 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3826 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3827 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3828 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3833 ops[2] = const0_rtx;
3835 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3839 [(set_attr "length" "2,6")
3840 (set_attr "type" "load,load")
3841 (set_attr "pool_range" "32,32")]
3844 (define_insn "extendsfdf2"
3845 [(set (match_operand:DF 0 "s_register_operand" "=f")
3846 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3847 "TARGET_ARM && TARGET_HARD_FLOAT"
3849 [(set_attr "type" "ffarith")
3850 (set_attr "predicable" "yes")]
3853 (define_insn "extendsfxf2"
3854 [(set (match_operand:XF 0 "s_register_operand" "=f")
3855 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3856 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3858 [(set_attr "type" "ffarith")
3859 (set_attr "predicable" "yes")]
3862 (define_insn "extenddfxf2"
3863 [(set (match_operand:XF 0 "s_register_operand" "=f")
3864 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3865 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3867 [(set_attr "type" "ffarith")
3868 (set_attr "predicable" "yes")]
3872 ;; Move insns (including loads and stores)
3874 ;; XXX Just some ideas about movti.
3875 ;; I don't think these are a good idea on the arm, there just aren't enough
3877 ;;(define_expand "loadti"
3878 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3879 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3882 ;;(define_expand "storeti"
3883 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3884 ;; (match_operand:TI 1 "s_register_operand" ""))]
3887 ;;(define_expand "movti"
3888 ;; [(set (match_operand:TI 0 "general_operand" "")
3889 ;; (match_operand:TI 1 "general_operand" ""))]
3895 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3896 ;; operands[1] = copy_to_reg (operands[1]);
3897 ;; if (GET_CODE (operands[0]) == MEM)
3898 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3899 ;; else if (GET_CODE (operands[1]) == MEM)
3900 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3904 ;; emit_insn (insn);
3908 ;; Recognise garbage generated above.
3911 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3912 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3916 ;; register mem = (which_alternative < 3);
3917 ;; register const char *template;
3919 ;; operands[mem] = XEXP (operands[mem], 0);
3920 ;; switch (which_alternative)
3922 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3923 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3924 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3925 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3926 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3927 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3929 ;; output_asm_insn (template, operands);
3933 (define_expand "movdi"
3934 [(set (match_operand:DI 0 "general_operand" "")
3935 (match_operand:DI 1 "general_operand" ""))]
3940 if (!no_new_pseudos)
3942 if (GET_CODE (operands[0]) != REG)
3943 operands[1] = force_reg (DImode, operands[1]);
3949 (define_insn "*arm_movdi"
3950 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3951 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3954 return (output_move_double (operands));
3956 [(set_attr "length" "8")
3957 (set_attr "type" "*,load,store2")
3958 (set_attr "pool_range" "*,1020,*")
3959 (set_attr "neg_pool_range" "*,1012,*")]
3962 ;;; ??? This should have alternatives for constants.
3963 ;;; ??? This was originally identical to the movdf_insn pattern.
3964 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3965 ;;; thumb_reorg with a memory reference.
3966 (define_insn "*thumb_movdi_insn"
3967 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3968 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3970 && ( register_operand (operands[0], DImode)
3971 || register_operand (operands[1], DImode))"
3974 switch (which_alternative)
3978 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3979 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3980 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3982 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3984 operands[1] = GEN_INT (- INTVAL (operands[1]));
3985 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3987 return \"ldmia\\t%1, {%0, %H0}\";
3989 return \"stmia\\t%0, {%1, %H1}\";
3991 return thumb_load_double_from_address (operands);
3993 operands[2] = gen_rtx (MEM, SImode,
3994 plus_constant (XEXP (operands[0], 0), 4));
3995 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3998 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3999 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4000 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4003 [(set_attr "length" "4,4,6,2,2,6,4,4")
4004 (set_attr "type" "*,*,*,load,store2,load,store2,*")
4005 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4008 (define_expand "movsi"
4009 [(set (match_operand:SI 0 "general_operand" "")
4010 (match_operand:SI 1 "general_operand" ""))]
4015 /* Everything except mem = const or mem = mem can be done easily */
4016 if (GET_CODE (operands[0]) == MEM)
4017 operands[1] = force_reg (SImode, operands[1]);
4018 if (GET_CODE (operands[1]) == CONST_INT
4019 && !(const_ok_for_arm (INTVAL (operands[1]))
4020 || const_ok_for_arm (~INTVAL (operands[1]))))
4022 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4025 : preserve_subexpressions_p ()));
4029 else /* TARGET_THUMB.... */
4031 if (!no_new_pseudos)
4033 if (GET_CODE (operands[0]) != REG)
4034 operands[1] = force_reg (SImode, operands[1]);
4039 && (CONSTANT_P (operands[1])
4040 || symbol_mentioned_p (operands[1])
4041 || label_mentioned_p (operands[1])))
4042 operands[1] = legitimize_pic_address (operands[1], SImode,
4043 (no_new_pseudos ? operands[0] : 0));
4047 (define_insn "*arm_movsi_insn"
4048 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4049 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4051 && ( register_operand (operands[0], SImode)
4052 || register_operand (operands[1], SImode))"
4058 [(set_attr "type" "*,*,load,store1")
4059 (set_attr "predicable" "yes")
4060 (set_attr "pool_range" "*,*,4096,*")
4061 (set_attr "neg_pool_range" "*,*,4084,*")]
4065 [(set (match_operand:SI 0 "s_register_operand" "")
4066 (match_operand:SI 1 "const_int_operand" ""))]
4068 && (!(const_ok_for_arm (INTVAL (operands[1]))
4069 || const_ok_for_arm (~INTVAL (operands[1]))))"
4070 [(clobber (const_int 0))]
4072 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4078 (define_insn "*thumb_movsi_insn"
4079 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4080 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4082 && ( register_operand (operands[0], SImode)
4083 || register_operand (operands[1], SImode))"
4094 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4095 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4096 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4100 [(set (match_operand:SI 0 "register_operand" "")
4101 (match_operand:SI 1 "const_int_operand" ""))]
4102 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4103 [(set (match_dup 0) (match_dup 1))
4104 (set (match_dup 0) (neg:SI (match_dup 0)))]
4105 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4109 [(set (match_operand:SI 0 "register_operand" "")
4110 (match_operand:SI 1 "const_int_operand" ""))]
4111 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4112 [(set (match_dup 0) (match_dup 1))
4113 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4116 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4117 unsigned HOST_WIDE_INT mask = 0xff;
4120 for (i = 0; i < 25; i++)
4121 if ((val & (mask << i)) == val)
4127 operands[1] = GEN_INT (val >> i);
4128 operands[2] = GEN_INT (i);
4132 (define_expand "movaddr"
4133 [(set (match_operand:SI 0 "s_register_operand" "")
4134 (match_operand:DI 1 "address_operand" ""))]
4139 (define_insn "*movaddr_insn"
4140 [(set (match_operand:SI 0 "s_register_operand" "=r")
4141 (match_operand:DI 1 "address_operand" "p"))]
4144 && (GET_CODE (operands[1]) == LABEL_REF
4145 || (GET_CODE (operands[1]) == CONST
4146 && GET_CODE (XEXP (operands[1], 0)) == PLUS
4147 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
4148 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
4150 [(set_attr "predicable" "yes")]
4153 ;; When generating pic, we need to load the symbol offset into a register.
4154 ;; So that the optimizer does not confuse this with a normal symbol load
4155 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4156 ;; since that is the only type of relocation we can use.
4158 ;; The rather odd constraints on the following are to force reload to leave
4159 ;; the insn alone, and to force the minipool generation pass to then move
4160 ;; the GOT symbol to memory.
4162 (define_insn "pic_load_addr_arm"
4163 [(set (match_operand:SI 0 "s_register_operand" "=r")
4164 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4165 "TARGET_ARM && flag_pic"
4167 [(set_attr "type" "load")
4168 (set (attr "pool_range") (const_int 4096))
4169 (set (attr "neg_pool_range") (const_int 4084))]
4172 (define_insn "pic_load_addr_thumb"
4173 [(set (match_operand:SI 0 "s_register_operand" "=l")
4174 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4175 "TARGET_THUMB && flag_pic"
4177 [(set_attr "type" "load")
4178 (set (attr "pool_range") (const_int 1024))]
4181 ;; This variant is used for AOF assembly, since it needs to mention the
4182 ;; pic register in the rtl.
4183 (define_expand "pic_load_addr_based"
4184 [(set (match_operand:SI 0 "s_register_operand" "=r")
4185 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4186 "TARGET_ARM && flag_pic"
4187 "operands[2] = pic_offset_table_rtx;"
4190 (define_insn "*pic_load_addr_based_insn"
4191 [(set (match_operand:SI 0 "s_register_operand" "=r")
4192 (unspec:SI [(match_operand 1 "" "")
4193 (match_operand 2 "s_register_operand" "r")]
4195 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4197 #ifdef AOF_ASSEMBLER
4198 operands[1] = aof_pic_entry (operands[1]);
4200 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4203 [(set_attr "type" "load")
4204 (set (attr "pool_range")
4205 (if_then_else (eq_attr "is_thumb" "yes")
4208 (set (attr "neg_pool_range")
4209 (if_then_else (eq_attr "is_thumb" "yes")
4214 (define_insn "pic_add_dot_plus_four"
4215 [(set (match_operand:SI 0 "register_operand" "+r")
4216 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4217 (use (label_ref (match_operand 1 "" "")))]
4218 "TARGET_THUMB && flag_pic"
4220 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4221 CODE_LABEL_NUMBER (operands[1]));
4222 return \"add\\t%0, %|pc\";
4224 [(set_attr "length" "2")]
4227 (define_insn "pic_add_dot_plus_eight"
4228 [(set (match_operand:SI 0 "register_operand" "+r")
4229 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4230 (use (label_ref (match_operand 1 "" "")))]
4231 "TARGET_ARM && flag_pic"
4233 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4234 CODE_LABEL_NUMBER (operands[1]));
4235 return \"add%?\\t%0, %|pc, %0\";
4237 [(set_attr "predicable" "yes")]
4240 (define_expand "builtin_setjmp_receiver"
4241 [(label_ref (match_operand 0 "" ""))]
4245 arm_finalize_pic (0);
4249 ;; If copying one reg to another we can set the condition codes according to
4250 ;; its value. Such a move is common after a return from subroutine and the
4251 ;; result is being tested against zero.
4253 (define_insn "*movsi_compare0"
4254 [(set (reg:CC CC_REGNUM)
4255 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4257 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4262 sub%?s\\t%0, %1, #0"
4263 [(set_attr "conds" "set")]
4266 ;; Subroutine to store a half word from a register into memory.
4267 ;; Operand 0 is the source register (HImode)
4268 ;; Operand 1 is the destination address in a register (SImode)
4270 ;; In both this routine and the next, we must be careful not to spill
4271 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4272 ;; can generate unrecognizable rtl.
4274 (define_expand "storehi"
4275 [;; store the low byte
4276 (set (match_operand 1 "" "") (match_dup 3))
4277 ;; extract the high byte
4279 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4280 ;; store the high byte
4281 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4285 rtx op1 = operands[1];
4286 rtx addr = XEXP (op1, 0);
4287 enum rtx_code code = GET_CODE (addr);
4289 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4291 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4293 operands[4] = adjust_address (op1, QImode, 1);
4294 operands[1] = adjust_address (operands[1], QImode, 0);
4295 operands[3] = gen_lowpart (QImode, operands[0]);
4296 operands[0] = gen_lowpart (SImode, operands[0]);
4297 operands[2] = gen_reg_rtx (SImode);
4301 (define_expand "storehi_bigend"
4302 [(set (match_dup 4) (match_dup 3))
4304 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4305 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
4309 rtx op1 = operands[1];
4310 rtx addr = XEXP (op1, 0);
4311 enum rtx_code code = GET_CODE (addr);
4313 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4315 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4317 operands[4] = adjust_address (op1, QImode, 1);
4318 operands[1] = adjust_address (operands[1], QImode, 0);
4319 operands[3] = gen_lowpart (QImode, operands[0]);
4320 operands[0] = gen_lowpart (SImode, operands[0]);
4321 operands[2] = gen_reg_rtx (SImode);
4325 ;; Subroutine to store a half word integer constant into memory.
4326 (define_expand "storeinthi"
4327 [(set (match_operand 0 "" "")
4328 (subreg:QI (match_operand 1 "" "") 0))
4329 (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
4333 HOST_WIDE_INT value = INTVAL (operands[1]);
4334 rtx addr = XEXP (operands[0], 0);
4335 rtx op0 = operands[0];
4336 enum rtx_code code = GET_CODE (addr);
4338 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4340 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4342 operands[1] = gen_reg_rtx (SImode);
4343 if (BYTES_BIG_ENDIAN)
4345 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4346 if ((value & 255) == ((value >> 8) & 255))
4347 operands[2] = operands[1];
4350 operands[2] = gen_reg_rtx (SImode);
4351 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4356 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4357 if ((value & 255) == ((value >> 8) & 255))
4358 operands[2] = operands[1];
4361 operands[2] = gen_reg_rtx (SImode);
4362 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4366 operands[3] = adjust_address (op0, QImode, 1);
4367 operands[0] = adjust_address (operands[0], QImode, 0);
4371 (define_expand "storehi_single_op"
4372 [(set (match_operand:HI 0 "memory_operand" "")
4373 (match_operand:HI 1 "general_operand" ""))]
4374 "TARGET_ARM && arm_arch4"
4376 if (!s_register_operand (operands[1], HImode))
4377 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4381 (define_expand "movhi"
4382 [(set (match_operand:HI 0 "general_operand" "")
4383 (match_operand:HI 1 "general_operand" ""))]
4388 if (!no_new_pseudos)
4390 if (GET_CODE (operands[0]) == MEM)
4394 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4397 if (GET_CODE (operands[1]) == CONST_INT)
4398 emit_insn (gen_storeinthi (operands[0], operands[1]));
4401 if (GET_CODE (operands[1]) == MEM)
4402 operands[1] = force_reg (HImode, operands[1]);
4403 if (BYTES_BIG_ENDIAN)
4404 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4406 emit_insn (gen_storehi (operands[1], operands[0]));
4410 /* Sign extend a constant, and keep it in an SImode reg. */
4411 else if (GET_CODE (operands[1]) == CONST_INT)
4413 rtx reg = gen_reg_rtx (SImode);
4414 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4416 /* If the constant is already valid, leave it alone. */
4417 if (!const_ok_for_arm (val))
4419 /* If setting all the top bits will make the constant
4420 loadable in a single instruction, then set them.
4421 Otherwise, sign extend the number. */
4423 if (const_ok_for_arm (~(val | ~0xffff)))
4425 else if (val & 0x8000)
4429 emit_insn (gen_movsi (reg, GEN_INT (val)));
4430 operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
4432 else if (!arm_arch4)
4434 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4435 for v4 and up architectures because LDRH instructions will
4436 be used to access the HI values, and these cannot generate
4437 unaligned word access faults in the MMU. */
4438 if (GET_CODE (operands[1]) == MEM)
4440 if (TARGET_MMU_TRAPS)
4443 rtx offset = const0_rtx;
4444 rtx reg = gen_reg_rtx (SImode);
4446 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4447 || (GET_CODE (base) == PLUS
4448 && (GET_CODE (offset = XEXP (base, 1))
4450 && ((INTVAL(offset) & 1) != 1)
4451 && GET_CODE (base = XEXP (base, 0)) == REG))
4452 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4454 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4457 new = gen_rtx_MEM (SImode,
4458 plus_constant (base, new_offset));
4459 MEM_COPY_ATTRIBUTES (new, operands[1]);
4460 emit_insn (gen_movsi (reg, new));
4461 if (((INTVAL (offset) & 2) != 0)
4462 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4464 rtx reg2 = gen_reg_rtx (SImode);
4466 emit_insn (gen_lshrsi3 (reg2, reg,
4472 emit_insn (gen_movhi_bytes (reg, operands[1]));
4474 operands[1] = gen_lowpart (HImode, reg);
4476 else if (BYTES_BIG_ENDIAN)
4479 rtx offset = const0_rtx;
4481 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4482 || (GET_CODE (base) == PLUS
4483 && (GET_CODE (offset = XEXP (base, 1))
4485 && GET_CODE (base = XEXP (base, 0)) == REG))
4486 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4488 rtx reg = gen_reg_rtx (SImode);
4491 if ((INTVAL (offset) & 2) == 2)
4493 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4494 new = gen_rtx_MEM (SImode,
4495 plus_constant (base,
4497 MEM_COPY_ATTRIBUTES (new, operands[1]);
4498 emit_insn (gen_movsi (reg, new));
4502 new = gen_rtx_MEM (SImode,
4503 XEXP (operands[1], 0));
4504 MEM_COPY_ATTRIBUTES (new, operands[1]);
4505 emit_insn (gen_rotated_loadsi (reg, new));
4508 operands[1] = gen_lowpart (HImode, reg);
4512 emit_insn (gen_movhi_bigend (operands[0],
4520 /* Handle loading a large integer during reload */
4521 else if (GET_CODE (operands[1]) == CONST_INT
4522 && !const_ok_for_arm (INTVAL (operands[1]))
4523 && !const_ok_for_arm (~INTVAL (operands[1])))
4525 /* Writing a constant to memory needs a scratch, which should
4526 be handled with SECONDARY_RELOADs. */
4527 if (GET_CODE (operands[0]) != REG)
4530 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4531 emit_insn (gen_movsi (operands[0], operands[1]));
4535 else /* TARGET_THUMB */
4537 if (!no_new_pseudos)
4539 if (GET_CODE (operands[0]) != REG)
4540 operands[1] = force_reg (HImode, operands[1]);
4542 /* ??? We shouldn't really get invalid addresses here, but this can
4543 happen if we are passed a SP (never OK for HImode/QImode) or
4544 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4545 HImode/QImode) relative address. */
4546 /* ??? This should perhaps be fixed elsewhere, for instance, in
4547 fixup_stack_1, by checking for other kinds of invalid addresses,
4548 e.g. a bare reference to a virtual register. This may confuse the
4549 alpha though, which must handle this case differently. */
4550 if (GET_CODE (operands[0]) == MEM
4551 && !memory_address_p (GET_MODE (operands[0]),
4552 XEXP (operands[0], 0)))
4554 = replace_equiv_address (operands[0],
4555 copy_to_reg (XEXP (operands[0], 0)));
4557 if (GET_CODE (operands[1]) == MEM
4558 && !memory_address_p (GET_MODE (operands[1]),
4559 XEXP (operands[1], 0)))
4561 = replace_equiv_address (operands[1],
4562 copy_to_reg (XEXP (operands[1], 0)));
4564 /* Handle loading a large integer during reload */
4565 else if (GET_CODE (operands[1]) == CONST_INT
4566 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4568 /* Writing a constant to memory needs a scratch, which should
4569 be handled with SECONDARY_RELOADs. */
4570 if (GET_CODE (operands[0]) != REG)
4573 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4574 emit_insn (gen_movsi (operands[0], operands[1]));
4581 (define_insn "*thumb_movhi_insn"
4582 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4583 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4585 && ( register_operand (operands[0], HImode)
4586 || register_operand (operands[1], HImode))"
4588 switch (which_alternative)
4590 case 0: return \"add %0, %1, #0\";
4591 case 2: return \"strh %1, %0\";
4592 case 3: return \"mov %0, %1\";
4593 case 4: return \"mov %0, %1\";
4594 case 5: return \"mov %0, %1\";
4597 /* The stack pointer can end up being taken as an index register.
4598 Catch this case here and deal with it. */
4599 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4600 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4601 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4604 ops[0] = operands[0];
4605 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4607 output_asm_insn (\"mov %0, %1\", ops);
4609 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4612 return \"ldrh %0, %1\";
4614 [(set_attr "length" "2,4,2,2,2,2")
4615 (set_attr "type" "*,load,store1,*,*,*")
4616 (set_attr "pool_range" "*,64,*,*,*,*")]
4620 (define_insn "rotated_loadsi"
4621 [(set (match_operand:SI 0 "s_register_operand" "=r")
4622 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4624 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4629 ops[0] = operands[0];
4630 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4631 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4634 [(set_attr "type" "load")
4635 (set_attr "predicable" "yes")]
4638 (define_expand "movhi_bytes"
4639 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4641 (zero_extend:SI (match_dup 6)))
4642 (set (match_operand:SI 0 "" "")
4643 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4648 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4650 mem1 = gen_rtx_MEM (QImode, addr);
4651 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4652 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4653 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4654 operands[0] = gen_lowpart (SImode, operands[0]);
4656 operands[2] = gen_reg_rtx (SImode);
4657 operands[3] = gen_reg_rtx (SImode);
4660 if (BYTES_BIG_ENDIAN)
4662 operands[4] = operands[2];
4663 operands[5] = operands[3];
4667 operands[4] = operands[3];
4668 operands[5] = operands[2];
4673 (define_expand "movhi_bigend"
4675 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4678 (ashiftrt:SI (match_dup 2) (const_int 16)))
4679 (set (match_operand:HI 0 "s_register_operand" "")
4680 (subreg:HI (match_dup 3) 0))]
4683 operands[2] = gen_reg_rtx (SImode);
4684 operands[3] = gen_reg_rtx (SImode);
4688 ;; Pattern to recognise insn generated default case above
4689 (define_insn "*movhi_insn_arch4"
4690 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4691 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4694 && (GET_CODE (operands[1]) != CONST_INT
4695 || const_ok_for_arm (INTVAL (operands[1]))
4696 || const_ok_for_arm (~INTVAL (operands[1])))"
4698 mov%?\\t%0, %1\\t%@ movhi
4699 mvn%?\\t%0, #%B1\\t%@ movhi
4700 str%?h\\t%1, %0\\t%@ movhi
4701 ldr%?h\\t%0, %1\\t%@ movhi"
4702 [(set_attr "type" "*,*,store1,load")
4703 (set_attr "predicable" "yes")
4704 (set_attr "pool_range" "*,*,*,256")
4705 (set_attr "neg_pool_range" "*,*,*,244")]
4708 (define_insn "*movhi_insn_littleend"
4709 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4710 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4713 && !BYTES_BIG_ENDIAN
4714 && !TARGET_MMU_TRAPS
4715 && (GET_CODE (operands[1]) != CONST_INT
4716 || const_ok_for_arm (INTVAL (operands[1]))
4717 || const_ok_for_arm (~INTVAL (operands[1])))"
4719 mov%?\\t%0, %1\\t%@ movhi
4720 mvn%?\\t%0, #%B1\\t%@ movhi
4721 ldr%?\\t%0, %1\\t%@ movhi"
4722 [(set_attr "type" "*,*,load")
4723 (set_attr "predicable" "yes")
4724 (set_attr "pool_range" "4096")
4725 (set_attr "neg_pool_range" "4084")]
4728 (define_insn "*movhi_insn_bigend"
4729 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4730 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4734 && !TARGET_MMU_TRAPS
4735 && (GET_CODE (operands[1]) != CONST_INT
4736 || const_ok_for_arm (INTVAL (operands[1]))
4737 || const_ok_for_arm (~INTVAL (operands[1])))"
4739 mov%?\\t%0, %1\\t%@ movhi
4740 mvn%?\\t%0, #%B1\\t%@ movhi
4741 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4742 [(set_attr "type" "*,*,load")
4743 (set_attr "predicable" "yes")
4744 (set_attr "length" "4,4,8")
4745 (set_attr "pool_range" "*,*,4092")
4746 (set_attr "neg_pool_range" "*,*,4084")]
4749 (define_insn "*loadhi_si_bigend"
4750 [(set (match_operand:SI 0 "s_register_operand" "=r")
4751 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4755 && !TARGET_MMU_TRAPS"
4756 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4757 [(set_attr "type" "load")
4758 (set_attr "predicable" "yes")
4759 (set_attr "pool_range" "4096")
4760 (set_attr "neg_pool_range" "4084")]
4763 (define_insn "*movhi_bytes"
4764 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4765 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4766 "TARGET_ARM && TARGET_MMU_TRAPS"
4768 mov%?\\t%0, %1\\t%@ movhi
4769 mvn%?\\t%0, #%B1\\t%@ movhi"
4770 [(set_attr "predicable" "yes")]
4773 (define_insn "thumb_movhi_clobber"
4774 [(set (match_operand:HI 0 "memory_operand" "=m")
4775 (match_operand:HI 1 "register_operand" "l"))
4776 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4782 ;; We use a DImode scratch because we may occasionally need an additional
4783 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4784 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4785 (define_expand "reload_outhi"
4786 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4787 (match_operand:HI 1 "s_register_operand" "r")
4788 (match_operand:DI 2 "s_register_operand" "=&l")])]
4791 arm_reload_out_hi (operands);
4793 thumb_reload_out_hi (operands);
4798 (define_expand "reload_inhi"
4799 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4800 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4801 (match_operand:DI 2 "s_register_operand" "=&r")])]
4802 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4805 arm_reload_in_hi (operands);
4807 thumb_reload_out_hi (operands);
4811 (define_expand "movqi"
4812 [(set (match_operand:QI 0 "general_operand" "")
4813 (match_operand:QI 1 "general_operand" ""))]
4818 /* Everything except mem = const or mem = mem can be done easily */
4820 if (!no_new_pseudos)
4822 if (GET_CODE (operands[1]) == CONST_INT)
4824 rtx reg = gen_reg_rtx (SImode);
4826 emit_insn (gen_movsi (reg, operands[1]));
4827 operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
4829 if (GET_CODE (operands[0]) == MEM)
4830 operands[1] = force_reg (QImode, operands[1]);
4833 else /* TARGET_THUMB */
4835 if (!no_new_pseudos)
4837 if (GET_CODE (operands[0]) != REG)
4838 operands[1] = force_reg (QImode, operands[1]);
4840 /* ??? We shouldn't really get invalid addresses here, but this can
4841 happen if we are passed a SP (never OK for HImode/QImode) or
4842 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4843 HImode/QImode) relative address. */
4844 /* ??? This should perhaps be fixed elsewhere, for instance, in
4845 fixup_stack_1, by checking for other kinds of invalid addresses,
4846 e.g. a bare reference to a virtual register. This may confuse the
4847 alpha though, which must handle this case differently. */
4848 if (GET_CODE (operands[0]) == MEM
4849 && !memory_address_p (GET_MODE (operands[0]),
4850 XEXP (operands[0], 0)))
4852 = replace_equiv_address (operands[0],
4853 copy_to_reg (XEXP (operands[0], 0)));
4854 if (GET_CODE (operands[1]) == MEM
4855 && !memory_address_p (GET_MODE (operands[1]),
4856 XEXP (operands[1], 0)))
4858 = replace_equiv_address (operands[1],
4859 copy_to_reg (XEXP (operands[1], 0)));
4861 /* Handle loading a large integer during reload */
4862 else if (GET_CODE (operands[1]) == CONST_INT
4863 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4865 /* Writing a constant to memory needs a scratch, which should
4866 be handled with SECONDARY_RELOADs. */
4867 if (GET_CODE (operands[0]) != REG)
4870 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4871 emit_insn (gen_movsi (operands[0], operands[1]));
4879 (define_insn "*arm_movqi_insn"
4880 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4881 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4883 && ( register_operand (operands[0], QImode)
4884 || register_operand (operands[1], QImode))"
4890 [(set_attr "type" "*,*,load,store1")
4891 (set_attr "predicable" "yes")]
4894 (define_insn "*thumb_movqi_insn"
4895 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4896 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4898 && ( register_operand (operands[0], QImode)
4899 || register_operand (operands[1], QImode))"
4907 [(set_attr "length" "2")
4908 (set_attr "type" "*,load,store1,*,*,*")
4909 (set_attr "pool_range" "*,32,*,*,*,*")]
4912 (define_expand "movsf"
4913 [(set (match_operand:SF 0 "general_operand" "")
4914 (match_operand:SF 1 "general_operand" ""))]
4919 if (GET_CODE (operands[0]) == MEM)
4920 operands[1] = force_reg (SFmode, operands[1]);
4922 else /* TARGET_THUMB */
4924 if (!no_new_pseudos)
4926 if (GET_CODE (operands[0]) != REG)
4927 operands[1] = force_reg (SFmode, operands[1]);
4934 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4935 (match_operand:SF 1 "immediate_operand" ""))]
4937 && !TARGET_HARD_FLOAT
4939 && GET_CODE (operands[1]) == CONST_DOUBLE"
4940 [(set (match_dup 2) (match_dup 3))]
4942 operands[2] = gen_lowpart (SImode, operands[0]);
4943 operands[3] = gen_lowpart (SImode, operands[1]);
4944 if (operands[2] == 0 || operands[3] == 0)
4949 (define_insn "*arm_movsf_hard_insn"
4950 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4951 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4953 && TARGET_HARD_FLOAT
4954 && (GET_CODE (operands[0]) != MEM
4955 || register_operand (operands[1], SFmode))"
4961 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4962 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4964 ldr%?\\t%0, %1\\t%@ float
4965 str%?\\t%1, %0\\t%@ float"
4966 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4967 (set_attr "predicable" "yes")
4969 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4970 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4971 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4974 ;; Exactly the same as above, except that all `f' cases are deleted.
4975 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4976 ;; when -msoft-float.
4978 (define_insn "*arm_movsf_soft_insn"
4979 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4980 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4982 && TARGET_SOFT_FLOAT
4983 && (GET_CODE (operands[0]) != MEM
4984 || register_operand (operands[1], SFmode))"
4987 ldr%?\\t%0, %1\\t%@ float
4988 str%?\\t%1, %0\\t%@ float"
4989 [(set_attr "length" "4,4,4")
4990 (set_attr "predicable" "yes")
4991 (set_attr "type" "*,load,store1")
4992 (set_attr "pool_range" "*,4096,*")
4993 (set_attr "neg_pool_range" "*,4084,*")]
4996 ;;; ??? This should have alternatives for constants.
4997 (define_insn "*thumb_movsf_insn"
4998 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4999 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5001 && ( register_operand (operands[0], SFmode)
5002 || register_operand (operands[1], SFmode))"
5011 [(set_attr "length" "2")
5012 (set_attr "type" "*,load,store1,load,store1,*,*")
5013 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5016 (define_expand "movdf"
5017 [(set (match_operand:DF 0 "general_operand" "")
5018 (match_operand:DF 1 "general_operand" ""))]
5023 if (GET_CODE (operands[0]) == MEM)
5024 operands[1] = force_reg (DFmode, operands[1]);
5026 else /* TARGET_THUMB */
5028 if (!no_new_pseudos)
5030 if (GET_CODE (operands[0]) != REG)
5031 operands[1] = force_reg (DFmode, operands[1]);
5037 ;; Reloading a df mode value stored in integer regs to memory can require a
5039 (define_expand "reload_outdf"
5040 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5041 (match_operand:DF 1 "s_register_operand" "r")
5042 (match_operand:SI 2 "s_register_operand" "=&r")]
5046 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5049 operands[2] = XEXP (operands[0], 0);
5050 else if (code == POST_INC || code == PRE_DEC)
5052 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5053 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5054 emit_insn (gen_movdi (operands[0], operands[1]));
5057 else if (code == PRE_INC)
5059 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5061 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5064 else if (code == POST_DEC)
5065 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5067 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5068 XEXP (XEXP (operands[0], 0), 1)));
5070 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5073 if (code == POST_DEC)
5074 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5080 (define_insn "*movdf_hard_insn"
5081 [(set (match_operand:DF 0 "nonimmediate_operand"
5082 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5083 (match_operand:DF 1 "general_operand"
5084 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5086 && TARGET_HARD_FLOAT
5087 && (GET_CODE (operands[0]) != MEM
5088 || register_operand (operands[1], DFmode))"
5091 switch (which_alternative)
5094 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5095 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5096 case 2: case 3: case 4: return output_move_double (operands);
5097 case 5: return \"mvf%?d\\t%0, %1\";
5098 case 6: return \"mnf%?d\\t%0, #%N1\";
5099 case 7: return \"ldf%?d\\t%0, %1\";
5100 case 8: return \"stf%?d\\t%1, %0\";
5101 case 9: return output_mov_double_fpu_from_arm (operands);
5102 case 10: return output_mov_double_arm_from_fpu (operands);
5106 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5107 (set_attr "predicable" "yes")
5109 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5110 (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")
5111 (set_attr "neg_pool_range" "*,*,*,*,244,*,*,1012,*,*,*")]
5114 ;; Software floating point version. This is essentially the same as movdi.
5115 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5118 (define_insn "*movdf_soft_insn"
5119 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5120 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5121 "TARGET_ARM && TARGET_SOFT_FLOAT
5123 "* return output_move_double (operands);"
5124 [(set_attr "length" "8,8,8")
5125 (set_attr "type" "*,load,store2")
5126 (set_attr "pool_range" "252")
5127 (set_attr "neg_pool_range" "244")]
5130 ;;; ??? This should have alternatives for constants.
5131 ;;; ??? This was originally identical to the movdi_insn pattern.
5132 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5133 ;;; thumb_reorg with a memory reference.
5134 (define_insn "*thumb_movdf_insn"
5135 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5136 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5138 && ( register_operand (operands[0], DFmode)
5139 || register_operand (operands[1], DFmode))"
5141 switch (which_alternative)
5145 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5146 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5147 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5149 return \"ldmia\\t%1, {%0, %H0}\";
5151 return \"stmia\\t%0, {%1, %H1}\";
5153 return thumb_load_double_from_address (operands);
5155 operands[2] = gen_rtx (MEM, SImode,
5156 plus_constant (XEXP (operands[0], 0), 4));
5157 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5160 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5161 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5162 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5165 [(set_attr "length" "4,2,2,6,4,4")
5166 (set_attr "type" "*,load,store2,load,store2,*")
5167 (set_attr "pool_range" "*,*,*,1020,*,*")]
5171 (define_expand "movxf"
5172 [(set (match_operand:XF 0 "general_operand" "")
5173 (match_operand:XF 1 "general_operand" ""))]
5174 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5177 ;; Even when the XFmode patterns aren't enabled, we enable this after
5178 ;; reloading so that we can push floating point registers in the prologue.
5180 (define_insn "*movxf_hard_insn"
5181 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5182 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5183 "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5185 switch (which_alternative)
5188 case 0: return \"mvf%?e\\t%0, %1\";
5189 case 1: return \"mnf%?e\\t%0, #%N1\";
5190 case 2: return \"ldf%?e\\t%0, %1\";
5191 case 3: return \"stf%?e\\t%1, %0\";
5192 case 4: return output_mov_long_double_fpu_from_arm (operands);
5193 case 5: return output_mov_long_double_arm_from_fpu (operands);
5194 case 6: return output_mov_long_double_arm_from_arm (operands);
5197 [(set_attr "length" "4,4,4,4,8,8,12")
5198 (set_attr "predicable" "yes")
5199 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5200 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5201 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*")]
5205 ;; load- and store-multiple insns
5206 ;; The arm can load/store any set of registers, provided that they are in
5207 ;; ascending order; but that is beyond GCC so stick with what it knows.
5209 (define_expand "load_multiple"
5210 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5211 (match_operand:SI 1 "" ""))
5212 (use (match_operand:SI 2 "" ""))])]
5215 /* Support only fixed point registers. */
5216 if (GET_CODE (operands[2]) != CONST_INT
5217 || INTVAL (operands[2]) > 14
5218 || INTVAL (operands[2]) < 2
5219 || GET_CODE (operands[1]) != MEM
5220 || GET_CODE (operands[0]) != REG
5221 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5222 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5226 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5227 force_reg (SImode, XEXP (operands[1], 0)),
5228 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5229 MEM_IN_STRUCT_P(operands[1]),
5230 MEM_SCALAR_P (operands[1]));
5234 ;; Load multiple with write-back
5236 (define_insn "*ldmsi_postinc4"
5237 [(match_parallel 0 "load_multiple_operation"
5238 [(set (match_operand:SI 1 "s_register_operand" "=r")
5239 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5241 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5242 (mem:SI (match_dup 2)))
5243 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5244 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5245 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5246 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5247 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5248 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5249 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5250 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5251 [(set_attr "type" "load")
5252 (set_attr "predicable" "yes")]
5255 (define_insn "*ldmsi_postinc3"
5256 [(match_parallel 0 "load_multiple_operation"
5257 [(set (match_operand:SI 1 "s_register_operand" "=r")
5258 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5260 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5261 (mem:SI (match_dup 2)))
5262 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5263 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5264 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5265 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5266 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5267 "ldm%?ia\\t%1!, {%3, %4, %5}"
5268 [(set_attr "type" "load")
5269 (set_attr "predicable" "yes")]
5272 (define_insn "*ldmsi_postinc2"
5273 [(match_parallel 0 "load_multiple_operation"
5274 [(set (match_operand:SI 1 "s_register_operand" "=r")
5275 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5277 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5278 (mem:SI (match_dup 2)))
5279 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5280 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5281 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5282 "ldm%?ia\\t%1!, {%3, %4}"
5283 [(set_attr "type" "load")
5284 (set_attr "predicable" "yes")]
5287 ;; Ordinary load multiple
5289 (define_insn "*ldmsi4"
5290 [(match_parallel 0 "load_multiple_operation"
5291 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5292 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5293 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5294 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5295 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5296 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5297 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5298 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5299 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5300 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5301 [(set_attr "type" "load")
5302 (set_attr "predicable" "yes")]
5305 (define_insn "*ldmsi3"
5306 [(match_parallel 0 "load_multiple_operation"
5307 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5308 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5309 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5310 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5311 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5312 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5313 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5314 "ldm%?ia\\t%1, {%2, %3, %4}"
5315 [(set_attr "type" "load")
5316 (set_attr "predicable" "yes")]
5319 (define_insn "*ldmsi2"
5320 [(match_parallel 0 "load_multiple_operation"
5321 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5322 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5323 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5324 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5325 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5326 "ldm%?ia\\t%1, {%2, %3}"
5327 [(set_attr "type" "load")
5328 (set_attr "predicable" "yes")]
5331 (define_expand "store_multiple"
5332 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5333 (match_operand:SI 1 "" ""))
5334 (use (match_operand:SI 2 "" ""))])]
5337 /* Support only fixed point registers */
5338 if (GET_CODE (operands[2]) != CONST_INT
5339 || INTVAL (operands[2]) > 14
5340 || INTVAL (operands[2]) < 2
5341 || GET_CODE (operands[1]) != REG
5342 || GET_CODE (operands[0]) != MEM
5343 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5344 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5348 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5349 force_reg (SImode, XEXP (operands[0], 0)),
5350 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5351 MEM_IN_STRUCT_P(operands[0]),
5352 MEM_SCALAR_P (operands[0]));
5356 ;; Store multiple with write-back
5358 (define_insn "*stmsi_postinc4"
5359 [(match_parallel 0 "store_multiple_operation"
5360 [(set (match_operand:SI 1 "s_register_operand" "=r")
5361 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5363 (set (mem:SI (match_dup 2))
5364 (match_operand:SI 3 "arm_hard_register_operand" ""))
5365 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5366 (match_operand:SI 4 "arm_hard_register_operand" ""))
5367 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5368 (match_operand:SI 5 "arm_hard_register_operand" ""))
5369 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5370 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5371 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5372 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5373 [(set_attr "predicable" "yes")
5374 (set_attr "type" "store4")]
5377 (define_insn "*stmsi_postinc3"
5378 [(match_parallel 0 "store_multiple_operation"
5379 [(set (match_operand:SI 1 "s_register_operand" "=r")
5380 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5382 (set (mem:SI (match_dup 2))
5383 (match_operand:SI 3 "arm_hard_register_operand" ""))
5384 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5385 (match_operand:SI 4 "arm_hard_register_operand" ""))
5386 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5387 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5388 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5389 "stm%?ia\\t%1!, {%3, %4, %5}"
5390 [(set_attr "predicable" "yes")
5391 (set_attr "type" "store3")]
5394 (define_insn "*stmsi_postinc2"
5395 [(match_parallel 0 "store_multiple_operation"
5396 [(set (match_operand:SI 1 "s_register_operand" "=r")
5397 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5399 (set (mem:SI (match_dup 2))
5400 (match_operand:SI 3 "arm_hard_register_operand" ""))
5401 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5402 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5403 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5404 "stm%?ia\\t%1!, {%3, %4}"
5405 [(set_attr "predicable" "yes")
5406 (set_attr "type" "store2")]
5409 ;; Ordinary store multiple
5411 (define_insn "*stmsi4"
5412 [(match_parallel 0 "store_multiple_operation"
5413 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5414 (match_operand:SI 2 "arm_hard_register_operand" ""))
5415 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5416 (match_operand:SI 3 "arm_hard_register_operand" ""))
5417 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5418 (match_operand:SI 4 "arm_hard_register_operand" ""))
5419 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5420 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5421 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5422 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5423 [(set_attr "predicable" "yes")
5424 (set_attr "type" "store4")]
5427 (define_insn "*stmsi3"
5428 [(match_parallel 0 "store_multiple_operation"
5429 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5430 (match_operand:SI 2 "arm_hard_register_operand" ""))
5431 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5432 (match_operand:SI 3 "arm_hard_register_operand" ""))
5433 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5434 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5435 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5436 "stm%?ia\\t%1, {%2, %3, %4}"
5437 [(set_attr "predicable" "yes")
5438 (set_attr "type" "store3")]
5441 (define_insn "*stmsi2"
5442 [(match_parallel 0 "store_multiple_operation"
5443 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5444 (match_operand:SI 2 "arm_hard_register_operand" ""))
5445 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5446 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5447 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5448 "stm%?ia\\t%1, {%2, %3}"
5449 [(set_attr "predicable" "yes")
5450 (set_attr "type" "store2")]
5453 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5454 ;; We could let this apply for blocks of less than this, but it clobbers so
5455 ;; many registers that there is then probably a better way.
5457 (define_expand "movstrqi"
5458 [(match_operand:BLK 0 "general_operand" "")
5459 (match_operand:BLK 1 "general_operand" "")
5460 (match_operand:SI 2 "const_int_operand" "")
5461 (match_operand:SI 3 "const_int_operand" "")]
5466 if (arm_gen_movstrqi (operands))
5470 else /* TARGET_THUMB */
5472 if ( INTVAL (operands[3]) != 4
5473 || INTVAL (operands[2]) > 48)
5476 thumb_expand_movstrqi (operands);
5482 ;; Thumb block-move insns
5484 (define_insn "movmem12b"
5485 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5486 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5487 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5488 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5489 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5490 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5491 (set (match_operand:SI 0 "register_operand" "=l")
5492 (plus:SI (match_dup 2) (const_int 12)))
5493 (set (match_operand:SI 1 "register_operand" "=l")
5494 (plus:SI (match_dup 3) (const_int 12)))
5495 (clobber (match_scratch:SI 4 "=&l"))
5496 (clobber (match_scratch:SI 5 "=&l"))
5497 (clobber (match_scratch:SI 6 "=&l"))]
5499 "* return thumb_output_move_mem_multiple (3, operands);"
5500 [(set_attr "length" "4")
5501 ; This isn't entirely accurate... It loads as well, but in terms of
5502 ; scheduling the following insn it is better to consider it as a store
5503 (set_attr "type" "store3")]
5506 (define_insn "movmem8b"
5507 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5508 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5509 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5510 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5511 (set (match_operand:SI 0 "register_operand" "=l")
5512 (plus:SI (match_dup 2) (const_int 8)))
5513 (set (match_operand:SI 1 "register_operand" "=l")
5514 (plus:SI (match_dup 3) (const_int 8)))
5515 (clobber (match_scratch:SI 4 "=&l"))
5516 (clobber (match_scratch:SI 5 "=&l"))]
5518 "* return thumb_output_move_mem_multiple (2, operands);"
5519 [(set_attr "length" "4")
5520 ; This isn't entirely accurate... It loads as well, but in terms of
5521 ; scheduling the following insn it is better to consider it as a store
5522 (set_attr "type" "store2")]
5527 ;; Compare & branch insns
5528 ;; The range calcualations are based as follows:
5529 ;; For forward branches, the address calculation returns the address of
5530 ;; the next instruction. This is 2 beyond the branch instruction.
5531 ;; For backward branches, the address calculation returns the address of
5532 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5533 ;; instruction for the shortest sequence, and 4 before the branch instruction
5534 ;; if we have to jump around an unconditional branch.
5535 ;; To the basic branch range the PC offset must be added (this is +4).
5536 ;; So for forward branches we have
5537 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5538 ;; And for backward branches we have
5539 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5541 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5542 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5544 (define_insn "cbranchsi4"
5547 (match_operator 0 "arm_comparison_operator"
5548 [(match_operand:SI 1 "register_operand" "l,r")
5549 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5550 (label_ref (match_operand 3 "" ""))
5554 output_asm_insn (\"cmp\\t%1, %2\", operands);
5555 switch (get_attr_length (insn))
5557 case 4: return \"b%d0\\t%l3\";
5558 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5559 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5562 [(set (attr "far_jump")
5564 (eq_attr "length" "8")
5565 (const_string "yes")
5566 (const_string "no")))
5567 (set (attr "length")
5569 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5570 (le (minus (match_dup 3) (pc)) (const_int 256)))
5573 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5574 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5579 (define_insn "*negated_cbranchsi4"
5582 (match_operator 0 "arm_comparison_operator"
5583 [(match_operand:SI 1 "register_operand" "l")
5584 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5585 (label_ref (match_operand 3 "" ""))
5589 output_asm_insn (\"cmn\\t%1, %2\", operands);
5590 switch (get_attr_length (insn))
5592 case 4: return \"b%d0\\t%l3\";
5593 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5594 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5597 [(set (attr "far_jump")
5599 (eq_attr "length" "8")
5600 (const_string "yes")
5601 (const_string "no")))
5602 (set (attr "length")
5604 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5605 (le (minus (match_dup 3) (pc)) (const_int 256)))
5608 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5609 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5615 ;; Comparison and test insns
5617 (define_expand "cmpsi"
5618 [(match_operand:SI 0 "s_register_operand" "")
5619 (match_operand:SI 1 "arm_add_operand" "")]
5622 arm_compare_op0 = operands[0];
5623 arm_compare_op1 = operands[1];
5628 (define_expand "cmpsf"
5629 [(match_operand:SF 0 "s_register_operand" "")
5630 (match_operand:SF 1 "fpu_rhs_operand" "")]
5631 "TARGET_ARM && TARGET_HARD_FLOAT"
5633 arm_compare_op0 = operands[0];
5634 arm_compare_op1 = operands[1];
5639 (define_expand "cmpdf"
5640 [(match_operand:DF 0 "s_register_operand" "")
5641 (match_operand:DF 1 "fpu_rhs_operand" "")]
5642 "TARGET_ARM && TARGET_HARD_FLOAT"
5644 arm_compare_op0 = operands[0];
5645 arm_compare_op1 = operands[1];
5650 (define_expand "cmpxf"
5651 [(match_operand:XF 0 "s_register_operand" "")
5652 (match_operand:XF 1 "fpu_rhs_operand" "")]
5653 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5655 arm_compare_op0 = operands[0];
5656 arm_compare_op1 = operands[1];
5661 (define_insn "*arm_cmpsi_insn"
5662 [(set (reg:CC CC_REGNUM)
5663 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5664 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5669 [(set_attr "conds" "set")]
5672 (define_insn "*cmpsi_shiftsi"
5673 [(set (reg:CC CC_REGNUM)
5674 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5675 (match_operator:SI 3 "shift_operator"
5676 [(match_operand:SI 1 "s_register_operand" "r")
5677 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5680 [(set_attr "conds" "set")
5681 (set_attr "shift" "1")
5685 (define_insn "*cmpsi_shiftsi_swp"
5686 [(set (reg:CC_SWP CC_REGNUM)
5687 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5688 [(match_operand:SI 1 "s_register_operand" "r")
5689 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5690 (match_operand:SI 0 "s_register_operand" "r")))]
5693 [(set_attr "conds" "set")
5694 (set_attr "shift" "1")
5698 (define_insn "*cmpsi_neg_shiftsi"
5699 [(set (reg:CC CC_REGNUM)
5700 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5701 (neg:SI (match_operator:SI 3 "shift_operator"
5702 [(match_operand:SI 1 "s_register_operand" "r")
5703 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5706 [(set_attr "conds" "set")
5707 (set_attr "shift" "1")
5711 (define_insn "*cmpsf_insn"
5712 [(set (reg:CCFP CC_REGNUM)
5713 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5714 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5715 "TARGET_ARM && TARGET_HARD_FLOAT"
5719 [(set_attr "conds" "set")
5720 (set_attr "type" "f_2_r")]
5723 (define_insn "*cmpdf_insn"
5724 [(set (reg:CCFP CC_REGNUM)
5725 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5726 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5727 "TARGET_ARM && TARGET_HARD_FLOAT"
5731 [(set_attr "conds" "set")
5732 (set_attr "type" "f_2_r")]
5735 (define_insn "*cmpesfdf_df"
5736 [(set (reg:CCFP CC_REGNUM)
5737 (compare:CCFP (float_extend:DF
5738 (match_operand:SF 0 "s_register_operand" "f,f"))
5739 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5740 "TARGET_ARM && TARGET_HARD_FLOAT"
5744 [(set_attr "conds" "set")
5745 (set_attr "type" "f_2_r")]
5748 (define_insn "*cmpdf_esfdf"
5749 [(set (reg:CCFP CC_REGNUM)
5750 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5752 (match_operand:SF 1 "s_register_operand" "f"))))]
5753 "TARGET_ARM && TARGET_HARD_FLOAT"
5755 [(set_attr "conds" "set")
5756 (set_attr "type" "f_2_r")]
5759 (define_insn "*cmpxf_insn"
5760 [(set (reg:CCFP CC_REGNUM)
5761 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5762 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5763 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5767 [(set_attr "conds" "set")
5768 (set_attr "type" "f_2_r")]
5771 (define_insn "*cmpsf_trap"
5772 [(set (reg:CCFPE CC_REGNUM)
5773 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5774 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5775 "TARGET_ARM && TARGET_HARD_FLOAT"
5779 [(set_attr "conds" "set")
5780 (set_attr "type" "f_2_r")]
5783 (define_insn "*cmpdf_trap"
5784 [(set (reg:CCFPE CC_REGNUM)
5785 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5786 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5787 "TARGET_ARM && TARGET_HARD_FLOAT"
5791 [(set_attr "conds" "set")
5792 (set_attr "type" "f_2_r")]
5795 (define_insn "*cmp_esfdf_df_trap"
5796 [(set (reg:CCFPE CC_REGNUM)
5797 (compare:CCFPE (float_extend:DF
5798 (match_operand:SF 0 "s_register_operand" "f,f"))
5799 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5800 "TARGET_ARM && TARGET_HARD_FLOAT"
5804 [(set_attr "conds" "set")
5805 (set_attr "type" "f_2_r")]
5808 (define_insn "*cmp_df_esfdf_trap"
5809 [(set (reg:CCFPE CC_REGNUM)
5810 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5812 (match_operand:SF 1 "s_register_operand" "f"))))]
5813 "TARGET_ARM && TARGET_HARD_FLOAT"
5815 [(set_attr "conds" "set")
5816 (set_attr "type" "f_2_r")]
5819 (define_insn "*cmpxf_trap"
5820 [(set (reg:CCFPE CC_REGNUM)
5821 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5822 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5823 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5827 [(set_attr "conds" "set")
5828 (set_attr "type" "f_2_r")]
5831 ; This insn allows redundant compares to be removed by cse, nothing should
5832 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5833 ; is deleted later on. The match_dup will match the mode here, so that
5834 ; mode changes of the condition codes aren't lost by this even though we don't
5835 ; specify what they are.
5837 (define_insn "*deleted_compare"
5838 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5840 "\\t%@ deleted compare"
5841 [(set_attr "conds" "set")
5842 (set_attr "length" "0")]
5846 ;; Conditional branch insns
5848 (define_expand "beq"
5850 (if_then_else (eq (match_dup 1) (const_int 0))
5851 (label_ref (match_operand 0 "" ""))
5854 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5857 (define_expand "bne"
5859 (if_then_else (ne (match_dup 1) (const_int 0))
5860 (label_ref (match_operand 0 "" ""))
5863 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5866 (define_expand "bgt"
5868 (if_then_else (gt (match_dup 1) (const_int 0))
5869 (label_ref (match_operand 0 "" ""))
5872 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5875 (define_expand "ble"
5877 (if_then_else (le (match_dup 1) (const_int 0))
5878 (label_ref (match_operand 0 "" ""))
5881 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5884 (define_expand "bge"
5886 (if_then_else (ge (match_dup 1) (const_int 0))
5887 (label_ref (match_operand 0 "" ""))
5890 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5893 (define_expand "blt"
5895 (if_then_else (lt (match_dup 1) (const_int 0))
5896 (label_ref (match_operand 0 "" ""))
5899 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5902 (define_expand "bgtu"
5904 (if_then_else (gtu (match_dup 1) (const_int 0))
5905 (label_ref (match_operand 0 "" ""))
5908 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5911 (define_expand "bleu"
5913 (if_then_else (leu (match_dup 1) (const_int 0))
5914 (label_ref (match_operand 0 "" ""))
5917 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5920 (define_expand "bgeu"
5922 (if_then_else (geu (match_dup 1) (const_int 0))
5923 (label_ref (match_operand 0 "" ""))
5926 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5929 (define_expand "bltu"
5931 (if_then_else (ltu (match_dup 1) (const_int 0))
5932 (label_ref (match_operand 0 "" ""))
5935 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5938 (define_expand "bunordered"
5940 (if_then_else (unordered (match_dup 1) (const_int 0))
5941 (label_ref (match_operand 0 "" ""))
5943 "TARGET_ARM && TARGET_HARD_FLOAT"
5944 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5948 (define_expand "bordered"
5950 (if_then_else (ordered (match_dup 1) (const_int 0))
5951 (label_ref (match_operand 0 "" ""))
5953 "TARGET_ARM && TARGET_HARD_FLOAT"
5954 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5958 (define_expand "bungt"
5960 (if_then_else (ungt (match_dup 1) (const_int 0))
5961 (label_ref (match_operand 0 "" ""))
5963 "TARGET_ARM && TARGET_HARD_FLOAT"
5964 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5967 (define_expand "bunlt"
5969 (if_then_else (unlt (match_dup 1) (const_int 0))
5970 (label_ref (match_operand 0 "" ""))
5972 "TARGET_ARM && TARGET_HARD_FLOAT"
5973 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5976 (define_expand "bunge"
5978 (if_then_else (unge (match_dup 1) (const_int 0))
5979 (label_ref (match_operand 0 "" ""))
5981 "TARGET_ARM && TARGET_HARD_FLOAT"
5982 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5985 (define_expand "bunle"
5987 (if_then_else (unle (match_dup 1) (const_int 0))
5988 (label_ref (match_operand 0 "" ""))
5990 "TARGET_ARM && TARGET_HARD_FLOAT"
5991 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5994 ;; The following two patterns need two branch instructions, since there is
5995 ;; no single instruction that will handle all cases.
5996 (define_expand "buneq"
5998 (if_then_else (uneq (match_dup 1) (const_int 0))
5999 (label_ref (match_operand 0 "" ""))
6001 "TARGET_ARM && TARGET_HARD_FLOAT"
6002 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6005 (define_expand "bltgt"
6007 (if_then_else (ltgt (match_dup 1) (const_int 0))
6008 (label_ref (match_operand 0 "" ""))
6010 "TARGET_ARM && TARGET_HARD_FLOAT"
6011 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6015 ;; Patterns to match conditional branch insns.
6018 ; Special pattern to match UNEQ.
6019 (define_insn "*arm_buneq"
6021 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6022 (label_ref (match_operand 0 "" ""))
6024 "TARGET_ARM && TARGET_HARD_FLOAT"
6026 if (arm_ccfsm_state != 0)
6029 return \"bvs\\t%l0;beq\\t%l0\";
6031 [(set_attr "conds" "jump_clob")
6032 (set_attr "length" "8")]
6035 ; Special pattern to match LTGT.
6036 (define_insn "*arm_bltgt"
6038 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6039 (label_ref (match_operand 0 "" ""))
6041 "TARGET_ARM && TARGET_HARD_FLOAT"
6043 if (arm_ccfsm_state != 0)
6046 return \"bmi\\t%l0;bgt\\t%l0\";
6048 [(set_attr "conds" "jump_clob")
6049 (set_attr "length" "8")]
6052 (define_insn "*arm_cond_branch"
6054 (if_then_else (match_operator 1 "arm_comparison_operator"
6055 [(match_operand 2 "cc_register" "") (const_int 0)])
6056 (label_ref (match_operand 0 "" ""))
6060 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6062 arm_ccfsm_state += 2;
6065 return \"b%d1\\t%l0\";
6067 [(set_attr "conds" "use")]
6070 ; Special pattern to match reversed UNEQ.
6071 (define_insn "*arm_buneq_reversed"
6073 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6075 (label_ref (match_operand 0 "" ""))))]
6076 "TARGET_ARM && TARGET_HARD_FLOAT"
6078 if (arm_ccfsm_state != 0)
6081 return \"bmi\\t%l0;bgt\\t%l0\";
6083 [(set_attr "conds" "jump_clob")
6084 (set_attr "length" "8")]
6087 ; Special pattern to match reversed LTGT.
6088 (define_insn "*arm_bltgt_reversed"
6090 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6092 (label_ref (match_operand 0 "" ""))))]
6093 "TARGET_ARM && TARGET_HARD_FLOAT"
6095 if (arm_ccfsm_state != 0)
6098 return \"bvs\\t%l0;beq\\t%l0\";
6100 [(set_attr "conds" "jump_clob")
6101 (set_attr "length" "8")]
6104 (define_insn "*arm_cond_branch_reversed"
6106 (if_then_else (match_operator 1 "arm_comparison_operator"
6107 [(match_operand 2 "cc_register" "") (const_int 0)])
6109 (label_ref (match_operand 0 "" ""))))]
6112 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6114 arm_ccfsm_state += 2;
6117 return \"b%D1\\t%l0\";
6119 [(set_attr "conds" "use")]
6126 (define_expand "seq"
6127 [(set (match_operand:SI 0 "s_register_operand" "=r")
6128 (eq:SI (match_dup 1) (const_int 0)))]
6130 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6133 (define_expand "sne"
6134 [(set (match_operand:SI 0 "s_register_operand" "=r")
6135 (ne:SI (match_dup 1) (const_int 0)))]
6137 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6140 (define_expand "sgt"
6141 [(set (match_operand:SI 0 "s_register_operand" "=r")
6142 (gt:SI (match_dup 1) (const_int 0)))]
6144 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6147 (define_expand "sle"
6148 [(set (match_operand:SI 0 "s_register_operand" "=r")
6149 (le:SI (match_dup 1) (const_int 0)))]
6151 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6154 (define_expand "sge"
6155 [(set (match_operand:SI 0 "s_register_operand" "=r")
6156 (ge:SI (match_dup 1) (const_int 0)))]
6158 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6161 (define_expand "slt"
6162 [(set (match_operand:SI 0 "s_register_operand" "=r")
6163 (lt:SI (match_dup 1) (const_int 0)))]
6165 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6168 (define_expand "sgtu"
6169 [(set (match_operand:SI 0 "s_register_operand" "=r")
6170 (gtu:SI (match_dup 1) (const_int 0)))]
6172 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6175 (define_expand "sleu"
6176 [(set (match_operand:SI 0 "s_register_operand" "=r")
6177 (leu:SI (match_dup 1) (const_int 0)))]
6179 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6182 (define_expand "sgeu"
6183 [(set (match_operand:SI 0 "s_register_operand" "=r")
6184 (geu:SI (match_dup 1) (const_int 0)))]
6186 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6189 (define_expand "sltu"
6190 [(set (match_operand:SI 0 "s_register_operand" "=r")
6191 (ltu:SI (match_dup 1) (const_int 0)))]
6193 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6196 (define_expand "sunordered"
6197 [(set (match_operand:SI 0 "s_register_operand" "=r")
6198 (unordered:SI (match_dup 1) (const_int 0)))]
6199 "TARGET_ARM && TARGET_HARD_FLOAT"
6200 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6204 (define_expand "sordered"
6205 [(set (match_operand:SI 0 "s_register_operand" "=r")
6206 (ordered:SI (match_dup 1) (const_int 0)))]
6207 "TARGET_ARM && TARGET_HARD_FLOAT"
6208 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6212 (define_expand "sungt"
6213 [(set (match_operand:SI 0 "s_register_operand" "=r")
6214 (ungt:SI (match_dup 1) (const_int 0)))]
6215 "TARGET_ARM && TARGET_HARD_FLOAT"
6216 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6220 (define_expand "sunge"
6221 [(set (match_operand:SI 0 "s_register_operand" "=r")
6222 (unge:SI (match_dup 1) (const_int 0)))]
6223 "TARGET_ARM && TARGET_HARD_FLOAT"
6224 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6228 (define_expand "sunlt"
6229 [(set (match_operand:SI 0 "s_register_operand" "=r")
6230 (unlt:SI (match_dup 1) (const_int 0)))]
6231 "TARGET_ARM && TARGET_HARD_FLOAT"
6232 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6236 (define_expand "sunle"
6237 [(set (match_operand:SI 0 "s_register_operand" "=r")
6238 (unle:SI (match_dup 1) (const_int 0)))]
6239 "TARGET_ARM && TARGET_HARD_FLOAT"
6240 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6244 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6245 ;;; simple ARM instructions.
6247 ; (define_expand "suneq"
6248 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6249 ; (uneq:SI (match_dup 1) (const_int 0)))]
6250 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6254 ; (define_expand "sltgt"
6255 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6256 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6257 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6261 (define_insn "*mov_scc"
6262 [(set (match_operand:SI 0 "s_register_operand" "=r")
6263 (match_operator:SI 1 "arm_comparison_operator"
6264 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6266 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6267 [(set_attr "conds" "use")
6268 (set_attr "length" "8")]
6271 (define_insn "*mov_negscc"
6272 [(set (match_operand:SI 0 "s_register_operand" "=r")
6273 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6274 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6276 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6277 [(set_attr "conds" "use")
6278 (set_attr "length" "8")]
6281 (define_insn "*mov_notscc"
6282 [(set (match_operand:SI 0 "s_register_operand" "=r")
6283 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6284 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6286 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6287 [(set_attr "conds" "use")
6288 (set_attr "length" "8")]
6292 ;; Conditional move insns
6294 (define_expand "movsicc"
6295 [(set (match_operand:SI 0 "s_register_operand" "")
6296 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6297 (match_operand:SI 2 "arm_not_operand" "")
6298 (match_operand:SI 3 "arm_not_operand" "")))]
6302 enum rtx_code code = GET_CODE (operands[1]);
6303 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6305 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6309 (define_expand "movsfcc"
6310 [(set (match_operand:SF 0 "s_register_operand" "")
6311 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6312 (match_operand:SF 2 "s_register_operand" "")
6313 (match_operand:SF 3 "nonmemory_operand" "")))]
6317 enum rtx_code code = GET_CODE (operands[1]);
6320 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6321 Otherwise, ensure it is a valid FP add operand */
6322 if ((!TARGET_HARD_FLOAT)
6323 || (!fpu_add_operand (operands[3], SFmode)))
6324 operands[3] = force_reg (SFmode, operands[3]);
6326 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6327 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6331 (define_expand "movdfcc"
6332 [(set (match_operand:DF 0 "s_register_operand" "")
6333 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6334 (match_operand:DF 2 "s_register_operand" "")
6335 (match_operand:DF 3 "fpu_add_operand" "")))]
6336 "TARGET_ARM && TARGET_HARD_FLOAT"
6339 enum rtx_code code = GET_CODE (operands[1]);
6340 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6342 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6346 (define_insn "*movsicc_insn"
6347 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6349 (match_operator 3 "arm_comparison_operator"
6350 [(match_operand 4 "cc_register" "") (const_int 0)])
6351 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6352 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6359 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6360 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6361 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6362 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6363 [(set_attr "length" "4,4,4,4,8,8,8,8")
6364 (set_attr "conds" "use")]
6367 (define_insn "*movsfcc_hard_insn"
6368 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6370 (match_operator 3 "arm_comparison_operator"
6371 [(match_operand 4 "cc_register" "") (const_int 0)])
6372 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6373 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6374 "TARGET_ARM && TARGET_HARD_FLOAT"
6380 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6381 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6382 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6383 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6384 [(set_attr "length" "4,4,4,4,8,8,8,8")
6385 (set_attr "type" "ffarith")
6386 (set_attr "conds" "use")]
6389 (define_insn "*movsfcc_soft_insn"
6390 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6391 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6392 [(match_operand 4 "cc_register" "") (const_int 0)])
6393 (match_operand:SF 1 "s_register_operand" "0,r")
6394 (match_operand:SF 2 "s_register_operand" "r,0")))]
6395 "TARGET_ARM && TARGET_SOFT_FLOAT"
6399 [(set_attr "conds" "use")]
6402 (define_insn "*movdfcc_insn"
6403 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6405 (match_operator 3 "arm_comparison_operator"
6406 [(match_operand 4 "cc_register" "") (const_int 0)])
6407 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6408 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6409 "TARGET_ARM && TARGET_HARD_FLOAT"
6415 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6416 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6417 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6418 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6419 [(set_attr "length" "4,4,4,4,8,8,8,8")
6420 (set_attr "type" "ffarith")
6421 (set_attr "conds" "use")]
6425 ;; Jump and linkage insns
6427 (define_expand "jump"
6429 (label_ref (match_operand 0 "" "")))]
6434 (define_insn "*arm_jump"
6436 (label_ref (match_operand 0 "" "")))]
6440 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6442 arm_ccfsm_state += 2;
6445 return \"b%?\\t%l0\";
6448 [(set_attr "predicable" "yes")]
6451 (define_insn "*thumb_jump"
6453 (label_ref (match_operand 0 "" "")))]
6456 if (get_attr_length (insn) == 2)
6458 return \"bl\\t%l0\\t%@ far jump\";
6460 [(set (attr "far_jump")
6462 (eq_attr "length" "4")
6463 (const_string "yes")
6464 (const_string "no")))
6465 (set (attr "length")
6467 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6468 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6473 (define_expand "call"
6474 [(parallel [(call (match_operand 0 "memory_operand" "")
6475 (match_operand 1 "general_operand" ""))
6476 (use (match_operand 2 "" ""))
6477 (clobber (reg:SI LR_REGNUM))])]
6483 /* In an untyped call, we can get NULL for operand 2. */
6484 if (operands[2] == NULL_RTX)
6485 operands[2] = const0_rtx;
6487 /* This is to decide if we should generate indirect calls by loading the
6488 32 bit address of the callee into a register before performing the
6489 branch and link. operand[2] encodes the long_call/short_call
6490 attribute of the function being called. This attribute is set whenever
6491 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6492 is used, and the short_call attribute can also be set if function is
6493 declared as static or if it has already been defined in the current
6494 compilation unit. See arm.c and arm.h for info about this. The third
6495 parameter to arm_is_longcall_p is used to tell it which pattern
6497 callee = XEXP (operands[0], 0);
6499 if (GET_CODE (callee) != REG
6500 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6501 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6505 (define_insn "*call_reg"
6506 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6507 (match_operand 1 "" ""))
6508 (use (match_operand 2 "" ""))
6509 (clobber (reg:SI LR_REGNUM))]
6512 return output_call (operands);
6514 ;; length is worst case, normally it is only two
6515 [(set_attr "length" "12")
6516 (set_attr "type" "call")]
6519 (define_insn "*call_mem"
6520 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6521 (match_operand 1 "" ""))
6522 (use (match_operand 2 "" ""))
6523 (clobber (reg:SI LR_REGNUM))]
6526 return output_call_mem (operands);
6528 [(set_attr "length" "12")
6529 (set_attr "type" "call")]
6532 (define_insn "*call_indirect"
6533 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6534 (match_operand 1 "" ""))
6535 (use (match_operand 2 "" ""))
6536 (clobber (reg:SI LR_REGNUM))]
6540 if (TARGET_CALLER_INTERWORKING)
6541 return \"bl\\t%__interwork_call_via_%0\";
6543 return \"bl\\t%__call_via_%0\";
6545 [(set_attr "type" "call")]
6548 (define_insn "*call_value_indirect"
6549 [(set (match_operand 0 "" "=l")
6550 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6551 (match_operand 2 "" "")))
6552 (use (match_operand 3 "" ""))
6553 (clobber (reg:SI LR_REGNUM))]
6557 if (TARGET_CALLER_INTERWORKING)
6558 return \"bl\\t%__interwork_call_via_%1\";
6560 return \"bl\\t%__call_via_%1\";
6562 [(set_attr "type" "call")]
6565 (define_expand "call_value"
6566 [(parallel [(set (match_operand 0 "" "")
6567 (call (match_operand 1 "memory_operand" "")
6568 (match_operand 2 "general_operand" "")))
6569 (use (match_operand 3 "" ""))
6570 (clobber (reg:SI LR_REGNUM))])]
6574 rtx callee = XEXP (operands[1], 0);
6576 /* In an untyped call, we can get NULL for operand 2. */
6577 if (operands[3] == 0)
6578 operands[3] = const0_rtx;
6580 /* See the comment in define_expand \"call\". */
6581 if (GET_CODE (callee) != REG
6582 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6583 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6587 (define_insn "*call_value_reg"
6588 [(set (match_operand 0 "" "=r,f")
6589 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6590 (match_operand 2 "" "")))
6591 (use (match_operand 3 "" ""))
6592 (clobber (reg:SI LR_REGNUM))]
6595 return output_call (&operands[1]);
6597 [(set_attr "length" "12")
6598 (set_attr "type" "call")]
6601 (define_insn "*call_value_mem"
6602 [(set (match_operand 0 "" "=r,f")
6603 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6604 (match_operand 2 "" "")))
6605 (use (match_operand 3 "" ""))
6606 (clobber (reg:SI LR_REGNUM))]
6607 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6609 return output_call_mem (&operands[1]);
6611 [(set_attr "length" "12")
6612 (set_attr "type" "call")]
6615 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6616 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6618 (define_insn "*call_symbol"
6619 [(call (mem:SI (match_operand:SI 0 "" "X"))
6620 (match_operand 1 "" ""))
6621 (use (match_operand 2 "" ""))
6622 (clobber (reg:SI LR_REGNUM))]
6624 && (GET_CODE (operands[0]) == SYMBOL_REF)
6625 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6628 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6630 [(set_attr "type" "call")]
6633 (define_insn "*call_value_symbol"
6634 [(set (match_operand 0 "s_register_operand" "=r,f")
6635 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6636 (match_operand:SI 2 "" "")))
6637 (use (match_operand 3 "" ""))
6638 (clobber (reg:SI LR_REGNUM))]
6640 && (GET_CODE (operands[1]) == SYMBOL_REF)
6641 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6644 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6646 [(set_attr "type" "call")]
6649 (define_insn "*call_insn"
6650 [(call (mem:SI (match_operand:SI 0 "" "X"))
6651 (match_operand:SI 1 "" ""))
6652 (use (match_operand 2 "" ""))
6653 (clobber (reg:SI LR_REGNUM))]
6655 && operands[2] == const0_rtx && (GET_CODE (operands[0]) == SYMBOL_REF)"
6657 [(set_attr "length" "4")
6658 (set_attr "type" "call")]
6661 (define_insn "*call_value_insn"
6662 [(set (match_operand 0 "register_operand" "=l")
6663 (call (mem:SI (match_operand 1 "" "X"))
6664 (match_operand 2 "" "")))
6665 (use (match_operand 3 "" ""))
6666 (clobber (reg:SI LR_REGNUM))]
6668 && operands[3] == const0_rtx && (GET_CODE (operands[1]) == SYMBOL_REF)"
6670 [(set_attr "length" "4")
6671 (set_attr "type" "call")]
6674 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6675 (define_expand "sibcall"
6676 [(parallel [(call (match_operand 0 "memory_operand" "")
6677 (match_operand 1 "general_operand" ""))
6678 (use (match_operand 2 "" ""))
6679 (use (reg:SI LR_REGNUM))])]
6683 if (operands[2] == NULL_RTX)
6684 operands[2] = const0_rtx;
6688 (define_expand "sibcall_value"
6689 [(parallel [(set (match_operand 0 "register_operand" "")
6690 (call (match_operand 1 "memory_operand" "")
6691 (match_operand 2 "general_operand" "")))
6692 (use (match_operand 3 "" ""))
6693 (use (reg:SI LR_REGNUM))])]
6697 if (operands[3] == NULL_RTX)
6698 operands[3] = const0_rtx;
6702 (define_insn "*sibcall_insn"
6703 [(call (mem:SI (match_operand:SI 0 "" "X"))
6704 (match_operand 1 "" ""))
6705 (use (match_operand 2 "" ""))
6706 (use (reg:SI LR_REGNUM))]
6707 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6709 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6711 [(set_attr "type" "call")]
6714 (define_insn "*sibcall_value_insn"
6715 [(set (match_operand 0 "s_register_operand" "=r,f")
6716 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6717 (match_operand 2 "" "")))
6718 (use (match_operand 3 "" ""))
6719 (use (reg:SI LR_REGNUM))]
6720 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6722 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6724 [(set_attr "type" "call")]
6727 ;; Often the return insn will be the same as loading from memory, so set attr
6728 (define_insn "return"
6730 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6733 if (arm_ccfsm_state == 2)
6735 arm_ccfsm_state += 2;
6738 return output_return_instruction (NULL, TRUE, FALSE);
6740 [(set_attr "type" "load")
6741 (set_attr "predicable" "yes")]
6744 (define_insn "*cond_return"
6746 (if_then_else (match_operator 0 "arm_comparison_operator"
6747 [(match_operand 1 "cc_register" "") (const_int 0)])
6750 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6753 if (arm_ccfsm_state == 2)
6755 arm_ccfsm_state += 2;
6758 return output_return_instruction (operands[0], TRUE, FALSE);
6760 [(set_attr "conds" "use")
6761 (set_attr "type" "load")]
6764 (define_insn "*cond_return_inverted"
6766 (if_then_else (match_operator 0 "arm_comparison_operator"
6767 [(match_operand 1 "cc_register" "") (const_int 0)])
6770 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6773 if (arm_ccfsm_state == 2)
6775 arm_ccfsm_state += 2;
6778 return output_return_instruction (operands[0], TRUE, TRUE);
6780 [(set_attr "conds" "use")
6781 (set_attr "type" "load")]
6784 ;; Call subroutine returning any type.
6786 (define_expand "untyped_call"
6787 [(parallel [(call (match_operand 0 "" "")
6789 (match_operand 1 "" "")
6790 (match_operand 2 "" "")])]
6796 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6798 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6800 rtx set = XVECEXP (operands[2], 0, i);
6802 emit_move_insn (SET_DEST (set), SET_SRC (set));
6805 /* The optimizer does not know that the call sets the function value
6806 registers we stored in the result block. We avoid problems by
6807 claiming that all hard registers are used and clobbered at this
6809 emit_insn (gen_blockage ());
6815 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6816 ;; all of memory. This blocks insns from being moved across this point.
6818 (define_insn "blockage"
6819 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6822 [(set_attr "length" "0")
6823 (set_attr "type" "block")]
6826 (define_expand "casesi"
6827 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6828 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6829 (match_operand:SI 2 "const_int_operand" "") ; total range
6830 (match_operand:SI 3 "" "") ; table label
6831 (match_operand:SI 4 "" "")] ; Out of range label
6836 if (operands[1] != const0_rtx)
6838 reg = gen_reg_rtx (SImode);
6840 emit_insn (gen_addsi3 (reg, operands[0],
6841 GEN_INT (-INTVAL (operands[1]))));
6845 if (!const_ok_for_arm (INTVAL (operands[2])))
6846 operands[2] = force_reg (SImode, operands[2]);
6848 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6854 ;; The USE in this pattern is needed to tell flow analysis that this is
6855 ;; a CASESI insn. It has no other purpose.
6856 (define_insn "casesi_internal"
6857 [(parallel [(set (pc)
6859 (leu (match_operand:SI 0 "s_register_operand" "r")
6860 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6861 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6862 (label_ref (match_operand 2 "" ""))))
6863 (label_ref (match_operand 3 "" ""))))
6864 (clobber (reg:CC CC_REGNUM))
6865 (use (label_ref (match_dup 2)))])]
6869 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6870 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6872 [(set_attr "conds" "clob")
6873 (set_attr "length" "12")]
6876 (define_expand "indirect_jump"
6878 (match_operand:SI 0 "s_register_operand" ""))]
6883 (define_insn "*arm_indirect_jump"
6885 (match_operand:SI 0 "s_register_operand" "r"))]
6887 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6888 [(set_attr "predicable" "yes")]
6891 ;; Although not supported by the define_expand above,
6892 ;; cse/combine may generate this form.
6893 (define_insn "*load_indirect_jump"
6895 (match_operand:SI 0 "memory_operand" "m"))]
6897 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6898 [(set_attr "type" "load")
6899 (set_attr "pool_range" "4096")
6900 (set_attr "neg_pool_range" "4084")
6901 (set_attr "predicable" "yes")]
6904 (define_insn "*thumb_indirect_jump"
6906 (match_operand:SI 0 "register_operand" "l*r"))]
6909 [(set_attr "conds" "clob")
6910 (set_attr "length" "2")]
6921 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6922 return \"mov\\tr8, r8\";
6924 [(set (attr "length")
6925 (if_then_else (eq_attr "is_thumb" "yes")
6931 ;; Patterns to allow combination of arithmetic, cond code and shifts
6933 (define_insn "*arith_shiftsi"
6934 [(set (match_operand:SI 0 "s_register_operand" "=r")
6935 (match_operator:SI 1 "shiftable_operator"
6936 [(match_operator:SI 3 "shift_operator"
6937 [(match_operand:SI 4 "s_register_operand" "r")
6938 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6939 (match_operand:SI 2 "s_register_operand" "r")]))]
6941 "%i1%?\\t%0, %2, %4%S3"
6942 [(set_attr "predicable" "yes")
6943 (set_attr "shift" "4")
6947 (define_insn "*arith_shiftsi_compare0"
6948 [(set (reg:CC_NOOV CC_REGNUM)
6949 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6950 [(match_operator:SI 3 "shift_operator"
6951 [(match_operand:SI 4 "s_register_operand" "r")
6952 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6953 (match_operand:SI 2 "s_register_operand" "r")])
6955 (set (match_operand:SI 0 "s_register_operand" "=r")
6956 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6959 "%i1%?s\\t%0, %2, %4%S3"
6960 [(set_attr "conds" "set")
6961 (set_attr "shift" "4")
6965 (define_insn "*arith_shiftsi_compare0_scratch"
6966 [(set (reg:CC_NOOV CC_REGNUM)
6967 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6968 [(match_operator:SI 3 "shift_operator"
6969 [(match_operand:SI 4 "s_register_operand" "r")
6970 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6971 (match_operand:SI 2 "s_register_operand" "r")])
6973 (clobber (match_scratch:SI 0 "=r"))]
6975 "%i1%?s\\t%0, %2, %4%S3"
6976 [(set_attr "conds" "set")
6977 (set_attr "shift" "4")
6981 (define_insn "*sub_shiftsi"
6982 [(set (match_operand:SI 0 "s_register_operand" "=r")
6983 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6984 (match_operator:SI 2 "shift_operator"
6985 [(match_operand:SI 3 "s_register_operand" "r")
6986 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6988 "sub%?\\t%0, %1, %3%S2"
6989 [(set_attr "predicable" "yes")
6990 (set_attr "shift" "3")
6994 (define_insn "*sub_shiftsi_compare0"
6995 [(set (reg:CC_NOOV CC_REGNUM)
6997 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6998 (match_operator:SI 2 "shift_operator"
6999 [(match_operand:SI 3 "s_register_operand" "r")
7000 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7002 (set (match_operand:SI 0 "s_register_operand" "=r")
7003 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7006 "sub%?s\\t%0, %1, %3%S2"
7007 [(set_attr "conds" "set")
7008 (set_attr "shift" "3")
7012 (define_insn "*sub_shiftsi_compare0_scratch"
7013 [(set (reg:CC_NOOV CC_REGNUM)
7015 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7016 (match_operator:SI 2 "shift_operator"
7017 [(match_operand:SI 3 "s_register_operand" "r")
7018 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7020 (clobber (match_scratch:SI 0 "=r"))]
7022 "sub%?s\\t%0, %1, %3%S2"
7023 [(set_attr "conds" "set")
7024 (set_attr "shift" "3")
7028 ;; These variants of the above insns can occur if the first operand is the
7029 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
7030 ;; seem to be a way around it. Most of the predicates have to be null
7031 ;; because the format can be generated part way through reload, so
7032 ;; if we don't match it as soon as it becomes available, reload doesn't know
7033 ;; how to reload pseudos that haven't got hard registers; the constraints will
7034 ;; sort everything out.
7036 (define_insn "*reload_mulsi3"
7037 [(set (match_operand:SI 0 "" "=&r")
7038 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
7039 [(match_operand:SI 3 "" "r")
7040 (match_operand:SI 4 "" "rM")])
7041 (match_operand:SI 2 "" "r"))
7042 (match_operand:SI 1 "const_int_operand" "n")))]
7043 "TARGET_ARM && reload_in_progress"
7045 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
7046 operands[2] = operands[1];
7047 operands[1] = operands[0];
7048 return output_add_immediate (operands);
7051 ; we have no idea how long the add_immediate is, it could be up to 4.
7052 (set_attr "length" "20")]
7055 (define_insn "*reload_mulsi_compare0"
7056 [(set (reg:CC_NOOV CC_REGNUM)
7057 (compare:CC_NOOV (plus:SI
7059 (match_operator:SI 5 "shift_operator"
7060 [(match_operand:SI 3 "" "r")
7061 (match_operand:SI 4 "" "rM")])
7062 (match_operand:SI 1 "" "r"))
7063 (match_operand:SI 2 "const_int_operand" "n"))
7065 (set (match_operand:SI 0 "" "=&r")
7066 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
7069 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7071 output_add_immediate (operands);
7072 return \"add%?s\\t%0, %0, %3%S5\";
7074 [(set_attr "conds" "set")
7075 (set_attr "shift" "3")
7076 (set_attr "length" "20")]
7079 (define_insn "*reload_mulsi_compare0_scratch"
7080 [(set (reg:CC_NOOV CC_REGNUM)
7081 (compare:CC_NOOV (plus:SI
7083 (match_operator:SI 5 "shift_operator"
7084 [(match_operand:SI 3 "" "r")
7085 (match_operand:SI 4 "" "rM")])
7086 (match_operand:SI 1 "" "r"))
7087 (match_operand:SI 2 "const_int_operand" "n"))
7089 (clobber (match_scratch:SI 0 "=&r"))]
7090 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7092 output_add_immediate (operands);
7093 return \"add%?s\\t%0, %0, %3%S5\";
7095 [(set_attr "conds" "set")
7096 (set_attr "shift" "3")
7097 (set_attr "length" "20")]
7100 ;; These are similar, but are needed when the mla pattern contains the
7101 ;; eliminated register as operand 3.
7103 (define_insn "*reload_muladdsi"
7104 [(set (match_operand:SI 0 "" "=&r,&r")
7105 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
7106 (match_operand:SI 2 "" "r,r"))
7107 (match_operand:SI 3 "" "r,r"))
7108 (match_operand:SI 4 "const_int_operand" "n,n")))]
7109 "TARGET_ARM && reload_in_progress"
7111 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
7112 operands[2] = operands[4];
7113 operands[1] = operands[0];
7114 return output_add_immediate (operands);
7116 [(set_attr "length" "20")
7117 (set_attr "type" "mult")]
7120 (define_insn "*reload_muladdsi_compare0"
7121 [(set (reg:CC_NOOV CC_REGNUM)
7122 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7123 (match_operand:SI 3 "" "r")
7124 (match_operand:SI 4 "" "r"))
7125 (match_operand:SI 1 "" "r"))
7126 (match_operand:SI 2 "const_int_operand" "n"))
7128 (set (match_operand:SI 0 "" "=&r")
7129 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
7131 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7133 output_add_immediate (operands);
7134 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
7137 [(set_attr "length" "20")
7138 (set_attr "conds" "set")
7139 (set_attr "type" "mult")]
7142 (define_insn "*reload_muladdsi_compare0_scratch"
7143 [(set (reg:CC_NOOV CC_REGNUM)
7144 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7145 (match_operand:SI 3 "" "r")
7146 (match_operand:SI 4 "" "r"))
7147 (match_operand:SI 1 "" "r"))
7148 (match_operand:SI 2 "const_int_operand" "n"))
7150 (clobber (match_scratch:SI 0 "=&r"))]
7151 "TARGET_ARM && reload_in_progress"
7153 output_add_immediate (operands);
7154 return \"mla%?s\\t%0, %3, %4, %0\";
7156 [(set_attr "length" "20")
7157 (set_attr "conds" "set")
7158 (set_attr "type" "mult")]
7163 (define_insn "*and_scc"
7164 [(set (match_operand:SI 0 "s_register_operand" "=r")
7165 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7166 [(match_operand 3 "cc_register" "") (const_int 0)])
7167 (match_operand:SI 2 "s_register_operand" "r")))]
7169 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7170 [(set_attr "conds" "use")
7171 (set_attr "length" "8")]
7174 (define_insn "*ior_scc"
7175 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7176 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7177 [(match_operand 3 "cc_register" "") (const_int 0)])
7178 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7182 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7183 [(set_attr "conds" "use")
7184 (set_attr "length" "4,8")]
7187 (define_insn "*compare_scc"
7188 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7189 (match_operator:SI 1 "arm_comparison_operator"
7190 [(match_operand:SI 2 "s_register_operand" "r,r")
7191 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7192 (clobber (reg:CC CC_REGNUM))]
7195 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7196 return \"mov\\t%0, %2, lsr #31\";
7198 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7199 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7201 if (GET_CODE (operands[1]) == NE)
7203 if (which_alternative == 1)
7204 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7205 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7207 if (which_alternative == 1)
7208 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7210 output_asm_insn (\"cmp\\t%2, %3\", operands);
7211 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7213 [(set_attr "conds" "clob")
7214 (set_attr "length" "12")]
7217 (define_insn "*cond_move"
7218 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7219 (if_then_else:SI (match_operator 3 "equality_operator"
7220 [(match_operator 4 "arm_comparison_operator"
7221 [(match_operand 5 "cc_register" "") (const_int 0)])
7223 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7224 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7227 if (GET_CODE (operands[3]) == NE)
7229 if (which_alternative != 1)
7230 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7231 if (which_alternative != 0)
7232 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7235 if (which_alternative != 0)
7236 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7237 if (which_alternative != 1)
7238 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7241 [(set_attr "conds" "use")
7242 (set_attr "length" "4,4,8")]
7245 (define_insn "*cond_arith"
7246 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7247 (match_operator:SI 5 "shiftable_operator"
7248 [(match_operator:SI 4 "arm_comparison_operator"
7249 [(match_operand:SI 2 "s_register_operand" "r,r")
7250 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7251 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7252 (clobber (reg:CC CC_REGNUM))]
7255 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7256 return \"%i5\\t%0, %1, %2, lsr #31\";
7258 output_asm_insn (\"cmp\\t%2, %3\", operands);
7259 if (GET_CODE (operands[5]) == AND)
7260 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7261 else if (GET_CODE (operands[5]) == MINUS)
7262 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7263 else if (which_alternative != 0)
7264 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7265 return \"%i5%d4\\t%0, %1, #1\";
7267 [(set_attr "conds" "clob")
7268 (set_attr "length" "12")]
7271 (define_insn "*cond_sub"
7272 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7273 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7274 (match_operator:SI 4 "arm_comparison_operator"
7275 [(match_operand:SI 2 "s_register_operand" "r,r")
7276 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7277 (clobber (reg:CC CC_REGNUM))]
7280 output_asm_insn (\"cmp\\t%2, %3\", operands);
7281 if (which_alternative != 0)
7282 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7283 return \"sub%d4\\t%0, %1, #1\";
7285 [(set_attr "conds" "clob")
7286 (set_attr "length" "8,12")]
7289 (define_insn "*cmp_ite0"
7290 [(set (match_operand 6 "dominant_cc_register" "")
7293 (match_operator 4 "arm_comparison_operator"
7294 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7295 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7296 (match_operator:SI 5 "arm_comparison_operator"
7297 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7298 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7304 static const char * const opcodes[4][2] =
7306 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7307 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7308 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7309 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7310 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7311 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7312 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7313 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7316 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7318 return opcodes[which_alternative][swap];
7320 [(set_attr "conds" "set")
7321 (set_attr "length" "8")]
7324 (define_insn "*cmp_ite1"
7325 [(set (match_operand 6 "dominant_cc_register" "")
7328 (match_operator 4 "arm_comparison_operator"
7329 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7330 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7331 (match_operator:SI 5 "arm_comparison_operator"
7332 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7333 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7339 static const char * const opcodes[4][2] =
7341 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7342 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7343 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7344 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7345 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7346 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7347 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7348 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7351 comparison_dominates_p (GET_CODE (operands[5]),
7352 reverse_condition (GET_CODE (operands[4])));
7354 return opcodes[which_alternative][swap];
7356 [(set_attr "conds" "set")
7357 (set_attr "length" "8")]
7360 (define_insn "*cmp_and"
7361 [(set (match_operand 6 "dominant_cc_register" "")
7364 (match_operator 4 "arm_comparison_operator"
7365 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7366 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7367 (match_operator:SI 5 "arm_comparison_operator"
7368 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7369 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7374 const char * opcodes[4][2] =
7376 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7377 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7378 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7379 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7380 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7381 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7382 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7383 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7386 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7388 return opcodes[which_alternative][swap];
7390 [(set_attr "conds" "set")
7391 (set_attr "predicable" "no")
7392 (set_attr "length" "8")]
7395 (define_insn "*cmp_ior"
7396 [(set (match_operand 6 "dominant_cc_register" "")
7399 (match_operator 4 "arm_comparison_operator"
7400 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7401 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7402 (match_operator:SI 5 "arm_comparison_operator"
7403 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7404 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7409 const char * opcodes[4][2] =
7411 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7412 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7413 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7414 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7415 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7416 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7417 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7418 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7421 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7423 return opcodes[which_alternative][swap];
7426 [(set_attr "conds" "set")
7427 (set_attr "length" "8")]
7430 (define_insn "*negscc"
7431 [(set (match_operand:SI 0 "s_register_operand" "=r")
7432 (neg:SI (match_operator 3 "arm_comparison_operator"
7433 [(match_operand:SI 1 "s_register_operand" "r")
7434 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7435 (clobber (reg:CC CC_REGNUM))]
7438 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7439 return \"mov\\t%0, %1, asr #31\";
7441 if (GET_CODE (operands[3]) == NE)
7442 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7444 if (GET_CODE (operands[3]) == GT)
7445 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7447 output_asm_insn (\"cmp\\t%1, %2\", operands);
7448 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7449 return \"mvn%d3\\t%0, #0\";
7451 [(set_attr "conds" "clob")
7452 (set_attr "length" "12")]
7455 (define_insn "movcond"
7456 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7458 (match_operator 5 "arm_comparison_operator"
7459 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7460 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7461 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7462 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7463 (clobber (reg:CC CC_REGNUM))]
7466 if (GET_CODE (operands[5]) == LT
7467 && (operands[4] == const0_rtx))
7469 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7471 if (operands[2] == const0_rtx)
7472 return \"and\\t%0, %1, %3, asr #31\";
7473 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7475 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7477 if (operands[1] == const0_rtx)
7478 return \"bic\\t%0, %2, %3, asr #31\";
7479 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7481 /* The only case that falls through to here is when both ops 1 & 2
7485 if (GET_CODE (operands[5]) == GE
7486 && (operands[4] == const0_rtx))
7488 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7490 if (operands[2] == const0_rtx)
7491 return \"bic\\t%0, %1, %3, asr #31\";
7492 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7494 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7496 if (operands[1] == const0_rtx)
7497 return \"and\\t%0, %2, %3, asr #31\";
7498 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7500 /* The only case that falls through to here is when both ops 1 & 2
7503 if (GET_CODE (operands[4]) == CONST_INT
7504 && !const_ok_for_arm (INTVAL (operands[4])))
7505 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7507 output_asm_insn (\"cmp\\t%3, %4\", operands);
7508 if (which_alternative != 0)
7509 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7510 if (which_alternative != 1)
7511 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7514 [(set_attr "conds" "clob")
7515 (set_attr "length" "8,8,12")]
7518 (define_insn "*ifcompare_plus_move"
7519 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7520 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7521 [(match_operand:SI 4 "s_register_operand" "r,r")
7522 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7524 (match_operand:SI 2 "s_register_operand" "r,r")
7525 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7526 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7527 (clobber (reg:CC CC_REGNUM))]
7530 [(set_attr "conds" "clob")
7531 (set_attr "length" "8,12")]
7534 (define_insn "*if_plus_move"
7535 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7537 (match_operator 4 "arm_comparison_operator"
7538 [(match_operand 5 "cc_register" "") (const_int 0)])
7540 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7541 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7542 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7546 sub%d4\\t%0, %2, #%n3
7547 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7548 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7549 [(set_attr "conds" "use")
7550 (set_attr "length" "4,4,8,8")
7551 (set_attr "type" "*,*,*,*")]
7554 (define_insn "*ifcompare_move_plus"
7555 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7556 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7557 [(match_operand:SI 4 "s_register_operand" "r,r")
7558 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7559 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7561 (match_operand:SI 2 "s_register_operand" "r,r")
7562 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7563 (clobber (reg:CC CC_REGNUM))]
7566 [(set_attr "conds" "clob")
7567 (set_attr "length" "8,12")]
7570 (define_insn "*if_move_plus"
7571 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7573 (match_operator 4 "arm_comparison_operator"
7574 [(match_operand 5 "cc_register" "") (const_int 0)])
7575 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7577 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7578 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7582 sub%D4\\t%0, %2, #%n3
7583 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7584 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7585 [(set_attr "conds" "use")
7586 (set_attr "length" "4,4,8,8")
7587 (set_attr "type" "*,*,*,*")]
7590 (define_insn "*ifcompare_arith_arith"
7591 [(set (match_operand:SI 0 "s_register_operand" "=r")
7592 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7593 [(match_operand:SI 5 "s_register_operand" "r")
7594 (match_operand:SI 6 "arm_add_operand" "rIL")])
7595 (match_operator:SI 8 "shiftable_operator"
7596 [(match_operand:SI 1 "s_register_operand" "r")
7597 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7598 (match_operator:SI 7 "shiftable_operator"
7599 [(match_operand:SI 3 "s_register_operand" "r")
7600 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7601 (clobber (reg:CC CC_REGNUM))]
7604 [(set_attr "conds" "clob")
7605 (set_attr "length" "12")]
7608 (define_insn "*if_arith_arith"
7609 [(set (match_operand:SI 0 "s_register_operand" "=r")
7610 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7611 [(match_operand 8 "cc_register" "") (const_int 0)])
7612 (match_operator:SI 6 "shiftable_operator"
7613 [(match_operand:SI 1 "s_register_operand" "r")
7614 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7615 (match_operator:SI 7 "shiftable_operator"
7616 [(match_operand:SI 3 "s_register_operand" "r")
7617 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7619 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7620 [(set_attr "conds" "use")
7621 (set_attr "length" "8")]
7624 (define_insn "*ifcompare_arith_move"
7625 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7626 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7627 [(match_operand:SI 2 "s_register_operand" "r,r")
7628 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7629 (match_operator:SI 7 "shiftable_operator"
7630 [(match_operand:SI 4 "s_register_operand" "r,r")
7631 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7632 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7633 (clobber (reg:CC CC_REGNUM))]
7636 /* If we have an operation where (op x 0) is the identity operation and
7637 the conditional operator is LT or GE and we are comparing against zero and
7638 everything is in registers then we can do this in two instructions */
7639 if (operands[3] == const0_rtx
7640 && GET_CODE (operands[7]) != AND
7641 && GET_CODE (operands[5]) == REG
7642 && GET_CODE (operands[1]) == REG
7643 && REGNO (operands[1]) == REGNO (operands[4])
7644 && REGNO (operands[4]) != REGNO (operands[0]))
7646 if (GET_CODE (operands[6]) == LT)
7647 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7648 else if (GET_CODE (operands[6]) == GE)
7649 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7651 if (GET_CODE (operands[3]) == CONST_INT
7652 && !const_ok_for_arm (INTVAL (operands[3])))
7653 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7655 output_asm_insn (\"cmp\\t%2, %3\", operands);
7656 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7657 if (which_alternative != 0)
7658 return \"mov%D6\\t%0, %1\";
7661 [(set_attr "conds" "clob")
7662 (set_attr "length" "8,12")]
7665 (define_insn "*if_arith_move"
7666 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7667 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7668 [(match_operand 6 "cc_register" "") (const_int 0)])
7669 (match_operator:SI 5 "shiftable_operator"
7670 [(match_operand:SI 2 "s_register_operand" "r,r")
7671 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7672 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7676 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7677 [(set_attr "conds" "use")
7678 (set_attr "length" "4,8")
7679 (set_attr "type" "*,*")]
7682 (define_insn "*ifcompare_move_arith"
7683 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7684 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7685 [(match_operand:SI 4 "s_register_operand" "r,r")
7686 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7687 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7688 (match_operator:SI 7 "shiftable_operator"
7689 [(match_operand:SI 2 "s_register_operand" "r,r")
7690 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7691 (clobber (reg:CC CC_REGNUM))]
7694 /* If we have an operation where (op x 0) is the identity operation and
7695 the conditional operator is LT or GE and we are comparing against zero and
7696 everything is in registers then we can do this in two instructions */
7697 if (operands[5] == const0_rtx
7698 && GET_CODE (operands[7]) != AND
7699 && GET_CODE (operands[3]) == REG
7700 && GET_CODE (operands[1]) == REG
7701 && REGNO (operands[1]) == REGNO (operands[2])
7702 && REGNO (operands[2]) != REGNO (operands[0]))
7704 if (GET_CODE (operands[6]) == GE)
7705 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7706 else if (GET_CODE (operands[6]) == LT)
7707 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7710 if (GET_CODE (operands[5]) == CONST_INT
7711 && !const_ok_for_arm (INTVAL (operands[5])))
7712 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7714 output_asm_insn (\"cmp\\t%4, %5\", operands);
7716 if (which_alternative != 0)
7717 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7718 return \"%I7%D6\\t%0, %2, %3\";
7720 [(set_attr "conds" "clob")
7721 (set_attr "length" "8,12")]
7724 (define_insn "*if_move_arith"
7725 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7727 (match_operator 4 "arm_comparison_operator"
7728 [(match_operand 6 "cc_register" "") (const_int 0)])
7729 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7730 (match_operator:SI 5 "shiftable_operator"
7731 [(match_operand:SI 2 "s_register_operand" "r,r")
7732 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7736 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7737 [(set_attr "conds" "use")
7738 (set_attr "length" "4,8")
7739 (set_attr "type" "*,*")]
7742 (define_insn "*ifcompare_move_not"
7743 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7745 (match_operator 5 "arm_comparison_operator"
7746 [(match_operand:SI 3 "s_register_operand" "r,r")
7747 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7748 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7750 (match_operand:SI 2 "s_register_operand" "r,r"))))
7751 (clobber (reg:CC CC_REGNUM))]
7754 [(set_attr "conds" "clob")
7755 (set_attr "length" "8,12")]
7758 (define_insn "*if_move_not"
7759 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7761 (match_operator 4 "arm_comparison_operator"
7762 [(match_operand 3 "cc_register" "") (const_int 0)])
7763 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7764 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7768 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7769 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7770 [(set_attr "conds" "use")
7771 (set_attr "length" "4,8,8")]
7774 (define_insn "*ifcompare_not_move"
7775 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7777 (match_operator 5 "arm_comparison_operator"
7778 [(match_operand:SI 3 "s_register_operand" "r,r")
7779 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7781 (match_operand:SI 2 "s_register_operand" "r,r"))
7782 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7783 (clobber (reg:CC CC_REGNUM))]
7786 [(set_attr "conds" "clob")
7787 (set_attr "length" "8,12")]
7790 (define_insn "*if_not_move"
7791 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7793 (match_operator 4 "arm_comparison_operator"
7794 [(match_operand 3 "cc_register" "") (const_int 0)])
7795 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7796 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7800 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7801 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7802 [(set_attr "conds" "use")
7803 (set_attr "length" "4,8,8")]
7806 (define_insn "*ifcompare_shift_move"
7807 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7809 (match_operator 6 "arm_comparison_operator"
7810 [(match_operand:SI 4 "s_register_operand" "r,r")
7811 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7812 (match_operator:SI 7 "shift_operator"
7813 [(match_operand:SI 2 "s_register_operand" "r,r")
7814 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7815 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7816 (clobber (reg:CC CC_REGNUM))]
7819 [(set_attr "conds" "clob")
7820 (set_attr "length" "8,12")]
7823 (define_insn "*if_shift_move"
7824 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7826 (match_operator 5 "arm_comparison_operator"
7827 [(match_operand 6 "cc_register" "") (const_int 0)])
7828 (match_operator:SI 4 "shift_operator"
7829 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7830 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7831 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7835 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7836 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7837 [(set_attr "conds" "use")
7838 (set_attr "shift" "2")
7839 (set_attr "length" "4,8,8")]
7842 (define_insn "*ifcompare_move_shift"
7843 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7845 (match_operator 6 "arm_comparison_operator"
7846 [(match_operand:SI 4 "s_register_operand" "r,r")
7847 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7848 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7849 (match_operator:SI 7 "shift_operator"
7850 [(match_operand:SI 2 "s_register_operand" "r,r")
7851 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7852 (clobber (reg:CC CC_REGNUM))]
7855 [(set_attr "conds" "clob")
7856 (set_attr "length" "8,12")]
7859 (define_insn "*if_move_shift"
7860 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7862 (match_operator 5 "arm_comparison_operator"
7863 [(match_operand 6 "cc_register" "") (const_int 0)])
7864 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7865 (match_operator:SI 4 "shift_operator"
7866 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7867 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7871 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7872 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7873 [(set_attr "conds" "use")
7874 (set_attr "shift" "2")
7875 (set_attr "length" "4,8,8")]
7878 (define_insn "*ifcompare_shift_shift"
7879 [(set (match_operand:SI 0 "s_register_operand" "=r")
7881 (match_operator 7 "arm_comparison_operator"
7882 [(match_operand:SI 5 "s_register_operand" "r")
7883 (match_operand:SI 6 "arm_add_operand" "rIL")])
7884 (match_operator:SI 8 "shift_operator"
7885 [(match_operand:SI 1 "s_register_operand" "r")
7886 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7887 (match_operator:SI 9 "shift_operator"
7888 [(match_operand:SI 3 "s_register_operand" "r")
7889 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7890 (clobber (reg:CC CC_REGNUM))]
7893 [(set_attr "conds" "clob")
7894 (set_attr "length" "12")]
7897 (define_insn "*if_shift_shift"
7898 [(set (match_operand:SI 0 "s_register_operand" "=r")
7900 (match_operator 5 "arm_comparison_operator"
7901 [(match_operand 8 "cc_register" "") (const_int 0)])
7902 (match_operator:SI 6 "shift_operator"
7903 [(match_operand:SI 1 "s_register_operand" "r")
7904 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7905 (match_operator:SI 7 "shift_operator"
7906 [(match_operand:SI 3 "s_register_operand" "r")
7907 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7909 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7910 [(set_attr "conds" "use")
7911 (set_attr "shift" "1")
7912 (set_attr "length" "8")]
7915 (define_insn "*ifcompare_not_arith"
7916 [(set (match_operand:SI 0 "s_register_operand" "=r")
7918 (match_operator 6 "arm_comparison_operator"
7919 [(match_operand:SI 4 "s_register_operand" "r")
7920 (match_operand:SI 5 "arm_add_operand" "rIL")])
7921 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7922 (match_operator:SI 7 "shiftable_operator"
7923 [(match_operand:SI 2 "s_register_operand" "r")
7924 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7925 (clobber (reg:CC CC_REGNUM))]
7928 [(set_attr "conds" "clob")
7929 (set_attr "length" "12")]
7932 (define_insn "*if_not_arith"
7933 [(set (match_operand:SI 0 "s_register_operand" "=r")
7935 (match_operator 5 "arm_comparison_operator"
7936 [(match_operand 4 "cc_register" "") (const_int 0)])
7937 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7938 (match_operator:SI 6 "shiftable_operator"
7939 [(match_operand:SI 2 "s_register_operand" "r")
7940 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7942 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7943 [(set_attr "conds" "use")
7944 (set_attr "length" "8")]
7947 (define_insn "*ifcompare_arith_not"
7948 [(set (match_operand:SI 0 "s_register_operand" "=r")
7950 (match_operator 6 "arm_comparison_operator"
7951 [(match_operand:SI 4 "s_register_operand" "r")
7952 (match_operand:SI 5 "arm_add_operand" "rIL")])
7953 (match_operator:SI 7 "shiftable_operator"
7954 [(match_operand:SI 2 "s_register_operand" "r")
7955 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7956 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7957 (clobber (reg:CC CC_REGNUM))]
7960 [(set_attr "conds" "clob")
7961 (set_attr "length" "12")]
7964 (define_insn "*if_arith_not"
7965 [(set (match_operand:SI 0 "s_register_operand" "=r")
7967 (match_operator 5 "arm_comparison_operator"
7968 [(match_operand 4 "cc_register" "") (const_int 0)])
7969 (match_operator:SI 6 "shiftable_operator"
7970 [(match_operand:SI 2 "s_register_operand" "r")
7971 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7972 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7974 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7975 [(set_attr "conds" "use")
7976 (set_attr "length" "8")]
7979 (define_insn "*ifcompare_neg_move"
7980 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7982 (match_operator 5 "arm_comparison_operator"
7983 [(match_operand:SI 3 "s_register_operand" "r,r")
7984 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7985 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7986 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7987 (clobber (reg:CC CC_REGNUM))]
7990 [(set_attr "conds" "clob")
7991 (set_attr "length" "8,12")]
7994 (define_insn "*if_neg_move"
7995 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7997 (match_operator 4 "arm_comparison_operator"
7998 [(match_operand 3 "cc_register" "") (const_int 0)])
7999 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8000 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8004 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8005 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8006 [(set_attr "conds" "use")
8007 (set_attr "length" "4,8,8")]
8010 (define_insn "*ifcompare_move_neg"
8011 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8013 (match_operator 5 "arm_comparison_operator"
8014 [(match_operand:SI 3 "s_register_operand" "r,r")
8015 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8016 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8017 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8018 (clobber (reg:CC CC_REGNUM))]
8021 [(set_attr "conds" "clob")
8022 (set_attr "length" "8,12")]
8025 (define_insn "*if_move_neg"
8026 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8028 (match_operator 4 "arm_comparison_operator"
8029 [(match_operand 3 "cc_register" "") (const_int 0)])
8030 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8031 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8035 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8036 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8037 [(set_attr "conds" "use")
8038 (set_attr "length" "4,8,8")]
8041 (define_insn "*arith_adjacentmem"
8042 [(set (match_operand:SI 0 "s_register_operand" "=r")
8043 (match_operator:SI 1 "shiftable_operator"
8044 [(match_operand:SI 2 "memory_operand" "m")
8045 (match_operand:SI 3 "memory_operand" "m")]))
8046 (clobber (match_scratch:SI 4 "=r"))]
8047 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8052 int val1 = 0, val2 = 0;
8054 if (REGNO (operands[0]) > REGNO (operands[4]))
8056 ldm[1] = operands[4];
8057 ldm[2] = operands[0];
8061 ldm[1] = operands[0];
8062 ldm[2] = operands[4];
8064 if (GET_CODE (XEXP (operands[2], 0)) != REG)
8065 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8066 if (GET_CODE (XEXP (operands[3], 0)) != REG)
8067 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8068 arith[0] = operands[0];
8069 arith[3] = operands[1];
8083 ldm[0] = ops[0] = operands[4];
8084 ops[1] = XEXP (XEXP (operands[2], 0), 0);
8085 ops[2] = XEXP (XEXP (operands[2], 0), 1);
8086 output_add_immediate (ops);
8088 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8090 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8094 ldm[0] = XEXP (operands[3], 0);
8096 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8098 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8102 ldm[0] = XEXP (operands[2], 0);
8104 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8106 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8108 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8111 [(set_attr "length" "12")
8112 (set_attr "predicable" "yes")
8113 (set_attr "type" "load")]
8116 ;; the arm can support extended pre-inc instructions
8118 ;; In all these cases, we use operands 0 and 1 for the register being
8119 ;; incremented because those are the operands that local-alloc will
8120 ;; tie and these are the pair most likely to be tieable (and the ones
8121 ;; that will benefit the most).
8123 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8124 ;; elimination will cause too many headaches.
8126 (define_insn "*strqi_preinc"
8127 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8128 (match_operand:SI 2 "index_operand" "rJ")))
8129 (match_operand:QI 3 "s_register_operand" "r"))
8130 (set (match_operand:SI 0 "s_register_operand" "=r")
8131 (plus:SI (match_dup 1) (match_dup 2)))]
8133 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8134 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8135 && (GET_CODE (operands[2]) != REG
8136 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8137 "str%?b\\t%3, [%0, %2]!"
8138 [(set_attr "type" "store1")
8139 (set_attr "predicable" "yes")]
8142 (define_insn "*strqi_predec"
8143 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8144 (match_operand:SI 2 "s_register_operand" "r")))
8145 (match_operand:QI 3 "s_register_operand" "r"))
8146 (set (match_operand:SI 0 "s_register_operand" "=r")
8147 (minus:SI (match_dup 1) (match_dup 2)))]
8149 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8150 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8151 && (GET_CODE (operands[2]) != REG
8152 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8153 "str%?b\\t%3, [%0, -%2]!"
8154 [(set_attr "type" "store1")
8155 (set_attr "predicable" "yes")]
8158 (define_insn "*loadqi_preinc"
8159 [(set (match_operand:QI 3 "s_register_operand" "=r")
8160 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8161 (match_operand:SI 2 "index_operand" "rJ"))))
8162 (set (match_operand:SI 0 "s_register_operand" "=r")
8163 (plus:SI (match_dup 1) (match_dup 2)))]
8165 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8166 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8167 && (GET_CODE (operands[2]) != REG
8168 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8169 "ldr%?b\\t%3, [%0, %2]!"
8170 [(set_attr "type" "load")
8171 (set_attr "predicable" "yes")]
8174 (define_insn "*loadqi_predec"
8175 [(set (match_operand:QI 3 "s_register_operand" "=r")
8176 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8177 (match_operand:SI 2 "s_register_operand" "r"))))
8178 (set (match_operand:SI 0 "s_register_operand" "=r")
8179 (minus:SI (match_dup 1) (match_dup 2)))]
8181 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8182 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8183 && (GET_CODE (operands[2]) != REG
8184 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8185 "ldr%?b\\t%3, [%0, -%2]!"
8186 [(set_attr "type" "load")
8187 (set_attr "predicable" "yes")]
8190 (define_insn "*loadqisi_preinc"
8191 [(set (match_operand:SI 3 "s_register_operand" "=r")
8193 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8194 (match_operand:SI 2 "index_operand" "rJ")))))
8195 (set (match_operand:SI 0 "s_register_operand" "=r")
8196 (plus:SI (match_dup 1) (match_dup 2)))]
8198 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8199 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8200 && (GET_CODE (operands[2]) != REG
8201 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8202 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8203 [(set_attr "type" "load")
8204 (set_attr "predicable" "yes")]
8207 (define_insn "*loadqisi_predec"
8208 [(set (match_operand:SI 3 "s_register_operand" "=r")
8210 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8211 (match_operand:SI 2 "s_register_operand" "r")))))
8212 (set (match_operand:SI 0 "s_register_operand" "=r")
8213 (minus:SI (match_dup 1) (match_dup 2)))]
8215 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8216 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8217 && (GET_CODE (operands[2]) != REG
8218 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8219 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8220 [(set_attr "type" "load")
8221 (set_attr "predicable" "yes")]
8224 (define_insn "*strsi_preinc"
8225 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8226 (match_operand:SI 2 "index_operand" "rJ")))
8227 (match_operand:SI 3 "s_register_operand" "r"))
8228 (set (match_operand:SI 0 "s_register_operand" "=r")
8229 (plus:SI (match_dup 1) (match_dup 2)))]
8231 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8232 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8233 && (GET_CODE (operands[2]) != REG
8234 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8235 "str%?\\t%3, [%0, %2]!"
8236 [(set_attr "type" "store1")
8237 (set_attr "predicable" "yes")]
8240 (define_insn "*strsi_predec"
8241 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8242 (match_operand:SI 2 "s_register_operand" "r")))
8243 (match_operand:SI 3 "s_register_operand" "r"))
8244 (set (match_operand:SI 0 "s_register_operand" "=r")
8245 (minus:SI (match_dup 1) (match_dup 2)))]
8247 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8248 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8249 && (GET_CODE (operands[2]) != REG
8250 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8251 "str%?\\t%3, [%0, -%2]!"
8252 [(set_attr "type" "store1")
8253 (set_attr "predicable" "yes")]
8256 (define_insn "*loadsi_preinc"
8257 [(set (match_operand:SI 3 "s_register_operand" "=r")
8258 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8259 (match_operand:SI 2 "index_operand" "rJ"))))
8260 (set (match_operand:SI 0 "s_register_operand" "=r")
8261 (plus:SI (match_dup 1) (match_dup 2)))]
8263 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8264 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8265 && (GET_CODE (operands[2]) != REG
8266 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8267 "ldr%?\\t%3, [%0, %2]!"
8268 [(set_attr "type" "load")
8269 (set_attr "predicable" "yes")]
8272 (define_insn "*loadsi_predec"
8273 [(set (match_operand:SI 3 "s_register_operand" "=r")
8274 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8275 (match_operand:SI 2 "s_register_operand" "r"))))
8276 (set (match_operand:SI 0 "s_register_operand" "=r")
8277 (minus:SI (match_dup 1) (match_dup 2)))]
8279 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8280 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8281 && (GET_CODE (operands[2]) != REG
8282 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8283 "ldr%?\\t%3, [%0, -%2]!"
8284 [(set_attr "type" "load")
8285 (set_attr "predicable" "yes")]
8288 (define_insn "*loadhi_preinc"
8289 [(set (match_operand:HI 3 "s_register_operand" "=r")
8290 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8291 (match_operand:SI 2 "index_operand" "rJ"))))
8292 (set (match_operand:SI 0 "s_register_operand" "=r")
8293 (plus:SI (match_dup 1) (match_dup 2)))]
8295 && !BYTES_BIG_ENDIAN
8296 && !TARGET_MMU_TRAPS
8297 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8298 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8299 && (GET_CODE (operands[2]) != REG
8300 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8301 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8302 [(set_attr "type" "load")
8303 (set_attr "predicable" "yes")]
8306 (define_insn "*loadhi_predec"
8307 [(set (match_operand:HI 3 "s_register_operand" "=r")
8308 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8309 (match_operand:SI 2 "s_register_operand" "r"))))
8310 (set (match_operand:SI 0 "s_register_operand" "=r")
8311 (minus:SI (match_dup 1) (match_dup 2)))]
8313 && !BYTES_BIG_ENDIAN
8314 && !TARGET_MMU_TRAPS
8315 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8316 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8317 && (GET_CODE (operands[2]) != REG
8318 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8319 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8320 [(set_attr "type" "load")
8321 (set_attr "predicable" "yes")]
8324 (define_insn "*strqi_shiftpreinc"
8325 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8326 [(match_operand:SI 3 "s_register_operand" "r")
8327 (match_operand:SI 4 "const_shift_operand" "n")])
8328 (match_operand:SI 1 "s_register_operand" "0")))
8329 (match_operand:QI 5 "s_register_operand" "r"))
8330 (set (match_operand:SI 0 "s_register_operand" "=r")
8331 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8334 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8335 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8336 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8337 "str%?b\\t%5, [%0, %3%S2]!"
8338 [(set_attr "type" "store1")
8339 (set_attr "predicable" "yes")]
8342 (define_insn "*strqi_shiftpredec"
8343 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8344 (match_operator:SI 2 "shift_operator"
8345 [(match_operand:SI 3 "s_register_operand" "r")
8346 (match_operand:SI 4 "const_shift_operand" "n")])))
8347 (match_operand:QI 5 "s_register_operand" "r"))
8348 (set (match_operand:SI 0 "s_register_operand" "=r")
8349 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8352 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8353 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8354 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8355 "str%?b\\t%5, [%0, -%3%S2]!"
8356 [(set_attr "type" "store1")
8357 (set_attr "predicable" "yes")]
8360 (define_insn "*loadqi_shiftpreinc"
8361 [(set (match_operand:QI 5 "s_register_operand" "=r")
8362 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8363 [(match_operand:SI 3 "s_register_operand" "r")
8364 (match_operand:SI 4 "const_shift_operand" "n")])
8365 (match_operand:SI 1 "s_register_operand" "0"))))
8366 (set (match_operand:SI 0 "s_register_operand" "=r")
8367 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8370 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8371 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8372 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8373 "ldr%?b\\t%5, [%0, %3%S2]!"
8374 [(set_attr "type" "load")
8375 (set_attr "predicable" "yes")]
8378 (define_insn "*loadqi_shiftpredec"
8379 [(set (match_operand:QI 5 "s_register_operand" "=r")
8380 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8381 (match_operator:SI 2 "shift_operator"
8382 [(match_operand:SI 3 "s_register_operand" "r")
8383 (match_operand:SI 4 "const_shift_operand" "n")]))))
8384 (set (match_operand:SI 0 "s_register_operand" "=r")
8385 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8388 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8389 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8390 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8391 "ldr%?b\\t%5, [%0, -%3%S2]!"
8392 [(set_attr "type" "load")
8393 (set_attr "predicable" "yes")]
8396 (define_insn "*strsi_shiftpreinc"
8397 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8398 [(match_operand:SI 3 "s_register_operand" "r")
8399 (match_operand:SI 4 "const_shift_operand" "n")])
8400 (match_operand:SI 1 "s_register_operand" "0")))
8401 (match_operand:SI 5 "s_register_operand" "r"))
8402 (set (match_operand:SI 0 "s_register_operand" "=r")
8403 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8406 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8407 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8408 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8409 "str%?\\t%5, [%0, %3%S2]!"
8410 [(set_attr "type" "store1")
8411 (set_attr "predicable" "yes")]
8414 (define_insn "*strsi_shiftpredec"
8415 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8416 (match_operator:SI 2 "shift_operator"
8417 [(match_operand:SI 3 "s_register_operand" "r")
8418 (match_operand:SI 4 "const_shift_operand" "n")])))
8419 (match_operand:SI 5 "s_register_operand" "r"))
8420 (set (match_operand:SI 0 "s_register_operand" "=r")
8421 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8424 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8425 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8426 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8427 "str%?\\t%5, [%0, -%3%S2]!"
8428 [(set_attr "type" "store1")
8429 (set_attr "predicable" "yes")]
8432 (define_insn "*loadsi_shiftpreinc"
8433 [(set (match_operand:SI 5 "s_register_operand" "=r")
8434 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8435 [(match_operand:SI 3 "s_register_operand" "r")
8436 (match_operand:SI 4 "const_shift_operand" "n")])
8437 (match_operand:SI 1 "s_register_operand" "0"))))
8438 (set (match_operand:SI 0 "s_register_operand" "=r")
8439 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8442 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8443 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8444 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8445 "ldr%?\\t%5, [%0, %3%S2]!"
8446 [(set_attr "type" "load")
8447 (set_attr "predicable" "yes")]
8450 (define_insn "*loadsi_shiftpredec"
8451 [(set (match_operand:SI 5 "s_register_operand" "=r")
8452 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8453 (match_operator:SI 2 "shift_operator"
8454 [(match_operand:SI 3 "s_register_operand" "r")
8455 (match_operand:SI 4 "const_shift_operand" "n")]))))
8456 (set (match_operand:SI 0 "s_register_operand" "=r")
8457 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8460 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8461 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8462 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8463 "ldr%?\\t%5, [%0, -%3%S2]!"
8464 [(set_attr "type" "load")
8465 (set_attr "predicable" "yes")])
8467 (define_insn "*loadhi_shiftpreinc"
8468 [(set (match_operand:HI 5 "s_register_operand" "=r")
8469 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8470 [(match_operand:SI 3 "s_register_operand" "r")
8471 (match_operand:SI 4 "const_shift_operand" "n")])
8472 (match_operand:SI 1 "s_register_operand" "0"))))
8473 (set (match_operand:SI 0 "s_register_operand" "=r")
8474 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8477 && !BYTES_BIG_ENDIAN
8478 && !TARGET_MMU_TRAPS
8479 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8480 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8481 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8482 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8483 [(set_attr "type" "load")
8484 (set_attr "predicable" "yes")]
8487 (define_insn "*loadhi_shiftpredec"
8488 [(set (match_operand:HI 5 "s_register_operand" "=r")
8489 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8490 (match_operator:SI 2 "shift_operator"
8491 [(match_operand:SI 3 "s_register_operand" "r")
8492 (match_operand:SI 4 "const_shift_operand" "n")]))))
8493 (set (match_operand:SI 0 "s_register_operand" "=r")
8494 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8497 && !BYTES_BIG_ENDIAN
8498 && !TARGET_MMU_TRAPS
8499 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8500 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8501 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8502 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8503 [(set_attr "type" "load")
8504 (set_attr "predicable" "yes")]
8507 ; It can also support extended post-inc expressions, but combine doesn't
8509 ; It doesn't seem worth adding peepholes for anything but the most common
8510 ; cases since, unlike combine, the increment must immediately follow the load
8511 ; for this pattern to match.
8512 ; We must watch to see that the source/destination register isn't also the
8513 ; same as the base address register, and that if the index is a register,
8514 ; that it is not the same as the base address register. In such cases the
8515 ; instruction that we would generate would have UNPREDICTABLE behaviour so
8519 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8520 (match_operand:QI 2 "s_register_operand" "r"))
8522 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8524 && (REGNO (operands[2]) != REGNO (operands[0]))
8525 && (GET_CODE (operands[1]) != REG
8526 || (REGNO (operands[1]) != REGNO (operands[0])))"
8527 "str%?b\\t%2, [%0], %1"
8531 [(set (match_operand:QI 0 "s_register_operand" "=r")
8532 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8534 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8536 && REGNO (operands[0]) != REGNO(operands[1])
8537 && (GET_CODE (operands[2]) != REG
8538 || REGNO(operands[0]) != REGNO (operands[2]))"
8539 "ldr%?b\\t%0, [%1], %2"
8543 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8544 (match_operand:SI 2 "s_register_operand" "r"))
8546 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8548 && (REGNO (operands[2]) != REGNO (operands[0]))
8549 && (GET_CODE (operands[1]) != REG
8550 || (REGNO (operands[1]) != REGNO (operands[0])))"
8551 "str%?\\t%2, [%0], %1"
8555 [(set (match_operand:HI 0 "s_register_operand" "=r")
8556 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8558 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8560 && !BYTES_BIG_ENDIAN
8561 && !TARGET_MMU_TRAPS
8562 && REGNO (operands[0]) != REGNO(operands[1])
8563 && (GET_CODE (operands[2]) != REG
8564 || REGNO(operands[0]) != REGNO (operands[2]))"
8565 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8569 [(set (match_operand:SI 0 "s_register_operand" "=r")
8570 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8572 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8574 && REGNO (operands[0]) != REGNO(operands[1])
8575 && (GET_CODE (operands[2]) != REG
8576 || REGNO(operands[0]) != REGNO (operands[2]))"
8577 "ldr%?\\t%0, [%1], %2"
8581 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8582 (match_operand:SI 1 "index_operand" "rJ")))
8583 (match_operand:QI 2 "s_register_operand" "r"))
8584 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8586 && (REGNO (operands[2]) != REGNO (operands[0]))
8587 && (GET_CODE (operands[1]) != REG
8588 || (REGNO (operands[1]) != REGNO (operands[0])))"
8589 "str%?b\\t%2, [%0, %1]!"
8593 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8594 [(match_operand:SI 0 "s_register_operand" "r")
8595 (match_operand:SI 1 "const_int_operand" "n")])
8596 (match_operand:SI 2 "s_register_operand" "+r")))
8597 (match_operand:QI 3 "s_register_operand" "r"))
8598 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8601 && (REGNO (operands[3]) != REGNO (operands[2]))
8602 && (REGNO (operands[0]) != REGNO (operands[2]))"
8603 "str%?b\\t%3, [%2, %0%S4]!"
8606 ; This pattern is never tried by combine, so do it as a peephole
8609 [(set (match_operand:SI 0 "s_register_operand" "")
8610 (match_operand:SI 1 "s_register_operand" ""))
8611 (set (reg:CC CC_REGNUM)
8612 (compare:CC (match_dup 1) (const_int 0)))]
8615 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8616 (set (match_dup 0) (match_dup 1))])]
8620 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8621 ; reversed, check that the memory references aren't volatile.
8624 [(set (match_operand:SI 0 "s_register_operand" "=r")
8625 (match_operand:SI 4 "memory_operand" "m"))
8626 (set (match_operand:SI 1 "s_register_operand" "=r")
8627 (match_operand:SI 5 "memory_operand" "m"))
8628 (set (match_operand:SI 2 "s_register_operand" "=r")
8629 (match_operand:SI 6 "memory_operand" "m"))
8630 (set (match_operand:SI 3 "s_register_operand" "=r")
8631 (match_operand:SI 7 "memory_operand" "m"))]
8632 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8634 return emit_ldm_seq (operands, 4);
8639 [(set (match_operand:SI 0 "s_register_operand" "=r")
8640 (match_operand:SI 3 "memory_operand" "m"))
8641 (set (match_operand:SI 1 "s_register_operand" "=r")
8642 (match_operand:SI 4 "memory_operand" "m"))
8643 (set (match_operand:SI 2 "s_register_operand" "=r")
8644 (match_operand:SI 5 "memory_operand" "m"))]
8645 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8647 return emit_ldm_seq (operands, 3);
8652 [(set (match_operand:SI 0 "s_register_operand" "=r")
8653 (match_operand:SI 2 "memory_operand" "m"))
8654 (set (match_operand:SI 1 "s_register_operand" "=r")
8655 (match_operand:SI 3 "memory_operand" "m"))]
8656 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8658 return emit_ldm_seq (operands, 2);
8663 [(set (match_operand:SI 4 "memory_operand" "=m")
8664 (match_operand:SI 0 "s_register_operand" "r"))
8665 (set (match_operand:SI 5 "memory_operand" "=m")
8666 (match_operand:SI 1 "s_register_operand" "r"))
8667 (set (match_operand:SI 6 "memory_operand" "=m")
8668 (match_operand:SI 2 "s_register_operand" "r"))
8669 (set (match_operand:SI 7 "memory_operand" "=m")
8670 (match_operand:SI 3 "s_register_operand" "r"))]
8671 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8673 return emit_stm_seq (operands, 4);
8678 [(set (match_operand:SI 3 "memory_operand" "=m")
8679 (match_operand:SI 0 "s_register_operand" "r"))
8680 (set (match_operand:SI 4 "memory_operand" "=m")
8681 (match_operand:SI 1 "s_register_operand" "r"))
8682 (set (match_operand:SI 5 "memory_operand" "=m")
8683 (match_operand:SI 2 "s_register_operand" "r"))]
8684 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8686 return emit_stm_seq (operands, 3);
8691 [(set (match_operand:SI 2 "memory_operand" "=m")
8692 (match_operand:SI 0 "s_register_operand" "r"))
8693 (set (match_operand:SI 3 "memory_operand" "=m")
8694 (match_operand:SI 1 "s_register_operand" "r"))]
8695 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8697 return emit_stm_seq (operands, 2);
8702 [(set (match_operand:SI 0 "s_register_operand" "")
8703 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8705 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8706 [(match_operand:SI 3 "s_register_operand" "")
8707 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8708 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8710 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8711 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8716 ;; This split can be used because CC_Z mode implies that the following
8717 ;; branch will be an equality, or an unsigned inequality, so the sign
8718 ;; extension is not needed.
8721 [(set (reg:CC_Z CC_REGNUM)
8723 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8725 (match_operand 1 "const_int_operand" "")))
8726 (clobber (match_scratch:SI 2 ""))]
8728 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8729 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8730 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8731 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8733 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8737 (define_expand "prologue"
8738 [(clobber (const_int 0))]
8741 arm_expand_prologue ();
8743 thumb_expand_prologue ();
8748 (define_expand "epilogue"
8749 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8753 thumb_expand_epilogue ();
8754 else if (USE_RETURN_INSN (FALSE))
8756 emit_jump_insn (gen_return ());
8759 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8761 gen_rtx_RETURN (VOIDmode)),
8767 (define_insn "sibcall_epilogue"
8768 [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8771 output_asm_insn (\"%@ Sibcall epilogue\", operands);
8772 if (USE_RETURN_INSN (FALSE))
8773 return output_return_instruction (NULL, FALSE, FALSE);
8774 return arm_output_epilogue (FALSE);
8776 ;; Length is absolute worst case
8777 [(set_attr "length" "44")
8778 (set_attr "type" "block")]
8781 (define_insn "*epilogue_insns"
8782 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8786 return arm_output_epilogue (TRUE);
8787 else /* TARGET_THUMB */
8788 return thumb_unexpanded_epilogue ();
8790 ; Length is absolute worst case
8791 [(set_attr "length" "44")
8792 (set_attr "type" "block")]
8795 (define_expand "eh_epilogue"
8796 [(use (match_operand:SI 0 "register_operand" "r"))
8797 (use (match_operand:SI 1 "register_operand" "r"))
8798 (use (match_operand:SI 2 "register_operand" "r"))]
8802 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8803 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8805 rtx ra = gen_rtx_REG (Pmode, 2);
8807 emit_move_insn (ra, operands[2]);
8810 /* This is a hack -- we may have crystalized the function type too
8812 cfun->machine->func_type = 0;
8816 ;; This split is only used during output to reduce the number of patterns
8817 ;; that need assembler instructions adding to them. We allowed the setting
8818 ;; of the conditions to be implicit during rtl generation so that
8819 ;; the conditional compare patterns would work. However this conflicts to
8820 ;; some extent with the conditional data operations, so we have to split them
8824 [(set (match_operand:SI 0 "s_register_operand" "")
8825 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8826 [(match_operand 2 "" "") (match_operand 3 "" "")])
8828 (match_operand 4 "" "")))
8829 (clobber (reg:CC CC_REGNUM))]
8830 "TARGET_ARM && reload_completed"
8831 [(set (match_dup 5) (match_dup 6))
8832 (cond_exec (match_dup 7)
8833 (set (match_dup 0) (match_dup 4)))]
8836 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8837 operands[2], operands[3]);
8838 enum rtx_code rc = GET_CODE (operands[1]);
8840 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8841 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8842 if (mode == CCFPmode || mode == CCFPEmode)
8843 rc = reverse_condition_maybe_unordered (rc);
8845 rc = reverse_condition (rc);
8847 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8852 [(set (match_operand:SI 0 "s_register_operand" "")
8853 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8854 [(match_operand 2 "" "") (match_operand 3 "" "")])
8855 (match_operand 4 "" "")
8857 (clobber (reg:CC CC_REGNUM))]
8858 "TARGET_ARM && reload_completed"
8859 [(set (match_dup 5) (match_dup 6))
8860 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8861 (set (match_dup 0) (match_dup 4)))]
8864 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8865 operands[2], operands[3]);
8867 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8868 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8873 [(set (match_operand:SI 0 "s_register_operand" "")
8874 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8875 [(match_operand 2 "" "") (match_operand 3 "" "")])
8876 (match_operand 4 "" "")
8877 (match_operand 5 "" "")))
8878 (clobber (reg:CC CC_REGNUM))]
8879 "TARGET_ARM && reload_completed"
8880 [(set (match_dup 6) (match_dup 7))
8881 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8882 (set (match_dup 0) (match_dup 4)))
8883 (cond_exec (match_dup 8)
8884 (set (match_dup 0) (match_dup 5)))]
8887 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8888 operands[2], operands[3]);
8889 enum rtx_code rc = GET_CODE (operands[1]);
8891 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8892 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8893 if (mode == CCFPmode || mode == CCFPEmode)
8894 rc = reverse_condition_maybe_unordered (rc);
8896 rc = reverse_condition (rc);
8898 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8903 [(set (match_operand:SI 0 "s_register_operand" "")
8904 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8905 [(match_operand:SI 2 "s_register_operand" "")
8906 (match_operand:SI 3 "arm_add_operand" "")])
8907 (match_operand:SI 4 "arm_rhs_operand" "")
8909 (match_operand:SI 5 "s_register_operand" ""))))
8910 (clobber (reg:CC CC_REGNUM))]
8911 "TARGET_ARM && reload_completed"
8912 [(set (match_dup 6) (match_dup 7))
8913 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8914 (set (match_dup 0) (match_dup 4)))
8915 (cond_exec (match_dup 8)
8916 (set (match_dup 0) (not:SI (match_dup 5))))]
8919 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8920 operands[2], operands[3]);
8921 enum rtx_code rc = GET_CODE (operands[1]);
8923 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8924 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8925 if (mode == CCFPmode || mode == CCFPEmode)
8926 rc = reverse_condition_maybe_unordered (rc);
8928 rc = reverse_condition (rc);
8930 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8934 (define_insn "*cond_move_not"
8935 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8936 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8937 [(match_operand 3 "cc_register" "") (const_int 0)])
8938 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8940 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8944 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8945 [(set_attr "conds" "use")
8946 (set_attr "length" "4,8")]
8949 ;; The next two patterns occur when an AND operation is followed by a
8950 ;; scc insn sequence
8952 (define_insn "*sign_extract_onebit"
8953 [(set (match_operand:SI 0 "s_register_operand" "=r")
8954 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8956 (match_operand:SI 2 "const_int_operand" "n")))]
8959 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8960 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8961 return \"mvnne\\t%0, #0\";
8963 [(set_attr "conds" "clob")
8964 (set_attr "length" "8")]
8967 (define_insn "*not_signextract_onebit"
8968 [(set (match_operand:SI 0 "s_register_operand" "=r")
8970 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8972 (match_operand:SI 2 "const_int_operand" "n"))))]
8975 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8976 output_asm_insn (\"tst\\t%1, %2\", operands);
8977 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8978 return \"movne\\t%0, #0\";
8980 [(set_attr "conds" "clob")
8981 (set_attr "length" "12")]
8984 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8985 ;; expressions. For simplicity, the first register is also in the unspec
8987 (define_insn "*push_multi"
8988 [(match_parallel 2 "multi_register_push"
8989 [(set (match_operand:BLK 0 "memory_operand" "=m")
8990 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8991 UNSPEC_PUSH_MULT))])]
8995 int num_saves = XVECLEN (operands[2], 0);
8997 /* For the StrongARM at least it is faster to
8998 use STR to store only a single register. */
9000 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9006 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9008 for (i = 1; i < num_saves; i++)
9010 strcat (pattern, \", %|\");
9012 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9015 strcat (pattern, \"}\");
9016 output_asm_insn (pattern, operands);
9021 [(set_attr "type" "store4")]
9024 ;; Similarly for the floating point registers
9025 (define_insn "*push_fp_multi"
9026 [(match_parallel 2 "multi_register_push"
9027 [(set (match_operand:BLK 0 "memory_operand" "=m")
9028 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9029 UNSPEC_PUSH_MULT))])]
9035 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9036 output_asm_insn (pattern, operands);
9039 [(set_attr "type" "f_store")]
9042 ;; Special patterns for dealing with the constant pool
9044 (define_insn "align_4"
9045 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9048 assemble_align (32);
9053 (define_insn "consttable_end"
9054 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9057 making_const_table = FALSE;
9062 (define_insn "consttable_1"
9063 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9066 making_const_table = TRUE;
9067 assemble_integer (operands[0], 1, 1);
9071 [(set_attr "length" "4")]
9074 (define_insn "consttable_2"
9075 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9078 making_const_table = TRUE;
9079 assemble_integer (operands[0], 2, 1);
9083 [(set_attr "length" "4")]
9086 (define_insn "consttable_4"
9087 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9091 making_const_table = TRUE;
9092 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9096 union real_extract u;
9097 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9098 assemble_real (u.d, GET_MODE (operands[0]));
9102 assemble_integer (operands[0], 4, 1);
9107 [(set_attr "length" "4")]
9110 (define_insn "consttable_8"
9111 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9115 making_const_table = TRUE;
9116 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9120 union real_extract u;
9121 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9122 assemble_real (u.d, GET_MODE (operands[0]));
9126 assemble_integer (operands[0], 8, 1);
9131 [(set_attr "length" "8")]
9134 ;; Miscellaneous Thumb patterns
9136 (define_insn "tablejump"
9137 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9138 (use (label_ref (match_operand 1 "" "")))]
9141 [(set_attr "length" "2")]
9147 [(set (match_operand:SI 0 "s_register_operand" "=r")
9148 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9150 "TARGET_ARM && arm_arch5"
9153 (define_expand "ffssi2"
9154 [(set (match_operand:SI 0 "s_register_operand" "")
9155 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9156 "TARGET_ARM && arm_arch5"
9161 t1 = gen_reg_rtx (SImode);
9162 t2 = gen_reg_rtx (SImode);
9163 t3 = gen_reg_rtx (SImode);
9165 emit_insn (gen_negsi2 (t1, operands[1]));
9166 emit_insn (gen_andsi3 (t2, operands[1], t1));
9167 emit_insn (gen_clz (t3, t2));
9168 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9173 ;; V5E instructions.
9175 (define_insn "prefetch"
9177 [(match_operand:SI 0 "offsettable_memory_operand" "o")] VUNSPEC_PREFETCH)]
9178 "TARGET_ARM && arm_arch5e"
9181 ;; General predication pattern
9184 [(match_operator 0 "arm_comparison_operator"
9185 [(match_operand 1 "cc_register" "")