1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003 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 GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; 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.
28 ;;---------------------------------------------------------------------------
33 [(IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (CC_REGNUM 24) ; Condition code pseudo register
41 ;; 3rd operand to select_dominance_cc_mode
50 ;; Note: sin and cos are no-longer used.
53 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
54 ; operand 0 is the result,
55 ; operand 1 the parameter.
56 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60 ; operand 0 is the first register,
61 ; subsequent registers are in parallel (use ...)
63 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
64 ; usage, that is, we will add the pic_register
65 ; value to it before trying to dereference it.
66 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
67 ; GLOBAL_OFFSET_TABLE. The operation is fully
68 ; described by the RTL but must be wrapped to
69 ; prevent combine from trying to rip it apart.
70 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
71 ; being scheduled before the stack adjustment insn.
72 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73 ; this unspec is used to prevent the deletion of
74 ; instructions setting registers for EH handling
75 ; and stack frame generation. Operand 0 is the
77 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93 ;; UNSPEC_VOLATILE Usage:
96 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
98 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99 ; instruction epilogue sequence that isn't expanded
100 ; into normal RTL. Used for both normal and sibcall
102 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
103 ; for inlined constants.
104 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
106 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
108 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
110 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
112 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
114 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
115 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
116 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
117 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
118 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
123 ;;---------------------------------------------------------------------------
126 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127 ; generating ARM code. This is used to control the length of some insn
128 ; patterns that share the same RTL in both ARM and Thumb code.
129 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
131 ; PROG_MODE attribute is used to determine whether condition codes are
132 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
133 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
134 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
140 ;; Operand number of an input operand that is shifted. Zero if the
141 ;; given instruction does not shift one of its input operands.
142 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 (define_attr "shift" "" (const_int 0))
145 ; Floating Point Unit. If we only have floating point emulation, then there
146 ; is no point in scheduling the floating point insns. (Well, for best
147 ; performance we should try and group them together).
148 (define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
149 (const (symbol_ref "arm_fpu_attr")))
151 ; LENGTH of an instruction (in bytes)
152 (define_attr "length" "" (const_int 4))
154 ; POOL_RANGE is how far away from a constant pool entry that this insn
155 ; can be placed. If the distance is zero, then this insn will never
156 ; reference the pool.
157 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
158 ; before its address.
159 (define_attr "pool_range" "" (const_int 0))
160 (define_attr "neg_pool_range" "" (const_int 0))
162 ; An assembler sequence may clobber the condition codes without us knowing.
163 ; If such an insn references the pool, then we have no way of knowing how,
164 ; so use the most conservative value for pool_range.
165 (define_asm_attributes
166 [(set_attr "conds" "clob")
167 (set_attr "length" "4")
168 (set_attr "pool_range" "250")])
170 ; TYPE attribute is used to detect floating point instructions which, if
171 ; running on a co-processor can run in parallel with other, basic instructions
172 ; If write-buffer scheduling is enabled then it can also be used in the
173 ; scheduling of writes.
175 ; Classification of each insn
176 ; normal any data instruction that doesn't hit memory or fp regs
177 ; mult a multiply instruction
178 ; block blockage insn, this blocks all functional units
179 ; float a floating point arithmetic operation (subject to expansion)
180 ; fdivd DFmode floating point division
181 ; fdivs SFmode floating point division
182 ; fmul Floating point multiply
183 ; ffmul Fast floating point multiply
184 ; farith Floating point arithmetic (4 cycle)
185 ; ffarith Fast floating point arithmetic (2 cycle)
186 ; float_em a floating point arithmetic operation that is normally emulated
187 ; even on a machine with an fpa.
188 ; f_load a floating point load from memory
189 ; f_store a floating point store to memory
190 ; f_mem_r a transfer of a floating point register to a real reg via mem
191 ; r_mem_f the reverse of f_mem_r
192 ; f_2_r fast transfer float to arm (no memory needed)
193 ; r_2_f fast transfer arm to float
194 ; call a subroutine call
195 ; load any load from memory
196 ; store1 store 1 word to memory from arm registers
197 ; store2 store 2 words
198 ; store3 store 3 words
199 ; store4 store 4 words
200 ; Additions for Cirrus Maverick co-processor:
201 ; mav_farith Floating point arithmetic (4 cycle)
202 ; mav_dmult Double multiplies (7 cycle)
205 "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,mav_farith,mav_dmult"
206 (const_string "normal"))
208 ; Load scheduling, set from the arm_ld_sched variable
209 ; initialized by arm_override_options()
210 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
212 ; condition codes: this one is used by final_prescan_insn to speed up
213 ; conditionalizing instructions. It saves having to scan the rtl to see if
214 ; it uses or alters the condition codes.
216 ; USE means that the condition codes are used by the insn in the process of
217 ; outputting code, this means (at present) that we can't use the insn in
220 ; SET means that the purpose of the insn is to set the condition codes in a
221 ; well defined manner.
223 ; CLOB means that the condition codes are altered in an undefined manner, if
224 ; they are altered at all
226 ; JUMP_CLOB is used when the condition cannot be represented by a single
227 ; instruction (UNEQ and LTGT). These cannot be predicated.
229 ; NOCOND means that the condition codes are neither altered nor affect the
230 ; output of this insn
232 (define_attr "conds" "use,set,clob,jump_clob,nocond"
233 (if_then_else (eq_attr "type" "call")
234 (if_then_else (eq_attr "prog_mode" "prog32")
235 (const_string "clob") (const_string "nocond"))
236 (const_string "nocond")))
238 ; Predicable means that the insn can be conditionally executed based on
239 ; an automatically added predicate (additional patterns are generated by
240 ; gen...). We default to 'no' because no Thumb patterns match this rule
241 ; and not all ARM patterns do.
242 (define_attr "predicable" "no,yes" (const_string "no"))
244 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
245 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
246 ; suffer blockages enough to warrant modelling this (and it can adversely
247 ; affect the schedule).
248 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
250 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
251 ; to stall the processor. Used with model_wbuf above.
252 (define_attr "write_conflict" "no,yes"
253 (if_then_else (eq_attr "type"
254 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
256 (const_string "no")))
258 ; Classify the insns into those that take one cycle and those that take more
259 ; than one on the main cpu execution unit.
260 (define_attr "core_cycles" "single,multi"
261 (if_then_else (eq_attr "type"
262 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
263 (const_string "single")
264 (const_string "multi")))
266 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
267 ;; distant label. Only applicable to Thumb code.
268 (define_attr "far_jump" "yes,no" (const_string "no"))
270 (define_automaton "arm")
274 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
276 ; The write buffer on some of the arm6 processors is hard to model exactly.
277 ; There is room in the buffer for up to two addresses and up to eight words
278 ; of memory, but the two needn't be split evenly. When writing the two
279 ; addresses are fully pipelined. However, a read from memory that is not
280 ; currently in the cache will block until the writes have completed.
281 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
282 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
283 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
284 ; cycle to add as well.
285 (define_cpu_unit "write_buf" "arm")
287 ;; Write blockage unit
289 ; The write_blockage unit models (partially), the fact that reads will stall
290 ; until the write buffer empties.
291 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
292 ; so we don't model them here
293 (define_cpu_unit "write_blockage" "arm")
297 (define_cpu_unit "core" "arm")
299 (define_insn_reservation "r_mem_f_wbuf" 5
300 (and (eq_attr "model_wbuf" "yes")
301 (eq_attr "type" "r_mem_f"))
304 (define_insn_reservation "store1_wbuf" 5
305 (and (eq_attr "model_wbuf" "yes")
306 (eq_attr "type" "store1"))
307 "core+write_buf*3+write_blockage*5")
309 (define_insn_reservation "store2_wbuf" 7
310 (and (eq_attr "model_wbuf" "yes")
311 (eq_attr "type" "store2"))
312 "core+write_buf*4+write_blockage*7")
314 (define_insn_reservation "store3_wbuf" 9
315 (and (eq_attr "model_wbuf" "yes")
316 (eq_attr "type" "store3"))
317 "core+write_buf*5+write_blockage*9")
319 (define_insn_reservation "store4_wbuf" 11
320 (and (eq_attr "model_wbuf" "yes")
321 (eq_attr "type" "store4"))
322 "core+write_buf*6+write_blockage*11")
324 (define_insn_reservation "store2" 3
325 (and (eq_attr "model_wbuf" "no")
326 (eq_attr "type" "store2"))
329 (define_insn_reservation "store3" 4
330 (and (eq_attr "model_wbuf" "no")
331 (eq_attr "type" "store3"))
334 (define_insn_reservation "store4" 5
335 (and (eq_attr "model_wbuf" "no")
336 (eq_attr "type" "store4"))
339 (define_insn_reservation "store1_ldsched" 1
340 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1"))
343 (define_insn_reservation "load_ldsched_xscale" 3
344 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
345 (eq_attr "is_xscale" "yes"))
348 (define_insn_reservation "load_ldsched" 2
349 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
350 (eq_attr "is_xscale" "no"))
353 (define_insn_reservation "load_or_store" 2
354 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1"))
357 (define_insn_reservation "mult" 16
358 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult"))
361 (define_insn_reservation "mult_ldsched_strongarm" 3
362 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
363 (eq_attr "type" "mult"))
366 (define_insn_reservation "mult_ldsched" 4
367 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
368 (eq_attr "type" "mult"))
371 (define_insn_reservation "multi_cycle" 32
372 (and (eq_attr "core_cycles" "multi")
373 (eq_attr "type" "!mult,load,store1,store2,store3,store4"))
376 (define_insn_reservation "single_cycle" 1
377 (eq_attr "core_cycles" "single")
381 ;;---------------------------------------------------------------------------
386 ;; Note: For DImode insns, there is normally no reason why operands should
387 ;; not be in the same register, what we don't want is for something being
388 ;; written to partially overlap something that is an input.
389 ;; Cirrus 64bit additions should not be split because we have a native
390 ;; 64bit addition instructions.
392 (define_expand "adddi3"
394 [(set (match_operand:DI 0 "s_register_operand" "")
395 (plus:DI (match_operand:DI 1 "s_register_operand" "")
396 (match_operand:DI 2 "s_register_operand" "")))
397 (clobber (reg:CC CC_REGNUM))])]
402 if (!cirrus_fp_register (operands[0], DImode))
403 operands[0] = force_reg (DImode, operands[0]);
404 if (!cirrus_fp_register (operands[1], DImode))
405 operands[1] = force_reg (DImode, operands[1]);
406 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
412 if (GET_CODE (operands[1]) != REG)
413 operands[1] = force_reg (SImode, operands[1]);
414 if (GET_CODE (operands[2]) != REG)
415 operands[2] = force_reg (SImode, operands[2]);
420 (define_insn "*thumb_adddi3"
421 [(set (match_operand:DI 0 "register_operand" "=l")
422 (plus:DI (match_operand:DI 1 "register_operand" "%0")
423 (match_operand:DI 2 "register_operand" "l")))
424 (clobber (reg:CC CC_REGNUM))
427 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
428 [(set_attr "length" "4")]
431 (define_insn_and_split "*arm_adddi3"
432 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
433 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
434 (match_operand:DI 2 "s_register_operand" "r, 0")))
435 (clobber (reg:CC CC_REGNUM))]
436 "TARGET_ARM && !TARGET_CIRRUS"
438 "TARGET_ARM && reload_completed"
439 [(parallel [(set (reg:CC_C CC_REGNUM)
440 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
442 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
443 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
444 (plus:SI (match_dup 4) (match_dup 5))))]
447 operands[3] = gen_highpart (SImode, operands[0]);
448 operands[0] = gen_lowpart (SImode, operands[0]);
449 operands[4] = gen_highpart (SImode, operands[1]);
450 operands[1] = gen_lowpart (SImode, operands[1]);
451 operands[5] = gen_highpart (SImode, operands[2]);
452 operands[2] = gen_lowpart (SImode, operands[2]);
454 [(set_attr "conds" "clob")
455 (set_attr "length" "8")]
458 (define_insn_and_split "*adddi_sesidi_di"
459 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
460 (plus:DI (sign_extend:DI
461 (match_operand:SI 2 "s_register_operand" "r,r"))
462 (match_operand:DI 1 "s_register_operand" "r,0")))
463 (clobber (reg:CC CC_REGNUM))]
464 "TARGET_ARM && !TARGET_CIRRUS"
466 "TARGET_ARM && reload_completed"
467 [(parallel [(set (reg:CC_C CC_REGNUM)
468 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
470 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
471 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
472 (plus:SI (ashiftrt:SI (match_dup 2)
477 operands[3] = gen_highpart (SImode, operands[0]);
478 operands[0] = gen_lowpart (SImode, operands[0]);
479 operands[4] = gen_highpart (SImode, operands[1]);
480 operands[1] = gen_lowpart (SImode, operands[1]);
481 operands[2] = gen_lowpart (SImode, operands[2]);
483 [(set_attr "conds" "clob")
484 (set_attr "length" "8")]
487 (define_insn_and_split "*adddi_zesidi_di"
488 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
489 (plus:DI (zero_extend:DI
490 (match_operand:SI 2 "s_register_operand" "r,r"))
491 (match_operand:DI 1 "s_register_operand" "r,0")))
492 (clobber (reg:CC CC_REGNUM))]
493 "TARGET_ARM && !TARGET_CIRRUS"
495 "TARGET_ARM && reload_completed"
496 [(parallel [(set (reg:CC_C CC_REGNUM)
497 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
499 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
500 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
501 (plus:SI (match_dup 4) (const_int 0))))]
504 operands[3] = gen_highpart (SImode, operands[0]);
505 operands[0] = gen_lowpart (SImode, operands[0]);
506 operands[4] = gen_highpart (SImode, operands[1]);
507 operands[1] = gen_lowpart (SImode, operands[1]);
508 operands[2] = gen_lowpart (SImode, operands[2]);
510 [(set_attr "conds" "clob")
511 (set_attr "length" "8")]
514 (define_expand "addsi3"
515 [(set (match_operand:SI 0 "s_register_operand" "")
516 (plus:SI (match_operand:SI 1 "s_register_operand" "")
517 (match_operand:SI 2 "reg_or_int_operand" "")))]
520 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
522 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
524 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
530 ; If there is a scratch available, this will be faster than synthesizing the
533 [(match_scratch:SI 3 "r")
534 (set (match_operand:SI 0 "s_register_operand" "")
535 (plus:SI (match_operand:SI 1 "s_register_operand" "")
536 (match_operand:SI 2 "const_int_operand" "")))]
538 !(const_ok_for_arm (INTVAL (operands[2]))
539 || const_ok_for_arm (-INTVAL (operands[2])))
540 && const_ok_for_arm (~INTVAL (operands[2]))"
541 [(set (match_dup 3) (match_dup 2))
542 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
546 (define_insn_and_split "*arm_addsi3"
547 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
548 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
549 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
556 GET_CODE (operands[2]) == CONST_INT
557 && !(const_ok_for_arm (INTVAL (operands[2]))
558 || const_ok_for_arm (-INTVAL (operands[2])))"
559 [(clobber (const_int 0))]
561 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
565 [(set_attr "length" "4,4,16")
566 (set_attr "predicable" "yes")]
569 ;; Register group 'k' is a single register group containing only the stack
570 ;; register. Trying to reload it will always fail catastrophically,
571 ;; so never allow those alternatives to match if reloading is needed.
573 (define_insn "*thumb_addsi3"
574 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
575 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
576 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
579 static const char * const asms[] =
581 \"add\\t%0, %0, %2\",
582 \"sub\\t%0, %0, #%n2\",
583 \"add\\t%0, %1, %2\",
584 \"add\\t%0, %0, %2\",
585 \"add\\t%0, %0, %2\",
586 \"add\\t%0, %1, %2\",
589 if ((which_alternative == 2 || which_alternative == 6)
590 && GET_CODE (operands[2]) == CONST_INT
591 && INTVAL (operands[2]) < 0)
592 return \"sub\\t%0, %1, #%n2\";
593 return asms[which_alternative];
595 [(set_attr "length" "2")]
598 ;; Reloading and elimination of the frame pointer can
599 ;; sometimes cause this optimization to be missed.
601 [(set (match_operand:SI 0 "register_operand" "")
602 (match_operand:SI 1 "const_int_operand" ""))
604 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
606 && REGNO (operands[2]) == STACK_POINTER_REGNUM
607 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
608 && (INTVAL (operands[1]) & 3) == 0"
609 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
613 (define_insn "*addsi3_compare0"
614 [(set (reg:CC_NOOV CC_REGNUM)
616 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
617 (match_operand:SI 2 "arm_add_operand" "rI,L"))
619 (set (match_operand:SI 0 "s_register_operand" "=r,r")
620 (plus:SI (match_dup 1) (match_dup 2)))]
624 sub%?s\\t%0, %1, #%n2"
625 [(set_attr "conds" "set")]
628 (define_insn "*addsi3_compare0_scratch"
629 [(set (reg:CC_NOOV CC_REGNUM)
631 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
632 (match_operand:SI 1 "arm_add_operand" "rI,L"))
638 [(set_attr "conds" "set")]
641 ;; These patterns are the same ones as the two regular addsi3_compare0
642 ;; patterns, except we write them slightly different - the combiner
643 ;; tends to generate them this way.
644 (define_insn "*addsi3_compare0_for_combiner"
645 [(set (reg:CC CC_REGNUM)
647 (match_operand:SI 1 "s_register_operand" "r,r")
648 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
649 (set (match_operand:SI 0 "s_register_operand" "=r,r")
650 (plus:SI (match_dup 1) (match_dup 2)))]
654 sub%?s\\t%0, %1, #%n2"
655 [(set_attr "conds" "set")]
658 (define_insn "*addsi3_compare0_scratch_for_combiner"
659 [(set (reg:CC CC_REGNUM)
661 (match_operand:SI 0 "s_register_operand" "r,r")
662 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
667 [(set_attr "conds" "set")]
670 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
671 ;; addend is a constant.
672 (define_insn "*cmpsi2_addneg"
673 [(set (reg:CC CC_REGNUM)
675 (match_operand:SI 1 "s_register_operand" "r,r")
676 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
677 (set (match_operand:SI 0 "s_register_operand" "=r,r")
678 (plus:SI (match_dup 1)
679 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
680 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
683 add%?s\\t%0, %1, #%n2"
684 [(set_attr "conds" "set")]
687 ;; Convert the sequence
689 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
693 ;; bcs dest ((unsigned)rn >= 1)
694 ;; similarly for the beq variant using bcc.
695 ;; This is a common looping idiom (while (n--))
697 [(set (match_operand:SI 0 "s_register_operand" "")
698 (plus:SI (match_operand:SI 1 "s_register_operand" "")
700 (set (match_operand 2 "cc_register" "")
701 (compare (match_dup 0) (const_int -1)))
703 (if_then_else (match_operator 3 "equality_operator"
704 [(match_dup 2) (const_int 0)])
705 (match_operand 4 "" "")
706 (match_operand 5 "" "")))]
707 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
711 (match_dup 1) (const_int 1)))
712 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
714 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
717 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
718 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
721 operands[2], const0_rtx);"
724 ;; The next four insns work because they compare the result with one of
725 ;; the operands, and we know that the use of the condition code is
726 ;; either GEU or LTU, so we can use the carry flag from the addition
727 ;; instead of doing the compare a second time.
728 (define_insn "*addsi3_compare_op1"
729 [(set (reg:CC_C CC_REGNUM)
731 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
732 (match_operand:SI 2 "arm_add_operand" "rI,L"))
734 (set (match_operand:SI 0 "s_register_operand" "=r,r")
735 (plus:SI (match_dup 1) (match_dup 2)))]
739 sub%?s\\t%0, %1, #%n2"
740 [(set_attr "conds" "set")]
743 (define_insn "*addsi3_compare_op2"
744 [(set (reg:CC_C CC_REGNUM)
746 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
747 (match_operand:SI 2 "arm_add_operand" "rI,L"))
749 (set (match_operand:SI 0 "s_register_operand" "=r,r")
750 (plus:SI (match_dup 1) (match_dup 2)))]
754 sub%?s\\t%0, %1, #%n2"
755 [(set_attr "conds" "set")]
758 (define_insn "*compare_addsi2_op0"
759 [(set (reg:CC_C CC_REGNUM)
761 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
762 (match_operand:SI 1 "arm_add_operand" "rI,L"))
768 [(set_attr "conds" "set")]
771 (define_insn "*compare_addsi2_op1"
772 [(set (reg:CC_C CC_REGNUM)
774 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
775 (match_operand:SI 1 "arm_add_operand" "rI,L"))
781 [(set_attr "conds" "set")]
784 (define_insn "*addsi3_carryin"
785 [(set (match_operand:SI 0 "s_register_operand" "=r")
786 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
787 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
788 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
791 [(set_attr "conds" "use")]
794 (define_insn "*addsi3_carryin_shift"
795 [(set (match_operand:SI 0 "s_register_operand" "")
796 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
798 (match_operator:SI 2 "shift_operator"
799 [(match_operand:SI 3 "s_register_operand" "")
800 (match_operand:SI 4 "reg_or_int_operand" "")])
801 (match_operand:SI 1 "s_register_operand" ""))))]
803 "adc%?\\t%0, %1, %3%S2"
804 [(set_attr "conds" "use")]
807 (define_insn "*addsi3_carryin_alt1"
808 [(set (match_operand:SI 0 "s_register_operand" "=r")
809 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
810 (match_operand:SI 2 "arm_rhs_operand" "rI"))
811 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
814 [(set_attr "conds" "use")]
817 (define_insn "*addsi3_carryin_alt2"
818 [(set (match_operand:SI 0 "s_register_operand" "=r")
819 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
820 (match_operand:SI 1 "s_register_operand" "r"))
821 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
824 [(set_attr "conds" "use")]
827 (define_insn "*addsi3_carryin_alt3"
828 [(set (match_operand:SI 0 "s_register_operand" "=r")
829 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
830 (match_operand:SI 2 "arm_rhs_operand" "rI"))
831 (match_operand:SI 1 "s_register_operand" "r")))]
834 [(set_attr "conds" "use")]
837 (define_insn "incscc"
838 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
839 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
840 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
841 (match_operand:SI 1 "s_register_operand" "0,?r")))]
845 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
846 [(set_attr "conds" "use")
847 (set_attr "length" "4,8")]
850 (define_expand "addsf3"
851 [(set (match_operand:SF 0 "s_register_operand" "")
852 (plus:SF (match_operand:SF 1 "s_register_operand" "")
853 (match_operand:SF 2 "fpa_add_operand" "")))]
854 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
857 && !cirrus_fp_register (operands[2], SFmode))
858 operands[2] = force_reg (SFmode, operands[2]);
861 (define_expand "adddf3"
862 [(set (match_operand:DF 0 "s_register_operand" "")
863 (plus:DF (match_operand:DF 1 "s_register_operand" "")
864 (match_operand:DF 2 "fpa_add_operand" "")))]
865 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
868 && !cirrus_fp_register (operands[2], DFmode))
869 operands[2] = force_reg (DFmode, operands[2]);
872 (define_expand "subdi3"
874 [(set (match_operand:DI 0 "s_register_operand" "")
875 (minus:DI (match_operand:DI 1 "s_register_operand" "")
876 (match_operand:DI 2 "s_register_operand" "")))
877 (clobber (reg:CC CC_REGNUM))])]
882 && cirrus_fp_register (operands[0], DImode)
883 && cirrus_fp_register (operands[1], DImode))
885 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
891 if (GET_CODE (operands[1]) != REG)
892 operands[1] = force_reg (SImode, operands[1]);
893 if (GET_CODE (operands[2]) != REG)
894 operands[2] = force_reg (SImode, operands[2]);
899 (define_insn "*arm_subdi3"
900 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
901 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
902 (match_operand:DI 2 "s_register_operand" "r,0,0")))
903 (clobber (reg:CC CC_REGNUM))]
905 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
906 [(set_attr "conds" "clob")
907 (set_attr "length" "8")]
910 (define_insn "*thumb_subdi3"
911 [(set (match_operand:DI 0 "register_operand" "=l")
912 (minus:DI (match_operand:DI 1 "register_operand" "0")
913 (match_operand:DI 2 "register_operand" "l")))
914 (clobber (reg:CC CC_REGNUM))]
916 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
917 [(set_attr "length" "4")]
920 (define_insn "*subdi_di_zesidi"
921 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
922 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
924 (match_operand:SI 2 "s_register_operand" "r,r"))))
925 (clobber (reg:CC CC_REGNUM))]
927 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
928 [(set_attr "conds" "clob")
929 (set_attr "length" "8")]
932 (define_insn "*subdi_di_sesidi"
933 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
934 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
936 (match_operand:SI 2 "s_register_operand" "r,r"))))
937 (clobber (reg:CC CC_REGNUM))]
939 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
940 [(set_attr "conds" "clob")
941 (set_attr "length" "8")]
944 (define_insn "*subdi_zesidi_di"
945 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
946 (minus:DI (zero_extend:DI
947 (match_operand:SI 2 "s_register_operand" "r,r"))
948 (match_operand:DI 1 "s_register_operand" "?r,0")))
949 (clobber (reg:CC CC_REGNUM))]
951 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
952 [(set_attr "conds" "clob")
953 (set_attr "length" "8")]
956 (define_insn "*subdi_sesidi_di"
957 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
958 (minus:DI (sign_extend:DI
959 (match_operand:SI 2 "s_register_operand" "r,r"))
960 (match_operand:DI 1 "s_register_operand" "?r,0")))
961 (clobber (reg:CC CC_REGNUM))]
963 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
964 [(set_attr "conds" "clob")
965 (set_attr "length" "8")]
968 (define_insn "*subdi_zesidi_zesidi"
969 [(set (match_operand:DI 0 "s_register_operand" "=r")
970 (minus:DI (zero_extend:DI
971 (match_operand:SI 1 "s_register_operand" "r"))
973 (match_operand:SI 2 "s_register_operand" "r"))))
974 (clobber (reg:CC CC_REGNUM))]
976 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
977 [(set_attr "conds" "clob")
978 (set_attr "length" "8")]
981 (define_expand "subsi3"
982 [(set (match_operand:SI 0 "s_register_operand" "")
983 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
984 (match_operand:SI 2 "s_register_operand" "")))]
987 if (GET_CODE (operands[1]) == CONST_INT)
991 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
994 : preserve_subexpressions_p ()));
997 else /* TARGET_THUMB */
998 operands[1] = force_reg (SImode, operands[1]);
1003 (define_insn "*thumb_subsi3_insn"
1004 [(set (match_operand:SI 0 "register_operand" "=l")
1005 (minus:SI (match_operand:SI 1 "register_operand" "l")
1006 (match_operand:SI 2 "register_operand" "l")))]
1009 [(set_attr "length" "2")]
1012 (define_insn_and_split "*arm_subsi3_insn"
1013 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1014 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1015 (match_operand:SI 2 "s_register_operand" "r,r")))]
1021 && GET_CODE (operands[1]) == CONST_INT
1022 && !const_ok_for_arm (INTVAL (operands[1]))"
1023 [(clobber (const_int 0))]
1025 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1029 [(set_attr "length" "4,16")
1030 (set_attr "predicable" "yes")]
1034 [(match_scratch:SI 3 "r")
1035 (set (match_operand:SI 0 "s_register_operand" "")
1036 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1037 (match_operand:SI 2 "s_register_operand" "")))]
1039 && !const_ok_for_arm (INTVAL (operands[1]))
1040 && const_ok_for_arm (~INTVAL (operands[1]))"
1041 [(set (match_dup 3) (match_dup 1))
1042 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1046 (define_insn "*subsi3_compare0"
1047 [(set (reg:CC_NOOV CC_REGNUM)
1049 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1050 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1052 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1053 (minus:SI (match_dup 1) (match_dup 2)))]
1057 rsb%?s\\t%0, %2, %1"
1058 [(set_attr "conds" "set")]
1061 (define_insn "decscc"
1062 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1063 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1064 (match_operator:SI 2 "arm_comparison_operator"
1065 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1069 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1070 [(set_attr "conds" "use")
1071 (set_attr "length" "*,8")]
1074 (define_expand "subsf3"
1075 [(set (match_operand:SF 0 "s_register_operand" "")
1076 (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1077 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1078 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1082 if (!cirrus_fp_register (operands[1], SFmode))
1083 operands[1] = force_reg (SFmode, operands[1]);
1084 if (!cirrus_fp_register (operands[2], SFmode))
1085 operands[2] = force_reg (SFmode, operands[2]);
1089 (define_expand "subdf3"
1090 [(set (match_operand:DF 0 "s_register_operand" "")
1091 (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1092 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1093 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1097 if (!cirrus_fp_register (operands[1], DFmode))
1098 operands[1] = force_reg (DFmode, operands[1]);
1099 if (!cirrus_fp_register (operands[2], DFmode))
1100 operands[2] = force_reg (DFmode, operands[2]);
1105 ;; Multiplication insns
1107 (define_expand "mulsi3"
1108 [(set (match_operand:SI 0 "s_register_operand" "")
1109 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1110 (match_operand:SI 1 "s_register_operand" "")))]
1115 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1116 (define_insn "*arm_mulsi3"
1117 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1118 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1119 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1121 "mul%?\\t%0, %2, %1"
1122 [(set_attr "type" "mult")
1123 (set_attr "predicable" "yes")]
1126 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1127 ; 1 and 2; are the same, because reload will make operand 0 match
1128 ; operand 1 without realizing that this conflicts with operand 2. We fix
1129 ; this by adding another alternative to match this case, and then `reload'
1130 ; it ourselves. This alternative must come first.
1131 (define_insn "*thumb_mulsi3"
1132 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1133 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1134 (match_operand:SI 2 "register_operand" "l,l,l")))]
1137 if (which_alternative < 2)
1138 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1140 return \"mul\\t%0, %0, %2\";
1142 [(set_attr "length" "4,4,2")
1143 (set_attr "type" "mult")]
1146 (define_insn "*mulsi3_compare0"
1147 [(set (reg:CC_NOOV CC_REGNUM)
1148 (compare:CC_NOOV (mult:SI
1149 (match_operand:SI 2 "s_register_operand" "r,r")
1150 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1152 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1153 (mult:SI (match_dup 2) (match_dup 1)))]
1154 "TARGET_ARM && !arm_arch_xscale"
1155 "mul%?s\\t%0, %2, %1"
1156 [(set_attr "conds" "set")
1157 (set_attr "type" "mult")]
1160 (define_insn "*mulsi_compare0_scratch"
1161 [(set (reg:CC_NOOV CC_REGNUM)
1162 (compare:CC_NOOV (mult:SI
1163 (match_operand:SI 2 "s_register_operand" "r,r")
1164 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1166 (clobber (match_scratch:SI 0 "=&r,&r"))]
1167 "TARGET_ARM && !arm_arch_xscale"
1168 "mul%?s\\t%0, %2, %1"
1169 [(set_attr "conds" "set")
1170 (set_attr "type" "mult")]
1173 ;; Unnamed templates to match MLA instruction.
1175 (define_insn "*mulsi3addsi"
1176 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1178 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1179 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1180 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1182 "mla%?\\t%0, %2, %1, %3"
1183 [(set_attr "type" "mult")
1184 (set_attr "predicable" "yes")]
1187 (define_insn "*mulsi3addsi_compare0"
1188 [(set (reg:CC_NOOV CC_REGNUM)
1191 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1192 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1193 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1195 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1196 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1198 "TARGET_ARM && !arm_arch_xscale"
1199 "mla%?s\\t%0, %2, %1, %3"
1200 [(set_attr "conds" "set")
1201 (set_attr "type" "mult")]
1204 (define_insn "*mulsi3addsi_compare0_scratch"
1205 [(set (reg:CC_NOOV CC_REGNUM)
1208 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1209 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1210 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1212 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1213 "TARGET_ARM && !arm_arch_xscale"
1214 "mla%?s\\t%0, %2, %1, %3"
1215 [(set_attr "conds" "set")
1216 (set_attr "type" "mult")]
1219 ;; Unnamed template to match long long multiply-accumlate (smlal)
1221 (define_insn "*mulsidi3adddi"
1222 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1225 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1226 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1227 (match_operand:DI 1 "s_register_operand" "0")))]
1228 "TARGET_ARM && arm_fast_multiply"
1229 "smlal%?\\t%Q0, %R0, %3, %2"
1230 [(set_attr "type" "mult")
1231 (set_attr "predicable" "yes")]
1234 (define_insn "mulsidi3"
1235 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1237 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1238 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1239 "TARGET_ARM && arm_fast_multiply"
1240 "smull%?\\t%Q0, %R0, %1, %2"
1241 [(set_attr "type" "mult")
1242 (set_attr "predicable" "yes")]
1245 (define_insn "umulsidi3"
1246 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1248 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1249 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1250 "TARGET_ARM && arm_fast_multiply"
1251 "umull%?\\t%Q0, %R0, %1, %2"
1252 [(set_attr "type" "mult")
1253 (set_attr "predicable" "yes")]
1256 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1258 (define_insn "*umulsidi3adddi"
1259 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1262 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1263 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1264 (match_operand:DI 1 "s_register_operand" "0")))]
1265 "TARGET_ARM && arm_fast_multiply"
1266 "umlal%?\\t%Q0, %R0, %3, %2"
1267 [(set_attr "type" "mult")
1268 (set_attr "predicable" "yes")]
1271 (define_insn "smulsi3_highpart"
1272 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1276 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1277 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1279 (clobber (match_scratch:SI 3 "=&r,&r"))]
1280 "TARGET_ARM && arm_fast_multiply"
1281 "smull%?\\t%3, %0, %2, %1"
1282 [(set_attr "type" "mult")
1283 (set_attr "predicable" "yes")]
1286 (define_insn "umulsi3_highpart"
1287 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1291 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1292 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1294 (clobber (match_scratch:SI 3 "=&r,&r"))]
1295 "TARGET_ARM && arm_fast_multiply"
1296 "umull%?\\t%3, %0, %2, %1"
1297 [(set_attr "type" "mult")
1298 (set_attr "predicable" "yes")]
1301 (define_insn "mulhisi3"
1302 [(set (match_operand:SI 0 "s_register_operand" "=r")
1303 (mult:SI (sign_extend:SI
1304 (match_operand:HI 1 "s_register_operand" "%r"))
1306 (match_operand:HI 2 "s_register_operand" "r"))))]
1307 "TARGET_ARM && arm_arch5e"
1308 "smulbb%?\\t%0, %1, %2"
1309 [(set_attr "type" "mult")
1310 (set_attr "predicable" "yes")]
1313 (define_insn "*mulhisi3tb"
1314 [(set (match_operand:SI 0 "s_register_operand" "=r")
1315 (mult:SI (ashiftrt:SI
1316 (match_operand:SI 1 "s_register_operand" "r")
1319 (match_operand:HI 2 "s_register_operand" "r"))))]
1320 "TARGET_ARM && arm_arch5e"
1321 "smultb%?\\t%0, %1, %2"
1322 [(set_attr "type" "mult")
1323 (set_attr "predicable" "yes")]
1326 (define_insn "*mulhisi3bt"
1327 [(set (match_operand:SI 0 "s_register_operand" "=r")
1328 (mult:SI (sign_extend:SI
1329 (match_operand:HI 1 "s_register_operand" "r"))
1331 (match_operand:SI 2 "s_register_operand" "r")
1333 "TARGET_ARM && arm_arch5e"
1334 "smulbt%?\\t%0, %1, %2"
1335 [(set_attr "type" "mult")
1336 (set_attr "predicable" "yes")]
1339 (define_insn "*mulhisi3tt"
1340 [(set (match_operand:SI 0 "s_register_operand" "=r")
1341 (mult:SI (ashiftrt:SI
1342 (match_operand:SI 1 "s_register_operand" "r")
1345 (match_operand:SI 2 "s_register_operand" "r")
1347 "TARGET_ARM && arm_arch5e"
1348 "smultt%?\\t%0, %1, %2"
1349 [(set_attr "type" "mult")
1350 (set_attr "predicable" "yes")]
1353 (define_insn "*mulhisi3addsi"
1354 [(set (match_operand:SI 0 "s_register_operand" "=r")
1355 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1356 (mult:SI (sign_extend:SI
1357 (match_operand:HI 2 "s_register_operand" "%r"))
1359 (match_operand:HI 3 "s_register_operand" "r")))))]
1360 "TARGET_ARM && arm_arch5e"
1361 "smlabb%?\\t%0, %2, %3, %1"
1362 [(set_attr "type" "mult")
1363 (set_attr "predicable" "yes")]
1366 (define_insn "*mulhidi3adddi"
1367 [(set (match_operand:DI 0 "s_register_operand" "=r")
1369 (match_operand:DI 1 "s_register_operand" "0")
1370 (mult:DI (sign_extend:DI
1371 (match_operand:HI 2 "s_register_operand" "%r"))
1373 (match_operand:HI 3 "s_register_operand" "r")))))]
1374 "TARGET_ARM && arm_arch5e"
1375 "smlalbb%?\\t%Q0, %R0, %2, %3"
1376 [(set_attr "type" "mult")
1377 (set_attr "predicable" "yes")])
1379 (define_expand "mulsf3"
1380 [(set (match_operand:SF 0 "s_register_operand" "")
1381 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1382 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1383 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1386 && !cirrus_fp_register (operands[2], SFmode))
1387 operands[2] = force_reg (SFmode, operands[2]);
1390 (define_expand "muldf3"
1391 [(set (match_operand:DF 0 "s_register_operand" "")
1392 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1393 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1394 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1397 && !cirrus_fp_register (operands[2], DFmode))
1398 operands[2] = force_reg (DFmode, operands[2]);
1403 (define_expand "divsf3"
1404 [(set (match_operand:SF 0 "s_register_operand" "")
1405 (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1406 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1407 "TARGET_ARM && TARGET_HARD_FLOAT"
1410 (define_expand "divdf3"
1411 [(set (match_operand:DF 0 "s_register_operand" "")
1412 (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1413 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1414 "TARGET_ARM && TARGET_HARD_FLOAT"
1419 (define_expand "modsf3"
1420 [(set (match_operand:SF 0 "s_register_operand" "")
1421 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1422 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1423 "TARGET_ARM && TARGET_HARD_FLOAT"
1426 (define_expand "moddf3"
1427 [(set (match_operand:DF 0 "s_register_operand" "")
1428 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1429 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1430 "TARGET_ARM && TARGET_HARD_FLOAT"
1433 ;; Boolean and,ior,xor insns
1435 ;; Split up double word logical operations
1437 ;; Split up simple DImode logical operations. Simply perform the logical
1438 ;; operation on the upper and lower halves of the registers.
1440 [(set (match_operand:DI 0 "s_register_operand" "")
1441 (match_operator:DI 6 "logical_binary_operator"
1442 [(match_operand:DI 1 "s_register_operand" "")
1443 (match_operand:DI 2 "s_register_operand" "")]))]
1444 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1445 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1446 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1449 operands[3] = gen_highpart (SImode, operands[0]);
1450 operands[0] = gen_lowpart (SImode, operands[0]);
1451 operands[4] = gen_highpart (SImode, operands[1]);
1452 operands[1] = gen_lowpart (SImode, operands[1]);
1453 operands[5] = gen_highpart (SImode, operands[2]);
1454 operands[2] = gen_lowpart (SImode, operands[2]);
1459 [(set (match_operand:DI 0 "s_register_operand" "")
1460 (match_operator:DI 6 "logical_binary_operator"
1461 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1462 (match_operand:DI 1 "s_register_operand" "")]))]
1463 "TARGET_ARM && reload_completed"
1464 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1465 (set (match_dup 3) (match_op_dup:SI 6
1466 [(ashiftrt:SI (match_dup 2) (const_int 31))
1470 operands[3] = gen_highpart (SImode, operands[0]);
1471 operands[0] = gen_lowpart (SImode, operands[0]);
1472 operands[4] = gen_highpart (SImode, operands[1]);
1473 operands[1] = gen_lowpart (SImode, operands[1]);
1474 operands[5] = gen_highpart (SImode, operands[2]);
1475 operands[2] = gen_lowpart (SImode, operands[2]);
1479 ;; The zero extend of operand 2 means we can just copy the high part of
1480 ;; operand1 into operand0.
1482 [(set (match_operand:DI 0 "s_register_operand" "")
1484 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1485 (match_operand:DI 1 "s_register_operand" "")))]
1486 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1487 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1488 (set (match_dup 3) (match_dup 4))]
1491 operands[4] = gen_highpart (SImode, operands[1]);
1492 operands[3] = gen_highpart (SImode, operands[0]);
1493 operands[0] = gen_lowpart (SImode, operands[0]);
1494 operands[1] = gen_lowpart (SImode, operands[1]);
1498 ;; The zero extend of operand 2 means we can just copy the high part of
1499 ;; operand1 into operand0.
1501 [(set (match_operand:DI 0 "s_register_operand" "")
1503 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1504 (match_operand:DI 1 "s_register_operand" "")))]
1505 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1506 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1507 (set (match_dup 3) (match_dup 4))]
1510 operands[4] = gen_highpart (SImode, operands[1]);
1511 operands[3] = gen_highpart (SImode, operands[0]);
1512 operands[0] = gen_lowpart (SImode, operands[0]);
1513 operands[1] = gen_lowpart (SImode, operands[1]);
1517 (define_insn "anddi3"
1518 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1519 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1520 (match_operand:DI 2 "s_register_operand" "r,r")))]
1521 "TARGET_ARM && ! TARGET_IWMMXT"
1523 [(set_attr "length" "8")]
1526 (define_insn_and_split "*anddi_zesidi_di"
1527 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1528 (and:DI (zero_extend:DI
1529 (match_operand:SI 2 "s_register_operand" "r,r"))
1530 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1533 "TARGET_ARM && reload_completed"
1534 ; The zero extend of operand 2 clears the high word of the output
1536 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1537 (set (match_dup 3) (const_int 0))]
1540 operands[3] = gen_highpart (SImode, operands[0]);
1541 operands[0] = gen_lowpart (SImode, operands[0]);
1542 operands[1] = gen_lowpart (SImode, operands[1]);
1544 [(set_attr "length" "8")]
1547 (define_insn "*anddi_sesdi_di"
1548 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1549 (and:DI (sign_extend:DI
1550 (match_operand:SI 2 "s_register_operand" "r,r"))
1551 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1554 [(set_attr "length" "8")]
1557 (define_expand "andsi3"
1558 [(set (match_operand:SI 0 "s_register_operand" "")
1559 (and:SI (match_operand:SI 1 "s_register_operand" "")
1560 (match_operand:SI 2 "reg_or_int_operand" "")))]
1565 if (GET_CODE (operands[2]) == CONST_INT)
1567 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1570 ? 0 : preserve_subexpressions_p ()));
1574 else /* TARGET_THUMB */
1576 if (GET_CODE (operands[2]) != CONST_INT)
1577 operands[2] = force_reg (SImode, operands[2]);
1582 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1584 operands[2] = force_reg (SImode,
1585 GEN_INT (~INTVAL (operands[2])));
1587 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1592 for (i = 9; i <= 31; i++)
1594 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1596 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1600 else if ((((HOST_WIDE_INT) 1) << i) - 1
1601 == ~INTVAL (operands[2]))
1603 rtx shift = GEN_INT (i);
1604 rtx reg = gen_reg_rtx (SImode);
1606 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1607 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1613 operands[2] = force_reg (SImode, operands[2]);
1619 (define_insn_and_split "*arm_andsi3_insn"
1620 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1621 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1622 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1626 bic%?\\t%0, %1, #%B2
1629 && GET_CODE (operands[2]) == CONST_INT
1630 && !(const_ok_for_arm (INTVAL (operands[2]))
1631 || const_ok_for_arm (~INTVAL (operands[2])))"
1632 [(clobber (const_int 0))]
1634 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1638 [(set_attr "length" "4,4,16")
1639 (set_attr "predicable" "yes")]
1642 (define_insn "*thumb_andsi3_insn"
1643 [(set (match_operand:SI 0 "register_operand" "=l")
1644 (and:SI (match_operand:SI 1 "register_operand" "%0")
1645 (match_operand:SI 2 "register_operand" "l")))]
1648 [(set_attr "length" "2")]
1651 (define_insn "*andsi3_compare0"
1652 [(set (reg:CC_NOOV CC_REGNUM)
1654 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1655 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1657 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1658 (and:SI (match_dup 1) (match_dup 2)))]
1662 bic%?s\\t%0, %1, #%B2"
1663 [(set_attr "conds" "set")]
1666 (define_insn "*andsi3_compare0_scratch"
1667 [(set (reg:CC_NOOV CC_REGNUM)
1669 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1670 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1672 (clobber (match_scratch:SI 2 "=X,r"))]
1676 bic%?s\\t%2, %0, #%B1"
1677 [(set_attr "conds" "set")]
1680 (define_insn "*zeroextractsi_compare0_scratch"
1681 [(set (reg:CC_NOOV CC_REGNUM)
1682 (compare:CC_NOOV (zero_extract:SI
1683 (match_operand:SI 0 "s_register_operand" "r")
1684 (match_operand 1 "const_int_operand" "n")
1685 (match_operand 2 "const_int_operand" "n"))
1688 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1689 && INTVAL (operands[1]) > 0
1690 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1691 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1693 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1694 << INTVAL (operands[2]));
1695 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1698 [(set_attr "conds" "set")]
1701 (define_insn "*ne_zeroextractsi"
1702 [(set (match_operand:SI 0 "s_register_operand" "=r")
1703 (ne:SI (zero_extract:SI
1704 (match_operand:SI 1 "s_register_operand" "r")
1705 (match_operand:SI 2 "const_int_operand" "n")
1706 (match_operand:SI 3 "const_int_operand" "n"))
1708 (clobber (reg:CC CC_REGNUM))]
1710 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1711 && INTVAL (operands[2]) > 0
1712 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1713 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1715 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1716 << INTVAL (operands[3]));
1717 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1718 return \"movne\\t%0, #1\";
1720 [(set_attr "conds" "clob")
1721 (set_attr "length" "8")]
1724 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1725 ;;; represented by the bitfield, then this will produce incorrect results.
1726 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1727 ;;; which have a real bit-field insert instruction, the truncation happens
1728 ;;; in the bit-field insert instruction itself. Since arm does not have a
1729 ;;; bit-field insert instruction, we would have to emit code here to truncate
1730 ;;; the value before we insert. This loses some of the advantage of having
1731 ;;; this insv pattern, so this pattern needs to be reevalutated.
1733 (define_expand "insv"
1734 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1735 (match_operand:SI 1 "general_operand" "")
1736 (match_operand:SI 2 "general_operand" ""))
1737 (match_operand:SI 3 "reg_or_int_operand" ""))]
1741 int start_bit = INTVAL (operands[2]);
1742 int width = INTVAL (operands[1]);
1743 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1744 rtx target, subtarget;
1746 target = operands[0];
1747 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1748 subreg as the final target. */
1749 if (GET_CODE (target) == SUBREG)
1751 subtarget = gen_reg_rtx (SImode);
1752 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1753 < GET_MODE_SIZE (SImode))
1754 target = SUBREG_REG (target);
1759 if (GET_CODE (operands[3]) == CONST_INT)
1761 /* Since we are inserting a known constant, we may be able to
1762 reduce the number of bits that we have to clear so that
1763 the mask becomes simple. */
1764 /* ??? This code does not check to see if the new mask is actually
1765 simpler. It may not be. */
1766 rtx op1 = gen_reg_rtx (SImode);
1767 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1768 start of this pattern. */
1769 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1770 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1772 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1773 emit_insn (gen_iorsi3 (subtarget, op1,
1774 GEN_INT (op3_value << start_bit)));
1776 else if (start_bit == 0
1777 && !(const_ok_for_arm (mask)
1778 || const_ok_for_arm (~mask)))
1780 /* A Trick, since we are setting the bottom bits in the word,
1781 we can shift operand[3] up, operand[0] down, OR them together
1782 and rotate the result back again. This takes 3 insns, and
1783 the third might be mergeable into another op. */
1784 /* The shift up copes with the possibility that operand[3] is
1785 wider than the bitfield. */
1786 rtx op0 = gen_reg_rtx (SImode);
1787 rtx op1 = gen_reg_rtx (SImode);
1789 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1790 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1791 emit_insn (gen_iorsi3 (op1, op1, op0));
1792 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1794 else if ((width + start_bit == 32)
1795 && !(const_ok_for_arm (mask)
1796 || const_ok_for_arm (~mask)))
1798 /* Similar trick, but slightly less efficient. */
1800 rtx op0 = gen_reg_rtx (SImode);
1801 rtx op1 = gen_reg_rtx (SImode);
1803 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1804 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1805 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1806 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1810 rtx op0 = GEN_INT (mask);
1811 rtx op1 = gen_reg_rtx (SImode);
1812 rtx op2 = gen_reg_rtx (SImode);
1814 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1816 rtx tmp = gen_reg_rtx (SImode);
1818 emit_insn (gen_movsi (tmp, op0));
1822 /* Mask out any bits in operand[3] that are not needed. */
1823 emit_insn (gen_andsi3 (op1, operands[3], op0));
1825 if (GET_CODE (op0) == CONST_INT
1826 && (const_ok_for_arm (mask << start_bit)
1827 || const_ok_for_arm (~(mask << start_bit))))
1829 op0 = GEN_INT (~(mask << start_bit));
1830 emit_insn (gen_andsi3 (op2, operands[0], op0));
1834 if (GET_CODE (op0) == CONST_INT)
1836 rtx tmp = gen_reg_rtx (SImode);
1838 emit_insn (gen_movsi (tmp, op0));
1843 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1845 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1849 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1851 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1854 if (subtarget != target)
1856 /* If TARGET is still a SUBREG, then it must be wider than a word,
1857 so we must be careful only to set the subword we were asked to. */
1858 if (GET_CODE (target) == SUBREG)
1859 emit_move_insn (target, subtarget);
1861 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1868 ; constants for op 2 will never be given to these patterns.
1869 (define_insn_and_split "*anddi_notdi_di"
1870 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1871 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1872 (match_operand:DI 2 "s_register_operand" "0,r")))]
1875 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1876 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1877 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1880 operands[3] = gen_highpart (SImode, operands[0]);
1881 operands[0] = gen_lowpart (SImode, operands[0]);
1882 operands[4] = gen_highpart (SImode, operands[1]);
1883 operands[1] = gen_lowpart (SImode, operands[1]);
1884 operands[5] = gen_highpart (SImode, operands[2]);
1885 operands[2] = gen_lowpart (SImode, operands[2]);
1887 [(set_attr "length" "8")
1888 (set_attr "predicable" "yes")]
1891 (define_insn_and_split "*anddi_notzesidi_di"
1892 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1893 (and:DI (not:DI (zero_extend:DI
1894 (match_operand:SI 2 "s_register_operand" "r,r")))
1895 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1898 bic%?\\t%Q0, %Q1, %2
1900 ; (not (zero_extend ...)) allows us to just copy the high word from
1901 ; operand1 to operand0.
1904 && operands[0] != operands[1]"
1905 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1906 (set (match_dup 3) (match_dup 4))]
1909 operands[3] = gen_highpart (SImode, operands[0]);
1910 operands[0] = gen_lowpart (SImode, operands[0]);
1911 operands[4] = gen_highpart (SImode, operands[1]);
1912 operands[1] = gen_lowpart (SImode, operands[1]);
1914 [(set_attr "length" "4,8")
1915 (set_attr "predicable" "yes")]
1918 (define_insn_and_split "*anddi_notsesidi_di"
1919 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1920 (and:DI (not:DI (sign_extend:DI
1921 (match_operand:SI 2 "s_register_operand" "r,r")))
1922 (match_operand:DI 1 "s_register_operand" "0,r")))]
1925 "TARGET_ARM && reload_completed"
1926 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1927 (set (match_dup 3) (and:SI (not:SI
1928 (ashiftrt:SI (match_dup 2) (const_int 31)))
1932 operands[3] = gen_highpart (SImode, operands[0]);
1933 operands[0] = gen_lowpart (SImode, operands[0]);
1934 operands[4] = gen_highpart (SImode, operands[1]);
1935 operands[1] = gen_lowpart (SImode, operands[1]);
1937 [(set_attr "length" "8")
1938 (set_attr "predicable" "yes")]
1941 (define_insn "andsi_notsi_si"
1942 [(set (match_operand:SI 0 "s_register_operand" "=r")
1943 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1944 (match_operand:SI 1 "s_register_operand" "r")))]
1946 "bic%?\\t%0, %1, %2"
1947 [(set_attr "predicable" "yes")]
1950 (define_insn "bicsi3"
1951 [(set (match_operand:SI 0 "register_operand" "=l")
1952 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1953 (match_operand:SI 2 "register_operand" "0")))]
1956 [(set_attr "length" "2")]
1959 (define_insn "andsi_not_shiftsi_si"
1960 [(set (match_operand:SI 0 "s_register_operand" "=r")
1961 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1962 [(match_operand:SI 2 "s_register_operand" "r")
1963 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1964 (match_operand:SI 1 "s_register_operand" "r")))]
1966 "bic%?\\t%0, %1, %2%S4"
1967 [(set_attr "predicable" "yes")
1968 (set_attr "shift" "2")
1972 (define_insn "*andsi_notsi_si_compare0"
1973 [(set (reg:CC_NOOV CC_REGNUM)
1975 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1976 (match_operand:SI 1 "s_register_operand" "r"))
1978 (set (match_operand:SI 0 "s_register_operand" "=r")
1979 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1981 "bic%?s\\t%0, %1, %2"
1982 [(set_attr "conds" "set")]
1985 (define_insn "*andsi_notsi_si_compare0_scratch"
1986 [(set (reg:CC_NOOV CC_REGNUM)
1988 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1989 (match_operand:SI 1 "s_register_operand" "r"))
1991 (clobber (match_scratch:SI 0 "=r"))]
1993 "bic%?s\\t%0, %1, %2"
1994 [(set_attr "conds" "set")]
1997 (define_insn "iordi3"
1998 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1999 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2000 (match_operand:DI 2 "s_register_operand" "r,r")))]
2001 "TARGET_ARM && ! TARGET_IWMMXT"
2003 [(set_attr "length" "8")
2004 (set_attr "predicable" "yes")]
2007 (define_insn "*iordi_zesidi_di"
2008 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2009 (ior:DI (zero_extend:DI
2010 (match_operand:SI 2 "s_register_operand" "r,r"))
2011 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2014 orr%?\\t%Q0, %Q1, %2
2016 [(set_attr "length" "4,8")
2017 (set_attr "predicable" "yes")]
2020 (define_insn "*iordi_sesidi_di"
2021 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2022 (ior:DI (sign_extend:DI
2023 (match_operand:SI 2 "s_register_operand" "r,r"))
2024 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2027 [(set_attr "length" "8")
2028 (set_attr "predicable" "yes")]
2031 (define_expand "iorsi3"
2032 [(set (match_operand:SI 0 "s_register_operand" "")
2033 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2034 (match_operand:SI 2 "reg_or_int_operand" "")))]
2037 if (GET_CODE (operands[2]) == CONST_INT)
2041 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2044 ? 0 : preserve_subexpressions_p ()));
2047 else /* TARGET_THUMB */
2048 operands [2] = force_reg (SImode, operands [2]);
2053 (define_insn_and_split "*arm_iorsi3"
2054 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2055 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2056 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2062 && GET_CODE (operands[2]) == CONST_INT
2063 && !const_ok_for_arm (INTVAL (operands[2]))"
2064 [(clobber (const_int 0))]
2066 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2070 [(set_attr "length" "4,16")
2071 (set_attr "predicable" "yes")]
2074 (define_insn "*thumb_iorsi3"
2075 [(set (match_operand:SI 0 "register_operand" "=l")
2076 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2077 (match_operand:SI 2 "register_operand" "l")))]
2080 [(set_attr "length" "2")]
2084 [(match_scratch:SI 3 "r")
2085 (set (match_operand:SI 0 "s_register_operand" "")
2086 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2087 (match_operand:SI 2 "const_int_operand" "")))]
2089 && !const_ok_for_arm (INTVAL (operands[2]))
2090 && const_ok_for_arm (~INTVAL (operands[2]))"
2091 [(set (match_dup 3) (match_dup 2))
2092 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2096 (define_insn "*iorsi3_compare0"
2097 [(set (reg:CC_NOOV CC_REGNUM)
2098 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2099 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2101 (set (match_operand:SI 0 "s_register_operand" "=r")
2102 (ior:SI (match_dup 1) (match_dup 2)))]
2104 "orr%?s\\t%0, %1, %2"
2105 [(set_attr "conds" "set")]
2108 (define_insn "*iorsi3_compare0_scratch"
2109 [(set (reg:CC_NOOV CC_REGNUM)
2110 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2111 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2113 (clobber (match_scratch:SI 0 "=r"))]
2115 "orr%?s\\t%0, %1, %2"
2116 [(set_attr "conds" "set")]
2119 (define_insn "xordi3"
2120 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2121 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2122 (match_operand:DI 2 "s_register_operand" "r,r")))]
2123 "TARGET_ARM && !TARGET_IWMMXT"
2125 [(set_attr "length" "8")
2126 (set_attr "predicable" "yes")]
2129 (define_insn "*xordi_zesidi_di"
2130 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2131 (xor:DI (zero_extend:DI
2132 (match_operand:SI 2 "s_register_operand" "r,r"))
2133 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2136 eor%?\\t%Q0, %Q1, %2
2138 [(set_attr "length" "4,8")
2139 (set_attr "predicable" "yes")]
2142 (define_insn "*xordi_sesidi_di"
2143 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2144 (xor:DI (sign_extend:DI
2145 (match_operand:SI 2 "s_register_operand" "r,r"))
2146 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2149 [(set_attr "length" "8")
2150 (set_attr "predicable" "yes")]
2153 (define_expand "xorsi3"
2154 [(set (match_operand:SI 0 "s_register_operand" "")
2155 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2156 (match_operand:SI 2 "arm_rhs_operand" "")))]
2159 if (GET_CODE (operands[2]) == CONST_INT)
2160 operands[2] = force_reg (SImode, operands[2]);
2164 (define_insn "*arm_xorsi3"
2165 [(set (match_operand:SI 0 "s_register_operand" "=r")
2166 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2167 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2169 "eor%?\\t%0, %1, %2"
2170 [(set_attr "predicable" "yes")]
2173 (define_insn "*thumb_xorsi3"
2174 [(set (match_operand:SI 0 "register_operand" "=l")
2175 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2176 (match_operand:SI 2 "register_operand" "l")))]
2179 [(set_attr "length" "2")]
2182 (define_insn "*xorsi3_compare0"
2183 [(set (reg:CC_NOOV CC_REGNUM)
2184 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2185 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2187 (set (match_operand:SI 0 "s_register_operand" "=r")
2188 (xor:SI (match_dup 1) (match_dup 2)))]
2190 "eor%?s\\t%0, %1, %2"
2191 [(set_attr "conds" "set")]
2194 (define_insn "*xorsi3_compare0_scratch"
2195 [(set (reg:CC_NOOV CC_REGNUM)
2196 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2197 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2201 [(set_attr "conds" "set")]
2204 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2205 ; (NOT D) we can sometimes merge the final NOT into one of the following
2209 [(set (match_operand:SI 0 "s_register_operand" "")
2210 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2211 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2212 (match_operand:SI 3 "arm_rhs_operand" "")))
2213 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2215 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2216 (not:SI (match_dup 3))))
2217 (set (match_dup 0) (not:SI (match_dup 4)))]
2221 (define_insn "*andsi_iorsi3_notsi"
2222 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2223 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2224 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2225 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2227 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2228 [(set_attr "length" "8")
2229 (set_attr "predicable" "yes")]
2234 ;; Minimum and maximum insns
2236 (define_insn "smaxsi3"
2237 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2238 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2239 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2240 (clobber (reg:CC CC_REGNUM))]
2243 cmp\\t%1, %2\;movlt\\t%0, %2
2244 cmp\\t%1, %2\;movge\\t%0, %1
2245 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2246 [(set_attr "conds" "clob")
2247 (set_attr "length" "8,8,12")]
2250 (define_insn "sminsi3"
2251 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2252 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2253 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2254 (clobber (reg:CC CC_REGNUM))]
2257 cmp\\t%1, %2\;movge\\t%0, %2
2258 cmp\\t%1, %2\;movlt\\t%0, %1
2259 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2260 [(set_attr "conds" "clob")
2261 (set_attr "length" "8,8,12")]
2264 (define_insn "umaxsi3"
2265 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2266 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2267 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2268 (clobber (reg:CC CC_REGNUM))]
2271 cmp\\t%1, %2\;movcc\\t%0, %2
2272 cmp\\t%1, %2\;movcs\\t%0, %1
2273 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2274 [(set_attr "conds" "clob")
2275 (set_attr "length" "8,8,12")]
2278 (define_insn "uminsi3"
2279 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2280 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2281 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2282 (clobber (reg:CC CC_REGNUM))]
2285 cmp\\t%1, %2\;movcs\\t%0, %2
2286 cmp\\t%1, %2\;movcc\\t%0, %1
2287 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2288 [(set_attr "conds" "clob")
2289 (set_attr "length" "8,8,12")]
2292 (define_insn "*store_minmaxsi"
2293 [(set (match_operand:SI 0 "memory_operand" "=m")
2294 (match_operator:SI 3 "minmax_operator"
2295 [(match_operand:SI 1 "s_register_operand" "r")
2296 (match_operand:SI 2 "s_register_operand" "r")]))
2297 (clobber (reg:CC CC_REGNUM))]
2300 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2302 output_asm_insn (\"cmp\\t%1, %2\", operands);
2303 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2304 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2307 [(set_attr "conds" "clob")
2308 (set_attr "length" "12")
2309 (set_attr "type" "store1")]
2312 ; Reject the frame pointer in operand[1], since reloading this after
2313 ; it has been eliminated can cause carnage.
2314 (define_insn "*minmax_arithsi"
2315 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2316 (match_operator:SI 4 "shiftable_operator"
2317 [(match_operator:SI 5 "minmax_operator"
2318 [(match_operand:SI 2 "s_register_operand" "r,r")
2319 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2320 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2321 (clobber (reg:CC CC_REGNUM))]
2323 && (GET_CODE (operands[1]) != REG
2324 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2325 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2328 enum rtx_code code = GET_CODE (operands[4]);
2330 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2332 output_asm_insn (\"cmp\\t%2, %3\", operands);
2333 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2334 if (which_alternative != 0 || operands[3] != const0_rtx
2335 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2336 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2339 [(set_attr "conds" "clob")
2340 (set_attr "length" "12")]
2344 ;; Shift and rotation insns
2346 (define_expand "ashlsi3"
2347 [(set (match_operand:SI 0 "s_register_operand" "")
2348 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2349 (match_operand:SI 2 "arm_rhs_operand" "")))]
2352 if (GET_CODE (operands[2]) == CONST_INT
2353 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2355 emit_insn (gen_movsi (operands[0], const0_rtx));
2361 (define_insn "*thumb_ashlsi3"
2362 [(set (match_operand:SI 0 "register_operand" "=l,l")
2363 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2364 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2367 [(set_attr "length" "2")]
2370 (define_expand "ashrsi3"
2371 [(set (match_operand:SI 0 "s_register_operand" "")
2372 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2373 (match_operand:SI 2 "arm_rhs_operand" "")))]
2376 if (GET_CODE (operands[2]) == CONST_INT
2377 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2378 operands[2] = GEN_INT (31);
2382 (define_insn "*thumb_ashrsi3"
2383 [(set (match_operand:SI 0 "register_operand" "=l,l")
2384 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2385 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2388 [(set_attr "length" "2")]
2391 (define_expand "lshrsi3"
2392 [(set (match_operand:SI 0 "s_register_operand" "")
2393 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2394 (match_operand:SI 2 "arm_rhs_operand" "")))]
2397 if (GET_CODE (operands[2]) == CONST_INT
2398 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2400 emit_insn (gen_movsi (operands[0], const0_rtx));
2406 (define_insn "*thumb_lshrsi3"
2407 [(set (match_operand:SI 0 "register_operand" "=l,l")
2408 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2409 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2412 [(set_attr "length" "2")]
2415 (define_expand "rotlsi3"
2416 [(set (match_operand:SI 0 "s_register_operand" "")
2417 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2418 (match_operand:SI 2 "reg_or_int_operand" "")))]
2421 if (GET_CODE (operands[2]) == CONST_INT)
2422 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2425 rtx reg = gen_reg_rtx (SImode);
2426 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2432 (define_expand "rotrsi3"
2433 [(set (match_operand:SI 0 "s_register_operand" "")
2434 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2435 (match_operand:SI 2 "arm_rhs_operand" "")))]
2440 if (GET_CODE (operands[2]) == CONST_INT
2441 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2442 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2444 else /* TARGET_THUMB */
2446 if (GET_CODE (operands [2]) == CONST_INT)
2447 operands [2] = force_reg (SImode, operands[2]);
2452 (define_insn "*thumb_rotrsi3"
2453 [(set (match_operand:SI 0 "register_operand" "=l")
2454 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2455 (match_operand:SI 2 "register_operand" "l")))]
2458 [(set_attr "length" "2")]
2461 (define_expand "ashldi3"
2462 [(set (match_operand:DI 0 "s_register_operand" "")
2463 (ashift:DI (match_operand:DI 1 "general_operand" "")
2464 (match_operand:SI 2 "general_operand" "")))]
2465 "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)"
2467 if (! s_register_operand (operands[1], DImode))
2468 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2469 if (! s_register_operand (operands[2], SImode))
2470 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2474 (define_insn "*arm_shiftsi3"
2475 [(set (match_operand:SI 0 "s_register_operand" "=r")
2476 (match_operator:SI 3 "shift_operator"
2477 [(match_operand:SI 1 "s_register_operand" "r")
2478 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2481 [(set_attr "predicable" "yes")
2482 (set_attr "shift" "1")
2486 (define_insn "*shiftsi3_compare0"
2487 [(set (reg:CC_NOOV CC_REGNUM)
2488 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2489 [(match_operand:SI 1 "s_register_operand" "r")
2490 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2492 (set (match_operand:SI 0 "s_register_operand" "=r")
2493 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2495 "mov%?s\\t%0, %1%S3"
2496 [(set_attr "conds" "set")
2497 (set_attr "shift" "1")
2501 (define_insn "*shiftsi3_compare0_scratch"
2502 [(set (reg:CC_NOOV CC_REGNUM)
2503 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2504 [(match_operand:SI 1 "s_register_operand" "r")
2505 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2507 (clobber (match_scratch:SI 0 "=r"))]
2509 "mov%?s\\t%0, %1%S3"
2510 [(set_attr "conds" "set")
2511 (set_attr "shift" "1")
2515 (define_insn "*notsi_shiftsi"
2516 [(set (match_operand:SI 0 "s_register_operand" "=r")
2517 (not:SI (match_operator:SI 3 "shift_operator"
2518 [(match_operand:SI 1 "s_register_operand" "r")
2519 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2522 [(set_attr "predicable" "yes")
2523 (set_attr "shift" "1")
2527 (define_insn "*notsi_shiftsi_compare0"
2528 [(set (reg:CC_NOOV CC_REGNUM)
2529 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2530 [(match_operand:SI 1 "s_register_operand" "r")
2531 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2533 (set (match_operand:SI 0 "s_register_operand" "=r")
2534 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2536 "mvn%?s\\t%0, %1%S3"
2537 [(set_attr "conds" "set")
2538 (set_attr "shift" "1")
2542 (define_insn "*not_shiftsi_compare0_scratch"
2543 [(set (reg:CC_NOOV CC_REGNUM)
2544 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2545 [(match_operand:SI 1 "s_register_operand" "r")
2546 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2548 (clobber (match_scratch:SI 0 "=r"))]
2550 "mvn%?s\\t%0, %1%S3"
2551 [(set_attr "conds" "set")
2552 (set_attr "shift" "1")
2556 ;; We don't really have extzv, but defining this using shifts helps
2557 ;; to reduce register pressure later on.
2559 (define_expand "extzv"
2561 (ashift:SI (match_operand:SI 1 "register_operand" "")
2562 (match_operand:SI 2 "const_int_operand" "")))
2563 (set (match_operand:SI 0 "register_operand" "")
2564 (lshiftrt:SI (match_dup 4)
2565 (match_operand:SI 3 "const_int_operand" "")))]
2569 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2570 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2572 operands[3] = GEN_INT (rshift);
2576 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2580 operands[2] = GEN_INT (lshift);
2581 operands[4] = gen_reg_rtx (SImode);
2586 ;; Unary arithmetic insns
2588 (define_expand "negdi2"
2590 [(set (match_operand:DI 0 "s_register_operand" "")
2591 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2592 (clobber (reg:CC CC_REGNUM))])]
2597 if (GET_CODE (operands[1]) != REG)
2598 operands[1] = force_reg (SImode, operands[1]);
2603 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2604 ;; The second alternative is to allow the common case of a *full* overlap.
2605 (define_insn "*arm_negdi2"
2606 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2607 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2608 (clobber (reg:CC CC_REGNUM))]
2610 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2611 [(set_attr "conds" "clob")
2612 (set_attr "length" "8")]
2615 (define_insn "*thumb_negdi2"
2616 [(set (match_operand:DI 0 "register_operand" "=&l")
2617 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2618 (clobber (reg:CC CC_REGNUM))]
2620 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2621 [(set_attr "length" "6")]
2624 (define_expand "negsi2"
2625 [(set (match_operand:SI 0 "s_register_operand" "")
2626 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2631 (define_insn "*arm_negsi2"
2632 [(set (match_operand:SI 0 "s_register_operand" "=r")
2633 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2635 "rsb%?\\t%0, %1, #0"
2636 [(set_attr "predicable" "yes")]
2639 (define_insn "*thumb_negsi2"
2640 [(set (match_operand:SI 0 "register_operand" "=l")
2641 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2644 [(set_attr "length" "2")]
2647 (define_expand "negsf2"
2648 [(set (match_operand:SF 0 "s_register_operand" "")
2649 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2650 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2654 (define_expand "negdf2"
2655 [(set (match_operand:DF 0 "s_register_operand" "")
2656 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2657 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2660 ;; abssi2 doesn't really clobber the condition codes if a different register
2661 ;; is being set. To keep things simple, assume during rtl manipulations that
2662 ;; it does, but tell the final scan operator the truth. Similarly for
2665 (define_expand "abssi2"
2667 [(set (match_operand:SI 0 "s_register_operand" "")
2668 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2669 (clobber (reg:CC CC_REGNUM))])]
2673 (define_insn "*arm_abssi2"
2674 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2675 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2676 (clobber (reg:CC CC_REGNUM))]
2679 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2680 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2681 [(set_attr "conds" "clob,*")
2682 (set_attr "shift" "1")
2683 ;; predicable can't be set based on the variant, so left as no
2684 (set_attr "length" "8")]
2687 (define_insn "*neg_abssi2"
2688 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2689 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2690 (clobber (reg:CC CC_REGNUM))]
2693 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2694 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2695 [(set_attr "conds" "clob,*")
2696 (set_attr "shift" "1")
2697 ;; predicable can't be set based on the variant, so left as no
2698 (set_attr "length" "8")]
2701 (define_expand "abssf2"
2702 [(set (match_operand:SF 0 "s_register_operand" "")
2703 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2704 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2707 (define_expand "absdf2"
2708 [(set (match_operand:DF 0 "s_register_operand" "")
2709 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2710 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2713 (define_expand "sqrtsf2"
2714 [(set (match_operand:SF 0 "s_register_operand" "")
2715 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2716 "TARGET_ARM && TARGET_HARD_FLOAT"
2719 (define_expand "sqrtdf2"
2720 [(set (match_operand:DF 0 "s_register_operand" "")
2721 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2722 "TARGET_ARM && TARGET_HARD_FLOAT"
2725 (define_insn_and_split "one_cmpldi2"
2726 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2727 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2730 "TARGET_ARM && reload_completed"
2731 [(set (match_dup 0) (not:SI (match_dup 1)))
2732 (set (match_dup 2) (not:SI (match_dup 3)))]
2735 operands[2] = gen_highpart (SImode, operands[0]);
2736 operands[0] = gen_lowpart (SImode, operands[0]);
2737 operands[3] = gen_highpart (SImode, operands[1]);
2738 operands[1] = gen_lowpart (SImode, operands[1]);
2740 [(set_attr "length" "8")
2741 (set_attr "predicable" "yes")]
2744 (define_expand "one_cmplsi2"
2745 [(set (match_operand:SI 0 "s_register_operand" "")
2746 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2751 (define_insn "*arm_one_cmplsi2"
2752 [(set (match_operand:SI 0 "s_register_operand" "=r")
2753 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2756 [(set_attr "predicable" "yes")]
2759 (define_insn "*thumb_one_cmplsi2"
2760 [(set (match_operand:SI 0 "register_operand" "=l")
2761 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2764 [(set_attr "length" "2")]
2767 (define_insn "*notsi_compare0"
2768 [(set (reg:CC_NOOV CC_REGNUM)
2769 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2771 (set (match_operand:SI 0 "s_register_operand" "=r")
2772 (not:SI (match_dup 1)))]
2775 [(set_attr "conds" "set")]
2778 (define_insn "*notsi_compare0_scratch"
2779 [(set (reg:CC_NOOV CC_REGNUM)
2780 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2782 (clobber (match_scratch:SI 0 "=r"))]
2785 [(set_attr "conds" "set")]
2788 ;; Fixed <--> Floating conversion insns
2790 (define_expand "floatsisf2"
2791 [(set (match_operand:SF 0 "s_register_operand" "")
2792 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2793 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2797 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2802 (define_expand "floatsidf2"
2803 [(set (match_operand:DF 0 "s_register_operand" "")
2804 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2805 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2809 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
2814 (define_expand "fix_truncsfsi2"
2815 [(set (match_operand:SI 0 "s_register_operand" "")
2816 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
2817 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2821 if (!cirrus_fp_register (operands[0], SImode))
2822 operands[0] = force_reg (SImode, operands[0]);
2823 if (!cirrus_fp_register (operands[1], SFmode))
2824 operands[1] = force_reg (SFmode, operands[0]);
2825 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
2830 (define_expand "fix_truncdfsi2"
2831 [(set (match_operand:SI 0 "s_register_operand" "")
2832 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
2833 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2837 if (!cirrus_fp_register (operands[1], DFmode))
2838 operands[1] = force_reg (DFmode, operands[0]);
2839 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
2846 (define_expand "truncdfsf2"
2847 [(set (match_operand:SF 0 "s_register_operand" "")
2849 (match_operand:DF 1 "s_register_operand" "")))]
2850 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2854 ;; Zero and sign extension instructions.
2856 (define_insn "zero_extendsidi2"
2857 [(set (match_operand:DI 0 "s_register_operand" "=r")
2858 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2861 if (REGNO (operands[1])
2862 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2863 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2864 return \"mov%?\\t%R0, #0\";
2866 [(set_attr "length" "8")
2867 (set_attr "predicable" "yes")]
2870 (define_insn "zero_extendqidi2"
2871 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2872 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2875 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2876 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2877 [(set_attr "length" "8")
2878 (set_attr "predicable" "yes")
2879 (set_attr "type" "*,load")
2880 (set_attr "pool_range" "*,4092")
2881 (set_attr "neg_pool_range" "*,4084")]
2884 (define_insn "extendsidi2"
2885 [(set (match_operand:DI 0 "s_register_operand" "=r")
2886 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2889 if (REGNO (operands[1])
2890 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2891 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2892 return \"mov%?\\t%R0, %Q0, asr #31\";
2894 [(set_attr "length" "8")
2895 (set_attr "shift" "1")
2896 (set_attr "predicable" "yes")]
2899 (define_expand "zero_extendhisi2"
2901 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2903 (set (match_operand:SI 0 "s_register_operand" "")
2904 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2910 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2912 /* Note: We do not have to worry about TARGET_MMU_TRAPS
2913 here because the insn below will generate an LDRH instruction
2914 rather than an LDR instruction, so we cannot get an unaligned
2916 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2917 gen_rtx_ZERO_EXTEND (SImode,
2921 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2923 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2926 if (!s_register_operand (operands[1], HImode))
2927 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2928 operands[1] = gen_lowpart (SImode, operands[1]);
2929 operands[2] = gen_reg_rtx (SImode);
2931 else /* TARGET_THUMB */
2933 if (GET_CODE (operands[1]) == MEM)
2937 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
2938 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
2945 if (!s_register_operand (operands[1], HImode))
2946 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2947 operands[1] = gen_lowpart (SImode, operands[1]);
2948 operands[2] = gen_reg_rtx (SImode);
2950 ops[0] = operands[2];
2951 ops[1] = operands[1];
2952 ops[2] = GEN_INT (16);
2954 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2955 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
2957 ops[0] = operands[0];
2958 ops[1] = operands[2];
2959 ops[2] = GEN_INT (16);
2961 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2962 gen_rtx_LSHIFTRT (SImode, ops[1],
2970 (define_insn "*thumb_zero_extendhisi2"
2971 [(set (match_operand:SI 0 "register_operand" "=l")
2972 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2975 rtx mem = XEXP (operands[1], 0);
2977 if (GET_CODE (mem) == CONST)
2978 mem = XEXP (mem, 0);
2980 if (GET_CODE (mem) == LABEL_REF)
2981 return \"ldr\\t%0, %1\";
2983 if (GET_CODE (mem) == PLUS)
2985 rtx a = XEXP (mem, 0);
2986 rtx b = XEXP (mem, 1);
2988 /* This can happen due to bugs in reload. */
2989 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
2992 ops[0] = operands[0];
2995 output_asm_insn (\"mov %0, %1\", ops);
2997 XEXP (mem, 0) = operands[0];
3000 else if ( GET_CODE (a) == LABEL_REF
3001 && GET_CODE (b) == CONST_INT)
3002 return \"ldr\\t%0, %1\";
3005 return \"ldrh\\t%0, %1\";
3007 [(set_attr "length" "4")
3008 (set_attr "type" "load")
3009 (set_attr "pool_range" "60")]
3012 (define_insn "*arm_zero_extendhisi2"
3013 [(set (match_operand:SI 0 "s_register_operand" "=r")
3014 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3015 "TARGET_ARM && arm_arch4"
3017 [(set_attr "type" "load")
3018 (set_attr "predicable" "yes")
3019 (set_attr "pool_range" "256")
3020 (set_attr "neg_pool_range" "244")]
3024 [(set (match_operand:SI 0 "s_register_operand" "")
3025 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3026 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3027 "TARGET_ARM && (!arm_arch4)"
3028 [(set (match_dup 2) (match_dup 1))
3029 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3031 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3037 [(set (match_operand:SI 0 "s_register_operand" "")
3038 (match_operator:SI 3 "shiftable_operator"
3039 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3040 (match_operand:SI 4 "s_register_operand" "")]))
3041 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3042 "TARGET_ARM && (!arm_arch4)"
3043 [(set (match_dup 2) (match_dup 1))
3046 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3048 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3053 (define_expand "zero_extendqisi2"
3054 [(set (match_operand:SI 0 "s_register_operand" "")
3055 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3058 if (GET_CODE (operands[1]) != MEM)
3062 emit_insn (gen_andsi3 (operands[0],
3063 gen_lowpart (SImode, operands[1]),
3066 else /* TARGET_THUMB */
3068 rtx temp = gen_reg_rtx (SImode);
3071 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3072 operands[1] = gen_lowpart (SImode, operands[1]);
3075 ops[1] = operands[1];
3076 ops[2] = GEN_INT (24);
3078 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3079 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3081 ops[0] = operands[0];
3083 ops[2] = GEN_INT (24);
3085 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3086 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3093 (define_insn "*thumb_zero_extendqisi2"
3094 [(set (match_operand:SI 0 "register_operand" "=l")
3095 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3098 [(set_attr "length" "2")
3099 (set_attr "type" "load")
3100 (set_attr "pool_range" "32")]
3103 (define_insn "*arm_zero_extendqisi2"
3104 [(set (match_operand:SI 0 "s_register_operand" "=r")
3105 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3107 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3108 [(set_attr "type" "load")
3109 (set_attr "predicable" "yes")
3110 (set_attr "pool_range" "4096")
3111 (set_attr "neg_pool_range" "4084")]
3115 [(set (match_operand:SI 0 "s_register_operand" "")
3116 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3117 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3118 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3119 [(set (match_dup 2) (match_dup 1))
3120 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3124 (define_insn "*compareqi_eq0"
3125 [(set (reg:CC_Z CC_REGNUM)
3126 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3130 [(set_attr "conds" "set")]
3133 (define_expand "extendhisi2"
3135 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3137 (set (match_operand:SI 0 "s_register_operand" "")
3138 (ashiftrt:SI (match_dup 2)
3143 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3145 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3146 here because the insn below will generate an LDRH instruction
3147 rather than an LDR instruction, so we cannot get an unaligned
3149 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3150 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3154 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3156 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3159 if (!s_register_operand (operands[1], HImode))
3160 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3161 operands[1] = gen_lowpart (SImode, operands[1]);
3162 operands[2] = gen_reg_rtx (SImode);
3168 ops[0] = operands[2];
3169 ops[1] = operands[1];
3170 ops[2] = GEN_INT (16);
3172 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3173 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3175 ops[0] = operands[0];
3176 ops[1] = operands[2];
3177 ops[2] = GEN_INT (16);
3179 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3180 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3187 (define_insn "*thumb_extendhisi2_insn"
3188 [(set (match_operand:SI 0 "register_operand" "=l")
3189 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3190 (clobber (match_scratch:SI 2 "=&l"))]
3195 rtx mem = XEXP (operands[1], 0);
3197 /* This code used to try to use 'V', and fix the address only if it was
3198 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3199 range of QImode offsets, and offsettable_address_p does a QImode
3202 if (GET_CODE (mem) == CONST)
3203 mem = XEXP (mem, 0);
3205 if (GET_CODE (mem) == LABEL_REF)
3206 return \"ldr\\t%0, %1\";
3208 if (GET_CODE (mem) == PLUS)
3210 rtx a = XEXP (mem, 0);
3211 rtx b = XEXP (mem, 1);
3213 if (GET_CODE (a) == LABEL_REF
3214 && GET_CODE (b) == CONST_INT)
3215 return \"ldr\\t%0, %1\";
3217 if (GET_CODE (b) == REG)
3218 return \"ldrsh\\t%0, %1\";
3226 ops[2] = const0_rtx;
3229 if (GET_CODE (ops[1]) != REG)
3235 ops[0] = operands[0];
3236 ops[3] = operands[2];
3237 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3240 [(set_attr "length" "4")
3241 (set_attr "type" "load")
3242 (set_attr "pool_range" "1020")]
3245 (define_expand "extendhisi2_mem"
3246 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3248 (zero_extend:SI (match_dup 7)))
3249 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3250 (set (match_operand:SI 0 "" "")
3251 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3256 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3258 mem1 = gen_rtx_MEM (QImode, addr);
3259 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3260 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3261 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3262 operands[0] = gen_lowpart (SImode, operands[0]);
3264 operands[2] = gen_reg_rtx (SImode);
3265 operands[3] = gen_reg_rtx (SImode);
3266 operands[6] = gen_reg_rtx (SImode);
3269 if (BYTES_BIG_ENDIAN)
3271 operands[4] = operands[2];
3272 operands[5] = operands[3];
3276 operands[4] = operands[3];
3277 operands[5] = operands[2];
3282 (define_insn "*arm_extendhisi_insn"
3283 [(set (match_operand:SI 0 "s_register_operand" "=r")
3284 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3285 "TARGET_ARM && arm_arch4"
3287 [(set_attr "type" "load")
3288 (set_attr "predicable" "yes")
3289 (set_attr "pool_range" "256")
3290 (set_attr "neg_pool_range" "244")]
3294 [(set (match_operand:SI 0 "s_register_operand" "")
3295 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3296 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3297 "TARGET_ARM && (!arm_arch4)"
3298 [(set (match_dup 2) (match_dup 1))
3299 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3301 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3307 [(set (match_operand:SI 0 "s_register_operand" "")
3308 (match_operator:SI 3 "shiftable_operator"
3309 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3310 (match_operand:SI 4 "s_register_operand" "")]))
3311 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3312 "TARGET_ARM && (!arm_arch4)"
3313 [(set (match_dup 2) (match_dup 1))
3316 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3317 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3322 (define_expand "extendqihi2"
3324 (ashift:SI (match_operand:QI 1 "general_operand" "")
3326 (set (match_operand:HI 0 "s_register_operand" "")
3327 (ashiftrt:SI (match_dup 2)
3332 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3334 emit_insn (gen_rtx_SET (VOIDmode,
3336 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3339 if (!s_register_operand (operands[1], QImode))
3340 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3341 operands[0] = gen_lowpart (SImode, operands[0]);
3342 operands[1] = gen_lowpart (SImode, operands[1]);
3343 operands[2] = gen_reg_rtx (SImode);
3347 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3348 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3349 (define_insn "*extendqihi_insn"
3350 [(set (match_operand:HI 0 "s_register_operand" "=r")
3351 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3352 "TARGET_ARM && arm_arch4"
3354 /* If the address is invalid, this will split the instruction into two. */
3355 if (bad_signed_byte_operand (operands[1], VOIDmode))
3357 return \"ldr%?sb\\t%0, %1\";
3359 [(set_attr "type" "load")
3360 (set_attr "predicable" "yes")
3361 (set_attr "length" "8")
3362 (set_attr "pool_range" "256")
3363 (set_attr "neg_pool_range" "244")]
3367 [(set (match_operand:HI 0 "s_register_operand" "")
3368 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3369 "TARGET_ARM && arm_arch4 && reload_completed"
3370 [(set (match_dup 3) (match_dup 1))
3371 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3374 HOST_WIDE_INT offset;
3376 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3377 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3378 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3379 operands[1] = XEXP (operands[1], 0);
3380 if (GET_CODE (operands[1]) == PLUS
3381 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3382 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3383 || const_ok_for_arm (-offset)))
3385 HOST_WIDE_INT low = (offset > 0
3386 ? (offset & 0xff) : -((-offset) & 0xff));
3387 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3388 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3390 /* Ensure the sum is in correct canonical form */
3391 else if (GET_CODE (operands[1]) == PLUS
3392 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3393 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3394 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3395 XEXP (operands[1], 1),
3396 XEXP (operands[1], 0));
3400 (define_expand "extendqisi2"
3402 (ashift:SI (match_operand:QI 1 "general_operand" "")
3404 (set (match_operand:SI 0 "s_register_operand" "")
3405 (ashiftrt:SI (match_dup 2)
3410 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3412 emit_insn (gen_rtx_SET (VOIDmode,
3414 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3417 if (!s_register_operand (operands[1], QImode))
3418 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3419 operands[1] = gen_lowpart (SImode, operands[1]);
3420 operands[2] = gen_reg_rtx (SImode);
3426 ops[0] = operands[2];
3427 ops[1] = operands[1];
3428 ops[2] = GEN_INT (24);
3430 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3431 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3433 ops[0] = operands[0];
3434 ops[1] = operands[2];
3435 ops[2] = GEN_INT (24);
3437 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3438 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3445 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3446 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3447 (define_insn "*arm_extendqisi_insn"
3448 [(set (match_operand:SI 0 "s_register_operand" "=r")
3449 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3450 "TARGET_ARM && arm_arch4"
3452 /* If the address is invalid, this will split the instruction into two. */
3453 if (bad_signed_byte_operand (operands[1], VOIDmode))
3455 return \"ldr%?sb\\t%0, %1\";
3457 [(set_attr "type" "load")
3458 (set_attr "predicable" "yes")
3459 (set_attr "length" "8")
3460 (set_attr "pool_range" "256")
3461 (set_attr "neg_pool_range" "244")]
3465 [(set (match_operand:SI 0 "s_register_operand" "")
3466 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3467 "TARGET_ARM && arm_arch4 && reload_completed"
3468 [(set (match_dup 0) (match_dup 1))
3469 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3472 HOST_WIDE_INT offset;
3474 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3475 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3476 operands[1] = XEXP (operands[1], 0);
3477 if (GET_CODE (operands[1]) == PLUS
3478 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3479 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3480 || const_ok_for_arm (-offset)))
3482 HOST_WIDE_INT low = (offset > 0
3483 ? (offset & 0xff) : -((-offset) & 0xff));
3484 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3485 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3487 /* Ensure the sum is in correct canonical form */
3488 else if (GET_CODE (operands[1]) == PLUS
3489 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3490 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3491 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3492 XEXP (operands[1], 1),
3493 XEXP (operands[1], 0));
3497 (define_insn "*thumb_extendqisi2_insn"
3498 [(set (match_operand:SI 0 "register_operand" "=l,l")
3499 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3504 rtx mem = XEXP (operands[1], 0);
3506 if (GET_CODE (mem) == CONST)
3507 mem = XEXP (mem, 0);
3509 if (GET_CODE (mem) == LABEL_REF)
3510 return \"ldr\\t%0, %1\";
3512 if (GET_CODE (mem) == PLUS
3513 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3514 return \"ldr\\t%0, %1\";
3516 if (which_alternative == 0)
3517 return \"ldrsb\\t%0, %1\";
3519 ops[0] = operands[0];
3521 if (GET_CODE (mem) == PLUS)
3523 rtx a = XEXP (mem, 0);
3524 rtx b = XEXP (mem, 1);
3529 if (GET_CODE (a) == REG)
3531 if (GET_CODE (b) == REG)
3532 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3533 else if (REGNO (a) == REGNO (ops[0]))
3535 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3536 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3537 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3540 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3542 else if (GET_CODE (b) != REG)
3546 if (REGNO (b) == REGNO (ops[0]))
3548 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3549 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3550 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3553 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3556 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3558 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3559 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3560 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3565 ops[2] = const0_rtx;
3567 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3571 [(set_attr "length" "2,6")
3572 (set_attr "type" "load,load")
3573 (set_attr "pool_range" "32,32")]
3576 (define_expand "extendsfdf2"
3577 [(set (match_operand:DF 0 "s_register_operand" "")
3578 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3579 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3583 ;; Move insns (including loads and stores)
3585 ;; XXX Just some ideas about movti.
3586 ;; I don't think these are a good idea on the arm, there just aren't enough
3588 ;;(define_expand "loadti"
3589 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3590 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3593 ;;(define_expand "storeti"
3594 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3595 ;; (match_operand:TI 1 "s_register_operand" ""))]
3598 ;;(define_expand "movti"
3599 ;; [(set (match_operand:TI 0 "general_operand" "")
3600 ;; (match_operand:TI 1 "general_operand" ""))]
3606 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3607 ;; operands[1] = copy_to_reg (operands[1]);
3608 ;; if (GET_CODE (operands[0]) == MEM)
3609 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3610 ;; else if (GET_CODE (operands[1]) == MEM)
3611 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3615 ;; emit_insn (insn);
3619 ;; Recognize garbage generated above.
3622 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3623 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3627 ;; register mem = (which_alternative < 3);
3628 ;; register const char *template;
3630 ;; operands[mem] = XEXP (operands[mem], 0);
3631 ;; switch (which_alternative)
3633 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3634 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3635 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3636 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3637 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3638 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3640 ;; output_asm_insn (template, operands);
3644 (define_expand "movdi"
3645 [(set (match_operand:DI 0 "general_operand" "")
3646 (match_operand:DI 1 "general_operand" ""))]
3651 if (!no_new_pseudos)
3653 if (GET_CODE (operands[0]) != REG)
3654 operands[1] = force_reg (DImode, operands[1]);
3660 (define_insn "*arm_movdi"
3661 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3662 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3663 "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT"
3665 return (output_move_double (operands));
3667 [(set_attr "length" "8")
3668 (set_attr "type" "*,load,store2")
3669 (set_attr "pool_range" "*,1020,*")
3670 (set_attr "neg_pool_range" "*,1008,*")]
3673 ;;; ??? This should have alternatives for constants.
3674 ;;; ??? This was originally identical to the movdf_insn pattern.
3675 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3676 ;;; thumb_reorg with a memory reference.
3677 (define_insn "*thumb_movdi_insn"
3678 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3679 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3682 && ( register_operand (operands[0], DImode)
3683 || register_operand (operands[1], DImode))"
3686 switch (which_alternative)
3690 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3691 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3692 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3694 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3696 operands[1] = GEN_INT (- INTVAL (operands[1]));
3697 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3699 return \"ldmia\\t%1, {%0, %H0}\";
3701 return \"stmia\\t%0, {%1, %H1}\";
3703 return thumb_load_double_from_address (operands);
3705 operands[2] = gen_rtx (MEM, SImode,
3706 plus_constant (XEXP (operands[0], 0), 4));
3707 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3710 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3711 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3712 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3715 [(set_attr "length" "4,4,6,2,2,6,4,4")
3716 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3717 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3720 (define_expand "movsi"
3721 [(set (match_operand:SI 0 "general_operand" "")
3722 (match_operand:SI 1 "general_operand" ""))]
3727 /* Everything except mem = const or mem = mem can be done easily */
3728 if (GET_CODE (operands[0]) == MEM)
3729 operands[1] = force_reg (SImode, operands[1]);
3730 if (GET_CODE (operands[1]) == CONST_INT
3731 && !(const_ok_for_arm (INTVAL (operands[1]))
3732 || const_ok_for_arm (~INTVAL (operands[1]))))
3734 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3737 : preserve_subexpressions_p ()));
3741 else /* TARGET_THUMB.... */
3743 if (!no_new_pseudos)
3745 if (GET_CODE (operands[0]) != REG)
3746 operands[1] = force_reg (SImode, operands[1]);
3751 && (CONSTANT_P (operands[1])
3752 || symbol_mentioned_p (operands[1])
3753 || label_mentioned_p (operands[1])))
3754 operands[1] = legitimize_pic_address (operands[1], SImode,
3755 (no_new_pseudos ? operands[0] : 0));
3759 (define_insn "*arm_movsi_insn"
3760 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3761 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
3762 "TARGET_ARM && ! TARGET_IWMMXT
3763 && ( register_operand (operands[0], SImode)
3764 || register_operand (operands[1], SImode))"
3770 [(set_attr "type" "*,*,load,store1")
3771 (set_attr "predicable" "yes")
3772 (set_attr "pool_range" "*,*,4096,*")
3773 (set_attr "neg_pool_range" "*,*,4084,*")]
3777 [(set (match_operand:SI 0 "s_register_operand" "")
3778 (match_operand:SI 1 "const_int_operand" ""))]
3780 && (!(const_ok_for_arm (INTVAL (operands[1]))
3781 || const_ok_for_arm (~INTVAL (operands[1]))))"
3782 [(clobber (const_int 0))]
3784 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3790 (define_insn "*thumb_movsi_insn"
3791 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3792 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
3794 && ( register_operand (operands[0], SImode)
3795 || register_operand (operands[1], SImode))"
3806 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3807 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3808 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3812 [(set (match_operand:SI 0 "register_operand" "")
3813 (match_operand:SI 1 "const_int_operand" ""))]
3814 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3815 [(set (match_dup 0) (match_dup 1))
3816 (set (match_dup 0) (neg:SI (match_dup 0)))]
3817 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3821 [(set (match_operand:SI 0 "register_operand" "")
3822 (match_operand:SI 1 "const_int_operand" ""))]
3823 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3824 [(set (match_dup 0) (match_dup 1))
3825 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3828 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3829 unsigned HOST_WIDE_INT mask = 0xff;
3832 for (i = 0; i < 25; i++)
3833 if ((val & (mask << i)) == val)
3836 /* Shouldn't happen, but we don't want to split if the shift is zero. */
3840 operands[1] = GEN_INT (val >> i);
3841 operands[2] = GEN_INT (i);
3845 ;; When generating pic, we need to load the symbol offset into a register.
3846 ;; So that the optimizer does not confuse this with a normal symbol load
3847 ;; we use an unspec. The offset will be loaded from a constant pool entry,
3848 ;; since that is the only type of relocation we can use.
3850 ;; The rather odd constraints on the following are to force reload to leave
3851 ;; the insn alone, and to force the minipool generation pass to then move
3852 ;; the GOT symbol to memory.
3854 (define_insn "pic_load_addr_arm"
3855 [(set (match_operand:SI 0 "s_register_operand" "=r")
3856 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3857 "TARGET_ARM && flag_pic"
3859 [(set_attr "type" "load")
3860 (set (attr "pool_range") (const_int 4096))
3861 (set (attr "neg_pool_range") (const_int 4084))]
3864 (define_insn "pic_load_addr_thumb"
3865 [(set (match_operand:SI 0 "s_register_operand" "=l")
3866 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3867 "TARGET_THUMB && flag_pic"
3869 [(set_attr "type" "load")
3870 (set (attr "pool_range") (const_int 1024))]
3873 ;; This variant is used for AOF assembly, since it needs to mention the
3874 ;; pic register in the rtl.
3875 (define_expand "pic_load_addr_based"
3876 [(set (match_operand:SI 0 "s_register_operand" "")
3877 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
3878 "TARGET_ARM && flag_pic"
3879 "operands[2] = pic_offset_table_rtx;"
3882 (define_insn "*pic_load_addr_based_insn"
3883 [(set (match_operand:SI 0 "s_register_operand" "=r")
3884 (unspec:SI [(match_operand 1 "" "")
3885 (match_operand 2 "s_register_operand" "r")]
3887 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
3889 #ifdef AOF_ASSEMBLER
3890 operands[1] = aof_pic_entry (operands[1]);
3892 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3895 [(set_attr "type" "load")
3896 (set (attr "pool_range")
3897 (if_then_else (eq_attr "is_thumb" "yes")
3900 (set (attr "neg_pool_range")
3901 (if_then_else (eq_attr "is_thumb" "yes")
3906 (define_insn "pic_add_dot_plus_four"
3907 [(set (match_operand:SI 0 "register_operand" "+r")
3908 (unspec:SI [(plus:SI (match_dup 0)
3909 (const (plus:SI (pc) (const_int 4))))]
3911 (use (label_ref (match_operand 1 "" "")))]
3912 "TARGET_THUMB && flag_pic"
3914 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3915 CODE_LABEL_NUMBER (operands[1]));
3916 return \"add\\t%0, %|pc\";
3918 [(set_attr "length" "2")]
3921 (define_insn "pic_add_dot_plus_eight"
3922 [(set (match_operand:SI 0 "register_operand" "+r")
3923 (unspec:SI [(plus:SI (match_dup 0)
3924 (const (plus:SI (pc) (const_int 8))))]
3926 (use (label_ref (match_operand 1 "" "")))]
3927 "TARGET_ARM && flag_pic"
3929 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3930 CODE_LABEL_NUMBER (operands[1]));
3931 return \"add%?\\t%0, %|pc, %0\";
3933 [(set_attr "predicable" "yes")]
3936 (define_expand "builtin_setjmp_receiver"
3937 [(label_ref (match_operand 0 "" ""))]
3941 arm_finalize_pic (0);
3945 ;; If copying one reg to another we can set the condition codes according to
3946 ;; its value. Such a move is common after a return from subroutine and the
3947 ;; result is being tested against zero.
3949 (define_insn "*movsi_compare0"
3950 [(set (reg:CC CC_REGNUM)
3951 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
3953 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3958 sub%?s\\t%0, %1, #0"
3959 [(set_attr "conds" "set")]
3962 ;; Subroutine to store a half word from a register into memory.
3963 ;; Operand 0 is the source register (HImode)
3964 ;; Operand 1 is the destination address in a register (SImode)
3966 ;; In both this routine and the next, we must be careful not to spill
3967 ;; a memory address of reg+large_const into a separate PLUS insn, since this
3968 ;; can generate unrecognizable rtl.
3970 (define_expand "storehi"
3971 [;; store the low byte
3972 (set (match_operand 1 "" "") (match_dup 3))
3973 ;; extract the high byte
3975 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3976 ;; store the high byte
3977 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
3981 rtx op1 = operands[1];
3982 rtx addr = XEXP (op1, 0);
3983 enum rtx_code code = GET_CODE (addr);
3985 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3987 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
3989 operands[4] = adjust_address (op1, QImode, 1);
3990 operands[1] = adjust_address (operands[1], QImode, 0);
3991 operands[3] = gen_lowpart (QImode, operands[0]);
3992 operands[0] = gen_lowpart (SImode, operands[0]);
3993 operands[2] = gen_reg_rtx (SImode);
3997 (define_expand "storehi_bigend"
3998 [(set (match_dup 4) (match_dup 3))
4000 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4001 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
4005 rtx op1 = operands[1];
4006 rtx addr = XEXP (op1, 0);
4007 enum rtx_code code = GET_CODE (addr);
4009 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4011 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4013 operands[4] = adjust_address (op1, QImode, 1);
4014 operands[1] = adjust_address (operands[1], QImode, 0);
4015 operands[3] = gen_lowpart (QImode, operands[0]);
4016 operands[0] = gen_lowpart (SImode, operands[0]);
4017 operands[2] = gen_reg_rtx (SImode);
4021 ;; Subroutine to store a half word integer constant into memory.
4022 (define_expand "storeinthi"
4023 [(set (match_operand 0 "" "")
4024 (subreg:QI (match_operand 1 "" "") 0))
4025 (set (match_dup 3) (match_dup 2))]
4029 HOST_WIDE_INT value = INTVAL (operands[1]);
4030 rtx addr = XEXP (operands[0], 0);
4031 rtx op0 = operands[0];
4032 enum rtx_code code = GET_CODE (addr);
4034 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4036 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4038 operands[1] = gen_reg_rtx (SImode);
4039 if (BYTES_BIG_ENDIAN)
4041 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4042 if ((value & 255) == ((value >> 8) & 255))
4043 operands[2] = operands[1];
4046 operands[2] = gen_reg_rtx (SImode);
4047 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4052 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4053 if ((value & 255) == ((value >> 8) & 255))
4054 operands[2] = operands[1];
4057 operands[2] = gen_reg_rtx (SImode);
4058 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4062 operands[3] = adjust_address (op0, QImode, 1);
4063 operands[0] = adjust_address (operands[0], QImode, 0);
4064 operands[2] = gen_lowpart (QImode, operands[2]);
4068 (define_expand "storehi_single_op"
4069 [(set (match_operand:HI 0 "memory_operand" "")
4070 (match_operand:HI 1 "general_operand" ""))]
4071 "TARGET_ARM && arm_arch4"
4073 if (!s_register_operand (operands[1], HImode))
4074 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4078 (define_expand "movhi"
4079 [(set (match_operand:HI 0 "general_operand" "")
4080 (match_operand:HI 1 "general_operand" ""))]
4085 if (!no_new_pseudos)
4087 if (GET_CODE (operands[0]) == MEM)
4091 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4094 if (GET_CODE (operands[1]) == CONST_INT)
4095 emit_insn (gen_storeinthi (operands[0], operands[1]));
4098 if (GET_CODE (operands[1]) == MEM)
4099 operands[1] = force_reg (HImode, operands[1]);
4100 if (BYTES_BIG_ENDIAN)
4101 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4103 emit_insn (gen_storehi (operands[1], operands[0]));
4107 /* Sign extend a constant, and keep it in an SImode reg. */
4108 else if (GET_CODE (operands[1]) == CONST_INT)
4110 rtx reg = gen_reg_rtx (SImode);
4111 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4113 /* If the constant is already valid, leave it alone. */
4114 if (!const_ok_for_arm (val))
4116 /* If setting all the top bits will make the constant
4117 loadable in a single instruction, then set them.
4118 Otherwise, sign extend the number. */
4120 if (const_ok_for_arm (~(val | ~0xffff)))
4122 else if (val & 0x8000)
4126 emit_insn (gen_movsi (reg, GEN_INT (val)));
4127 operands[1] = gen_lowpart (HImode, reg);
4129 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4130 && GET_CODE (operands[1]) == MEM)
4132 rtx reg = gen_reg_rtx (SImode);
4134 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4135 operands[1] = gen_lowpart (HImode, reg);
4137 else if (!arm_arch4)
4139 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4140 for v4 and up architectures because LDRH instructions will
4141 be used to access the HI values, and these cannot generate
4142 unaligned word access faults in the MMU. */
4143 if (GET_CODE (operands[1]) == MEM)
4145 if (TARGET_MMU_TRAPS)
4148 rtx offset = const0_rtx;
4149 rtx reg = gen_reg_rtx (SImode);
4151 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4152 || (GET_CODE (base) == PLUS
4153 && (GET_CODE (offset = XEXP (base, 1))
4155 && ((INTVAL(offset) & 1) != 1)
4156 && GET_CODE (base = XEXP (base, 0)) == REG))
4157 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4159 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4162 new = gen_rtx_MEM (SImode,
4163 plus_constant (base, new_offset));
4164 MEM_COPY_ATTRIBUTES (new, operands[1]);
4165 emit_insn (gen_movsi (reg, new));
4166 if (((INTVAL (offset) & 2) != 0)
4167 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4169 rtx reg2 = gen_reg_rtx (SImode);
4171 emit_insn (gen_lshrsi3 (reg2, reg,
4177 emit_insn (gen_movhi_bytes (reg, operands[1]));
4179 operands[1] = gen_lowpart (HImode, reg);
4181 else if (BYTES_BIG_ENDIAN)
4184 rtx offset = const0_rtx;
4186 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4187 || (GET_CODE (base) == PLUS
4188 && (GET_CODE (offset = XEXP (base, 1))
4190 && GET_CODE (base = XEXP (base, 0)) == REG))
4191 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4193 rtx reg = gen_reg_rtx (SImode);
4196 if ((INTVAL (offset) & 2) == 2)
4198 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4199 new = gen_rtx_MEM (SImode,
4200 plus_constant (base,
4202 MEM_COPY_ATTRIBUTES (new, operands[1]);
4203 emit_insn (gen_movsi (reg, new));
4207 new = gen_rtx_MEM (SImode,
4208 XEXP (operands[1], 0));
4209 MEM_COPY_ATTRIBUTES (new, operands[1]);
4210 emit_insn (gen_rotated_loadsi (reg, new));
4213 operands[1] = gen_lowpart (HImode, reg);
4217 emit_insn (gen_movhi_bigend (operands[0],
4225 /* Handle loading a large integer during reload */
4226 else if (GET_CODE (operands[1]) == CONST_INT
4227 && !const_ok_for_arm (INTVAL (operands[1]))
4228 && !const_ok_for_arm (~INTVAL (operands[1])))
4230 /* Writing a constant to memory needs a scratch, which should
4231 be handled with SECONDARY_RELOADs. */
4232 if (GET_CODE (operands[0]) != REG)
4235 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4236 emit_insn (gen_movsi (operands[0], operands[1]));
4240 else /* TARGET_THUMB */
4242 if (!no_new_pseudos)
4244 if (GET_CODE (operands[0]) != REG)
4245 operands[1] = force_reg (HImode, operands[1]);
4247 /* ??? We shouldn't really get invalid addresses here, but this can
4248 happen if we are passed a SP (never OK for HImode/QImode) or
4249 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4250 HImode/QImode) relative address. */
4251 /* ??? This should perhaps be fixed elsewhere, for instance, in
4252 fixup_stack_1, by checking for other kinds of invalid addresses,
4253 e.g. a bare reference to a virtual register. This may confuse the
4254 alpha though, which must handle this case differently. */
4255 if (GET_CODE (operands[0]) == MEM
4256 && !memory_address_p (GET_MODE (operands[0]),
4257 XEXP (operands[0], 0)))
4259 = replace_equiv_address (operands[0],
4260 copy_to_reg (XEXP (operands[0], 0)));
4262 if (GET_CODE (operands[1]) == MEM
4263 && !memory_address_p (GET_MODE (operands[1]),
4264 XEXP (operands[1], 0)))
4266 = replace_equiv_address (operands[1],
4267 copy_to_reg (XEXP (operands[1], 0)));
4269 /* Handle loading a large integer during reload */
4270 else if (GET_CODE (operands[1]) == CONST_INT
4271 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4273 /* Writing a constant to memory needs a scratch, which should
4274 be handled with SECONDARY_RELOADs. */
4275 if (GET_CODE (operands[0]) != REG)
4278 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4279 emit_insn (gen_movsi (operands[0], operands[1]));
4286 (define_insn "*thumb_movhi_insn"
4287 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4288 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4290 && ( register_operand (operands[0], HImode)
4291 || register_operand (operands[1], HImode))"
4293 switch (which_alternative)
4295 case 0: return \"add %0, %1, #0\";
4296 case 2: return \"strh %1, %0\";
4297 case 3: return \"mov %0, %1\";
4298 case 4: return \"mov %0, %1\";
4299 case 5: return \"mov %0, %1\";
4302 /* The stack pointer can end up being taken as an index register.
4303 Catch this case here and deal with it. */
4304 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4305 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4306 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4309 ops[0] = operands[0];
4310 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4312 output_asm_insn (\"mov %0, %1\", ops);
4314 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4317 return \"ldrh %0, %1\";
4319 [(set_attr "length" "2,4,2,2,2,2")
4320 (set_attr "type" "*,load,store1,*,*,*")
4321 (set_attr "pool_range" "*,64,*,*,*,*")]
4325 (define_insn "rotated_loadsi"
4326 [(set (match_operand:SI 0 "s_register_operand" "=r")
4327 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4329 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4334 ops[0] = operands[0];
4335 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4336 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4339 [(set_attr "type" "load")
4340 (set_attr "predicable" "yes")]
4343 (define_expand "movhi_bytes"
4344 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4346 (zero_extend:SI (match_dup 6)))
4347 (set (match_operand:SI 0 "" "")
4348 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4353 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4355 mem1 = gen_rtx_MEM (QImode, addr);
4356 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4357 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4358 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4359 operands[0] = gen_lowpart (SImode, operands[0]);
4361 operands[2] = gen_reg_rtx (SImode);
4362 operands[3] = gen_reg_rtx (SImode);
4365 if (BYTES_BIG_ENDIAN)
4367 operands[4] = operands[2];
4368 operands[5] = operands[3];
4372 operands[4] = operands[3];
4373 operands[5] = operands[2];
4378 (define_expand "movhi_bigend"
4380 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4383 (ashiftrt:SI (match_dup 2) (const_int 16)))
4384 (set (match_operand:HI 0 "s_register_operand" "")
4385 (subreg:HI (match_dup 3) 0))]
4388 operands[2] = gen_reg_rtx (SImode);
4389 operands[3] = gen_reg_rtx (SImode);
4393 ;; Pattern to recognize insn generated default case above
4394 (define_insn "*movhi_insn_arch4"
4395 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4396 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4399 && (GET_CODE (operands[1]) != CONST_INT
4400 || const_ok_for_arm (INTVAL (operands[1]))
4401 || const_ok_for_arm (~INTVAL (operands[1])))"
4403 mov%?\\t%0, %1\\t%@ movhi
4404 mvn%?\\t%0, #%B1\\t%@ movhi
4405 str%?h\\t%1, %0\\t%@ movhi
4406 ldr%?h\\t%0, %1\\t%@ movhi"
4407 [(set_attr "type" "*,*,store1,load")
4408 (set_attr "predicable" "yes")
4409 (set_attr "pool_range" "*,*,*,256")
4410 (set_attr "neg_pool_range" "*,*,*,244")]
4413 (define_insn "*movhi_insn_littleend"
4414 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4415 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4418 && !BYTES_BIG_ENDIAN
4419 && !TARGET_MMU_TRAPS
4420 && (GET_CODE (operands[1]) != CONST_INT
4421 || const_ok_for_arm (INTVAL (operands[1]))
4422 || const_ok_for_arm (~INTVAL (operands[1])))"
4424 mov%?\\t%0, %1\\t%@ movhi
4425 mvn%?\\t%0, #%B1\\t%@ movhi
4426 ldr%?\\t%0, %1\\t%@ movhi"
4427 [(set_attr "type" "*,*,load")
4428 (set_attr "predicable" "yes")
4429 (set_attr "pool_range" "4096")
4430 (set_attr "neg_pool_range" "4084")]
4433 (define_insn "*movhi_insn_bigend"
4434 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4435 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4439 && !TARGET_MMU_TRAPS
4440 && (GET_CODE (operands[1]) != CONST_INT
4441 || const_ok_for_arm (INTVAL (operands[1]))
4442 || const_ok_for_arm (~INTVAL (operands[1])))"
4444 mov%?\\t%0, %1\\t%@ movhi
4445 mvn%?\\t%0, #%B1\\t%@ movhi
4446 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4447 [(set_attr "type" "*,*,load")
4448 (set_attr "predicable" "yes")
4449 (set_attr "length" "4,4,8")
4450 (set_attr "pool_range" "*,*,4092")
4451 (set_attr "neg_pool_range" "*,*,4084")]
4454 (define_insn "*loadhi_si_bigend"
4455 [(set (match_operand:SI 0 "s_register_operand" "=r")
4456 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4460 && !TARGET_MMU_TRAPS"
4461 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4462 [(set_attr "type" "load")
4463 (set_attr "predicable" "yes")
4464 (set_attr "pool_range" "4096")
4465 (set_attr "neg_pool_range" "4084")]
4468 (define_insn "*movhi_bytes"
4469 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4470 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4471 "TARGET_ARM && TARGET_MMU_TRAPS"
4473 mov%?\\t%0, %1\\t%@ movhi
4474 mvn%?\\t%0, #%B1\\t%@ movhi"
4475 [(set_attr "predicable" "yes")]
4478 (define_insn "thumb_movhi_clobber"
4479 [(set (match_operand:HI 0 "memory_operand" "=m")
4480 (match_operand:HI 1 "register_operand" "l"))
4481 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4487 ;; We use a DImode scratch because we may occasionally need an additional
4488 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4489 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4490 (define_expand "reload_outhi"
4491 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4492 (match_operand:HI 1 "s_register_operand" "r")
4493 (match_operand:DI 2 "s_register_operand" "=&l")])]
4496 arm_reload_out_hi (operands);
4498 thumb_reload_out_hi (operands);
4503 (define_expand "reload_inhi"
4504 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4505 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4506 (match_operand:DI 2 "s_register_operand" "=&r")])]
4507 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4510 arm_reload_in_hi (operands);
4512 thumb_reload_out_hi (operands);
4516 (define_expand "movqi"
4517 [(set (match_operand:QI 0 "general_operand" "")
4518 (match_operand:QI 1 "general_operand" ""))]
4523 /* Everything except mem = const or mem = mem can be done easily */
4525 if (!no_new_pseudos)
4527 if (GET_CODE (operands[1]) == CONST_INT)
4529 rtx reg = gen_reg_rtx (SImode);
4531 emit_insn (gen_movsi (reg, operands[1]));
4532 operands[1] = gen_lowpart (QImode, reg);
4534 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4536 rtx reg = gen_reg_rtx (SImode);
4538 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4539 operands[1] = gen_lowpart (QImode, reg);
4541 if (GET_CODE (operands[0]) == MEM)
4542 operands[1] = force_reg (QImode, operands[1]);
4545 else /* TARGET_THUMB */
4547 if (!no_new_pseudos)
4549 if (GET_CODE (operands[0]) != REG)
4550 operands[1] = force_reg (QImode, operands[1]);
4552 /* ??? We shouldn't really get invalid addresses here, but this can
4553 happen if we are passed a SP (never OK for HImode/QImode) or
4554 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4555 HImode/QImode) relative address. */
4556 /* ??? This should perhaps be fixed elsewhere, for instance, in
4557 fixup_stack_1, by checking for other kinds of invalid addresses,
4558 e.g. a bare reference to a virtual register. This may confuse the
4559 alpha though, which must handle this case differently. */
4560 if (GET_CODE (operands[0]) == MEM
4561 && !memory_address_p (GET_MODE (operands[0]),
4562 XEXP (operands[0], 0)))
4564 = replace_equiv_address (operands[0],
4565 copy_to_reg (XEXP (operands[0], 0)));
4566 if (GET_CODE (operands[1]) == MEM
4567 && !memory_address_p (GET_MODE (operands[1]),
4568 XEXP (operands[1], 0)))
4570 = replace_equiv_address (operands[1],
4571 copy_to_reg (XEXP (operands[1], 0)));
4573 /* Handle loading a large integer during reload */
4574 else if (GET_CODE (operands[1]) == CONST_INT
4575 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4577 /* Writing a constant to memory needs a scratch, which should
4578 be handled with SECONDARY_RELOADs. */
4579 if (GET_CODE (operands[0]) != REG)
4582 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4583 emit_insn (gen_movsi (operands[0], operands[1]));
4591 (define_insn "*arm_movqi_insn"
4592 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4593 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4595 && ( register_operand (operands[0], QImode)
4596 || register_operand (operands[1], QImode))"
4602 [(set_attr "type" "*,*,load,store1")
4603 (set_attr "predicable" "yes")]
4606 (define_insn "*thumb_movqi_insn"
4607 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4608 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4610 && ( register_operand (operands[0], QImode)
4611 || register_operand (operands[1], QImode))"
4619 [(set_attr "length" "2")
4620 (set_attr "type" "*,load,store1,*,*,*")
4621 (set_attr "pool_range" "*,32,*,*,*,*")]
4624 (define_expand "movsf"
4625 [(set (match_operand:SF 0 "general_operand" "")
4626 (match_operand:SF 1 "general_operand" ""))]
4631 if (GET_CODE (operands[0]) == MEM)
4632 operands[1] = force_reg (SFmode, operands[1]);
4634 else /* TARGET_THUMB */
4636 if (!no_new_pseudos)
4638 if (GET_CODE (operands[0]) != REG)
4639 operands[1] = force_reg (SFmode, operands[1]);
4646 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4647 (match_operand:SF 1 "immediate_operand" ""))]
4649 && !TARGET_HARD_FLOAT
4651 && GET_CODE (operands[1]) == CONST_DOUBLE"
4652 [(set (match_dup 2) (match_dup 3))]
4654 operands[2] = gen_lowpart (SImode, operands[0]);
4655 operands[3] = gen_lowpart (SImode, operands[1]);
4656 if (operands[2] == 0 || operands[3] == 0)
4661 (define_insn "*arm_movsf_soft_insn"
4662 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4663 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4666 && TARGET_SOFT_FLOAT
4667 && (GET_CODE (operands[0]) != MEM
4668 || register_operand (operands[1], SFmode))"
4671 ldr%?\\t%0, %1\\t%@ float
4672 str%?\\t%1, %0\\t%@ float"
4673 [(set_attr "length" "4,4,4")
4674 (set_attr "predicable" "yes")
4675 (set_attr "type" "*,load,store1")
4676 (set_attr "pool_range" "*,4096,*")
4677 (set_attr "neg_pool_range" "*,4084,*")]
4680 ;;; ??? This should have alternatives for constants.
4681 (define_insn "*thumb_movsf_insn"
4682 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4683 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4685 && ( register_operand (operands[0], SFmode)
4686 || register_operand (operands[1], SFmode))"
4695 [(set_attr "length" "2")
4696 (set_attr "type" "*,load,store1,load,store1,*,*")
4697 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4700 (define_expand "movdf"
4701 [(set (match_operand:DF 0 "general_operand" "")
4702 (match_operand:DF 1 "general_operand" ""))]
4707 if (GET_CODE (operands[0]) == MEM)
4708 operands[1] = force_reg (DFmode, operands[1]);
4710 else /* TARGET_THUMB */
4712 if (!no_new_pseudos)
4714 if (GET_CODE (operands[0]) != REG)
4715 operands[1] = force_reg (DFmode, operands[1]);
4721 ;; Reloading a df mode value stored in integer regs to memory can require a
4723 (define_expand "reload_outdf"
4724 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4725 (match_operand:DF 1 "s_register_operand" "r")
4726 (match_operand:SI 2 "s_register_operand" "=&r")]
4730 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4733 operands[2] = XEXP (operands[0], 0);
4734 else if (code == POST_INC || code == PRE_DEC)
4736 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4737 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4738 emit_insn (gen_movdi (operands[0], operands[1]));
4741 else if (code == PRE_INC)
4743 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4745 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4748 else if (code == POST_DEC)
4749 operands[2] = XEXP (XEXP (operands[0], 0), 0);
4751 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4752 XEXP (XEXP (operands[0], 0), 1)));
4754 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4757 if (code == POST_DEC)
4758 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4764 (define_insn "*movdf_soft_insn"
4765 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4766 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4767 "TARGET_ARM && TARGET_SOFT_FLOAT
4770 "* return output_move_double (operands);"
4771 [(set_attr "length" "8,8,8")
4772 (set_attr "type" "*,load,store2")
4773 (set_attr "pool_range" "1020")
4774 (set_attr "neg_pool_range" "1008")]
4777 ;;; ??? This should have alternatives for constants.
4778 ;;; ??? This was originally identical to the movdi_insn pattern.
4779 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4780 ;;; thumb_reorg with a memory reference.
4781 (define_insn "*thumb_movdf_insn"
4782 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4783 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
4785 && ( register_operand (operands[0], DFmode)
4786 || register_operand (operands[1], DFmode))"
4788 switch (which_alternative)
4792 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4793 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4794 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4796 return \"ldmia\\t%1, {%0, %H0}\";
4798 return \"stmia\\t%0, {%1, %H1}\";
4800 return thumb_load_double_from_address (operands);
4802 operands[2] = gen_rtx (MEM, SImode,
4803 plus_constant (XEXP (operands[0], 0), 4));
4804 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4807 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4808 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4809 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4812 [(set_attr "length" "4,2,2,6,4,4")
4813 (set_attr "type" "*,load,store2,load,store2,*")
4814 (set_attr "pool_range" "*,*,*,1020,*,*")]
4818 (define_expand "movv2si"
4819 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
4820 (match_operand:V2SI 1 "general_operand" ""))]
4821 "TARGET_REALLY_IWMMXT"
4825 (define_expand "movv4hi"
4826 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
4827 (match_operand:V4HI 1 "general_operand" ""))]
4828 "TARGET_REALLY_IWMMXT"
4832 (define_expand "movv8qi"
4833 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
4834 (match_operand:V8QI 1 "general_operand" ""))]
4835 "TARGET_REALLY_IWMMXT"
4840 ;; load- and store-multiple insns
4841 ;; The arm can load/store any set of registers, provided that they are in
4842 ;; ascending order; but that is beyond GCC so stick with what it knows.
4844 (define_expand "load_multiple"
4845 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4846 (match_operand:SI 1 "" ""))
4847 (use (match_operand:SI 2 "" ""))])]
4850 /* Support only fixed point registers. */
4851 if (GET_CODE (operands[2]) != CONST_INT
4852 || INTVAL (operands[2]) > 14
4853 || INTVAL (operands[2]) < 2
4854 || GET_CODE (operands[1]) != MEM
4855 || GET_CODE (operands[0]) != REG
4856 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
4857 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4861 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
4862 force_reg (SImode, XEXP (operands[1], 0)),
4863 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
4864 MEM_IN_STRUCT_P(operands[1]),
4865 MEM_SCALAR_P (operands[1]));
4869 ;; Load multiple with write-back
4871 (define_insn "*ldmsi_postinc4"
4872 [(match_parallel 0 "load_multiple_operation"
4873 [(set (match_operand:SI 1 "s_register_operand" "=r")
4874 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4876 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4877 (mem:SI (match_dup 2)))
4878 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4879 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4880 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4881 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
4882 (set (match_operand:SI 6 "arm_hard_register_operand" "")
4883 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
4884 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4885 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
4886 [(set_attr "type" "load")
4887 (set_attr "predicable" "yes")]
4890 (define_insn "*ldmsi_postinc3"
4891 [(match_parallel 0 "load_multiple_operation"
4892 [(set (match_operand:SI 1 "s_register_operand" "=r")
4893 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4895 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4896 (mem:SI (match_dup 2)))
4897 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4898 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4899 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4900 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
4901 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4902 "ldm%?ia\\t%1!, {%3, %4, %5}"
4903 [(set_attr "type" "load")
4904 (set_attr "predicable" "yes")]
4907 (define_insn "*ldmsi_postinc2"
4908 [(match_parallel 0 "load_multiple_operation"
4909 [(set (match_operand:SI 1 "s_register_operand" "=r")
4910 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4912 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4913 (mem:SI (match_dup 2)))
4914 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4915 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
4916 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4917 "ldm%?ia\\t%1!, {%3, %4}"
4918 [(set_attr "type" "load")
4919 (set_attr "predicable" "yes")]
4922 ;; Ordinary load multiple
4924 (define_insn "*ldmsi4"
4925 [(match_parallel 0 "load_multiple_operation"
4926 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4927 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4928 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4929 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4930 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4931 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4932 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4933 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
4934 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4935 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
4936 [(set_attr "type" "load")
4937 (set_attr "predicable" "yes")]
4940 (define_insn "*ldmsi3"
4941 [(match_parallel 0 "load_multiple_operation"
4942 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4943 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4944 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4945 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4946 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4947 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
4948 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4949 "ldm%?ia\\t%1, {%2, %3, %4}"
4950 [(set_attr "type" "load")
4951 (set_attr "predicable" "yes")]
4954 (define_insn "*ldmsi2"
4955 [(match_parallel 0 "load_multiple_operation"
4956 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4957 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4958 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4959 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
4960 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4961 "ldm%?ia\\t%1, {%2, %3}"
4962 [(set_attr "type" "load")
4963 (set_attr "predicable" "yes")]
4966 (define_expand "store_multiple"
4967 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4968 (match_operand:SI 1 "" ""))
4969 (use (match_operand:SI 2 "" ""))])]
4972 /* Support only fixed point registers */
4973 if (GET_CODE (operands[2]) != CONST_INT
4974 || INTVAL (operands[2]) > 14
4975 || INTVAL (operands[2]) < 2
4976 || GET_CODE (operands[1]) != REG
4977 || GET_CODE (operands[0]) != MEM
4978 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
4979 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4983 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
4984 force_reg (SImode, XEXP (operands[0], 0)),
4985 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
4986 MEM_IN_STRUCT_P(operands[0]),
4987 MEM_SCALAR_P (operands[0]));
4991 ;; Store multiple with write-back
4993 (define_insn "*stmsi_postinc4"
4994 [(match_parallel 0 "store_multiple_operation"
4995 [(set (match_operand:SI 1 "s_register_operand" "=r")
4996 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4998 (set (mem:SI (match_dup 2))
4999 (match_operand:SI 3 "arm_hard_register_operand" ""))
5000 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5001 (match_operand:SI 4 "arm_hard_register_operand" ""))
5002 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5003 (match_operand:SI 5 "arm_hard_register_operand" ""))
5004 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5005 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5006 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5007 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5008 [(set_attr "predicable" "yes")
5009 (set_attr "type" "store4")]
5012 (define_insn "*stmsi_postinc3"
5013 [(match_parallel 0 "store_multiple_operation"
5014 [(set (match_operand:SI 1 "s_register_operand" "=r")
5015 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5017 (set (mem:SI (match_dup 2))
5018 (match_operand:SI 3 "arm_hard_register_operand" ""))
5019 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5020 (match_operand:SI 4 "arm_hard_register_operand" ""))
5021 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5022 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5023 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5024 "stm%?ia\\t%1!, {%3, %4, %5}"
5025 [(set_attr "predicable" "yes")
5026 (set_attr "type" "store3")]
5029 (define_insn "*stmsi_postinc2"
5030 [(match_parallel 0 "store_multiple_operation"
5031 [(set (match_operand:SI 1 "s_register_operand" "=r")
5032 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5034 (set (mem:SI (match_dup 2))
5035 (match_operand:SI 3 "arm_hard_register_operand" ""))
5036 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5037 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5038 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5039 "stm%?ia\\t%1!, {%3, %4}"
5040 [(set_attr "predicable" "yes")
5041 (set_attr "type" "store2")]
5044 ;; Ordinary store multiple
5046 (define_insn "*stmsi4"
5047 [(match_parallel 0 "store_multiple_operation"
5048 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5049 (match_operand:SI 2 "arm_hard_register_operand" ""))
5050 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5051 (match_operand:SI 3 "arm_hard_register_operand" ""))
5052 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5053 (match_operand:SI 4 "arm_hard_register_operand" ""))
5054 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5055 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5056 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5057 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5058 [(set_attr "predicable" "yes")
5059 (set_attr "type" "store4")]
5062 (define_insn "*stmsi3"
5063 [(match_parallel 0 "store_multiple_operation"
5064 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5065 (match_operand:SI 2 "arm_hard_register_operand" ""))
5066 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5067 (match_operand:SI 3 "arm_hard_register_operand" ""))
5068 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5069 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5070 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5071 "stm%?ia\\t%1, {%2, %3, %4}"
5072 [(set_attr "predicable" "yes")
5073 (set_attr "type" "store3")]
5076 (define_insn "*stmsi2"
5077 [(match_parallel 0 "store_multiple_operation"
5078 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5079 (match_operand:SI 2 "arm_hard_register_operand" ""))
5080 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5081 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5082 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5083 "stm%?ia\\t%1, {%2, %3}"
5084 [(set_attr "predicable" "yes")
5085 (set_attr "type" "store2")]
5088 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5089 ;; We could let this apply for blocks of less than this, but it clobbers so
5090 ;; many registers that there is then probably a better way.
5092 (define_expand "movstrqi"
5093 [(match_operand:BLK 0 "general_operand" "")
5094 (match_operand:BLK 1 "general_operand" "")
5095 (match_operand:SI 2 "const_int_operand" "")
5096 (match_operand:SI 3 "const_int_operand" "")]
5101 if (arm_gen_movstrqi (operands))
5105 else /* TARGET_THUMB */
5107 if ( INTVAL (operands[3]) != 4
5108 || INTVAL (operands[2]) > 48)
5111 thumb_expand_movstrqi (operands);
5117 ;; Thumb block-move insns
5119 (define_insn "movmem12b"
5120 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5121 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5122 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5123 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5124 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5125 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5126 (set (match_operand:SI 0 "register_operand" "=l")
5127 (plus:SI (match_dup 2) (const_int 12)))
5128 (set (match_operand:SI 1 "register_operand" "=l")
5129 (plus:SI (match_dup 3) (const_int 12)))
5130 (clobber (match_scratch:SI 4 "=&l"))
5131 (clobber (match_scratch:SI 5 "=&l"))
5132 (clobber (match_scratch:SI 6 "=&l"))]
5134 "* return thumb_output_move_mem_multiple (3, operands);"
5135 [(set_attr "length" "4")
5136 ; This isn't entirely accurate... It loads as well, but in terms of
5137 ; scheduling the following insn it is better to consider it as a store
5138 (set_attr "type" "store3")]
5141 (define_insn "movmem8b"
5142 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5143 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5144 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5145 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5146 (set (match_operand:SI 0 "register_operand" "=l")
5147 (plus:SI (match_dup 2) (const_int 8)))
5148 (set (match_operand:SI 1 "register_operand" "=l")
5149 (plus:SI (match_dup 3) (const_int 8)))
5150 (clobber (match_scratch:SI 4 "=&l"))
5151 (clobber (match_scratch:SI 5 "=&l"))]
5153 "* return thumb_output_move_mem_multiple (2, operands);"
5154 [(set_attr "length" "4")
5155 ; This isn't entirely accurate... It loads as well, but in terms of
5156 ; scheduling the following insn it is better to consider it as a store
5157 (set_attr "type" "store2")]
5162 ;; Compare & branch insns
5163 ;; The range calculations are based as follows:
5164 ;; For forward branches, the address calculation returns the address of
5165 ;; the next instruction. This is 2 beyond the branch instruction.
5166 ;; For backward branches, the address calculation returns the address of
5167 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5168 ;; instruction for the shortest sequence, and 4 before the branch instruction
5169 ;; if we have to jump around an unconditional branch.
5170 ;; To the basic branch range the PC offset must be added (this is +4).
5171 ;; So for forward branches we have
5172 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5173 ;; And for backward branches we have
5174 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5176 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5177 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5179 (define_insn "cbranchsi4"
5182 (match_operator 0 "arm_comparison_operator"
5183 [(match_operand:SI 1 "register_operand" "l,r")
5184 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5185 (label_ref (match_operand 3 "" ""))
5189 output_asm_insn (\"cmp\\t%1, %2\", operands);
5190 switch (get_attr_length (insn))
5192 case 4: return \"b%d0\\t%l3\";
5193 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5194 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5197 [(set (attr "far_jump")
5199 (eq_attr "length" "8")
5200 (const_string "yes")
5201 (const_string "no")))
5202 (set (attr "length")
5204 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5205 (le (minus (match_dup 3) (pc)) (const_int 256)))
5208 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5209 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5214 (define_insn "*negated_cbranchsi4"
5217 (match_operator 0 "arm_comparison_operator"
5218 [(match_operand:SI 1 "register_operand" "l")
5219 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5220 (label_ref (match_operand 3 "" ""))
5224 output_asm_insn (\"cmn\\t%1, %2\", operands);
5225 switch (get_attr_length (insn))
5227 case 4: return \"b%d0\\t%l3\";
5228 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5229 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5232 [(set (attr "far_jump")
5234 (eq_attr "length" "8")
5235 (const_string "yes")
5236 (const_string "no")))
5237 (set (attr "length")
5239 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5240 (le (minus (match_dup 3) (pc)) (const_int 256)))
5243 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5244 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5249 (define_insn "*cbranchne_decr1"
5251 (if_then_else (match_operator 3 "equality_operator"
5252 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
5254 (label_ref (match_operand 4 "" ""))
5256 (set (match_operand:SI 0 "s_register_operand" "=l,?h,?m,?m")
5257 (plus:SI (match_dup 2) (const_int -1)))
5258 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5263 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
5265 VOIDmode, NULL, NULL);
5266 cond[1] = operands[4];
5268 if (which_alternative == 0)
5269 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
5270 else if (which_alternative == 1)
5272 /* We must provide an alternative for a hi reg because reload
5273 cannot handle output reloads on a jump instruction, but we
5274 can't subtract into that. Fortunately a mov from lo to hi
5275 does not clobber the condition codes. */
5276 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
5277 output_asm_insn (\"mov\\t%0, %1\", operands);
5281 /* Similarly, but the target is memory. */
5282 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
5283 output_asm_insn (\"str\\t%1, %0\", operands);
5286 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5289 output_asm_insn (\"b%d0\\t%l1\", &cond);
5292 output_asm_insn (\"b%D0\\t.LCB%=\", &cond);
5293 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
5295 output_asm_insn (\"b%D0\\t.LCB%=\", &cond);
5296 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5300 [(set (attr "far_jump")
5302 (ior (and (eq (symbol_ref ("which_alternative"))
5304 (eq_attr "length" "8"))
5305 (eq_attr "length" "10"))
5306 (const_string "yes")
5307 (const_string "no")))
5308 (set_attr_alternative "length"
5312 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5313 (le (minus (match_dup 4) (pc)) (const_int 256)))
5316 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5317 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5322 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5323 (le (minus (match_dup 4) (pc)) (const_int 256)))
5326 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5327 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5332 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5333 (le (minus (match_dup 4) (pc)) (const_int 256)))
5336 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5337 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5342 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5343 (le (minus (match_dup 4) (pc)) (const_int 256)))
5346 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5347 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5352 ;; Comparison and test insns
5354 (define_expand "cmpsi"
5355 [(match_operand:SI 0 "s_register_operand" "")
5356 (match_operand:SI 1 "arm_add_operand" "")]
5359 arm_compare_op0 = operands[0];
5360 arm_compare_op1 = operands[1];
5365 (define_expand "cmpsf"
5366 [(match_operand:SF 0 "s_register_operand" "")
5367 (match_operand:SF 1 "fpa_rhs_operand" "")]
5368 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5370 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5371 operands[1] = force_reg (SFmode, operands[1]);
5373 arm_compare_op0 = operands[0];
5374 arm_compare_op1 = operands[1];
5379 (define_expand "cmpdf"
5380 [(match_operand:DF 0 "s_register_operand" "")
5381 (match_operand:DF 1 "fpa_rhs_operand" "")]
5382 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5384 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5385 operands[1] = force_reg (DFmode, operands[1]);
5387 arm_compare_op0 = operands[0];
5388 arm_compare_op1 = operands[1];
5393 (define_insn "*arm_cmpsi_insn"
5394 [(set (reg:CC CC_REGNUM)
5395 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5396 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5401 [(set_attr "conds" "set")]
5404 (define_insn "*cmpsi_shiftsi"
5405 [(set (reg:CC CC_REGNUM)
5406 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5407 (match_operator:SI 3 "shift_operator"
5408 [(match_operand:SI 1 "s_register_operand" "r")
5409 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5412 [(set_attr "conds" "set")
5413 (set_attr "shift" "1")
5417 (define_insn "*cmpsi_shiftsi_swp"
5418 [(set (reg:CC_SWP CC_REGNUM)
5419 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5420 [(match_operand:SI 1 "s_register_operand" "r")
5421 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5422 (match_operand:SI 0 "s_register_operand" "r")))]
5425 [(set_attr "conds" "set")
5426 (set_attr "shift" "1")
5430 (define_insn "*cmpsi_neg_shiftsi"
5431 [(set (reg:CC CC_REGNUM)
5432 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5433 (neg:SI (match_operator:SI 3 "shift_operator"
5434 [(match_operand:SI 1 "s_register_operand" "r")
5435 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5438 [(set_attr "conds" "set")
5439 (set_attr "shift" "1")
5443 ;; Cirrus SF compare instruction
5444 (define_insn "*cirrus_cmpsf"
5445 [(set (reg:CCFP CC_REGNUM)
5446 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5447 (match_operand:SF 1 "cirrus_fp_register" "v")))]
5448 "TARGET_ARM && TARGET_CIRRUS"
5449 "cfcmps%?\\tr15, %V0, %V1"
5450 [(set_attr "type" "mav_farith")
5451 (set_attr "cirrus" "compare")]
5454 ;; Cirrus DF compare instruction
5455 (define_insn "*cirrus_cmpdf"
5456 [(set (reg:CCFP CC_REGNUM)
5457 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5458 (match_operand:DF 1 "cirrus_fp_register" "v")))]
5459 "TARGET_ARM && TARGET_CIRRUS"
5460 "cfcmpd%?\\tr15, %V0, %V1"
5461 [(set_attr "type" "mav_farith")
5462 (set_attr "cirrus" "compare")]
5465 ;; Cirrus DI compare instruction
5466 (define_expand "cmpdi"
5467 [(match_operand:DI 0 "cirrus_fp_register" "")
5468 (match_operand:DI 1 "cirrus_fp_register" "")]
5469 "TARGET_ARM && TARGET_CIRRUS"
5471 arm_compare_op0 = operands[0];
5472 arm_compare_op1 = operands[1];
5476 (define_insn "*cirrus_cmpdi"
5477 [(set (reg:CC CC_REGNUM)
5478 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5479 (match_operand:DI 1 "cirrus_fp_register" "v")))]
5480 "TARGET_ARM && TARGET_CIRRUS"
5481 "cfcmp64%?\\tr15, %V0, %V1"
5482 [(set_attr "type" "mav_farith")
5483 (set_attr "cirrus" "compare")]
5486 ; This insn allows redundant compares to be removed by cse, nothing should
5487 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5488 ; is deleted later on. The match_dup will match the mode here, so that
5489 ; mode changes of the condition codes aren't lost by this even though we don't
5490 ; specify what they are.
5492 (define_insn "*deleted_compare"
5493 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5495 "\\t%@ deleted compare"
5496 [(set_attr "conds" "set")
5497 (set_attr "length" "0")]
5501 ;; Conditional branch insns
5503 (define_expand "beq"
5505 (if_then_else (eq (match_dup 1) (const_int 0))
5506 (label_ref (match_operand 0 "" ""))
5509 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5512 (define_expand "bne"
5514 (if_then_else (ne (match_dup 1) (const_int 0))
5515 (label_ref (match_operand 0 "" ""))
5518 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5521 (define_expand "bgt"
5523 (if_then_else (gt (match_dup 1) (const_int 0))
5524 (label_ref (match_operand 0 "" ""))
5527 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5530 (define_expand "ble"
5532 (if_then_else (le (match_dup 1) (const_int 0))
5533 (label_ref (match_operand 0 "" ""))
5536 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5539 (define_expand "bge"
5541 (if_then_else (ge (match_dup 1) (const_int 0))
5542 (label_ref (match_operand 0 "" ""))
5545 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5548 (define_expand "blt"
5550 (if_then_else (lt (match_dup 1) (const_int 0))
5551 (label_ref (match_operand 0 "" ""))
5554 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5557 (define_expand "bgtu"
5559 (if_then_else (gtu (match_dup 1) (const_int 0))
5560 (label_ref (match_operand 0 "" ""))
5563 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5566 (define_expand "bleu"
5568 (if_then_else (leu (match_dup 1) (const_int 0))
5569 (label_ref (match_operand 0 "" ""))
5572 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5575 (define_expand "bgeu"
5577 (if_then_else (geu (match_dup 1) (const_int 0))
5578 (label_ref (match_operand 0 "" ""))
5581 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5584 (define_expand "bltu"
5586 (if_then_else (ltu (match_dup 1) (const_int 0))
5587 (label_ref (match_operand 0 "" ""))
5590 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5593 (define_expand "bunordered"
5595 (if_then_else (unordered (match_dup 1) (const_int 0))
5596 (label_ref (match_operand 0 "" ""))
5598 "TARGET_ARM && TARGET_HARD_FLOAT"
5599 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5603 (define_expand "bordered"
5605 (if_then_else (ordered (match_dup 1) (const_int 0))
5606 (label_ref (match_operand 0 "" ""))
5608 "TARGET_ARM && TARGET_HARD_FLOAT"
5609 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5613 (define_expand "bungt"
5615 (if_then_else (ungt (match_dup 1) (const_int 0))
5616 (label_ref (match_operand 0 "" ""))
5618 "TARGET_ARM && TARGET_HARD_FLOAT"
5619 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5622 (define_expand "bunlt"
5624 (if_then_else (unlt (match_dup 1) (const_int 0))
5625 (label_ref (match_operand 0 "" ""))
5627 "TARGET_ARM && TARGET_HARD_FLOAT"
5628 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5631 (define_expand "bunge"
5633 (if_then_else (unge (match_dup 1) (const_int 0))
5634 (label_ref (match_operand 0 "" ""))
5636 "TARGET_ARM && TARGET_HARD_FLOAT"
5637 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5640 (define_expand "bunle"
5642 (if_then_else (unle (match_dup 1) (const_int 0))
5643 (label_ref (match_operand 0 "" ""))
5645 "TARGET_ARM && TARGET_HARD_FLOAT"
5646 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5649 ;; The following two patterns need two branch instructions, since there is
5650 ;; no single instruction that will handle all cases.
5651 (define_expand "buneq"
5653 (if_then_else (uneq (match_dup 1) (const_int 0))
5654 (label_ref (match_operand 0 "" ""))
5656 "TARGET_ARM && TARGET_HARD_FLOAT"
5657 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5660 (define_expand "bltgt"
5662 (if_then_else (ltgt (match_dup 1) (const_int 0))
5663 (label_ref (match_operand 0 "" ""))
5665 "TARGET_ARM && TARGET_HARD_FLOAT"
5666 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5670 ;; Patterns to match conditional branch insns.
5673 ; Special pattern to match UNEQ.
5674 (define_insn "*arm_buneq"
5676 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5677 (label_ref (match_operand 0 "" ""))
5679 "TARGET_ARM && TARGET_HARD_FLOAT"
5681 if (arm_ccfsm_state != 0)
5684 return \"bvs\\t%l0\;beq\\t%l0\";
5686 [(set_attr "conds" "jump_clob")
5687 (set_attr "length" "8")]
5690 ; Special pattern to match LTGT.
5691 (define_insn "*arm_bltgt"
5693 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5694 (label_ref (match_operand 0 "" ""))
5696 "TARGET_ARM && TARGET_HARD_FLOAT"
5698 if (arm_ccfsm_state != 0)
5701 return \"bmi\\t%l0\;bgt\\t%l0\";
5703 [(set_attr "conds" "jump_clob")
5704 (set_attr "length" "8")]
5707 (define_insn "*arm_cond_branch"
5709 (if_then_else (match_operator 1 "arm_comparison_operator"
5710 [(match_operand 2 "cc_register" "") (const_int 0)])
5711 (label_ref (match_operand 0 "" ""))
5715 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5717 arm_ccfsm_state += 2;
5720 return \"b%d1\\t%l0\";
5722 [(set_attr "conds" "use")]
5725 ; Special pattern to match reversed UNEQ.
5726 (define_insn "*arm_buneq_reversed"
5728 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5730 (label_ref (match_operand 0 "" ""))))]
5731 "TARGET_ARM && TARGET_HARD_FLOAT"
5733 if (arm_ccfsm_state != 0)
5736 return \"bmi\\t%l0\;bgt\\t%l0\";
5738 [(set_attr "conds" "jump_clob")
5739 (set_attr "length" "8")]
5742 ; Special pattern to match reversed LTGT.
5743 (define_insn "*arm_bltgt_reversed"
5745 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5747 (label_ref (match_operand 0 "" ""))))]
5748 "TARGET_ARM && TARGET_HARD_FLOAT"
5750 if (arm_ccfsm_state != 0)
5753 return \"bvs\\t%l0\;beq\\t%l0\";
5755 [(set_attr "conds" "jump_clob")
5756 (set_attr "length" "8")]
5759 (define_insn "*arm_cond_branch_reversed"
5761 (if_then_else (match_operator 1 "arm_comparison_operator"
5762 [(match_operand 2 "cc_register" "") (const_int 0)])
5764 (label_ref (match_operand 0 "" ""))))]
5767 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5769 arm_ccfsm_state += 2;
5772 return \"b%D1\\t%l0\";
5774 [(set_attr "conds" "use")]
5781 (define_expand "seq"
5782 [(set (match_operand:SI 0 "s_register_operand" "")
5783 (eq:SI (match_dup 1) (const_int 0)))]
5785 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5788 (define_expand "sne"
5789 [(set (match_operand:SI 0 "s_register_operand" "")
5790 (ne:SI (match_dup 1) (const_int 0)))]
5792 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5795 (define_expand "sgt"
5796 [(set (match_operand:SI 0 "s_register_operand" "")
5797 (gt:SI (match_dup 1) (const_int 0)))]
5799 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5802 (define_expand "sle"
5803 [(set (match_operand:SI 0 "s_register_operand" "")
5804 (le:SI (match_dup 1) (const_int 0)))]
5806 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5809 (define_expand "sge"
5810 [(set (match_operand:SI 0 "s_register_operand" "")
5811 (ge:SI (match_dup 1) (const_int 0)))]
5813 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5816 (define_expand "slt"
5817 [(set (match_operand:SI 0 "s_register_operand" "")
5818 (lt:SI (match_dup 1) (const_int 0)))]
5820 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5823 (define_expand "sgtu"
5824 [(set (match_operand:SI 0 "s_register_operand" "")
5825 (gtu:SI (match_dup 1) (const_int 0)))]
5827 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5830 (define_expand "sleu"
5831 [(set (match_operand:SI 0 "s_register_operand" "")
5832 (leu:SI (match_dup 1) (const_int 0)))]
5834 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5837 (define_expand "sgeu"
5838 [(set (match_operand:SI 0 "s_register_operand" "")
5839 (geu:SI (match_dup 1) (const_int 0)))]
5841 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5844 (define_expand "sltu"
5845 [(set (match_operand:SI 0 "s_register_operand" "")
5846 (ltu:SI (match_dup 1) (const_int 0)))]
5848 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5851 (define_expand "sunordered"
5852 [(set (match_operand:SI 0 "s_register_operand" "")
5853 (unordered:SI (match_dup 1) (const_int 0)))]
5854 "TARGET_ARM && TARGET_HARD_FLOAT"
5855 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5859 (define_expand "sordered"
5860 [(set (match_operand:SI 0 "s_register_operand" "")
5861 (ordered:SI (match_dup 1) (const_int 0)))]
5862 "TARGET_ARM && TARGET_HARD_FLOAT"
5863 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5867 (define_expand "sungt"
5868 [(set (match_operand:SI 0 "s_register_operand" "")
5869 (ungt:SI (match_dup 1) (const_int 0)))]
5870 "TARGET_ARM && TARGET_HARD_FLOAT"
5871 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
5875 (define_expand "sunge"
5876 [(set (match_operand:SI 0 "s_register_operand" "")
5877 (unge:SI (match_dup 1) (const_int 0)))]
5878 "TARGET_ARM && TARGET_HARD_FLOAT"
5879 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
5883 (define_expand "sunlt"
5884 [(set (match_operand:SI 0 "s_register_operand" "")
5885 (unlt:SI (match_dup 1) (const_int 0)))]
5886 "TARGET_ARM && TARGET_HARD_FLOAT"
5887 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
5891 (define_expand "sunle"
5892 [(set (match_operand:SI 0 "s_register_operand" "")
5893 (unle:SI (match_dup 1) (const_int 0)))]
5894 "TARGET_ARM && TARGET_HARD_FLOAT"
5895 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
5899 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
5900 ;;; simple ARM instructions.
5902 ; (define_expand "suneq"
5903 ; [(set (match_operand:SI 0 "s_register_operand" "")
5904 ; (uneq:SI (match_dup 1) (const_int 0)))]
5905 ; "TARGET_ARM && TARGET_HARD_FLOAT"
5909 ; (define_expand "sltgt"
5910 ; [(set (match_operand:SI 0 "s_register_operand" "")
5911 ; (ltgt:SI (match_dup 1) (const_int 0)))]
5912 ; "TARGET_ARM && TARGET_HARD_FLOAT"
5916 (define_insn "*mov_scc"
5917 [(set (match_operand:SI 0 "s_register_operand" "=r")
5918 (match_operator:SI 1 "arm_comparison_operator"
5919 [(match_operand 2 "cc_register" "") (const_int 0)]))]
5921 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
5922 [(set_attr "conds" "use")
5923 (set_attr "length" "8")]
5926 (define_insn "*mov_negscc"
5927 [(set (match_operand:SI 0 "s_register_operand" "=r")
5928 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
5929 [(match_operand 2 "cc_register" "") (const_int 0)])))]
5931 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
5932 [(set_attr "conds" "use")
5933 (set_attr "length" "8")]
5936 (define_insn "*mov_notscc"
5937 [(set (match_operand:SI 0 "s_register_operand" "=r")
5938 (not:SI (match_operator:SI 1 "arm_comparison_operator"
5939 [(match_operand 2 "cc_register" "") (const_int 0)])))]
5941 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
5942 [(set_attr "conds" "use")
5943 (set_attr "length" "8")]
5947 ;; Conditional move insns
5949 (define_expand "movsicc"
5950 [(set (match_operand:SI 0 "s_register_operand" "")
5951 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
5952 (match_operand:SI 2 "arm_not_operand" "")
5953 (match_operand:SI 3 "arm_not_operand" "")))]
5957 enum rtx_code code = GET_CODE (operands[1]);
5960 if (code == UNEQ || code == LTGT)
5963 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5964 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5968 (define_expand "movsfcc"
5969 [(set (match_operand:SF 0 "s_register_operand" "")
5970 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
5971 (match_operand:SF 2 "s_register_operand" "")
5972 (match_operand:SF 3 "nonmemory_operand" "")))]
5976 enum rtx_code code = GET_CODE (operands[1]);
5979 if (code == UNEQ || code == LTGT)
5982 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
5983 Otherwise, ensure it is a valid FP add operand */
5984 if ((!TARGET_HARD_FLOAT)
5985 || (!fpa_add_operand (operands[3], SFmode)))
5986 operands[3] = force_reg (SFmode, operands[3]);
5988 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5989 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5993 (define_expand "movdfcc"
5994 [(set (match_operand:DF 0 "s_register_operand" "")
5995 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
5996 (match_operand:DF 2 "s_register_operand" "")
5997 (match_operand:DF 3 "fpa_add_operand" "")))]
5998 "TARGET_ARM && TARGET_HARD_FLOAT"
6001 enum rtx_code code = GET_CODE (operands[1]);
6004 if (code == UNEQ || code == LTGT)
6007 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6008 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6012 (define_insn "*movsicc_insn"
6013 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6015 (match_operator 3 "arm_comparison_operator"
6016 [(match_operand 4 "cc_register" "") (const_int 0)])
6017 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6018 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6025 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6026 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6027 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6028 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6029 [(set_attr "length" "4,4,4,4,8,8,8,8")
6030 (set_attr "conds" "use")]
6033 (define_insn "*movsfcc_soft_insn"
6034 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6035 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6036 [(match_operand 4 "cc_register" "") (const_int 0)])
6037 (match_operand:SF 1 "s_register_operand" "0,r")
6038 (match_operand:SF 2 "s_register_operand" "r,0")))]
6039 "TARGET_ARM && TARGET_SOFT_FLOAT"
6043 [(set_attr "conds" "use")]
6047 ;; Jump and linkage insns
6049 (define_expand "jump"
6051 (label_ref (match_operand 0 "" "")))]
6056 (define_insn "*arm_jump"
6058 (label_ref (match_operand 0 "" "")))]
6062 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6064 arm_ccfsm_state += 2;
6067 return \"b%?\\t%l0\";
6070 [(set_attr "predicable" "yes")]
6073 (define_insn "*thumb_jump"
6075 (label_ref (match_operand 0 "" "")))]
6078 if (get_attr_length (insn) == 2)
6080 return \"bl\\t%l0\\t%@ far jump\";
6082 [(set (attr "far_jump")
6084 (eq_attr "length" "4")
6085 (const_string "yes")
6086 (const_string "no")))
6087 (set (attr "length")
6089 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6090 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6095 (define_expand "call"
6096 [(parallel [(call (match_operand 0 "memory_operand" "")
6097 (match_operand 1 "general_operand" ""))
6098 (use (match_operand 2 "" ""))
6099 (clobber (reg:SI LR_REGNUM))])]
6105 /* In an untyped call, we can get NULL for operand 2. */
6106 if (operands[2] == NULL_RTX)
6107 operands[2] = const0_rtx;
6109 /* This is to decide if we should generate indirect calls by loading the
6110 32 bit address of the callee into a register before performing the
6111 branch and link. operand[2] encodes the long_call/short_call
6112 attribute of the function being called. This attribute is set whenever
6113 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
6114 is used, and the short_call attribute can also be set if function is
6115 declared as static or if it has already been defined in the current
6116 compilation unit. See arm.c and arm.h for info about this. The third
6117 parameter to arm_is_longcall_p is used to tell it which pattern
6119 callee = XEXP (operands[0], 0);
6121 if (GET_CODE (callee) != REG
6122 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
6123 XEXP (operands[0], 0) = force_reg (Pmode, callee);
6127 (define_insn "*call_reg"
6128 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
6129 (match_operand 1 "" ""))
6130 (use (match_operand 2 "" ""))
6131 (clobber (reg:SI LR_REGNUM))]
6134 return output_call (operands);
6136 ;; length is worst case, normally it is only two
6137 [(set_attr "length" "12")
6138 (set_attr "type" "call")]
6141 (define_insn "*call_mem"
6142 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
6143 (match_operand 1 "" ""))
6144 (use (match_operand 2 "" ""))
6145 (clobber (reg:SI LR_REGNUM))]
6148 return output_call_mem (operands);
6150 [(set_attr "length" "12")
6151 (set_attr "type" "call")]
6154 (define_insn "*call_indirect"
6155 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6156 (match_operand 1 "" ""))
6157 (use (match_operand 2 "" ""))
6158 (clobber (reg:SI LR_REGNUM))]
6162 if (TARGET_CALLER_INTERWORKING)
6163 return \"bl\\t%__interwork_call_via_%0\";
6165 return \"bl\\t%__call_via_%0\";
6167 [(set_attr "type" "call")]
6170 (define_insn "*call_value_indirect"
6171 [(set (match_operand 0 "" "")
6172 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6173 (match_operand 2 "" "")))
6174 (use (match_operand 3 "" ""))
6175 (clobber (reg:SI LR_REGNUM))]
6179 if (TARGET_CALLER_INTERWORKING)
6180 return \"bl\\t%__interwork_call_via_%1\";
6182 return \"bl\\t%__call_via_%1\";
6184 [(set_attr "type" "call")]
6187 (define_expand "call_value"
6188 [(parallel [(set (match_operand 0 "" "")
6189 (call (match_operand 1 "memory_operand" "")
6190 (match_operand 2 "general_operand" "")))
6191 (use (match_operand 3 "" ""))
6192 (clobber (reg:SI LR_REGNUM))])]
6196 rtx callee = XEXP (operands[1], 0);
6198 /* In an untyped call, we can get NULL for operand 2. */
6199 if (operands[3] == 0)
6200 operands[3] = const0_rtx;
6202 /* See the comment in define_expand \"call\". */
6203 if (GET_CODE (callee) != REG
6204 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6205 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6209 (define_insn "*call_value_reg"
6210 [(set (match_operand 0 "" "")
6211 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6212 (match_operand 2 "" "")))
6213 (use (match_operand 3 "" ""))
6214 (clobber (reg:SI LR_REGNUM))]
6217 return output_call (&operands[1]);
6219 [(set_attr "length" "12")
6220 (set_attr "type" "call")]
6223 (define_insn "*call_value_mem"
6224 [(set (match_operand 0 "" "")
6225 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
6226 (match_operand 2 "" "")))
6227 (use (match_operand 3 "" ""))
6228 (clobber (reg:SI LR_REGNUM))]
6229 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6231 return output_call_mem (&operands[1]);
6233 [(set_attr "length" "12")
6234 (set_attr "type" "call")]
6237 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6238 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6240 (define_insn "*call_symbol"
6241 [(call (mem:SI (match_operand:SI 0 "" ""))
6242 (match_operand 1 "" ""))
6243 (use (match_operand 2 "" ""))
6244 (clobber (reg:SI LR_REGNUM))]
6246 && (GET_CODE (operands[0]) == SYMBOL_REF)
6247 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6250 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6252 [(set_attr "type" "call")]
6255 (define_insn "*call_value_symbol"
6256 [(set (match_operand 0 "s_register_operand" "")
6257 (call (mem:SI (match_operand:SI 1 "" ""))
6258 (match_operand:SI 2 "" "")))
6259 (use (match_operand 3 "" ""))
6260 (clobber (reg:SI LR_REGNUM))]
6262 && (GET_CODE (operands[1]) == SYMBOL_REF)
6263 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6266 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6268 [(set_attr "type" "call")]
6271 (define_insn "*call_insn"
6272 [(call (mem:SI (match_operand:SI 0 "" ""))
6273 (match_operand:SI 1 "" ""))
6274 (use (match_operand 2 "" ""))
6275 (clobber (reg:SI LR_REGNUM))]
6277 && GET_CODE (operands[0]) == SYMBOL_REF
6278 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6280 [(set_attr "length" "4")
6281 (set_attr "type" "call")]
6284 (define_insn "*call_value_insn"
6285 [(set (match_operand 0 "register_operand" "")
6286 (call (mem:SI (match_operand 1 "" ""))
6287 (match_operand 2 "" "")))
6288 (use (match_operand 3 "" ""))
6289 (clobber (reg:SI LR_REGNUM))]
6291 && GET_CODE (operands[1]) == SYMBOL_REF
6292 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6294 [(set_attr "length" "4")
6295 (set_attr "type" "call")]
6298 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6299 (define_expand "sibcall"
6300 [(parallel [(call (match_operand 0 "memory_operand" "")
6301 (match_operand 1 "general_operand" ""))
6303 (use (match_operand 2 "" ""))])]
6307 if (operands[2] == NULL_RTX)
6308 operands[2] = const0_rtx;
6312 (define_expand "sibcall_value"
6313 [(parallel [(set (match_operand 0 "register_operand" "")
6314 (call (match_operand 1 "memory_operand" "")
6315 (match_operand 2 "general_operand" "")))
6317 (use (match_operand 3 "" ""))])]
6321 if (operands[3] == NULL_RTX)
6322 operands[3] = const0_rtx;
6326 (define_insn "*sibcall_insn"
6327 [(call (mem:SI (match_operand:SI 0 "" "X"))
6328 (match_operand 1 "" ""))
6330 (use (match_operand 2 "" ""))]
6331 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6333 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6335 [(set_attr "type" "call")]
6338 (define_insn "*sibcall_value_insn"
6339 [(set (match_operand 0 "s_register_operand" "")
6340 (call (mem:SI (match_operand:SI 1 "" "X"))
6341 (match_operand 2 "" "")))
6343 (use (match_operand 3 "" ""))]
6344 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6346 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6348 [(set_attr "type" "call")]
6351 ;; Often the return insn will be the same as loading from memory, so set attr
6352 (define_insn "return"
6354 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6357 if (arm_ccfsm_state == 2)
6359 arm_ccfsm_state += 2;
6362 return output_return_instruction (const_true_rtx, TRUE, FALSE);
6364 [(set_attr "type" "load")
6365 (set_attr "length" "12")
6366 (set_attr "predicable" "yes")]
6369 (define_insn "*cond_return"
6371 (if_then_else (match_operator 0 "arm_comparison_operator"
6372 [(match_operand 1 "cc_register" "") (const_int 0)])
6375 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6378 if (arm_ccfsm_state == 2)
6380 arm_ccfsm_state += 2;
6383 return output_return_instruction (operands[0], TRUE, FALSE);
6385 [(set_attr "conds" "use")
6386 (set_attr "length" "12")
6387 (set_attr "type" "load")]
6390 (define_insn "*cond_return_inverted"
6392 (if_then_else (match_operator 0 "arm_comparison_operator"
6393 [(match_operand 1 "cc_register" "") (const_int 0)])
6396 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6399 if (arm_ccfsm_state == 2)
6401 arm_ccfsm_state += 2;
6404 return output_return_instruction (operands[0], TRUE, TRUE);
6406 [(set_attr "conds" "use")
6407 (set_attr "type" "load")]
6410 ;; Generate a sequence of instructions to determine if the processor is
6411 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6414 (define_expand "return_addr_mask"
6416 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6418 (set (match_operand:SI 0 "s_register_operand" "")
6419 (if_then_else:SI (eq (match_dup 1) (const_int 0))
6421 (const_int 67108860)))] ; 0x03fffffc
6424 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6427 (define_insn "*check_arch2"
6428 [(set (match_operand:CC_NOOV 0 "cc_register" "")
6429 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6432 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6433 [(set_attr "length" "8")
6434 (set_attr "conds" "set")]
6437 ;; Call subroutine returning any type.
6439 (define_expand "untyped_call"
6440 [(parallel [(call (match_operand 0 "" "")
6442 (match_operand 1 "" "")
6443 (match_operand 2 "" "")])]
6449 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6451 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6453 rtx set = XVECEXP (operands[2], 0, i);
6455 emit_move_insn (SET_DEST (set), SET_SRC (set));
6458 /* The optimizer does not know that the call sets the function value
6459 registers we stored in the result block. We avoid problems by
6460 claiming that all hard registers are used and clobbered at this
6462 emit_insn (gen_blockage ());
6468 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6469 ;; all of memory. This blocks insns from being moved across this point.
6471 (define_insn "blockage"
6472 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6475 [(set_attr "length" "0")
6476 (set_attr "type" "block")]
6479 (define_expand "casesi"
6480 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6481 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6482 (match_operand:SI 2 "const_int_operand" "") ; total range
6483 (match_operand:SI 3 "" "") ; table label
6484 (match_operand:SI 4 "" "")] ; Out of range label
6489 if (operands[1] != const0_rtx)
6491 reg = gen_reg_rtx (SImode);
6493 emit_insn (gen_addsi3 (reg, operands[0],
6494 GEN_INT (-INTVAL (operands[1]))));
6498 if (!const_ok_for_arm (INTVAL (operands[2])))
6499 operands[2] = force_reg (SImode, operands[2]);
6501 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6507 ;; The USE in this pattern is needed to tell flow analysis that this is
6508 ;; a CASESI insn. It has no other purpose.
6509 (define_insn "casesi_internal"
6510 [(parallel [(set (pc)
6512 (leu (match_operand:SI 0 "s_register_operand" "r")
6513 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6514 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6515 (label_ref (match_operand 2 "" ""))))
6516 (label_ref (match_operand 3 "" ""))))
6517 (clobber (reg:CC CC_REGNUM))
6518 (use (label_ref (match_dup 2)))])]
6522 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6523 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6525 [(set_attr "conds" "clob")
6526 (set_attr "length" "12")]
6529 (define_expand "indirect_jump"
6531 (match_operand:SI 0 "s_register_operand" ""))]
6536 (define_insn "*arm_indirect_jump"
6538 (match_operand:SI 0 "s_register_operand" "r"))]
6540 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6541 [(set_attr "predicable" "yes")]
6544 ;; Although not supported by the define_expand above,
6545 ;; cse/combine may generate this form.
6546 (define_insn "*load_indirect_jump"
6548 (match_operand:SI 0 "memory_operand" "m"))]
6550 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6551 [(set_attr "type" "load")
6552 (set_attr "pool_range" "4096")
6553 (set_attr "neg_pool_range" "4084")
6554 (set_attr "predicable" "yes")]
6557 (define_insn "*thumb_indirect_jump"
6559 (match_operand:SI 0 "register_operand" "l*r"))]
6562 [(set_attr "conds" "clob")
6563 (set_attr "length" "2")]
6574 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6575 return \"mov\\tr8, r8\";
6577 [(set (attr "length")
6578 (if_then_else (eq_attr "is_thumb" "yes")
6584 ;; Patterns to allow combination of arithmetic, cond code and shifts
6586 (define_insn "*arith_shiftsi"
6587 [(set (match_operand:SI 0 "s_register_operand" "=r")
6588 (match_operator:SI 1 "shiftable_operator"
6589 [(match_operator:SI 3 "shift_operator"
6590 [(match_operand:SI 4 "s_register_operand" "r")
6591 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6592 (match_operand:SI 2 "s_register_operand" "r")]))]
6594 "%i1%?\\t%0, %2, %4%S3"
6595 [(set_attr "predicable" "yes")
6596 (set_attr "shift" "4")
6600 (define_insn "*arith_shiftsi_compare0"
6601 [(set (reg:CC_NOOV CC_REGNUM)
6602 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6603 [(match_operator:SI 3 "shift_operator"
6604 [(match_operand:SI 4 "s_register_operand" "r")
6605 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6606 (match_operand:SI 2 "s_register_operand" "r")])
6608 (set (match_operand:SI 0 "s_register_operand" "=r")
6609 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6612 "%i1%?s\\t%0, %2, %4%S3"
6613 [(set_attr "conds" "set")
6614 (set_attr "shift" "4")
6618 (define_insn "*arith_shiftsi_compare0_scratch"
6619 [(set (reg:CC_NOOV CC_REGNUM)
6620 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6621 [(match_operator:SI 3 "shift_operator"
6622 [(match_operand:SI 4 "s_register_operand" "r")
6623 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6624 (match_operand:SI 2 "s_register_operand" "r")])
6626 (clobber (match_scratch:SI 0 "=r"))]
6628 "%i1%?s\\t%0, %2, %4%S3"
6629 [(set_attr "conds" "set")
6630 (set_attr "shift" "4")
6634 (define_insn "*sub_shiftsi"
6635 [(set (match_operand:SI 0 "s_register_operand" "=r")
6636 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6637 (match_operator:SI 2 "shift_operator"
6638 [(match_operand:SI 3 "s_register_operand" "r")
6639 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6641 "sub%?\\t%0, %1, %3%S2"
6642 [(set_attr "predicable" "yes")
6643 (set_attr "shift" "3")
6647 (define_insn "*sub_shiftsi_compare0"
6648 [(set (reg:CC_NOOV CC_REGNUM)
6650 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6651 (match_operator:SI 2 "shift_operator"
6652 [(match_operand:SI 3 "s_register_operand" "r")
6653 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6655 (set (match_operand:SI 0 "s_register_operand" "=r")
6656 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6659 "sub%?s\\t%0, %1, %3%S2"
6660 [(set_attr "conds" "set")
6661 (set_attr "shift" "3")
6665 (define_insn "*sub_shiftsi_compare0_scratch"
6666 [(set (reg:CC_NOOV CC_REGNUM)
6668 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6669 (match_operator:SI 2 "shift_operator"
6670 [(match_operand:SI 3 "s_register_operand" "r")
6671 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6673 (clobber (match_scratch:SI 0 "=r"))]
6675 "sub%?s\\t%0, %1, %3%S2"
6676 [(set_attr "conds" "set")
6677 (set_attr "shift" "3")
6683 (define_insn "*and_scc"
6684 [(set (match_operand:SI 0 "s_register_operand" "=r")
6685 (and:SI (match_operator:SI 1 "arm_comparison_operator"
6686 [(match_operand 3 "cc_register" "") (const_int 0)])
6687 (match_operand:SI 2 "s_register_operand" "r")))]
6689 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6690 [(set_attr "conds" "use")
6691 (set_attr "length" "8")]
6694 (define_insn "*ior_scc"
6695 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6696 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6697 [(match_operand 3 "cc_register" "") (const_int 0)])
6698 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6702 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6703 [(set_attr "conds" "use")
6704 (set_attr "length" "4,8")]
6707 (define_insn "*compare_scc"
6708 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6709 (match_operator:SI 1 "arm_comparison_operator"
6710 [(match_operand:SI 2 "s_register_operand" "r,r")
6711 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6712 (clobber (reg:CC CC_REGNUM))]
6715 if (operands[3] == const0_rtx)
6717 if (GET_CODE (operands[1]) == LT)
6718 return \"mov\\t%0, %2, lsr #31\";
6720 if (GET_CODE (operands[1]) == GE)
6721 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6723 if (GET_CODE (operands[1]) == EQ)
6724 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
6727 if (GET_CODE (operands[1]) == NE)
6729 if (which_alternative == 1)
6730 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
6731 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
6733 if (which_alternative == 1)
6734 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6736 output_asm_insn (\"cmp\\t%2, %3\", operands);
6737 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
6739 [(set_attr "conds" "clob")
6740 (set_attr "length" "12")]
6743 (define_insn "*cond_move"
6744 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6745 (if_then_else:SI (match_operator 3 "equality_operator"
6746 [(match_operator 4 "arm_comparison_operator"
6747 [(match_operand 5 "cc_register" "") (const_int 0)])
6749 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6750 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
6753 if (GET_CODE (operands[3]) == NE)
6755 if (which_alternative != 1)
6756 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
6757 if (which_alternative != 0)
6758 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6761 if (which_alternative != 0)
6762 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6763 if (which_alternative != 1)
6764 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
6767 [(set_attr "conds" "use")
6768 (set_attr "length" "4,4,8")]
6771 (define_insn "*cond_arith"
6772 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6773 (match_operator:SI 5 "shiftable_operator"
6774 [(match_operator:SI 4 "arm_comparison_operator"
6775 [(match_operand:SI 2 "s_register_operand" "r,r")
6776 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
6777 (match_operand:SI 1 "s_register_operand" "0,?r")]))
6778 (clobber (reg:CC CC_REGNUM))]
6781 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
6782 return \"%i5\\t%0, %1, %2, lsr #31\";
6784 output_asm_insn (\"cmp\\t%2, %3\", operands);
6785 if (GET_CODE (operands[5]) == AND)
6786 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
6787 else if (GET_CODE (operands[5]) == MINUS)
6788 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
6789 else if (which_alternative != 0)
6790 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6791 return \"%i5%d4\\t%0, %1, #1\";
6793 [(set_attr "conds" "clob")
6794 (set_attr "length" "12")]
6797 (define_insn "*cond_sub"
6798 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6799 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
6800 (match_operator:SI 4 "arm_comparison_operator"
6801 [(match_operand:SI 2 "s_register_operand" "r,r")
6802 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
6803 (clobber (reg:CC CC_REGNUM))]
6806 output_asm_insn (\"cmp\\t%2, %3\", operands);
6807 if (which_alternative != 0)
6808 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6809 return \"sub%d4\\t%0, %1, #1\";
6811 [(set_attr "conds" "clob")
6812 (set_attr "length" "8,12")]
6815 (define_insn "*cmp_ite0"
6816 [(set (match_operand 6 "dominant_cc_register" "")
6819 (match_operator 4 "arm_comparison_operator"
6820 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6821 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6822 (match_operator:SI 5 "arm_comparison_operator"
6823 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6824 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6830 static const char * const opcodes[4][2] =
6832 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6833 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6834 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6835 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6836 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6837 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6838 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6839 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6842 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6844 return opcodes[which_alternative][swap];
6846 [(set_attr "conds" "set")
6847 (set_attr "length" "8")]
6850 (define_insn "*cmp_ite1"
6851 [(set (match_operand 6 "dominant_cc_register" "")
6854 (match_operator 4 "arm_comparison_operator"
6855 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6856 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6857 (match_operator:SI 5 "arm_comparison_operator"
6858 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6859 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6865 static const char * const opcodes[4][2] =
6867 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
6868 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6869 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
6870 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6871 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
6872 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6873 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
6874 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6877 comparison_dominates_p (GET_CODE (operands[5]),
6878 reverse_condition (GET_CODE (operands[4])));
6880 return opcodes[which_alternative][swap];
6882 [(set_attr "conds" "set")
6883 (set_attr "length" "8")]
6886 (define_insn "*cmp_and"
6887 [(set (match_operand 6 "dominant_cc_register" "")
6890 (match_operator 4 "arm_comparison_operator"
6891 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6892 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6893 (match_operator:SI 5 "arm_comparison_operator"
6894 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6895 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6900 static const char *const opcodes[4][2] =
6902 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6903 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6904 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6905 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6906 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6907 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6908 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6909 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6912 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6914 return opcodes[which_alternative][swap];
6916 [(set_attr "conds" "set")
6917 (set_attr "predicable" "no")
6918 (set_attr "length" "8")]
6921 (define_insn "*cmp_ior"
6922 [(set (match_operand 6 "dominant_cc_register" "")
6925 (match_operator 4 "arm_comparison_operator"
6926 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6927 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6928 (match_operator:SI 5 "arm_comparison_operator"
6929 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6930 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6935 static const char *const opcodes[4][2] =
6937 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
6938 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6939 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
6940 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6941 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
6942 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6943 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
6944 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6947 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6949 return opcodes[which_alternative][swap];
6952 [(set_attr "conds" "set")
6953 (set_attr "length" "8")]
6956 (define_insn_and_split "*ior_scc_scc"
6957 [(set (match_operand:SI 0 "s_register_operand" "=r")
6958 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6959 [(match_operand:SI 1 "s_register_operand" "r")
6960 (match_operand:SI 2 "arm_add_operand" "rIL")])
6961 (match_operator:SI 6 "arm_comparison_operator"
6962 [(match_operand:SI 4 "s_register_operand" "r")
6963 (match_operand:SI 5 "arm_add_operand" "rIL")])))
6964 (clobber (reg:CC CC_REGNUM))]
6966 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
6969 "TARGET_ARM && reload_completed"
6973 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6974 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6976 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
6978 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
6981 [(set_attr "conds" "clob")
6982 (set_attr "length" "16")])
6984 ; If the above pattern is followed by a CMP insn, then the compare is
6985 ; redundant, since we can rework the conditional instruction that follows.
6986 (define_insn_and_split "*ior_scc_scc_cmp"
6987 [(set (match_operand 0 "dominant_cc_register" "")
6988 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6989 [(match_operand:SI 1 "s_register_operand" "r")
6990 (match_operand:SI 2 "arm_add_operand" "rIL")])
6991 (match_operator:SI 6 "arm_comparison_operator"
6992 [(match_operand:SI 4 "s_register_operand" "r")
6993 (match_operand:SI 5 "arm_add_operand" "rIL")]))
6995 (set (match_operand:SI 7 "s_register_operand" "=r")
6996 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6997 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
7000 "TARGET_ARM && reload_completed"
7004 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7005 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7007 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
7009 [(set_attr "conds" "set")
7010 (set_attr "length" "16")])
7012 (define_insn_and_split "*and_scc_scc"
7013 [(set (match_operand:SI 0 "s_register_operand" "=r")
7014 (and:SI (match_operator:SI 3 "arm_comparison_operator"
7015 [(match_operand:SI 1 "s_register_operand" "r")
7016 (match_operand:SI 2 "arm_add_operand" "rIL")])
7017 (match_operator:SI 6 "arm_comparison_operator"
7018 [(match_operand:SI 4 "s_register_operand" "r")
7019 (match_operand:SI 5 "arm_add_operand" "rIL")])))
7020 (clobber (reg:CC CC_REGNUM))]
7022 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7025 "TARGET_ARM && reload_completed
7026 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7031 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7032 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7034 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
7036 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
7039 [(set_attr "conds" "clob")
7040 (set_attr "length" "16")])
7042 ; If the above pattern is followed by a CMP insn, then the compare is
7043 ; redundant, since we can rework the conditional instruction that follows.
7044 (define_insn_and_split "*and_scc_scc_cmp"
7045 [(set (match_operand 0 "dominant_cc_register" "")
7046 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
7047 [(match_operand:SI 1 "s_register_operand" "r")
7048 (match_operand:SI 2 "arm_add_operand" "rIL")])
7049 (match_operator:SI 6 "arm_comparison_operator"
7050 [(match_operand:SI 4 "s_register_operand" "r")
7051 (match_operand:SI 5 "arm_add_operand" "rIL")]))
7053 (set (match_operand:SI 7 "s_register_operand" "=r")
7054 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7055 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
7058 "TARGET_ARM && reload_completed"
7062 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7063 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7065 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
7067 [(set_attr "conds" "set")
7068 (set_attr "length" "16")])
7070 ;; If there is no dominance in the comparison, then we can still save an
7071 ;; instruction in the AND case, since we can know that the second compare
7072 ;; need only zero the value if false (if true, then the value is already
7074 (define_insn_and_split "*and_scc_scc_nodom"
7075 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
7076 (and:SI (match_operator:SI 3 "arm_comparison_operator"
7077 [(match_operand:SI 1 "s_register_operand" "r,r,0")
7078 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
7079 (match_operator:SI 6 "arm_comparison_operator"
7080 [(match_operand:SI 4 "s_register_operand" "r,r,r")
7081 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
7082 (clobber (reg:CC CC_REGNUM))]
7084 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7087 "TARGET_ARM && reload_completed"
7088 [(parallel [(set (match_dup 0)
7089 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
7090 (clobber (reg:CC CC_REGNUM))])
7091 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
7093 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
7096 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
7097 operands[4], operands[5]),
7099 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
7101 [(set_attr "conds" "clob")
7102 (set_attr "length" "20")])
7104 (define_insn "*negscc"
7105 [(set (match_operand:SI 0 "s_register_operand" "=r")
7106 (neg:SI (match_operator 3 "arm_comparison_operator"
7107 [(match_operand:SI 1 "s_register_operand" "r")
7108 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
7109 (clobber (reg:CC CC_REGNUM))]
7112 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
7113 return \"mov\\t%0, %1, asr #31\";
7115 if (GET_CODE (operands[3]) == NE)
7116 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
7118 if (GET_CODE (operands[3]) == GT)
7119 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
7121 output_asm_insn (\"cmp\\t%1, %2\", operands);
7122 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
7123 return \"mvn%d3\\t%0, #0\";
7125 [(set_attr "conds" "clob")
7126 (set_attr "length" "12")]
7129 (define_insn "movcond"
7130 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7132 (match_operator 5 "arm_comparison_operator"
7133 [(match_operand:SI 3 "s_register_operand" "r,r,r")
7134 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
7135 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7136 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
7137 (clobber (reg:CC CC_REGNUM))]
7140 if (GET_CODE (operands[5]) == LT
7141 && (operands[4] == const0_rtx))
7143 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7145 if (operands[2] == const0_rtx)
7146 return \"and\\t%0, %1, %3, asr #31\";
7147 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
7149 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7151 if (operands[1] == const0_rtx)
7152 return \"bic\\t%0, %2, %3, asr #31\";
7153 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
7155 /* The only case that falls through to here is when both ops 1 & 2
7159 if (GET_CODE (operands[5]) == GE
7160 && (operands[4] == const0_rtx))
7162 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7164 if (operands[2] == const0_rtx)
7165 return \"bic\\t%0, %1, %3, asr #31\";
7166 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7168 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7170 if (operands[1] == const0_rtx)
7171 return \"and\\t%0, %2, %3, asr #31\";
7172 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7174 /* The only case that falls through to here is when both ops 1 & 2
7177 if (GET_CODE (operands[4]) == CONST_INT
7178 && !const_ok_for_arm (INTVAL (operands[4])))
7179 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7181 output_asm_insn (\"cmp\\t%3, %4\", operands);
7182 if (which_alternative != 0)
7183 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7184 if (which_alternative != 1)
7185 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7188 [(set_attr "conds" "clob")
7189 (set_attr "length" "8,8,12")]
7192 (define_insn "*ifcompare_plus_move"
7193 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7194 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7195 [(match_operand:SI 4 "s_register_operand" "r,r")
7196 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7198 (match_operand:SI 2 "s_register_operand" "r,r")
7199 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7200 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7201 (clobber (reg:CC CC_REGNUM))]
7204 [(set_attr "conds" "clob")
7205 (set_attr "length" "8,12")]
7208 (define_insn "*if_plus_move"
7209 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7211 (match_operator 4 "arm_comparison_operator"
7212 [(match_operand 5 "cc_register" "") (const_int 0)])
7214 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7215 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7216 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7220 sub%d4\\t%0, %2, #%n3
7221 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7222 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7223 [(set_attr "conds" "use")
7224 (set_attr "length" "4,4,8,8")
7225 (set_attr "type" "*,*,*,*")]
7228 (define_insn "*ifcompare_move_plus"
7229 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7230 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7231 [(match_operand:SI 4 "s_register_operand" "r,r")
7232 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7233 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7235 (match_operand:SI 2 "s_register_operand" "r,r")
7236 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7237 (clobber (reg:CC CC_REGNUM))]
7240 [(set_attr "conds" "clob")
7241 (set_attr "length" "8,12")]
7244 (define_insn "*if_move_plus"
7245 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7247 (match_operator 4 "arm_comparison_operator"
7248 [(match_operand 5 "cc_register" "") (const_int 0)])
7249 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7251 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7252 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7256 sub%D4\\t%0, %2, #%n3
7257 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7258 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7259 [(set_attr "conds" "use")
7260 (set_attr "length" "4,4,8,8")
7261 (set_attr "type" "*,*,*,*")]
7264 (define_insn "*ifcompare_arith_arith"
7265 [(set (match_operand:SI 0 "s_register_operand" "=r")
7266 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7267 [(match_operand:SI 5 "s_register_operand" "r")
7268 (match_operand:SI 6 "arm_add_operand" "rIL")])
7269 (match_operator:SI 8 "shiftable_operator"
7270 [(match_operand:SI 1 "s_register_operand" "r")
7271 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7272 (match_operator:SI 7 "shiftable_operator"
7273 [(match_operand:SI 3 "s_register_operand" "r")
7274 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7275 (clobber (reg:CC CC_REGNUM))]
7278 [(set_attr "conds" "clob")
7279 (set_attr "length" "12")]
7282 (define_insn "*if_arith_arith"
7283 [(set (match_operand:SI 0 "s_register_operand" "=r")
7284 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7285 [(match_operand 8 "cc_register" "") (const_int 0)])
7286 (match_operator:SI 6 "shiftable_operator"
7287 [(match_operand:SI 1 "s_register_operand" "r")
7288 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7289 (match_operator:SI 7 "shiftable_operator"
7290 [(match_operand:SI 3 "s_register_operand" "r")
7291 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7293 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7294 [(set_attr "conds" "use")
7295 (set_attr "length" "8")]
7298 (define_insn "*ifcompare_arith_move"
7299 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7300 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7301 [(match_operand:SI 2 "s_register_operand" "r,r")
7302 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7303 (match_operator:SI 7 "shiftable_operator"
7304 [(match_operand:SI 4 "s_register_operand" "r,r")
7305 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7306 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7307 (clobber (reg:CC CC_REGNUM))]
7310 /* If we have an operation where (op x 0) is the identity operation and
7311 the conditional operator is LT or GE and we are comparing against zero and
7312 everything is in registers then we can do this in two instructions */
7313 if (operands[3] == const0_rtx
7314 && GET_CODE (operands[7]) != AND
7315 && GET_CODE (operands[5]) == REG
7316 && GET_CODE (operands[1]) == REG
7317 && REGNO (operands[1]) == REGNO (operands[4])
7318 && REGNO (operands[4]) != REGNO (operands[0]))
7320 if (GET_CODE (operands[6]) == LT)
7321 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7322 else if (GET_CODE (operands[6]) == GE)
7323 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7325 if (GET_CODE (operands[3]) == CONST_INT
7326 && !const_ok_for_arm (INTVAL (operands[3])))
7327 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7329 output_asm_insn (\"cmp\\t%2, %3\", operands);
7330 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7331 if (which_alternative != 0)
7332 return \"mov%D6\\t%0, %1\";
7335 [(set_attr "conds" "clob")
7336 (set_attr "length" "8,12")]
7339 (define_insn "*if_arith_move"
7340 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7341 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7342 [(match_operand 6 "cc_register" "") (const_int 0)])
7343 (match_operator:SI 5 "shiftable_operator"
7344 [(match_operand:SI 2 "s_register_operand" "r,r")
7345 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7346 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7350 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7351 [(set_attr "conds" "use")
7352 (set_attr "length" "4,8")
7353 (set_attr "type" "*,*")]
7356 (define_insn "*ifcompare_move_arith"
7357 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7358 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7359 [(match_operand:SI 4 "s_register_operand" "r,r")
7360 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7361 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7362 (match_operator:SI 7 "shiftable_operator"
7363 [(match_operand:SI 2 "s_register_operand" "r,r")
7364 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7365 (clobber (reg:CC CC_REGNUM))]
7368 /* If we have an operation where (op x 0) is the identity operation and
7369 the conditional operator is LT or GE and we are comparing against zero and
7370 everything is in registers then we can do this in two instructions */
7371 if (operands[5] == const0_rtx
7372 && GET_CODE (operands[7]) != AND
7373 && GET_CODE (operands[3]) == REG
7374 && GET_CODE (operands[1]) == REG
7375 && REGNO (operands[1]) == REGNO (operands[2])
7376 && REGNO (operands[2]) != REGNO (operands[0]))
7378 if (GET_CODE (operands[6]) == GE)
7379 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7380 else if (GET_CODE (operands[6]) == LT)
7381 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7384 if (GET_CODE (operands[5]) == CONST_INT
7385 && !const_ok_for_arm (INTVAL (operands[5])))
7386 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7388 output_asm_insn (\"cmp\\t%4, %5\", operands);
7390 if (which_alternative != 0)
7391 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7392 return \"%I7%D6\\t%0, %2, %3\";
7394 [(set_attr "conds" "clob")
7395 (set_attr "length" "8,12")]
7398 (define_insn "*if_move_arith"
7399 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7401 (match_operator 4 "arm_comparison_operator"
7402 [(match_operand 6 "cc_register" "") (const_int 0)])
7403 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7404 (match_operator:SI 5 "shiftable_operator"
7405 [(match_operand:SI 2 "s_register_operand" "r,r")
7406 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7410 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7411 [(set_attr "conds" "use")
7412 (set_attr "length" "4,8")
7413 (set_attr "type" "*,*")]
7416 (define_insn "*ifcompare_move_not"
7417 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7419 (match_operator 5 "arm_comparison_operator"
7420 [(match_operand:SI 3 "s_register_operand" "r,r")
7421 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7422 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7424 (match_operand:SI 2 "s_register_operand" "r,r"))))
7425 (clobber (reg:CC CC_REGNUM))]
7428 [(set_attr "conds" "clob")
7429 (set_attr "length" "8,12")]
7432 (define_insn "*if_move_not"
7433 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7435 (match_operator 4 "arm_comparison_operator"
7436 [(match_operand 3 "cc_register" "") (const_int 0)])
7437 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7438 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7442 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7443 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7444 [(set_attr "conds" "use")
7445 (set_attr "length" "4,8,8")]
7448 (define_insn "*ifcompare_not_move"
7449 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7451 (match_operator 5 "arm_comparison_operator"
7452 [(match_operand:SI 3 "s_register_operand" "r,r")
7453 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7455 (match_operand:SI 2 "s_register_operand" "r,r"))
7456 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7457 (clobber (reg:CC CC_REGNUM))]
7460 [(set_attr "conds" "clob")
7461 (set_attr "length" "8,12")]
7464 (define_insn "*if_not_move"
7465 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7467 (match_operator 4 "arm_comparison_operator"
7468 [(match_operand 3 "cc_register" "") (const_int 0)])
7469 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7470 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7474 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7475 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7476 [(set_attr "conds" "use")
7477 (set_attr "length" "4,8,8")]
7480 (define_insn "*ifcompare_shift_move"
7481 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7483 (match_operator 6 "arm_comparison_operator"
7484 [(match_operand:SI 4 "s_register_operand" "r,r")
7485 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7486 (match_operator:SI 7 "shift_operator"
7487 [(match_operand:SI 2 "s_register_operand" "r,r")
7488 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7489 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7490 (clobber (reg:CC CC_REGNUM))]
7493 [(set_attr "conds" "clob")
7494 (set_attr "length" "8,12")]
7497 (define_insn "*if_shift_move"
7498 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7500 (match_operator 5 "arm_comparison_operator"
7501 [(match_operand 6 "cc_register" "") (const_int 0)])
7502 (match_operator:SI 4 "shift_operator"
7503 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7504 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7505 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7509 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7510 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7511 [(set_attr "conds" "use")
7512 (set_attr "shift" "2")
7513 (set_attr "length" "4,8,8")]
7516 (define_insn "*ifcompare_move_shift"
7517 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7519 (match_operator 6 "arm_comparison_operator"
7520 [(match_operand:SI 4 "s_register_operand" "r,r")
7521 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7522 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7523 (match_operator:SI 7 "shift_operator"
7524 [(match_operand:SI 2 "s_register_operand" "r,r")
7525 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7526 (clobber (reg:CC CC_REGNUM))]
7529 [(set_attr "conds" "clob")
7530 (set_attr "length" "8,12")]
7533 (define_insn "*if_move_shift"
7534 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7536 (match_operator 5 "arm_comparison_operator"
7537 [(match_operand 6 "cc_register" "") (const_int 0)])
7538 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7539 (match_operator:SI 4 "shift_operator"
7540 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7541 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7545 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7546 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7547 [(set_attr "conds" "use")
7548 (set_attr "shift" "2")
7549 (set_attr "length" "4,8,8")]
7552 (define_insn "*ifcompare_shift_shift"
7553 [(set (match_operand:SI 0 "s_register_operand" "=r")
7555 (match_operator 7 "arm_comparison_operator"
7556 [(match_operand:SI 5 "s_register_operand" "r")
7557 (match_operand:SI 6 "arm_add_operand" "rIL")])
7558 (match_operator:SI 8 "shift_operator"
7559 [(match_operand:SI 1 "s_register_operand" "r")
7560 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7561 (match_operator:SI 9 "shift_operator"
7562 [(match_operand:SI 3 "s_register_operand" "r")
7563 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7564 (clobber (reg:CC CC_REGNUM))]
7567 [(set_attr "conds" "clob")
7568 (set_attr "length" "12")]
7571 (define_insn "*if_shift_shift"
7572 [(set (match_operand:SI 0 "s_register_operand" "=r")
7574 (match_operator 5 "arm_comparison_operator"
7575 [(match_operand 8 "cc_register" "") (const_int 0)])
7576 (match_operator:SI 6 "shift_operator"
7577 [(match_operand:SI 1 "s_register_operand" "r")
7578 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7579 (match_operator:SI 7 "shift_operator"
7580 [(match_operand:SI 3 "s_register_operand" "r")
7581 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7583 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7584 [(set_attr "conds" "use")
7585 (set_attr "shift" "1")
7586 (set_attr "length" "8")]
7589 (define_insn "*ifcompare_not_arith"
7590 [(set (match_operand:SI 0 "s_register_operand" "=r")
7592 (match_operator 6 "arm_comparison_operator"
7593 [(match_operand:SI 4 "s_register_operand" "r")
7594 (match_operand:SI 5 "arm_add_operand" "rIL")])
7595 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7596 (match_operator:SI 7 "shiftable_operator"
7597 [(match_operand:SI 2 "s_register_operand" "r")
7598 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7599 (clobber (reg:CC CC_REGNUM))]
7602 [(set_attr "conds" "clob")
7603 (set_attr "length" "12")]
7606 (define_insn "*if_not_arith"
7607 [(set (match_operand:SI 0 "s_register_operand" "=r")
7609 (match_operator 5 "arm_comparison_operator"
7610 [(match_operand 4 "cc_register" "") (const_int 0)])
7611 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7612 (match_operator:SI 6 "shiftable_operator"
7613 [(match_operand:SI 2 "s_register_operand" "r")
7614 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7616 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7617 [(set_attr "conds" "use")
7618 (set_attr "length" "8")]
7621 (define_insn "*ifcompare_arith_not"
7622 [(set (match_operand:SI 0 "s_register_operand" "=r")
7624 (match_operator 6 "arm_comparison_operator"
7625 [(match_operand:SI 4 "s_register_operand" "r")
7626 (match_operand:SI 5 "arm_add_operand" "rIL")])
7627 (match_operator:SI 7 "shiftable_operator"
7628 [(match_operand:SI 2 "s_register_operand" "r")
7629 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7630 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7631 (clobber (reg:CC CC_REGNUM))]
7634 [(set_attr "conds" "clob")
7635 (set_attr "length" "12")]
7638 (define_insn "*if_arith_not"
7639 [(set (match_operand:SI 0 "s_register_operand" "=r")
7641 (match_operator 5 "arm_comparison_operator"
7642 [(match_operand 4 "cc_register" "") (const_int 0)])
7643 (match_operator:SI 6 "shiftable_operator"
7644 [(match_operand:SI 2 "s_register_operand" "r")
7645 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7646 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7648 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7649 [(set_attr "conds" "use")
7650 (set_attr "length" "8")]
7653 (define_insn "*ifcompare_neg_move"
7654 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7656 (match_operator 5 "arm_comparison_operator"
7657 [(match_operand:SI 3 "s_register_operand" "r,r")
7658 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7659 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7660 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7661 (clobber (reg:CC CC_REGNUM))]
7664 [(set_attr "conds" "clob")
7665 (set_attr "length" "8,12")]
7668 (define_insn "*if_neg_move"
7669 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7671 (match_operator 4 "arm_comparison_operator"
7672 [(match_operand 3 "cc_register" "") (const_int 0)])
7673 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7674 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7678 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7679 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7680 [(set_attr "conds" "use")
7681 (set_attr "length" "4,8,8")]
7684 (define_insn "*ifcompare_move_neg"
7685 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7687 (match_operator 5 "arm_comparison_operator"
7688 [(match_operand:SI 3 "s_register_operand" "r,r")
7689 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7690 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7691 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7692 (clobber (reg:CC CC_REGNUM))]
7695 [(set_attr "conds" "clob")
7696 (set_attr "length" "8,12")]
7699 (define_insn "*if_move_neg"
7700 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7702 (match_operator 4 "arm_comparison_operator"
7703 [(match_operand 3 "cc_register" "") (const_int 0)])
7704 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7705 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7709 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7710 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7711 [(set_attr "conds" "use")
7712 (set_attr "length" "4,8,8")]
7715 (define_insn "*arith_adjacentmem"
7716 [(set (match_operand:SI 0 "s_register_operand" "=r")
7717 (match_operator:SI 1 "shiftable_operator"
7718 [(match_operand:SI 2 "memory_operand" "m")
7719 (match_operand:SI 3 "memory_operand" "m")]))
7720 (clobber (match_scratch:SI 4 "=r"))]
7721 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7726 int val1 = 0, val2 = 0;
7728 if (REGNO (operands[0]) > REGNO (operands[4]))
7730 ldm[1] = operands[4];
7731 ldm[2] = operands[0];
7735 ldm[1] = operands[0];
7736 ldm[2] = operands[4];
7738 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7739 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7740 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7741 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7742 arith[0] = operands[0];
7743 arith[3] = operands[1];
7757 ldm[0] = ops[0] = operands[4];
7758 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7759 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7760 output_add_immediate (ops);
7762 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7764 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7768 ldm[0] = XEXP (operands[3], 0);
7770 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7772 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7776 ldm[0] = XEXP (operands[2], 0);
7778 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7780 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7782 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7785 [(set_attr "length" "12")
7786 (set_attr "predicable" "yes")
7787 (set_attr "type" "load")]
7790 ;; the arm can support extended pre-inc instructions
7792 ;; In all these cases, we use operands 0 and 1 for the register being
7793 ;; incremented because those are the operands that local-alloc will
7794 ;; tie and these are the pair most likely to be tieable (and the ones
7795 ;; that will benefit the most).
7797 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7798 ;; elimination will cause too many headaches.
7800 (define_insn "*strqi_preinc"
7801 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7802 (match_operand:SI 2 "index_operand" "rJ")))
7803 (match_operand:QI 3 "s_register_operand" "r"))
7804 (set (match_operand:SI 0 "s_register_operand" "=r")
7805 (plus:SI (match_dup 1) (match_dup 2)))]
7807 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7808 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7809 && (GET_CODE (operands[2]) != REG
7810 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7811 "str%?b\\t%3, [%0, %2]!"
7812 [(set_attr "type" "store1")
7813 (set_attr "predicable" "yes")]
7816 (define_insn "*strqi_predec"
7817 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7818 (match_operand:SI 2 "s_register_operand" "r")))
7819 (match_operand:QI 3 "s_register_operand" "r"))
7820 (set (match_operand:SI 0 "s_register_operand" "=r")
7821 (minus:SI (match_dup 1) (match_dup 2)))]
7823 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7824 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7825 && (GET_CODE (operands[2]) != REG
7826 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7827 "str%?b\\t%3, [%0, -%2]!"
7828 [(set_attr "type" "store1")
7829 (set_attr "predicable" "yes")]
7832 (define_insn "*loadqi_preinc"
7833 [(set (match_operand:QI 3 "s_register_operand" "=r")
7834 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7835 (match_operand:SI 2 "index_operand" "rJ"))))
7836 (set (match_operand:SI 0 "s_register_operand" "=r")
7837 (plus:SI (match_dup 1) (match_dup 2)))]
7839 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7840 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7841 && (GET_CODE (operands[2]) != REG
7842 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7843 "ldr%?b\\t%3, [%0, %2]!"
7844 [(set_attr "type" "load")
7845 (set_attr "predicable" "yes")]
7848 (define_insn "*loadqi_predec"
7849 [(set (match_operand:QI 3 "s_register_operand" "=r")
7850 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7851 (match_operand:SI 2 "s_register_operand" "r"))))
7852 (set (match_operand:SI 0 "s_register_operand" "=r")
7853 (minus:SI (match_dup 1) (match_dup 2)))]
7855 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7856 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7857 && (GET_CODE (operands[2]) != REG
7858 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7859 "ldr%?b\\t%3, [%0, -%2]!"
7860 [(set_attr "type" "load")
7861 (set_attr "predicable" "yes")]
7864 (define_insn "*loadqisi_preinc"
7865 [(set (match_operand:SI 3 "s_register_operand" "=r")
7867 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7868 (match_operand:SI 2 "index_operand" "rJ")))))
7869 (set (match_operand:SI 0 "s_register_operand" "=r")
7870 (plus:SI (match_dup 1) (match_dup 2)))]
7872 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7873 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7874 && (GET_CODE (operands[2]) != REG
7875 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7876 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
7877 [(set_attr "type" "load")
7878 (set_attr "predicable" "yes")]
7881 (define_insn "*loadqisi_predec"
7882 [(set (match_operand:SI 3 "s_register_operand" "=r")
7884 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7885 (match_operand:SI 2 "s_register_operand" "r")))))
7886 (set (match_operand:SI 0 "s_register_operand" "=r")
7887 (minus:SI (match_dup 1) (match_dup 2)))]
7889 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7890 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7891 && (GET_CODE (operands[2]) != REG
7892 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7893 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
7894 [(set_attr "type" "load")
7895 (set_attr "predicable" "yes")]
7898 (define_insn "*strsi_preinc"
7899 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7900 (match_operand:SI 2 "index_operand" "rJ")))
7901 (match_operand:SI 3 "s_register_operand" "r"))
7902 (set (match_operand:SI 0 "s_register_operand" "=r")
7903 (plus:SI (match_dup 1) (match_dup 2)))]
7905 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7906 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7907 && (GET_CODE (operands[2]) != REG
7908 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7909 "str%?\\t%3, [%0, %2]!"
7910 [(set_attr "type" "store1")
7911 (set_attr "predicable" "yes")]
7914 (define_insn "*strsi_predec"
7915 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7916 (match_operand:SI 2 "s_register_operand" "r")))
7917 (match_operand:SI 3 "s_register_operand" "r"))
7918 (set (match_operand:SI 0 "s_register_operand" "=r")
7919 (minus:SI (match_dup 1) (match_dup 2)))]
7921 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7922 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7923 && (GET_CODE (operands[2]) != REG
7924 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7925 "str%?\\t%3, [%0, -%2]!"
7926 [(set_attr "type" "store1")
7927 (set_attr "predicable" "yes")]
7930 (define_insn "*loadsi_preinc"
7931 [(set (match_operand:SI 3 "s_register_operand" "=r")
7932 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7933 (match_operand:SI 2 "index_operand" "rJ"))))
7934 (set (match_operand:SI 0 "s_register_operand" "=r")
7935 (plus:SI (match_dup 1) (match_dup 2)))]
7937 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7938 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7939 && (GET_CODE (operands[2]) != REG
7940 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7941 "ldr%?\\t%3, [%0, %2]!"
7942 [(set_attr "type" "load")
7943 (set_attr "predicable" "yes")]
7946 (define_insn "*loadsi_predec"
7947 [(set (match_operand:SI 3 "s_register_operand" "=r")
7948 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7949 (match_operand:SI 2 "s_register_operand" "r"))))
7950 (set (match_operand:SI 0 "s_register_operand" "=r")
7951 (minus:SI (match_dup 1) (match_dup 2)))]
7953 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7954 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7955 && (GET_CODE (operands[2]) != REG
7956 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7957 "ldr%?\\t%3, [%0, -%2]!"
7958 [(set_attr "type" "load")
7959 (set_attr "predicable" "yes")]
7962 (define_insn "*loadhi_preinc"
7963 [(set (match_operand:HI 3 "s_register_operand" "=r")
7964 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7965 (match_operand:SI 2 "index_operand" "rJ"))))
7966 (set (match_operand:SI 0 "s_register_operand" "=r")
7967 (plus:SI (match_dup 1) (match_dup 2)))]
7969 && !BYTES_BIG_ENDIAN
7970 && !TARGET_MMU_TRAPS
7972 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7973 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7974 && (GET_CODE (operands[2]) != REG
7975 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7976 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
7977 [(set_attr "type" "load")
7978 (set_attr "predicable" "yes")]
7981 (define_insn "*loadhi_predec"
7982 [(set (match_operand:HI 3 "s_register_operand" "=r")
7983 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7984 (match_operand:SI 2 "s_register_operand" "r"))))
7985 (set (match_operand:SI 0 "s_register_operand" "=r")
7986 (minus:SI (match_dup 1) (match_dup 2)))]
7988 && !BYTES_BIG_ENDIAN
7989 && !TARGET_MMU_TRAPS
7991 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7992 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7993 && (GET_CODE (operands[2]) != REG
7994 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7995 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
7996 [(set_attr "type" "load")
7997 (set_attr "predicable" "yes")]
8000 (define_insn "*strqi_shiftpreinc"
8001 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8002 [(match_operand:SI 3 "s_register_operand" "r")
8003 (match_operand:SI 4 "const_shift_operand" "n")])
8004 (match_operand:SI 1 "s_register_operand" "0")))
8005 (match_operand:QI 5 "s_register_operand" "r"))
8006 (set (match_operand:SI 0 "s_register_operand" "=r")
8007 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8010 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8011 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8012 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8013 "str%?b\\t%5, [%0, %3%S2]!"
8014 [(set_attr "type" "store1")
8015 (set_attr "predicable" "yes")]
8018 (define_insn "*strqi_shiftpredec"
8019 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8020 (match_operator:SI 2 "shift_operator"
8021 [(match_operand:SI 3 "s_register_operand" "r")
8022 (match_operand:SI 4 "const_shift_operand" "n")])))
8023 (match_operand:QI 5 "s_register_operand" "r"))
8024 (set (match_operand:SI 0 "s_register_operand" "=r")
8025 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8028 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8029 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8030 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8031 "str%?b\\t%5, [%0, -%3%S2]!"
8032 [(set_attr "type" "store1")
8033 (set_attr "predicable" "yes")]
8036 (define_insn "*loadqi_shiftpreinc"
8037 [(set (match_operand:QI 5 "s_register_operand" "=r")
8038 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8039 [(match_operand:SI 3 "s_register_operand" "r")
8040 (match_operand:SI 4 "const_shift_operand" "n")])
8041 (match_operand:SI 1 "s_register_operand" "0"))))
8042 (set (match_operand:SI 0 "s_register_operand" "=r")
8043 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8046 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8047 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8048 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8049 "ldr%?b\\t%5, [%0, %3%S2]!"
8050 [(set_attr "type" "load")
8051 (set_attr "predicable" "yes")]
8054 (define_insn "*loadqi_shiftpredec"
8055 [(set (match_operand:QI 5 "s_register_operand" "=r")
8056 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8057 (match_operator:SI 2 "shift_operator"
8058 [(match_operand:SI 3 "s_register_operand" "r")
8059 (match_operand:SI 4 "const_shift_operand" "n")]))))
8060 (set (match_operand:SI 0 "s_register_operand" "=r")
8061 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8064 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8065 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8066 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8067 "ldr%?b\\t%5, [%0, -%3%S2]!"
8068 [(set_attr "type" "load")
8069 (set_attr "predicable" "yes")]
8072 (define_insn "*strsi_shiftpreinc"
8073 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8074 [(match_operand:SI 3 "s_register_operand" "r")
8075 (match_operand:SI 4 "const_shift_operand" "n")])
8076 (match_operand:SI 1 "s_register_operand" "0")))
8077 (match_operand:SI 5 "s_register_operand" "r"))
8078 (set (match_operand:SI 0 "s_register_operand" "=r")
8079 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8082 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8083 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8084 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8085 "str%?\\t%5, [%0, %3%S2]!"
8086 [(set_attr "type" "store1")
8087 (set_attr "predicable" "yes")]
8090 (define_insn "*strsi_shiftpredec"
8091 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8092 (match_operator:SI 2 "shift_operator"
8093 [(match_operand:SI 3 "s_register_operand" "r")
8094 (match_operand:SI 4 "const_shift_operand" "n")])))
8095 (match_operand:SI 5 "s_register_operand" "r"))
8096 (set (match_operand:SI 0 "s_register_operand" "=r")
8097 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8100 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8101 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8102 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8103 "str%?\\t%5, [%0, -%3%S2]!"
8104 [(set_attr "type" "store1")
8105 (set_attr "predicable" "yes")]
8108 (define_insn "*loadsi_shiftpreinc"
8109 [(set (match_operand:SI 5 "s_register_operand" "=r")
8110 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
8111 [(match_operand:SI 3 "s_register_operand" "r")
8112 (match_operand:SI 4 "const_shift_operand" "n")])
8113 (match_operand:SI 1 "s_register_operand" "0"))))
8114 (set (match_operand:SI 0 "s_register_operand" "=r")
8115 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8118 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8119 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8120 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8121 "ldr%?\\t%5, [%0, %3%S2]!"
8122 [(set_attr "type" "load")
8123 (set_attr "predicable" "yes")]
8126 (define_insn "*loadsi_shiftpredec"
8127 [(set (match_operand:SI 5 "s_register_operand" "=r")
8128 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8129 (match_operator:SI 2 "shift_operator"
8130 [(match_operand:SI 3 "s_register_operand" "r")
8131 (match_operand:SI 4 "const_shift_operand" "n")]))))
8132 (set (match_operand:SI 0 "s_register_operand" "=r")
8133 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8136 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8137 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8138 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8139 "ldr%?\\t%5, [%0, -%3%S2]!"
8140 [(set_attr "type" "load")
8141 (set_attr "predicable" "yes")])
8143 (define_insn "*loadhi_shiftpreinc"
8144 [(set (match_operand:HI 5 "s_register_operand" "=r")
8145 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
8146 [(match_operand:SI 3 "s_register_operand" "r")
8147 (match_operand:SI 4 "const_shift_operand" "n")])
8148 (match_operand:SI 1 "s_register_operand" "0"))))
8149 (set (match_operand:SI 0 "s_register_operand" "=r")
8150 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8153 && !BYTES_BIG_ENDIAN
8154 && !TARGET_MMU_TRAPS
8156 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8157 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8158 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8159 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8160 [(set_attr "type" "load")
8161 (set_attr "predicable" "yes")]
8164 (define_insn "*loadhi_shiftpredec"
8165 [(set (match_operand:HI 5 "s_register_operand" "=r")
8166 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8167 (match_operator:SI 2 "shift_operator"
8168 [(match_operand:SI 3 "s_register_operand" "r")
8169 (match_operand:SI 4 "const_shift_operand" "n")]))))
8170 (set (match_operand:SI 0 "s_register_operand" "=r")
8171 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8174 && !BYTES_BIG_ENDIAN
8175 && !TARGET_MMU_TRAPS
8177 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8178 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8179 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8180 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8181 [(set_attr "type" "load")
8182 (set_attr "predicable" "yes")]
8185 ; It can also support extended post-inc expressions, but combine doesn't
8187 ; It doesn't seem worth adding peepholes for anything but the most common
8188 ; cases since, unlike combine, the increment must immediately follow the load
8189 ; for this pattern to match.
8190 ; We must watch to see that the source/destination register isn't also the
8191 ; same as the base address register, and that if the index is a register,
8192 ; that it is not the same as the base address register. In such cases the
8193 ; instruction that we would generate would have UNPREDICTABLE behavior so
8197 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8198 (match_operand:QI 2 "s_register_operand" "r"))
8200 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8202 && (REGNO (operands[2]) != REGNO (operands[0]))
8203 && (GET_CODE (operands[1]) != REG
8204 || (REGNO (operands[1]) != REGNO (operands[0])))"
8205 "str%?b\\t%2, [%0], %1"
8209 [(set (match_operand:QI 0 "s_register_operand" "=r")
8210 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8212 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8214 && REGNO (operands[0]) != REGNO(operands[1])
8215 && (GET_CODE (operands[2]) != REG
8216 || REGNO(operands[0]) != REGNO (operands[2]))"
8217 "ldr%?b\\t%0, [%1], %2"
8221 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8222 (match_operand:SI 2 "s_register_operand" "r"))
8224 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8226 && (REGNO (operands[2]) != REGNO (operands[0]))
8227 && (GET_CODE (operands[1]) != REG
8228 || (REGNO (operands[1]) != REGNO (operands[0])))"
8229 "str%?\\t%2, [%0], %1"
8233 [(set (match_operand:HI 0 "s_register_operand" "=r")
8234 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8236 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8238 && !BYTES_BIG_ENDIAN
8239 && !TARGET_MMU_TRAPS
8241 && REGNO (operands[0]) != REGNO(operands[1])
8242 && (GET_CODE (operands[2]) != REG
8243 || REGNO(operands[0]) != REGNO (operands[2]))"
8244 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8248 [(set (match_operand:SI 0 "s_register_operand" "=r")
8249 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8251 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8253 && REGNO (operands[0]) != REGNO(operands[1])
8254 && (GET_CODE (operands[2]) != REG
8255 || REGNO(operands[0]) != REGNO (operands[2]))"
8256 "ldr%?\\t%0, [%1], %2"
8260 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8261 (match_operand:SI 1 "index_operand" "rJ")))
8262 (match_operand:QI 2 "s_register_operand" "r"))
8263 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8265 && (REGNO (operands[2]) != REGNO (operands[0]))
8266 && (GET_CODE (operands[1]) != REG
8267 || (REGNO (operands[1]) != REGNO (operands[0])))"
8268 "str%?b\\t%2, [%0, %1]!"
8272 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8273 [(match_operand:SI 0 "s_register_operand" "r")
8274 (match_operand:SI 1 "const_int_operand" "n")])
8275 (match_operand:SI 2 "s_register_operand" "+r")))
8276 (match_operand:QI 3 "s_register_operand" "r"))
8277 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8280 && (REGNO (operands[3]) != REGNO (operands[2]))
8281 && (REGNO (operands[0]) != REGNO (operands[2]))"
8282 "str%?b\\t%3, [%2, %0%S4]!"
8285 ; This pattern is never tried by combine, so do it as a peephole
8288 [(set (match_operand:SI 0 "s_register_operand" "")
8289 (match_operand:SI 1 "s_register_operand" ""))
8290 (set (reg:CC CC_REGNUM)
8291 (compare:CC (match_dup 1) (const_int 0)))]
8294 || (!cirrus_fp_register (operands[0], SImode)
8295 && !cirrus_fp_register (operands[1], SImode)))
8297 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8298 (set (match_dup 0) (match_dup 1))])]
8302 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8303 ; reversed, check that the memory references aren't volatile.
8306 [(set (match_operand:SI 0 "s_register_operand" "=r")
8307 (match_operand:SI 4 "memory_operand" "m"))
8308 (set (match_operand:SI 1 "s_register_operand" "=r")
8309 (match_operand:SI 5 "memory_operand" "m"))
8310 (set (match_operand:SI 2 "s_register_operand" "=r")
8311 (match_operand:SI 6 "memory_operand" "m"))
8312 (set (match_operand:SI 3 "s_register_operand" "=r")
8313 (match_operand:SI 7 "memory_operand" "m"))]
8314 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8316 return emit_ldm_seq (operands, 4);
8321 [(set (match_operand:SI 0 "s_register_operand" "=r")
8322 (match_operand:SI 3 "memory_operand" "m"))
8323 (set (match_operand:SI 1 "s_register_operand" "=r")
8324 (match_operand:SI 4 "memory_operand" "m"))
8325 (set (match_operand:SI 2 "s_register_operand" "=r")
8326 (match_operand:SI 5 "memory_operand" "m"))]
8327 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8329 return emit_ldm_seq (operands, 3);
8334 [(set (match_operand:SI 0 "s_register_operand" "=r")
8335 (match_operand:SI 2 "memory_operand" "m"))
8336 (set (match_operand:SI 1 "s_register_operand" "=r")
8337 (match_operand:SI 3 "memory_operand" "m"))]
8338 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8340 return emit_ldm_seq (operands, 2);
8345 [(set (match_operand:SI 4 "memory_operand" "=m")
8346 (match_operand:SI 0 "s_register_operand" "r"))
8347 (set (match_operand:SI 5 "memory_operand" "=m")
8348 (match_operand:SI 1 "s_register_operand" "r"))
8349 (set (match_operand:SI 6 "memory_operand" "=m")
8350 (match_operand:SI 2 "s_register_operand" "r"))
8351 (set (match_operand:SI 7 "memory_operand" "=m")
8352 (match_operand:SI 3 "s_register_operand" "r"))]
8353 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8355 return emit_stm_seq (operands, 4);
8360 [(set (match_operand:SI 3 "memory_operand" "=m")
8361 (match_operand:SI 0 "s_register_operand" "r"))
8362 (set (match_operand:SI 4 "memory_operand" "=m")
8363 (match_operand:SI 1 "s_register_operand" "r"))
8364 (set (match_operand:SI 5 "memory_operand" "=m")
8365 (match_operand:SI 2 "s_register_operand" "r"))]
8366 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8368 return emit_stm_seq (operands, 3);
8373 [(set (match_operand:SI 2 "memory_operand" "=m")
8374 (match_operand:SI 0 "s_register_operand" "r"))
8375 (set (match_operand:SI 3 "memory_operand" "=m")
8376 (match_operand:SI 1 "s_register_operand" "r"))]
8377 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8379 return emit_stm_seq (operands, 2);
8384 [(set (match_operand:SI 0 "s_register_operand" "")
8385 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8387 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8388 [(match_operand:SI 3 "s_register_operand" "")
8389 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8390 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8392 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8393 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8398 ;; This split can be used because CC_Z mode implies that the following
8399 ;; branch will be an equality, or an unsigned inequality, so the sign
8400 ;; extension is not needed.
8403 [(set (reg:CC_Z CC_REGNUM)
8405 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8407 (match_operand 1 "const_int_operand" "")))
8408 (clobber (match_scratch:SI 2 ""))]
8410 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8411 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8412 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8413 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8415 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8419 (define_expand "prologue"
8420 [(clobber (const_int 0))]
8423 arm_expand_prologue ();
8425 thumb_expand_prologue ();
8430 (define_expand "epilogue"
8431 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8435 thumb_expand_epilogue ();
8436 else if (USE_RETURN_INSN (FALSE))
8438 emit_jump_insn (gen_return ());
8441 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8443 gen_rtx_RETURN (VOIDmode)),
8449 ;; Note - although unspec_volatile's USE all hard registers,
8450 ;; USEs are ignored after relaod has completed. Thus we need
8451 ;; to add an unspec of the link register to ensure that flow
8452 ;; does not think that it is unused by the sibcall branch that
8453 ;; will replace the standard function epilogue.
8454 (define_insn "sibcall_epilogue"
8455 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8456 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8459 if (USE_RETURN_INSN (FALSE))
8460 return output_return_instruction (const_true_rtx, FALSE, FALSE);
8461 return arm_output_epilogue (FALSE);
8463 ;; Length is absolute worst case
8464 [(set_attr "length" "44")
8465 (set_attr "type" "block")
8466 ;; We don't clobber the conditions, but the potential length of this
8467 ;; operation is sufficient to make conditionalizing the sequence
8468 ;; unlikely to be profitable.
8469 (set_attr "conds" "clob")]
8472 (define_insn "*epilogue_insns"
8473 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8477 return arm_output_epilogue (TRUE);
8478 else /* TARGET_THUMB */
8479 return thumb_unexpanded_epilogue ();
8481 ; Length is absolute worst case
8482 [(set_attr "length" "44")
8483 (set_attr "type" "block")
8484 ;; We don't clobber the conditions, but the potential length of this
8485 ;; operation is sufficient to make conditionalizing the sequence
8486 ;; unlikely to be profitable.
8487 (set_attr "conds" "clob")]
8490 (define_expand "eh_epilogue"
8491 [(use (match_operand:SI 0 "register_operand" ""))
8492 (use (match_operand:SI 1 "register_operand" ""))
8493 (use (match_operand:SI 2 "register_operand" ""))]
8497 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8498 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8500 rtx ra = gen_rtx_REG (Pmode, 2);
8502 emit_move_insn (ra, operands[2]);
8505 /* This is a hack -- we may have crystalized the function type too
8507 cfun->machine->func_type = 0;
8511 ;; This split is only used during output to reduce the number of patterns
8512 ;; that need assembler instructions adding to them. We allowed the setting
8513 ;; of the conditions to be implicit during rtl generation so that
8514 ;; the conditional compare patterns would work. However this conflicts to
8515 ;; some extent with the conditional data operations, so we have to split them
8519 [(set (match_operand:SI 0 "s_register_operand" "")
8520 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8521 [(match_operand 2 "" "") (match_operand 3 "" "")])
8523 (match_operand 4 "" "")))
8524 (clobber (reg:CC CC_REGNUM))]
8525 ;; Note we have to suppress this split for the iwmmxt because it
8526 ;; creates a conditional movsi and the iwmmxt_movsi_insn pattern
8527 ;; is not predicable. This sucks.
8528 "TARGET_ARM && reload_completed && ! TARGET_IWMMXT"
8529 [(set (match_dup 5) (match_dup 6))
8530 (cond_exec (match_dup 7)
8531 (set (match_dup 0) (match_dup 4)))]
8534 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8535 operands[2], operands[3]);
8536 enum rtx_code rc = GET_CODE (operands[1]);
8538 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8539 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8540 if (mode == CCFPmode || mode == CCFPEmode)
8541 rc = reverse_condition_maybe_unordered (rc);
8543 rc = reverse_condition (rc);
8545 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8550 [(set (match_operand:SI 0 "s_register_operand" "")
8551 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8552 [(match_operand 2 "" "") (match_operand 3 "" "")])
8553 (match_operand 4 "" "")
8555 (clobber (reg:CC CC_REGNUM))]
8556 ;; Note we have to suppress this split for the iwmmxt because it
8557 ;; creates a conditional movsi and the iwmmxt_movsi_insn pattern
8558 ;; is not predicable. This sucks.
8559 "TARGET_ARM && reload_completed && ! TARGET_IWMMXT"
8560 [(set (match_dup 5) (match_dup 6))
8561 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8562 (set (match_dup 0) (match_dup 4)))]
8565 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8566 operands[2], operands[3]);
8568 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8569 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8574 [(set (match_operand:SI 0 "s_register_operand" "")
8575 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8576 [(match_operand 2 "" "") (match_operand 3 "" "")])
8577 (match_operand 4 "" "")
8578 (match_operand 5 "" "")))
8579 (clobber (reg:CC CC_REGNUM))]
8580 ;; Note we have to suppress this split for the iwmmxt because it
8581 ;; creates a conditional movsi and the iwmmxt_movsi_insn pattern
8582 ;; is not predicable. This sucks.
8583 "TARGET_ARM && reload_completed && ! TARGET_IWMMXT"
8584 [(set (match_dup 6) (match_dup 7))
8585 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8586 (set (match_dup 0) (match_dup 4)))
8587 (cond_exec (match_dup 8)
8588 (set (match_dup 0) (match_dup 5)))]
8591 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8592 operands[2], operands[3]);
8593 enum rtx_code rc = GET_CODE (operands[1]);
8595 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8596 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8597 if (mode == CCFPmode || mode == CCFPEmode)
8598 rc = reverse_condition_maybe_unordered (rc);
8600 rc = reverse_condition (rc);
8602 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8607 [(set (match_operand:SI 0 "s_register_operand" "")
8608 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8609 [(match_operand:SI 2 "s_register_operand" "")
8610 (match_operand:SI 3 "arm_add_operand" "")])
8611 (match_operand:SI 4 "arm_rhs_operand" "")
8613 (match_operand:SI 5 "s_register_operand" ""))))
8614 (clobber (reg:CC CC_REGNUM))]
8615 ;; Note we have to suppress this split for the iwmmxt because it
8616 ;; creates a conditional movsi and the iwmmxt_movsi_insn pattern
8617 ;; is not predicable. This sucks.
8618 "TARGET_ARM && reload_completed && ! TARGET_IWMMXT"
8619 [(set (match_dup 6) (match_dup 7))
8620 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8621 (set (match_dup 0) (match_dup 4)))
8622 (cond_exec (match_dup 8)
8623 (set (match_dup 0) (not:SI (match_dup 5))))]
8626 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8627 operands[2], operands[3]);
8628 enum rtx_code rc = GET_CODE (operands[1]);
8630 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8631 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8632 if (mode == CCFPmode || mode == CCFPEmode)
8633 rc = reverse_condition_maybe_unordered (rc);
8635 rc = reverse_condition (rc);
8637 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8641 (define_insn "*cond_move_not"
8642 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8643 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8644 [(match_operand 3 "cc_register" "") (const_int 0)])
8645 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8647 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8651 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8652 [(set_attr "conds" "use")
8653 (set_attr "length" "4,8")]
8656 ;; The next two patterns occur when an AND operation is followed by a
8657 ;; scc insn sequence
8659 (define_insn "*sign_extract_onebit"
8660 [(set (match_operand:SI 0 "s_register_operand" "=r")
8661 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8663 (match_operand:SI 2 "const_int_operand" "n")))
8664 (clobber (reg:CC CC_REGNUM))]
8667 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8668 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8669 return \"mvnne\\t%0, #0\";
8671 [(set_attr "conds" "clob")
8672 (set_attr "length" "8")]
8675 (define_insn "*not_signextract_onebit"
8676 [(set (match_operand:SI 0 "s_register_operand" "=r")
8678 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8680 (match_operand:SI 2 "const_int_operand" "n"))))
8681 (clobber (reg:CC CC_REGNUM))]
8684 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8685 output_asm_insn (\"tst\\t%1, %2\", operands);
8686 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8687 return \"movne\\t%0, #0\";
8689 [(set_attr "conds" "clob")
8690 (set_attr "length" "12")]
8693 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8694 ;; expressions. For simplicity, the first register is also in the unspec
8696 (define_insn "*push_multi"
8697 [(match_parallel 2 "multi_register_push"
8698 [(set (match_operand:BLK 0 "memory_operand" "=m")
8699 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8700 UNSPEC_PUSH_MULT))])]
8704 int num_saves = XVECLEN (operands[2], 0);
8706 /* For the StrongARM at least it is faster to
8707 use STR to store only a single register. */
8709 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8715 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8717 for (i = 1; i < num_saves; i++)
8719 strcat (pattern, \", %|\");
8721 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8724 strcat (pattern, \"}\");
8725 output_asm_insn (pattern, operands);
8730 [(set_attr "type" "store4")]
8733 (define_insn "stack_tie"
8734 [(set (mem:BLK (scratch))
8735 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8736 (match_operand:SI 1 "s_register_operand" "r")]
8740 [(set_attr "length" "0")]
8743 ;; Similarly for the floating point registers
8744 (define_insn "*push_fp_multi"
8745 [(match_parallel 2 "multi_register_push"
8746 [(set (match_operand:BLK 0 "memory_operand" "=m")
8747 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8748 UNSPEC_PUSH_MULT))])]
8754 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8755 output_asm_insn (pattern, operands);
8758 [(set_attr "type" "f_store")]
8761 ;; Special patterns for dealing with the constant pool
8763 (define_insn "align_4"
8764 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8767 assemble_align (32);
8772 (define_insn "align_8"
8773 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
8774 "TARGET_REALLY_IWMMXT"
8776 assemble_align (64);
8781 (define_insn "consttable_end"
8782 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8785 making_const_table = FALSE;
8790 (define_insn "consttable_1"
8791 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8794 making_const_table = TRUE;
8795 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8799 [(set_attr "length" "4")]
8802 (define_insn "consttable_2"
8803 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8806 making_const_table = TRUE;
8807 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8811 [(set_attr "length" "4")]
8814 (define_insn "consttable_4"
8815 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8819 making_const_table = TRUE;
8820 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8825 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8826 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8830 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8835 [(set_attr "length" "4")]
8838 (define_insn "consttable_8"
8839 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8843 making_const_table = TRUE;
8844 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8849 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8850 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8854 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8859 [(set_attr "length" "8")]
8862 ;; Miscellaneous Thumb patterns
8864 (define_expand "tablejump"
8865 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
8866 (use (label_ref (match_operand 1 "" "")))])]
8871 /* Hopefully, CSE will eliminate this copy. */
8872 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8873 rtx reg2 = gen_reg_rtx (SImode);
8875 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8881 (define_insn "*thumb_tablejump"
8882 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8883 (use (label_ref (match_operand 1 "" "")))]
8886 [(set_attr "length" "2")]
8891 (define_insn "clzsi2"
8892 [(set (match_operand:SI 0 "s_register_operand" "=r")
8893 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8894 "TARGET_ARM && arm_arch5"
8896 [(set_attr "predicable" "yes")])
8898 (define_expand "ffssi2"
8899 [(set (match_operand:SI 0 "s_register_operand" "")
8900 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
8901 "TARGET_ARM && arm_arch5"
8906 t1 = gen_reg_rtx (SImode);
8907 t2 = gen_reg_rtx (SImode);
8908 t3 = gen_reg_rtx (SImode);
8910 emit_insn (gen_negsi2 (t1, operands[1]));
8911 emit_insn (gen_andsi3 (t2, operands[1], t1));
8912 emit_insn (gen_clzsi2 (t3, t2));
8913 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
8918 (define_expand "ctzsi2"
8919 [(set (match_operand:SI 0 "s_register_operand" "")
8920 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
8921 "TARGET_ARM && arm_arch5"
8926 t1 = gen_reg_rtx (SImode);
8927 t2 = gen_reg_rtx (SImode);
8928 t3 = gen_reg_rtx (SImode);
8930 emit_insn (gen_negsi2 (t1, operands[1]));
8931 emit_insn (gen_andsi3 (t2, operands[1], t1));
8932 emit_insn (gen_clzsi2 (t3, t2));
8933 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
8938 ;; V5E instructions.
8940 (define_insn "prefetch"
8941 [(prefetch (match_operand:SI 0 "address_operand" "p")
8942 (match_operand:SI 1 "" "")
8943 (match_operand:SI 2 "" ""))]
8944 "TARGET_ARM && arm_arch5e"
8947 ;; General predication pattern
8950 [(match_operator 0 "arm_comparison_operator"
8951 [(match_operand 1 "cc_register" "")
8957 (define_insn "prologue_use"
8958 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
8960 "%@ %0 needed for prologue"
8963 ;; Load the FPA co-processor patterns
8965 ;; Load the Maverick co-processor patterns
8966 (include "cirrus.md")
8967 ;; Load the Intel Wireless Multimedia Extension patterns
8968 (include "iwmmxt.md")