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 addr = XEXP (operands[1], 0);
4286 enum rtx_code code = GET_CODE (addr);
4288 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4290 addr = force_reg (SImode, addr);
4292 operands[4] = change_address (operands[1], QImode,
4293 plus_constant (addr, 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 addr = XEXP (operands[1], 0);
4310 enum rtx_code code = GET_CODE (addr);
4312 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4314 addr = force_reg (SImode, addr);
4316 operands[4] = change_address (operands[1], QImode,
4317 plus_constant (addr, 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 enum rtx_code code = GET_CODE (addr);
4337 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4339 addr = force_reg (SImode, addr);
4341 operands[1] = gen_reg_rtx (SImode);
4342 if (BYTES_BIG_ENDIAN)
4344 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4345 if ((value & 255) == ((value >> 8) & 255))
4346 operands[2] = operands[1];
4349 operands[2] = gen_reg_rtx (SImode);
4350 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4355 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4356 if ((value & 255) == ((value >> 8) & 255))
4357 operands[2] = operands[1];
4360 operands[2] = gen_reg_rtx (SImode);
4361 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4365 operands[3] = change_address (operands[0], QImode,
4366 plus_constant (addr, 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 rtx temp = copy_to_reg (XEXP (operands[0], 0));
4555 operands[0] = change_address (operands[0], VOIDmode, temp);
4558 if (GET_CODE (operands[1]) == MEM
4559 && !memory_address_p (GET_MODE (operands[1]),
4560 XEXP (operands[1], 0)))
4562 rtx temp = copy_to_reg (XEXP (operands[1], 0));
4563 operands[1] = change_address (operands[1], VOIDmode, temp);
4566 /* Handle loading a large integer during reload */
4567 else if (GET_CODE (operands[1]) == CONST_INT
4568 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4570 /* Writing a constant to memory needs a scratch, which should
4571 be handled with SECONDARY_RELOADs. */
4572 if (GET_CODE (operands[0]) != REG)
4575 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4576 emit_insn (gen_movsi (operands[0], operands[1]));
4583 (define_insn "*thumb_movhi_insn"
4584 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4585 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4587 && ( register_operand (operands[0], HImode)
4588 || register_operand (operands[1], HImode))"
4590 switch (which_alternative)
4592 case 0: return \"add %0, %1, #0\";
4593 case 2: return \"strh %1, %0\";
4594 case 3: return \"mov %0, %1\";
4595 case 4: return \"mov %0, %1\";
4596 case 5: return \"mov %0, %1\";
4599 /* The stack pointer can end up being taken as an index register.
4600 Catch this case here and deal with it. */
4601 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4602 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4603 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4606 ops[0] = operands[0];
4607 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4609 output_asm_insn (\"mov %0, %1\", ops);
4611 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4614 return \"ldrh %0, %1\";
4616 [(set_attr "length" "2,4,2,2,2,2")
4617 (set_attr "type" "*,load,store1,*,*,*")
4618 (set_attr "pool_range" "*,64,*,*,*,*")]
4622 (define_insn "rotated_loadsi"
4623 [(set (match_operand:SI 0 "s_register_operand" "=r")
4624 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4626 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4631 ops[0] = operands[0];
4632 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4633 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4636 [(set_attr "type" "load")
4637 (set_attr "predicable" "yes")]
4640 (define_expand "movhi_bytes"
4641 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4643 (zero_extend:SI (match_dup 6)))
4644 (set (match_operand:SI 0 "" "")
4645 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4650 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4652 mem1 = gen_rtx_MEM (QImode, addr);
4653 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4654 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4655 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4656 operands[0] = gen_lowpart (SImode, operands[0]);
4658 operands[2] = gen_reg_rtx (SImode);
4659 operands[3] = gen_reg_rtx (SImode);
4662 if (BYTES_BIG_ENDIAN)
4664 operands[4] = operands[2];
4665 operands[5] = operands[3];
4669 operands[4] = operands[3];
4670 operands[5] = operands[2];
4675 (define_expand "movhi_bigend"
4677 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4680 (ashiftrt:SI (match_dup 2) (const_int 16)))
4681 (set (match_operand:HI 0 "s_register_operand" "")
4682 (subreg:HI (match_dup 3) 0))]
4685 operands[2] = gen_reg_rtx (SImode);
4686 operands[3] = gen_reg_rtx (SImode);
4690 ;; Pattern to recognise insn generated default case above
4691 (define_insn "*movhi_insn_arch4"
4692 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4693 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4696 && (GET_CODE (operands[1]) != CONST_INT
4697 || const_ok_for_arm (INTVAL (operands[1]))
4698 || const_ok_for_arm (~INTVAL (operands[1])))"
4700 mov%?\\t%0, %1\\t%@ movhi
4701 mvn%?\\t%0, #%B1\\t%@ movhi
4702 str%?h\\t%1, %0\\t%@ movhi
4703 ldr%?h\\t%0, %1\\t%@ movhi"
4704 [(set_attr "type" "*,*,store1,load")
4705 (set_attr "predicable" "yes")
4706 (set_attr "pool_range" "*,*,*,256")
4707 (set_attr "neg_pool_range" "*,*,*,244")]
4710 (define_insn "*movhi_insn_littleend"
4711 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4712 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4715 && !BYTES_BIG_ENDIAN
4716 && !TARGET_MMU_TRAPS
4717 && (GET_CODE (operands[1]) != CONST_INT
4718 || const_ok_for_arm (INTVAL (operands[1]))
4719 || const_ok_for_arm (~INTVAL (operands[1])))"
4721 mov%?\\t%0, %1\\t%@ movhi
4722 mvn%?\\t%0, #%B1\\t%@ movhi
4723 ldr%?\\t%0, %1\\t%@ movhi"
4724 [(set_attr "type" "*,*,load")
4725 (set_attr "predicable" "yes")
4726 (set_attr "pool_range" "4096")
4727 (set_attr "neg_pool_range" "4084")]
4730 (define_insn "*movhi_insn_bigend"
4731 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4732 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4736 && !TARGET_MMU_TRAPS
4737 && (GET_CODE (operands[1]) != CONST_INT
4738 || const_ok_for_arm (INTVAL (operands[1]))
4739 || const_ok_for_arm (~INTVAL (operands[1])))"
4741 mov%?\\t%0, %1\\t%@ movhi
4742 mvn%?\\t%0, #%B1\\t%@ movhi
4743 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4744 [(set_attr "type" "*,*,load")
4745 (set_attr "predicable" "yes")
4746 (set_attr "length" "4,4,8")
4747 (set_attr "pool_range" "*,*,4092")
4748 (set_attr "neg_pool_range" "*,*,4084")]
4751 (define_insn "*loadhi_si_bigend"
4752 [(set (match_operand:SI 0 "s_register_operand" "=r")
4753 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4757 && !TARGET_MMU_TRAPS"
4758 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4759 [(set_attr "type" "load")
4760 (set_attr "predicable" "yes")
4761 (set_attr "pool_range" "4096")
4762 (set_attr "neg_pool_range" "4084")]
4765 (define_insn "*movhi_bytes"
4766 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4767 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4768 "TARGET_ARM && TARGET_MMU_TRAPS"
4770 mov%?\\t%0, %1\\t%@ movhi
4771 mvn%?\\t%0, #%B1\\t%@ movhi"
4772 [(set_attr "predicable" "yes")]
4775 (define_insn "thumb_movhi_clobber"
4776 [(set (match_operand:HI 0 "memory_operand" "=m")
4777 (match_operand:HI 1 "register_operand" "l"))
4778 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4784 ;; We use a DImode scratch because we may occasionally need an additional
4785 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4786 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4787 (define_expand "reload_outhi"
4788 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4789 (match_operand:HI 1 "s_register_operand" "r")
4790 (match_operand:DI 2 "s_register_operand" "=&l")])]
4793 arm_reload_out_hi (operands);
4795 thumb_reload_out_hi (operands);
4800 (define_expand "reload_inhi"
4801 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4802 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4803 (match_operand:DI 2 "s_register_operand" "=&r")])]
4804 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4807 arm_reload_in_hi (operands);
4809 thumb_reload_out_hi (operands);
4813 (define_expand "movqi"
4814 [(set (match_operand:QI 0 "general_operand" "")
4815 (match_operand:QI 1 "general_operand" ""))]
4820 /* Everything except mem = const or mem = mem can be done easily */
4822 if (!no_new_pseudos)
4824 if (GET_CODE (operands[1]) == CONST_INT)
4826 rtx reg = gen_reg_rtx (SImode);
4828 emit_insn (gen_movsi (reg, operands[1]));
4829 operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
4831 if (GET_CODE (operands[0]) == MEM)
4832 operands[1] = force_reg (QImode, operands[1]);
4835 else /* TARGET_THUMB */
4837 if (!no_new_pseudos)
4839 if (GET_CODE (operands[0]) != REG)
4840 operands[1] = force_reg (QImode, operands[1]);
4842 /* ??? We shouldn't really get invalid addresses here, but this can
4843 happen if we are passed a SP (never OK for HImode/QImode) or
4844 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4845 HImode/QImode) relative address. */
4846 /* ??? This should perhaps be fixed elsewhere, for instance, in
4847 fixup_stack_1, by checking for other kinds of invalid addresses,
4848 e.g. a bare reference to a virtual register. This may confuse the
4849 alpha though, which must handle this case differently. */
4850 if (GET_CODE (operands[0]) == MEM
4851 && !memory_address_p (GET_MODE (operands[0]),
4852 XEXP (operands[0], 0)))
4854 rtx temp = copy_to_reg (XEXP (operands[0], 0));
4855 operands[0] = change_address (operands[0], VOIDmode, temp);
4857 if (GET_CODE (operands[1]) == MEM
4858 && !memory_address_p (GET_MODE (operands[1]),
4859 XEXP (operands[1], 0)))
4861 rtx temp = copy_to_reg (XEXP (operands[1], 0));
4862 operands[1] = change_address (operands[1], VOIDmode, temp);
4865 /* Handle loading a large integer during reload */
4866 else if (GET_CODE (operands[1]) == CONST_INT
4867 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4869 /* Writing a constant to memory needs a scratch, which should
4870 be handled with SECONDARY_RELOADs. */
4871 if (GET_CODE (operands[0]) != REG)
4874 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4875 emit_insn (gen_movsi (operands[0], operands[1]));
4883 (define_insn "*arm_movqi_insn"
4884 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4885 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4887 && ( register_operand (operands[0], QImode)
4888 || register_operand (operands[1], QImode))"
4894 [(set_attr "type" "*,*,load,store1")
4895 (set_attr "predicable" "yes")]
4898 (define_insn "*thumb_movqi_insn"
4899 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4900 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4902 && ( register_operand (operands[0], QImode)
4903 || register_operand (operands[1], QImode))"
4911 [(set_attr "length" "2")
4912 (set_attr "type" "*,load,store1,*,*,*")
4913 (set_attr "pool_range" "*,32,*,*,*,*")]
4916 (define_expand "movsf"
4917 [(set (match_operand:SF 0 "general_operand" "")
4918 (match_operand:SF 1 "general_operand" ""))]
4923 if (GET_CODE (operands[0]) == MEM)
4924 operands[1] = force_reg (SFmode, operands[1]);
4926 else /* TARGET_THUMB */
4928 if (!no_new_pseudos)
4930 if (GET_CODE (operands[0]) != REG)
4931 operands[1] = force_reg (SFmode, operands[1]);
4938 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4939 (match_operand:SF 1 "immediate_operand" ""))]
4941 && !TARGET_HARD_FLOAT
4943 && GET_CODE (operands[1]) == CONST_DOUBLE"
4944 [(set (match_dup 2) (match_dup 3))]
4946 operands[2] = gen_lowpart (SImode, operands[0]);
4947 operands[3] = gen_lowpart (SImode, operands[1]);
4948 if (operands[2] == 0 || operands[3] == 0)
4953 (define_insn "*arm_movsf_hard_insn"
4954 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4955 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4957 && TARGET_HARD_FLOAT
4958 && (GET_CODE (operands[0]) != MEM
4959 || register_operand (operands[1], SFmode))"
4965 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4966 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4968 ldr%?\\t%0, %1\\t%@ float
4969 str%?\\t%1, %0\\t%@ float"
4970 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4971 (set_attr "predicable" "yes")
4973 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4974 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4975 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4978 ;; Exactly the same as above, except that all `f' cases are deleted.
4979 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4980 ;; when -msoft-float.
4982 (define_insn "*arm_movsf_soft_insn"
4983 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4984 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4986 && TARGET_SOFT_FLOAT
4987 && (GET_CODE (operands[0]) != MEM
4988 || register_operand (operands[1], SFmode))"
4991 ldr%?\\t%0, %1\\t%@ float
4992 str%?\\t%1, %0\\t%@ float"
4993 [(set_attr "length" "4,4,4")
4994 (set_attr "predicable" "yes")
4995 (set_attr "type" "*,load,store1")
4996 (set_attr "pool_range" "*,4096,*")
4997 (set_attr "neg_pool_range" "*,4084,*")]
5000 ;;; ??? This should have alternatives for constants.
5001 (define_insn "*thumb_movsf_insn"
5002 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
5003 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
5005 && ( register_operand (operands[0], SFmode)
5006 || register_operand (operands[1], SFmode))"
5015 [(set_attr "length" "2")
5016 (set_attr "type" "*,load,store1,load,store1,*,*")
5017 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5020 (define_expand "movdf"
5021 [(set (match_operand:DF 0 "general_operand" "")
5022 (match_operand:DF 1 "general_operand" ""))]
5027 if (GET_CODE (operands[0]) == MEM)
5028 operands[1] = force_reg (DFmode, operands[1]);
5030 else /* TARGET_THUMB */
5032 if (!no_new_pseudos)
5034 if (GET_CODE (operands[0]) != REG)
5035 operands[1] = force_reg (DFmode, operands[1]);
5041 ;; Reloading a df mode value stored in integer regs to memory can require a
5043 (define_expand "reload_outdf"
5044 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5045 (match_operand:DF 1 "s_register_operand" "r")
5046 (match_operand:SI 2 "s_register_operand" "=&r")]
5050 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5053 operands[2] = XEXP (operands[0], 0);
5054 else if (code == POST_INC || code == PRE_DEC)
5056 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5057 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5058 emit_insn (gen_movdi (operands[0], operands[1]));
5061 else if (code == PRE_INC)
5063 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5065 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5068 else if (code == POST_DEC)
5069 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5071 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5072 XEXP (XEXP (operands[0], 0), 1)));
5074 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5077 if (code == POST_DEC)
5078 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5084 (define_insn "*movdf_hard_insn"
5085 [(set (match_operand:DF 0 "nonimmediate_operand"
5086 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5087 (match_operand:DF 1 "general_operand"
5088 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5090 && TARGET_HARD_FLOAT
5091 && (GET_CODE (operands[0]) != MEM
5092 || register_operand (operands[1], DFmode))"
5095 switch (which_alternative)
5098 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5099 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5100 case 2: case 3: case 4: return output_move_double (operands);
5101 case 5: return \"mvf%?d\\t%0, %1\";
5102 case 6: return \"mnf%?d\\t%0, #%N1\";
5103 case 7: return \"ldf%?d\\t%0, %1\";
5104 case 8: return \"stf%?d\\t%1, %0\";
5105 case 9: return output_mov_double_fpu_from_arm (operands);
5106 case 10: return output_mov_double_arm_from_fpu (operands);
5110 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5111 (set_attr "predicable" "yes")
5113 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5114 (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")
5115 (set_attr "neg_pool_range" "*,*,*,*,244,*,*,1012,*,*,*")]
5118 ;; Software floating point version. This is essentially the same as movdi.
5119 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5122 (define_insn "*movdf_soft_insn"
5123 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5124 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5125 "TARGET_ARM && TARGET_SOFT_FLOAT
5127 "* return output_move_double (operands);"
5128 [(set_attr "length" "8,8,8")
5129 (set_attr "type" "*,load,store2")
5130 (set_attr "pool_range" "252")
5131 (set_attr "neg_pool_range" "244")]
5134 ;;; ??? This should have alternatives for constants.
5135 ;;; ??? This was originally identical to the movdi_insn pattern.
5136 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5137 ;;; thumb_reorg with a memory reference.
5138 (define_insn "*thumb_movdf_insn"
5139 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5140 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5142 && ( register_operand (operands[0], DFmode)
5143 || register_operand (operands[1], DFmode))"
5145 switch (which_alternative)
5149 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5150 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5151 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5153 return \"ldmia\\t%1, {%0, %H0}\";
5155 return \"stmia\\t%0, {%1, %H1}\";
5157 return thumb_load_double_from_address (operands);
5159 operands[2] = gen_rtx (MEM, SImode,
5160 plus_constant (XEXP (operands[0], 0), 4));
5161 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5164 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5165 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5166 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5169 [(set_attr "length" "4,2,2,6,4,4")
5170 (set_attr "type" "*,load,store2,load,store2,*")
5171 (set_attr "pool_range" "*,*,*,1020,*,*")]
5175 (define_expand "movxf"
5176 [(set (match_operand:XF 0 "general_operand" "")
5177 (match_operand:XF 1 "general_operand" ""))]
5178 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5181 ;; Even when the XFmode patterns aren't enabled, we enable this after
5182 ;; reloading so that we can push floating point registers in the prologue.
5184 (define_insn "*movxf_hard_insn"
5185 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5186 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5187 "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5189 switch (which_alternative)
5192 case 0: return \"mvf%?e\\t%0, %1\";
5193 case 1: return \"mnf%?e\\t%0, #%N1\";
5194 case 2: return \"ldf%?e\\t%0, %1\";
5195 case 3: return \"stf%?e\\t%1, %0\";
5196 case 4: return output_mov_long_double_fpu_from_arm (operands);
5197 case 5: return output_mov_long_double_arm_from_fpu (operands);
5198 case 6: return output_mov_long_double_arm_from_arm (operands);
5201 [(set_attr "length" "4,4,4,4,8,8,12")
5202 (set_attr "predicable" "yes")
5203 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5204 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5205 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*")]
5209 ;; load- and store-multiple insns
5210 ;; The arm can load/store any set of registers, provided that they are in
5211 ;; ascending order; but that is beyond GCC so stick with what it knows.
5213 (define_expand "load_multiple"
5214 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5215 (match_operand:SI 1 "" ""))
5216 (use (match_operand:SI 2 "" ""))])]
5219 /* Support only fixed point registers. */
5220 if (GET_CODE (operands[2]) != CONST_INT
5221 || INTVAL (operands[2]) > 14
5222 || INTVAL (operands[2]) < 2
5223 || GET_CODE (operands[1]) != MEM
5224 || GET_CODE (operands[0]) != REG
5225 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5226 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5230 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5231 force_reg (SImode, XEXP (operands[1], 0)),
5232 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5233 MEM_IN_STRUCT_P(operands[1]),
5234 MEM_SCALAR_P (operands[1]));
5238 ;; Load multiple with write-back
5240 (define_insn "*ldmsi_postinc4"
5241 [(match_parallel 0 "load_multiple_operation"
5242 [(set (match_operand:SI 1 "s_register_operand" "=r")
5243 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5245 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5246 (mem:SI (match_dup 2)))
5247 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5248 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5249 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5250 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5251 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5252 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5253 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5254 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5255 [(set_attr "type" "load")
5256 (set_attr "predicable" "yes")]
5259 (define_insn "*ldmsi_postinc3"
5260 [(match_parallel 0 "load_multiple_operation"
5261 [(set (match_operand:SI 1 "s_register_operand" "=r")
5262 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5264 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5265 (mem:SI (match_dup 2)))
5266 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5267 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5268 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5269 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5270 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5271 "ldm%?ia\\t%1!, {%3, %4, %5}"
5272 [(set_attr "type" "load")
5273 (set_attr "predicable" "yes")]
5276 (define_insn "*ldmsi_postinc2"
5277 [(match_parallel 0 "load_multiple_operation"
5278 [(set (match_operand:SI 1 "s_register_operand" "=r")
5279 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5281 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5282 (mem:SI (match_dup 2)))
5283 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5284 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5285 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5286 "ldm%?ia\\t%1!, {%3, %4}"
5287 [(set_attr "type" "load")
5288 (set_attr "predicable" "yes")]
5291 ;; Ordinary load multiple
5293 (define_insn "*ldmsi4"
5294 [(match_parallel 0 "load_multiple_operation"
5295 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5296 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5297 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5298 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5299 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5300 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5301 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5302 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5303 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5304 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5305 [(set_attr "type" "load")
5306 (set_attr "predicable" "yes")]
5309 (define_insn "*ldmsi3"
5310 [(match_parallel 0 "load_multiple_operation"
5311 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5312 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5313 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5314 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5315 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5316 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5317 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5318 "ldm%?ia\\t%1, {%2, %3, %4}"
5319 [(set_attr "type" "load")
5320 (set_attr "predicable" "yes")]
5323 (define_insn "*ldmsi2"
5324 [(match_parallel 0 "load_multiple_operation"
5325 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5326 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5327 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5328 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5329 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5330 "ldm%?ia\\t%1, {%2, %3}"
5331 [(set_attr "type" "load")
5332 (set_attr "predicable" "yes")]
5335 (define_expand "store_multiple"
5336 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5337 (match_operand:SI 1 "" ""))
5338 (use (match_operand:SI 2 "" ""))])]
5341 /* Support only fixed point registers */
5342 if (GET_CODE (operands[2]) != CONST_INT
5343 || INTVAL (operands[2]) > 14
5344 || INTVAL (operands[2]) < 2
5345 || GET_CODE (operands[1]) != REG
5346 || GET_CODE (operands[0]) != MEM
5347 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5348 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5352 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5353 force_reg (SImode, XEXP (operands[0], 0)),
5354 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5355 MEM_IN_STRUCT_P(operands[0]),
5356 MEM_SCALAR_P (operands[0]));
5360 ;; Store multiple with write-back
5362 (define_insn "*stmsi_postinc4"
5363 [(match_parallel 0 "store_multiple_operation"
5364 [(set (match_operand:SI 1 "s_register_operand" "=r")
5365 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5367 (set (mem:SI (match_dup 2))
5368 (match_operand:SI 3 "arm_hard_register_operand" ""))
5369 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5370 (match_operand:SI 4 "arm_hard_register_operand" ""))
5371 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5372 (match_operand:SI 5 "arm_hard_register_operand" ""))
5373 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5374 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5375 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5376 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5377 [(set_attr "predicable" "yes")
5378 (set_attr "type" "store4")]
5381 (define_insn "*stmsi_postinc3"
5382 [(match_parallel 0 "store_multiple_operation"
5383 [(set (match_operand:SI 1 "s_register_operand" "=r")
5384 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5386 (set (mem:SI (match_dup 2))
5387 (match_operand:SI 3 "arm_hard_register_operand" ""))
5388 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5389 (match_operand:SI 4 "arm_hard_register_operand" ""))
5390 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5391 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5392 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5393 "stm%?ia\\t%1!, {%3, %4, %5}"
5394 [(set_attr "predicable" "yes")
5395 (set_attr "type" "store3")]
5398 (define_insn "*stmsi_postinc2"
5399 [(match_parallel 0 "store_multiple_operation"
5400 [(set (match_operand:SI 1 "s_register_operand" "=r")
5401 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5403 (set (mem:SI (match_dup 2))
5404 (match_operand:SI 3 "arm_hard_register_operand" ""))
5405 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5406 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5407 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5408 "stm%?ia\\t%1!, {%3, %4}"
5409 [(set_attr "predicable" "yes")
5410 (set_attr "type" "store2")]
5413 ;; Ordinary store multiple
5415 (define_insn "*stmsi4"
5416 [(match_parallel 0 "store_multiple_operation"
5417 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5418 (match_operand:SI 2 "arm_hard_register_operand" ""))
5419 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5420 (match_operand:SI 3 "arm_hard_register_operand" ""))
5421 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5422 (match_operand:SI 4 "arm_hard_register_operand" ""))
5423 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5424 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5425 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5426 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5427 [(set_attr "predicable" "yes")
5428 (set_attr "type" "store4")]
5431 (define_insn "*stmsi3"
5432 [(match_parallel 0 "store_multiple_operation"
5433 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5434 (match_operand:SI 2 "arm_hard_register_operand" ""))
5435 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5436 (match_operand:SI 3 "arm_hard_register_operand" ""))
5437 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5438 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5439 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5440 "stm%?ia\\t%1, {%2, %3, %4}"
5441 [(set_attr "predicable" "yes")
5442 (set_attr "type" "store3")]
5445 (define_insn "*stmsi2"
5446 [(match_parallel 0 "store_multiple_operation"
5447 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5448 (match_operand:SI 2 "arm_hard_register_operand" ""))
5449 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5450 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5451 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5452 "stm%?ia\\t%1, {%2, %3}"
5453 [(set_attr "predicable" "yes")
5454 (set_attr "type" "store2")]
5457 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5458 ;; We could let this apply for blocks of less than this, but it clobbers so
5459 ;; many registers that there is then probably a better way.
5461 (define_expand "movstrqi"
5462 [(match_operand:BLK 0 "general_operand" "")
5463 (match_operand:BLK 1 "general_operand" "")
5464 (match_operand:SI 2 "const_int_operand" "")
5465 (match_operand:SI 3 "const_int_operand" "")]
5470 if (arm_gen_movstrqi (operands))
5474 else /* TARGET_THUMB */
5476 if ( INTVAL (operands[3]) != 4
5477 || INTVAL (operands[2]) > 48)
5480 thumb_expand_movstrqi (operands);
5486 ;; Thumb block-move insns
5488 (define_insn "movmem12b"
5489 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5490 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5491 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5492 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5493 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5494 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5495 (set (match_operand:SI 0 "register_operand" "=l")
5496 (plus:SI (match_dup 2) (const_int 12)))
5497 (set (match_operand:SI 1 "register_operand" "=l")
5498 (plus:SI (match_dup 3) (const_int 12)))
5499 (clobber (match_scratch:SI 4 "=&l"))
5500 (clobber (match_scratch:SI 5 "=&l"))
5501 (clobber (match_scratch:SI 6 "=&l"))]
5503 "* return thumb_output_move_mem_multiple (3, operands);"
5504 [(set_attr "length" "4")
5505 ; This isn't entirely accurate... It loads as well, but in terms of
5506 ; scheduling the following insn it is better to consider it as a store
5507 (set_attr "type" "store3")]
5510 (define_insn "movmem8b"
5511 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5512 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5513 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5514 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5515 (set (match_operand:SI 0 "register_operand" "=l")
5516 (plus:SI (match_dup 2) (const_int 8)))
5517 (set (match_operand:SI 1 "register_operand" "=l")
5518 (plus:SI (match_dup 3) (const_int 8)))
5519 (clobber (match_scratch:SI 4 "=&l"))
5520 (clobber (match_scratch:SI 5 "=&l"))]
5522 "* return thumb_output_move_mem_multiple (2, operands);"
5523 [(set_attr "length" "4")
5524 ; This isn't entirely accurate... It loads as well, but in terms of
5525 ; scheduling the following insn it is better to consider it as a store
5526 (set_attr "type" "store2")]
5531 ;; Compare & branch insns
5532 ;; The range calcualations are based as follows:
5533 ;; For forward branches, the address calculation returns the address of
5534 ;; the next instruction. This is 2 beyond the branch instruction.
5535 ;; For backward branches, the address calculation returns the address of
5536 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5537 ;; instruction for the shortest sequence, and 4 before the branch instruction
5538 ;; if we have to jump around an unconditional branch.
5539 ;; To the basic branch range the PC offset must be added (this is +4).
5540 ;; So for forward branches we have
5541 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5542 ;; And for backward branches we have
5543 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5545 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5546 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5548 (define_insn "cbranchsi4"
5551 (match_operator 0 "arm_comparison_operator"
5552 [(match_operand:SI 1 "register_operand" "l,r")
5553 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5554 (label_ref (match_operand 3 "" ""))
5558 output_asm_insn (\"cmp\\t%1, %2\", operands);
5559 switch (get_attr_length (insn))
5561 case 4: return \"b%d0\\t%l3\";
5562 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5563 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5566 [(set (attr "far_jump")
5568 (eq_attr "length" "8")
5569 (const_string "yes")
5570 (const_string "no")))
5571 (set (attr "length")
5573 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5574 (le (minus (match_dup 3) (pc)) (const_int 256)))
5577 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5578 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5583 (define_insn "*negated_cbranchsi4"
5586 (match_operator 0 "arm_comparison_operator"
5587 [(match_operand:SI 1 "register_operand" "l")
5588 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5589 (label_ref (match_operand 3 "" ""))
5593 output_asm_insn (\"cmn\\t%1, %2\", operands);
5594 switch (get_attr_length (insn))
5596 case 4: return \"b%d0\\t%l3\";
5597 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5598 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5601 [(set (attr "far_jump")
5603 (eq_attr "length" "8")
5604 (const_string "yes")
5605 (const_string "no")))
5606 (set (attr "length")
5608 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5609 (le (minus (match_dup 3) (pc)) (const_int 256)))
5612 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5613 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5619 ;; Comparison and test insns
5621 (define_expand "cmpsi"
5622 [(match_operand:SI 0 "s_register_operand" "")
5623 (match_operand:SI 1 "arm_add_operand" "")]
5626 arm_compare_op0 = operands[0];
5627 arm_compare_op1 = operands[1];
5632 (define_expand "cmpsf"
5633 [(match_operand:SF 0 "s_register_operand" "")
5634 (match_operand:SF 1 "fpu_rhs_operand" "")]
5635 "TARGET_ARM && TARGET_HARD_FLOAT"
5637 arm_compare_op0 = operands[0];
5638 arm_compare_op1 = operands[1];
5643 (define_expand "cmpdf"
5644 [(match_operand:DF 0 "s_register_operand" "")
5645 (match_operand:DF 1 "fpu_rhs_operand" "")]
5646 "TARGET_ARM && TARGET_HARD_FLOAT"
5648 arm_compare_op0 = operands[0];
5649 arm_compare_op1 = operands[1];
5654 (define_expand "cmpxf"
5655 [(match_operand:XF 0 "s_register_operand" "")
5656 (match_operand:XF 1 "fpu_rhs_operand" "")]
5657 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5659 arm_compare_op0 = operands[0];
5660 arm_compare_op1 = operands[1];
5665 (define_insn "*arm_cmpsi_insn"
5666 [(set (reg:CC CC_REGNUM)
5667 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5668 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5673 [(set_attr "conds" "set")]
5676 (define_insn "*cmpsi_shiftsi"
5677 [(set (reg:CC CC_REGNUM)
5678 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5679 (match_operator:SI 3 "shift_operator"
5680 [(match_operand:SI 1 "s_register_operand" "r")
5681 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5684 [(set_attr "conds" "set")
5685 (set_attr "shift" "1")
5689 (define_insn "*cmpsi_shiftsi_swp"
5690 [(set (reg:CC_SWP CC_REGNUM)
5691 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5692 [(match_operand:SI 1 "s_register_operand" "r")
5693 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5694 (match_operand:SI 0 "s_register_operand" "r")))]
5697 [(set_attr "conds" "set")
5698 (set_attr "shift" "1")
5702 (define_insn "*cmpsi_neg_shiftsi"
5703 [(set (reg:CC CC_REGNUM)
5704 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5705 (neg:SI (match_operator:SI 3 "shift_operator"
5706 [(match_operand:SI 1 "s_register_operand" "r")
5707 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5710 [(set_attr "conds" "set")
5711 (set_attr "shift" "1")
5715 (define_insn "*cmpsf_insn"
5716 [(set (reg:CCFP CC_REGNUM)
5717 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5718 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5719 "TARGET_ARM && TARGET_HARD_FLOAT"
5723 [(set_attr "conds" "set")
5724 (set_attr "type" "f_2_r")]
5727 (define_insn "*cmpdf_insn"
5728 [(set (reg:CCFP CC_REGNUM)
5729 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5730 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5731 "TARGET_ARM && TARGET_HARD_FLOAT"
5735 [(set_attr "conds" "set")
5736 (set_attr "type" "f_2_r")]
5739 (define_insn "*cmpesfdf_df"
5740 [(set (reg:CCFP CC_REGNUM)
5741 (compare:CCFP (float_extend:DF
5742 (match_operand:SF 0 "s_register_operand" "f,f"))
5743 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5744 "TARGET_ARM && TARGET_HARD_FLOAT"
5748 [(set_attr "conds" "set")
5749 (set_attr "type" "f_2_r")]
5752 (define_insn "*cmpdf_esfdf"
5753 [(set (reg:CCFP CC_REGNUM)
5754 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5756 (match_operand:SF 1 "s_register_operand" "f"))))]
5757 "TARGET_ARM && TARGET_HARD_FLOAT"
5759 [(set_attr "conds" "set")
5760 (set_attr "type" "f_2_r")]
5763 (define_insn "*cmpxf_insn"
5764 [(set (reg:CCFP CC_REGNUM)
5765 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5766 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5767 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5771 [(set_attr "conds" "set")
5772 (set_attr "type" "f_2_r")]
5775 (define_insn "*cmpsf_trap"
5776 [(set (reg:CCFPE CC_REGNUM)
5777 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5778 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5779 "TARGET_ARM && TARGET_HARD_FLOAT"
5783 [(set_attr "conds" "set")
5784 (set_attr "type" "f_2_r")]
5787 (define_insn "*cmpdf_trap"
5788 [(set (reg:CCFPE CC_REGNUM)
5789 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5790 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5791 "TARGET_ARM && TARGET_HARD_FLOAT"
5795 [(set_attr "conds" "set")
5796 (set_attr "type" "f_2_r")]
5799 (define_insn "*cmp_esfdf_df_trap"
5800 [(set (reg:CCFPE CC_REGNUM)
5801 (compare:CCFPE (float_extend:DF
5802 (match_operand:SF 0 "s_register_operand" "f,f"))
5803 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5804 "TARGET_ARM && TARGET_HARD_FLOAT"
5808 [(set_attr "conds" "set")
5809 (set_attr "type" "f_2_r")]
5812 (define_insn "*cmp_df_esfdf_trap"
5813 [(set (reg:CCFPE CC_REGNUM)
5814 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5816 (match_operand:SF 1 "s_register_operand" "f"))))]
5817 "TARGET_ARM && TARGET_HARD_FLOAT"
5819 [(set_attr "conds" "set")
5820 (set_attr "type" "f_2_r")]
5823 (define_insn "*cmpxf_trap"
5824 [(set (reg:CCFPE CC_REGNUM)
5825 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5826 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5827 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5831 [(set_attr "conds" "set")
5832 (set_attr "type" "f_2_r")]
5835 ; This insn allows redundant compares to be removed by cse, nothing should
5836 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5837 ; is deleted later on. The match_dup will match the mode here, so that
5838 ; mode changes of the condition codes aren't lost by this even though we don't
5839 ; specify what they are.
5841 (define_insn "*deleted_compare"
5842 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5844 "\\t%@ deleted compare"
5845 [(set_attr "conds" "set")
5846 (set_attr "length" "0")]
5850 ;; Conditional branch insns
5852 (define_expand "beq"
5854 (if_then_else (eq (match_dup 1) (const_int 0))
5855 (label_ref (match_operand 0 "" ""))
5858 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5861 (define_expand "bne"
5863 (if_then_else (ne (match_dup 1) (const_int 0))
5864 (label_ref (match_operand 0 "" ""))
5867 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5870 (define_expand "bgt"
5872 (if_then_else (gt (match_dup 1) (const_int 0))
5873 (label_ref (match_operand 0 "" ""))
5876 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5879 (define_expand "ble"
5881 (if_then_else (le (match_dup 1) (const_int 0))
5882 (label_ref (match_operand 0 "" ""))
5885 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5888 (define_expand "bge"
5890 (if_then_else (ge (match_dup 1) (const_int 0))
5891 (label_ref (match_operand 0 "" ""))
5894 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5897 (define_expand "blt"
5899 (if_then_else (lt (match_dup 1) (const_int 0))
5900 (label_ref (match_operand 0 "" ""))
5903 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5906 (define_expand "bgtu"
5908 (if_then_else (gtu (match_dup 1) (const_int 0))
5909 (label_ref (match_operand 0 "" ""))
5912 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5915 (define_expand "bleu"
5917 (if_then_else (leu (match_dup 1) (const_int 0))
5918 (label_ref (match_operand 0 "" ""))
5921 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5924 (define_expand "bgeu"
5926 (if_then_else (geu (match_dup 1) (const_int 0))
5927 (label_ref (match_operand 0 "" ""))
5930 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5933 (define_expand "bltu"
5935 (if_then_else (ltu (match_dup 1) (const_int 0))
5936 (label_ref (match_operand 0 "" ""))
5939 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5942 (define_expand "bunordered"
5944 (if_then_else (unordered (match_dup 1) (const_int 0))
5945 (label_ref (match_operand 0 "" ""))
5947 "TARGET_ARM && TARGET_HARD_FLOAT"
5948 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5952 (define_expand "bordered"
5954 (if_then_else (ordered (match_dup 1) (const_int 0))
5955 (label_ref (match_operand 0 "" ""))
5957 "TARGET_ARM && TARGET_HARD_FLOAT"
5958 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5962 (define_expand "bungt"
5964 (if_then_else (ungt (match_dup 1) (const_int 0))
5965 (label_ref (match_operand 0 "" ""))
5967 "TARGET_ARM && TARGET_HARD_FLOAT"
5968 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5971 (define_expand "bunlt"
5973 (if_then_else (unlt (match_dup 1) (const_int 0))
5974 (label_ref (match_operand 0 "" ""))
5976 "TARGET_ARM && TARGET_HARD_FLOAT"
5977 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5980 (define_expand "bunge"
5982 (if_then_else (unge (match_dup 1) (const_int 0))
5983 (label_ref (match_operand 0 "" ""))
5985 "TARGET_ARM && TARGET_HARD_FLOAT"
5986 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5989 (define_expand "bunle"
5991 (if_then_else (unle (match_dup 1) (const_int 0))
5992 (label_ref (match_operand 0 "" ""))
5994 "TARGET_ARM && TARGET_HARD_FLOAT"
5995 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5998 ;; The following two patterns need two branch instructions, since there is
5999 ;; no single instruction that will handle all cases.
6000 (define_expand "buneq"
6002 (if_then_else (uneq (match_dup 1) (const_int 0))
6003 (label_ref (match_operand 0 "" ""))
6005 "TARGET_ARM && TARGET_HARD_FLOAT"
6006 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6009 (define_expand "bltgt"
6011 (if_then_else (ltgt (match_dup 1) (const_int 0))
6012 (label_ref (match_operand 0 "" ""))
6014 "TARGET_ARM && TARGET_HARD_FLOAT"
6015 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6019 ;; Patterns to match conditional branch insns.
6022 ; Special pattern to match UNEQ.
6023 (define_insn "*arm_buneq"
6025 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6026 (label_ref (match_operand 0 "" ""))
6028 "TARGET_ARM && TARGET_HARD_FLOAT"
6030 if (arm_ccfsm_state != 0)
6033 return \"bvs\\t%l0;beq\\t%l0\";
6035 [(set_attr "conds" "jump_clob")
6036 (set_attr "length" "8")]
6039 ; Special pattern to match LTGT.
6040 (define_insn "*arm_bltgt"
6042 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6043 (label_ref (match_operand 0 "" ""))
6045 "TARGET_ARM && TARGET_HARD_FLOAT"
6047 if (arm_ccfsm_state != 0)
6050 return \"bmi\\t%l0;bgt\\t%l0\";
6052 [(set_attr "conds" "jump_clob")
6053 (set_attr "length" "8")]
6056 (define_insn "*arm_cond_branch"
6058 (if_then_else (match_operator 1 "arm_comparison_operator"
6059 [(match_operand 2 "cc_register" "") (const_int 0)])
6060 (label_ref (match_operand 0 "" ""))
6064 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6066 arm_ccfsm_state += 2;
6069 return \"b%d1\\t%l0\";
6071 [(set_attr "conds" "use")]
6074 ; Special pattern to match reversed UNEQ.
6075 (define_insn "*arm_buneq_reversed"
6077 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6079 (label_ref (match_operand 0 "" ""))))]
6080 "TARGET_ARM && TARGET_HARD_FLOAT"
6082 if (arm_ccfsm_state != 0)
6085 return \"bmi\\t%l0;bgt\\t%l0\";
6087 [(set_attr "conds" "jump_clob")
6088 (set_attr "length" "8")]
6091 ; Special pattern to match reversed LTGT.
6092 (define_insn "*arm_bltgt_reversed"
6094 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6096 (label_ref (match_operand 0 "" ""))))]
6097 "TARGET_ARM && TARGET_HARD_FLOAT"
6099 if (arm_ccfsm_state != 0)
6102 return \"bvs\\t%l0;beq\\t%l0\";
6104 [(set_attr "conds" "jump_clob")
6105 (set_attr "length" "8")]
6108 (define_insn "*arm_cond_branch_reversed"
6110 (if_then_else (match_operator 1 "arm_comparison_operator"
6111 [(match_operand 2 "cc_register" "") (const_int 0)])
6113 (label_ref (match_operand 0 "" ""))))]
6116 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6118 arm_ccfsm_state += 2;
6121 return \"b%D1\\t%l0\";
6123 [(set_attr "conds" "use")]
6130 (define_expand "seq"
6131 [(set (match_operand:SI 0 "s_register_operand" "=r")
6132 (eq:SI (match_dup 1) (const_int 0)))]
6134 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6137 (define_expand "sne"
6138 [(set (match_operand:SI 0 "s_register_operand" "=r")
6139 (ne:SI (match_dup 1) (const_int 0)))]
6141 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6144 (define_expand "sgt"
6145 [(set (match_operand:SI 0 "s_register_operand" "=r")
6146 (gt:SI (match_dup 1) (const_int 0)))]
6148 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6151 (define_expand "sle"
6152 [(set (match_operand:SI 0 "s_register_operand" "=r")
6153 (le:SI (match_dup 1) (const_int 0)))]
6155 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6158 (define_expand "sge"
6159 [(set (match_operand:SI 0 "s_register_operand" "=r")
6160 (ge:SI (match_dup 1) (const_int 0)))]
6162 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6165 (define_expand "slt"
6166 [(set (match_operand:SI 0 "s_register_operand" "=r")
6167 (lt:SI (match_dup 1) (const_int 0)))]
6169 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6172 (define_expand "sgtu"
6173 [(set (match_operand:SI 0 "s_register_operand" "=r")
6174 (gtu:SI (match_dup 1) (const_int 0)))]
6176 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6179 (define_expand "sleu"
6180 [(set (match_operand:SI 0 "s_register_operand" "=r")
6181 (leu:SI (match_dup 1) (const_int 0)))]
6183 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6186 (define_expand "sgeu"
6187 [(set (match_operand:SI 0 "s_register_operand" "=r")
6188 (geu:SI (match_dup 1) (const_int 0)))]
6190 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6193 (define_expand "sltu"
6194 [(set (match_operand:SI 0 "s_register_operand" "=r")
6195 (ltu:SI (match_dup 1) (const_int 0)))]
6197 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6200 (define_expand "sunordered"
6201 [(set (match_operand:SI 0 "s_register_operand" "=r")
6202 (unordered:SI (match_dup 1) (const_int 0)))]
6203 "TARGET_ARM && TARGET_HARD_FLOAT"
6204 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6208 (define_expand "sordered"
6209 [(set (match_operand:SI 0 "s_register_operand" "=r")
6210 (ordered:SI (match_dup 1) (const_int 0)))]
6211 "TARGET_ARM && TARGET_HARD_FLOAT"
6212 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6216 (define_expand "sungt"
6217 [(set (match_operand:SI 0 "s_register_operand" "=r")
6218 (ungt:SI (match_dup 1) (const_int 0)))]
6219 "TARGET_ARM && TARGET_HARD_FLOAT"
6220 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6224 (define_expand "sunge"
6225 [(set (match_operand:SI 0 "s_register_operand" "=r")
6226 (unge:SI (match_dup 1) (const_int 0)))]
6227 "TARGET_ARM && TARGET_HARD_FLOAT"
6228 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6232 (define_expand "sunlt"
6233 [(set (match_operand:SI 0 "s_register_operand" "=r")
6234 (unlt:SI (match_dup 1) (const_int 0)))]
6235 "TARGET_ARM && TARGET_HARD_FLOAT"
6236 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6240 (define_expand "sunle"
6241 [(set (match_operand:SI 0 "s_register_operand" "=r")
6242 (unle:SI (match_dup 1) (const_int 0)))]
6243 "TARGET_ARM && TARGET_HARD_FLOAT"
6244 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6248 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6249 ;;; simple ARM instructions.
6251 ; (define_expand "suneq"
6252 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6253 ; (uneq:SI (match_dup 1) (const_int 0)))]
6254 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6258 ; (define_expand "sltgt"
6259 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6260 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6261 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6265 (define_insn "*mov_scc"
6266 [(set (match_operand:SI 0 "s_register_operand" "=r")
6267 (match_operator:SI 1 "arm_comparison_operator"
6268 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6270 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6271 [(set_attr "conds" "use")
6272 (set_attr "length" "8")]
6275 (define_insn "*mov_negscc"
6276 [(set (match_operand:SI 0 "s_register_operand" "=r")
6277 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6278 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6280 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6281 [(set_attr "conds" "use")
6282 (set_attr "length" "8")]
6285 (define_insn "*mov_notscc"
6286 [(set (match_operand:SI 0 "s_register_operand" "=r")
6287 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6288 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6290 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6291 [(set_attr "conds" "use")
6292 (set_attr "length" "8")]
6296 ;; Conditional move insns
6298 (define_expand "movsicc"
6299 [(set (match_operand:SI 0 "s_register_operand" "")
6300 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6301 (match_operand:SI 2 "arm_not_operand" "")
6302 (match_operand:SI 3 "arm_not_operand" "")))]
6306 enum rtx_code code = GET_CODE (operands[1]);
6307 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6309 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6313 (define_expand "movsfcc"
6314 [(set (match_operand:SF 0 "s_register_operand" "")
6315 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6316 (match_operand:SF 2 "s_register_operand" "")
6317 (match_operand:SF 3 "nonmemory_operand" "")))]
6321 enum rtx_code code = GET_CODE (operands[1]);
6324 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6325 Otherwise, ensure it is a valid FP add operand */
6326 if ((!TARGET_HARD_FLOAT)
6327 || (!fpu_add_operand (operands[3], SFmode)))
6328 operands[3] = force_reg (SFmode, operands[3]);
6330 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6331 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6335 (define_expand "movdfcc"
6336 [(set (match_operand:DF 0 "s_register_operand" "")
6337 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6338 (match_operand:DF 2 "s_register_operand" "")
6339 (match_operand:DF 3 "fpu_add_operand" "")))]
6340 "TARGET_ARM && TARGET_HARD_FLOAT"
6343 enum rtx_code code = GET_CODE (operands[1]);
6344 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6346 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6350 (define_insn "*movsicc_insn"
6351 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6353 (match_operator 3 "arm_comparison_operator"
6354 [(match_operand 4 "cc_register" "") (const_int 0)])
6355 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6356 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6363 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6364 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6365 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6366 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6367 [(set_attr "length" "4,4,4,4,8,8,8,8")
6368 (set_attr "conds" "use")]
6371 (define_insn "*movsfcc_hard_insn"
6372 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6374 (match_operator 3 "arm_comparison_operator"
6375 [(match_operand 4 "cc_register" "") (const_int 0)])
6376 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6377 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6378 "TARGET_ARM && TARGET_HARD_FLOAT"
6384 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6385 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6386 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6387 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6388 [(set_attr "length" "4,4,4,4,8,8,8,8")
6389 (set_attr "type" "ffarith")
6390 (set_attr "conds" "use")]
6393 (define_insn "*movsfcc_soft_insn"
6394 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6395 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6396 [(match_operand 4 "cc_register" "") (const_int 0)])
6397 (match_operand:SF 1 "s_register_operand" "0,r")
6398 (match_operand:SF 2 "s_register_operand" "r,0")))]
6399 "TARGET_ARM && TARGET_SOFT_FLOAT"
6403 [(set_attr "conds" "use")]
6406 (define_insn "*movdfcc_insn"
6407 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6409 (match_operator 3 "arm_comparison_operator"
6410 [(match_operand 4 "cc_register" "") (const_int 0)])
6411 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6412 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6413 "TARGET_ARM && TARGET_HARD_FLOAT"
6419 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6420 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6421 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6422 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6423 [(set_attr "length" "4,4,4,4,8,8,8,8")
6424 (set_attr "type" "ffarith")
6425 (set_attr "conds" "use")]
6429 ;; Jump and linkage insns
6431 (define_expand "jump"
6433 (label_ref (match_operand 0 "" "")))]
6438 (define_insn "*arm_jump"
6440 (label_ref (match_operand 0 "" "")))]
6444 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6446 arm_ccfsm_state += 2;
6449 return \"b%?\\t%l0\";
6452 [(set_attr "predicable" "yes")]
6455 (define_insn "*thumb_jump"
6457 (label_ref (match_operand 0 "" "")))]
6460 if (get_attr_length (insn) == 2)
6462 return \"bl\\t%l0\\t%@ far jump\";
6464 [(set (attr "far_jump")
6466 (eq_attr "length" "4")
6467 (const_string "yes")
6468 (const_string "no")))
6469 (set (attr "length")
6471 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6472 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6477 (define_expand "call"
6478 [(parallel [(call (match_operand 0 "memory_operand" "")
6479 (match_operand 1 "general_operand" ""))
6480 (use (match_operand 2 "" ""))
6481 (clobber (reg:SI LR_REGNUM))])]
6487 /* In an untyped call, we can get NULL for operand 2. */
6488 if (operands[2] == NULL_RTX)
6489 operands[2] = const0_rtx;
6491 /* This is to decide if we should generate indirect calls by loading the
6492 32 bit address of the callee into a register before performing the
6493 branch and link. operand[2] encodes the long_call/short_call
6494 attribute of the function being called. This attribute is set whenever
6495 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6496 is used, and the short_call attribute can also be set if function is
6497 declared as static or if it has already been defined in the current
6498 compilation unit. See arm.c and arm.h for info about this. The third
6499 parameter to arm_is_longcall_p is used to tell it which pattern
6501 callee = XEXP (operands[0], 0);
6503 if (GET_CODE (callee) != REG
6504 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6505 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6509 (define_insn "*call_reg"
6510 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6511 (match_operand 1 "" ""))
6512 (use (match_operand 2 "" ""))
6513 (clobber (reg:SI LR_REGNUM))]
6516 return output_call (operands);
6518 ;; length is worst case, normally it is only two
6519 [(set_attr "length" "12")
6520 (set_attr "type" "call")]
6523 (define_insn "*call_mem"
6524 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6525 (match_operand 1 "" ""))
6526 (use (match_operand 2 "" ""))
6527 (clobber (reg:SI LR_REGNUM))]
6530 return output_call_mem (operands);
6532 [(set_attr "length" "12")
6533 (set_attr "type" "call")]
6536 (define_insn "*call_indirect"
6537 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6538 (match_operand 1 "" ""))
6539 (use (match_operand 2 "" ""))
6540 (clobber (reg:SI LR_REGNUM))]
6544 if (TARGET_CALLER_INTERWORKING)
6545 return \"bl\\t%__interwork_call_via_%0\";
6547 return \"bl\\t%__call_via_%0\";
6549 [(set_attr "type" "call")]
6552 (define_insn "*call_value_indirect"
6553 [(set (match_operand 0 "" "=l")
6554 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6555 (match_operand 2 "" "")))
6556 (use (match_operand 3 "" ""))
6557 (clobber (reg:SI LR_REGNUM))]
6561 if (TARGET_CALLER_INTERWORKING)
6562 return \"bl\\t%__interwork_call_via_%1\";
6564 return \"bl\\t%__call_via_%1\";
6566 [(set_attr "type" "call")]
6569 (define_expand "call_value"
6570 [(parallel [(set (match_operand 0 "" "")
6571 (call (match_operand 1 "memory_operand" "")
6572 (match_operand 2 "general_operand" "")))
6573 (use (match_operand 3 "" ""))
6574 (clobber (reg:SI LR_REGNUM))])]
6578 rtx callee = XEXP (operands[1], 0);
6580 /* In an untyped call, we can get NULL for operand 2. */
6581 if (operands[3] == 0)
6582 operands[3] = const0_rtx;
6584 /* See the comment in define_expand \"call\". */
6585 if (GET_CODE (callee) != REG
6586 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6587 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6591 (define_insn "*call_value_reg"
6592 [(set (match_operand 0 "" "=r,f")
6593 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6594 (match_operand 2 "" "")))
6595 (use (match_operand 3 "" ""))
6596 (clobber (reg:SI LR_REGNUM))]
6599 return output_call (&operands[1]);
6601 [(set_attr "length" "12")
6602 (set_attr "type" "call")]
6605 (define_insn "*call_value_mem"
6606 [(set (match_operand 0 "" "=r,f")
6607 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6608 (match_operand 2 "" "")))
6609 (use (match_operand 3 "" ""))
6610 (clobber (reg:SI LR_REGNUM))]
6611 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6613 return output_call_mem (&operands[1]);
6615 [(set_attr "length" "12")
6616 (set_attr "type" "call")]
6619 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6620 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6622 (define_insn "*call_symbol"
6623 [(call (mem:SI (match_operand:SI 0 "" "X"))
6624 (match_operand 1 "" ""))
6625 (use (match_operand 2 "" ""))
6626 (clobber (reg:SI LR_REGNUM))]
6628 && (GET_CODE (operands[0]) == SYMBOL_REF)
6629 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6632 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6634 [(set_attr "type" "call")]
6637 (define_insn "*call_value_symbol"
6638 [(set (match_operand 0 "s_register_operand" "=r,f")
6639 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6640 (match_operand:SI 2 "" "")))
6641 (use (match_operand 3 "" ""))
6642 (clobber (reg:SI LR_REGNUM))]
6644 && (GET_CODE (operands[1]) == SYMBOL_REF)
6645 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6648 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6650 [(set_attr "type" "call")]
6653 (define_insn "*call_insn"
6654 [(call (mem:SI (match_operand:SI 0 "" "X"))
6655 (match_operand:SI 1 "" ""))
6656 (use (match_operand 2 "" ""))
6657 (clobber (reg:SI LR_REGNUM))]
6659 && operands[2] == const0_rtx && (GET_CODE (operands[0]) == SYMBOL_REF)"
6661 [(set_attr "length" "4")
6662 (set_attr "type" "call")]
6665 (define_insn "*call_value_insn"
6666 [(set (match_operand 0 "register_operand" "=l")
6667 (call (mem:SI (match_operand 1 "" "X"))
6668 (match_operand 2 "" "")))
6669 (use (match_operand 3 "" ""))
6670 (clobber (reg:SI LR_REGNUM))]
6672 && operands[3] == const0_rtx && (GET_CODE (operands[1]) == SYMBOL_REF)"
6674 [(set_attr "length" "4")
6675 (set_attr "type" "call")]
6678 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6679 (define_expand "sibcall"
6680 [(parallel [(call (match_operand 0 "memory_operand" "")
6681 (match_operand 1 "general_operand" ""))
6682 (use (match_operand 2 "" ""))
6683 (use (reg:SI LR_REGNUM))])]
6687 if (operands[2] == NULL_RTX)
6688 operands[2] = const0_rtx;
6692 (define_expand "sibcall_value"
6693 [(parallel [(set (match_operand 0 "register_operand" "")
6694 (call (match_operand 1 "memory_operand" "")
6695 (match_operand 2 "general_operand" "")))
6696 (use (match_operand 3 "" ""))
6697 (use (reg:SI LR_REGNUM))])]
6701 if (operands[3] == NULL_RTX)
6702 operands[3] = const0_rtx;
6706 (define_insn "*sibcall_insn"
6707 [(call (mem:SI (match_operand:SI 0 "" "X"))
6708 (match_operand 1 "" ""))
6709 (use (match_operand 2 "" ""))
6710 (use (reg:SI LR_REGNUM))]
6711 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6713 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6715 [(set_attr "type" "call")]
6718 (define_insn "*sibcall_value_insn"
6719 [(set (match_operand 0 "s_register_operand" "=r,f")
6720 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6721 (match_operand 2 "" "")))
6722 (use (match_operand 3 "" ""))
6723 (use (reg:SI LR_REGNUM))]
6724 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6726 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6728 [(set_attr "type" "call")]
6731 ;; Often the return insn will be the same as loading from memory, so set attr
6732 (define_insn "return"
6734 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6737 if (arm_ccfsm_state == 2)
6739 arm_ccfsm_state += 2;
6742 return output_return_instruction (NULL, TRUE, FALSE);
6744 [(set_attr "type" "load")
6745 (set_attr "predicable" "yes")]
6748 (define_insn "*cond_return"
6750 (if_then_else (match_operator 0 "arm_comparison_operator"
6751 [(match_operand 1 "cc_register" "") (const_int 0)])
6754 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6757 if (arm_ccfsm_state == 2)
6759 arm_ccfsm_state += 2;
6762 return output_return_instruction (operands[0], TRUE, FALSE);
6764 [(set_attr "conds" "use")
6765 (set_attr "type" "load")]
6768 (define_insn "*cond_return_inverted"
6770 (if_then_else (match_operator 0 "arm_comparison_operator"
6771 [(match_operand 1 "cc_register" "") (const_int 0)])
6774 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6777 if (arm_ccfsm_state == 2)
6779 arm_ccfsm_state += 2;
6782 return output_return_instruction (operands[0], TRUE, TRUE);
6784 [(set_attr "conds" "use")
6785 (set_attr "type" "load")]
6788 ;; Call subroutine returning any type.
6790 (define_expand "untyped_call"
6791 [(parallel [(call (match_operand 0 "" "")
6793 (match_operand 1 "" "")
6794 (match_operand 2 "" "")])]
6800 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6802 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6804 rtx set = XVECEXP (operands[2], 0, i);
6806 emit_move_insn (SET_DEST (set), SET_SRC (set));
6809 /* The optimizer does not know that the call sets the function value
6810 registers we stored in the result block. We avoid problems by
6811 claiming that all hard registers are used and clobbered at this
6813 emit_insn (gen_blockage ());
6819 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6820 ;; all of memory. This blocks insns from being moved across this point.
6822 (define_insn "blockage"
6823 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6826 [(set_attr "length" "0")
6827 (set_attr "type" "block")]
6830 (define_expand "casesi"
6831 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6832 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6833 (match_operand:SI 2 "const_int_operand" "") ; total range
6834 (match_operand:SI 3 "" "") ; table label
6835 (match_operand:SI 4 "" "")] ; Out of range label
6840 if (operands[1] != const0_rtx)
6842 reg = gen_reg_rtx (SImode);
6844 emit_insn (gen_addsi3 (reg, operands[0],
6845 GEN_INT (-INTVAL (operands[1]))));
6849 if (!const_ok_for_arm (INTVAL (operands[2])))
6850 operands[2] = force_reg (SImode, operands[2]);
6852 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6858 ;; The USE in this pattern is needed to tell flow analysis that this is
6859 ;; a CASESI insn. It has no other purpose.
6860 (define_insn "casesi_internal"
6861 [(parallel [(set (pc)
6863 (leu (match_operand:SI 0 "s_register_operand" "r")
6864 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6865 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6866 (label_ref (match_operand 2 "" ""))))
6867 (label_ref (match_operand 3 "" ""))))
6868 (clobber (reg:CC CC_REGNUM))
6869 (use (label_ref (match_dup 2)))])]
6873 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6874 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6876 [(set_attr "conds" "clob")
6877 (set_attr "length" "12")]
6880 (define_expand "indirect_jump"
6882 (match_operand:SI 0 "s_register_operand" ""))]
6887 (define_insn "*arm_indirect_jump"
6889 (match_operand:SI 0 "s_register_operand" "r"))]
6891 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6892 [(set_attr "predicable" "yes")]
6895 ;; Although not supported by the define_expand above,
6896 ;; cse/combine may generate this form.
6897 (define_insn "*load_indirect_jump"
6899 (match_operand:SI 0 "memory_operand" "m"))]
6901 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6902 [(set_attr "type" "load")
6903 (set_attr "pool_range" "4096")
6904 (set_attr "neg_pool_range" "4084")
6905 (set_attr "predicable" "yes")]
6908 (define_insn "*thumb_indirect_jump"
6910 (match_operand:SI 0 "register_operand" "l*r"))]
6913 [(set_attr "conds" "clob")
6914 (set_attr "length" "2")]
6925 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6926 return \"mov\\tr8, r8\";
6928 [(set (attr "length")
6929 (if_then_else (eq_attr "is_thumb" "yes")
6935 ;; Patterns to allow combination of arithmetic, cond code and shifts
6937 (define_insn "*arith_shiftsi"
6938 [(set (match_operand:SI 0 "s_register_operand" "=r")
6939 (match_operator:SI 1 "shiftable_operator"
6940 [(match_operator:SI 3 "shift_operator"
6941 [(match_operand:SI 4 "s_register_operand" "r")
6942 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6943 (match_operand:SI 2 "s_register_operand" "r")]))]
6945 "%i1%?\\t%0, %2, %4%S3"
6946 [(set_attr "predicable" "yes")
6947 (set_attr "shift" "4")
6951 (define_insn "*arith_shiftsi_compare0"
6952 [(set (reg:CC_NOOV CC_REGNUM)
6953 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6954 [(match_operator:SI 3 "shift_operator"
6955 [(match_operand:SI 4 "s_register_operand" "r")
6956 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6957 (match_operand:SI 2 "s_register_operand" "r")])
6959 (set (match_operand:SI 0 "s_register_operand" "=r")
6960 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6963 "%i1%?s\\t%0, %2, %4%S3"
6964 [(set_attr "conds" "set")
6965 (set_attr "shift" "4")
6969 (define_insn "*arith_shiftsi_compare0_scratch"
6970 [(set (reg:CC_NOOV CC_REGNUM)
6971 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6972 [(match_operator:SI 3 "shift_operator"
6973 [(match_operand:SI 4 "s_register_operand" "r")
6974 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6975 (match_operand:SI 2 "s_register_operand" "r")])
6977 (clobber (match_scratch:SI 0 "=r"))]
6979 "%i1%?s\\t%0, %2, %4%S3"
6980 [(set_attr "conds" "set")
6981 (set_attr "shift" "4")
6985 (define_insn "*sub_shiftsi"
6986 [(set (match_operand:SI 0 "s_register_operand" "=r")
6987 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6988 (match_operator:SI 2 "shift_operator"
6989 [(match_operand:SI 3 "s_register_operand" "r")
6990 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6992 "sub%?\\t%0, %1, %3%S2"
6993 [(set_attr "predicable" "yes")
6994 (set_attr "shift" "3")
6998 (define_insn "*sub_shiftsi_compare0"
6999 [(set (reg:CC_NOOV CC_REGNUM)
7001 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7002 (match_operator:SI 2 "shift_operator"
7003 [(match_operand:SI 3 "s_register_operand" "r")
7004 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7006 (set (match_operand:SI 0 "s_register_operand" "=r")
7007 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7010 "sub%?s\\t%0, %1, %3%S2"
7011 [(set_attr "conds" "set")
7012 (set_attr "shift" "3")
7016 (define_insn "*sub_shiftsi_compare0_scratch"
7017 [(set (reg:CC_NOOV CC_REGNUM)
7019 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7020 (match_operator:SI 2 "shift_operator"
7021 [(match_operand:SI 3 "s_register_operand" "r")
7022 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7024 (clobber (match_scratch:SI 0 "=r"))]
7026 "sub%?s\\t%0, %1, %3%S2"
7027 [(set_attr "conds" "set")
7028 (set_attr "shift" "3")
7032 ;; These variants of the above insns can occur if the first operand is the
7033 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
7034 ;; seem to be a way around it. Most of the predicates have to be null
7035 ;; because the format can be generated part way through reload, so
7036 ;; if we don't match it as soon as it becomes available, reload doesn't know
7037 ;; how to reload pseudos that haven't got hard registers; the constraints will
7038 ;; sort everything out.
7040 (define_insn "*reload_mulsi3"
7041 [(set (match_operand:SI 0 "" "=&r")
7042 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
7043 [(match_operand:SI 3 "" "r")
7044 (match_operand:SI 4 "" "rM")])
7045 (match_operand:SI 2 "" "r"))
7046 (match_operand:SI 1 "const_int_operand" "n")))]
7047 "TARGET_ARM && reload_in_progress"
7049 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
7050 operands[2] = operands[1];
7051 operands[1] = operands[0];
7052 return output_add_immediate (operands);
7055 ; we have no idea how long the add_immediate is, it could be up to 4.
7056 (set_attr "length" "20")]
7059 (define_insn "*reload_mulsi_compare0"
7060 [(set (reg:CC_NOOV CC_REGNUM)
7061 (compare:CC_NOOV (plus:SI
7063 (match_operator:SI 5 "shift_operator"
7064 [(match_operand:SI 3 "" "r")
7065 (match_operand:SI 4 "" "rM")])
7066 (match_operand:SI 1 "" "r"))
7067 (match_operand:SI 2 "const_int_operand" "n"))
7069 (set (match_operand:SI 0 "" "=&r")
7070 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
7073 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7075 output_add_immediate (operands);
7076 return \"add%?s\\t%0, %0, %3%S5\";
7078 [(set_attr "conds" "set")
7079 (set_attr "shift" "3")
7080 (set_attr "length" "20")]
7083 (define_insn "*reload_mulsi_compare0_scratch"
7084 [(set (reg:CC_NOOV CC_REGNUM)
7085 (compare:CC_NOOV (plus:SI
7087 (match_operator:SI 5 "shift_operator"
7088 [(match_operand:SI 3 "" "r")
7089 (match_operand:SI 4 "" "rM")])
7090 (match_operand:SI 1 "" "r"))
7091 (match_operand:SI 2 "const_int_operand" "n"))
7093 (clobber (match_scratch:SI 0 "=&r"))]
7094 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7096 output_add_immediate (operands);
7097 return \"add%?s\\t%0, %0, %3%S5\";
7099 [(set_attr "conds" "set")
7100 (set_attr "shift" "3")
7101 (set_attr "length" "20")]
7104 ;; These are similar, but are needed when the mla pattern contains the
7105 ;; eliminated register as operand 3.
7107 (define_insn "*reload_muladdsi"
7108 [(set (match_operand:SI 0 "" "=&r,&r")
7109 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
7110 (match_operand:SI 2 "" "r,r"))
7111 (match_operand:SI 3 "" "r,r"))
7112 (match_operand:SI 4 "const_int_operand" "n,n")))]
7113 "TARGET_ARM && reload_in_progress"
7115 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
7116 operands[2] = operands[4];
7117 operands[1] = operands[0];
7118 return output_add_immediate (operands);
7120 [(set_attr "length" "20")
7121 (set_attr "type" "mult")]
7124 (define_insn "*reload_muladdsi_compare0"
7125 [(set (reg:CC_NOOV CC_REGNUM)
7126 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7127 (match_operand:SI 3 "" "r")
7128 (match_operand:SI 4 "" "r"))
7129 (match_operand:SI 1 "" "r"))
7130 (match_operand:SI 2 "const_int_operand" "n"))
7132 (set (match_operand:SI 0 "" "=&r")
7133 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
7135 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7137 output_add_immediate (operands);
7138 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
7141 [(set_attr "length" "20")
7142 (set_attr "conds" "set")
7143 (set_attr "type" "mult")]
7146 (define_insn "*reload_muladdsi_compare0_scratch"
7147 [(set (reg:CC_NOOV CC_REGNUM)
7148 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7149 (match_operand:SI 3 "" "r")
7150 (match_operand:SI 4 "" "r"))
7151 (match_operand:SI 1 "" "r"))
7152 (match_operand:SI 2 "const_int_operand" "n"))
7154 (clobber (match_scratch:SI 0 "=&r"))]
7155 "TARGET_ARM && reload_in_progress"
7157 output_add_immediate (operands);
7158 return \"mla%?s\\t%0, %3, %4, %0\";
7160 [(set_attr "length" "20")
7161 (set_attr "conds" "set")
7162 (set_attr "type" "mult")]
7167 (define_insn "*and_scc"
7168 [(set (match_operand:SI 0 "s_register_operand" "=r")
7169 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7170 [(match_operand 3 "cc_register" "") (const_int 0)])
7171 (match_operand:SI 2 "s_register_operand" "r")))]
7173 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7174 [(set_attr "conds" "use")
7175 (set_attr "length" "8")]
7178 (define_insn "*ior_scc"
7179 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7180 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7181 [(match_operand 3 "cc_register" "") (const_int 0)])
7182 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7186 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7187 [(set_attr "conds" "use")
7188 (set_attr "length" "4,8")]
7191 (define_insn "*compare_scc"
7192 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7193 (match_operator:SI 1 "arm_comparison_operator"
7194 [(match_operand:SI 2 "s_register_operand" "r,r")
7195 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7196 (clobber (reg:CC CC_REGNUM))]
7199 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7200 return \"mov\\t%0, %2, lsr #31\";
7202 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7203 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7205 if (GET_CODE (operands[1]) == NE)
7207 if (which_alternative == 1)
7208 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7209 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7211 if (which_alternative == 1)
7212 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7214 output_asm_insn (\"cmp\\t%2, %3\", operands);
7215 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7217 [(set_attr "conds" "clob")
7218 (set_attr "length" "12")]
7221 (define_insn "*cond_move"
7222 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7223 (if_then_else:SI (match_operator 3 "equality_operator"
7224 [(match_operator 4 "arm_comparison_operator"
7225 [(match_operand 5 "cc_register" "") (const_int 0)])
7227 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7228 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7231 if (GET_CODE (operands[3]) == NE)
7233 if (which_alternative != 1)
7234 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7235 if (which_alternative != 0)
7236 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7239 if (which_alternative != 0)
7240 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7241 if (which_alternative != 1)
7242 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7245 [(set_attr "conds" "use")
7246 (set_attr "length" "4,4,8")]
7249 (define_insn "*cond_arith"
7250 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7251 (match_operator:SI 5 "shiftable_operator"
7252 [(match_operator:SI 4 "arm_comparison_operator"
7253 [(match_operand:SI 2 "s_register_operand" "r,r")
7254 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7255 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7256 (clobber (reg:CC CC_REGNUM))]
7259 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7260 return \"%i5\\t%0, %1, %2, lsr #31\";
7262 output_asm_insn (\"cmp\\t%2, %3\", operands);
7263 if (GET_CODE (operands[5]) == AND)
7264 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7265 else if (GET_CODE (operands[5]) == MINUS)
7266 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7267 else if (which_alternative != 0)
7268 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7269 return \"%i5%d4\\t%0, %1, #1\";
7271 [(set_attr "conds" "clob")
7272 (set_attr "length" "12")]
7275 (define_insn "*cond_sub"
7276 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7277 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7278 (match_operator:SI 4 "arm_comparison_operator"
7279 [(match_operand:SI 2 "s_register_operand" "r,r")
7280 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7281 (clobber (reg:CC CC_REGNUM))]
7284 output_asm_insn (\"cmp\\t%2, %3\", operands);
7285 if (which_alternative != 0)
7286 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7287 return \"sub%d4\\t%0, %1, #1\";
7289 [(set_attr "conds" "clob")
7290 (set_attr "length" "8,12")]
7293 (define_insn "*cmp_ite0"
7294 [(set (match_operand 6 "dominant_cc_register" "")
7297 (match_operator 4 "arm_comparison_operator"
7298 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7299 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7300 (match_operator:SI 5 "arm_comparison_operator"
7301 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7302 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7308 static const char * const opcodes[4][2] =
7310 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7311 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7312 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7313 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7314 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7315 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7316 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7317 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7320 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7322 return opcodes[which_alternative][swap];
7324 [(set_attr "conds" "set")
7325 (set_attr "length" "8")]
7328 (define_insn "*cmp_ite1"
7329 [(set (match_operand 6 "dominant_cc_register" "")
7332 (match_operator 4 "arm_comparison_operator"
7333 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7334 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7335 (match_operator:SI 5 "arm_comparison_operator"
7336 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7337 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7343 static const char * const opcodes[4][2] =
7345 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7346 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7347 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7348 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7349 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7350 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7351 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7352 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7355 comparison_dominates_p (GET_CODE (operands[5]),
7356 reverse_condition (GET_CODE (operands[4])));
7358 return opcodes[which_alternative][swap];
7360 [(set_attr "conds" "set")
7361 (set_attr "length" "8")]
7364 (define_insn "*cmp_and"
7365 [(set (match_operand 6 "dominant_cc_register" "")
7368 (match_operator 4 "arm_comparison_operator"
7369 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7370 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7371 (match_operator:SI 5 "arm_comparison_operator"
7372 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7373 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7378 const char * opcodes[4][2] =
7380 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7381 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7382 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7383 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7384 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7385 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7386 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7387 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7390 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7392 return opcodes[which_alternative][swap];
7394 [(set_attr "conds" "set")
7395 (set_attr "predicable" "no")
7396 (set_attr "length" "8")]
7399 (define_insn "*cmp_ior"
7400 [(set (match_operand 6 "dominant_cc_register" "")
7403 (match_operator 4 "arm_comparison_operator"
7404 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7405 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7406 (match_operator:SI 5 "arm_comparison_operator"
7407 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7408 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7413 const char * opcodes[4][2] =
7415 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7416 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7417 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7418 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7419 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7420 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7421 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7422 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7425 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7427 return opcodes[which_alternative][swap];
7430 [(set_attr "conds" "set")
7431 (set_attr "length" "8")]
7434 (define_insn "*negscc"
7435 [(set (match_operand:SI 0 "s_register_operand" "=r")
7436 (neg:SI (match_operator 3 "arm_comparison_operator"
7437 [(match_operand:SI 1 "s_register_operand" "r")
7438 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7439 (clobber (reg:CC CC_REGNUM))]
7442 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7443 return \"mov\\t%0, %1, asr #31\";
7445 if (GET_CODE (operands[3]) == NE)
7446 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7448 if (GET_CODE (operands[3]) == GT)
7449 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7451 output_asm_insn (\"cmp\\t%1, %2\", operands);
7452 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7453 return \"mvn%d3\\t%0, #0\";
7455 [(set_attr "conds" "clob")
7456 (set_attr "length" "12")]
7459 (define_insn "movcond"
7460 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7462 (match_operator 5 "arm_comparison_operator"
7463 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7464 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7465 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7466 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7467 (clobber (reg:CC CC_REGNUM))]
7470 if (GET_CODE (operands[5]) == LT
7471 && (operands[4] == const0_rtx))
7473 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7475 if (operands[2] == const0_rtx)
7476 return \"and\\t%0, %1, %3, asr #31\";
7477 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7479 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7481 if (operands[1] == const0_rtx)
7482 return \"bic\\t%0, %2, %3, asr #31\";
7483 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7485 /* The only case that falls through to here is when both ops 1 & 2
7489 if (GET_CODE (operands[5]) == GE
7490 && (operands[4] == const0_rtx))
7492 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7494 if (operands[2] == const0_rtx)
7495 return \"bic\\t%0, %1, %3, asr #31\";
7496 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7498 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7500 if (operands[1] == const0_rtx)
7501 return \"and\\t%0, %2, %3, asr #31\";
7502 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7504 /* The only case that falls through to here is when both ops 1 & 2
7507 if (GET_CODE (operands[4]) == CONST_INT
7508 && !const_ok_for_arm (INTVAL (operands[4])))
7509 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7511 output_asm_insn (\"cmp\\t%3, %4\", operands);
7512 if (which_alternative != 0)
7513 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7514 if (which_alternative != 1)
7515 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7518 [(set_attr "conds" "clob")
7519 (set_attr "length" "8,8,12")]
7522 (define_insn "*ifcompare_plus_move"
7523 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7524 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7525 [(match_operand:SI 4 "s_register_operand" "r,r")
7526 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7528 (match_operand:SI 2 "s_register_operand" "r,r")
7529 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7530 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7531 (clobber (reg:CC CC_REGNUM))]
7534 [(set_attr "conds" "clob")
7535 (set_attr "length" "8,12")]
7538 (define_insn "*if_plus_move"
7539 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7541 (match_operator 4 "arm_comparison_operator"
7542 [(match_operand 5 "cc_register" "") (const_int 0)])
7544 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7545 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7546 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7550 sub%d4\\t%0, %2, #%n3
7551 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7552 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7553 [(set_attr "conds" "use")
7554 (set_attr "length" "4,4,8,8")
7555 (set_attr "type" "*,*,*,*")]
7558 (define_insn "*ifcompare_move_plus"
7559 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7560 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7561 [(match_operand:SI 4 "s_register_operand" "r,r")
7562 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7563 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7565 (match_operand:SI 2 "s_register_operand" "r,r")
7566 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7567 (clobber (reg:CC CC_REGNUM))]
7570 [(set_attr "conds" "clob")
7571 (set_attr "length" "8,12")]
7574 (define_insn "*if_move_plus"
7575 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7577 (match_operator 4 "arm_comparison_operator"
7578 [(match_operand 5 "cc_register" "") (const_int 0)])
7579 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7581 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7582 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7586 sub%D4\\t%0, %2, #%n3
7587 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7588 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7589 [(set_attr "conds" "use")
7590 (set_attr "length" "4,4,8,8")
7591 (set_attr "type" "*,*,*,*")]
7594 (define_insn "*ifcompare_arith_arith"
7595 [(set (match_operand:SI 0 "s_register_operand" "=r")
7596 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7597 [(match_operand:SI 5 "s_register_operand" "r")
7598 (match_operand:SI 6 "arm_add_operand" "rIL")])
7599 (match_operator:SI 8 "shiftable_operator"
7600 [(match_operand:SI 1 "s_register_operand" "r")
7601 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7602 (match_operator:SI 7 "shiftable_operator"
7603 [(match_operand:SI 3 "s_register_operand" "r")
7604 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7605 (clobber (reg:CC CC_REGNUM))]
7608 [(set_attr "conds" "clob")
7609 (set_attr "length" "12")]
7612 (define_insn "*if_arith_arith"
7613 [(set (match_operand:SI 0 "s_register_operand" "=r")
7614 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7615 [(match_operand 8 "cc_register" "") (const_int 0)])
7616 (match_operator:SI 6 "shiftable_operator"
7617 [(match_operand:SI 1 "s_register_operand" "r")
7618 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7619 (match_operator:SI 7 "shiftable_operator"
7620 [(match_operand:SI 3 "s_register_operand" "r")
7621 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7623 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7624 [(set_attr "conds" "use")
7625 (set_attr "length" "8")]
7628 (define_insn "*ifcompare_arith_move"
7629 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7630 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7631 [(match_operand:SI 2 "s_register_operand" "r,r")
7632 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7633 (match_operator:SI 7 "shiftable_operator"
7634 [(match_operand:SI 4 "s_register_operand" "r,r")
7635 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7636 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7637 (clobber (reg:CC CC_REGNUM))]
7640 /* If we have an operation where (op x 0) is the identity operation and
7641 the conditional operator is LT or GE and we are comparing against zero and
7642 everything is in registers then we can do this in two instructions */
7643 if (operands[3] == const0_rtx
7644 && GET_CODE (operands[7]) != AND
7645 && GET_CODE (operands[5]) == REG
7646 && GET_CODE (operands[1]) == REG
7647 && REGNO (operands[1]) == REGNO (operands[4])
7648 && REGNO (operands[4]) != REGNO (operands[0]))
7650 if (GET_CODE (operands[6]) == LT)
7651 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7652 else if (GET_CODE (operands[6]) == GE)
7653 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7655 if (GET_CODE (operands[3]) == CONST_INT
7656 && !const_ok_for_arm (INTVAL (operands[3])))
7657 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7659 output_asm_insn (\"cmp\\t%2, %3\", operands);
7660 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7661 if (which_alternative != 0)
7662 return \"mov%D6\\t%0, %1\";
7665 [(set_attr "conds" "clob")
7666 (set_attr "length" "8,12")]
7669 (define_insn "*if_arith_move"
7670 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7671 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7672 [(match_operand 6 "cc_register" "") (const_int 0)])
7673 (match_operator:SI 5 "shiftable_operator"
7674 [(match_operand:SI 2 "s_register_operand" "r,r")
7675 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7676 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7680 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7681 [(set_attr "conds" "use")
7682 (set_attr "length" "4,8")
7683 (set_attr "type" "*,*")]
7686 (define_insn "*ifcompare_move_arith"
7687 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7688 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7689 [(match_operand:SI 4 "s_register_operand" "r,r")
7690 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7691 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7692 (match_operator:SI 7 "shiftable_operator"
7693 [(match_operand:SI 2 "s_register_operand" "r,r")
7694 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7695 (clobber (reg:CC CC_REGNUM))]
7698 /* If we have an operation where (op x 0) is the identity operation and
7699 the conditional operator is LT or GE and we are comparing against zero and
7700 everything is in registers then we can do this in two instructions */
7701 if (operands[5] == const0_rtx
7702 && GET_CODE (operands[7]) != AND
7703 && GET_CODE (operands[3]) == REG
7704 && GET_CODE (operands[1]) == REG
7705 && REGNO (operands[1]) == REGNO (operands[2])
7706 && REGNO (operands[2]) != REGNO (operands[0]))
7708 if (GET_CODE (operands[6]) == GE)
7709 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7710 else if (GET_CODE (operands[6]) == LT)
7711 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7714 if (GET_CODE (operands[5]) == CONST_INT
7715 && !const_ok_for_arm (INTVAL (operands[5])))
7716 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7718 output_asm_insn (\"cmp\\t%4, %5\", operands);
7720 if (which_alternative != 0)
7721 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7722 return \"%I7%D6\\t%0, %2, %3\";
7724 [(set_attr "conds" "clob")
7725 (set_attr "length" "8,12")]
7728 (define_insn "*if_move_arith"
7729 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7731 (match_operator 4 "arm_comparison_operator"
7732 [(match_operand 6 "cc_register" "") (const_int 0)])
7733 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7734 (match_operator:SI 5 "shiftable_operator"
7735 [(match_operand:SI 2 "s_register_operand" "r,r")
7736 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7740 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7741 [(set_attr "conds" "use")
7742 (set_attr "length" "4,8")
7743 (set_attr "type" "*,*")]
7746 (define_insn "*ifcompare_move_not"
7747 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7749 (match_operator 5 "arm_comparison_operator"
7750 [(match_operand:SI 3 "s_register_operand" "r,r")
7751 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7752 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7754 (match_operand:SI 2 "s_register_operand" "r,r"))))
7755 (clobber (reg:CC CC_REGNUM))]
7758 [(set_attr "conds" "clob")
7759 (set_attr "length" "8,12")]
7762 (define_insn "*if_move_not"
7763 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7765 (match_operator 4 "arm_comparison_operator"
7766 [(match_operand 3 "cc_register" "") (const_int 0)])
7767 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7768 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7772 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7773 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7774 [(set_attr "conds" "use")
7775 (set_attr "length" "4,8,8")]
7778 (define_insn "*ifcompare_not_move"
7779 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7781 (match_operator 5 "arm_comparison_operator"
7782 [(match_operand:SI 3 "s_register_operand" "r,r")
7783 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7785 (match_operand:SI 2 "s_register_operand" "r,r"))
7786 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7787 (clobber (reg:CC CC_REGNUM))]
7790 [(set_attr "conds" "clob")
7791 (set_attr "length" "8,12")]
7794 (define_insn "*if_not_move"
7795 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7797 (match_operator 4 "arm_comparison_operator"
7798 [(match_operand 3 "cc_register" "") (const_int 0)])
7799 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7800 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7804 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7805 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7806 [(set_attr "conds" "use")
7807 (set_attr "length" "4,8,8")]
7810 (define_insn "*ifcompare_shift_move"
7811 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7813 (match_operator 6 "arm_comparison_operator"
7814 [(match_operand:SI 4 "s_register_operand" "r,r")
7815 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7816 (match_operator:SI 7 "shift_operator"
7817 [(match_operand:SI 2 "s_register_operand" "r,r")
7818 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7819 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7820 (clobber (reg:CC CC_REGNUM))]
7823 [(set_attr "conds" "clob")
7824 (set_attr "length" "8,12")]
7827 (define_insn "*if_shift_move"
7828 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7830 (match_operator 5 "arm_comparison_operator"
7831 [(match_operand 6 "cc_register" "") (const_int 0)])
7832 (match_operator:SI 4 "shift_operator"
7833 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7834 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7835 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7839 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7840 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7841 [(set_attr "conds" "use")
7842 (set_attr "shift" "2")
7843 (set_attr "length" "4,8,8")]
7846 (define_insn "*ifcompare_move_shift"
7847 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7849 (match_operator 6 "arm_comparison_operator"
7850 [(match_operand:SI 4 "s_register_operand" "r,r")
7851 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7852 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7853 (match_operator:SI 7 "shift_operator"
7854 [(match_operand:SI 2 "s_register_operand" "r,r")
7855 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7856 (clobber (reg:CC CC_REGNUM))]
7859 [(set_attr "conds" "clob")
7860 (set_attr "length" "8,12")]
7863 (define_insn "*if_move_shift"
7864 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7866 (match_operator 5 "arm_comparison_operator"
7867 [(match_operand 6 "cc_register" "") (const_int 0)])
7868 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7869 (match_operator:SI 4 "shift_operator"
7870 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7871 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7875 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7876 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7877 [(set_attr "conds" "use")
7878 (set_attr "shift" "2")
7879 (set_attr "length" "4,8,8")]
7882 (define_insn "*ifcompare_shift_shift"
7883 [(set (match_operand:SI 0 "s_register_operand" "=r")
7885 (match_operator 7 "arm_comparison_operator"
7886 [(match_operand:SI 5 "s_register_operand" "r")
7887 (match_operand:SI 6 "arm_add_operand" "rIL")])
7888 (match_operator:SI 8 "shift_operator"
7889 [(match_operand:SI 1 "s_register_operand" "r")
7890 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7891 (match_operator:SI 9 "shift_operator"
7892 [(match_operand:SI 3 "s_register_operand" "r")
7893 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7894 (clobber (reg:CC CC_REGNUM))]
7897 [(set_attr "conds" "clob")
7898 (set_attr "length" "12")]
7901 (define_insn "*if_shift_shift"
7902 [(set (match_operand:SI 0 "s_register_operand" "=r")
7904 (match_operator 5 "arm_comparison_operator"
7905 [(match_operand 8 "cc_register" "") (const_int 0)])
7906 (match_operator:SI 6 "shift_operator"
7907 [(match_operand:SI 1 "s_register_operand" "r")
7908 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7909 (match_operator:SI 7 "shift_operator"
7910 [(match_operand:SI 3 "s_register_operand" "r")
7911 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7913 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7914 [(set_attr "conds" "use")
7915 (set_attr "shift" "1")
7916 (set_attr "length" "8")]
7919 (define_insn "*ifcompare_not_arith"
7920 [(set (match_operand:SI 0 "s_register_operand" "=r")
7922 (match_operator 6 "arm_comparison_operator"
7923 [(match_operand:SI 4 "s_register_operand" "r")
7924 (match_operand:SI 5 "arm_add_operand" "rIL")])
7925 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7926 (match_operator:SI 7 "shiftable_operator"
7927 [(match_operand:SI 2 "s_register_operand" "r")
7928 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7929 (clobber (reg:CC CC_REGNUM))]
7932 [(set_attr "conds" "clob")
7933 (set_attr "length" "12")]
7936 (define_insn "*if_not_arith"
7937 [(set (match_operand:SI 0 "s_register_operand" "=r")
7939 (match_operator 5 "arm_comparison_operator"
7940 [(match_operand 4 "cc_register" "") (const_int 0)])
7941 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7942 (match_operator:SI 6 "shiftable_operator"
7943 [(match_operand:SI 2 "s_register_operand" "r")
7944 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7946 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7947 [(set_attr "conds" "use")
7948 (set_attr "length" "8")]
7951 (define_insn "*ifcompare_arith_not"
7952 [(set (match_operand:SI 0 "s_register_operand" "=r")
7954 (match_operator 6 "arm_comparison_operator"
7955 [(match_operand:SI 4 "s_register_operand" "r")
7956 (match_operand:SI 5 "arm_add_operand" "rIL")])
7957 (match_operator:SI 7 "shiftable_operator"
7958 [(match_operand:SI 2 "s_register_operand" "r")
7959 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7960 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7961 (clobber (reg:CC CC_REGNUM))]
7964 [(set_attr "conds" "clob")
7965 (set_attr "length" "12")]
7968 (define_insn "*if_arith_not"
7969 [(set (match_operand:SI 0 "s_register_operand" "=r")
7971 (match_operator 5 "arm_comparison_operator"
7972 [(match_operand 4 "cc_register" "") (const_int 0)])
7973 (match_operator:SI 6 "shiftable_operator"
7974 [(match_operand:SI 2 "s_register_operand" "r")
7975 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7976 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7978 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7979 [(set_attr "conds" "use")
7980 (set_attr "length" "8")]
7983 (define_insn "*ifcompare_neg_move"
7984 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7986 (match_operator 5 "arm_comparison_operator"
7987 [(match_operand:SI 3 "s_register_operand" "r,r")
7988 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7989 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7990 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7991 (clobber (reg:CC CC_REGNUM))]
7994 [(set_attr "conds" "clob")
7995 (set_attr "length" "8,12")]
7998 (define_insn "*if_neg_move"
7999 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8001 (match_operator 4 "arm_comparison_operator"
8002 [(match_operand 3 "cc_register" "") (const_int 0)])
8003 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8004 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8008 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8009 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8010 [(set_attr "conds" "use")
8011 (set_attr "length" "4,8,8")]
8014 (define_insn "*ifcompare_move_neg"
8015 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8017 (match_operator 5 "arm_comparison_operator"
8018 [(match_operand:SI 3 "s_register_operand" "r,r")
8019 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8020 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8021 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8022 (clobber (reg:CC CC_REGNUM))]
8025 [(set_attr "conds" "clob")
8026 (set_attr "length" "8,12")]
8029 (define_insn "*if_move_neg"
8030 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8032 (match_operator 4 "arm_comparison_operator"
8033 [(match_operand 3 "cc_register" "") (const_int 0)])
8034 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8035 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8039 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8040 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8041 [(set_attr "conds" "use")
8042 (set_attr "length" "4,8,8")]
8045 (define_insn "*arith_adjacentmem"
8046 [(set (match_operand:SI 0 "s_register_operand" "=r")
8047 (match_operator:SI 1 "shiftable_operator"
8048 [(match_operand:SI 2 "memory_operand" "m")
8049 (match_operand:SI 3 "memory_operand" "m")]))
8050 (clobber (match_scratch:SI 4 "=r"))]
8051 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8056 int val1 = 0, val2 = 0;
8058 if (REGNO (operands[0]) > REGNO (operands[4]))
8060 ldm[1] = operands[4];
8061 ldm[2] = operands[0];
8065 ldm[1] = operands[0];
8066 ldm[2] = operands[4];
8068 if (GET_CODE (XEXP (operands[2], 0)) != REG)
8069 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8070 if (GET_CODE (XEXP (operands[3], 0)) != REG)
8071 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8072 arith[0] = operands[0];
8073 arith[3] = operands[1];
8087 ldm[0] = ops[0] = operands[4];
8088 ops[1] = XEXP (XEXP (operands[2], 0), 0);
8089 ops[2] = XEXP (XEXP (operands[2], 0), 1);
8090 output_add_immediate (ops);
8092 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8094 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8098 ldm[0] = XEXP (operands[3], 0);
8100 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8102 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8106 ldm[0] = XEXP (operands[2], 0);
8108 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8110 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8112 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8115 [(set_attr "length" "12")
8116 (set_attr "predicable" "yes")
8117 (set_attr "type" "load")]
8120 ;; the arm can support extended pre-inc instructions
8122 ;; In all these cases, we use operands 0 and 1 for the register being
8123 ;; incremented because those are the operands that local-alloc will
8124 ;; tie and these are the pair most likely to be tieable (and the ones
8125 ;; that will benefit the most).
8127 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8128 ;; elimination will cause too many headaches.
8130 (define_insn "*strqi_preinc"
8131 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8132 (match_operand:SI 2 "index_operand" "rJ")))
8133 (match_operand:QI 3 "s_register_operand" "r"))
8134 (set (match_operand:SI 0 "s_register_operand" "=r")
8135 (plus:SI (match_dup 1) (match_dup 2)))]
8137 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8138 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8139 && (GET_CODE (operands[2]) != REG
8140 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8141 "str%?b\\t%3, [%0, %2]!"
8142 [(set_attr "type" "store1")
8143 (set_attr "predicable" "yes")]
8146 (define_insn "*strqi_predec"
8147 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8148 (match_operand:SI 2 "s_register_operand" "r")))
8149 (match_operand:QI 3 "s_register_operand" "r"))
8150 (set (match_operand:SI 0 "s_register_operand" "=r")
8151 (minus:SI (match_dup 1) (match_dup 2)))]
8153 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8154 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8155 && (GET_CODE (operands[2]) != REG
8156 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8157 "str%?b\\t%3, [%0, -%2]!"
8158 [(set_attr "type" "store1")
8159 (set_attr "predicable" "yes")]
8162 (define_insn "*loadqi_preinc"
8163 [(set (match_operand:QI 3 "s_register_operand" "=r")
8164 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8165 (match_operand:SI 2 "index_operand" "rJ"))))
8166 (set (match_operand:SI 0 "s_register_operand" "=r")
8167 (plus:SI (match_dup 1) (match_dup 2)))]
8169 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8170 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8171 && (GET_CODE (operands[2]) != REG
8172 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8173 "ldr%?b\\t%3, [%0, %2]!"
8174 [(set_attr "type" "load")
8175 (set_attr "predicable" "yes")]
8178 (define_insn "*loadqi_predec"
8179 [(set (match_operand:QI 3 "s_register_operand" "=r")
8180 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8181 (match_operand:SI 2 "s_register_operand" "r"))))
8182 (set (match_operand:SI 0 "s_register_operand" "=r")
8183 (minus:SI (match_dup 1) (match_dup 2)))]
8185 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8186 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8187 && (GET_CODE (operands[2]) != REG
8188 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8189 "ldr%?b\\t%3, [%0, -%2]!"
8190 [(set_attr "type" "load")
8191 (set_attr "predicable" "yes")]
8194 (define_insn "*loadqisi_preinc"
8195 [(set (match_operand:SI 3 "s_register_operand" "=r")
8197 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8198 (match_operand:SI 2 "index_operand" "rJ")))))
8199 (set (match_operand:SI 0 "s_register_operand" "=r")
8200 (plus:SI (match_dup 1) (match_dup 2)))]
8202 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8203 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8204 && (GET_CODE (operands[2]) != REG
8205 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8206 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8207 [(set_attr "type" "load")
8208 (set_attr "predicable" "yes")]
8211 (define_insn "*loadqisi_predec"
8212 [(set (match_operand:SI 3 "s_register_operand" "=r")
8214 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8215 (match_operand:SI 2 "s_register_operand" "r")))))
8216 (set (match_operand:SI 0 "s_register_operand" "=r")
8217 (minus:SI (match_dup 1) (match_dup 2)))]
8219 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8220 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8221 && (GET_CODE (operands[2]) != REG
8222 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8223 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8224 [(set_attr "type" "load")
8225 (set_attr "predicable" "yes")]
8228 (define_insn "*strsi_preinc"
8229 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8230 (match_operand:SI 2 "index_operand" "rJ")))
8231 (match_operand:SI 3 "s_register_operand" "r"))
8232 (set (match_operand:SI 0 "s_register_operand" "=r")
8233 (plus:SI (match_dup 1) (match_dup 2)))]
8235 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8236 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8237 && (GET_CODE (operands[2]) != REG
8238 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8239 "str%?\\t%3, [%0, %2]!"
8240 [(set_attr "type" "store1")
8241 (set_attr "predicable" "yes")]
8244 (define_insn "*strsi_predec"
8245 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8246 (match_operand:SI 2 "s_register_operand" "r")))
8247 (match_operand:SI 3 "s_register_operand" "r"))
8248 (set (match_operand:SI 0 "s_register_operand" "=r")
8249 (minus:SI (match_dup 1) (match_dup 2)))]
8251 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8252 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8253 && (GET_CODE (operands[2]) != REG
8254 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8255 "str%?\\t%3, [%0, -%2]!"
8256 [(set_attr "type" "store1")
8257 (set_attr "predicable" "yes")]
8260 (define_insn "*loadsi_preinc"
8261 [(set (match_operand:SI 3 "s_register_operand" "=r")
8262 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8263 (match_operand:SI 2 "index_operand" "rJ"))))
8264 (set (match_operand:SI 0 "s_register_operand" "=r")
8265 (plus:SI (match_dup 1) (match_dup 2)))]
8267 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8268 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8269 && (GET_CODE (operands[2]) != REG
8270 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8271 "ldr%?\\t%3, [%0, %2]!"
8272 [(set_attr "type" "load")
8273 (set_attr "predicable" "yes")]
8276 (define_insn "*loadsi_predec"
8277 [(set (match_operand:SI 3 "s_register_operand" "=r")
8278 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8279 (match_operand:SI 2 "s_register_operand" "r"))))
8280 (set (match_operand:SI 0 "s_register_operand" "=r")
8281 (minus:SI (match_dup 1) (match_dup 2)))]
8283 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8284 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8285 && (GET_CODE (operands[2]) != REG
8286 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8287 "ldr%?\\t%3, [%0, -%2]!"
8288 [(set_attr "type" "load")
8289 (set_attr "predicable" "yes")]
8292 (define_insn "*loadhi_preinc"
8293 [(set (match_operand:HI 3 "s_register_operand" "=r")
8294 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8295 (match_operand:SI 2 "index_operand" "rJ"))))
8296 (set (match_operand:SI 0 "s_register_operand" "=r")
8297 (plus:SI (match_dup 1) (match_dup 2)))]
8299 && !BYTES_BIG_ENDIAN
8300 && !TARGET_MMU_TRAPS
8301 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8302 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8303 && (GET_CODE (operands[2]) != REG
8304 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8305 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8306 [(set_attr "type" "load")
8307 (set_attr "predicable" "yes")]
8310 (define_insn "*loadhi_predec"
8311 [(set (match_operand:HI 3 "s_register_operand" "=r")
8312 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8313 (match_operand:SI 2 "s_register_operand" "r"))))
8314 (set (match_operand:SI 0 "s_register_operand" "=r")
8315 (minus:SI (match_dup 1) (match_dup 2)))]
8317 && !BYTES_BIG_ENDIAN
8318 && !TARGET_MMU_TRAPS
8319 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8320 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8321 && (GET_CODE (operands[2]) != REG
8322 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8323 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8324 [(set_attr "type" "load")
8325 (set_attr "predicable" "yes")]
8328 (define_insn "*strqi_shiftpreinc"
8329 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8330 [(match_operand:SI 3 "s_register_operand" "r")
8331 (match_operand:SI 4 "const_shift_operand" "n")])
8332 (match_operand:SI 1 "s_register_operand" "0")))
8333 (match_operand:QI 5 "s_register_operand" "r"))
8334 (set (match_operand:SI 0 "s_register_operand" "=r")
8335 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8338 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8339 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8340 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8341 "str%?b\\t%5, [%0, %3%S2]!"
8342 [(set_attr "type" "store1")
8343 (set_attr "predicable" "yes")]
8346 (define_insn "*strqi_shiftpredec"
8347 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8348 (match_operator:SI 2 "shift_operator"
8349 [(match_operand:SI 3 "s_register_operand" "r")
8350 (match_operand:SI 4 "const_shift_operand" "n")])))
8351 (match_operand:QI 5 "s_register_operand" "r"))
8352 (set (match_operand:SI 0 "s_register_operand" "=r")
8353 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8356 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8357 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8358 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8359 "str%?b\\t%5, [%0, -%3%S2]!"
8360 [(set_attr "type" "store1")
8361 (set_attr "predicable" "yes")]
8364 (define_insn "*loadqi_shiftpreinc"
8365 [(set (match_operand:QI 5 "s_register_operand" "=r")
8366 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8367 [(match_operand:SI 3 "s_register_operand" "r")
8368 (match_operand:SI 4 "const_shift_operand" "n")])
8369 (match_operand:SI 1 "s_register_operand" "0"))))
8370 (set (match_operand:SI 0 "s_register_operand" "=r")
8371 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8374 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8375 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8376 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8377 "ldr%?b\\t%5, [%0, %3%S2]!"
8378 [(set_attr "type" "load")
8379 (set_attr "predicable" "yes")]
8382 (define_insn "*loadqi_shiftpredec"
8383 [(set (match_operand:QI 5 "s_register_operand" "=r")
8384 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8385 (match_operator:SI 2 "shift_operator"
8386 [(match_operand:SI 3 "s_register_operand" "r")
8387 (match_operand:SI 4 "const_shift_operand" "n")]))))
8388 (set (match_operand:SI 0 "s_register_operand" "=r")
8389 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8392 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8393 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8394 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8395 "ldr%?b\\t%5, [%0, -%3%S2]!"
8396 [(set_attr "type" "load")
8397 (set_attr "predicable" "yes")]
8400 (define_insn "*strsi_shiftpreinc"
8401 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8402 [(match_operand:SI 3 "s_register_operand" "r")
8403 (match_operand:SI 4 "const_shift_operand" "n")])
8404 (match_operand:SI 1 "s_register_operand" "0")))
8405 (match_operand:SI 5 "s_register_operand" "r"))
8406 (set (match_operand:SI 0 "s_register_operand" "=r")
8407 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8410 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8411 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8412 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8413 "str%?\\t%5, [%0, %3%S2]!"
8414 [(set_attr "type" "store1")
8415 (set_attr "predicable" "yes")]
8418 (define_insn "*strsi_shiftpredec"
8419 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8420 (match_operator:SI 2 "shift_operator"
8421 [(match_operand:SI 3 "s_register_operand" "r")
8422 (match_operand:SI 4 "const_shift_operand" "n")])))
8423 (match_operand:SI 5 "s_register_operand" "r"))
8424 (set (match_operand:SI 0 "s_register_operand" "=r")
8425 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8428 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8429 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8430 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8431 "str%?\\t%5, [%0, -%3%S2]!"
8432 [(set_attr "type" "store1")
8433 (set_attr "predicable" "yes")]
8436 (define_insn "*loadsi_shiftpreinc"
8437 [(set (match_operand:SI 5 "s_register_operand" "=r")
8438 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8439 [(match_operand:SI 3 "s_register_operand" "r")
8440 (match_operand:SI 4 "const_shift_operand" "n")])
8441 (match_operand:SI 1 "s_register_operand" "0"))))
8442 (set (match_operand:SI 0 "s_register_operand" "=r")
8443 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8446 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8447 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8448 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8449 "ldr%?\\t%5, [%0, %3%S2]!"
8450 [(set_attr "type" "load")
8451 (set_attr "predicable" "yes")]
8454 (define_insn "*loadsi_shiftpredec"
8455 [(set (match_operand:SI 5 "s_register_operand" "=r")
8456 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8457 (match_operator:SI 2 "shift_operator"
8458 [(match_operand:SI 3 "s_register_operand" "r")
8459 (match_operand:SI 4 "const_shift_operand" "n")]))))
8460 (set (match_operand:SI 0 "s_register_operand" "=r")
8461 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8464 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8465 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8466 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8467 "ldr%?\\t%5, [%0, -%3%S2]!"
8468 [(set_attr "type" "load")
8469 (set_attr "predicable" "yes")])
8471 (define_insn "*loadhi_shiftpreinc"
8472 [(set (match_operand:HI 5 "s_register_operand" "=r")
8473 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8474 [(match_operand:SI 3 "s_register_operand" "r")
8475 (match_operand:SI 4 "const_shift_operand" "n")])
8476 (match_operand:SI 1 "s_register_operand" "0"))))
8477 (set (match_operand:SI 0 "s_register_operand" "=r")
8478 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8481 && !BYTES_BIG_ENDIAN
8482 && !TARGET_MMU_TRAPS
8483 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8484 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8485 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8486 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8487 [(set_attr "type" "load")
8488 (set_attr "predicable" "yes")]
8491 (define_insn "*loadhi_shiftpredec"
8492 [(set (match_operand:HI 5 "s_register_operand" "=r")
8493 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8494 (match_operator:SI 2 "shift_operator"
8495 [(match_operand:SI 3 "s_register_operand" "r")
8496 (match_operand:SI 4 "const_shift_operand" "n")]))))
8497 (set (match_operand:SI 0 "s_register_operand" "=r")
8498 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8501 && !BYTES_BIG_ENDIAN
8502 && !TARGET_MMU_TRAPS
8503 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8504 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8505 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8506 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8507 [(set_attr "type" "load")
8508 (set_attr "predicable" "yes")]
8511 ; It can also support extended post-inc expressions, but combine doesn't
8513 ; It doesn't seem worth adding peepholes for anything but the most common
8514 ; cases since, unlike combine, the increment must immediately follow the load
8515 ; for this pattern to match.
8516 ; We must watch to see that the source/destination register isn't also the
8517 ; same as the base address register, and that if the index is a register,
8518 ; that it is not the same as the base address register. In such cases the
8519 ; instruction that we would generate would have UNPREDICTABLE behaviour so
8523 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8524 (match_operand:QI 2 "s_register_operand" "r"))
8526 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8528 && (REGNO (operands[2]) != REGNO (operands[0]))
8529 && (GET_CODE (operands[1]) != REG
8530 || (REGNO (operands[1]) != REGNO (operands[0])))"
8531 "str%?b\\t%2, [%0], %1"
8535 [(set (match_operand:QI 0 "s_register_operand" "=r")
8536 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8538 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8540 && REGNO (operands[0]) != REGNO(operands[1])
8541 && (GET_CODE (operands[2]) != REG
8542 || REGNO(operands[0]) != REGNO (operands[2]))"
8543 "ldr%?b\\t%0, [%1], %2"
8547 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8548 (match_operand:SI 2 "s_register_operand" "r"))
8550 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8552 && (REGNO (operands[2]) != REGNO (operands[0]))
8553 && (GET_CODE (operands[1]) != REG
8554 || (REGNO (operands[1]) != REGNO (operands[0])))"
8555 "str%?\\t%2, [%0], %1"
8559 [(set (match_operand:HI 0 "s_register_operand" "=r")
8560 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8562 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8564 && !BYTES_BIG_ENDIAN
8565 && !TARGET_MMU_TRAPS
8566 && REGNO (operands[0]) != REGNO(operands[1])
8567 && (GET_CODE (operands[2]) != REG
8568 || REGNO(operands[0]) != REGNO (operands[2]))"
8569 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8573 [(set (match_operand:SI 0 "s_register_operand" "=r")
8574 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8576 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8578 && REGNO (operands[0]) != REGNO(operands[1])
8579 && (GET_CODE (operands[2]) != REG
8580 || REGNO(operands[0]) != REGNO (operands[2]))"
8581 "ldr%?\\t%0, [%1], %2"
8585 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8586 (match_operand:SI 1 "index_operand" "rJ")))
8587 (match_operand:QI 2 "s_register_operand" "r"))
8588 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8590 && (REGNO (operands[2]) != REGNO (operands[0]))
8591 && (GET_CODE (operands[1]) != REG
8592 || (REGNO (operands[1]) != REGNO (operands[0])))"
8593 "str%?b\\t%2, [%0, %1]!"
8597 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8598 [(match_operand:SI 0 "s_register_operand" "r")
8599 (match_operand:SI 1 "const_int_operand" "n")])
8600 (match_operand:SI 2 "s_register_operand" "+r")))
8601 (match_operand:QI 3 "s_register_operand" "r"))
8602 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8605 && (REGNO (operands[3]) != REGNO (operands[2]))
8606 && (REGNO (operands[0]) != REGNO (operands[2]))"
8607 "str%?b\\t%3, [%2, %0%S4]!"
8610 ; This pattern is never tried by combine, so do it as a peephole
8613 [(set (match_operand:SI 0 "s_register_operand" "")
8614 (match_operand:SI 1 "s_register_operand" ""))
8615 (set (reg:CC CC_REGNUM)
8616 (compare:CC (match_dup 1) (const_int 0)))]
8619 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8620 (set (match_dup 0) (match_dup 1))])]
8624 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8625 ; reversed, check that the memory references aren't volatile.
8628 [(set (match_operand:SI 0 "s_register_operand" "=r")
8629 (match_operand:SI 4 "memory_operand" "m"))
8630 (set (match_operand:SI 1 "s_register_operand" "=r")
8631 (match_operand:SI 5 "memory_operand" "m"))
8632 (set (match_operand:SI 2 "s_register_operand" "=r")
8633 (match_operand:SI 6 "memory_operand" "m"))
8634 (set (match_operand:SI 3 "s_register_operand" "=r")
8635 (match_operand:SI 7 "memory_operand" "m"))]
8636 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8638 return emit_ldm_seq (operands, 4);
8643 [(set (match_operand:SI 0 "s_register_operand" "=r")
8644 (match_operand:SI 3 "memory_operand" "m"))
8645 (set (match_operand:SI 1 "s_register_operand" "=r")
8646 (match_operand:SI 4 "memory_operand" "m"))
8647 (set (match_operand:SI 2 "s_register_operand" "=r")
8648 (match_operand:SI 5 "memory_operand" "m"))]
8649 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8651 return emit_ldm_seq (operands, 3);
8656 [(set (match_operand:SI 0 "s_register_operand" "=r")
8657 (match_operand:SI 2 "memory_operand" "m"))
8658 (set (match_operand:SI 1 "s_register_operand" "=r")
8659 (match_operand:SI 3 "memory_operand" "m"))]
8660 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8662 return emit_ldm_seq (operands, 2);
8667 [(set (match_operand:SI 4 "memory_operand" "=m")
8668 (match_operand:SI 0 "s_register_operand" "r"))
8669 (set (match_operand:SI 5 "memory_operand" "=m")
8670 (match_operand:SI 1 "s_register_operand" "r"))
8671 (set (match_operand:SI 6 "memory_operand" "=m")
8672 (match_operand:SI 2 "s_register_operand" "r"))
8673 (set (match_operand:SI 7 "memory_operand" "=m")
8674 (match_operand:SI 3 "s_register_operand" "r"))]
8675 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8677 return emit_stm_seq (operands, 4);
8682 [(set (match_operand:SI 3 "memory_operand" "=m")
8683 (match_operand:SI 0 "s_register_operand" "r"))
8684 (set (match_operand:SI 4 "memory_operand" "=m")
8685 (match_operand:SI 1 "s_register_operand" "r"))
8686 (set (match_operand:SI 5 "memory_operand" "=m")
8687 (match_operand:SI 2 "s_register_operand" "r"))]
8688 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8690 return emit_stm_seq (operands, 3);
8695 [(set (match_operand:SI 2 "memory_operand" "=m")
8696 (match_operand:SI 0 "s_register_operand" "r"))
8697 (set (match_operand:SI 3 "memory_operand" "=m")
8698 (match_operand:SI 1 "s_register_operand" "r"))]
8699 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8701 return emit_stm_seq (operands, 2);
8706 [(set (match_operand:SI 0 "s_register_operand" "")
8707 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8709 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8710 [(match_operand:SI 3 "s_register_operand" "")
8711 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8712 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8714 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8715 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8720 ;; This split can be used because CC_Z mode implies that the following
8721 ;; branch will be an equality, or an unsigned inequality, so the sign
8722 ;; extension is not needed.
8725 [(set (reg:CC_Z CC_REGNUM)
8727 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8729 (match_operand 1 "const_int_operand" "")))
8730 (clobber (match_scratch:SI 2 ""))]
8732 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8733 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8734 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8735 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8737 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8741 (define_expand "prologue"
8742 [(clobber (const_int 0))]
8745 arm_expand_prologue ();
8747 thumb_expand_prologue ();
8752 (define_expand "epilogue"
8753 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8757 thumb_expand_epilogue ();
8758 else if (USE_RETURN_INSN (FALSE))
8760 emit_jump_insn (gen_return ());
8763 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8765 gen_rtx_RETURN (VOIDmode)),
8771 (define_insn "sibcall_epilogue"
8772 [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8775 output_asm_insn (\"%@ Sibcall epilogue\", operands);
8776 if (USE_RETURN_INSN (FALSE))
8777 return output_return_instruction (NULL, FALSE, FALSE);
8778 return arm_output_epilogue (FALSE);
8780 ;; Length is absolute worst case
8781 [(set_attr "length" "44")
8782 (set_attr "type" "block")]
8785 (define_insn "*epilogue_insns"
8786 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8790 return arm_output_epilogue (TRUE);
8791 else /* TARGET_THUMB */
8792 return thumb_unexpanded_epilogue ();
8794 ; Length is absolute worst case
8795 [(set_attr "length" "44")
8796 (set_attr "type" "block")]
8799 (define_expand "eh_epilogue"
8800 [(use (match_operand:SI 0 "register_operand" "r"))
8801 (use (match_operand:SI 1 "register_operand" "r"))
8802 (use (match_operand:SI 2 "register_operand" "r"))]
8806 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8807 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8809 rtx ra = gen_rtx_REG (Pmode, 2);
8811 emit_move_insn (ra, operands[2]);
8814 /* This is a hack -- we may have crystalized the function type too
8816 cfun->machine->func_type = 0;
8820 ;; This split is only used during output to reduce the number of patterns
8821 ;; that need assembler instructions adding to them. We allowed the setting
8822 ;; of the conditions to be implicit during rtl generation so that
8823 ;; the conditional compare patterns would work. However this conflicts to
8824 ;; some extent with the conditional data operations, so we have to split them
8828 [(set (match_operand:SI 0 "s_register_operand" "")
8829 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8830 [(match_operand 2 "" "") (match_operand 3 "" "")])
8832 (match_operand 4 "" "")))
8833 (clobber (reg:CC CC_REGNUM))]
8834 "TARGET_ARM && reload_completed"
8835 [(set (match_dup 5) (match_dup 6))
8836 (cond_exec (match_dup 7)
8837 (set (match_dup 0) (match_dup 4)))]
8840 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8841 operands[2], operands[3]);
8842 enum rtx_code rc = GET_CODE (operands[1]);
8844 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8845 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8846 if (mode == CCFPmode || mode == CCFPEmode)
8847 rc = reverse_condition_maybe_unordered (rc);
8849 rc = reverse_condition (rc);
8851 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8856 [(set (match_operand:SI 0 "s_register_operand" "")
8857 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8858 [(match_operand 2 "" "") (match_operand 3 "" "")])
8859 (match_operand 4 "" "")
8861 (clobber (reg:CC CC_REGNUM))]
8862 "TARGET_ARM && reload_completed"
8863 [(set (match_dup 5) (match_dup 6))
8864 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8865 (set (match_dup 0) (match_dup 4)))]
8868 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8869 operands[2], operands[3]);
8871 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8872 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8877 [(set (match_operand:SI 0 "s_register_operand" "")
8878 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8879 [(match_operand 2 "" "") (match_operand 3 "" "")])
8880 (match_operand 4 "" "")
8881 (match_operand 5 "" "")))
8882 (clobber (reg:CC CC_REGNUM))]
8883 "TARGET_ARM && reload_completed"
8884 [(set (match_dup 6) (match_dup 7))
8885 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8886 (set (match_dup 0) (match_dup 4)))
8887 (cond_exec (match_dup 8)
8888 (set (match_dup 0) (match_dup 5)))]
8891 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8892 operands[2], operands[3]);
8893 enum rtx_code rc = GET_CODE (operands[1]);
8895 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8896 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8897 if (mode == CCFPmode || mode == CCFPEmode)
8898 rc = reverse_condition_maybe_unordered (rc);
8900 rc = reverse_condition (rc);
8902 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8907 [(set (match_operand:SI 0 "s_register_operand" "")
8908 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8909 [(match_operand:SI 2 "s_register_operand" "")
8910 (match_operand:SI 3 "arm_add_operand" "")])
8911 (match_operand:SI 4 "arm_rhs_operand" "")
8913 (match_operand:SI 5 "s_register_operand" ""))))
8914 (clobber (reg:CC CC_REGNUM))]
8915 "TARGET_ARM && reload_completed"
8916 [(set (match_dup 6) (match_dup 7))
8917 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8918 (set (match_dup 0) (match_dup 4)))
8919 (cond_exec (match_dup 8)
8920 (set (match_dup 0) (not:SI (match_dup 5))))]
8923 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8924 operands[2], operands[3]);
8925 enum rtx_code rc = GET_CODE (operands[1]);
8927 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8928 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8929 if (mode == CCFPmode || mode == CCFPEmode)
8930 rc = reverse_condition_maybe_unordered (rc);
8932 rc = reverse_condition (rc);
8934 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8938 (define_insn "*cond_move_not"
8939 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8940 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8941 [(match_operand 3 "cc_register" "") (const_int 0)])
8942 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8944 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8948 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8949 [(set_attr "conds" "use")
8950 (set_attr "length" "4,8")]
8953 ;; The next two patterns occur when an AND operation is followed by a
8954 ;; scc insn sequence
8956 (define_insn "*sign_extract_onebit"
8957 [(set (match_operand:SI 0 "s_register_operand" "=r")
8958 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8960 (match_operand:SI 2 "const_int_operand" "n")))]
8963 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8964 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8965 return \"mvnne\\t%0, #0\";
8967 [(set_attr "conds" "clob")
8968 (set_attr "length" "8")]
8971 (define_insn "*not_signextract_onebit"
8972 [(set (match_operand:SI 0 "s_register_operand" "=r")
8974 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8976 (match_operand:SI 2 "const_int_operand" "n"))))]
8979 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8980 output_asm_insn (\"tst\\t%1, %2\", operands);
8981 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8982 return \"movne\\t%0, #0\";
8984 [(set_attr "conds" "clob")
8985 (set_attr "length" "12")]
8988 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8989 ;; expressions. For simplicity, the first register is also in the unspec
8991 (define_insn "*push_multi"
8992 [(match_parallel 2 "multi_register_push"
8993 [(set (match_operand:BLK 0 "memory_operand" "=m")
8994 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8995 UNSPEC_PUSH_MULT))])]
8999 int num_saves = XVECLEN (operands[2], 0);
9001 /* For the StrongARM at least it is faster to
9002 use STR to store only a single register. */
9004 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9010 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9012 for (i = 1; i < num_saves; i++)
9014 strcat (pattern, \", %|\");
9016 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9019 strcat (pattern, \"}\");
9020 output_asm_insn (pattern, operands);
9025 [(set_attr "type" "store4")]
9028 ;; Similarly for the floating point registers
9029 (define_insn "*push_fp_multi"
9030 [(match_parallel 2 "multi_register_push"
9031 [(set (match_operand:BLK 0 "memory_operand" "=m")
9032 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9033 UNSPEC_PUSH_MULT))])]
9039 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9040 output_asm_insn (pattern, operands);
9043 [(set_attr "type" "f_store")]
9046 ;; Special patterns for dealing with the constant pool
9048 (define_insn "align_4"
9049 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9052 assemble_align (32);
9057 (define_insn "consttable_end"
9058 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9061 making_const_table = FALSE;
9066 (define_insn "consttable_1"
9067 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9070 making_const_table = TRUE;
9071 assemble_integer (operands[0], 1, 1);
9075 [(set_attr "length" "4")]
9078 (define_insn "consttable_2"
9079 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9082 making_const_table = TRUE;
9083 assemble_integer (operands[0], 2, 1);
9087 [(set_attr "length" "4")]
9090 (define_insn "consttable_4"
9091 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9095 making_const_table = TRUE;
9096 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9100 union real_extract u;
9101 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9102 assemble_real (u.d, GET_MODE (operands[0]));
9106 assemble_integer (operands[0], 4, 1);
9111 [(set_attr "length" "4")]
9114 (define_insn "consttable_8"
9115 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9119 making_const_table = TRUE;
9120 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9124 union real_extract u;
9125 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9126 assemble_real (u.d, GET_MODE (operands[0]));
9130 assemble_integer (operands[0], 8, 1);
9135 [(set_attr "length" "8")]
9138 ;; Miscellaneous Thumb patterns
9140 (define_insn "tablejump"
9141 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9142 (use (label_ref (match_operand 1 "" "")))]
9145 [(set_attr "length" "2")]
9151 [(set (match_operand:SI 0 "s_register_operand" "=r")
9152 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9154 "TARGET_ARM && arm_arch5"
9157 (define_expand "ffssi2"
9158 [(set (match_operand:SI 0 "s_register_operand" "")
9159 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9160 "TARGET_ARM && arm_arch5"
9165 t1 = gen_reg_rtx (SImode);
9166 t2 = gen_reg_rtx (SImode);
9167 t3 = gen_reg_rtx (SImode);
9169 emit_insn (gen_negsi2 (t1, operands[1]));
9170 emit_insn (gen_andsi3 (t2, operands[1], t1));
9171 emit_insn (gen_clz (t3, t2));
9172 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9177 ;; V5E instructions.
9179 (define_insn "prefetch"
9181 [(match_operand:SI 0 "offsettable_memory_operand" "o")] VUNSPEC_PREFETCH)]
9182 "TARGET_ARM && arm_arch5e"
9185 ;; General predication pattern
9188 [(match_operator 0 "arm_comparison_operator"
9189 [(match_operand 1 "cc_register" "")