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"))]
3955 return (output_move_double (operands));
3957 [(set_attr "length" "8")
3958 (set_attr "type" "*,load,store2")
3959 (set_attr "pool_range" "*,1020,*")
3960 (set_attr "neg_pool_range" "*,1012,*")]
3963 ;;; ??? This should have alternatives for constants.
3964 ;;; ??? This was originally identical to the movdf_insn pattern.
3965 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3966 ;;; thumb_reorg with a memory reference.
3967 (define_insn "*thumb_movdi_insn"
3968 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3969 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3971 && ( register_operand (operands[0], DImode)
3972 || register_operand (operands[1], DImode))"
3975 switch (which_alternative)
3979 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3980 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3981 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3983 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3985 operands[1] = GEN_INT (- INTVAL (operands[1]));
3986 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3988 return \"ldmia\\t%1, {%0, %H0}\";
3990 return \"stmia\\t%0, {%1, %H1}\";
3992 return thumb_load_double_from_address (operands);
3994 operands[2] = gen_rtx (MEM, SImode,
3995 plus_constant (XEXP (operands[0], 0), 4));
3996 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3999 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4000 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4001 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4004 [(set_attr "length" "4,4,6,2,2,6,4,4")
4005 (set_attr "type" "*,*,*,load,store2,load,store2,*")
4006 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
4009 (define_expand "movsi"
4010 [(set (match_operand:SI 0 "general_operand" "")
4011 (match_operand:SI 1 "general_operand" ""))]
4016 /* Everything except mem = const or mem = mem can be done easily */
4017 if (GET_CODE (operands[0]) == MEM)
4018 operands[1] = force_reg (SImode, operands[1]);
4019 if (GET_CODE (operands[1]) == CONST_INT
4020 && !(const_ok_for_arm (INTVAL (operands[1]))
4021 || const_ok_for_arm (~INTVAL (operands[1]))))
4023 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4026 : preserve_subexpressions_p ()));
4030 else /* TARGET_THUMB.... */
4032 if (!no_new_pseudos)
4034 if (GET_CODE (operands[0]) != REG)
4035 operands[1] = force_reg (SImode, operands[1]);
4040 && (CONSTANT_P (operands[1])
4041 || symbol_mentioned_p (operands[1])
4042 || label_mentioned_p (operands[1])))
4043 operands[1] = legitimize_pic_address (operands[1], SImode,
4044 (no_new_pseudos ? operands[0] : 0));
4048 (define_insn "*arm_movsi_insn"
4049 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
4050 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
4052 && ( register_operand (operands[0], SImode)
4053 || register_operand (operands[1], SImode))"
4059 [(set_attr "type" "*,*,load,store1")
4060 (set_attr "predicable" "yes")
4061 (set_attr "pool_range" "*,*,4096,*")
4062 (set_attr "neg_pool_range" "*,*,4084,*")]
4066 [(set (match_operand:SI 0 "s_register_operand" "")
4067 (match_operand:SI 1 "const_int_operand" ""))]
4069 && (!(const_ok_for_arm (INTVAL (operands[1]))
4070 || const_ok_for_arm (~INTVAL (operands[1]))))"
4071 [(clobber (const_int 0))]
4073 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
4079 (define_insn "*thumb_movsi_insn"
4080 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
4081 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
4083 && ( register_operand (operands[0], SImode)
4084 || register_operand (operands[1], SImode))"
4095 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4096 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4097 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4101 [(set (match_operand:SI 0 "register_operand" "")
4102 (match_operand:SI 1 "const_int_operand" ""))]
4103 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4104 [(set (match_dup 0) (match_dup 1))
4105 (set (match_dup 0) (neg:SI (match_dup 0)))]
4106 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4110 [(set (match_operand:SI 0 "register_operand" "")
4111 (match_operand:SI 1 "const_int_operand" ""))]
4112 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4113 [(set (match_dup 0) (match_dup 1))
4114 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4117 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4118 unsigned HOST_WIDE_INT mask = 0xff;
4121 for (i = 0; i < 25; i++)
4122 if ((val & (mask << i)) == val)
4128 operands[1] = GEN_INT (val >> i);
4129 operands[2] = GEN_INT (i);
4133 (define_expand "movaddr"
4134 [(set (match_operand:SI 0 "s_register_operand" "")
4135 (match_operand:DI 1 "address_operand" ""))]
4140 (define_insn "*movaddr_insn"
4141 [(set (match_operand:SI 0 "s_register_operand" "=r")
4142 (match_operand:DI 1 "address_operand" "p"))]
4145 && (GET_CODE (operands[1]) == LABEL_REF
4146 || (GET_CODE (operands[1]) == CONST
4147 && GET_CODE (XEXP (operands[1], 0)) == PLUS
4148 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
4149 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
4151 [(set_attr "predicable" "yes")]
4154 ;; When generating pic, we need to load the symbol offset into a register.
4155 ;; So that the optimizer does not confuse this with a normal symbol load
4156 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4157 ;; since that is the only type of relocation we can use.
4159 ;; The rather odd constraints on the following are to force reload to leave
4160 ;; the insn alone, and to force the minipool generation pass to then move
4161 ;; the GOT symbol to memory.
4163 (define_insn "pic_load_addr_arm"
4164 [(set (match_operand:SI 0 "s_register_operand" "=r")
4165 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4166 "TARGET_ARM && flag_pic"
4168 [(set_attr "type" "load")
4169 (set (attr "pool_range") (const_int 4096))
4170 (set (attr "neg_pool_range") (const_int 4084))]
4173 (define_insn "pic_load_addr_thumb"
4174 [(set (match_operand:SI 0 "s_register_operand" "=l")
4175 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4176 "TARGET_THUMB && flag_pic"
4178 [(set_attr "type" "load")
4179 (set (attr "pool_range") (const_int 1024))]
4182 ;; This variant is used for AOF assembly, since it needs to mention the
4183 ;; pic register in the rtl.
4184 (define_expand "pic_load_addr_based"
4185 [(set (match_operand:SI 0 "s_register_operand" "=r")
4186 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4187 "TARGET_ARM && flag_pic"
4188 "operands[2] = pic_offset_table_rtx;"
4191 (define_insn "*pic_load_addr_based_insn"
4192 [(set (match_operand:SI 0 "s_register_operand" "=r")
4193 (unspec:SI [(match_operand 1 "" "")
4194 (match_operand 2 "s_register_operand" "r")]
4196 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4198 #ifdef AOF_ASSEMBLER
4199 operands[1] = aof_pic_entry (operands[1]);
4201 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4204 [(set_attr "type" "load")
4205 (set (attr "pool_range")
4206 (if_then_else (eq_attr "is_thumb" "yes")
4209 (set (attr "neg_pool_range")
4210 (if_then_else (eq_attr "is_thumb" "yes")
4215 (define_insn "pic_add_dot_plus_four"
4216 [(set (match_operand:SI 0 "register_operand" "+r")
4217 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
4218 (use (label_ref (match_operand 1 "" "")))]
4219 "TARGET_THUMB && flag_pic"
4221 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4222 CODE_LABEL_NUMBER (operands[1]));
4223 return \"add\\t%0, %|pc\";
4225 [(set_attr "length" "2")]
4228 (define_insn "pic_add_dot_plus_eight"
4229 [(set (match_operand:SI 0 "register_operand" "+r")
4230 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
4231 (use (label_ref (match_operand 1 "" "")))]
4232 "TARGET_ARM && flag_pic"
4234 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
4235 CODE_LABEL_NUMBER (operands[1]));
4236 return \"add%?\\t%0, %|pc, %0\";
4238 [(set_attr "predicable" "yes")]
4241 ;; If copying one reg to another we can set the condition codes according to
4242 ;; its value. Such a move is common after a return from subroutine and the
4243 ;; result is being tested against zero.
4245 (define_insn "*movsi_compare0"
4246 [(set (reg:CC CC_REGNUM)
4247 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4249 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4254 sub%?s\\t%0, %1, #0"
4255 [(set_attr "conds" "set")]
4258 ;; Subroutine to store a half word from a register into memory.
4259 ;; Operand 0 is the source register (HImode)
4260 ;; Operand 1 is the destination address in a register (SImode)
4262 ;; In both this routine and the next, we must be careful not to spill
4263 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4264 ;; can generate unrecognizable rtl.
4266 (define_expand "storehi"
4267 [;; store the low byte
4268 (set (match_operand 1 "" "") (match_dup 3))
4269 ;; extract the high byte
4271 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4272 ;; store the high byte
4273 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4277 rtx addr = XEXP (operands[1], 0);
4278 enum rtx_code code = GET_CODE (addr);
4280 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4282 addr = force_reg (SImode, addr);
4284 operands[4] = change_address (operands[1], QImode,
4285 plus_constant (addr, 1));
4286 operands[1] = change_address (operands[1], QImode, NULL_RTX);
4287 operands[3] = gen_lowpart (QImode, operands[0]);
4288 operands[0] = gen_lowpart (SImode, operands[0]);
4289 operands[2] = gen_reg_rtx (SImode);
4293 (define_expand "storehi_bigend"
4294 [(set (match_dup 4) (match_dup 3))
4296 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4297 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
4301 rtx addr = XEXP (operands[1], 0);
4302 enum rtx_code code = GET_CODE (addr);
4304 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4306 addr = force_reg (SImode, addr);
4308 operands[4] = change_address (operands[1], QImode,
4309 plus_constant (addr, 1));
4310 operands[1] = change_address (operands[1], QImode, NULL_RTX);
4311 operands[3] = gen_lowpart (QImode, operands[0]);
4312 operands[0] = gen_lowpart (SImode, operands[0]);
4313 operands[2] = gen_reg_rtx (SImode);
4317 ;; Subroutine to store a half word integer constant into memory.
4318 (define_expand "storeinthi"
4319 [(set (match_operand 0 "" "")
4320 (subreg:QI (match_operand 1 "" "") 0))
4321 (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
4325 HOST_WIDE_INT value = INTVAL (operands[1]);
4326 rtx addr = XEXP (operands[0], 0);
4327 enum rtx_code code = GET_CODE (addr);
4329 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4331 addr = force_reg (SImode, addr);
4333 operands[1] = gen_reg_rtx (SImode);
4334 if (BYTES_BIG_ENDIAN)
4336 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4337 if ((value & 255) == ((value >> 8) & 255))
4338 operands[2] = operands[1];
4341 operands[2] = gen_reg_rtx (SImode);
4342 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4347 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4348 if ((value & 255) == ((value >> 8) & 255))
4349 operands[2] = operands[1];
4352 operands[2] = gen_reg_rtx (SImode);
4353 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4357 operands[3] = change_address (operands[0], QImode,
4358 plus_constant (addr, 1));
4359 operands[0] = change_address (operands[0], QImode, NULL_RTX);
4363 (define_expand "storehi_single_op"
4364 [(set (match_operand:HI 0 "memory_operand" "")
4365 (match_operand:HI 1 "general_operand" ""))]
4366 "TARGET_ARM && arm_arch4"
4368 if (!s_register_operand (operands[1], HImode))
4369 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4373 (define_expand "movhi"
4374 [(set (match_operand:HI 0 "general_operand" "")
4375 (match_operand:HI 1 "general_operand" ""))]
4380 if (!no_new_pseudos)
4382 if (GET_CODE (operands[0]) == MEM)
4386 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4389 if (GET_CODE (operands[1]) == CONST_INT)
4390 emit_insn (gen_storeinthi (operands[0], operands[1]));
4393 if (GET_CODE (operands[1]) == MEM)
4394 operands[1] = force_reg (HImode, operands[1]);
4395 if (BYTES_BIG_ENDIAN)
4396 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4398 emit_insn (gen_storehi (operands[1], operands[0]));
4402 /* Sign extend a constant, and keep it in an SImode reg. */
4403 else if (GET_CODE (operands[1]) == CONST_INT)
4405 rtx reg = gen_reg_rtx (SImode);
4406 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4408 /* If the constant is already valid, leave it alone. */
4409 if (!const_ok_for_arm (val))
4411 /* If setting all the top bits will make the constant
4412 loadable in a single instruction, then set them.
4413 Otherwise, sign extend the number. */
4415 if (const_ok_for_arm (~(val | ~0xffff)))
4417 else if (val & 0x8000)
4421 emit_insn (gen_movsi (reg, GEN_INT (val)));
4422 operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
4424 else if (!arm_arch4)
4426 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4427 for v4 and up architectures because LDRH instructions will
4428 be used to access the HI values, and these cannot generate
4429 unaligned word access faults in the MMU. */
4430 if (GET_CODE (operands[1]) == MEM)
4432 if (TARGET_MMU_TRAPS)
4435 rtx offset = const0_rtx;
4436 rtx reg = gen_reg_rtx (SImode);
4438 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4439 || (GET_CODE (base) == PLUS
4440 && (GET_CODE (offset = XEXP (base, 1))
4442 && ((INTVAL(offset) & 1) != 1)
4443 && GET_CODE (base = XEXP (base, 0)) == REG))
4444 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4446 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4449 new = gen_rtx_MEM (SImode,
4450 plus_constant (base, new_offset));
4451 MEM_COPY_ATTRIBUTES (new, operands[1]);
4452 emit_insn (gen_movsi (reg, new));
4453 if (((INTVAL (offset) & 2) != 0)
4454 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4456 rtx reg2 = gen_reg_rtx (SImode);
4458 emit_insn (gen_lshrsi3 (reg2, reg,
4464 emit_insn (gen_movhi_bytes (reg, operands[1]));
4466 operands[1] = gen_lowpart (HImode, reg);
4468 else if (BYTES_BIG_ENDIAN)
4471 rtx offset = const0_rtx;
4473 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4474 || (GET_CODE (base) == PLUS
4475 && (GET_CODE (offset = XEXP (base, 1))
4477 && GET_CODE (base = XEXP (base, 0)) == REG))
4478 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4480 rtx reg = gen_reg_rtx (SImode);
4483 if ((INTVAL (offset) & 2) == 2)
4485 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4486 new = gen_rtx_MEM (SImode,
4487 plus_constant (base,
4489 MEM_COPY_ATTRIBUTES (new, operands[1]);
4490 emit_insn (gen_movsi (reg, new));
4494 new = gen_rtx_MEM (SImode,
4495 XEXP (operands[1], 0));
4496 MEM_COPY_ATTRIBUTES (new, operands[1]);
4497 emit_insn (gen_rotated_loadsi (reg, new));
4500 operands[1] = gen_lowpart (HImode, reg);
4504 emit_insn (gen_movhi_bigend (operands[0],
4512 /* Handle loading a large integer during reload */
4513 else if (GET_CODE (operands[1]) == CONST_INT
4514 && !const_ok_for_arm (INTVAL (operands[1]))
4515 && !const_ok_for_arm (~INTVAL (operands[1])))
4517 /* Writing a constant to memory needs a scratch, which should
4518 be handled with SECONDARY_RELOADs. */
4519 if (GET_CODE (operands[0]) != REG)
4522 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4523 emit_insn (gen_movsi (operands[0], operands[1]));
4527 else /* TARGET_THUMB */
4529 if (!no_new_pseudos)
4531 if (GET_CODE (operands[0]) != REG)
4532 operands[1] = force_reg (HImode, operands[1]);
4534 /* ??? We shouldn't really get invalid addresses here, but this can
4535 happen if we are passed a SP (never OK for HImode/QImode) or
4536 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4537 HImode/QImode) relative address. */
4538 /* ??? This should perhaps be fixed elsewhere, for instance, in
4539 fixup_stack_1, by checking for other kinds of invalid addresses,
4540 e.g. a bare reference to a virtual register. This may confuse the
4541 alpha though, which must handle this case differently. */
4542 if (GET_CODE (operands[0]) == MEM
4543 && !memory_address_p (GET_MODE (operands[0]),
4544 XEXP (operands[0], 0)))
4546 rtx temp = copy_to_reg (XEXP (operands[0], 0));
4547 operands[0] = change_address (operands[0], VOIDmode, temp);
4550 if (GET_CODE (operands[1]) == MEM
4551 && !memory_address_p (GET_MODE (operands[1]),
4552 XEXP (operands[1], 0)))
4554 rtx temp = copy_to_reg (XEXP (operands[1], 0));
4555 operands[1] = change_address (operands[1], VOIDmode, temp);
4558 /* Handle loading a large integer during reload */
4559 else if (GET_CODE (operands[1]) == CONST_INT
4560 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4562 /* Writing a constant to memory needs a scratch, which should
4563 be handled with SECONDARY_RELOADs. */
4564 if (GET_CODE (operands[0]) != REG)
4567 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4568 emit_insn (gen_movsi (operands[0], operands[1]));
4575 (define_insn "*thumb_movhi_insn"
4576 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4577 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4579 && ( register_operand (operands[0], HImode)
4580 || register_operand (operands[1], HImode))"
4582 switch (which_alternative)
4584 case 0: return \"add %0, %1, #0\";
4585 case 2: return \"strh %1, %0\";
4586 case 3: return \"mov %0, %1\";
4587 case 4: return \"mov %0, %1\";
4588 case 5: return \"mov %0, %1\";
4591 /* The stack pointer can end up being taken as an index register.
4592 Catch this case here and deal with it. */
4593 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4594 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4595 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4598 ops[0] = operands[0];
4599 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4601 output_asm_insn (\"mov %0, %1\", ops);
4603 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4606 return \"ldrh %0, %1\";
4608 [(set_attr "length" "2,4,2,2,2,2")
4609 (set_attr "type" "*,load,store1,*,*,*")
4610 (set_attr "pool_range" "*,64,*,*,*,*")]
4614 (define_insn "rotated_loadsi"
4615 [(set (match_operand:SI 0 "s_register_operand" "=r")
4616 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4618 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4623 ops[0] = operands[0];
4624 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4625 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4628 [(set_attr "type" "load")
4629 (set_attr "predicable" "yes")]
4632 (define_expand "movhi_bytes"
4633 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4635 (zero_extend:SI (match_dup 6)))
4636 (set (match_operand:SI 0 "" "")
4637 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4642 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4644 mem1 = gen_rtx_MEM (QImode, addr);
4645 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4646 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4647 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4648 operands[0] = gen_lowpart (SImode, operands[0]);
4650 operands[2] = gen_reg_rtx (SImode);
4651 operands[3] = gen_reg_rtx (SImode);
4654 if (BYTES_BIG_ENDIAN)
4656 operands[4] = operands[2];
4657 operands[5] = operands[3];
4661 operands[4] = operands[3];
4662 operands[5] = operands[2];
4667 (define_expand "movhi_bigend"
4669 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4672 (ashiftrt:SI (match_dup 2) (const_int 16)))
4673 (set (match_operand:HI 0 "s_register_operand" "")
4674 (subreg:HI (match_dup 3) 0))]
4677 operands[2] = gen_reg_rtx (SImode);
4678 operands[3] = gen_reg_rtx (SImode);
4682 ;; Pattern to recognise insn generated default case above
4683 (define_insn "*movhi_insn_arch4"
4684 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4685 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4688 && (GET_CODE (operands[1]) != CONST_INT
4689 || const_ok_for_arm (INTVAL (operands[1]))
4690 || const_ok_for_arm (~INTVAL (operands[1])))"
4692 mov%?\\t%0, %1\\t%@ movhi
4693 mvn%?\\t%0, #%B1\\t%@ movhi
4694 str%?h\\t%1, %0\\t%@ movhi
4695 ldr%?h\\t%0, %1\\t%@ movhi"
4696 [(set_attr "type" "*,*,store1,load")
4697 (set_attr "predicable" "yes")
4698 (set_attr "pool_range" "*,*,*,256")
4699 (set_attr "neg_pool_range" "*,*,*,244")]
4702 (define_insn "*movhi_insn_littleend"
4703 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4704 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4707 && !BYTES_BIG_ENDIAN
4708 && !TARGET_MMU_TRAPS
4709 && (GET_CODE (operands[1]) != CONST_INT
4710 || const_ok_for_arm (INTVAL (operands[1]))
4711 || const_ok_for_arm (~INTVAL (operands[1])))"
4713 mov%?\\t%0, %1\\t%@ movhi
4714 mvn%?\\t%0, #%B1\\t%@ movhi
4715 ldr%?\\t%0, %1\\t%@ movhi"
4716 [(set_attr "type" "*,*,load")
4717 (set_attr "predicable" "yes")
4718 (set_attr "pool_range" "4096")
4719 (set_attr "neg_pool_range" "4084")]
4722 (define_insn "*movhi_insn_bigend"
4723 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4724 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4728 && !TARGET_MMU_TRAPS
4729 && (GET_CODE (operands[1]) != CONST_INT
4730 || const_ok_for_arm (INTVAL (operands[1]))
4731 || const_ok_for_arm (~INTVAL (operands[1])))"
4733 mov%?\\t%0, %1\\t%@ movhi
4734 mvn%?\\t%0, #%B1\\t%@ movhi
4735 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4736 [(set_attr "type" "*,*,load")
4737 (set_attr "predicable" "yes")
4738 (set_attr "length" "4,4,8")
4739 (set_attr "pool_range" "*,*,4092")
4740 (set_attr "neg_pool_range" "*,*,4084")]
4743 (define_insn "*loadhi_si_bigend"
4744 [(set (match_operand:SI 0 "s_register_operand" "=r")
4745 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4749 && !TARGET_MMU_TRAPS"
4750 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4751 [(set_attr "type" "load")
4752 (set_attr "predicable" "yes")
4753 (set_attr "pool_range" "4096")
4754 (set_attr "neg_pool_range" "4084")]
4757 (define_insn "*movhi_bytes"
4758 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4759 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4760 "TARGET_ARM && TARGET_MMU_TRAPS"
4762 mov%?\\t%0, %1\\t%@ movhi
4763 mvn%?\\t%0, #%B1\\t%@ movhi"
4764 [(set_attr "predicable" "yes")]
4767 (define_insn "thumb_movhi_clobber"
4768 [(set (match_operand:HI 0 "memory_operand" "=m")
4769 (match_operand:HI 1 "register_operand" "l"))
4770 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4776 ;; We use a DImode scratch because we may occasionally need an additional
4777 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4778 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4779 (define_expand "reload_outhi"
4780 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4781 (match_operand:HI 1 "s_register_operand" "r")
4782 (match_operand:DI 2 "s_register_operand" "=&l")])]
4785 arm_reload_out_hi (operands);
4787 thumb_reload_out_hi (operands);
4792 (define_expand "reload_inhi"
4793 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4794 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4795 (match_operand:DI 2 "s_register_operand" "=&r")])]
4796 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4799 arm_reload_in_hi (operands);
4801 thumb_reload_out_hi (operands);
4805 (define_expand "movqi"
4806 [(set (match_operand:QI 0 "general_operand" "")
4807 (match_operand:QI 1 "general_operand" ""))]
4812 /* Everything except mem = const or mem = mem can be done easily */
4814 if (!no_new_pseudos)
4816 if (GET_CODE (operands[1]) == CONST_INT)
4818 rtx reg = gen_reg_rtx (SImode);
4820 emit_insn (gen_movsi (reg, operands[1]));
4821 operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
4823 if (GET_CODE (operands[0]) == MEM)
4824 operands[1] = force_reg (QImode, operands[1]);
4827 else /* TARGET_THUMB */
4829 if (!no_new_pseudos)
4831 if (GET_CODE (operands[0]) != REG)
4832 operands[1] = force_reg (QImode, operands[1]);
4834 /* ??? We shouldn't really get invalid addresses here, but this can
4835 happen if we are passed a SP (never OK for HImode/QImode) or
4836 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4837 HImode/QImode) relative address. */
4838 /* ??? This should perhaps be fixed elsewhere, for instance, in
4839 fixup_stack_1, by checking for other kinds of invalid addresses,
4840 e.g. a bare reference to a virtual register. This may confuse the
4841 alpha though, which must handle this case differently. */
4842 if (GET_CODE (operands[0]) == MEM
4843 && !memory_address_p (GET_MODE (operands[0]),
4844 XEXP (operands[0], 0)))
4846 rtx temp = copy_to_reg (XEXP (operands[0], 0));
4847 operands[0] = change_address (operands[0], VOIDmode, temp);
4849 if (GET_CODE (operands[1]) == MEM
4850 && !memory_address_p (GET_MODE (operands[1]),
4851 XEXP (operands[1], 0)))
4853 rtx temp = copy_to_reg (XEXP (operands[1], 0));
4854 operands[1] = change_address (operands[1], VOIDmode, temp);
4857 /* Handle loading a large integer during reload */
4858 else if (GET_CODE (operands[1]) == CONST_INT
4859 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4861 /* Writing a constant to memory needs a scratch, which should
4862 be handled with SECONDARY_RELOADs. */
4863 if (GET_CODE (operands[0]) != REG)
4866 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4867 emit_insn (gen_movsi (operands[0], operands[1]));
4875 (define_insn "*arm_movqi_insn"
4876 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4877 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4879 && ( register_operand (operands[0], QImode)
4880 || register_operand (operands[1], QImode))"
4886 [(set_attr "type" "*,*,load,store1")
4887 (set_attr "predicable" "yes")]
4890 (define_insn "*thumb_movqi_insn"
4891 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4892 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4894 && ( register_operand (operands[0], QImode)
4895 || register_operand (operands[1], QImode))"
4903 [(set_attr "length" "2")
4904 (set_attr "type" "*,load,store1,*,*,*")
4905 (set_attr "pool_range" "*,32,*,*,*,*")]
4908 (define_expand "movsf"
4909 [(set (match_operand:SF 0 "general_operand" "")
4910 (match_operand:SF 1 "general_operand" ""))]
4915 if (GET_CODE (operands[0]) == MEM)
4916 operands[1] = force_reg (SFmode, operands[1]);
4918 else /* TARGET_THUMB */
4920 if (!no_new_pseudos)
4922 if (GET_CODE (operands[0]) != REG)
4923 operands[1] = force_reg (SFmode, operands[1]);
4930 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4931 (match_operand:SF 1 "immediate_operand" ""))]
4933 && !TARGET_HARD_FLOAT
4935 && GET_CODE (operands[1]) == CONST_DOUBLE"
4936 [(set (match_dup 2) (match_dup 3))]
4938 operands[2] = gen_lowpart (SImode, operands[0]);
4939 operands[3] = gen_lowpart (SImode, operands[1]);
4940 if (operands[2] == 0 || operands[3] == 0)
4945 (define_insn "*arm_movsf_hard_insn"
4946 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
4947 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4949 && TARGET_HARD_FLOAT
4950 && (GET_CODE (operands[0]) != MEM
4951 || register_operand (operands[1], SFmode))"
4957 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4958 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4960 ldr%?\\t%0, %1\\t%@ float
4961 str%?\\t%1, %0\\t%@ float"
4962 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4963 (set_attr "predicable" "yes")
4965 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4966 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4967 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4970 ;; Exactly the same as above, except that all `f' cases are deleted.
4971 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4972 ;; when -msoft-float.
4974 (define_insn "*arm_movsf_soft_insn"
4975 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4976 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4978 && TARGET_SOFT_FLOAT
4979 && (GET_CODE (operands[0]) != MEM
4980 || register_operand (operands[1], SFmode))"
4983 ldr%?\\t%0, %1\\t%@ float
4984 str%?\\t%1, %0\\t%@ float"
4985 [(set_attr "length" "4,4,4")
4986 (set_attr "predicable" "yes")
4987 (set_attr "type" "*,load,store1")
4988 (set_attr "pool_range" "*,4096,*")
4989 (set_attr "neg_pool_range" "*,4084,*")]
4992 ;;; ??? This should have alternatives for constants.
4993 (define_insn "*thumb_movsf_insn"
4994 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4995 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4997 && ( register_operand (operands[0], SFmode)
4998 || register_operand (operands[1], SFmode))"
5007 [(set_attr "length" "2")
5008 (set_attr "type" "*,load,store1,load,store1,*,*")
5009 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
5012 (define_expand "movdf"
5013 [(set (match_operand:DF 0 "general_operand" "")
5014 (match_operand:DF 1 "general_operand" ""))]
5019 if (GET_CODE (operands[0]) == MEM)
5020 operands[1] = force_reg (DFmode, operands[1]);
5022 else /* TARGET_THUMB */
5024 if (!no_new_pseudos)
5026 if (GET_CODE (operands[0]) != REG)
5027 operands[1] = force_reg (DFmode, operands[1]);
5033 ;; Reloading a df mode value stored in integer regs to memory can require a
5035 (define_expand "reload_outdf"
5036 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
5037 (match_operand:DF 1 "s_register_operand" "r")
5038 (match_operand:SI 2 "s_register_operand" "=&r")]
5042 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
5045 operands[2] = XEXP (operands[0], 0);
5046 else if (code == POST_INC || code == PRE_DEC)
5048 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
5049 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
5050 emit_insn (gen_movdi (operands[0], operands[1]));
5053 else if (code == PRE_INC)
5055 rtx reg = XEXP (XEXP (operands[0], 0), 0);
5057 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
5060 else if (code == POST_DEC)
5061 operands[2] = XEXP (XEXP (operands[0], 0), 0);
5063 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
5064 XEXP (XEXP (operands[0], 0), 1)));
5066 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
5069 if (code == POST_DEC)
5070 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
5076 (define_insn "*movdf_hard_insn"
5077 [(set (match_operand:DF 0 "nonimmediate_operand"
5078 "=r,Q,r,m,r, f, f,f, m,!f,!r")
5079 (match_operand:DF 1 "general_operand"
5080 "Q, r,r,r,mF,fG,H,mF,f,r, f"))]
5082 && TARGET_HARD_FLOAT
5083 && (GET_CODE (operands[0]) != MEM
5084 || register_operand (operands[1], DFmode))"
5087 switch (which_alternative)
5090 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
5091 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
5092 case 2: case 3: case 4: return output_move_double (operands);
5093 case 5: return \"mvf%?d\\t%0, %1\";
5094 case 6: return \"mnf%?d\\t%0, #%N1\";
5095 case 7: return \"ldf%?d\\t%0, %1\";
5096 case 8: return \"stf%?d\\t%1, %0\";
5097 case 9: return output_mov_double_fpu_from_arm (operands);
5098 case 10: return output_mov_double_arm_from_fpu (operands);
5102 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
5103 (set_attr "predicable" "yes")
5105 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
5106 (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")
5107 (set_attr "neg_pool_range" "*,*,*,*,244,*,*,1012,*,*,*")]
5110 ;; Software floating point version. This is essentially the same as movdi.
5111 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
5114 (define_insn "*movdf_soft_insn"
5115 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
5116 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
5117 "TARGET_ARM && TARGET_SOFT_FLOAT
5119 "* return output_move_double (operands);"
5120 [(set_attr "length" "8,8,8")
5121 (set_attr "type" "*,load,store2")
5122 (set_attr "pool_range" "252")
5123 (set_attr "neg_pool_range" "244")]
5126 ;;; ??? This should have alternatives for constants.
5127 ;;; ??? This was originally identical to the movdi_insn pattern.
5128 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
5129 ;;; thumb_reorg with a memory reference.
5130 (define_insn "*thumb_movdf_insn"
5131 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
5132 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
5134 && ( register_operand (operands[0], DFmode)
5135 || register_operand (operands[1], DFmode))"
5137 switch (which_alternative)
5141 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5142 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
5143 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
5145 return \"ldmia\\t%1, {%0, %H0}\";
5147 return \"stmia\\t%0, {%1, %H1}\";
5149 return thumb_load_double_from_address (operands);
5151 operands[2] = gen_rtx (MEM, SImode,
5152 plus_constant (XEXP (operands[0], 0), 4));
5153 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5156 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5157 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5158 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5161 [(set_attr "length" "4,2,2,6,4,4")
5162 (set_attr "type" "*,load,store2,load,store2,*")
5163 (set_attr "pool_range" "*,*,*,1020,*,*")]
5167 (define_expand "movxf"
5168 [(set (match_operand:XF 0 "general_operand" "")
5169 (match_operand:XF 1 "general_operand" ""))]
5170 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5173 ;; Even when the XFmode patterns aren't enabled, we enable this after
5174 ;; reloading so that we can push floating point registers in the prologue.
5176 (define_insn "*movxf_hard_insn"
5177 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
5178 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
5179 "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
5181 switch (which_alternative)
5184 case 0: return \"mvf%?e\\t%0, %1\";
5185 case 1: return \"mnf%?e\\t%0, #%N1\";
5186 case 2: return \"ldf%?e\\t%0, %1\";
5187 case 3: return \"stf%?e\\t%1, %0\";
5188 case 4: return output_mov_long_double_fpu_from_arm (operands);
5189 case 5: return output_mov_long_double_arm_from_fpu (operands);
5190 case 6: return output_mov_long_double_arm_from_arm (operands);
5193 [(set_attr "length" "4,4,4,4,8,8,12")
5194 (set_attr "predicable" "yes")
5195 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
5196 (set_attr "pool_range" "*,*,1024,*,*,*,*")
5197 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*")]
5201 ;; load- and store-multiple insns
5202 ;; The arm can load/store any set of registers, provided that they are in
5203 ;; ascending order; but that is beyond GCC so stick with what it knows.
5205 (define_expand "load_multiple"
5206 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5207 (match_operand:SI 1 "" ""))
5208 (use (match_operand:SI 2 "" ""))])]
5211 /* Support only fixed point registers. */
5212 if (GET_CODE (operands[2]) != CONST_INT
5213 || INTVAL (operands[2]) > 14
5214 || INTVAL (operands[2]) < 2
5215 || GET_CODE (operands[1]) != MEM
5216 || GET_CODE (operands[0]) != REG
5217 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5218 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5222 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5223 force_reg (SImode, XEXP (operands[1], 0)),
5224 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5225 MEM_IN_STRUCT_P(operands[1]),
5226 MEM_SCALAR_P (operands[1]));
5230 ;; Load multiple with write-back
5232 (define_insn "*ldmsi_postinc4"
5233 [(match_parallel 0 "load_multiple_operation"
5234 [(set (match_operand:SI 1 "s_register_operand" "=r")
5235 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5237 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5238 (mem:SI (match_dup 2)))
5239 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5240 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5241 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5242 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5243 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5244 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5245 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5246 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5247 [(set_attr "type" "load")
5248 (set_attr "predicable" "yes")]
5251 (define_insn "*ldmsi_postinc3"
5252 [(match_parallel 0 "load_multiple_operation"
5253 [(set (match_operand:SI 1 "s_register_operand" "=r")
5254 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5256 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5257 (mem:SI (match_dup 2)))
5258 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5259 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5260 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5261 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5262 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5263 "ldm%?ia\\t%1!, {%3, %4, %5}"
5264 [(set_attr "type" "load")
5265 (set_attr "predicable" "yes")]
5268 (define_insn "*ldmsi_postinc2"
5269 [(match_parallel 0 "load_multiple_operation"
5270 [(set (match_operand:SI 1 "s_register_operand" "=r")
5271 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5273 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5274 (mem:SI (match_dup 2)))
5275 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5276 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5277 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5278 "ldm%?ia\\t%1!, {%3, %4}"
5279 [(set_attr "type" "load")
5280 (set_attr "predicable" "yes")]
5283 ;; Ordinary load multiple
5285 (define_insn "*ldmsi4"
5286 [(match_parallel 0 "load_multiple_operation"
5287 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5288 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5289 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5290 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5291 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5292 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5293 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5294 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5295 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5296 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5297 [(set_attr "type" "load")
5298 (set_attr "predicable" "yes")]
5301 (define_insn "*ldmsi3"
5302 [(match_parallel 0 "load_multiple_operation"
5303 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5304 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5305 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5306 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5307 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5308 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5309 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5310 "ldm%?ia\\t%1, {%2, %3, %4}"
5311 [(set_attr "type" "load")
5312 (set_attr "predicable" "yes")]
5315 (define_insn "*ldmsi2"
5316 [(match_parallel 0 "load_multiple_operation"
5317 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5318 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5319 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5320 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5321 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5322 "ldm%?ia\\t%1, {%2, %3}"
5323 [(set_attr "type" "load")
5324 (set_attr "predicable" "yes")]
5327 (define_expand "store_multiple"
5328 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5329 (match_operand:SI 1 "" ""))
5330 (use (match_operand:SI 2 "" ""))])]
5333 /* Support only fixed point registers */
5334 if (GET_CODE (operands[2]) != CONST_INT
5335 || INTVAL (operands[2]) > 14
5336 || INTVAL (operands[2]) < 2
5337 || GET_CODE (operands[1]) != REG
5338 || GET_CODE (operands[0]) != MEM
5339 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5340 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5344 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5345 force_reg (SImode, XEXP (operands[0], 0)),
5346 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5347 MEM_IN_STRUCT_P(operands[0]),
5348 MEM_SCALAR_P (operands[0]));
5352 ;; Store multiple with write-back
5354 (define_insn "*stmsi_postinc4"
5355 [(match_parallel 0 "store_multiple_operation"
5356 [(set (match_operand:SI 1 "s_register_operand" "=r")
5357 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5359 (set (mem:SI (match_dup 2))
5360 (match_operand:SI 3 "arm_hard_register_operand" ""))
5361 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5362 (match_operand:SI 4 "arm_hard_register_operand" ""))
5363 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5364 (match_operand:SI 5 "arm_hard_register_operand" ""))
5365 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5366 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5367 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5368 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5369 [(set_attr "predicable" "yes")
5370 (set_attr "type" "store4")]
5373 (define_insn "*stmsi_postinc3"
5374 [(match_parallel 0 "store_multiple_operation"
5375 [(set (match_operand:SI 1 "s_register_operand" "=r")
5376 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5378 (set (mem:SI (match_dup 2))
5379 (match_operand:SI 3 "arm_hard_register_operand" ""))
5380 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5381 (match_operand:SI 4 "arm_hard_register_operand" ""))
5382 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5383 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5384 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5385 "stm%?ia\\t%1!, {%3, %4, %5}"
5386 [(set_attr "predicable" "yes")
5387 (set_attr "type" "store3")]
5390 (define_insn "*stmsi_postinc2"
5391 [(match_parallel 0 "store_multiple_operation"
5392 [(set (match_operand:SI 1 "s_register_operand" "=r")
5393 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5395 (set (mem:SI (match_dup 2))
5396 (match_operand:SI 3 "arm_hard_register_operand" ""))
5397 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5398 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5399 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5400 "stm%?ia\\t%1!, {%3, %4}"
5401 [(set_attr "predicable" "yes")
5402 (set_attr "type" "store2")]
5405 ;; Ordinary store multiple
5407 (define_insn "*stmsi4"
5408 [(match_parallel 0 "store_multiple_operation"
5409 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5410 (match_operand:SI 2 "arm_hard_register_operand" ""))
5411 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5412 (match_operand:SI 3 "arm_hard_register_operand" ""))
5413 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5414 (match_operand:SI 4 "arm_hard_register_operand" ""))
5415 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5416 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5417 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5418 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5419 [(set_attr "predicable" "yes")
5420 (set_attr "type" "store4")]
5423 (define_insn "*stmsi3"
5424 [(match_parallel 0 "store_multiple_operation"
5425 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5426 (match_operand:SI 2 "arm_hard_register_operand" ""))
5427 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5428 (match_operand:SI 3 "arm_hard_register_operand" ""))
5429 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5430 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5431 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5432 "stm%?ia\\t%1, {%2, %3, %4}"
5433 [(set_attr "predicable" "yes")
5434 (set_attr "type" "store3")]
5437 (define_insn "*stmsi2"
5438 [(match_parallel 0 "store_multiple_operation"
5439 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5440 (match_operand:SI 2 "arm_hard_register_operand" ""))
5441 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5442 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5443 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5444 "stm%?ia\\t%1, {%2, %3}"
5445 [(set_attr "predicable" "yes")
5446 (set_attr "type" "store2")]
5449 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5450 ;; We could let this apply for blocks of less than this, but it clobbers so
5451 ;; many registers that there is then probably a better way.
5453 (define_expand "movstrqi"
5454 [(match_operand:BLK 0 "general_operand" "")
5455 (match_operand:BLK 1 "general_operand" "")
5456 (match_operand:SI 2 "const_int_operand" "")
5457 (match_operand:SI 3 "const_int_operand" "")]
5462 if (arm_gen_movstrqi (operands))
5466 else /* TARGET_THUMB */
5468 if ( INTVAL (operands[3]) != 4
5469 || INTVAL (operands[2]) > 48)
5472 thumb_expand_movstrqi (operands);
5478 ;; Thumb block-move insns
5480 (define_insn "movmem12b"
5481 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5482 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5483 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5484 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5485 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5486 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5487 (set (match_operand:SI 0 "register_operand" "=l")
5488 (plus:SI (match_dup 2) (const_int 12)))
5489 (set (match_operand:SI 1 "register_operand" "=l")
5490 (plus:SI (match_dup 3) (const_int 12)))
5491 (clobber (match_scratch:SI 4 "=&l"))
5492 (clobber (match_scratch:SI 5 "=&l"))
5493 (clobber (match_scratch:SI 6 "=&l"))]
5495 "* return thumb_output_move_mem_multiple (3, operands);"
5496 [(set_attr "length" "4")
5497 ; This isn't entirely accurate... It loads as well, but in terms of
5498 ; scheduling the following insn it is better to consider it as a store
5499 (set_attr "type" "store3")]
5502 (define_insn "movmem8b"
5503 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5504 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5505 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5506 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5507 (set (match_operand:SI 0 "register_operand" "=l")
5508 (plus:SI (match_dup 2) (const_int 8)))
5509 (set (match_operand:SI 1 "register_operand" "=l")
5510 (plus:SI (match_dup 3) (const_int 8)))
5511 (clobber (match_scratch:SI 4 "=&l"))
5512 (clobber (match_scratch:SI 5 "=&l"))]
5514 "* return thumb_output_move_mem_multiple (2, operands);"
5515 [(set_attr "length" "4")
5516 ; This isn't entirely accurate... It loads as well, but in terms of
5517 ; scheduling the following insn it is better to consider it as a store
5518 (set_attr "type" "store2")]
5523 ;; Compare & branch insns
5524 ;; The range calcualations are based as follows:
5525 ;; For forward branches, the address calculation returns the address of
5526 ;; the next instruction. This is 2 beyond the branch instruction.
5527 ;; For backward branches, the address calculation returns the address of
5528 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5529 ;; instruction for the shortest sequence, and 4 before the branch instruction
5530 ;; if we have to jump around an unconditional branch.
5531 ;; To the basic branch range the PC offset must be added (this is +4).
5532 ;; So for forward branches we have
5533 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5534 ;; And for backward branches we have
5535 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5537 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5538 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5540 (define_insn "cbranchsi4"
5543 (match_operator 0 "arm_comparison_operator"
5544 [(match_operand:SI 1 "register_operand" "l,r")
5545 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5546 (label_ref (match_operand 3 "" ""))
5550 output_asm_insn (\"cmp\\t%1, %2\", operands);
5551 switch (get_attr_length (insn))
5553 case 4: return \"b%d0\\t%l3\";
5554 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5555 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5558 [(set (attr "far_jump")
5560 (eq_attr "length" "8")
5561 (const_string "yes")
5562 (const_string "no")))
5563 (set (attr "length")
5565 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5566 (le (minus (match_dup 3) (pc)) (const_int 256)))
5569 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5570 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5575 (define_insn "*negated_cbranchsi4"
5578 (match_operator 0 "arm_comparison_operator"
5579 [(match_operand:SI 1 "register_operand" "l")
5580 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5581 (label_ref (match_operand 3 "" ""))
5585 output_asm_insn (\"cmn\\t%1, %2\", operands);
5586 switch (get_attr_length (insn))
5588 case 4: return \"b%d0\\t%l3\";
5589 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5590 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5593 [(set (attr "far_jump")
5595 (eq_attr "length" "8")
5596 (const_string "yes")
5597 (const_string "no")))
5598 (set (attr "length")
5600 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5601 (le (minus (match_dup 3) (pc)) (const_int 256)))
5604 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5605 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5611 ;; Comparison and test insns
5613 (define_expand "cmpsi"
5614 [(match_operand:SI 0 "s_register_operand" "")
5615 (match_operand:SI 1 "arm_add_operand" "")]
5618 arm_compare_op0 = operands[0];
5619 arm_compare_op1 = operands[1];
5624 (define_expand "cmpsf"
5625 [(match_operand:SF 0 "s_register_operand" "")
5626 (match_operand:SF 1 "fpu_rhs_operand" "")]
5627 "TARGET_ARM && TARGET_HARD_FLOAT"
5629 arm_compare_op0 = operands[0];
5630 arm_compare_op1 = operands[1];
5635 (define_expand "cmpdf"
5636 [(match_operand:DF 0 "s_register_operand" "")
5637 (match_operand:DF 1 "fpu_rhs_operand" "")]
5638 "TARGET_ARM && TARGET_HARD_FLOAT"
5640 arm_compare_op0 = operands[0];
5641 arm_compare_op1 = operands[1];
5646 (define_expand "cmpxf"
5647 [(match_operand:XF 0 "s_register_operand" "")
5648 (match_operand:XF 1 "fpu_rhs_operand" "")]
5649 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5651 arm_compare_op0 = operands[0];
5652 arm_compare_op1 = operands[1];
5657 (define_insn "*arm_cmpsi_insn"
5658 [(set (reg:CC CC_REGNUM)
5659 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5660 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5665 [(set_attr "conds" "set")]
5668 (define_insn "*cmpsi_shiftsi"
5669 [(set (reg:CC CC_REGNUM)
5670 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5671 (match_operator:SI 3 "shift_operator"
5672 [(match_operand:SI 1 "s_register_operand" "r")
5673 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5676 [(set_attr "conds" "set")
5677 (set_attr "shift" "1")
5681 (define_insn "*cmpsi_shiftsi_swp"
5682 [(set (reg:CC_SWP CC_REGNUM)
5683 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5684 [(match_operand:SI 1 "s_register_operand" "r")
5685 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5686 (match_operand:SI 0 "s_register_operand" "r")))]
5689 [(set_attr "conds" "set")
5690 (set_attr "shift" "1")
5694 (define_insn "*cmpsi_neg_shiftsi"
5695 [(set (reg:CC CC_REGNUM)
5696 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5697 (neg:SI (match_operator:SI 3 "shift_operator"
5698 [(match_operand:SI 1 "s_register_operand" "r")
5699 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5702 [(set_attr "conds" "set")
5703 (set_attr "shift" "1")
5707 (define_insn "*cmpsf_insn"
5708 [(set (reg:CCFP CC_REGNUM)
5709 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5710 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5711 "TARGET_ARM && TARGET_HARD_FLOAT"
5715 [(set_attr "conds" "set")
5716 (set_attr "type" "f_2_r")]
5719 (define_insn "*cmpdf_insn"
5720 [(set (reg:CCFP CC_REGNUM)
5721 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5722 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5723 "TARGET_ARM && TARGET_HARD_FLOAT"
5727 [(set_attr "conds" "set")
5728 (set_attr "type" "f_2_r")]
5731 (define_insn "*cmpesfdf_df"
5732 [(set (reg:CCFP CC_REGNUM)
5733 (compare:CCFP (float_extend:DF
5734 (match_operand:SF 0 "s_register_operand" "f,f"))
5735 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5736 "TARGET_ARM && TARGET_HARD_FLOAT"
5740 [(set_attr "conds" "set")
5741 (set_attr "type" "f_2_r")]
5744 (define_insn "*cmpdf_esfdf"
5745 [(set (reg:CCFP CC_REGNUM)
5746 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5748 (match_operand:SF 1 "s_register_operand" "f"))))]
5749 "TARGET_ARM && TARGET_HARD_FLOAT"
5751 [(set_attr "conds" "set")
5752 (set_attr "type" "f_2_r")]
5755 (define_insn "*cmpxf_insn"
5756 [(set (reg:CCFP CC_REGNUM)
5757 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5758 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5759 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5763 [(set_attr "conds" "set")
5764 (set_attr "type" "f_2_r")]
5767 (define_insn "*cmpsf_trap"
5768 [(set (reg:CCFPE CC_REGNUM)
5769 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5770 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5771 "TARGET_ARM && TARGET_HARD_FLOAT"
5775 [(set_attr "conds" "set")
5776 (set_attr "type" "f_2_r")]
5779 (define_insn "*cmpdf_trap"
5780 [(set (reg:CCFPE CC_REGNUM)
5781 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5782 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5783 "TARGET_ARM && TARGET_HARD_FLOAT"
5787 [(set_attr "conds" "set")
5788 (set_attr "type" "f_2_r")]
5791 (define_insn "*cmp_esfdf_df_trap"
5792 [(set (reg:CCFPE CC_REGNUM)
5793 (compare:CCFPE (float_extend:DF
5794 (match_operand:SF 0 "s_register_operand" "f,f"))
5795 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5796 "TARGET_ARM && TARGET_HARD_FLOAT"
5800 [(set_attr "conds" "set")
5801 (set_attr "type" "f_2_r")]
5804 (define_insn "*cmp_df_esfdf_trap"
5805 [(set (reg:CCFPE CC_REGNUM)
5806 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5808 (match_operand:SF 1 "s_register_operand" "f"))))]
5809 "TARGET_ARM && TARGET_HARD_FLOAT"
5811 [(set_attr "conds" "set")
5812 (set_attr "type" "f_2_r")]
5815 (define_insn "*cmpxf_trap"
5816 [(set (reg:CCFPE CC_REGNUM)
5817 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5818 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5819 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5823 [(set_attr "conds" "set")
5824 (set_attr "type" "f_2_r")]
5827 ; This insn allows redundant compares to be removed by cse, nothing should
5828 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5829 ; is deleted later on. The match_dup will match the mode here, so that
5830 ; mode changes of the condition codes aren't lost by this even though we don't
5831 ; specify what they are.
5833 (define_insn "*deleted_compare"
5834 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5836 "\\t%@ deleted compare"
5837 [(set_attr "conds" "set")
5838 (set_attr "length" "0")]
5842 ;; Conditional branch insns
5844 (define_expand "beq"
5846 (if_then_else (eq (match_dup 1) (const_int 0))
5847 (label_ref (match_operand 0 "" ""))
5850 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5853 (define_expand "bne"
5855 (if_then_else (ne (match_dup 1) (const_int 0))
5856 (label_ref (match_operand 0 "" ""))
5859 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5862 (define_expand "bgt"
5864 (if_then_else (gt (match_dup 1) (const_int 0))
5865 (label_ref (match_operand 0 "" ""))
5868 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5871 (define_expand "ble"
5873 (if_then_else (le (match_dup 1) (const_int 0))
5874 (label_ref (match_operand 0 "" ""))
5877 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5880 (define_expand "bge"
5882 (if_then_else (ge (match_dup 1) (const_int 0))
5883 (label_ref (match_operand 0 "" ""))
5886 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5889 (define_expand "blt"
5891 (if_then_else (lt (match_dup 1) (const_int 0))
5892 (label_ref (match_operand 0 "" ""))
5895 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5898 (define_expand "bgtu"
5900 (if_then_else (gtu (match_dup 1) (const_int 0))
5901 (label_ref (match_operand 0 "" ""))
5904 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5907 (define_expand "bleu"
5909 (if_then_else (leu (match_dup 1) (const_int 0))
5910 (label_ref (match_operand 0 "" ""))
5913 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5916 (define_expand "bgeu"
5918 (if_then_else (geu (match_dup 1) (const_int 0))
5919 (label_ref (match_operand 0 "" ""))
5922 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5925 (define_expand "bltu"
5927 (if_then_else (ltu (match_dup 1) (const_int 0))
5928 (label_ref (match_operand 0 "" ""))
5931 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5934 (define_expand "bunordered"
5936 (if_then_else (unordered (match_dup 1) (const_int 0))
5937 (label_ref (match_operand 0 "" ""))
5939 "TARGET_ARM && TARGET_HARD_FLOAT"
5940 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5944 (define_expand "bordered"
5946 (if_then_else (ordered (match_dup 1) (const_int 0))
5947 (label_ref (match_operand 0 "" ""))
5949 "TARGET_ARM && TARGET_HARD_FLOAT"
5950 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5954 (define_expand "bungt"
5956 (if_then_else (ungt (match_dup 1) (const_int 0))
5957 (label_ref (match_operand 0 "" ""))
5959 "TARGET_ARM && TARGET_HARD_FLOAT"
5960 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5963 (define_expand "bunlt"
5965 (if_then_else (unlt (match_dup 1) (const_int 0))
5966 (label_ref (match_operand 0 "" ""))
5968 "TARGET_ARM && TARGET_HARD_FLOAT"
5969 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5972 (define_expand "bunge"
5974 (if_then_else (unge (match_dup 1) (const_int 0))
5975 (label_ref (match_operand 0 "" ""))
5977 "TARGET_ARM && TARGET_HARD_FLOAT"
5978 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5981 (define_expand "bunle"
5983 (if_then_else (unle (match_dup 1) (const_int 0))
5984 (label_ref (match_operand 0 "" ""))
5986 "TARGET_ARM && TARGET_HARD_FLOAT"
5987 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5990 ;; The following two patterns need two branch instructions, since there is
5991 ;; no single instruction that will handle all cases.
5992 (define_expand "buneq"
5994 (if_then_else (uneq (match_dup 1) (const_int 0))
5995 (label_ref (match_operand 0 "" ""))
5997 "TARGET_ARM && TARGET_HARD_FLOAT"
5998 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6001 (define_expand "bltgt"
6003 (if_then_else (ltgt (match_dup 1) (const_int 0))
6004 (label_ref (match_operand 0 "" ""))
6006 "TARGET_ARM && TARGET_HARD_FLOAT"
6007 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6011 ;; Patterns to match conditional branch insns.
6014 ; Special pattern to match UNEQ.
6015 (define_insn "*arm_buneq"
6017 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6018 (label_ref (match_operand 0 "" ""))
6020 "TARGET_ARM && TARGET_HARD_FLOAT"
6022 if (arm_ccfsm_state != 0)
6025 return \"bvs\\t%l0;beq\\t%l0\";
6027 [(set_attr "conds" "jump_clob")
6028 (set_attr "length" "8")]
6031 ; Special pattern to match LTGT.
6032 (define_insn "*arm_bltgt"
6034 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6035 (label_ref (match_operand 0 "" ""))
6037 "TARGET_ARM && TARGET_HARD_FLOAT"
6039 if (arm_ccfsm_state != 0)
6042 return \"bmi\\t%l0;bgt\\t%l0\";
6044 [(set_attr "conds" "jump_clob")
6045 (set_attr "length" "8")]
6048 (define_insn "*arm_cond_branch"
6050 (if_then_else (match_operator 1 "arm_comparison_operator"
6051 [(match_operand 2 "cc_register" "") (const_int 0)])
6052 (label_ref (match_operand 0 "" ""))
6056 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6058 arm_ccfsm_state += 2;
6061 return \"b%d1\\t%l0\";
6063 [(set_attr "conds" "use")]
6066 ; Special pattern to match reversed UNEQ.
6067 (define_insn "*arm_buneq_reversed"
6069 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6071 (label_ref (match_operand 0 "" ""))))]
6072 "TARGET_ARM && TARGET_HARD_FLOAT"
6074 if (arm_ccfsm_state != 0)
6077 return \"bmi\\t%l0;bgt\\t%l0\";
6079 [(set_attr "conds" "jump_clob")
6080 (set_attr "length" "8")]
6083 ; Special pattern to match reversed LTGT.
6084 (define_insn "*arm_bltgt_reversed"
6086 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6088 (label_ref (match_operand 0 "" ""))))]
6089 "TARGET_ARM && TARGET_HARD_FLOAT"
6091 if (arm_ccfsm_state != 0)
6094 return \"bvs\\t%l0;beq\\t%l0\";
6096 [(set_attr "conds" "jump_clob")
6097 (set_attr "length" "8")]
6100 (define_insn "*arm_cond_branch_reversed"
6102 (if_then_else (match_operator 1 "arm_comparison_operator"
6103 [(match_operand 2 "cc_register" "") (const_int 0)])
6105 (label_ref (match_operand 0 "" ""))))]
6108 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6110 arm_ccfsm_state += 2;
6113 return \"b%D1\\t%l0\";
6115 [(set_attr "conds" "use")]
6122 (define_expand "seq"
6123 [(set (match_operand:SI 0 "s_register_operand" "=r")
6124 (eq:SI (match_dup 1) (const_int 0)))]
6126 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6129 (define_expand "sne"
6130 [(set (match_operand:SI 0 "s_register_operand" "=r")
6131 (ne:SI (match_dup 1) (const_int 0)))]
6133 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6136 (define_expand "sgt"
6137 [(set (match_operand:SI 0 "s_register_operand" "=r")
6138 (gt:SI (match_dup 1) (const_int 0)))]
6140 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6143 (define_expand "sle"
6144 [(set (match_operand:SI 0 "s_register_operand" "=r")
6145 (le:SI (match_dup 1) (const_int 0)))]
6147 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6150 (define_expand "sge"
6151 [(set (match_operand:SI 0 "s_register_operand" "=r")
6152 (ge:SI (match_dup 1) (const_int 0)))]
6154 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6157 (define_expand "slt"
6158 [(set (match_operand:SI 0 "s_register_operand" "=r")
6159 (lt:SI (match_dup 1) (const_int 0)))]
6161 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6164 (define_expand "sgtu"
6165 [(set (match_operand:SI 0 "s_register_operand" "=r")
6166 (gtu:SI (match_dup 1) (const_int 0)))]
6168 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6171 (define_expand "sleu"
6172 [(set (match_operand:SI 0 "s_register_operand" "=r")
6173 (leu:SI (match_dup 1) (const_int 0)))]
6175 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6178 (define_expand "sgeu"
6179 [(set (match_operand:SI 0 "s_register_operand" "=r")
6180 (geu:SI (match_dup 1) (const_int 0)))]
6182 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6185 (define_expand "sltu"
6186 [(set (match_operand:SI 0 "s_register_operand" "=r")
6187 (ltu:SI (match_dup 1) (const_int 0)))]
6189 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6192 (define_expand "sunordered"
6193 [(set (match_operand:SI 0 "s_register_operand" "=r")
6194 (unordered:SI (match_dup 1) (const_int 0)))]
6195 "TARGET_ARM && TARGET_HARD_FLOAT"
6196 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6200 (define_expand "sordered"
6201 [(set (match_operand:SI 0 "s_register_operand" "=r")
6202 (ordered:SI (match_dup 1) (const_int 0)))]
6203 "TARGET_ARM && TARGET_HARD_FLOAT"
6204 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6208 (define_expand "sungt"
6209 [(set (match_operand:SI 0 "s_register_operand" "=r")
6210 (ungt:SI (match_dup 1) (const_int 0)))]
6211 "TARGET_ARM && TARGET_HARD_FLOAT"
6212 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6216 (define_expand "sunge"
6217 [(set (match_operand:SI 0 "s_register_operand" "=r")
6218 (unge:SI (match_dup 1) (const_int 0)))]
6219 "TARGET_ARM && TARGET_HARD_FLOAT"
6220 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6224 (define_expand "sunlt"
6225 [(set (match_operand:SI 0 "s_register_operand" "=r")
6226 (unlt:SI (match_dup 1) (const_int 0)))]
6227 "TARGET_ARM && TARGET_HARD_FLOAT"
6228 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6232 (define_expand "sunle"
6233 [(set (match_operand:SI 0 "s_register_operand" "=r")
6234 (unle:SI (match_dup 1) (const_int 0)))]
6235 "TARGET_ARM && TARGET_HARD_FLOAT"
6236 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6240 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6241 ;;; simple ARM instructions.
6243 ; (define_expand "suneq"
6244 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6245 ; (uneq:SI (match_dup 1) (const_int 0)))]
6246 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6250 ; (define_expand "sltgt"
6251 ; [(set (match_operand:SI 0 "s_register_operand" "=r")
6252 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6253 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6257 (define_insn "*mov_scc"
6258 [(set (match_operand:SI 0 "s_register_operand" "=r")
6259 (match_operator:SI 1 "arm_comparison_operator"
6260 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6262 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6263 [(set_attr "conds" "use")
6264 (set_attr "length" "8")]
6267 (define_insn "*mov_negscc"
6268 [(set (match_operand:SI 0 "s_register_operand" "=r")
6269 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6270 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6272 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6273 [(set_attr "conds" "use")
6274 (set_attr "length" "8")]
6277 (define_insn "*mov_notscc"
6278 [(set (match_operand:SI 0 "s_register_operand" "=r")
6279 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6280 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6282 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6283 [(set_attr "conds" "use")
6284 (set_attr "length" "8")]
6288 ;; Conditional move insns
6290 (define_expand "movsicc"
6291 [(set (match_operand:SI 0 "s_register_operand" "")
6292 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6293 (match_operand:SI 2 "arm_not_operand" "")
6294 (match_operand:SI 3 "arm_not_operand" "")))]
6298 enum rtx_code code = GET_CODE (operands[1]);
6299 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6301 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6305 (define_expand "movsfcc"
6306 [(set (match_operand:SF 0 "s_register_operand" "")
6307 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6308 (match_operand:SF 2 "s_register_operand" "")
6309 (match_operand:SF 3 "nonmemory_operand" "")))]
6313 enum rtx_code code = GET_CODE (operands[1]);
6316 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6317 Otherwise, ensure it is a valid FP add operand */
6318 if ((!TARGET_HARD_FLOAT)
6319 || (!fpu_add_operand (operands[3], SFmode)))
6320 operands[3] = force_reg (SFmode, operands[3]);
6322 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6323 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6327 (define_expand "movdfcc"
6328 [(set (match_operand:DF 0 "s_register_operand" "")
6329 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6330 (match_operand:DF 2 "s_register_operand" "")
6331 (match_operand:DF 3 "fpu_add_operand" "")))]
6332 "TARGET_ARM && TARGET_HARD_FLOAT"
6335 enum rtx_code code = GET_CODE (operands[1]);
6336 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6338 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6342 (define_insn "*movsicc_insn"
6343 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6345 (match_operator 3 "arm_comparison_operator"
6346 [(match_operand 4 "cc_register" "") (const_int 0)])
6347 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6348 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6355 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6356 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6357 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6358 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6359 [(set_attr "length" "4,4,4,4,8,8,8,8")
6360 (set_attr "conds" "use")]
6363 (define_insn "*movsfcc_hard_insn"
6364 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6366 (match_operator 3 "arm_comparison_operator"
6367 [(match_operand 4 "cc_register" "") (const_int 0)])
6368 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6369 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6370 "TARGET_ARM && TARGET_HARD_FLOAT"
6376 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
6377 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
6378 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
6379 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
6380 [(set_attr "length" "4,4,4,4,8,8,8,8")
6381 (set_attr "type" "ffarith")
6382 (set_attr "conds" "use")]
6385 (define_insn "*movsfcc_soft_insn"
6386 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6387 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6388 [(match_operand 4 "cc_register" "") (const_int 0)])
6389 (match_operand:SF 1 "s_register_operand" "0,r")
6390 (match_operand:SF 2 "s_register_operand" "r,0")))]
6391 "TARGET_ARM && TARGET_SOFT_FLOAT"
6395 [(set_attr "conds" "use")]
6398 (define_insn "*movdfcc_insn"
6399 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
6401 (match_operator 3 "arm_comparison_operator"
6402 [(match_operand 4 "cc_register" "") (const_int 0)])
6403 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
6404 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
6405 "TARGET_ARM && TARGET_HARD_FLOAT"
6411 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
6412 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
6413 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
6414 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
6415 [(set_attr "length" "4,4,4,4,8,8,8,8")
6416 (set_attr "type" "ffarith")
6417 (set_attr "conds" "use")]
6421 ;; Jump and linkage insns
6423 (define_expand "jump"
6425 (label_ref (match_operand 0 "" "")))]
6430 (define_insn "*arm_jump"
6432 (label_ref (match_operand 0 "" "")))]
6436 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6438 arm_ccfsm_state += 2;
6441 return \"b%?\\t%l0\";
6444 [(set_attr "predicable" "yes")]
6447 (define_insn "*thumb_jump"
6449 (label_ref (match_operand 0 "" "")))]
6452 if (get_attr_length (insn) == 2)
6454 return \"bl\\t%l0\\t%@ far jump\";
6456 [(set (attr "far_jump")
6458 (eq_attr "length" "4")
6459 (const_string "yes")
6460 (const_string "no")))
6461 (set (attr "length")
6463 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6464 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6469 (define_expand "call"
6470 [(parallel [(call (match_operand 0 "memory_operand" "")
6471 (match_operand 1 "general_operand" ""))
6472 (use (match_operand 2 "" ""))
6473 (clobber (reg:SI LR_REGNUM))])]
6479 /* In an untyped call, we can get NULL for operand 2. */
6480 if (operands[2] == NULL_RTX)
6481 operands[2] = const0_rtx;
6483 /* This is to decide if we should generate indirect calls by loading the
6484 32 bit address of the callee into a register before performing the
6485 branch and link. operand[2] encodes the long_call/short_call
6486 attribute of the function being called. This attribute is set whenever
6487 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6488 is used, and the short_call attribute can also be set if function is
6489 declared as static or if it has already been defined in the current
6490 compilation unit. See arm.c and arm.h for info about this. The third
6491 parameter to arm_is_longcall_p is used to tell it which pattern
6493 callee = XEXP (operands[0], 0);
6495 if (GET_CODE (callee) != REG
6496 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6497 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6501 (define_insn "*call_reg"
6502 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6503 (match_operand 1 "" ""))
6504 (use (match_operand 2 "" ""))
6505 (clobber (reg:SI LR_REGNUM))]
6508 return output_call (operands);
6510 ;; length is worst case, normally it is only two
6511 [(set_attr "length" "12")
6512 (set_attr "type" "call")]
6515 (define_insn "*call_mem"
6516 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6517 (match_operand 1 "" ""))
6518 (use (match_operand 2 "" ""))
6519 (clobber (reg:SI LR_REGNUM))]
6522 return output_call_mem (operands);
6524 [(set_attr "length" "12")
6525 (set_attr "type" "call")]
6528 (define_insn "*call_indirect"
6529 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6530 (match_operand 1 "" ""))
6531 (use (match_operand 2 "" ""))
6532 (clobber (reg:SI LR_REGNUM))]
6536 if (TARGET_CALLER_INTERWORKING)
6537 return \"bl\\t%__interwork_call_via_%0\";
6539 return \"bl\\t%__call_via_%0\";
6541 [(set_attr "type" "call")]
6544 (define_insn "*call_value_indirect"
6545 [(set (match_operand 0 "" "=l")
6546 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6547 (match_operand 2 "" "")))
6548 (use (match_operand 3 "" ""))
6549 (clobber (reg:SI LR_REGNUM))]
6553 if (TARGET_CALLER_INTERWORKING)
6554 return \"bl\\t%__interwork_call_via_%1\";
6556 return \"bl\\t%__call_via_%1\";
6558 [(set_attr "type" "call")]
6561 (define_expand "call_value"
6562 [(parallel [(set (match_operand 0 "" "")
6563 (call (match_operand 1 "memory_operand" "")
6564 (match_operand 2 "general_operand" "")))
6565 (use (match_operand 3 "" ""))
6566 (clobber (reg:SI LR_REGNUM))])]
6570 rtx callee = XEXP (operands[1], 0);
6572 /* In an untyped call, we can get NULL for operand 2. */
6573 if (operands[3] == 0)
6574 operands[3] = const0_rtx;
6576 /* See the comment in define_expand \"call\". */
6577 if (GET_CODE (callee) != REG
6578 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6579 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6583 (define_insn "*call_value_reg"
6584 [(set (match_operand 0 "" "=r,f")
6585 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
6586 (match_operand 2 "" "")))
6587 (use (match_operand 3 "" ""))
6588 (clobber (reg:SI LR_REGNUM))]
6591 return output_call (&operands[1]);
6593 [(set_attr "length" "12")
6594 (set_attr "type" "call")]
6597 (define_insn "*call_value_mem"
6598 [(set (match_operand 0 "" "=r,f")
6599 (call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
6600 (match_operand 2 "" "")))
6601 (use (match_operand 3 "" ""))
6602 (clobber (reg:SI LR_REGNUM))]
6603 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6605 return output_call_mem (&operands[1]);
6607 [(set_attr "length" "12")
6608 (set_attr "type" "call")]
6611 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6612 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6614 (define_insn "*call_symbol"
6615 [(call (mem:SI (match_operand:SI 0 "" "X"))
6616 (match_operand 1 "" ""))
6617 (use (match_operand 2 "" ""))
6618 (clobber (reg:SI LR_REGNUM))]
6620 && (GET_CODE (operands[0]) == SYMBOL_REF)
6621 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6624 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6626 [(set_attr "type" "call")]
6629 (define_insn "*call_value_symbol"
6630 [(set (match_operand 0 "s_register_operand" "=r,f")
6631 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6632 (match_operand:SI 2 "" "")))
6633 (use (match_operand 3 "" ""))
6634 (clobber (reg:SI LR_REGNUM))]
6636 && (GET_CODE (operands[1]) == SYMBOL_REF)
6637 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6640 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6642 [(set_attr "type" "call")]
6645 (define_insn "*call_insn"
6646 [(call (mem:SI (match_operand:SI 0 "" "X"))
6647 (match_operand:SI 1 "" ""))
6648 (use (match_operand 2 "" ""))
6649 (clobber (reg:SI LR_REGNUM))]
6651 && operands[2] == const0_rtx && (GET_CODE (operands[0]) == SYMBOL_REF)"
6653 [(set_attr "length" "4")
6654 (set_attr "type" "call")]
6657 (define_insn "*call_value_insn"
6658 [(set (match_operand 0 "register_operand" "=l")
6659 (call (mem:SI (match_operand 1 "" "X"))
6660 (match_operand 2 "" "")))
6661 (use (match_operand 3 "" ""))
6662 (clobber (reg:SI LR_REGNUM))]
6664 && operands[3] == const0_rtx && (GET_CODE (operands[1]) == SYMBOL_REF)"
6666 [(set_attr "length" "4")
6667 (set_attr "type" "call")]
6670 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6671 (define_expand "sibcall"
6672 [(parallel [(call (match_operand 0 "memory_operand" "")
6673 (match_operand 1 "general_operand" ""))
6674 (use (match_operand 2 "" ""))
6675 (use (reg:SI LR_REGNUM))])]
6679 if (operands[2] == NULL_RTX)
6680 operands[2] = const0_rtx;
6684 (define_expand "sibcall_value"
6685 [(parallel [(set (match_operand 0 "register_operand" "")
6686 (call (match_operand 1 "memory_operand" "")
6687 (match_operand 2 "general_operand" "")))
6688 (use (match_operand 3 "" ""))
6689 (use (reg:SI LR_REGNUM))])]
6693 if (operands[3] == NULL_RTX)
6694 operands[3] = const0_rtx;
6698 (define_insn "*sibcall_insn"
6699 [(call (mem:SI (match_operand:SI 0 "" "X"))
6700 (match_operand 1 "" ""))
6701 (use (match_operand 2 "" ""))
6702 (use (reg:SI LR_REGNUM))]
6703 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6705 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6707 [(set_attr "type" "call")]
6710 (define_insn "*sibcall_value_insn"
6711 [(set (match_operand 0 "s_register_operand" "=r,f")
6712 (call (mem:SI (match_operand:SI 1 "" "X,X"))
6713 (match_operand 2 "" "")))
6714 (use (match_operand 3 "" ""))
6715 (use (reg:SI LR_REGNUM))]
6716 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6718 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6720 [(set_attr "type" "call")]
6723 ;; Often the return insn will be the same as loading from memory, so set attr
6724 (define_insn "return"
6726 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6729 if (arm_ccfsm_state == 2)
6731 arm_ccfsm_state += 2;
6734 return output_return_instruction (NULL, TRUE, FALSE);
6736 [(set_attr "type" "load")
6737 (set_attr "predicable" "yes")]
6740 (define_insn "*cond_return"
6742 (if_then_else (match_operator 0 "arm_comparison_operator"
6743 [(match_operand 1 "cc_register" "") (const_int 0)])
6746 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6749 if (arm_ccfsm_state == 2)
6751 arm_ccfsm_state += 2;
6754 return output_return_instruction (operands[0], TRUE, FALSE);
6756 [(set_attr "conds" "use")
6757 (set_attr "type" "load")]
6760 (define_insn "*cond_return_inverted"
6762 (if_then_else (match_operator 0 "arm_comparison_operator"
6763 [(match_operand 1 "cc_register" "") (const_int 0)])
6766 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6769 if (arm_ccfsm_state == 2)
6771 arm_ccfsm_state += 2;
6774 return output_return_instruction (operands[0], TRUE, TRUE);
6776 [(set_attr "conds" "use")
6777 (set_attr "type" "load")]
6780 ;; Call subroutine returning any type.
6782 (define_expand "untyped_call"
6783 [(parallel [(call (match_operand 0 "" "")
6785 (match_operand 1 "" "")
6786 (match_operand 2 "" "")])]
6792 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6794 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6796 rtx set = XVECEXP (operands[2], 0, i);
6798 emit_move_insn (SET_DEST (set), SET_SRC (set));
6801 /* The optimizer does not know that the call sets the function value
6802 registers we stored in the result block. We avoid problems by
6803 claiming that all hard registers are used and clobbered at this
6805 emit_insn (gen_blockage ());
6811 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6812 ;; all of memory. This blocks insns from being moved across this point.
6814 (define_insn "blockage"
6815 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6818 [(set_attr "length" "0")
6819 (set_attr "type" "block")]
6822 (define_expand "casesi"
6823 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6824 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6825 (match_operand:SI 2 "const_int_operand" "") ; total range
6826 (match_operand:SI 3 "" "") ; table label
6827 (match_operand:SI 4 "" "")] ; Out of range label
6832 if (operands[1] != const0_rtx)
6834 reg = gen_reg_rtx (SImode);
6836 emit_insn (gen_addsi3 (reg, operands[0],
6837 GEN_INT (-INTVAL (operands[1]))));
6841 if (!const_ok_for_arm (INTVAL (operands[2])))
6842 operands[2] = force_reg (SImode, operands[2]);
6844 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6850 ;; The USE in this pattern is needed to tell flow analysis that this is
6851 ;; a CASESI insn. It has no other purpose.
6852 (define_insn "casesi_internal"
6853 [(parallel [(set (pc)
6855 (leu (match_operand:SI 0 "s_register_operand" "r")
6856 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6857 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6858 (label_ref (match_operand 2 "" ""))))
6859 (label_ref (match_operand 3 "" ""))))
6860 (clobber (reg:CC CC_REGNUM))
6861 (use (label_ref (match_dup 2)))])]
6865 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6866 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6868 [(set_attr "conds" "clob")
6869 (set_attr "length" "12")]
6872 (define_expand "indirect_jump"
6874 (match_operand:SI 0 "s_register_operand" ""))]
6879 (define_insn "*arm_indirect_jump"
6881 (match_operand:SI 0 "s_register_operand" "r"))]
6883 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6884 [(set_attr "predicable" "yes")]
6887 ;; Although not supported by the define_expand above,
6888 ;; cse/combine may generate this form.
6889 (define_insn "*load_indirect_jump"
6891 (match_operand:SI 0 "memory_operand" "m"))]
6893 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6894 [(set_attr "type" "load")
6895 (set_attr "pool_range" "4096")
6896 (set_attr "neg_pool_range" "4084")
6897 (set_attr "predicable" "yes")]
6900 (define_insn "*thumb_indirect_jump"
6902 (match_operand:SI 0 "register_operand" "l*r"))]
6905 [(set_attr "conds" "clob")
6906 (set_attr "length" "2")]
6917 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6918 return \"mov\\tr8, r8\";
6920 [(set (attr "length")
6921 (if_then_else (eq_attr "is_thumb" "yes")
6927 ;; Patterns to allow combination of arithmetic, cond code and shifts
6929 (define_insn "*arith_shiftsi"
6930 [(set (match_operand:SI 0 "s_register_operand" "=r")
6931 (match_operator:SI 1 "shiftable_operator"
6932 [(match_operator:SI 3 "shift_operator"
6933 [(match_operand:SI 4 "s_register_operand" "r")
6934 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6935 (match_operand:SI 2 "s_register_operand" "r")]))]
6937 "%i1%?\\t%0, %2, %4%S3"
6938 [(set_attr "predicable" "yes")
6939 (set_attr "shift" "4")
6943 (define_insn "*arith_shiftsi_compare0"
6944 [(set (reg:CC_NOOV CC_REGNUM)
6945 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6946 [(match_operator:SI 3 "shift_operator"
6947 [(match_operand:SI 4 "s_register_operand" "r")
6948 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6949 (match_operand:SI 2 "s_register_operand" "r")])
6951 (set (match_operand:SI 0 "s_register_operand" "=r")
6952 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6955 "%i1%?s\\t%0, %2, %4%S3"
6956 [(set_attr "conds" "set")
6957 (set_attr "shift" "4")
6961 (define_insn "*arith_shiftsi_compare0_scratch"
6962 [(set (reg:CC_NOOV CC_REGNUM)
6963 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6964 [(match_operator:SI 3 "shift_operator"
6965 [(match_operand:SI 4 "s_register_operand" "r")
6966 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6967 (match_operand:SI 2 "s_register_operand" "r")])
6969 (clobber (match_scratch:SI 0 "=r"))]
6971 "%i1%?s\\t%0, %2, %4%S3"
6972 [(set_attr "conds" "set")
6973 (set_attr "shift" "4")
6977 (define_insn "*sub_shiftsi"
6978 [(set (match_operand:SI 0 "s_register_operand" "=r")
6979 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6980 (match_operator:SI 2 "shift_operator"
6981 [(match_operand:SI 3 "s_register_operand" "r")
6982 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6984 "sub%?\\t%0, %1, %3%S2"
6985 [(set_attr "predicable" "yes")
6986 (set_attr "shift" "3")
6990 (define_insn "*sub_shiftsi_compare0"
6991 [(set (reg:CC_NOOV CC_REGNUM)
6993 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6994 (match_operator:SI 2 "shift_operator"
6995 [(match_operand:SI 3 "s_register_operand" "r")
6996 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6998 (set (match_operand:SI 0 "s_register_operand" "=r")
6999 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7002 "sub%?s\\t%0, %1, %3%S2"
7003 [(set_attr "conds" "set")
7004 (set_attr "shift" "3")
7008 (define_insn "*sub_shiftsi_compare0_scratch"
7009 [(set (reg:CC_NOOV CC_REGNUM)
7011 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7012 (match_operator:SI 2 "shift_operator"
7013 [(match_operand:SI 3 "s_register_operand" "r")
7014 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7016 (clobber (match_scratch:SI 0 "=r"))]
7018 "sub%?s\\t%0, %1, %3%S2"
7019 [(set_attr "conds" "set")
7020 (set_attr "shift" "3")
7024 ;; These variants of the above insns can occur if the first operand is the
7025 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
7026 ;; seem to be a way around it. Most of the predicates have to be null
7027 ;; because the format can be generated part way through reload, so
7028 ;; if we don't match it as soon as it becomes available, reload doesn't know
7029 ;; how to reload pseudos that haven't got hard registers; the constraints will
7030 ;; sort everything out.
7032 (define_insn "*reload_mulsi3"
7033 [(set (match_operand:SI 0 "" "=&r")
7034 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
7035 [(match_operand:SI 3 "" "r")
7036 (match_operand:SI 4 "" "rM")])
7037 (match_operand:SI 2 "" "r"))
7038 (match_operand:SI 1 "const_int_operand" "n")))]
7039 "TARGET_ARM && reload_in_progress"
7041 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
7042 operands[2] = operands[1];
7043 operands[1] = operands[0];
7044 return output_add_immediate (operands);
7047 ; we have no idea how long the add_immediate is, it could be up to 4.
7048 (set_attr "length" "20")]
7051 (define_insn "*reload_mulsi_compare0"
7052 [(set (reg:CC_NOOV CC_REGNUM)
7053 (compare:CC_NOOV (plus:SI
7055 (match_operator:SI 5 "shift_operator"
7056 [(match_operand:SI 3 "" "r")
7057 (match_operand:SI 4 "" "rM")])
7058 (match_operand:SI 1 "" "r"))
7059 (match_operand:SI 2 "const_int_operand" "n"))
7061 (set (match_operand:SI 0 "" "=&r")
7062 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
7065 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7067 output_add_immediate (operands);
7068 return \"add%?s\\t%0, %0, %3%S5\";
7070 [(set_attr "conds" "set")
7071 (set_attr "shift" "3")
7072 (set_attr "length" "20")]
7075 (define_insn "*reload_mulsi_compare0_scratch"
7076 [(set (reg:CC_NOOV CC_REGNUM)
7077 (compare:CC_NOOV (plus:SI
7079 (match_operator:SI 5 "shift_operator"
7080 [(match_operand:SI 3 "" "r")
7081 (match_operand:SI 4 "" "rM")])
7082 (match_operand:SI 1 "" "r"))
7083 (match_operand:SI 2 "const_int_operand" "n"))
7085 (clobber (match_scratch:SI 0 "=&r"))]
7086 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7088 output_add_immediate (operands);
7089 return \"add%?s\\t%0, %0, %3%S5\";
7091 [(set_attr "conds" "set")
7092 (set_attr "shift" "3")
7093 (set_attr "length" "20")]
7096 ;; These are similar, but are needed when the mla pattern contains the
7097 ;; eliminated register as operand 3.
7099 (define_insn "*reload_muladdsi"
7100 [(set (match_operand:SI 0 "" "=&r,&r")
7101 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
7102 (match_operand:SI 2 "" "r,r"))
7103 (match_operand:SI 3 "" "r,r"))
7104 (match_operand:SI 4 "const_int_operand" "n,n")))]
7105 "TARGET_ARM && reload_in_progress"
7107 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
7108 operands[2] = operands[4];
7109 operands[1] = operands[0];
7110 return output_add_immediate (operands);
7112 [(set_attr "length" "20")
7113 (set_attr "type" "mult")]
7116 (define_insn "*reload_muladdsi_compare0"
7117 [(set (reg:CC_NOOV CC_REGNUM)
7118 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7119 (match_operand:SI 3 "" "r")
7120 (match_operand:SI 4 "" "r"))
7121 (match_operand:SI 1 "" "r"))
7122 (match_operand:SI 2 "const_int_operand" "n"))
7124 (set (match_operand:SI 0 "" "=&r")
7125 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
7127 "TARGET_ARM && reload_in_progress && !arm_is_xscale"
7129 output_add_immediate (operands);
7130 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
7133 [(set_attr "length" "20")
7134 (set_attr "conds" "set")
7135 (set_attr "type" "mult")]
7138 (define_insn "*reload_muladdsi_compare0_scratch"
7139 [(set (reg:CC_NOOV CC_REGNUM)
7140 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
7141 (match_operand:SI 3 "" "r")
7142 (match_operand:SI 4 "" "r"))
7143 (match_operand:SI 1 "" "r"))
7144 (match_operand:SI 2 "const_int_operand" "n"))
7146 (clobber (match_scratch:SI 0 "=&r"))]
7147 "TARGET_ARM && reload_in_progress"
7149 output_add_immediate (operands);
7150 return \"mla%?s\\t%0, %3, %4, %0\";
7152 [(set_attr "length" "20")
7153 (set_attr "conds" "set")
7154 (set_attr "type" "mult")]
7159 (define_insn "*and_scc"
7160 [(set (match_operand:SI 0 "s_register_operand" "=r")
7161 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7162 [(match_operand 3 "cc_register" "") (const_int 0)])
7163 (match_operand:SI 2 "s_register_operand" "r")))]
7165 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7166 [(set_attr "conds" "use")
7167 (set_attr "length" "8")]
7170 (define_insn "*ior_scc"
7171 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7172 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7173 [(match_operand 3 "cc_register" "") (const_int 0)])
7174 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7178 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7179 [(set_attr "conds" "use")
7180 (set_attr "length" "4,8")]
7183 (define_insn "*compare_scc"
7184 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7185 (match_operator:SI 1 "arm_comparison_operator"
7186 [(match_operand:SI 2 "s_register_operand" "r,r")
7187 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7188 (clobber (reg:CC CC_REGNUM))]
7191 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
7192 return \"mov\\t%0, %2, lsr #31\";
7194 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
7195 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7197 if (GET_CODE (operands[1]) == NE)
7199 if (which_alternative == 1)
7200 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7201 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7203 if (which_alternative == 1)
7204 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7206 output_asm_insn (\"cmp\\t%2, %3\", operands);
7207 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7209 [(set_attr "conds" "clob")
7210 (set_attr "length" "12")]
7213 (define_insn "*cond_move"
7214 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7215 (if_then_else:SI (match_operator 3 "equality_operator"
7216 [(match_operator 4 "arm_comparison_operator"
7217 [(match_operand 5 "cc_register" "") (const_int 0)])
7219 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7220 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7223 if (GET_CODE (operands[3]) == NE)
7225 if (which_alternative != 1)
7226 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7227 if (which_alternative != 0)
7228 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7231 if (which_alternative != 0)
7232 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7233 if (which_alternative != 1)
7234 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7237 [(set_attr "conds" "use")
7238 (set_attr "length" "4,4,8")]
7241 (define_insn "*cond_arith"
7242 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7243 (match_operator:SI 5 "shiftable_operator"
7244 [(match_operator:SI 4 "arm_comparison_operator"
7245 [(match_operand:SI 2 "s_register_operand" "r,r")
7246 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7247 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7248 (clobber (reg:CC CC_REGNUM))]
7251 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7252 return \"%i5\\t%0, %1, %2, lsr #31\";
7254 output_asm_insn (\"cmp\\t%2, %3\", operands);
7255 if (GET_CODE (operands[5]) == AND)
7256 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7257 else if (GET_CODE (operands[5]) == MINUS)
7258 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7259 else if (which_alternative != 0)
7260 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7261 return \"%i5%d4\\t%0, %1, #1\";
7263 [(set_attr "conds" "clob")
7264 (set_attr "length" "12")]
7267 (define_insn "*cond_sub"
7268 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7269 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7270 (match_operator:SI 4 "arm_comparison_operator"
7271 [(match_operand:SI 2 "s_register_operand" "r,r")
7272 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7273 (clobber (reg:CC CC_REGNUM))]
7276 output_asm_insn (\"cmp\\t%2, %3\", operands);
7277 if (which_alternative != 0)
7278 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7279 return \"sub%d4\\t%0, %1, #1\";
7281 [(set_attr "conds" "clob")
7282 (set_attr "length" "8,12")]
7285 (define_insn "*cmp_ite0"
7286 [(set (match_operand 6 "dominant_cc_register" "")
7289 (match_operator 4 "arm_comparison_operator"
7290 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7291 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7292 (match_operator:SI 5 "arm_comparison_operator"
7293 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7294 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7300 static const char * const opcodes[4][2] =
7302 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7303 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7304 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7305 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7306 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7307 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7308 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7309 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7312 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7314 return opcodes[which_alternative][swap];
7316 [(set_attr "conds" "set")
7317 (set_attr "length" "8")]
7320 (define_insn "*cmp_ite1"
7321 [(set (match_operand 6 "dominant_cc_register" "")
7324 (match_operator 4 "arm_comparison_operator"
7325 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7326 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7327 (match_operator:SI 5 "arm_comparison_operator"
7328 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7329 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7335 static const char * const opcodes[4][2] =
7337 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7338 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7339 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7340 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7341 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7342 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7343 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7344 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7347 comparison_dominates_p (GET_CODE (operands[5]),
7348 reverse_condition (GET_CODE (operands[4])));
7350 return opcodes[which_alternative][swap];
7352 [(set_attr "conds" "set")
7353 (set_attr "length" "8")]
7356 (define_insn "*cmp_and"
7357 [(set (match_operand 6 "dominant_cc_register" "")
7360 (match_operator 4 "arm_comparison_operator"
7361 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7362 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7363 (match_operator:SI 5 "arm_comparison_operator"
7364 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7365 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7370 const char * opcodes[4][2] =
7372 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7373 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7374 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7375 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7376 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7377 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7378 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7379 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7382 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7384 return opcodes[which_alternative][swap];
7386 [(set_attr "conds" "set")
7387 (set_attr "predicable" "no")
7388 (set_attr "length" "8")]
7391 (define_insn "*cmp_ior"
7392 [(set (match_operand 6 "dominant_cc_register" "")
7395 (match_operator 4 "arm_comparison_operator"
7396 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7397 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7398 (match_operator:SI 5 "arm_comparison_operator"
7399 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7400 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7405 const char * opcodes[4][2] =
7407 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7408 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7409 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7410 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7411 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7412 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7413 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7414 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7417 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7419 return opcodes[which_alternative][swap];
7422 [(set_attr "conds" "set")
7423 (set_attr "length" "8")]
7426 (define_insn "*negscc"
7427 [(set (match_operand:SI 0 "s_register_operand" "=r")
7428 (neg:SI (match_operator 3 "arm_comparison_operator"
7429 [(match_operand:SI 1 "s_register_operand" "r")
7430 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7431 (clobber (reg:CC CC_REGNUM))]
7434 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7435 return \"mov\\t%0, %1, asr #31\";
7437 if (GET_CODE (operands[3]) == NE)
7438 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7440 if (GET_CODE (operands[3]) == GT)
7441 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7443 output_asm_insn (\"cmp\\t%1, %2\", operands);
7444 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7445 return \"mvn%d3\\t%0, #0\";
7447 [(set_attr "conds" "clob")
7448 (set_attr "length" "12")]
7451 (define_insn "movcond"
7452 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7454 (match_operator 5 "arm_comparison_operator"
7455 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7456 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7457 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7458 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7459 (clobber (reg:CC CC_REGNUM))]
7462 if (GET_CODE (operands[5]) == LT
7463 && (operands[4] == const0_rtx))
7465 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7467 if (operands[2] == const0_rtx)
7468 return \"and\\t%0, %1, %3, asr #31\";
7469 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7471 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7473 if (operands[1] == const0_rtx)
7474 return \"bic\\t%0, %2, %3, asr #31\";
7475 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7477 /* The only case that falls through to here is when both ops 1 & 2
7481 if (GET_CODE (operands[5]) == GE
7482 && (operands[4] == const0_rtx))
7484 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7486 if (operands[2] == const0_rtx)
7487 return \"bic\\t%0, %1, %3, asr #31\";
7488 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7490 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7492 if (operands[1] == const0_rtx)
7493 return \"and\\t%0, %2, %3, asr #31\";
7494 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7496 /* The only case that falls through to here is when both ops 1 & 2
7499 if (GET_CODE (operands[4]) == CONST_INT
7500 && !const_ok_for_arm (INTVAL (operands[4])))
7501 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7503 output_asm_insn (\"cmp\\t%3, %4\", operands);
7504 if (which_alternative != 0)
7505 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7506 if (which_alternative != 1)
7507 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7510 [(set_attr "conds" "clob")
7511 (set_attr "length" "8,8,12")]
7514 (define_insn "*ifcompare_plus_move"
7515 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7516 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7517 [(match_operand:SI 4 "s_register_operand" "r,r")
7518 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7520 (match_operand:SI 2 "s_register_operand" "r,r")
7521 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7522 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7523 (clobber (reg:CC CC_REGNUM))]
7526 [(set_attr "conds" "clob")
7527 (set_attr "length" "8,12")]
7530 (define_insn "*if_plus_move"
7531 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7533 (match_operator 4 "arm_comparison_operator"
7534 [(match_operand 5 "cc_register" "") (const_int 0)])
7536 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7537 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7538 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7542 sub%d4\\t%0, %2, #%n3
7543 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7544 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7545 [(set_attr "conds" "use")
7546 (set_attr "length" "4,4,8,8")
7547 (set_attr "type" "*,*,*,*")]
7550 (define_insn "*ifcompare_move_plus"
7551 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7552 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7553 [(match_operand:SI 4 "s_register_operand" "r,r")
7554 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7555 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7557 (match_operand:SI 2 "s_register_operand" "r,r")
7558 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7559 (clobber (reg:CC CC_REGNUM))]
7562 [(set_attr "conds" "clob")
7563 (set_attr "length" "8,12")]
7566 (define_insn "*if_move_plus"
7567 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7569 (match_operator 4 "arm_comparison_operator"
7570 [(match_operand 5 "cc_register" "") (const_int 0)])
7571 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7573 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7574 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7578 sub%D4\\t%0, %2, #%n3
7579 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7580 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7581 [(set_attr "conds" "use")
7582 (set_attr "length" "4,4,8,8")
7583 (set_attr "type" "*,*,*,*")]
7586 (define_insn "*ifcompare_arith_arith"
7587 [(set (match_operand:SI 0 "s_register_operand" "=r")
7588 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7589 [(match_operand:SI 5 "s_register_operand" "r")
7590 (match_operand:SI 6 "arm_add_operand" "rIL")])
7591 (match_operator:SI 8 "shiftable_operator"
7592 [(match_operand:SI 1 "s_register_operand" "r")
7593 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7594 (match_operator:SI 7 "shiftable_operator"
7595 [(match_operand:SI 3 "s_register_operand" "r")
7596 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7597 (clobber (reg:CC CC_REGNUM))]
7600 [(set_attr "conds" "clob")
7601 (set_attr "length" "12")]
7604 (define_insn "*if_arith_arith"
7605 [(set (match_operand:SI 0 "s_register_operand" "=r")
7606 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7607 [(match_operand 8 "cc_register" "") (const_int 0)])
7608 (match_operator:SI 6 "shiftable_operator"
7609 [(match_operand:SI 1 "s_register_operand" "r")
7610 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7611 (match_operator:SI 7 "shiftable_operator"
7612 [(match_operand:SI 3 "s_register_operand" "r")
7613 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7615 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7616 [(set_attr "conds" "use")
7617 (set_attr "length" "8")]
7620 (define_insn "*ifcompare_arith_move"
7621 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7622 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7623 [(match_operand:SI 2 "s_register_operand" "r,r")
7624 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7625 (match_operator:SI 7 "shiftable_operator"
7626 [(match_operand:SI 4 "s_register_operand" "r,r")
7627 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7628 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7629 (clobber (reg:CC CC_REGNUM))]
7632 /* If we have an operation where (op x 0) is the identity operation and
7633 the conditional operator is LT or GE and we are comparing against zero and
7634 everything is in registers then we can do this in two instructions */
7635 if (operands[3] == const0_rtx
7636 && GET_CODE (operands[7]) != AND
7637 && GET_CODE (operands[5]) == REG
7638 && GET_CODE (operands[1]) == REG
7639 && REGNO (operands[1]) == REGNO (operands[4])
7640 && REGNO (operands[4]) != REGNO (operands[0]))
7642 if (GET_CODE (operands[6]) == LT)
7643 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7644 else if (GET_CODE (operands[6]) == GE)
7645 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7647 if (GET_CODE (operands[3]) == CONST_INT
7648 && !const_ok_for_arm (INTVAL (operands[3])))
7649 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7651 output_asm_insn (\"cmp\\t%2, %3\", operands);
7652 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7653 if (which_alternative != 0)
7654 return \"mov%D6\\t%0, %1\";
7657 [(set_attr "conds" "clob")
7658 (set_attr "length" "8,12")]
7661 (define_insn "*if_arith_move"
7662 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7663 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7664 [(match_operand 6 "cc_register" "") (const_int 0)])
7665 (match_operator:SI 5 "shiftable_operator"
7666 [(match_operand:SI 2 "s_register_operand" "r,r")
7667 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7668 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7672 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7673 [(set_attr "conds" "use")
7674 (set_attr "length" "4,8")
7675 (set_attr "type" "*,*")]
7678 (define_insn "*ifcompare_move_arith"
7679 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7680 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7681 [(match_operand:SI 4 "s_register_operand" "r,r")
7682 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7683 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7684 (match_operator:SI 7 "shiftable_operator"
7685 [(match_operand:SI 2 "s_register_operand" "r,r")
7686 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7687 (clobber (reg:CC CC_REGNUM))]
7690 /* If we have an operation where (op x 0) is the identity operation and
7691 the conditional operator is LT or GE and we are comparing against zero and
7692 everything is in registers then we can do this in two instructions */
7693 if (operands[5] == const0_rtx
7694 && GET_CODE (operands[7]) != AND
7695 && GET_CODE (operands[3]) == REG
7696 && GET_CODE (operands[1]) == REG
7697 && REGNO (operands[1]) == REGNO (operands[2])
7698 && REGNO (operands[2]) != REGNO (operands[0]))
7700 if (GET_CODE (operands[6]) == GE)
7701 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7702 else if (GET_CODE (operands[6]) == LT)
7703 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7706 if (GET_CODE (operands[5]) == CONST_INT
7707 && !const_ok_for_arm (INTVAL (operands[5])))
7708 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7710 output_asm_insn (\"cmp\\t%4, %5\", operands);
7712 if (which_alternative != 0)
7713 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7714 return \"%I7%D6\\t%0, %2, %3\";
7716 [(set_attr "conds" "clob")
7717 (set_attr "length" "8,12")]
7720 (define_insn "*if_move_arith"
7721 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7723 (match_operator 4 "arm_comparison_operator"
7724 [(match_operand 6 "cc_register" "") (const_int 0)])
7725 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7726 (match_operator:SI 5 "shiftable_operator"
7727 [(match_operand:SI 2 "s_register_operand" "r,r")
7728 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7732 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7733 [(set_attr "conds" "use")
7734 (set_attr "length" "4,8")
7735 (set_attr "type" "*,*")]
7738 (define_insn "*ifcompare_move_not"
7739 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7741 (match_operator 5 "arm_comparison_operator"
7742 [(match_operand:SI 3 "s_register_operand" "r,r")
7743 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7744 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7746 (match_operand:SI 2 "s_register_operand" "r,r"))))
7747 (clobber (reg:CC CC_REGNUM))]
7750 [(set_attr "conds" "clob")
7751 (set_attr "length" "8,12")]
7754 (define_insn "*if_move_not"
7755 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7757 (match_operator 4 "arm_comparison_operator"
7758 [(match_operand 3 "cc_register" "") (const_int 0)])
7759 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7760 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7764 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7765 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7766 [(set_attr "conds" "use")
7767 (set_attr "length" "4,8,8")]
7770 (define_insn "*ifcompare_not_move"
7771 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7773 (match_operator 5 "arm_comparison_operator"
7774 [(match_operand:SI 3 "s_register_operand" "r,r")
7775 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7777 (match_operand:SI 2 "s_register_operand" "r,r"))
7778 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7779 (clobber (reg:CC CC_REGNUM))]
7782 [(set_attr "conds" "clob")
7783 (set_attr "length" "8,12")]
7786 (define_insn "*if_not_move"
7787 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7789 (match_operator 4 "arm_comparison_operator"
7790 [(match_operand 3 "cc_register" "") (const_int 0)])
7791 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7792 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7796 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7797 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7798 [(set_attr "conds" "use")
7799 (set_attr "length" "4,8,8")]
7802 (define_insn "*ifcompare_shift_move"
7803 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7805 (match_operator 6 "arm_comparison_operator"
7806 [(match_operand:SI 4 "s_register_operand" "r,r")
7807 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7808 (match_operator:SI 7 "shift_operator"
7809 [(match_operand:SI 2 "s_register_operand" "r,r")
7810 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7811 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7812 (clobber (reg:CC CC_REGNUM))]
7815 [(set_attr "conds" "clob")
7816 (set_attr "length" "8,12")]
7819 (define_insn "*if_shift_move"
7820 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7822 (match_operator 5 "arm_comparison_operator"
7823 [(match_operand 6 "cc_register" "") (const_int 0)])
7824 (match_operator:SI 4 "shift_operator"
7825 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7826 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7827 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7831 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7832 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7833 [(set_attr "conds" "use")
7834 (set_attr "shift" "2")
7835 (set_attr "length" "4,8,8")]
7838 (define_insn "*ifcompare_move_shift"
7839 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7841 (match_operator 6 "arm_comparison_operator"
7842 [(match_operand:SI 4 "s_register_operand" "r,r")
7843 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7844 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7845 (match_operator:SI 7 "shift_operator"
7846 [(match_operand:SI 2 "s_register_operand" "r,r")
7847 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7848 (clobber (reg:CC CC_REGNUM))]
7851 [(set_attr "conds" "clob")
7852 (set_attr "length" "8,12")]
7855 (define_insn "*if_move_shift"
7856 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7858 (match_operator 5 "arm_comparison_operator"
7859 [(match_operand 6 "cc_register" "") (const_int 0)])
7860 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7861 (match_operator:SI 4 "shift_operator"
7862 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7863 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7867 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7868 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7869 [(set_attr "conds" "use")
7870 (set_attr "shift" "2")
7871 (set_attr "length" "4,8,8")]
7874 (define_insn "*ifcompare_shift_shift"
7875 [(set (match_operand:SI 0 "s_register_operand" "=r")
7877 (match_operator 7 "arm_comparison_operator"
7878 [(match_operand:SI 5 "s_register_operand" "r")
7879 (match_operand:SI 6 "arm_add_operand" "rIL")])
7880 (match_operator:SI 8 "shift_operator"
7881 [(match_operand:SI 1 "s_register_operand" "r")
7882 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7883 (match_operator:SI 9 "shift_operator"
7884 [(match_operand:SI 3 "s_register_operand" "r")
7885 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7886 (clobber (reg:CC CC_REGNUM))]
7889 [(set_attr "conds" "clob")
7890 (set_attr "length" "12")]
7893 (define_insn "*if_shift_shift"
7894 [(set (match_operand:SI 0 "s_register_operand" "=r")
7896 (match_operator 5 "arm_comparison_operator"
7897 [(match_operand 8 "cc_register" "") (const_int 0)])
7898 (match_operator:SI 6 "shift_operator"
7899 [(match_operand:SI 1 "s_register_operand" "r")
7900 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7901 (match_operator:SI 7 "shift_operator"
7902 [(match_operand:SI 3 "s_register_operand" "r")
7903 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7905 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7906 [(set_attr "conds" "use")
7907 (set_attr "shift" "1")
7908 (set_attr "length" "8")]
7911 (define_insn "*ifcompare_not_arith"
7912 [(set (match_operand:SI 0 "s_register_operand" "=r")
7914 (match_operator 6 "arm_comparison_operator"
7915 [(match_operand:SI 4 "s_register_operand" "r")
7916 (match_operand:SI 5 "arm_add_operand" "rIL")])
7917 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7918 (match_operator:SI 7 "shiftable_operator"
7919 [(match_operand:SI 2 "s_register_operand" "r")
7920 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7921 (clobber (reg:CC CC_REGNUM))]
7924 [(set_attr "conds" "clob")
7925 (set_attr "length" "12")]
7928 (define_insn "*if_not_arith"
7929 [(set (match_operand:SI 0 "s_register_operand" "=r")
7931 (match_operator 5 "arm_comparison_operator"
7932 [(match_operand 4 "cc_register" "") (const_int 0)])
7933 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7934 (match_operator:SI 6 "shiftable_operator"
7935 [(match_operand:SI 2 "s_register_operand" "r")
7936 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7938 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7939 [(set_attr "conds" "use")
7940 (set_attr "length" "8")]
7943 (define_insn "*ifcompare_arith_not"
7944 [(set (match_operand:SI 0 "s_register_operand" "=r")
7946 (match_operator 6 "arm_comparison_operator"
7947 [(match_operand:SI 4 "s_register_operand" "r")
7948 (match_operand:SI 5 "arm_add_operand" "rIL")])
7949 (match_operator:SI 7 "shiftable_operator"
7950 [(match_operand:SI 2 "s_register_operand" "r")
7951 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7952 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7953 (clobber (reg:CC CC_REGNUM))]
7956 [(set_attr "conds" "clob")
7957 (set_attr "length" "12")]
7960 (define_insn "*if_arith_not"
7961 [(set (match_operand:SI 0 "s_register_operand" "=r")
7963 (match_operator 5 "arm_comparison_operator"
7964 [(match_operand 4 "cc_register" "") (const_int 0)])
7965 (match_operator:SI 6 "shiftable_operator"
7966 [(match_operand:SI 2 "s_register_operand" "r")
7967 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7968 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7970 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7971 [(set_attr "conds" "use")
7972 (set_attr "length" "8")]
7975 (define_insn "*ifcompare_neg_move"
7976 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7978 (match_operator 5 "arm_comparison_operator"
7979 [(match_operand:SI 3 "s_register_operand" "r,r")
7980 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7981 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7982 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7983 (clobber (reg:CC CC_REGNUM))]
7986 [(set_attr "conds" "clob")
7987 (set_attr "length" "8,12")]
7990 (define_insn "*if_neg_move"
7991 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7993 (match_operator 4 "arm_comparison_operator"
7994 [(match_operand 3 "cc_register" "") (const_int 0)])
7995 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7996 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8000 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8001 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8002 [(set_attr "conds" "use")
8003 (set_attr "length" "4,8,8")]
8006 (define_insn "*ifcompare_move_neg"
8007 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8009 (match_operator 5 "arm_comparison_operator"
8010 [(match_operand:SI 3 "s_register_operand" "r,r")
8011 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8012 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8013 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8014 (clobber (reg:CC CC_REGNUM))]
8017 [(set_attr "conds" "clob")
8018 (set_attr "length" "8,12")]
8021 (define_insn "*if_move_neg"
8022 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8024 (match_operator 4 "arm_comparison_operator"
8025 [(match_operand 3 "cc_register" "") (const_int 0)])
8026 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8027 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8031 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8032 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8033 [(set_attr "conds" "use")
8034 (set_attr "length" "4,8,8")]
8037 (define_insn "*arith_adjacentmem"
8038 [(set (match_operand:SI 0 "s_register_operand" "=r")
8039 (match_operator:SI 1 "shiftable_operator"
8040 [(match_operand:SI 2 "memory_operand" "m")
8041 (match_operand:SI 3 "memory_operand" "m")]))
8042 (clobber (match_scratch:SI 4 "=r"))]
8043 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8048 int val1 = 0, val2 = 0;
8050 if (REGNO (operands[0]) > REGNO (operands[4]))
8052 ldm[1] = operands[4];
8053 ldm[2] = operands[0];
8057 ldm[1] = operands[0];
8058 ldm[2] = operands[4];
8060 if (GET_CODE (XEXP (operands[2], 0)) != REG)
8061 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8062 if (GET_CODE (XEXP (operands[3], 0)) != REG)
8063 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8064 arith[0] = operands[0];
8065 arith[3] = operands[1];
8079 ldm[0] = ops[0] = operands[4];
8080 ops[1] = XEXP (XEXP (operands[2], 0), 0);
8081 ops[2] = XEXP (XEXP (operands[2], 0), 1);
8082 output_add_immediate (ops);
8084 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8086 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8090 ldm[0] = XEXP (operands[3], 0);
8092 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8094 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8098 ldm[0] = XEXP (operands[2], 0);
8100 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8102 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8104 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8107 [(set_attr "length" "12")
8108 (set_attr "predicable" "yes")
8109 (set_attr "type" "load")]
8112 ;; the arm can support extended pre-inc instructions
8114 ;; In all these cases, we use operands 0 and 1 for the register being
8115 ;; incremented because those are the operands that local-alloc will
8116 ;; tie and these are the pair most likely to be tieable (and the ones
8117 ;; that will benefit the most).
8119 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8120 ;; elimination will cause too many headaches.
8122 (define_insn "*strqi_preinc"
8123 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8124 (match_operand:SI 2 "index_operand" "rJ")))
8125 (match_operand:QI 3 "s_register_operand" "r"))
8126 (set (match_operand:SI 0 "s_register_operand" "=r")
8127 (plus:SI (match_dup 1) (match_dup 2)))]
8129 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8130 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8131 && (GET_CODE (operands[2]) != REG
8132 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8133 "str%?b\\t%3, [%0, %2]!"
8134 [(set_attr "type" "store1")
8135 (set_attr "predicable" "yes")]
8138 (define_insn "*strqi_predec"
8139 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8140 (match_operand:SI 2 "s_register_operand" "r")))
8141 (match_operand:QI 3 "s_register_operand" "r"))
8142 (set (match_operand:SI 0 "s_register_operand" "=r")
8143 (minus:SI (match_dup 1) (match_dup 2)))]
8145 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8146 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8147 && (GET_CODE (operands[2]) != REG
8148 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8149 "str%?b\\t%3, [%0, -%2]!"
8150 [(set_attr "type" "store1")
8151 (set_attr "predicable" "yes")]
8154 (define_insn "*loadqi_preinc"
8155 [(set (match_operand:QI 3 "s_register_operand" "=r")
8156 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8157 (match_operand:SI 2 "index_operand" "rJ"))))
8158 (set (match_operand:SI 0 "s_register_operand" "=r")
8159 (plus:SI (match_dup 1) (match_dup 2)))]
8161 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8162 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8163 && (GET_CODE (operands[2]) != REG
8164 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8165 "ldr%?b\\t%3, [%0, %2]!"
8166 [(set_attr "type" "load")
8167 (set_attr "predicable" "yes")]
8170 (define_insn "*loadqi_predec"
8171 [(set (match_operand:QI 3 "s_register_operand" "=r")
8172 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8173 (match_operand:SI 2 "s_register_operand" "r"))))
8174 (set (match_operand:SI 0 "s_register_operand" "=r")
8175 (minus:SI (match_dup 1) (match_dup 2)))]
8177 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8178 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8179 && (GET_CODE (operands[2]) != REG
8180 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8181 "ldr%?b\\t%3, [%0, -%2]!"
8182 [(set_attr "type" "load")
8183 (set_attr "predicable" "yes")]
8186 (define_insn "*loadqisi_preinc"
8187 [(set (match_operand:SI 3 "s_register_operand" "=r")
8189 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8190 (match_operand:SI 2 "index_operand" "rJ")))))
8191 (set (match_operand:SI 0 "s_register_operand" "=r")
8192 (plus:SI (match_dup 1) (match_dup 2)))]
8194 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8195 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8196 && (GET_CODE (operands[2]) != REG
8197 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8198 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8199 [(set_attr "type" "load")
8200 (set_attr "predicable" "yes")]
8203 (define_insn "*loadqisi_predec"
8204 [(set (match_operand:SI 3 "s_register_operand" "=r")
8206 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8207 (match_operand:SI 2 "s_register_operand" "r")))))
8208 (set (match_operand:SI 0 "s_register_operand" "=r")
8209 (minus:SI (match_dup 1) (match_dup 2)))]
8211 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8212 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8213 && (GET_CODE (operands[2]) != REG
8214 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8215 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8216 [(set_attr "type" "load")
8217 (set_attr "predicable" "yes")]
8220 (define_insn "*strsi_preinc"
8221 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8222 (match_operand:SI 2 "index_operand" "rJ")))
8223 (match_operand:SI 3 "s_register_operand" "r"))
8224 (set (match_operand:SI 0 "s_register_operand" "=r")
8225 (plus:SI (match_dup 1) (match_dup 2)))]
8227 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8228 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8229 && (GET_CODE (operands[2]) != REG
8230 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8231 "str%?\\t%3, [%0, %2]!"
8232 [(set_attr "type" "store1")
8233 (set_attr "predicable" "yes")]
8236 (define_insn "*strsi_predec"
8237 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8238 (match_operand:SI 2 "s_register_operand" "r")))
8239 (match_operand:SI 3 "s_register_operand" "r"))
8240 (set (match_operand:SI 0 "s_register_operand" "=r")
8241 (minus:SI (match_dup 1) (match_dup 2)))]
8243 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8244 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8245 && (GET_CODE (operands[2]) != REG
8246 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8247 "str%?\\t%3, [%0, -%2]!"
8248 [(set_attr "type" "store1")
8249 (set_attr "predicable" "yes")]
8252 (define_insn "*loadsi_preinc"
8253 [(set (match_operand:SI 3 "s_register_operand" "=r")
8254 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8255 (match_operand:SI 2 "index_operand" "rJ"))))
8256 (set (match_operand:SI 0 "s_register_operand" "=r")
8257 (plus:SI (match_dup 1) (match_dup 2)))]
8259 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8260 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8261 && (GET_CODE (operands[2]) != REG
8262 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8263 "ldr%?\\t%3, [%0, %2]!"
8264 [(set_attr "type" "load")
8265 (set_attr "predicable" "yes")]
8268 (define_insn "*loadsi_predec"
8269 [(set (match_operand:SI 3 "s_register_operand" "=r")
8270 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8271 (match_operand:SI 2 "s_register_operand" "r"))))
8272 (set (match_operand:SI 0 "s_register_operand" "=r")
8273 (minus:SI (match_dup 1) (match_dup 2)))]
8275 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8276 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8277 && (GET_CODE (operands[2]) != REG
8278 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8279 "ldr%?\\t%3, [%0, -%2]!"
8280 [(set_attr "type" "load")
8281 (set_attr "predicable" "yes")]
8284 (define_insn "*loadhi_preinc"
8285 [(set (match_operand:HI 3 "s_register_operand" "=r")
8286 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8287 (match_operand:SI 2 "index_operand" "rJ"))))
8288 (set (match_operand:SI 0 "s_register_operand" "=r")
8289 (plus:SI (match_dup 1) (match_dup 2)))]
8291 && !BYTES_BIG_ENDIAN
8292 && !TARGET_MMU_TRAPS
8293 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8294 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8295 && (GET_CODE (operands[2]) != REG
8296 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8297 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8298 [(set_attr "type" "load")
8299 (set_attr "predicable" "yes")]
8302 (define_insn "*loadhi_predec"
8303 [(set (match_operand:HI 3 "s_register_operand" "=r")
8304 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8305 (match_operand:SI 2 "s_register_operand" "r"))))
8306 (set (match_operand:SI 0 "s_register_operand" "=r")
8307 (minus:SI (match_dup 1) (match_dup 2)))]
8309 && !BYTES_BIG_ENDIAN
8310 && !TARGET_MMU_TRAPS
8311 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8312 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8313 && (GET_CODE (operands[2]) != REG
8314 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8315 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8316 [(set_attr "type" "load")
8317 (set_attr "predicable" "yes")]
8320 (define_insn "*strqi_shiftpreinc"
8321 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8322 [(match_operand:SI 3 "s_register_operand" "r")
8323 (match_operand:SI 4 "const_shift_operand" "n")])
8324 (match_operand:SI 1 "s_register_operand" "0")))
8325 (match_operand:QI 5 "s_register_operand" "r"))
8326 (set (match_operand:SI 0 "s_register_operand" "=r")
8327 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8330 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8331 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8332 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8333 "str%?b\\t%5, [%0, %3%S2]!"
8334 [(set_attr "type" "store1")
8335 (set_attr "predicable" "yes")]
8338 (define_insn "*strqi_shiftpredec"
8339 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8340 (match_operator:SI 2 "shift_operator"
8341 [(match_operand:SI 3 "s_register_operand" "r")
8342 (match_operand:SI 4 "const_shift_operand" "n")])))
8343 (match_operand:QI 5 "s_register_operand" "r"))
8344 (set (match_operand:SI 0 "s_register_operand" "=r")
8345 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8348 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8349 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8350 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8351 "str%?b\\t%5, [%0, -%3%S2]!"
8352 [(set_attr "type" "store1")
8353 (set_attr "predicable" "yes")]
8356 (define_insn "*loadqi_shiftpreinc"
8357 [(set (match_operand:QI 5 "s_register_operand" "=r")
8358 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8359 [(match_operand:SI 3 "s_register_operand" "r")
8360 (match_operand:SI 4 "const_shift_operand" "n")])
8361 (match_operand:SI 1 "s_register_operand" "0"))))
8362 (set (match_operand:SI 0 "s_register_operand" "=r")
8363 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8366 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8367 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8368 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8369 "ldr%?b\\t%5, [%0, %3%S2]!"
8370 [(set_attr "type" "load")
8371 (set_attr "predicable" "yes")]
8374 (define_insn "*loadqi_shiftpredec"
8375 [(set (match_operand:QI 5 "s_register_operand" "=r")
8376 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8377 (match_operator:SI 2 "shift_operator"
8378 [(match_operand:SI 3 "s_register_operand" "r")
8379 (match_operand:SI 4 "const_shift_operand" "n")]))))
8380 (set (match_operand:SI 0 "s_register_operand" "=r")
8381 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8384 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8385 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8386 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8387 "ldr%?b\\t%5, [%0, -%3%S2]!"
8388 [(set_attr "type" "load")
8389 (set_attr "predicable" "yes")]
8392 (define_insn "*strsi_shiftpreinc"
8393 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8394 [(match_operand:SI 3 "s_register_operand" "r")
8395 (match_operand:SI 4 "const_shift_operand" "n")])
8396 (match_operand:SI 1 "s_register_operand" "0")))
8397 (match_operand:SI 5 "s_register_operand" "r"))
8398 (set (match_operand:SI 0 "s_register_operand" "=r")
8399 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8402 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8403 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8404 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8405 "str%?\\t%5, [%0, %3%S2]!"
8406 [(set_attr "type" "store1")
8407 (set_attr "predicable" "yes")]
8410 (define_insn "*strsi_shiftpredec"
8411 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8412 (match_operator:SI 2 "shift_operator"
8413 [(match_operand:SI 3 "s_register_operand" "r")
8414 (match_operand:SI 4 "const_shift_operand" "n")])))
8415 (match_operand:SI 5 "s_register_operand" "r"))
8416 (set (match_operand:SI 0 "s_register_operand" "=r")
8417 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8420 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8421 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8422 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8423 "str%?\\t%5, [%0, -%3%S2]!"
8424 [(set_attr "type" "store1")
8425 (set_attr "predicable" "yes")]
8428 (define_insn "*loadsi_shiftpreinc"
8429 [(set (match_operand:SI 5 "s_register_operand" "=r")
8430 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8431 [(match_operand:SI 3 "s_register_operand" "r")
8432 (match_operand:SI 4 "const_shift_operand" "n")])
8433 (match_operand:SI 1 "s_register_operand" "0"))))
8434 (set (match_operand:SI 0 "s_register_operand" "=r")
8435 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8438 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8439 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8440 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8441 "ldr%?\\t%5, [%0, %3%S2]!"
8442 [(set_attr "type" "load")
8443 (set_attr "predicable" "yes")]
8446 (define_insn "*loadsi_shiftpredec"
8447 [(set (match_operand:SI 5 "s_register_operand" "=r")
8448 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8449 (match_operator:SI 2 "shift_operator"
8450 [(match_operand:SI 3 "s_register_operand" "r")
8451 (match_operand:SI 4 "const_shift_operand" "n")]))))
8452 (set (match_operand:SI 0 "s_register_operand" "=r")
8453 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8456 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8457 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8458 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8459 "ldr%?\\t%5, [%0, -%3%S2]!"
8460 [(set_attr "type" "load")
8461 (set_attr "predicable" "yes")])
8463 (define_insn "*loadhi_shiftpreinc"
8464 [(set (match_operand:HI 5 "s_register_operand" "=r")
8465 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8466 [(match_operand:SI 3 "s_register_operand" "r")
8467 (match_operand:SI 4 "const_shift_operand" "n")])
8468 (match_operand:SI 1 "s_register_operand" "0"))))
8469 (set (match_operand:SI 0 "s_register_operand" "=r")
8470 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8473 && !BYTES_BIG_ENDIAN
8474 && !TARGET_MMU_TRAPS
8475 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8476 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8477 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8478 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8479 [(set_attr "type" "load")
8480 (set_attr "predicable" "yes")]
8483 (define_insn "*loadhi_shiftpredec"
8484 [(set (match_operand:HI 5 "s_register_operand" "=r")
8485 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8486 (match_operator:SI 2 "shift_operator"
8487 [(match_operand:SI 3 "s_register_operand" "r")
8488 (match_operand:SI 4 "const_shift_operand" "n")]))))
8489 (set (match_operand:SI 0 "s_register_operand" "=r")
8490 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8493 && !BYTES_BIG_ENDIAN
8494 && !TARGET_MMU_TRAPS
8495 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8496 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8497 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8498 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8499 [(set_attr "type" "load")
8500 (set_attr "predicable" "yes")]
8503 ; It can also support extended post-inc expressions, but combine doesn't
8505 ; It doesn't seem worth adding peepholes for anything but the most common
8506 ; cases since, unlike combine, the increment must immediately follow the load
8507 ; for this pattern to match.
8508 ; We must watch to see that the source/destination register isn't also the
8509 ; same as the base address register, and that if the index is a register,
8510 ; that it is not the same as the base address register. In such cases the
8511 ; instruction that we would generate would have UNPREDICTABLE behaviour so
8515 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8516 (match_operand:QI 2 "s_register_operand" "r"))
8518 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8520 && (REGNO (operands[2]) != REGNO (operands[0]))
8521 && (GET_CODE (operands[1]) != REG
8522 || (REGNO (operands[1]) != REGNO (operands[0])))"
8523 "str%?b\\t%2, [%0], %1"
8527 [(set (match_operand:QI 0 "s_register_operand" "=r")
8528 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8530 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8532 && REGNO (operands[0]) != REGNO(operands[1])
8533 && (GET_CODE (operands[2]) != REG
8534 || REGNO(operands[0]) != REGNO (operands[2]))"
8535 "ldr%?b\\t%0, [%1], %2"
8539 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8540 (match_operand:SI 2 "s_register_operand" "r"))
8542 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8544 && (REGNO (operands[2]) != REGNO (operands[0]))
8545 && (GET_CODE (operands[1]) != REG
8546 || (REGNO (operands[1]) != REGNO (operands[0])))"
8547 "str%?\\t%2, [%0], %1"
8551 [(set (match_operand:HI 0 "s_register_operand" "=r")
8552 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8554 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8556 && !BYTES_BIG_ENDIAN
8557 && !TARGET_MMU_TRAPS
8558 && REGNO (operands[0]) != REGNO(operands[1])
8559 && (GET_CODE (operands[2]) != REG
8560 || REGNO(operands[0]) != REGNO (operands[2]))"
8561 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8565 [(set (match_operand:SI 0 "s_register_operand" "=r")
8566 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8568 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8570 && REGNO (operands[0]) != REGNO(operands[1])
8571 && (GET_CODE (operands[2]) != REG
8572 || REGNO(operands[0]) != REGNO (operands[2]))"
8573 "ldr%?\\t%0, [%1], %2"
8577 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8578 (match_operand:SI 1 "index_operand" "rJ")))
8579 (match_operand:QI 2 "s_register_operand" "r"))
8580 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8582 && (REGNO (operands[2]) != REGNO (operands[0]))
8583 && (GET_CODE (operands[1]) != REG
8584 || (REGNO (operands[1]) != REGNO (operands[0])))"
8585 "str%?b\\t%2, [%0, %1]!"
8589 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8590 [(match_operand:SI 0 "s_register_operand" "r")
8591 (match_operand:SI 1 "const_int_operand" "n")])
8592 (match_operand:SI 2 "s_register_operand" "+r")))
8593 (match_operand:QI 3 "s_register_operand" "r"))
8594 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8597 && (REGNO (operands[3]) != REGNO (operands[2]))
8598 && (REGNO (operands[0]) != REGNO (operands[2]))"
8599 "str%?b\\t%3, [%2, %0%S4]!"
8602 ; This pattern is never tried by combine, so do it as a peephole
8605 [(set (match_operand:SI 0 "s_register_operand" "")
8606 (match_operand:SI 1 "s_register_operand" ""))
8607 (set (reg:CC CC_REGNUM)
8608 (compare:CC (match_dup 1) (const_int 0)))]
8610 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8611 (set (match_dup 0) (match_dup 1))])]
8615 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8616 ; reversed, check that the memory references aren't volatile.
8619 [(set (match_operand:SI 0 "s_register_operand" "=r")
8620 (match_operand:SI 4 "memory_operand" "m"))
8621 (set (match_operand:SI 1 "s_register_operand" "=r")
8622 (match_operand:SI 5 "memory_operand" "m"))
8623 (set (match_operand:SI 2 "s_register_operand" "=r")
8624 (match_operand:SI 6 "memory_operand" "m"))
8625 (set (match_operand:SI 3 "s_register_operand" "=r")
8626 (match_operand:SI 7 "memory_operand" "m"))]
8627 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8629 return emit_ldm_seq (operands, 4);
8634 [(set (match_operand:SI 0 "s_register_operand" "=r")
8635 (match_operand:SI 3 "memory_operand" "m"))
8636 (set (match_operand:SI 1 "s_register_operand" "=r")
8637 (match_operand:SI 4 "memory_operand" "m"))
8638 (set (match_operand:SI 2 "s_register_operand" "=r")
8639 (match_operand:SI 5 "memory_operand" "m"))]
8640 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8642 return emit_ldm_seq (operands, 3);
8647 [(set (match_operand:SI 0 "s_register_operand" "=r")
8648 (match_operand:SI 2 "memory_operand" "m"))
8649 (set (match_operand:SI 1 "s_register_operand" "=r")
8650 (match_operand:SI 3 "memory_operand" "m"))]
8651 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8653 return emit_ldm_seq (operands, 2);
8658 [(set (match_operand:SI 4 "memory_operand" "=m")
8659 (match_operand:SI 0 "s_register_operand" "r"))
8660 (set (match_operand:SI 5 "memory_operand" "=m")
8661 (match_operand:SI 1 "s_register_operand" "r"))
8662 (set (match_operand:SI 6 "memory_operand" "=m")
8663 (match_operand:SI 2 "s_register_operand" "r"))
8664 (set (match_operand:SI 7 "memory_operand" "=m")
8665 (match_operand:SI 3 "s_register_operand" "r"))]
8666 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8668 return emit_stm_seq (operands, 4);
8673 [(set (match_operand:SI 3 "memory_operand" "=m")
8674 (match_operand:SI 0 "s_register_operand" "r"))
8675 (set (match_operand:SI 4 "memory_operand" "=m")
8676 (match_operand:SI 1 "s_register_operand" "r"))
8677 (set (match_operand:SI 5 "memory_operand" "=m")
8678 (match_operand:SI 2 "s_register_operand" "r"))]
8679 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8681 return emit_stm_seq (operands, 3);
8686 [(set (match_operand:SI 2 "memory_operand" "=m")
8687 (match_operand:SI 0 "s_register_operand" "r"))
8688 (set (match_operand:SI 3 "memory_operand" "=m")
8689 (match_operand:SI 1 "s_register_operand" "r"))]
8690 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8692 return emit_stm_seq (operands, 2);
8697 [(set (match_operand:SI 0 "s_register_operand" "")
8698 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8700 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8701 [(match_operand:SI 3 "s_register_operand" "")
8702 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8703 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8705 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8706 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8711 ;; This split can be used because CC_Z mode implies that the following
8712 ;; branch will be an equality, or an unsigned inequality, so the sign
8713 ;; extension is not needed.
8716 [(set (reg:CC_Z CC_REGNUM)
8718 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8720 (match_operand 1 "const_int_operand" "")))
8721 (clobber (match_scratch:SI 2 ""))]
8723 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8724 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8725 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8726 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8728 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8732 (define_expand "prologue"
8733 [(clobber (const_int 0))]
8736 arm_expand_prologue ();
8738 thumb_expand_prologue ();
8743 (define_expand "epilogue"
8744 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8748 thumb_expand_epilogue ();
8749 else if (USE_RETURN_INSN (FALSE))
8751 emit_jump_insn (gen_return ());
8754 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8756 gen_rtx_RETURN (VOIDmode)),
8762 (define_insn "sibcall_epilogue"
8763 [(unspec_volatile [(const_int 0)] VUNSPEC_EPILOGUE)]
8766 output_asm_insn (\"%@ Sibcall epilogue\", operands);
8767 if (USE_RETURN_INSN (FALSE))
8768 return output_return_instruction (NULL, FALSE, FALSE);
8769 return arm_output_epilogue (FALSE);
8771 ;; Length is absolute worst case
8772 [(set_attr "length" "44")
8773 (set_attr "type" "block")]
8776 (define_insn "*epilogue_insns"
8777 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8781 return arm_output_epilogue (TRUE);
8782 else /* TARGET_THUMB */
8783 return thumb_unexpanded_epilogue ();
8785 ; Length is absolute worst case
8786 [(set_attr "length" "44")
8787 (set_attr "type" "block")]
8790 (define_expand "eh_epilogue"
8791 [(use (match_operand:SI 0 "register_operand" "r"))
8792 (use (match_operand:SI 1 "register_operand" "r"))
8793 (use (match_operand:SI 2 "register_operand" "r"))]
8797 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8798 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8800 rtx ra = gen_rtx_REG (Pmode, 2);
8802 emit_move_insn (ra, operands[2]);
8805 /* This is a hack -- we may have crystalized the function type too
8807 cfun->machine->func_type = 0;
8811 ;; This split is only used during output to reduce the number of patterns
8812 ;; that need assembler instructions adding to them. We allowed the setting
8813 ;; of the conditions to be implicit during rtl generation so that
8814 ;; the conditional compare patterns would work. However this conflicts to
8815 ;; some extent with the conditional data operations, so we have to split them
8819 [(set (match_operand:SI 0 "s_register_operand" "")
8820 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8821 [(match_operand 2 "" "") (match_operand 3 "" "")])
8823 (match_operand 4 "" "")))
8824 (clobber (reg:CC CC_REGNUM))]
8825 "TARGET_ARM && reload_completed"
8826 [(set (match_dup 5) (match_dup 6))
8827 (cond_exec (match_dup 7)
8828 (set (match_dup 0) (match_dup 4)))]
8831 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8832 operands[2], operands[3]);
8833 enum rtx_code rc = GET_CODE (operands[1]);
8835 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8836 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8837 if (mode == CCFPmode || mode == CCFPEmode)
8838 rc = reverse_condition_maybe_unordered (rc);
8840 rc = reverse_condition (rc);
8842 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8847 [(set (match_operand:SI 0 "s_register_operand" "")
8848 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8849 [(match_operand 2 "" "") (match_operand 3 "" "")])
8850 (match_operand 4 "" "")
8852 (clobber (reg:CC CC_REGNUM))]
8853 "TARGET_ARM && reload_completed"
8854 [(set (match_dup 5) (match_dup 6))
8855 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8856 (set (match_dup 0) (match_dup 4)))]
8859 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8860 operands[2], operands[3]);
8862 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8863 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8868 [(set (match_operand:SI 0 "s_register_operand" "")
8869 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8870 [(match_operand 2 "" "") (match_operand 3 "" "")])
8871 (match_operand 4 "" "")
8872 (match_operand 5 "" "")))
8873 (clobber (reg:CC CC_REGNUM))]
8874 "TARGET_ARM && reload_completed"
8875 [(set (match_dup 6) (match_dup 7))
8876 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8877 (set (match_dup 0) (match_dup 4)))
8878 (cond_exec (match_dup 8)
8879 (set (match_dup 0) (match_dup 5)))]
8882 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8883 operands[2], operands[3]);
8884 enum rtx_code rc = GET_CODE (operands[1]);
8886 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8887 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8888 if (mode == CCFPmode || mode == CCFPEmode)
8889 rc = reverse_condition_maybe_unordered (rc);
8891 rc = reverse_condition (rc);
8893 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8898 [(set (match_operand:SI 0 "s_register_operand" "")
8899 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8900 [(match_operand:SI 2 "s_register_operand" "")
8901 (match_operand:SI 3 "arm_add_operand" "")])
8902 (match_operand:SI 4 "arm_rhs_operand" "")
8904 (match_operand:SI 5 "s_register_operand" ""))))
8905 (clobber (reg:CC CC_REGNUM))]
8906 "TARGET_ARM && reload_completed"
8907 [(set (match_dup 6) (match_dup 7))
8908 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8909 (set (match_dup 0) (match_dup 4)))
8910 (cond_exec (match_dup 8)
8911 (set (match_dup 0) (not:SI (match_dup 5))))]
8914 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8915 operands[2], operands[3]);
8916 enum rtx_code rc = GET_CODE (operands[1]);
8918 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8919 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8920 if (mode == CCFPmode || mode == CCFPEmode)
8921 rc = reverse_condition_maybe_unordered (rc);
8923 rc = reverse_condition (rc);
8925 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8929 (define_insn "*cond_move_not"
8930 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8931 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8932 [(match_operand 3 "cc_register" "") (const_int 0)])
8933 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8935 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8939 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8940 [(set_attr "conds" "use")
8941 (set_attr "length" "4,8")]
8944 ;; The next two patterns occur when an AND operation is followed by a
8945 ;; scc insn sequence
8947 (define_insn "*sign_extract_onebit"
8948 [(set (match_operand:SI 0 "s_register_operand" "=r")
8949 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8951 (match_operand:SI 2 "const_int_operand" "n")))]
8954 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8955 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8956 return \"mvnne\\t%0, #0\";
8958 [(set_attr "conds" "clob")
8959 (set_attr "length" "8")]
8962 (define_insn "*not_signextract_onebit"
8963 [(set (match_operand:SI 0 "s_register_operand" "=r")
8965 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8967 (match_operand:SI 2 "const_int_operand" "n"))))]
8970 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8971 output_asm_insn (\"tst\\t%1, %2\", operands);
8972 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8973 return \"movne\\t%0, #0\";
8975 [(set_attr "conds" "clob")
8976 (set_attr "length" "12")]
8979 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8980 ;; expressions. For simplicity, the first register is also in the unspec
8982 (define_insn "*push_multi"
8983 [(match_parallel 2 "multi_register_push"
8984 [(set (match_operand:BLK 0 "memory_operand" "=m")
8985 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8986 UNSPEC_PUSH_MULT))])]
8990 int num_saves = XVECLEN (operands[2], 0);
8992 /* For the StrongARM at least it is faster to
8993 use STR to store only a single register. */
8995 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9001 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9003 for (i = 1; i < num_saves; i++)
9005 strcat (pattern, \", %|\");
9007 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9010 strcat (pattern, \"}\");
9011 output_asm_insn (pattern, operands);
9016 [(set_attr "type" "store4")]
9019 ;; Similarly for the floating point registers
9020 (define_insn "*push_fp_multi"
9021 [(match_parallel 2 "multi_register_push"
9022 [(set (match_operand:BLK 0 "memory_operand" "=m")
9023 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9024 UNSPEC_PUSH_MULT))])]
9030 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9031 output_asm_insn (pattern, operands);
9034 [(set_attr "type" "f_store")]
9037 ;; Special patterns for dealing with the constant pool
9039 (define_insn "align_4"
9040 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9043 assemble_align (32);
9048 (define_insn "consttable_end"
9049 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9052 making_const_table = FALSE;
9057 (define_insn "consttable_1"
9058 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9061 making_const_table = TRUE;
9062 assemble_integer (operands[0], 1, 1);
9066 [(set_attr "length" "4")]
9069 (define_insn "consttable_2"
9070 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9073 making_const_table = TRUE;
9074 assemble_integer (operands[0], 2, 1);
9078 [(set_attr "length" "4")]
9081 (define_insn "consttable_4"
9082 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9086 making_const_table = TRUE;
9087 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9091 union real_extract u;
9092 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9093 assemble_real (u.d, GET_MODE (operands[0]));
9097 assemble_integer (operands[0], 4, 1);
9102 [(set_attr "length" "4")]
9105 (define_insn "consttable_8"
9106 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9110 making_const_table = TRUE;
9111 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9115 union real_extract u;
9116 memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
9117 assemble_real (u.d, GET_MODE (operands[0]));
9121 assemble_integer (operands[0], 8, 1);
9126 [(set_attr "length" "8")]
9129 ;; Miscellaneous Thumb patterns
9131 (define_insn "tablejump"
9132 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9133 (use (label_ref (match_operand 1 "" "")))]
9136 [(set_attr "length" "2")]
9142 [(set (match_operand:SI 0 "s_register_operand" "=r")
9143 (unspec:SI [(match_operand:SI 1 "s_register_operand" "r")]
9145 "TARGET_ARM && arm_arch5"
9148 (define_expand "ffssi2"
9149 [(set (match_operand:SI 0 "s_register_operand" "")
9150 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9151 "TARGET_ARM && arm_arch5"
9156 t1 = gen_reg_rtx (SImode);
9157 t2 = gen_reg_rtx (SImode);
9158 t3 = gen_reg_rtx (SImode);
9160 emit_insn (gen_negsi2 (t1, operands[1]));
9161 emit_insn (gen_andsi3 (t2, operands[1], t1));
9162 emit_insn (gen_clz (t3, t2));
9163 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9168 ;; V5E instructions.
9170 (define_insn "prefetch"
9172 [(match_operand:SI 0 "offsettable_memory_operand" "o")] VUNSPEC_PREFETCH)]
9173 "TARGET_ARM && arm_arch5e"
9176 ;; General predication pattern
9179 [(match_operator 0 "arm_comparison_operator"
9180 [(match_operand 1 "cc_register" "")