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 ;; The next four insns work because they compare the result with one of
671 ;; the operands, and we know that the use of the condition code is
672 ;; either GEU or LTU, so we can use the carry flag from the addition
673 ;; instead of doing the compare a second time.
674 (define_insn "*addsi3_compare_op1"
675 [(set (reg:CC_C CC_REGNUM)
677 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
678 (match_operand:SI 2 "arm_add_operand" "rI,L"))
680 (set (match_operand:SI 0 "s_register_operand" "=r,r")
681 (plus:SI (match_dup 1) (match_dup 2)))]
685 sub%?s\\t%0, %1, #%n2"
686 [(set_attr "conds" "set")]
689 (define_insn "*addsi3_compare_op2"
690 [(set (reg:CC_C CC_REGNUM)
692 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
693 (match_operand:SI 2 "arm_add_operand" "rI,L"))
695 (set (match_operand:SI 0 "s_register_operand" "=r,r")
696 (plus:SI (match_dup 1) (match_dup 2)))]
700 sub%?s\\t%0, %1, #%n2"
701 [(set_attr "conds" "set")]
704 (define_insn "*compare_addsi2_op0"
705 [(set (reg:CC_C CC_REGNUM)
707 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
708 (match_operand:SI 1 "arm_add_operand" "rI,L"))
714 [(set_attr "conds" "set")]
717 (define_insn "*compare_addsi2_op1"
718 [(set (reg:CC_C CC_REGNUM)
720 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
721 (match_operand:SI 1 "arm_add_operand" "rI,L"))
727 [(set_attr "conds" "set")]
730 (define_insn "*addsi3_carryin"
731 [(set (match_operand:SI 0 "s_register_operand" "=r")
732 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
733 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
734 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
737 [(set_attr "conds" "use")]
740 (define_insn "*addsi3_carryin_shift"
741 [(set (match_operand:SI 0 "s_register_operand" "")
742 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
744 (match_operator:SI 2 "shift_operator"
745 [(match_operand:SI 3 "s_register_operand" "")
746 (match_operand:SI 4 "reg_or_int_operand" "")])
747 (match_operand:SI 1 "s_register_operand" ""))))]
749 "adc%?\\t%0, %1, %3%S2"
750 [(set_attr "conds" "use")]
753 (define_insn "*addsi3_carryin_alt1"
754 [(set (match_operand:SI 0 "s_register_operand" "=r")
755 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
756 (match_operand:SI 2 "arm_rhs_operand" "rI"))
757 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
760 [(set_attr "conds" "use")]
763 (define_insn "*addsi3_carryin_alt2"
764 [(set (match_operand:SI 0 "s_register_operand" "=r")
765 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
766 (match_operand:SI 1 "s_register_operand" "r"))
767 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
770 [(set_attr "conds" "use")]
773 (define_insn "*addsi3_carryin_alt3"
774 [(set (match_operand:SI 0 "s_register_operand" "=r")
775 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
776 (match_operand:SI 2 "arm_rhs_operand" "rI"))
777 (match_operand:SI 1 "s_register_operand" "r")))]
780 [(set_attr "conds" "use")]
783 (define_insn "incscc"
784 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
785 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
786 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
787 (match_operand:SI 1 "s_register_operand" "0,?r")))]
791 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
792 [(set_attr "conds" "use")
793 (set_attr "length" "4,8")]
796 (define_expand "addsf3"
797 [(set (match_operand:SF 0 "s_register_operand" "")
798 (plus:SF (match_operand:SF 1 "s_register_operand" "")
799 (match_operand:SF 2 "fpa_add_operand" "")))]
800 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
803 && !cirrus_fp_register (operands[2], SFmode))
804 operands[2] = force_reg (SFmode, operands[2]);
807 (define_expand "adddf3"
808 [(set (match_operand:DF 0 "s_register_operand" "")
809 (plus:DF (match_operand:DF 1 "s_register_operand" "")
810 (match_operand:DF 2 "fpa_add_operand" "")))]
811 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
814 && !cirrus_fp_register (operands[2], DFmode))
815 operands[2] = force_reg (DFmode, operands[2]);
818 (define_expand "subdi3"
820 [(set (match_operand:DI 0 "s_register_operand" "")
821 (minus:DI (match_operand:DI 1 "s_register_operand" "")
822 (match_operand:DI 2 "s_register_operand" "")))
823 (clobber (reg:CC CC_REGNUM))])]
828 && cirrus_fp_register (operands[0], DImode)
829 && cirrus_fp_register (operands[1], DImode))
831 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
837 if (GET_CODE (operands[1]) != REG)
838 operands[1] = force_reg (SImode, operands[1]);
839 if (GET_CODE (operands[2]) != REG)
840 operands[2] = force_reg (SImode, operands[2]);
845 (define_insn "*arm_subdi3"
846 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
847 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
848 (match_operand:DI 2 "s_register_operand" "r,0,0")))
849 (clobber (reg:CC CC_REGNUM))]
851 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
852 [(set_attr "conds" "clob")
853 (set_attr "length" "8")]
856 (define_insn "*thumb_subdi3"
857 [(set (match_operand:DI 0 "register_operand" "=l")
858 (minus:DI (match_operand:DI 1 "register_operand" "0")
859 (match_operand:DI 2 "register_operand" "l")))
860 (clobber (reg:CC CC_REGNUM))]
862 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
863 [(set_attr "length" "4")]
866 (define_insn "*subdi_di_zesidi"
867 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
868 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
870 (match_operand:SI 2 "s_register_operand" "r,r"))))
871 (clobber (reg:CC CC_REGNUM))]
873 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
874 [(set_attr "conds" "clob")
875 (set_attr "length" "8")]
878 (define_insn "*subdi_di_sesidi"
879 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
880 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
882 (match_operand:SI 2 "s_register_operand" "r,r"))))
883 (clobber (reg:CC CC_REGNUM))]
885 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
886 [(set_attr "conds" "clob")
887 (set_attr "length" "8")]
890 (define_insn "*subdi_zesidi_di"
891 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
892 (minus:DI (zero_extend:DI
893 (match_operand:SI 2 "s_register_operand" "r,r"))
894 (match_operand:DI 1 "s_register_operand" "?r,0")))
895 (clobber (reg:CC CC_REGNUM))]
897 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
898 [(set_attr "conds" "clob")
899 (set_attr "length" "8")]
902 (define_insn "*subdi_sesidi_di"
903 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
904 (minus:DI (sign_extend:DI
905 (match_operand:SI 2 "s_register_operand" "r,r"))
906 (match_operand:DI 1 "s_register_operand" "?r,0")))
907 (clobber (reg:CC CC_REGNUM))]
909 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
910 [(set_attr "conds" "clob")
911 (set_attr "length" "8")]
914 (define_insn "*subdi_zesidi_zesidi"
915 [(set (match_operand:DI 0 "s_register_operand" "=r")
916 (minus:DI (zero_extend:DI
917 (match_operand:SI 1 "s_register_operand" "r"))
919 (match_operand:SI 2 "s_register_operand" "r"))))
920 (clobber (reg:CC CC_REGNUM))]
922 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
923 [(set_attr "conds" "clob")
924 (set_attr "length" "8")]
927 (define_expand "subsi3"
928 [(set (match_operand:SI 0 "s_register_operand" "")
929 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
930 (match_operand:SI 2 "s_register_operand" "")))]
933 if (GET_CODE (operands[1]) == CONST_INT)
937 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
940 : preserve_subexpressions_p ()));
943 else /* TARGET_THUMB */
944 operands[1] = force_reg (SImode, operands[1]);
949 (define_insn "*thumb_subsi3_insn"
950 [(set (match_operand:SI 0 "register_operand" "=l")
951 (minus:SI (match_operand:SI 1 "register_operand" "l")
952 (match_operand:SI 2 "register_operand" "l")))]
955 [(set_attr "length" "2")]
958 (define_insn_and_split "*arm_subsi3_insn"
959 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
960 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
961 (match_operand:SI 2 "s_register_operand" "r,r")))]
967 && GET_CODE (operands[1]) == CONST_INT
968 && !const_ok_for_arm (INTVAL (operands[1]))"
969 [(clobber (const_int 0))]
971 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
975 [(set_attr "length" "4,16")
976 (set_attr "predicable" "yes")]
980 [(match_scratch:SI 3 "r")
981 (set (match_operand:SI 0 "s_register_operand" "")
982 (minus:SI (match_operand:SI 1 "const_int_operand" "")
983 (match_operand:SI 2 "s_register_operand" "")))]
985 && !const_ok_for_arm (INTVAL (operands[1]))
986 && const_ok_for_arm (~INTVAL (operands[1]))"
987 [(set (match_dup 3) (match_dup 1))
988 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
992 (define_insn "*subsi3_compare0"
993 [(set (reg:CC_NOOV CC_REGNUM)
995 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
996 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
998 (set (match_operand:SI 0 "s_register_operand" "=r,r")
999 (minus:SI (match_dup 1) (match_dup 2)))]
1003 rsb%?s\\t%0, %2, %1"
1004 [(set_attr "conds" "set")]
1007 (define_insn "decscc"
1008 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1009 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1010 (match_operator:SI 2 "arm_comparison_operator"
1011 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1015 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1016 [(set_attr "conds" "use")
1017 (set_attr "length" "*,8")]
1020 (define_expand "subsf3"
1021 [(set (match_operand:SF 0 "s_register_operand" "")
1022 (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1023 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1024 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1028 if (!cirrus_fp_register (operands[1], SFmode))
1029 operands[1] = force_reg (SFmode, operands[1]);
1030 if (!cirrus_fp_register (operands[2], SFmode))
1031 operands[2] = force_reg (SFmode, operands[2]);
1035 (define_expand "subdf3"
1036 [(set (match_operand:DF 0 "s_register_operand" "")
1037 (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1038 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1039 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1043 if (!cirrus_fp_register (operands[1], DFmode))
1044 operands[1] = force_reg (DFmode, operands[1]);
1045 if (!cirrus_fp_register (operands[2], DFmode))
1046 operands[2] = force_reg (DFmode, operands[2]);
1051 ;; Multiplication insns
1053 (define_expand "mulsi3"
1054 [(set (match_operand:SI 0 "s_register_operand" "")
1055 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1056 (match_operand:SI 1 "s_register_operand" "")))]
1061 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1062 (define_insn "*arm_mulsi3"
1063 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1064 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1065 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1067 "mul%?\\t%0, %2, %1"
1068 [(set_attr "type" "mult")
1069 (set_attr "predicable" "yes")]
1072 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1073 ; 1 and 2; are the same, because reload will make operand 0 match
1074 ; operand 1 without realizing that this conflicts with operand 2. We fix
1075 ; this by adding another alternative to match this case, and then `reload'
1076 ; it ourselves. This alternative must come first.
1077 (define_insn "*thumb_mulsi3"
1078 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1079 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1080 (match_operand:SI 2 "register_operand" "l,l,l")))]
1083 if (which_alternative < 2)
1084 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1086 return \"mul\\t%0, %0, %2\";
1088 [(set_attr "length" "4,4,2")
1089 (set_attr "type" "mult")]
1092 (define_insn "*mulsi3_compare0"
1093 [(set (reg:CC_NOOV CC_REGNUM)
1094 (compare:CC_NOOV (mult:SI
1095 (match_operand:SI 2 "s_register_operand" "r,r")
1096 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1098 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1099 (mult:SI (match_dup 2) (match_dup 1)))]
1100 "TARGET_ARM && !arm_arch_xscale"
1101 "mul%?s\\t%0, %2, %1"
1102 [(set_attr "conds" "set")
1103 (set_attr "type" "mult")]
1106 (define_insn "*mulsi_compare0_scratch"
1107 [(set (reg:CC_NOOV CC_REGNUM)
1108 (compare:CC_NOOV (mult:SI
1109 (match_operand:SI 2 "s_register_operand" "r,r")
1110 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1112 (clobber (match_scratch:SI 0 "=&r,&r"))]
1113 "TARGET_ARM && !arm_arch_xscale"
1114 "mul%?s\\t%0, %2, %1"
1115 [(set_attr "conds" "set")
1116 (set_attr "type" "mult")]
1119 ;; Unnamed templates to match MLA instruction.
1121 (define_insn "*mulsi3addsi"
1122 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1124 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1125 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1126 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1128 "mla%?\\t%0, %2, %1, %3"
1129 [(set_attr "type" "mult")
1130 (set_attr "predicable" "yes")]
1133 (define_insn "*mulsi3addsi_compare0"
1134 [(set (reg:CC_NOOV CC_REGNUM)
1137 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1138 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1139 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1141 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1142 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1144 "TARGET_ARM && !arm_arch_xscale"
1145 "mla%?s\\t%0, %2, %1, %3"
1146 [(set_attr "conds" "set")
1147 (set_attr "type" "mult")]
1150 (define_insn "*mulsi3addsi_compare0_scratch"
1151 [(set (reg:CC_NOOV CC_REGNUM)
1154 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1155 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1156 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1158 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1159 "TARGET_ARM && !arm_arch_xscale"
1160 "mla%?s\\t%0, %2, %1, %3"
1161 [(set_attr "conds" "set")
1162 (set_attr "type" "mult")]
1165 ;; Unnamed template to match long long multiply-accumlate (smlal)
1167 (define_insn "*mulsidi3adddi"
1168 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1171 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1172 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1173 (match_operand:DI 1 "s_register_operand" "0")))]
1174 "TARGET_ARM && arm_fast_multiply"
1175 "smlal%?\\t%Q0, %R0, %3, %2"
1176 [(set_attr "type" "mult")
1177 (set_attr "predicable" "yes")]
1180 (define_insn "mulsidi3"
1181 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1183 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1184 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1185 "TARGET_ARM && arm_fast_multiply"
1186 "smull%?\\t%Q0, %R0, %1, %2"
1187 [(set_attr "type" "mult")
1188 (set_attr "predicable" "yes")]
1191 (define_insn "umulsidi3"
1192 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1194 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1195 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1196 "TARGET_ARM && arm_fast_multiply"
1197 "umull%?\\t%Q0, %R0, %1, %2"
1198 [(set_attr "type" "mult")
1199 (set_attr "predicable" "yes")]
1202 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1204 (define_insn "*umulsidi3adddi"
1205 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1208 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1209 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1210 (match_operand:DI 1 "s_register_operand" "0")))]
1211 "TARGET_ARM && arm_fast_multiply"
1212 "umlal%?\\t%Q0, %R0, %3, %2"
1213 [(set_attr "type" "mult")
1214 (set_attr "predicable" "yes")]
1217 (define_insn "smulsi3_highpart"
1218 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1222 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1223 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1225 (clobber (match_scratch:SI 3 "=&r,&r"))]
1226 "TARGET_ARM && arm_fast_multiply"
1227 "smull%?\\t%3, %0, %2, %1"
1228 [(set_attr "type" "mult")
1229 (set_attr "predicable" "yes")]
1232 (define_insn "umulsi3_highpart"
1233 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1237 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1238 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1240 (clobber (match_scratch:SI 3 "=&r,&r"))]
1241 "TARGET_ARM && arm_fast_multiply"
1242 "umull%?\\t%3, %0, %2, %1"
1243 [(set_attr "type" "mult")
1244 (set_attr "predicable" "yes")]
1247 (define_insn "mulhisi3"
1248 [(set (match_operand:SI 0 "s_register_operand" "=r")
1249 (mult:SI (sign_extend:SI
1250 (match_operand:HI 1 "s_register_operand" "%r"))
1252 (match_operand:HI 2 "s_register_operand" "r"))))]
1253 "TARGET_ARM && arm_arch5e"
1254 "smulbb%?\\t%0, %1, %2"
1255 [(set_attr "type" "mult")
1256 (set_attr "predicable" "yes")]
1259 (define_insn "*mulhisi3tb"
1260 [(set (match_operand:SI 0 "s_register_operand" "=r")
1261 (mult:SI (ashiftrt:SI
1262 (match_operand:SI 1 "s_register_operand" "r")
1265 (match_operand:HI 2 "s_register_operand" "r"))))]
1266 "TARGET_ARM && arm_arch5e"
1267 "smultb%?\\t%0, %1, %2"
1268 [(set_attr "type" "mult")
1269 (set_attr "predicable" "yes")]
1272 (define_insn "*mulhisi3bt"
1273 [(set (match_operand:SI 0 "s_register_operand" "=r")
1274 (mult:SI (sign_extend:SI
1275 (match_operand:HI 1 "s_register_operand" "r"))
1277 (match_operand:SI 2 "s_register_operand" "r")
1279 "TARGET_ARM && arm_arch5e"
1280 "smulbt%?\\t%0, %1, %2"
1281 [(set_attr "type" "mult")
1282 (set_attr "predicable" "yes")]
1285 (define_insn "*mulhisi3tt"
1286 [(set (match_operand:SI 0 "s_register_operand" "=r")
1287 (mult:SI (ashiftrt:SI
1288 (match_operand:SI 1 "s_register_operand" "r")
1291 (match_operand:SI 2 "s_register_operand" "r")
1293 "TARGET_ARM && arm_arch5e"
1294 "smultt%?\\t%0, %1, %2"
1295 [(set_attr "type" "mult")
1296 (set_attr "predicable" "yes")]
1299 (define_insn "*mulhisi3addsi"
1300 [(set (match_operand:SI 0 "s_register_operand" "=r")
1301 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1302 (mult:SI (sign_extend:SI
1303 (match_operand:HI 2 "s_register_operand" "%r"))
1305 (match_operand:HI 3 "s_register_operand" "r")))))]
1306 "TARGET_ARM && arm_arch5e"
1307 "smlabb%?\\t%0, %2, %3, %1"
1308 [(set_attr "type" "mult")
1309 (set_attr "predicable" "yes")]
1312 (define_insn "*mulhidi3adddi"
1313 [(set (match_operand:DI 0 "s_register_operand" "=r")
1315 (match_operand:DI 1 "s_register_operand" "0")
1316 (mult:DI (sign_extend:DI
1317 (match_operand:HI 2 "s_register_operand" "%r"))
1319 (match_operand:HI 3 "s_register_operand" "r")))))]
1320 "TARGET_ARM && arm_arch5e"
1321 "smlalbb%?\\t%Q0, %R0, %2, %3"
1322 [(set_attr "type" "mult")
1323 (set_attr "predicable" "yes")])
1325 (define_expand "mulsf3"
1326 [(set (match_operand:SF 0 "s_register_operand" "")
1327 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1328 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1329 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1332 && !cirrus_fp_register (operands[2], SFmode))
1333 operands[2] = force_reg (SFmode, operands[2]);
1336 (define_expand "muldf3"
1337 [(set (match_operand:DF 0 "s_register_operand" "")
1338 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1339 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1340 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1343 && !cirrus_fp_register (operands[2], DFmode))
1344 operands[2] = force_reg (DFmode, operands[2]);
1349 (define_expand "divsf3"
1350 [(set (match_operand:SF 0 "s_register_operand" "")
1351 (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1352 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1353 "TARGET_ARM && TARGET_HARD_FLOAT"
1356 (define_expand "divdf3"
1357 [(set (match_operand:DF 0 "s_register_operand" "")
1358 (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1359 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1360 "TARGET_ARM && TARGET_HARD_FLOAT"
1365 (define_expand "modsf3"
1366 [(set (match_operand:SF 0 "s_register_operand" "")
1367 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1368 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1369 "TARGET_ARM && TARGET_HARD_FLOAT"
1372 (define_expand "moddf3"
1373 [(set (match_operand:DF 0 "s_register_operand" "")
1374 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1375 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1376 "TARGET_ARM && TARGET_HARD_FLOAT"
1379 ;; Boolean and,ior,xor insns
1381 ;; Split up double word logical operations
1383 ;; Split up simple DImode logical operations. Simply perform the logical
1384 ;; operation on the upper and lower halves of the registers.
1386 [(set (match_operand:DI 0 "s_register_operand" "")
1387 (match_operator:DI 6 "logical_binary_operator"
1388 [(match_operand:DI 1 "s_register_operand" "")
1389 (match_operand:DI 2 "s_register_operand" "")]))]
1390 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1391 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1392 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1395 operands[3] = gen_highpart (SImode, operands[0]);
1396 operands[0] = gen_lowpart (SImode, operands[0]);
1397 operands[4] = gen_highpart (SImode, operands[1]);
1398 operands[1] = gen_lowpart (SImode, operands[1]);
1399 operands[5] = gen_highpart (SImode, operands[2]);
1400 operands[2] = gen_lowpart (SImode, operands[2]);
1405 [(set (match_operand:DI 0 "s_register_operand" "")
1406 (match_operator:DI 6 "logical_binary_operator"
1407 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1408 (match_operand:DI 1 "s_register_operand" "")]))]
1409 "TARGET_ARM && reload_completed"
1410 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1411 (set (match_dup 3) (match_op_dup:SI 6
1412 [(ashiftrt:SI (match_dup 2) (const_int 31))
1416 operands[3] = gen_highpart (SImode, operands[0]);
1417 operands[0] = gen_lowpart (SImode, operands[0]);
1418 operands[4] = gen_highpart (SImode, operands[1]);
1419 operands[1] = gen_lowpart (SImode, operands[1]);
1420 operands[5] = gen_highpart (SImode, operands[2]);
1421 operands[2] = gen_lowpart (SImode, operands[2]);
1425 ;; The zero extend of operand 2 means we can just copy the high part of
1426 ;; operand1 into operand0.
1428 [(set (match_operand:DI 0 "s_register_operand" "")
1430 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1431 (match_operand:DI 1 "s_register_operand" "")))]
1432 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1433 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1434 (set (match_dup 3) (match_dup 4))]
1437 operands[4] = gen_highpart (SImode, operands[1]);
1438 operands[3] = gen_highpart (SImode, operands[0]);
1439 operands[0] = gen_lowpart (SImode, operands[0]);
1440 operands[1] = gen_lowpart (SImode, operands[1]);
1444 ;; The zero extend of operand 2 means we can just copy the high part of
1445 ;; operand1 into operand0.
1447 [(set (match_operand:DI 0 "s_register_operand" "")
1449 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1450 (match_operand:DI 1 "s_register_operand" "")))]
1451 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1452 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1453 (set (match_dup 3) (match_dup 4))]
1456 operands[4] = gen_highpart (SImode, operands[1]);
1457 operands[3] = gen_highpart (SImode, operands[0]);
1458 operands[0] = gen_lowpart (SImode, operands[0]);
1459 operands[1] = gen_lowpart (SImode, operands[1]);
1463 (define_insn "anddi3"
1464 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1465 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1466 (match_operand:DI 2 "s_register_operand" "r,r")))]
1467 "TARGET_ARM && ! TARGET_IWMMXT"
1469 [(set_attr "length" "8")]
1472 (define_insn_and_split "*anddi_zesidi_di"
1473 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1474 (and:DI (zero_extend:DI
1475 (match_operand:SI 2 "s_register_operand" "r,r"))
1476 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1479 "TARGET_ARM && reload_completed"
1480 ; The zero extend of operand 2 clears the high word of the output
1482 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1483 (set (match_dup 3) (const_int 0))]
1486 operands[3] = gen_highpart (SImode, operands[0]);
1487 operands[0] = gen_lowpart (SImode, operands[0]);
1488 operands[1] = gen_lowpart (SImode, operands[1]);
1490 [(set_attr "length" "8")]
1493 (define_insn "*anddi_sesdi_di"
1494 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1495 (and:DI (sign_extend:DI
1496 (match_operand:SI 2 "s_register_operand" "r,r"))
1497 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1500 [(set_attr "length" "8")]
1503 (define_expand "andsi3"
1504 [(set (match_operand:SI 0 "s_register_operand" "")
1505 (and:SI (match_operand:SI 1 "s_register_operand" "")
1506 (match_operand:SI 2 "reg_or_int_operand" "")))]
1511 if (GET_CODE (operands[2]) == CONST_INT)
1513 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1516 ? 0 : preserve_subexpressions_p ()));
1520 else /* TARGET_THUMB */
1522 if (GET_CODE (operands[2]) != CONST_INT)
1523 operands[2] = force_reg (SImode, operands[2]);
1528 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1530 operands[2] = force_reg (SImode,
1531 GEN_INT (~INTVAL (operands[2])));
1533 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1538 for (i = 9; i <= 31; i++)
1540 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1542 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1546 else if ((((HOST_WIDE_INT) 1) << i) - 1
1547 == ~INTVAL (operands[2]))
1549 rtx shift = GEN_INT (i);
1550 rtx reg = gen_reg_rtx (SImode);
1552 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1553 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1559 operands[2] = force_reg (SImode, operands[2]);
1565 (define_insn_and_split "*arm_andsi3_insn"
1566 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1567 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1568 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1572 bic%?\\t%0, %1, #%B2
1575 && GET_CODE (operands[2]) == CONST_INT
1576 && !(const_ok_for_arm (INTVAL (operands[2]))
1577 || const_ok_for_arm (~INTVAL (operands[2])))"
1578 [(clobber (const_int 0))]
1580 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1584 [(set_attr "length" "4,4,16")
1585 (set_attr "predicable" "yes")]
1588 (define_insn "*thumb_andsi3_insn"
1589 [(set (match_operand:SI 0 "register_operand" "=l")
1590 (and:SI (match_operand:SI 1 "register_operand" "%0")
1591 (match_operand:SI 2 "register_operand" "l")))]
1594 [(set_attr "length" "2")]
1597 (define_insn "*andsi3_compare0"
1598 [(set (reg:CC_NOOV CC_REGNUM)
1600 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1601 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1603 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1604 (and:SI (match_dup 1) (match_dup 2)))]
1608 bic%?s\\t%0, %1, #%B2"
1609 [(set_attr "conds" "set")]
1612 (define_insn "*andsi3_compare0_scratch"
1613 [(set (reg:CC_NOOV CC_REGNUM)
1615 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1616 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1618 (clobber (match_scratch:SI 2 "=X,r"))]
1622 bic%?s\\t%2, %0, #%B1"
1623 [(set_attr "conds" "set")]
1626 (define_insn "*zeroextractsi_compare0_scratch"
1627 [(set (reg:CC_NOOV CC_REGNUM)
1628 (compare:CC_NOOV (zero_extract:SI
1629 (match_operand:SI 0 "s_register_operand" "r")
1630 (match_operand 1 "const_int_operand" "n")
1631 (match_operand 2 "const_int_operand" "n"))
1634 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1635 && INTVAL (operands[1]) > 0
1636 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1637 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1639 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1640 << INTVAL (operands[2]));
1641 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1644 [(set_attr "conds" "set")]
1647 (define_insn "*ne_zeroextractsi"
1648 [(set (match_operand:SI 0 "s_register_operand" "=r")
1649 (ne:SI (zero_extract:SI
1650 (match_operand:SI 1 "s_register_operand" "r")
1651 (match_operand:SI 2 "const_int_operand" "n")
1652 (match_operand:SI 3 "const_int_operand" "n"))
1654 (clobber (reg:CC CC_REGNUM))]
1656 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1657 && INTVAL (operands[2]) > 0
1658 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1659 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1661 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1662 << INTVAL (operands[3]));
1663 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1664 return \"movne\\t%0, #1\";
1666 [(set_attr "conds" "clob")
1667 (set_attr "length" "8")]
1670 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1671 ;;; represented by the bitfield, then this will produce incorrect results.
1672 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1673 ;;; which have a real bit-field insert instruction, the truncation happens
1674 ;;; in the bit-field insert instruction itself. Since arm does not have a
1675 ;;; bit-field insert instruction, we would have to emit code here to truncate
1676 ;;; the value before we insert. This loses some of the advantage of having
1677 ;;; this insv pattern, so this pattern needs to be reevalutated.
1679 (define_expand "insv"
1680 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1681 (match_operand:SI 1 "general_operand" "")
1682 (match_operand:SI 2 "general_operand" ""))
1683 (match_operand:SI 3 "reg_or_int_operand" ""))]
1687 int start_bit = INTVAL (operands[2]);
1688 int width = INTVAL (operands[1]);
1689 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1690 rtx target, subtarget;
1692 target = operands[0];
1693 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1694 subreg as the final target. */
1695 if (GET_CODE (target) == SUBREG)
1697 subtarget = gen_reg_rtx (SImode);
1698 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1699 < GET_MODE_SIZE (SImode))
1700 target = SUBREG_REG (target);
1705 if (GET_CODE (operands[3]) == CONST_INT)
1707 /* Since we are inserting a known constant, we may be able to
1708 reduce the number of bits that we have to clear so that
1709 the mask becomes simple. */
1710 /* ??? This code does not check to see if the new mask is actually
1711 simpler. It may not be. */
1712 rtx op1 = gen_reg_rtx (SImode);
1713 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1714 start of this pattern. */
1715 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1716 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1718 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1719 emit_insn (gen_iorsi3 (subtarget, op1,
1720 GEN_INT (op3_value << start_bit)));
1722 else if (start_bit == 0
1723 && !(const_ok_for_arm (mask)
1724 || const_ok_for_arm (~mask)))
1726 /* A Trick, since we are setting the bottom bits in the word,
1727 we can shift operand[3] up, operand[0] down, OR them together
1728 and rotate the result back again. This takes 3 insns, and
1729 the third might be mergeable into another op. */
1730 /* The shift up copes with the possibility that operand[3] is
1731 wider than the bitfield. */
1732 rtx op0 = gen_reg_rtx (SImode);
1733 rtx op1 = gen_reg_rtx (SImode);
1735 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1736 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1737 emit_insn (gen_iorsi3 (op1, op1, op0));
1738 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1740 else if ((width + start_bit == 32)
1741 && !(const_ok_for_arm (mask)
1742 || const_ok_for_arm (~mask)))
1744 /* Similar trick, but slightly less efficient. */
1746 rtx op0 = gen_reg_rtx (SImode);
1747 rtx op1 = gen_reg_rtx (SImode);
1749 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1750 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1751 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1752 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1756 rtx op0 = GEN_INT (mask);
1757 rtx op1 = gen_reg_rtx (SImode);
1758 rtx op2 = gen_reg_rtx (SImode);
1760 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1762 rtx tmp = gen_reg_rtx (SImode);
1764 emit_insn (gen_movsi (tmp, op0));
1768 /* Mask out any bits in operand[3] that are not needed. */
1769 emit_insn (gen_andsi3 (op1, operands[3], op0));
1771 if (GET_CODE (op0) == CONST_INT
1772 && (const_ok_for_arm (mask << start_bit)
1773 || const_ok_for_arm (~(mask << start_bit))))
1775 op0 = GEN_INT (~(mask << start_bit));
1776 emit_insn (gen_andsi3 (op2, operands[0], op0));
1780 if (GET_CODE (op0) == CONST_INT)
1782 rtx tmp = gen_reg_rtx (SImode);
1784 emit_insn (gen_movsi (tmp, op0));
1789 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1791 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1795 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1797 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1800 if (subtarget != target)
1802 /* If TARGET is still a SUBREG, then it must be wider than a word,
1803 so we must be careful only to set the subword we were asked to. */
1804 if (GET_CODE (target) == SUBREG)
1805 emit_move_insn (target, subtarget);
1807 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1814 ; constants for op 2 will never be given to these patterns.
1815 (define_insn_and_split "*anddi_notdi_di"
1816 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1817 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1818 (match_operand:DI 2 "s_register_operand" "0,r")))]
1821 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1822 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1823 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1826 operands[3] = gen_highpart (SImode, operands[0]);
1827 operands[0] = gen_lowpart (SImode, operands[0]);
1828 operands[4] = gen_highpart (SImode, operands[1]);
1829 operands[1] = gen_lowpart (SImode, operands[1]);
1830 operands[5] = gen_highpart (SImode, operands[2]);
1831 operands[2] = gen_lowpart (SImode, operands[2]);
1833 [(set_attr "length" "8")
1834 (set_attr "predicable" "yes")]
1837 (define_insn_and_split "*anddi_notzesidi_di"
1838 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1839 (and:DI (not:DI (zero_extend:DI
1840 (match_operand:SI 2 "s_register_operand" "r,r")))
1841 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1844 bic%?\\t%Q0, %Q1, %2
1846 ; (not (zero_extend ...)) allows us to just copy the high word from
1847 ; operand1 to operand0.
1850 && operands[0] != operands[1]"
1851 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1852 (set (match_dup 3) (match_dup 4))]
1855 operands[3] = gen_highpart (SImode, operands[0]);
1856 operands[0] = gen_lowpart (SImode, operands[0]);
1857 operands[4] = gen_highpart (SImode, operands[1]);
1858 operands[1] = gen_lowpart (SImode, operands[1]);
1860 [(set_attr "length" "4,8")
1861 (set_attr "predicable" "yes")]
1864 (define_insn_and_split "*anddi_notsesidi_di"
1865 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1866 (and:DI (not:DI (sign_extend:DI
1867 (match_operand:SI 2 "s_register_operand" "r,r")))
1868 (match_operand:DI 1 "s_register_operand" "0,r")))]
1871 "TARGET_ARM && reload_completed"
1872 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1873 (set (match_dup 3) (and:SI (not:SI
1874 (ashiftrt:SI (match_dup 2) (const_int 31)))
1878 operands[3] = gen_highpart (SImode, operands[0]);
1879 operands[0] = gen_lowpart (SImode, operands[0]);
1880 operands[4] = gen_highpart (SImode, operands[1]);
1881 operands[1] = gen_lowpart (SImode, operands[1]);
1883 [(set_attr "length" "8")
1884 (set_attr "predicable" "yes")]
1887 (define_insn "andsi_notsi_si"
1888 [(set (match_operand:SI 0 "s_register_operand" "=r")
1889 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1890 (match_operand:SI 1 "s_register_operand" "r")))]
1892 "bic%?\\t%0, %1, %2"
1893 [(set_attr "predicable" "yes")]
1896 (define_insn "bicsi3"
1897 [(set (match_operand:SI 0 "register_operand" "=l")
1898 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1899 (match_operand:SI 2 "register_operand" "0")))]
1902 [(set_attr "length" "2")]
1905 (define_insn "andsi_not_shiftsi_si"
1906 [(set (match_operand:SI 0 "s_register_operand" "=r")
1907 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1908 [(match_operand:SI 2 "s_register_operand" "r")
1909 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1910 (match_operand:SI 1 "s_register_operand" "r")))]
1912 "bic%?\\t%0, %1, %2%S4"
1913 [(set_attr "predicable" "yes")
1914 (set_attr "shift" "2")
1918 (define_insn "*andsi_notsi_si_compare0"
1919 [(set (reg:CC_NOOV CC_REGNUM)
1921 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1922 (match_operand:SI 1 "s_register_operand" "r"))
1924 (set (match_operand:SI 0 "s_register_operand" "=r")
1925 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1927 "bic%?s\\t%0, %1, %2"
1928 [(set_attr "conds" "set")]
1931 (define_insn "*andsi_notsi_si_compare0_scratch"
1932 [(set (reg:CC_NOOV CC_REGNUM)
1934 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1935 (match_operand:SI 1 "s_register_operand" "r"))
1937 (clobber (match_scratch:SI 0 "=r"))]
1939 "bic%?s\\t%0, %1, %2"
1940 [(set_attr "conds" "set")]
1943 (define_insn "iordi3"
1944 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1945 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1946 (match_operand:DI 2 "s_register_operand" "r,r")))]
1947 "TARGET_ARM && ! TARGET_IWMMXT"
1949 [(set_attr "length" "8")
1950 (set_attr "predicable" "yes")]
1953 (define_insn "*iordi_zesidi_di"
1954 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1955 (ior:DI (zero_extend:DI
1956 (match_operand:SI 2 "s_register_operand" "r,r"))
1957 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1960 orr%?\\t%Q0, %Q1, %2
1962 [(set_attr "length" "4,8")
1963 (set_attr "predicable" "yes")]
1966 (define_insn "*iordi_sesidi_di"
1967 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1968 (ior:DI (sign_extend:DI
1969 (match_operand:SI 2 "s_register_operand" "r,r"))
1970 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1973 [(set_attr "length" "8")
1974 (set_attr "predicable" "yes")]
1977 (define_expand "iorsi3"
1978 [(set (match_operand:SI 0 "s_register_operand" "")
1979 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1980 (match_operand:SI 2 "reg_or_int_operand" "")))]
1983 if (GET_CODE (operands[2]) == CONST_INT)
1987 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1990 ? 0 : preserve_subexpressions_p ()));
1993 else /* TARGET_THUMB */
1994 operands [2] = force_reg (SImode, operands [2]);
1999 (define_insn_and_split "*arm_iorsi3"
2000 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2001 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2002 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2008 && GET_CODE (operands[2]) == CONST_INT
2009 && !const_ok_for_arm (INTVAL (operands[2]))"
2010 [(clobber (const_int 0))]
2012 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2016 [(set_attr "length" "4,16")
2017 (set_attr "predicable" "yes")]
2020 (define_insn "*thumb_iorsi3"
2021 [(set (match_operand:SI 0 "register_operand" "=l")
2022 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2023 (match_operand:SI 2 "register_operand" "l")))]
2026 [(set_attr "length" "2")]
2030 [(match_scratch:SI 3 "r")
2031 (set (match_operand:SI 0 "s_register_operand" "")
2032 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2033 (match_operand:SI 2 "const_int_operand" "")))]
2035 && !const_ok_for_arm (INTVAL (operands[2]))
2036 && const_ok_for_arm (~INTVAL (operands[2]))"
2037 [(set (match_dup 3) (match_dup 2))
2038 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2042 (define_insn "*iorsi3_compare0"
2043 [(set (reg:CC_NOOV CC_REGNUM)
2044 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2045 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2047 (set (match_operand:SI 0 "s_register_operand" "=r")
2048 (ior:SI (match_dup 1) (match_dup 2)))]
2050 "orr%?s\\t%0, %1, %2"
2051 [(set_attr "conds" "set")]
2054 (define_insn "*iorsi3_compare0_scratch"
2055 [(set (reg:CC_NOOV CC_REGNUM)
2056 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2057 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2059 (clobber (match_scratch:SI 0 "=r"))]
2061 "orr%?s\\t%0, %1, %2"
2062 [(set_attr "conds" "set")]
2065 (define_insn "xordi3"
2066 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2067 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2068 (match_operand:DI 2 "s_register_operand" "r,r")))]
2069 "TARGET_ARM && !TARGET_IWMMXT"
2071 [(set_attr "length" "8")
2072 (set_attr "predicable" "yes")]
2075 (define_insn "*xordi_zesidi_di"
2076 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2077 (xor:DI (zero_extend:DI
2078 (match_operand:SI 2 "s_register_operand" "r,r"))
2079 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2082 eor%?\\t%Q0, %Q1, %2
2084 [(set_attr "length" "4,8")
2085 (set_attr "predicable" "yes")]
2088 (define_insn "*xordi_sesidi_di"
2089 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2090 (xor:DI (sign_extend:DI
2091 (match_operand:SI 2 "s_register_operand" "r,r"))
2092 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2095 [(set_attr "length" "8")
2096 (set_attr "predicable" "yes")]
2099 (define_expand "xorsi3"
2100 [(set (match_operand:SI 0 "s_register_operand" "")
2101 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2102 (match_operand:SI 2 "arm_rhs_operand" "")))]
2105 if (GET_CODE (operands[2]) == CONST_INT)
2106 operands[2] = force_reg (SImode, operands[2]);
2110 (define_insn "*arm_xorsi3"
2111 [(set (match_operand:SI 0 "s_register_operand" "=r")
2112 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2113 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2115 "eor%?\\t%0, %1, %2"
2116 [(set_attr "predicable" "yes")]
2119 (define_insn "*thumb_xorsi3"
2120 [(set (match_operand:SI 0 "register_operand" "=l")
2121 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2122 (match_operand:SI 2 "register_operand" "l")))]
2125 [(set_attr "length" "2")]
2128 (define_insn "*xorsi3_compare0"
2129 [(set (reg:CC_NOOV CC_REGNUM)
2130 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2131 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2133 (set (match_operand:SI 0 "s_register_operand" "=r")
2134 (xor:SI (match_dup 1) (match_dup 2)))]
2136 "eor%?s\\t%0, %1, %2"
2137 [(set_attr "conds" "set")]
2140 (define_insn "*xorsi3_compare0_scratch"
2141 [(set (reg:CC_NOOV CC_REGNUM)
2142 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2143 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2147 [(set_attr "conds" "set")]
2150 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2151 ; (NOT D) we can sometimes merge the final NOT into one of the following
2155 [(set (match_operand:SI 0 "s_register_operand" "")
2156 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2157 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2158 (match_operand:SI 3 "arm_rhs_operand" "")))
2159 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2161 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2162 (not:SI (match_dup 3))))
2163 (set (match_dup 0) (not:SI (match_dup 4)))]
2167 (define_insn "*andsi_iorsi3_notsi"
2168 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2169 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2170 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2171 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2173 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2174 [(set_attr "length" "8")
2175 (set_attr "predicable" "yes")]
2180 ;; Minimum and maximum insns
2182 (define_insn "smaxsi3"
2183 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2184 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2185 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2186 (clobber (reg:CC CC_REGNUM))]
2189 cmp\\t%1, %2\;movlt\\t%0, %2
2190 cmp\\t%1, %2\;movge\\t%0, %1
2191 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2192 [(set_attr "conds" "clob")
2193 (set_attr "length" "8,8,12")]
2196 (define_insn "sminsi3"
2197 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2198 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2199 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2200 (clobber (reg:CC CC_REGNUM))]
2203 cmp\\t%1, %2\;movge\\t%0, %2
2204 cmp\\t%1, %2\;movlt\\t%0, %1
2205 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2206 [(set_attr "conds" "clob")
2207 (set_attr "length" "8,8,12")]
2210 (define_insn "umaxsi3"
2211 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2212 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2213 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2214 (clobber (reg:CC CC_REGNUM))]
2217 cmp\\t%1, %2\;movcc\\t%0, %2
2218 cmp\\t%1, %2\;movcs\\t%0, %1
2219 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2220 [(set_attr "conds" "clob")
2221 (set_attr "length" "8,8,12")]
2224 (define_insn "uminsi3"
2225 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2226 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2227 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2228 (clobber (reg:CC CC_REGNUM))]
2231 cmp\\t%1, %2\;movcs\\t%0, %2
2232 cmp\\t%1, %2\;movcc\\t%0, %1
2233 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2234 [(set_attr "conds" "clob")
2235 (set_attr "length" "8,8,12")]
2238 (define_insn "*store_minmaxsi"
2239 [(set (match_operand:SI 0 "memory_operand" "=m")
2240 (match_operator:SI 3 "minmax_operator"
2241 [(match_operand:SI 1 "s_register_operand" "r")
2242 (match_operand:SI 2 "s_register_operand" "r")]))
2243 (clobber (reg:CC CC_REGNUM))]
2246 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2248 output_asm_insn (\"cmp\\t%1, %2\", operands);
2249 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2250 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2253 [(set_attr "conds" "clob")
2254 (set_attr "length" "12")
2255 (set_attr "type" "store1")]
2258 ; Reject the frame pointer in operand[1], since reloading this after
2259 ; it has been eliminated can cause carnage.
2260 (define_insn "*minmax_arithsi"
2261 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2262 (match_operator:SI 4 "shiftable_operator"
2263 [(match_operator:SI 5 "minmax_operator"
2264 [(match_operand:SI 2 "s_register_operand" "r,r")
2265 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2266 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2267 (clobber (reg:CC CC_REGNUM))]
2269 && (GET_CODE (operands[1]) != REG
2270 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2271 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2274 enum rtx_code code = GET_CODE (operands[4]);
2276 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2278 output_asm_insn (\"cmp\\t%2, %3\", operands);
2279 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2280 if (which_alternative != 0 || operands[3] != const0_rtx
2281 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2282 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2285 [(set_attr "conds" "clob")
2286 (set_attr "length" "12")]
2290 ;; Shift and rotation insns
2292 (define_expand "ashlsi3"
2293 [(set (match_operand:SI 0 "s_register_operand" "")
2294 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2295 (match_operand:SI 2 "arm_rhs_operand" "")))]
2298 if (GET_CODE (operands[2]) == CONST_INT
2299 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2301 emit_insn (gen_movsi (operands[0], const0_rtx));
2307 (define_insn "*thumb_ashlsi3"
2308 [(set (match_operand:SI 0 "register_operand" "=l,l")
2309 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2310 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2313 [(set_attr "length" "2")]
2316 (define_expand "ashrsi3"
2317 [(set (match_operand:SI 0 "s_register_operand" "")
2318 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2319 (match_operand:SI 2 "arm_rhs_operand" "")))]
2322 if (GET_CODE (operands[2]) == CONST_INT
2323 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2324 operands[2] = GEN_INT (31);
2328 (define_insn "*thumb_ashrsi3"
2329 [(set (match_operand:SI 0 "register_operand" "=l,l")
2330 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2331 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2334 [(set_attr "length" "2")]
2337 (define_expand "lshrsi3"
2338 [(set (match_operand:SI 0 "s_register_operand" "")
2339 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2340 (match_operand:SI 2 "arm_rhs_operand" "")))]
2343 if (GET_CODE (operands[2]) == CONST_INT
2344 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2346 emit_insn (gen_movsi (operands[0], const0_rtx));
2352 (define_insn "*thumb_lshrsi3"
2353 [(set (match_operand:SI 0 "register_operand" "=l,l")
2354 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2355 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2358 [(set_attr "length" "2")]
2361 (define_expand "rotlsi3"
2362 [(set (match_operand:SI 0 "s_register_operand" "")
2363 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2364 (match_operand:SI 2 "reg_or_int_operand" "")))]
2367 if (GET_CODE (operands[2]) == CONST_INT)
2368 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2371 rtx reg = gen_reg_rtx (SImode);
2372 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2378 (define_expand "rotrsi3"
2379 [(set (match_operand:SI 0 "s_register_operand" "")
2380 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2381 (match_operand:SI 2 "arm_rhs_operand" "")))]
2386 if (GET_CODE (operands[2]) == CONST_INT
2387 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2388 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2390 else /* TARGET_THUMB */
2392 if (GET_CODE (operands [2]) == CONST_INT)
2393 operands [2] = force_reg (SImode, operands[2]);
2398 (define_insn "*thumb_rotrsi3"
2399 [(set (match_operand:SI 0 "register_operand" "=l")
2400 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2401 (match_operand:SI 2 "register_operand" "l")))]
2404 [(set_attr "length" "2")]
2407 (define_expand "ashldi3"
2408 [(set (match_operand:DI 0 "s_register_operand" "")
2409 (ashift:DI (match_operand:DI 1 "general_operand" "")
2410 (match_operand:SI 2 "general_operand" "")))]
2411 "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)"
2413 if (! s_register_operand (operands[1], DImode))
2414 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2415 if (! s_register_operand (operands[2], SImode))
2416 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2420 (define_insn "*arm_shiftsi3"
2421 [(set (match_operand:SI 0 "s_register_operand" "=r")
2422 (match_operator:SI 3 "shift_operator"
2423 [(match_operand:SI 1 "s_register_operand" "r")
2424 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2427 [(set_attr "predicable" "yes")
2428 (set_attr "shift" "1")
2432 (define_insn "*shiftsi3_compare0"
2433 [(set (reg:CC_NOOV CC_REGNUM)
2434 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2435 [(match_operand:SI 1 "s_register_operand" "r")
2436 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2438 (set (match_operand:SI 0 "s_register_operand" "=r")
2439 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2441 "mov%?s\\t%0, %1%S3"
2442 [(set_attr "conds" "set")
2443 (set_attr "shift" "1")
2447 (define_insn "*shiftsi3_compare0_scratch"
2448 [(set (reg:CC_NOOV CC_REGNUM)
2449 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2450 [(match_operand:SI 1 "s_register_operand" "r")
2451 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2453 (clobber (match_scratch:SI 0 "=r"))]
2455 "mov%?s\\t%0, %1%S3"
2456 [(set_attr "conds" "set")
2457 (set_attr "shift" "1")
2461 (define_insn "*notsi_shiftsi"
2462 [(set (match_operand:SI 0 "s_register_operand" "=r")
2463 (not:SI (match_operator:SI 3 "shift_operator"
2464 [(match_operand:SI 1 "s_register_operand" "r")
2465 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2468 [(set_attr "predicable" "yes")
2469 (set_attr "shift" "1")
2473 (define_insn "*notsi_shiftsi_compare0"
2474 [(set (reg:CC_NOOV CC_REGNUM)
2475 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2476 [(match_operand:SI 1 "s_register_operand" "r")
2477 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2479 (set (match_operand:SI 0 "s_register_operand" "=r")
2480 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2482 "mvn%?s\\t%0, %1%S3"
2483 [(set_attr "conds" "set")
2484 (set_attr "shift" "1")
2488 (define_insn "*not_shiftsi_compare0_scratch"
2489 [(set (reg:CC_NOOV CC_REGNUM)
2490 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2491 [(match_operand:SI 1 "s_register_operand" "r")
2492 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2494 (clobber (match_scratch:SI 0 "=r"))]
2496 "mvn%?s\\t%0, %1%S3"
2497 [(set_attr "conds" "set")
2498 (set_attr "shift" "1")
2502 ;; We don't really have extzv, but defining this using shifts helps
2503 ;; to reduce register pressure later on.
2505 (define_expand "extzv"
2507 (ashift:SI (match_operand:SI 1 "register_operand" "")
2508 (match_operand:SI 2 "const_int_operand" "")))
2509 (set (match_operand:SI 0 "register_operand" "")
2510 (lshiftrt:SI (match_dup 4)
2511 (match_operand:SI 3 "const_int_operand" "")))]
2515 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2516 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2518 operands[3] = GEN_INT (rshift);
2522 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2526 operands[2] = GEN_INT (lshift);
2527 operands[4] = gen_reg_rtx (SImode);
2532 ;; Unary arithmetic insns
2534 (define_expand "negdi2"
2536 [(set (match_operand:DI 0 "s_register_operand" "")
2537 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2538 (clobber (reg:CC CC_REGNUM))])]
2543 if (GET_CODE (operands[1]) != REG)
2544 operands[1] = force_reg (SImode, operands[1]);
2549 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2550 ;; The second alternative is to allow the common case of a *full* overlap.
2551 (define_insn "*arm_negdi2"
2552 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2553 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2554 (clobber (reg:CC CC_REGNUM))]
2556 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2557 [(set_attr "conds" "clob")
2558 (set_attr "length" "8")]
2561 (define_insn "*thumb_negdi2"
2562 [(set (match_operand:DI 0 "register_operand" "=&l")
2563 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2564 (clobber (reg:CC CC_REGNUM))]
2566 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2567 [(set_attr "length" "6")]
2570 (define_expand "negsi2"
2571 [(set (match_operand:SI 0 "s_register_operand" "")
2572 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2577 (define_insn "*arm_negsi2"
2578 [(set (match_operand:SI 0 "s_register_operand" "=r")
2579 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2581 "rsb%?\\t%0, %1, #0"
2582 [(set_attr "predicable" "yes")]
2585 (define_insn "*thumb_negsi2"
2586 [(set (match_operand:SI 0 "register_operand" "=l")
2587 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2590 [(set_attr "length" "2")]
2593 (define_expand "negsf2"
2594 [(set (match_operand:SF 0 "s_register_operand" "")
2595 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2596 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2600 (define_expand "negdf2"
2601 [(set (match_operand:DF 0 "s_register_operand" "")
2602 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2603 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2606 ;; abssi2 doesn't really clobber the condition codes if a different register
2607 ;; is being set. To keep things simple, assume during rtl manipulations that
2608 ;; it does, but tell the final scan operator the truth. Similarly for
2611 (define_expand "abssi2"
2613 [(set (match_operand:SI 0 "s_register_operand" "")
2614 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2615 (clobber (reg:CC CC_REGNUM))])]
2619 (define_insn "*arm_abssi2"
2620 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2621 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2622 (clobber (reg:CC CC_REGNUM))]
2625 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2626 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2627 [(set_attr "conds" "clob,*")
2628 (set_attr "shift" "1")
2629 ;; predicable can't be set based on the variant, so left as no
2630 (set_attr "length" "8")]
2633 (define_insn "*neg_abssi2"
2634 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2635 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2636 (clobber (reg:CC CC_REGNUM))]
2639 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2640 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2641 [(set_attr "conds" "clob,*")
2642 (set_attr "shift" "1")
2643 ;; predicable can't be set based on the variant, so left as no
2644 (set_attr "length" "8")]
2647 (define_expand "abssf2"
2648 [(set (match_operand:SF 0 "s_register_operand" "")
2649 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2650 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2653 (define_expand "absdf2"
2654 [(set (match_operand:DF 0 "s_register_operand" "")
2655 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2656 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2659 (define_expand "sqrtsf2"
2660 [(set (match_operand:SF 0 "s_register_operand" "")
2661 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2662 "TARGET_ARM && TARGET_HARD_FLOAT"
2665 (define_expand "sqrtdf2"
2666 [(set (match_operand:DF 0 "s_register_operand" "")
2667 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2668 "TARGET_ARM && TARGET_HARD_FLOAT"
2671 (define_insn_and_split "one_cmpldi2"
2672 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2673 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2676 "TARGET_ARM && reload_completed"
2677 [(set (match_dup 0) (not:SI (match_dup 1)))
2678 (set (match_dup 2) (not:SI (match_dup 3)))]
2681 operands[2] = gen_highpart (SImode, operands[0]);
2682 operands[0] = gen_lowpart (SImode, operands[0]);
2683 operands[3] = gen_highpart (SImode, operands[1]);
2684 operands[1] = gen_lowpart (SImode, operands[1]);
2686 [(set_attr "length" "8")
2687 (set_attr "predicable" "yes")]
2690 (define_expand "one_cmplsi2"
2691 [(set (match_operand:SI 0 "s_register_operand" "")
2692 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2697 (define_insn "*arm_one_cmplsi2"
2698 [(set (match_operand:SI 0 "s_register_operand" "=r")
2699 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2702 [(set_attr "predicable" "yes")]
2705 (define_insn "*thumb_one_cmplsi2"
2706 [(set (match_operand:SI 0 "register_operand" "=l")
2707 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2710 [(set_attr "length" "2")]
2713 (define_insn "*notsi_compare0"
2714 [(set (reg:CC_NOOV CC_REGNUM)
2715 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2717 (set (match_operand:SI 0 "s_register_operand" "=r")
2718 (not:SI (match_dup 1)))]
2721 [(set_attr "conds" "set")]
2724 (define_insn "*notsi_compare0_scratch"
2725 [(set (reg:CC_NOOV CC_REGNUM)
2726 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2728 (clobber (match_scratch:SI 0 "=r"))]
2731 [(set_attr "conds" "set")]
2734 ;; Fixed <--> Floating conversion insns
2736 (define_expand "floatsisf2"
2737 [(set (match_operand:SF 0 "s_register_operand" "")
2738 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2739 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2743 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2748 (define_expand "floatsidf2"
2749 [(set (match_operand:DF 0 "s_register_operand" "")
2750 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2751 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2755 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
2760 (define_expand "fix_truncsfsi2"
2761 [(set (match_operand:SI 0 "s_register_operand" "")
2762 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
2763 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2767 if (!cirrus_fp_register (operands[0], SImode))
2768 operands[0] = force_reg (SImode, operands[0]);
2769 if (!cirrus_fp_register (operands[1], SFmode))
2770 operands[1] = force_reg (SFmode, operands[0]);
2771 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
2776 (define_expand "fix_truncdfsi2"
2777 [(set (match_operand:SI 0 "s_register_operand" "")
2778 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
2779 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2783 if (!cirrus_fp_register (operands[1], DFmode))
2784 operands[1] = force_reg (DFmode, operands[0]);
2785 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
2792 (define_expand "truncdfsf2"
2793 [(set (match_operand:SF 0 "s_register_operand" "")
2795 (match_operand:DF 1 "s_register_operand" "")))]
2796 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2800 ;; Zero and sign extension instructions.
2802 (define_insn "zero_extendsidi2"
2803 [(set (match_operand:DI 0 "s_register_operand" "=r")
2804 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2807 if (REGNO (operands[1])
2808 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2809 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2810 return \"mov%?\\t%R0, #0\";
2812 [(set_attr "length" "8")
2813 (set_attr "predicable" "yes")]
2816 (define_insn "zero_extendqidi2"
2817 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2818 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2821 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2822 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2823 [(set_attr "length" "8")
2824 (set_attr "predicable" "yes")
2825 (set_attr "type" "*,load")
2826 (set_attr "pool_range" "*,4092")
2827 (set_attr "neg_pool_range" "*,4084")]
2830 (define_insn "extendsidi2"
2831 [(set (match_operand:DI 0 "s_register_operand" "=r")
2832 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2835 if (REGNO (operands[1])
2836 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2837 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2838 return \"mov%?\\t%R0, %Q0, asr #31\";
2840 [(set_attr "length" "8")
2841 (set_attr "shift" "1")
2842 (set_attr "predicable" "yes")]
2845 (define_expand "zero_extendhisi2"
2847 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2849 (set (match_operand:SI 0 "s_register_operand" "")
2850 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2856 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2858 /* Note: We do not have to worry about TARGET_MMU_TRAPS
2859 here because the insn below will generate an LDRH instruction
2860 rather than an LDR instruction, so we cannot get an unaligned
2862 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2863 gen_rtx_ZERO_EXTEND (SImode,
2867 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2869 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2872 if (!s_register_operand (operands[1], HImode))
2873 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2874 operands[1] = gen_lowpart (SImode, operands[1]);
2875 operands[2] = gen_reg_rtx (SImode);
2877 else /* TARGET_THUMB */
2879 if (GET_CODE (operands[1]) == MEM)
2883 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
2884 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
2891 if (!s_register_operand (operands[1], HImode))
2892 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2893 operands[1] = gen_lowpart (SImode, operands[1]);
2894 operands[2] = gen_reg_rtx (SImode);
2896 ops[0] = operands[2];
2897 ops[1] = operands[1];
2898 ops[2] = GEN_INT (16);
2900 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2901 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
2903 ops[0] = operands[0];
2904 ops[1] = operands[2];
2905 ops[2] = GEN_INT (16);
2907 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
2908 gen_rtx_LSHIFTRT (SImode, ops[1],
2916 (define_insn "*thumb_zero_extendhisi2"
2917 [(set (match_operand:SI 0 "register_operand" "=l")
2918 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2921 rtx mem = XEXP (operands[1], 0);
2923 if (GET_CODE (mem) == CONST)
2924 mem = XEXP (mem, 0);
2926 if (GET_CODE (mem) == LABEL_REF)
2927 return \"ldr\\t%0, %1\";
2929 if (GET_CODE (mem) == PLUS)
2931 rtx a = XEXP (mem, 0);
2932 rtx b = XEXP (mem, 1);
2934 /* This can happen due to bugs in reload. */
2935 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
2938 ops[0] = operands[0];
2941 output_asm_insn (\"mov %0, %1\", ops);
2943 XEXP (mem, 0) = operands[0];
2946 else if ( GET_CODE (a) == LABEL_REF
2947 && GET_CODE (b) == CONST_INT)
2948 return \"ldr\\t%0, %1\";
2951 return \"ldrh\\t%0, %1\";
2953 [(set_attr "length" "4")
2954 (set_attr "type" "load")
2955 (set_attr "pool_range" "60")]
2958 (define_insn "*arm_zero_extendhisi2"
2959 [(set (match_operand:SI 0 "s_register_operand" "=r")
2960 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2961 "TARGET_ARM && arm_arch4"
2963 [(set_attr "type" "load")
2964 (set_attr "predicable" "yes")
2965 (set_attr "pool_range" "256")
2966 (set_attr "neg_pool_range" "244")]
2970 [(set (match_operand:SI 0 "s_register_operand" "")
2971 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2972 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2973 "TARGET_ARM && (!arm_arch4)"
2974 [(set (match_dup 2) (match_dup 1))
2975 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2977 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
2983 [(set (match_operand:SI 0 "s_register_operand" "")
2984 (match_operator:SI 3 "shiftable_operator"
2985 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2986 (match_operand:SI 4 "s_register_operand" "")]))
2987 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2988 "TARGET_ARM && (!arm_arch4)"
2989 [(set (match_dup 2) (match_dup 1))
2992 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2994 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
2999 (define_expand "zero_extendqisi2"
3000 [(set (match_operand:SI 0 "s_register_operand" "")
3001 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3004 if (GET_CODE (operands[1]) != MEM)
3008 emit_insn (gen_andsi3 (operands[0],
3009 gen_lowpart (SImode, operands[1]),
3012 else /* TARGET_THUMB */
3014 rtx temp = gen_reg_rtx (SImode);
3017 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3018 operands[1] = gen_lowpart (SImode, operands[1]);
3021 ops[1] = operands[1];
3022 ops[2] = GEN_INT (24);
3024 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3025 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3027 ops[0] = operands[0];
3029 ops[2] = GEN_INT (24);
3031 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3032 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3039 (define_insn "*thumb_zero_extendqisi2"
3040 [(set (match_operand:SI 0 "register_operand" "=l")
3041 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3044 [(set_attr "length" "2")
3045 (set_attr "type" "load")
3046 (set_attr "pool_range" "32")]
3049 (define_insn "*arm_zero_extendqisi2"
3050 [(set (match_operand:SI 0 "s_register_operand" "=r")
3051 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3053 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3054 [(set_attr "type" "load")
3055 (set_attr "predicable" "yes")
3056 (set_attr "pool_range" "4096")
3057 (set_attr "neg_pool_range" "4084")]
3061 [(set (match_operand:SI 0 "s_register_operand" "")
3062 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3063 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3064 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3065 [(set (match_dup 2) (match_dup 1))
3066 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3070 (define_insn "*compareqi_eq0"
3071 [(set (reg:CC_Z CC_REGNUM)
3072 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3076 [(set_attr "conds" "set")]
3079 (define_expand "extendhisi2"
3081 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3083 (set (match_operand:SI 0 "s_register_operand" "")
3084 (ashiftrt:SI (match_dup 2)
3089 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3091 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3092 here because the insn below will generate an LDRH instruction
3093 rather than an LDR instruction, so we cannot get an unaligned
3095 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3096 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3100 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3102 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3105 if (!s_register_operand (operands[1], HImode))
3106 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3107 operands[1] = gen_lowpart (SImode, operands[1]);
3108 operands[2] = gen_reg_rtx (SImode);
3114 ops[0] = operands[2];
3115 ops[1] = operands[1];
3116 ops[2] = GEN_INT (16);
3118 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3119 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3121 ops[0] = operands[0];
3122 ops[1] = operands[2];
3123 ops[2] = GEN_INT (16);
3125 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3126 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3133 (define_insn "*thumb_extendhisi2_insn"
3134 [(set (match_operand:SI 0 "register_operand" "=l")
3135 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3136 (clobber (match_scratch:SI 2 "=&l"))]
3141 rtx mem = XEXP (operands[1], 0);
3143 /* This code used to try to use 'V', and fix the address only if it was
3144 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3145 range of QImode offsets, and offsettable_address_p does a QImode
3148 if (GET_CODE (mem) == CONST)
3149 mem = XEXP (mem, 0);
3151 if (GET_CODE (mem) == LABEL_REF)
3152 return \"ldr\\t%0, %1\";
3154 if (GET_CODE (mem) == PLUS)
3156 rtx a = XEXP (mem, 0);
3157 rtx b = XEXP (mem, 1);
3159 if (GET_CODE (a) == LABEL_REF
3160 && GET_CODE (b) == CONST_INT)
3161 return \"ldr\\t%0, %1\";
3163 if (GET_CODE (b) == REG)
3164 return \"ldrsh\\t%0, %1\";
3172 ops[2] = const0_rtx;
3175 if (GET_CODE (ops[1]) != REG)
3181 ops[0] = operands[0];
3182 ops[3] = operands[2];
3183 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3186 [(set_attr "length" "4")
3187 (set_attr "type" "load")
3188 (set_attr "pool_range" "1020")]
3191 (define_expand "extendhisi2_mem"
3192 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3194 (zero_extend:SI (match_dup 7)))
3195 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3196 (set (match_operand:SI 0 "" "")
3197 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3202 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3204 mem1 = gen_rtx_MEM (QImode, addr);
3205 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3206 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3207 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3208 operands[0] = gen_lowpart (SImode, operands[0]);
3210 operands[2] = gen_reg_rtx (SImode);
3211 operands[3] = gen_reg_rtx (SImode);
3212 operands[6] = gen_reg_rtx (SImode);
3215 if (BYTES_BIG_ENDIAN)
3217 operands[4] = operands[2];
3218 operands[5] = operands[3];
3222 operands[4] = operands[3];
3223 operands[5] = operands[2];
3228 (define_insn "*arm_extendhisi_insn"
3229 [(set (match_operand:SI 0 "s_register_operand" "=r")
3230 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3231 "TARGET_ARM && arm_arch4"
3233 [(set_attr "type" "load")
3234 (set_attr "predicable" "yes")
3235 (set_attr "pool_range" "256")
3236 (set_attr "neg_pool_range" "244")]
3240 [(set (match_operand:SI 0 "s_register_operand" "")
3241 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3242 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3243 "TARGET_ARM && (!arm_arch4)"
3244 [(set (match_dup 2) (match_dup 1))
3245 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3247 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3253 [(set (match_operand:SI 0 "s_register_operand" "")
3254 (match_operator:SI 3 "shiftable_operator"
3255 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3256 (match_operand:SI 4 "s_register_operand" "")]))
3257 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3258 "TARGET_ARM && (!arm_arch4)"
3259 [(set (match_dup 2) (match_dup 1))
3262 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3263 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3268 (define_expand "extendqihi2"
3270 (ashift:SI (match_operand:QI 1 "general_operand" "")
3272 (set (match_operand:HI 0 "s_register_operand" "")
3273 (ashiftrt:SI (match_dup 2)
3278 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3280 emit_insn (gen_rtx_SET (VOIDmode,
3282 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3285 if (!s_register_operand (operands[1], QImode))
3286 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3287 operands[0] = gen_lowpart (SImode, operands[0]);
3288 operands[1] = gen_lowpart (SImode, operands[1]);
3289 operands[2] = gen_reg_rtx (SImode);
3293 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3294 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3295 (define_insn "*extendqihi_insn"
3296 [(set (match_operand:HI 0 "s_register_operand" "=r")
3297 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3298 "TARGET_ARM && arm_arch4"
3300 /* If the address is invalid, this will split the instruction into two. */
3301 if (bad_signed_byte_operand (operands[1], VOIDmode))
3303 return \"ldr%?sb\\t%0, %1\";
3305 [(set_attr "type" "load")
3306 (set_attr "predicable" "yes")
3307 (set_attr "length" "8")
3308 (set_attr "pool_range" "256")
3309 (set_attr "neg_pool_range" "244")]
3313 [(set (match_operand:HI 0 "s_register_operand" "")
3314 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3315 "TARGET_ARM && arm_arch4 && reload_completed"
3316 [(set (match_dup 3) (match_dup 1))
3317 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3320 HOST_WIDE_INT offset;
3322 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3323 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3324 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3325 operands[1] = XEXP (operands[1], 0);
3326 if (GET_CODE (operands[1]) == PLUS
3327 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3328 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3329 || const_ok_for_arm (-offset)))
3331 HOST_WIDE_INT low = (offset > 0
3332 ? (offset & 0xff) : -((-offset) & 0xff));
3333 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3334 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3336 /* Ensure the sum is in correct canonical form */
3337 else if (GET_CODE (operands[1]) == PLUS
3338 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3339 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3340 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3341 XEXP (operands[1], 1),
3342 XEXP (operands[1], 0));
3346 (define_expand "extendqisi2"
3348 (ashift:SI (match_operand:QI 1 "general_operand" "")
3350 (set (match_operand:SI 0 "s_register_operand" "")
3351 (ashiftrt:SI (match_dup 2)
3356 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3358 emit_insn (gen_rtx_SET (VOIDmode,
3360 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3363 if (!s_register_operand (operands[1], QImode))
3364 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3365 operands[1] = gen_lowpart (SImode, operands[1]);
3366 operands[2] = gen_reg_rtx (SImode);
3372 ops[0] = operands[2];
3373 ops[1] = operands[1];
3374 ops[2] = GEN_INT (24);
3376 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3377 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3379 ops[0] = operands[0];
3380 ops[1] = operands[2];
3381 ops[2] = GEN_INT (24);
3383 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3384 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3391 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3392 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3393 (define_insn "*arm_extendqisi_insn"
3394 [(set (match_operand:SI 0 "s_register_operand" "=r")
3395 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3396 "TARGET_ARM && arm_arch4"
3398 /* If the address is invalid, this will split the instruction into two. */
3399 if (bad_signed_byte_operand (operands[1], VOIDmode))
3401 return \"ldr%?sb\\t%0, %1\";
3403 [(set_attr "type" "load")
3404 (set_attr "predicable" "yes")
3405 (set_attr "length" "8")
3406 (set_attr "pool_range" "256")
3407 (set_attr "neg_pool_range" "244")]
3411 [(set (match_operand:SI 0 "s_register_operand" "")
3412 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3413 "TARGET_ARM && arm_arch4 && reload_completed"
3414 [(set (match_dup 0) (match_dup 1))
3415 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3418 HOST_WIDE_INT offset;
3420 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3421 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3422 operands[1] = XEXP (operands[1], 0);
3423 if (GET_CODE (operands[1]) == PLUS
3424 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3425 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3426 || const_ok_for_arm (-offset)))
3428 HOST_WIDE_INT low = (offset > 0
3429 ? (offset & 0xff) : -((-offset) & 0xff));
3430 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3431 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3433 /* Ensure the sum is in correct canonical form */
3434 else if (GET_CODE (operands[1]) == PLUS
3435 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3436 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3437 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3438 XEXP (operands[1], 1),
3439 XEXP (operands[1], 0));
3443 (define_insn "*thumb_extendqisi2_insn"
3444 [(set (match_operand:SI 0 "register_operand" "=l,l")
3445 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3450 rtx mem = XEXP (operands[1], 0);
3452 if (GET_CODE (mem) == CONST)
3453 mem = XEXP (mem, 0);
3455 if (GET_CODE (mem) == LABEL_REF)
3456 return \"ldr\\t%0, %1\";
3458 if (GET_CODE (mem) == PLUS
3459 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3460 return \"ldr\\t%0, %1\";
3462 if (which_alternative == 0)
3463 return \"ldrsb\\t%0, %1\";
3465 ops[0] = operands[0];
3467 if (GET_CODE (mem) == PLUS)
3469 rtx a = XEXP (mem, 0);
3470 rtx b = XEXP (mem, 1);
3475 if (GET_CODE (a) == REG)
3477 if (GET_CODE (b) == REG)
3478 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3479 else if (REGNO (a) == REGNO (ops[0]))
3481 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3482 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3483 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3486 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3488 else if (GET_CODE (b) != REG)
3492 if (REGNO (b) == REGNO (ops[0]))
3494 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3495 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3496 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3499 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3502 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3504 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3505 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3506 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3511 ops[2] = const0_rtx;
3513 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3517 [(set_attr "length" "2,6")
3518 (set_attr "type" "load,load")
3519 (set_attr "pool_range" "32,32")]
3522 (define_expand "extendsfdf2"
3523 [(set (match_operand:DF 0 "s_register_operand" "")
3524 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3525 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3529 ;; Move insns (including loads and stores)
3531 ;; XXX Just some ideas about movti.
3532 ;; I don't think these are a good idea on the arm, there just aren't enough
3534 ;;(define_expand "loadti"
3535 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3536 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3539 ;;(define_expand "storeti"
3540 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3541 ;; (match_operand:TI 1 "s_register_operand" ""))]
3544 ;;(define_expand "movti"
3545 ;; [(set (match_operand:TI 0 "general_operand" "")
3546 ;; (match_operand:TI 1 "general_operand" ""))]
3552 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3553 ;; operands[1] = copy_to_reg (operands[1]);
3554 ;; if (GET_CODE (operands[0]) == MEM)
3555 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3556 ;; else if (GET_CODE (operands[1]) == MEM)
3557 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3561 ;; emit_insn (insn);
3565 ;; Recognize garbage generated above.
3568 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3569 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3573 ;; register mem = (which_alternative < 3);
3574 ;; register const char *template;
3576 ;; operands[mem] = XEXP (operands[mem], 0);
3577 ;; switch (which_alternative)
3579 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3580 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3581 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3582 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3583 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3584 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3586 ;; output_asm_insn (template, operands);
3590 (define_expand "movdi"
3591 [(set (match_operand:DI 0 "general_operand" "")
3592 (match_operand:DI 1 "general_operand" ""))]
3597 if (!no_new_pseudos)
3599 if (GET_CODE (operands[0]) != REG)
3600 operands[1] = force_reg (DImode, operands[1]);
3606 (define_insn "*arm_movdi"
3607 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3608 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3609 "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT"
3611 return (output_move_double (operands));
3613 [(set_attr "length" "8")
3614 (set_attr "type" "*,load,store2")
3615 (set_attr "pool_range" "*,1020,*")
3616 (set_attr "neg_pool_range" "*,1008,*")]
3619 ;;; ??? This should have alternatives for constants.
3620 ;;; ??? This was originally identical to the movdf_insn pattern.
3621 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3622 ;;; thumb_reorg with a memory reference.
3623 (define_insn "*thumb_movdi_insn"
3624 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3625 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3628 && ( register_operand (operands[0], DImode)
3629 || register_operand (operands[1], DImode))"
3632 switch (which_alternative)
3636 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3637 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3638 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3640 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3642 operands[1] = GEN_INT (- INTVAL (operands[1]));
3643 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3645 return \"ldmia\\t%1, {%0, %H0}\";
3647 return \"stmia\\t%0, {%1, %H1}\";
3649 return thumb_load_double_from_address (operands);
3651 operands[2] = gen_rtx (MEM, SImode,
3652 plus_constant (XEXP (operands[0], 0), 4));
3653 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3656 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3657 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3658 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3661 [(set_attr "length" "4,4,6,2,2,6,4,4")
3662 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3663 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3666 (define_expand "movsi"
3667 [(set (match_operand:SI 0 "general_operand" "")
3668 (match_operand:SI 1 "general_operand" ""))]
3673 /* Everything except mem = const or mem = mem can be done easily */
3674 if (GET_CODE (operands[0]) == MEM)
3675 operands[1] = force_reg (SImode, operands[1]);
3676 if (GET_CODE (operands[1]) == CONST_INT
3677 && !(const_ok_for_arm (INTVAL (operands[1]))
3678 || const_ok_for_arm (~INTVAL (operands[1]))))
3680 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3683 : preserve_subexpressions_p ()));
3687 else /* TARGET_THUMB.... */
3689 if (!no_new_pseudos)
3691 if (GET_CODE (operands[0]) != REG)
3692 operands[1] = force_reg (SImode, operands[1]);
3697 && (CONSTANT_P (operands[1])
3698 || symbol_mentioned_p (operands[1])
3699 || label_mentioned_p (operands[1])))
3700 operands[1] = legitimize_pic_address (operands[1], SImode,
3701 (no_new_pseudos ? operands[0] : 0));
3705 (define_insn "*arm_movsi_insn"
3706 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3707 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
3708 "TARGET_ARM && ! TARGET_IWMMXT
3709 && ( register_operand (operands[0], SImode)
3710 || register_operand (operands[1], SImode))"
3716 [(set_attr "type" "*,*,load,store1")
3717 (set_attr "predicable" "yes")
3718 (set_attr "pool_range" "*,*,4096,*")
3719 (set_attr "neg_pool_range" "*,*,4084,*")]
3723 [(set (match_operand:SI 0 "s_register_operand" "")
3724 (match_operand:SI 1 "const_int_operand" ""))]
3726 && (!(const_ok_for_arm (INTVAL (operands[1]))
3727 || const_ok_for_arm (~INTVAL (operands[1]))))"
3728 [(clobber (const_int 0))]
3730 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3736 (define_insn "*thumb_movsi_insn"
3737 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3738 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
3740 && ( register_operand (operands[0], SImode)
3741 || register_operand (operands[1], SImode))"
3752 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3753 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3754 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3758 [(set (match_operand:SI 0 "register_operand" "")
3759 (match_operand:SI 1 "const_int_operand" ""))]
3760 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3761 [(set (match_dup 0) (match_dup 1))
3762 (set (match_dup 0) (neg:SI (match_dup 0)))]
3763 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3767 [(set (match_operand:SI 0 "register_operand" "")
3768 (match_operand:SI 1 "const_int_operand" ""))]
3769 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3770 [(set (match_dup 0) (match_dup 1))
3771 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3774 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3775 unsigned HOST_WIDE_INT mask = 0xff;
3778 for (i = 0; i < 25; i++)
3779 if ((val & (mask << i)) == val)
3782 /* Shouldn't happen, but we don't want to split if the shift is zero. */
3786 operands[1] = GEN_INT (val >> i);
3787 operands[2] = GEN_INT (i);
3791 ;; When generating pic, we need to load the symbol offset into a register.
3792 ;; So that the optimizer does not confuse this with a normal symbol load
3793 ;; we use an unspec. The offset will be loaded from a constant pool entry,
3794 ;; since that is the only type of relocation we can use.
3796 ;; The rather odd constraints on the following are to force reload to leave
3797 ;; the insn alone, and to force the minipool generation pass to then move
3798 ;; the GOT symbol to memory.
3800 (define_insn "pic_load_addr_arm"
3801 [(set (match_operand:SI 0 "s_register_operand" "=r")
3802 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3803 "TARGET_ARM && flag_pic"
3805 [(set_attr "type" "load")
3806 (set (attr "pool_range") (const_int 4096))
3807 (set (attr "neg_pool_range") (const_int 4084))]
3810 (define_insn "pic_load_addr_thumb"
3811 [(set (match_operand:SI 0 "s_register_operand" "=l")
3812 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3813 "TARGET_THUMB && flag_pic"
3815 [(set_attr "type" "load")
3816 (set (attr "pool_range") (const_int 1024))]
3819 ;; This variant is used for AOF assembly, since it needs to mention the
3820 ;; pic register in the rtl.
3821 (define_expand "pic_load_addr_based"
3822 [(set (match_operand:SI 0 "s_register_operand" "")
3823 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
3824 "TARGET_ARM && flag_pic"
3825 "operands[2] = pic_offset_table_rtx;"
3828 (define_insn "*pic_load_addr_based_insn"
3829 [(set (match_operand:SI 0 "s_register_operand" "=r")
3830 (unspec:SI [(match_operand 1 "" "")
3831 (match_operand 2 "s_register_operand" "r")]
3833 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
3835 #ifdef AOF_ASSEMBLER
3836 operands[1] = aof_pic_entry (operands[1]);
3838 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3841 [(set_attr "type" "load")
3842 (set (attr "pool_range")
3843 (if_then_else (eq_attr "is_thumb" "yes")
3846 (set (attr "neg_pool_range")
3847 (if_then_else (eq_attr "is_thumb" "yes")
3852 (define_insn "pic_add_dot_plus_four"
3853 [(set (match_operand:SI 0 "register_operand" "+r")
3854 (unspec:SI [(plus:SI (match_dup 0)
3855 (const (plus:SI (pc) (const_int 4))))]
3857 (use (label_ref (match_operand 1 "" "")))]
3858 "TARGET_THUMB && flag_pic"
3860 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3861 CODE_LABEL_NUMBER (operands[1]));
3862 return \"add\\t%0, %|pc\";
3864 [(set_attr "length" "2")]
3867 (define_insn "pic_add_dot_plus_eight"
3868 [(set (match_operand:SI 0 "register_operand" "+r")
3869 (unspec:SI [(plus:SI (match_dup 0)
3870 (const (plus:SI (pc) (const_int 8))))]
3872 (use (label_ref (match_operand 1 "" "")))]
3873 "TARGET_ARM && flag_pic"
3875 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3876 CODE_LABEL_NUMBER (operands[1]));
3877 return \"add%?\\t%0, %|pc, %0\";
3879 [(set_attr "predicable" "yes")]
3882 (define_expand "builtin_setjmp_receiver"
3883 [(label_ref (match_operand 0 "" ""))]
3887 arm_finalize_pic (0);
3891 ;; If copying one reg to another we can set the condition codes according to
3892 ;; its value. Such a move is common after a return from subroutine and the
3893 ;; result is being tested against zero.
3895 (define_insn "*movsi_compare0"
3896 [(set (reg:CC CC_REGNUM)
3897 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
3899 (set (match_operand:SI 0 "s_register_operand" "=r,r")
3904 sub%?s\\t%0, %1, #0"
3905 [(set_attr "conds" "set")]
3908 ;; Subroutine to store a half word from a register into memory.
3909 ;; Operand 0 is the source register (HImode)
3910 ;; Operand 1 is the destination address in a register (SImode)
3912 ;; In both this routine and the next, we must be careful not to spill
3913 ;; a memory address of reg+large_const into a separate PLUS insn, since this
3914 ;; can generate unrecognizable rtl.
3916 (define_expand "storehi"
3917 [;; store the low byte
3918 (set (match_operand 1 "" "") (match_dup 3))
3919 ;; extract the high byte
3921 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3922 ;; store the high byte
3923 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
3927 rtx op1 = operands[1];
3928 rtx addr = XEXP (op1, 0);
3929 enum rtx_code code = GET_CODE (addr);
3931 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3933 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
3935 operands[4] = adjust_address (op1, QImode, 1);
3936 operands[1] = adjust_address (operands[1], QImode, 0);
3937 operands[3] = gen_lowpart (QImode, operands[0]);
3938 operands[0] = gen_lowpart (SImode, operands[0]);
3939 operands[2] = gen_reg_rtx (SImode);
3943 (define_expand "storehi_bigend"
3944 [(set (match_dup 4) (match_dup 3))
3946 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3947 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 3))]
3951 rtx op1 = operands[1];
3952 rtx addr = XEXP (op1, 0);
3953 enum rtx_code code = GET_CODE (addr);
3955 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3957 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
3959 operands[4] = adjust_address (op1, QImode, 1);
3960 operands[1] = adjust_address (operands[1], QImode, 0);
3961 operands[3] = gen_lowpart (QImode, operands[0]);
3962 operands[0] = gen_lowpart (SImode, operands[0]);
3963 operands[2] = gen_reg_rtx (SImode);
3967 ;; Subroutine to store a half word integer constant into memory.
3968 (define_expand "storeinthi"
3969 [(set (match_operand 0 "" "")
3970 (subreg:QI (match_operand 1 "" "") 0))
3971 (set (match_dup 3) (match_dup 2))]
3975 HOST_WIDE_INT value = INTVAL (operands[1]);
3976 rtx addr = XEXP (operands[0], 0);
3977 rtx op0 = operands[0];
3978 enum rtx_code code = GET_CODE (addr);
3980 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
3982 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
3984 operands[1] = gen_reg_rtx (SImode);
3985 if (BYTES_BIG_ENDIAN)
3987 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
3988 if ((value & 255) == ((value >> 8) & 255))
3989 operands[2] = operands[1];
3992 operands[2] = gen_reg_rtx (SImode);
3993 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
3998 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
3999 if ((value & 255) == ((value >> 8) & 255))
4000 operands[2] = operands[1];
4003 operands[2] = gen_reg_rtx (SImode);
4004 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4008 operands[3] = adjust_address (op0, QImode, 1);
4009 operands[0] = adjust_address (operands[0], QImode, 0);
4010 operands[2] = gen_lowpart (QImode, operands[2]);
4014 (define_expand "storehi_single_op"
4015 [(set (match_operand:HI 0 "memory_operand" "")
4016 (match_operand:HI 1 "general_operand" ""))]
4017 "TARGET_ARM && arm_arch4"
4019 if (!s_register_operand (operands[1], HImode))
4020 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4024 (define_expand "movhi"
4025 [(set (match_operand:HI 0 "general_operand" "")
4026 (match_operand:HI 1 "general_operand" ""))]
4031 if (!no_new_pseudos)
4033 if (GET_CODE (operands[0]) == MEM)
4037 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4040 if (GET_CODE (operands[1]) == CONST_INT)
4041 emit_insn (gen_storeinthi (operands[0], operands[1]));
4044 if (GET_CODE (operands[1]) == MEM)
4045 operands[1] = force_reg (HImode, operands[1]);
4046 if (BYTES_BIG_ENDIAN)
4047 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4049 emit_insn (gen_storehi (operands[1], operands[0]));
4053 /* Sign extend a constant, and keep it in an SImode reg. */
4054 else if (GET_CODE (operands[1]) == CONST_INT)
4056 rtx reg = gen_reg_rtx (SImode);
4057 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4059 /* If the constant is already valid, leave it alone. */
4060 if (!const_ok_for_arm (val))
4062 /* If setting all the top bits will make the constant
4063 loadable in a single instruction, then set them.
4064 Otherwise, sign extend the number. */
4066 if (const_ok_for_arm (~(val | ~0xffff)))
4068 else if (val & 0x8000)
4072 emit_insn (gen_movsi (reg, GEN_INT (val)));
4073 operands[1] = gen_lowpart (HImode, reg);
4075 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4076 && GET_CODE (operands[1]) == MEM)
4078 rtx reg = gen_reg_rtx (SImode);
4080 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4081 operands[1] = gen_lowpart (HImode, reg);
4083 else if (!arm_arch4)
4085 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4086 for v4 and up architectures because LDRH instructions will
4087 be used to access the HI values, and these cannot generate
4088 unaligned word access faults in the MMU. */
4089 if (GET_CODE (operands[1]) == MEM)
4091 if (TARGET_MMU_TRAPS)
4094 rtx offset = const0_rtx;
4095 rtx reg = gen_reg_rtx (SImode);
4097 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4098 || (GET_CODE (base) == PLUS
4099 && (GET_CODE (offset = XEXP (base, 1))
4101 && ((INTVAL(offset) & 1) != 1)
4102 && GET_CODE (base = XEXP (base, 0)) == REG))
4103 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4105 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4108 new = gen_rtx_MEM (SImode,
4109 plus_constant (base, new_offset));
4110 MEM_COPY_ATTRIBUTES (new, operands[1]);
4111 emit_insn (gen_movsi (reg, new));
4112 if (((INTVAL (offset) & 2) != 0)
4113 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4115 rtx reg2 = gen_reg_rtx (SImode);
4117 emit_insn (gen_lshrsi3 (reg2, reg,
4123 emit_insn (gen_movhi_bytes (reg, operands[1]));
4125 operands[1] = gen_lowpart (HImode, reg);
4127 else if (BYTES_BIG_ENDIAN)
4130 rtx offset = const0_rtx;
4132 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4133 || (GET_CODE (base) == PLUS
4134 && (GET_CODE (offset = XEXP (base, 1))
4136 && GET_CODE (base = XEXP (base, 0)) == REG))
4137 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4139 rtx reg = gen_reg_rtx (SImode);
4142 if ((INTVAL (offset) & 2) == 2)
4144 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4145 new = gen_rtx_MEM (SImode,
4146 plus_constant (base,
4148 MEM_COPY_ATTRIBUTES (new, operands[1]);
4149 emit_insn (gen_movsi (reg, new));
4153 new = gen_rtx_MEM (SImode,
4154 XEXP (operands[1], 0));
4155 MEM_COPY_ATTRIBUTES (new, operands[1]);
4156 emit_insn (gen_rotated_loadsi (reg, new));
4159 operands[1] = gen_lowpart (HImode, reg);
4163 emit_insn (gen_movhi_bigend (operands[0],
4171 /* Handle loading a large integer during reload */
4172 else if (GET_CODE (operands[1]) == CONST_INT
4173 && !const_ok_for_arm (INTVAL (operands[1]))
4174 && !const_ok_for_arm (~INTVAL (operands[1])))
4176 /* Writing a constant to memory needs a scratch, which should
4177 be handled with SECONDARY_RELOADs. */
4178 if (GET_CODE (operands[0]) != REG)
4181 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4182 emit_insn (gen_movsi (operands[0], operands[1]));
4186 else /* TARGET_THUMB */
4188 if (!no_new_pseudos)
4190 if (GET_CODE (operands[0]) != REG)
4191 operands[1] = force_reg (HImode, operands[1]);
4193 /* ??? We shouldn't really get invalid addresses here, but this can
4194 happen if we are passed a SP (never OK for HImode/QImode) or
4195 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4196 HImode/QImode) relative address. */
4197 /* ??? This should perhaps be fixed elsewhere, for instance, in
4198 fixup_stack_1, by checking for other kinds of invalid addresses,
4199 e.g. a bare reference to a virtual register. This may confuse the
4200 alpha though, which must handle this case differently. */
4201 if (GET_CODE (operands[0]) == MEM
4202 && !memory_address_p (GET_MODE (operands[0]),
4203 XEXP (operands[0], 0)))
4205 = replace_equiv_address (operands[0],
4206 copy_to_reg (XEXP (operands[0], 0)));
4208 if (GET_CODE (operands[1]) == MEM
4209 && !memory_address_p (GET_MODE (operands[1]),
4210 XEXP (operands[1], 0)))
4212 = replace_equiv_address (operands[1],
4213 copy_to_reg (XEXP (operands[1], 0)));
4215 /* Handle loading a large integer during reload */
4216 else if (GET_CODE (operands[1]) == CONST_INT
4217 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4219 /* Writing a constant to memory needs a scratch, which should
4220 be handled with SECONDARY_RELOADs. */
4221 if (GET_CODE (operands[0]) != REG)
4224 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4225 emit_insn (gen_movsi (operands[0], operands[1]));
4232 (define_insn "*thumb_movhi_insn"
4233 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4234 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4236 && ( register_operand (operands[0], HImode)
4237 || register_operand (operands[1], HImode))"
4239 switch (which_alternative)
4241 case 0: return \"add %0, %1, #0\";
4242 case 2: return \"strh %1, %0\";
4243 case 3: return \"mov %0, %1\";
4244 case 4: return \"mov %0, %1\";
4245 case 5: return \"mov %0, %1\";
4248 /* The stack pointer can end up being taken as an index register.
4249 Catch this case here and deal with it. */
4250 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4251 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4252 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4255 ops[0] = operands[0];
4256 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4258 output_asm_insn (\"mov %0, %1\", ops);
4260 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4263 return \"ldrh %0, %1\";
4265 [(set_attr "length" "2,4,2,2,2,2")
4266 (set_attr "type" "*,load,store1,*,*,*")
4267 (set_attr "pool_range" "*,64,*,*,*,*")]
4271 (define_insn "rotated_loadsi"
4272 [(set (match_operand:SI 0 "s_register_operand" "=r")
4273 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4275 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4280 ops[0] = operands[0];
4281 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4282 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4285 [(set_attr "type" "load")
4286 (set_attr "predicable" "yes")]
4289 (define_expand "movhi_bytes"
4290 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4292 (zero_extend:SI (match_dup 6)))
4293 (set (match_operand:SI 0 "" "")
4294 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4299 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4301 mem1 = gen_rtx_MEM (QImode, addr);
4302 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4303 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4304 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4305 operands[0] = gen_lowpart (SImode, operands[0]);
4307 operands[2] = gen_reg_rtx (SImode);
4308 operands[3] = gen_reg_rtx (SImode);
4311 if (BYTES_BIG_ENDIAN)
4313 operands[4] = operands[2];
4314 operands[5] = operands[3];
4318 operands[4] = operands[3];
4319 operands[5] = operands[2];
4324 (define_expand "movhi_bigend"
4326 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4329 (ashiftrt:SI (match_dup 2) (const_int 16)))
4330 (set (match_operand:HI 0 "s_register_operand" "")
4331 (subreg:HI (match_dup 3) 0))]
4334 operands[2] = gen_reg_rtx (SImode);
4335 operands[3] = gen_reg_rtx (SImode);
4339 ;; Pattern to recognize insn generated default case above
4340 (define_insn "*movhi_insn_arch4"
4341 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4342 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4345 && (GET_CODE (operands[1]) != CONST_INT
4346 || const_ok_for_arm (INTVAL (operands[1]))
4347 || const_ok_for_arm (~INTVAL (operands[1])))"
4349 mov%?\\t%0, %1\\t%@ movhi
4350 mvn%?\\t%0, #%B1\\t%@ movhi
4351 str%?h\\t%1, %0\\t%@ movhi
4352 ldr%?h\\t%0, %1\\t%@ movhi"
4353 [(set_attr "type" "*,*,store1,load")
4354 (set_attr "predicable" "yes")
4355 (set_attr "pool_range" "*,*,*,256")
4356 (set_attr "neg_pool_range" "*,*,*,244")]
4359 (define_insn "*movhi_insn_littleend"
4360 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4361 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4364 && !BYTES_BIG_ENDIAN
4365 && !TARGET_MMU_TRAPS
4366 && (GET_CODE (operands[1]) != CONST_INT
4367 || const_ok_for_arm (INTVAL (operands[1]))
4368 || const_ok_for_arm (~INTVAL (operands[1])))"
4370 mov%?\\t%0, %1\\t%@ movhi
4371 mvn%?\\t%0, #%B1\\t%@ movhi
4372 ldr%?\\t%0, %1\\t%@ movhi"
4373 [(set_attr "type" "*,*,load")
4374 (set_attr "predicable" "yes")
4375 (set_attr "pool_range" "4096")
4376 (set_attr "neg_pool_range" "4084")]
4379 (define_insn "*movhi_insn_bigend"
4380 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4381 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4385 && !TARGET_MMU_TRAPS
4386 && (GET_CODE (operands[1]) != CONST_INT
4387 || const_ok_for_arm (INTVAL (operands[1]))
4388 || const_ok_for_arm (~INTVAL (operands[1])))"
4390 mov%?\\t%0, %1\\t%@ movhi
4391 mvn%?\\t%0, #%B1\\t%@ movhi
4392 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4393 [(set_attr "type" "*,*,load")
4394 (set_attr "predicable" "yes")
4395 (set_attr "length" "4,4,8")
4396 (set_attr "pool_range" "*,*,4092")
4397 (set_attr "neg_pool_range" "*,*,4084")]
4400 (define_insn "*loadhi_si_bigend"
4401 [(set (match_operand:SI 0 "s_register_operand" "=r")
4402 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4406 && !TARGET_MMU_TRAPS"
4407 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4408 [(set_attr "type" "load")
4409 (set_attr "predicable" "yes")
4410 (set_attr "pool_range" "4096")
4411 (set_attr "neg_pool_range" "4084")]
4414 (define_insn "*movhi_bytes"
4415 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4416 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4417 "TARGET_ARM && TARGET_MMU_TRAPS"
4419 mov%?\\t%0, %1\\t%@ movhi
4420 mvn%?\\t%0, #%B1\\t%@ movhi"
4421 [(set_attr "predicable" "yes")]
4424 (define_insn "thumb_movhi_clobber"
4425 [(set (match_operand:HI 0 "memory_operand" "=m")
4426 (match_operand:HI 1 "register_operand" "l"))
4427 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4433 ;; We use a DImode scratch because we may occasionally need an additional
4434 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4435 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4436 (define_expand "reload_outhi"
4437 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4438 (match_operand:HI 1 "s_register_operand" "r")
4439 (match_operand:DI 2 "s_register_operand" "=&l")])]
4442 arm_reload_out_hi (operands);
4444 thumb_reload_out_hi (operands);
4449 (define_expand "reload_inhi"
4450 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4451 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4452 (match_operand:DI 2 "s_register_operand" "=&r")])]
4453 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4456 arm_reload_in_hi (operands);
4458 thumb_reload_out_hi (operands);
4462 (define_expand "movqi"
4463 [(set (match_operand:QI 0 "general_operand" "")
4464 (match_operand:QI 1 "general_operand" ""))]
4469 /* Everything except mem = const or mem = mem can be done easily */
4471 if (!no_new_pseudos)
4473 if (GET_CODE (operands[1]) == CONST_INT)
4475 rtx reg = gen_reg_rtx (SImode);
4477 emit_insn (gen_movsi (reg, operands[1]));
4478 operands[1] = gen_lowpart (QImode, reg);
4480 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4482 rtx reg = gen_reg_rtx (SImode);
4484 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4485 operands[1] = gen_lowpart (QImode, reg);
4487 if (GET_CODE (operands[0]) == MEM)
4488 operands[1] = force_reg (QImode, operands[1]);
4491 else /* TARGET_THUMB */
4493 if (!no_new_pseudos)
4495 if (GET_CODE (operands[0]) != REG)
4496 operands[1] = force_reg (QImode, operands[1]);
4498 /* ??? We shouldn't really get invalid addresses here, but this can
4499 happen if we are passed a SP (never OK for HImode/QImode) or
4500 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4501 HImode/QImode) relative address. */
4502 /* ??? This should perhaps be fixed elsewhere, for instance, in
4503 fixup_stack_1, by checking for other kinds of invalid addresses,
4504 e.g. a bare reference to a virtual register. This may confuse the
4505 alpha though, which must handle this case differently. */
4506 if (GET_CODE (operands[0]) == MEM
4507 && !memory_address_p (GET_MODE (operands[0]),
4508 XEXP (operands[0], 0)))
4510 = replace_equiv_address (operands[0],
4511 copy_to_reg (XEXP (operands[0], 0)));
4512 if (GET_CODE (operands[1]) == MEM
4513 && !memory_address_p (GET_MODE (operands[1]),
4514 XEXP (operands[1], 0)))
4516 = replace_equiv_address (operands[1],
4517 copy_to_reg (XEXP (operands[1], 0)));
4519 /* Handle loading a large integer during reload */
4520 else if (GET_CODE (operands[1]) == CONST_INT
4521 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4523 /* Writing a constant to memory needs a scratch, which should
4524 be handled with SECONDARY_RELOADs. */
4525 if (GET_CODE (operands[0]) != REG)
4528 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4529 emit_insn (gen_movsi (operands[0], operands[1]));
4537 (define_insn "*arm_movqi_insn"
4538 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4539 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4541 && ( register_operand (operands[0], QImode)
4542 || register_operand (operands[1], QImode))"
4548 [(set_attr "type" "*,*,load,store1")
4549 (set_attr "predicable" "yes")]
4552 (define_insn "*thumb_movqi_insn"
4553 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4554 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4556 && ( register_operand (operands[0], QImode)
4557 || register_operand (operands[1], QImode))"
4565 [(set_attr "length" "2")
4566 (set_attr "type" "*,load,store1,*,*,*")
4567 (set_attr "pool_range" "*,32,*,*,*,*")]
4570 (define_expand "movsf"
4571 [(set (match_operand:SF 0 "general_operand" "")
4572 (match_operand:SF 1 "general_operand" ""))]
4577 if (GET_CODE (operands[0]) == MEM)
4578 operands[1] = force_reg (SFmode, operands[1]);
4580 else /* TARGET_THUMB */
4582 if (!no_new_pseudos)
4584 if (GET_CODE (operands[0]) != REG)
4585 operands[1] = force_reg (SFmode, operands[1]);
4592 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4593 (match_operand:SF 1 "immediate_operand" ""))]
4595 && !TARGET_HARD_FLOAT
4597 && GET_CODE (operands[1]) == CONST_DOUBLE"
4598 [(set (match_dup 2) (match_dup 3))]
4600 operands[2] = gen_lowpart (SImode, operands[0]);
4601 operands[3] = gen_lowpart (SImode, operands[1]);
4602 if (operands[2] == 0 || operands[3] == 0)
4607 (define_insn "*arm_movsf_soft_insn"
4608 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4609 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4612 && TARGET_SOFT_FLOAT
4613 && (GET_CODE (operands[0]) != MEM
4614 || register_operand (operands[1], SFmode))"
4617 ldr%?\\t%0, %1\\t%@ float
4618 str%?\\t%1, %0\\t%@ float"
4619 [(set_attr "length" "4,4,4")
4620 (set_attr "predicable" "yes")
4621 (set_attr "type" "*,load,store1")
4622 (set_attr "pool_range" "*,4096,*")
4623 (set_attr "neg_pool_range" "*,4084,*")]
4626 ;;; ??? This should have alternatives for constants.
4627 (define_insn "*thumb_movsf_insn"
4628 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4629 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4631 && ( register_operand (operands[0], SFmode)
4632 || register_operand (operands[1], SFmode))"
4641 [(set_attr "length" "2")
4642 (set_attr "type" "*,load,store1,load,store1,*,*")
4643 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4646 (define_expand "movdf"
4647 [(set (match_operand:DF 0 "general_operand" "")
4648 (match_operand:DF 1 "general_operand" ""))]
4653 if (GET_CODE (operands[0]) == MEM)
4654 operands[1] = force_reg (DFmode, operands[1]);
4656 else /* TARGET_THUMB */
4658 if (!no_new_pseudos)
4660 if (GET_CODE (operands[0]) != REG)
4661 operands[1] = force_reg (DFmode, operands[1]);
4667 ;; Reloading a df mode value stored in integer regs to memory can require a
4669 (define_expand "reload_outdf"
4670 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4671 (match_operand:DF 1 "s_register_operand" "r")
4672 (match_operand:SI 2 "s_register_operand" "=&r")]
4676 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4679 operands[2] = XEXP (operands[0], 0);
4680 else if (code == POST_INC || code == PRE_DEC)
4682 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4683 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4684 emit_insn (gen_movdi (operands[0], operands[1]));
4687 else if (code == PRE_INC)
4689 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4691 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4694 else if (code == POST_DEC)
4695 operands[2] = XEXP (XEXP (operands[0], 0), 0);
4697 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4698 XEXP (XEXP (operands[0], 0), 1)));
4700 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4703 if (code == POST_DEC)
4704 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4710 (define_insn "*movdf_soft_insn"
4711 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4712 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4713 "TARGET_ARM && TARGET_SOFT_FLOAT
4716 "* return output_move_double (operands);"
4717 [(set_attr "length" "8,8,8")
4718 (set_attr "type" "*,load,store2")
4719 (set_attr "pool_range" "1020")
4720 (set_attr "neg_pool_range" "1008")]
4723 ;;; ??? This should have alternatives for constants.
4724 ;;; ??? This was originally identical to the movdi_insn pattern.
4725 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4726 ;;; thumb_reorg with a memory reference.
4727 (define_insn "*thumb_movdf_insn"
4728 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4729 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
4731 && ( register_operand (operands[0], DFmode)
4732 || register_operand (operands[1], DFmode))"
4734 switch (which_alternative)
4738 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4739 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4740 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4742 return \"ldmia\\t%1, {%0, %H0}\";
4744 return \"stmia\\t%0, {%1, %H1}\";
4746 return thumb_load_double_from_address (operands);
4748 operands[2] = gen_rtx (MEM, SImode,
4749 plus_constant (XEXP (operands[0], 0), 4));
4750 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4753 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4754 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4755 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4758 [(set_attr "length" "4,2,2,6,4,4")
4759 (set_attr "type" "*,load,store2,load,store2,*")
4760 (set_attr "pool_range" "*,*,*,1020,*,*")]
4764 (define_expand "movv2si"
4765 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
4766 (match_operand:V2SI 1 "general_operand" ""))]
4767 "TARGET_REALLY_IWMMXT"
4771 (define_expand "movv4hi"
4772 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
4773 (match_operand:V4HI 1 "general_operand" ""))]
4774 "TARGET_REALLY_IWMMXT"
4778 (define_expand "movv8qi"
4779 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
4780 (match_operand:V8QI 1 "general_operand" ""))]
4781 "TARGET_REALLY_IWMMXT"
4786 ;; load- and store-multiple insns
4787 ;; The arm can load/store any set of registers, provided that they are in
4788 ;; ascending order; but that is beyond GCC so stick with what it knows.
4790 (define_expand "load_multiple"
4791 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4792 (match_operand:SI 1 "" ""))
4793 (use (match_operand:SI 2 "" ""))])]
4796 /* Support only fixed point registers. */
4797 if (GET_CODE (operands[2]) != CONST_INT
4798 || INTVAL (operands[2]) > 14
4799 || INTVAL (operands[2]) < 2
4800 || GET_CODE (operands[1]) != MEM
4801 || GET_CODE (operands[0]) != REG
4802 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
4803 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4807 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
4808 force_reg (SImode, XEXP (operands[1], 0)),
4809 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
4810 MEM_IN_STRUCT_P(operands[1]),
4811 MEM_SCALAR_P (operands[1]));
4815 ;; Load multiple with write-back
4817 (define_insn "*ldmsi_postinc4"
4818 [(match_parallel 0 "load_multiple_operation"
4819 [(set (match_operand:SI 1 "s_register_operand" "=r")
4820 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4822 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4823 (mem:SI (match_dup 2)))
4824 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4825 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4826 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4827 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
4828 (set (match_operand:SI 6 "arm_hard_register_operand" "")
4829 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
4830 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4831 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
4832 [(set_attr "type" "load")
4833 (set_attr "predicable" "yes")]
4836 (define_insn "*ldmsi_postinc3"
4837 [(match_parallel 0 "load_multiple_operation"
4838 [(set (match_operand:SI 1 "s_register_operand" "=r")
4839 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4841 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4842 (mem:SI (match_dup 2)))
4843 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4844 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4845 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4846 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
4847 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4848 "ldm%?ia\\t%1!, {%3, %4, %5}"
4849 [(set_attr "type" "load")
4850 (set_attr "predicable" "yes")]
4853 (define_insn "*ldmsi_postinc2"
4854 [(match_parallel 0 "load_multiple_operation"
4855 [(set (match_operand:SI 1 "s_register_operand" "=r")
4856 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4858 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4859 (mem:SI (match_dup 2)))
4860 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4861 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
4862 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4863 "ldm%?ia\\t%1!, {%3, %4}"
4864 [(set_attr "type" "load")
4865 (set_attr "predicable" "yes")]
4868 ;; Ordinary load multiple
4870 (define_insn "*ldmsi4"
4871 [(match_parallel 0 "load_multiple_operation"
4872 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4873 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4874 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4875 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4876 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4877 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4878 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4879 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
4880 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4881 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
4882 [(set_attr "type" "load")
4883 (set_attr "predicable" "yes")]
4886 (define_insn "*ldmsi3"
4887 [(match_parallel 0 "load_multiple_operation"
4888 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4889 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4890 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4891 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4892 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4893 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
4894 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4895 "ldm%?ia\\t%1, {%2, %3, %4}"
4896 [(set_attr "type" "load")
4897 (set_attr "predicable" "yes")]
4900 (define_insn "*ldmsi2"
4901 [(match_parallel 0 "load_multiple_operation"
4902 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4903 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4904 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4905 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
4906 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
4907 "ldm%?ia\\t%1, {%2, %3}"
4908 [(set_attr "type" "load")
4909 (set_attr "predicable" "yes")]
4912 (define_expand "store_multiple"
4913 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4914 (match_operand:SI 1 "" ""))
4915 (use (match_operand:SI 2 "" ""))])]
4918 /* Support only fixed point registers */
4919 if (GET_CODE (operands[2]) != CONST_INT
4920 || INTVAL (operands[2]) > 14
4921 || INTVAL (operands[2]) < 2
4922 || GET_CODE (operands[1]) != REG
4923 || GET_CODE (operands[0]) != MEM
4924 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
4925 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4929 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
4930 force_reg (SImode, XEXP (operands[0], 0)),
4931 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
4932 MEM_IN_STRUCT_P(operands[0]),
4933 MEM_SCALAR_P (operands[0]));
4937 ;; Store multiple with write-back
4939 (define_insn "*stmsi_postinc4"
4940 [(match_parallel 0 "store_multiple_operation"
4941 [(set (match_operand:SI 1 "s_register_operand" "=r")
4942 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4944 (set (mem:SI (match_dup 2))
4945 (match_operand:SI 3 "arm_hard_register_operand" ""))
4946 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4947 (match_operand:SI 4 "arm_hard_register_operand" ""))
4948 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
4949 (match_operand:SI 5 "arm_hard_register_operand" ""))
4950 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
4951 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
4952 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4953 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
4954 [(set_attr "predicable" "yes")
4955 (set_attr "type" "store4")]
4958 (define_insn "*stmsi_postinc3"
4959 [(match_parallel 0 "store_multiple_operation"
4960 [(set (match_operand:SI 1 "s_register_operand" "=r")
4961 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4963 (set (mem:SI (match_dup 2))
4964 (match_operand:SI 3 "arm_hard_register_operand" ""))
4965 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4966 (match_operand:SI 4 "arm_hard_register_operand" ""))
4967 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
4968 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
4969 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4970 "stm%?ia\\t%1!, {%3, %4, %5}"
4971 [(set_attr "predicable" "yes")
4972 (set_attr "type" "store3")]
4975 (define_insn "*stmsi_postinc2"
4976 [(match_parallel 0 "store_multiple_operation"
4977 [(set (match_operand:SI 1 "s_register_operand" "=r")
4978 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4980 (set (mem:SI (match_dup 2))
4981 (match_operand:SI 3 "arm_hard_register_operand" ""))
4982 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
4983 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
4984 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4985 "stm%?ia\\t%1!, {%3, %4}"
4986 [(set_attr "predicable" "yes")
4987 (set_attr "type" "store2")]
4990 ;; Ordinary store multiple
4992 (define_insn "*stmsi4"
4993 [(match_parallel 0 "store_multiple_operation"
4994 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4995 (match_operand:SI 2 "arm_hard_register_operand" ""))
4996 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
4997 (match_operand:SI 3 "arm_hard_register_operand" ""))
4998 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
4999 (match_operand:SI 4 "arm_hard_register_operand" ""))
5000 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5001 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5002 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5003 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5004 [(set_attr "predicable" "yes")
5005 (set_attr "type" "store4")]
5008 (define_insn "*stmsi3"
5009 [(match_parallel 0 "store_multiple_operation"
5010 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5011 (match_operand:SI 2 "arm_hard_register_operand" ""))
5012 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5013 (match_operand:SI 3 "arm_hard_register_operand" ""))
5014 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5015 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5016 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5017 "stm%?ia\\t%1, {%2, %3, %4}"
5018 [(set_attr "predicable" "yes")
5019 (set_attr "type" "store3")]
5022 (define_insn "*stmsi2"
5023 [(match_parallel 0 "store_multiple_operation"
5024 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5025 (match_operand:SI 2 "arm_hard_register_operand" ""))
5026 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5027 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5028 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5029 "stm%?ia\\t%1, {%2, %3}"
5030 [(set_attr "predicable" "yes")
5031 (set_attr "type" "store2")]
5034 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5035 ;; We could let this apply for blocks of less than this, but it clobbers so
5036 ;; many registers that there is then probably a better way.
5038 (define_expand "movstrqi"
5039 [(match_operand:BLK 0 "general_operand" "")
5040 (match_operand:BLK 1 "general_operand" "")
5041 (match_operand:SI 2 "const_int_operand" "")
5042 (match_operand:SI 3 "const_int_operand" "")]
5047 if (arm_gen_movstrqi (operands))
5051 else /* TARGET_THUMB */
5053 if ( INTVAL (operands[3]) != 4
5054 || INTVAL (operands[2]) > 48)
5057 thumb_expand_movstrqi (operands);
5063 ;; Thumb block-move insns
5065 (define_insn "movmem12b"
5066 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5067 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5068 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5069 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5070 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5071 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5072 (set (match_operand:SI 0 "register_operand" "=l")
5073 (plus:SI (match_dup 2) (const_int 12)))
5074 (set (match_operand:SI 1 "register_operand" "=l")
5075 (plus:SI (match_dup 3) (const_int 12)))
5076 (clobber (match_scratch:SI 4 "=&l"))
5077 (clobber (match_scratch:SI 5 "=&l"))
5078 (clobber (match_scratch:SI 6 "=&l"))]
5080 "* return thumb_output_move_mem_multiple (3, operands);"
5081 [(set_attr "length" "4")
5082 ; This isn't entirely accurate... It loads as well, but in terms of
5083 ; scheduling the following insn it is better to consider it as a store
5084 (set_attr "type" "store3")]
5087 (define_insn "movmem8b"
5088 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5089 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5090 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5091 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5092 (set (match_operand:SI 0 "register_operand" "=l")
5093 (plus:SI (match_dup 2) (const_int 8)))
5094 (set (match_operand:SI 1 "register_operand" "=l")
5095 (plus:SI (match_dup 3) (const_int 8)))
5096 (clobber (match_scratch:SI 4 "=&l"))
5097 (clobber (match_scratch:SI 5 "=&l"))]
5099 "* return thumb_output_move_mem_multiple (2, operands);"
5100 [(set_attr "length" "4")
5101 ; This isn't entirely accurate... It loads as well, but in terms of
5102 ; scheduling the following insn it is better to consider it as a store
5103 (set_attr "type" "store2")]
5108 ;; Compare & branch insns
5109 ;; The range calculations are based as follows:
5110 ;; For forward branches, the address calculation returns the address of
5111 ;; the next instruction. This is 2 beyond the branch instruction.
5112 ;; For backward branches, the address calculation returns the address of
5113 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5114 ;; instruction for the shortest sequence, and 4 before the branch instruction
5115 ;; if we have to jump around an unconditional branch.
5116 ;; To the basic branch range the PC offset must be added (this is +4).
5117 ;; So for forward branches we have
5118 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5119 ;; And for backward branches we have
5120 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5122 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5123 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5125 (define_insn "cbranchsi4"
5128 (match_operator 0 "arm_comparison_operator"
5129 [(match_operand:SI 1 "register_operand" "l,r")
5130 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5131 (label_ref (match_operand 3 "" ""))
5135 output_asm_insn (\"cmp\\t%1, %2\", operands);
5136 switch (get_attr_length (insn))
5138 case 4: return \"b%d0\\t%l3\";
5139 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5140 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5143 [(set (attr "far_jump")
5145 (eq_attr "length" "8")
5146 (const_string "yes")
5147 (const_string "no")))
5148 (set (attr "length")
5150 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5151 (le (minus (match_dup 3) (pc)) (const_int 256)))
5154 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5155 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5160 (define_insn "*negated_cbranchsi4"
5163 (match_operator 0 "arm_comparison_operator"
5164 [(match_operand:SI 1 "register_operand" "l")
5165 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5166 (label_ref (match_operand 3 "" ""))
5170 output_asm_insn (\"cmn\\t%1, %2\", operands);
5171 switch (get_attr_length (insn))
5173 case 4: return \"b%d0\\t%l3\";
5174 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5175 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5178 [(set (attr "far_jump")
5180 (eq_attr "length" "8")
5181 (const_string "yes")
5182 (const_string "no")))
5183 (set (attr "length")
5185 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5186 (le (minus (match_dup 3) (pc)) (const_int 256)))
5189 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5190 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5196 ;; Comparison and test insns
5198 (define_expand "cmpsi"
5199 [(match_operand:SI 0 "s_register_operand" "")
5200 (match_operand:SI 1 "arm_add_operand" "")]
5203 arm_compare_op0 = operands[0];
5204 arm_compare_op1 = operands[1];
5209 (define_expand "cmpsf"
5210 [(match_operand:SF 0 "s_register_operand" "")
5211 (match_operand:SF 1 "fpa_rhs_operand" "")]
5212 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5214 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
5215 operands[1] = force_reg (SFmode, operands[1]);
5217 arm_compare_op0 = operands[0];
5218 arm_compare_op1 = operands[1];
5223 (define_expand "cmpdf"
5224 [(match_operand:DF 0 "s_register_operand" "")
5225 (match_operand:DF 1 "fpa_rhs_operand" "")]
5226 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
5228 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
5229 operands[1] = force_reg (DFmode, operands[1]);
5231 arm_compare_op0 = operands[0];
5232 arm_compare_op1 = operands[1];
5237 (define_insn "*arm_cmpsi_insn"
5238 [(set (reg:CC CC_REGNUM)
5239 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5240 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5245 [(set_attr "conds" "set")]
5248 (define_insn "*cmpsi_shiftsi"
5249 [(set (reg:CC CC_REGNUM)
5250 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5251 (match_operator:SI 3 "shift_operator"
5252 [(match_operand:SI 1 "s_register_operand" "r")
5253 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5256 [(set_attr "conds" "set")
5257 (set_attr "shift" "1")
5261 (define_insn "*cmpsi_shiftsi_swp"
5262 [(set (reg:CC_SWP CC_REGNUM)
5263 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5264 [(match_operand:SI 1 "s_register_operand" "r")
5265 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5266 (match_operand:SI 0 "s_register_operand" "r")))]
5269 [(set_attr "conds" "set")
5270 (set_attr "shift" "1")
5274 (define_insn "*cmpsi_neg_shiftsi"
5275 [(set (reg:CC CC_REGNUM)
5276 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5277 (neg:SI (match_operator:SI 3 "shift_operator"
5278 [(match_operand:SI 1 "s_register_operand" "r")
5279 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5282 [(set_attr "conds" "set")
5283 (set_attr "shift" "1")
5287 ;; Cirrus SF compare instruction
5288 (define_insn "*cirrus_cmpsf"
5289 [(set (reg:CCFP CC_REGNUM)
5290 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
5291 (match_operand:SF 1 "cirrus_fp_register" "v")))]
5292 "TARGET_ARM && TARGET_CIRRUS"
5293 "cfcmps%?\\tr15, %V0, %V1"
5294 [(set_attr "type" "mav_farith")
5295 (set_attr "cirrus" "compare")]
5298 ;; Cirrus DF compare instruction
5299 (define_insn "*cirrus_cmpdf"
5300 [(set (reg:CCFP CC_REGNUM)
5301 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
5302 (match_operand:DF 1 "cirrus_fp_register" "v")))]
5303 "TARGET_ARM && TARGET_CIRRUS"
5304 "cfcmpd%?\\tr15, %V0, %V1"
5305 [(set_attr "type" "mav_farith")
5306 (set_attr "cirrus" "compare")]
5309 ;; Cirrus DI compare instruction
5310 (define_expand "cmpdi"
5311 [(match_operand:DI 0 "cirrus_fp_register" "")
5312 (match_operand:DI 1 "cirrus_fp_register" "")]
5313 "TARGET_ARM && TARGET_CIRRUS"
5315 arm_compare_op0 = operands[0];
5316 arm_compare_op1 = operands[1];
5320 (define_insn "*cirrus_cmpdi"
5321 [(set (reg:CC CC_REGNUM)
5322 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
5323 (match_operand:DI 1 "cirrus_fp_register" "v")))]
5324 "TARGET_ARM && TARGET_CIRRUS"
5325 "cfcmp64%?\\tr15, %V0, %V1"
5326 [(set_attr "type" "mav_farith")
5327 (set_attr "cirrus" "compare")]
5330 ; This insn allows redundant compares to be removed by cse, nothing should
5331 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5332 ; is deleted later on. The match_dup will match the mode here, so that
5333 ; mode changes of the condition codes aren't lost by this even though we don't
5334 ; specify what they are.
5336 (define_insn "*deleted_compare"
5337 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5339 "\\t%@ deleted compare"
5340 [(set_attr "conds" "set")
5341 (set_attr "length" "0")]
5345 ;; Conditional branch insns
5347 (define_expand "beq"
5349 (if_then_else (eq (match_dup 1) (const_int 0))
5350 (label_ref (match_operand 0 "" ""))
5353 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5356 (define_expand "bne"
5358 (if_then_else (ne (match_dup 1) (const_int 0))
5359 (label_ref (match_operand 0 "" ""))
5362 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5365 (define_expand "bgt"
5367 (if_then_else (gt (match_dup 1) (const_int 0))
5368 (label_ref (match_operand 0 "" ""))
5371 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5374 (define_expand "ble"
5376 (if_then_else (le (match_dup 1) (const_int 0))
5377 (label_ref (match_operand 0 "" ""))
5380 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5383 (define_expand "bge"
5385 (if_then_else (ge (match_dup 1) (const_int 0))
5386 (label_ref (match_operand 0 "" ""))
5389 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5392 (define_expand "blt"
5394 (if_then_else (lt (match_dup 1) (const_int 0))
5395 (label_ref (match_operand 0 "" ""))
5398 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5401 (define_expand "bgtu"
5403 (if_then_else (gtu (match_dup 1) (const_int 0))
5404 (label_ref (match_operand 0 "" ""))
5407 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5410 (define_expand "bleu"
5412 (if_then_else (leu (match_dup 1) (const_int 0))
5413 (label_ref (match_operand 0 "" ""))
5416 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5419 (define_expand "bgeu"
5421 (if_then_else (geu (match_dup 1) (const_int 0))
5422 (label_ref (match_operand 0 "" ""))
5425 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5428 (define_expand "bltu"
5430 (if_then_else (ltu (match_dup 1) (const_int 0))
5431 (label_ref (match_operand 0 "" ""))
5434 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5437 (define_expand "bunordered"
5439 (if_then_else (unordered (match_dup 1) (const_int 0))
5440 (label_ref (match_operand 0 "" ""))
5442 "TARGET_ARM && TARGET_HARD_FLOAT"
5443 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5447 (define_expand "bordered"
5449 (if_then_else (ordered (match_dup 1) (const_int 0))
5450 (label_ref (match_operand 0 "" ""))
5452 "TARGET_ARM && TARGET_HARD_FLOAT"
5453 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5457 (define_expand "bungt"
5459 (if_then_else (ungt (match_dup 1) (const_int 0))
5460 (label_ref (match_operand 0 "" ""))
5462 "TARGET_ARM && TARGET_HARD_FLOAT"
5463 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
5466 (define_expand "bunlt"
5468 (if_then_else (unlt (match_dup 1) (const_int 0))
5469 (label_ref (match_operand 0 "" ""))
5471 "TARGET_ARM && TARGET_HARD_FLOAT"
5472 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
5475 (define_expand "bunge"
5477 (if_then_else (unge (match_dup 1) (const_int 0))
5478 (label_ref (match_operand 0 "" ""))
5480 "TARGET_ARM && TARGET_HARD_FLOAT"
5481 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
5484 (define_expand "bunle"
5486 (if_then_else (unle (match_dup 1) (const_int 0))
5487 (label_ref (match_operand 0 "" ""))
5489 "TARGET_ARM && TARGET_HARD_FLOAT"
5490 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
5493 ;; The following two patterns need two branch instructions, since there is
5494 ;; no single instruction that will handle all cases.
5495 (define_expand "buneq"
5497 (if_then_else (uneq (match_dup 1) (const_int 0))
5498 (label_ref (match_operand 0 "" ""))
5500 "TARGET_ARM && TARGET_HARD_FLOAT"
5501 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
5504 (define_expand "bltgt"
5506 (if_then_else (ltgt (match_dup 1) (const_int 0))
5507 (label_ref (match_operand 0 "" ""))
5509 "TARGET_ARM && TARGET_HARD_FLOAT"
5510 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
5514 ;; Patterns to match conditional branch insns.
5517 ; Special pattern to match UNEQ.
5518 (define_insn "*arm_buneq"
5520 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5521 (label_ref (match_operand 0 "" ""))
5523 "TARGET_ARM && TARGET_HARD_FLOAT"
5525 if (arm_ccfsm_state != 0)
5528 return \"bvs\\t%l0\;beq\\t%l0\";
5530 [(set_attr "conds" "jump_clob")
5531 (set_attr "length" "8")]
5534 ; Special pattern to match LTGT.
5535 (define_insn "*arm_bltgt"
5537 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5538 (label_ref (match_operand 0 "" ""))
5540 "TARGET_ARM && TARGET_HARD_FLOAT"
5542 if (arm_ccfsm_state != 0)
5545 return \"bmi\\t%l0\;bgt\\t%l0\";
5547 [(set_attr "conds" "jump_clob")
5548 (set_attr "length" "8")]
5551 (define_insn "*arm_cond_branch"
5553 (if_then_else (match_operator 1 "arm_comparison_operator"
5554 [(match_operand 2 "cc_register" "") (const_int 0)])
5555 (label_ref (match_operand 0 "" ""))
5559 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5561 arm_ccfsm_state += 2;
5564 return \"b%d1\\t%l0\";
5566 [(set_attr "conds" "use")]
5569 ; Special pattern to match reversed UNEQ.
5570 (define_insn "*arm_buneq_reversed"
5572 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
5574 (label_ref (match_operand 0 "" ""))))]
5575 "TARGET_ARM && TARGET_HARD_FLOAT"
5577 if (arm_ccfsm_state != 0)
5580 return \"bmi\\t%l0\;bgt\\t%l0\";
5582 [(set_attr "conds" "jump_clob")
5583 (set_attr "length" "8")]
5586 ; Special pattern to match reversed LTGT.
5587 (define_insn "*arm_bltgt_reversed"
5589 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
5591 (label_ref (match_operand 0 "" ""))))]
5592 "TARGET_ARM && TARGET_HARD_FLOAT"
5594 if (arm_ccfsm_state != 0)
5597 return \"bvs\\t%l0\;beq\\t%l0\";
5599 [(set_attr "conds" "jump_clob")
5600 (set_attr "length" "8")]
5603 (define_insn "*arm_cond_branch_reversed"
5605 (if_then_else (match_operator 1 "arm_comparison_operator"
5606 [(match_operand 2 "cc_register" "") (const_int 0)])
5608 (label_ref (match_operand 0 "" ""))))]
5611 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5613 arm_ccfsm_state += 2;
5616 return \"b%D1\\t%l0\";
5618 [(set_attr "conds" "use")]
5625 (define_expand "seq"
5626 [(set (match_operand:SI 0 "s_register_operand" "")
5627 (eq:SI (match_dup 1) (const_int 0)))]
5629 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5632 (define_expand "sne"
5633 [(set (match_operand:SI 0 "s_register_operand" "")
5634 (ne:SI (match_dup 1) (const_int 0)))]
5636 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5639 (define_expand "sgt"
5640 [(set (match_operand:SI 0 "s_register_operand" "")
5641 (gt:SI (match_dup 1) (const_int 0)))]
5643 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5646 (define_expand "sle"
5647 [(set (match_operand:SI 0 "s_register_operand" "")
5648 (le:SI (match_dup 1) (const_int 0)))]
5650 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5653 (define_expand "sge"
5654 [(set (match_operand:SI 0 "s_register_operand" "")
5655 (ge:SI (match_dup 1) (const_int 0)))]
5657 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5660 (define_expand "slt"
5661 [(set (match_operand:SI 0 "s_register_operand" "")
5662 (lt:SI (match_dup 1) (const_int 0)))]
5664 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5667 (define_expand "sgtu"
5668 [(set (match_operand:SI 0 "s_register_operand" "")
5669 (gtu:SI (match_dup 1) (const_int 0)))]
5671 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5674 (define_expand "sleu"
5675 [(set (match_operand:SI 0 "s_register_operand" "")
5676 (leu:SI (match_dup 1) (const_int 0)))]
5678 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5681 (define_expand "sgeu"
5682 [(set (match_operand:SI 0 "s_register_operand" "")
5683 (geu:SI (match_dup 1) (const_int 0)))]
5685 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5688 (define_expand "sltu"
5689 [(set (match_operand:SI 0 "s_register_operand" "")
5690 (ltu:SI (match_dup 1) (const_int 0)))]
5692 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5695 (define_expand "sunordered"
5696 [(set (match_operand:SI 0 "s_register_operand" "")
5697 (unordered:SI (match_dup 1) (const_int 0)))]
5698 "TARGET_ARM && TARGET_HARD_FLOAT"
5699 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
5703 (define_expand "sordered"
5704 [(set (match_operand:SI 0 "s_register_operand" "")
5705 (ordered:SI (match_dup 1) (const_int 0)))]
5706 "TARGET_ARM && TARGET_HARD_FLOAT"
5707 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
5711 (define_expand "sungt"
5712 [(set (match_operand:SI 0 "s_register_operand" "")
5713 (ungt:SI (match_dup 1) (const_int 0)))]
5714 "TARGET_ARM && TARGET_HARD_FLOAT"
5715 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
5719 (define_expand "sunge"
5720 [(set (match_operand:SI 0 "s_register_operand" "")
5721 (unge:SI (match_dup 1) (const_int 0)))]
5722 "TARGET_ARM && TARGET_HARD_FLOAT"
5723 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
5727 (define_expand "sunlt"
5728 [(set (match_operand:SI 0 "s_register_operand" "")
5729 (unlt:SI (match_dup 1) (const_int 0)))]
5730 "TARGET_ARM && TARGET_HARD_FLOAT"
5731 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
5735 (define_expand "sunle"
5736 [(set (match_operand:SI 0 "s_register_operand" "")
5737 (unle:SI (match_dup 1) (const_int 0)))]
5738 "TARGET_ARM && TARGET_HARD_FLOAT"
5739 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
5743 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
5744 ;;; simple ARM instructions.
5746 ; (define_expand "suneq"
5747 ; [(set (match_operand:SI 0 "s_register_operand" "")
5748 ; (uneq:SI (match_dup 1) (const_int 0)))]
5749 ; "TARGET_ARM && TARGET_HARD_FLOAT"
5753 ; (define_expand "sltgt"
5754 ; [(set (match_operand:SI 0 "s_register_operand" "")
5755 ; (ltgt:SI (match_dup 1) (const_int 0)))]
5756 ; "TARGET_ARM && TARGET_HARD_FLOAT"
5760 (define_insn "*mov_scc"
5761 [(set (match_operand:SI 0 "s_register_operand" "=r")
5762 (match_operator:SI 1 "arm_comparison_operator"
5763 [(match_operand 2 "cc_register" "") (const_int 0)]))]
5765 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
5766 [(set_attr "conds" "use")
5767 (set_attr "length" "8")]
5770 (define_insn "*mov_negscc"
5771 [(set (match_operand:SI 0 "s_register_operand" "=r")
5772 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
5773 [(match_operand 2 "cc_register" "") (const_int 0)])))]
5775 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
5776 [(set_attr "conds" "use")
5777 (set_attr "length" "8")]
5780 (define_insn "*mov_notscc"
5781 [(set (match_operand:SI 0 "s_register_operand" "=r")
5782 (not:SI (match_operator:SI 1 "arm_comparison_operator"
5783 [(match_operand 2 "cc_register" "") (const_int 0)])))]
5785 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
5786 [(set_attr "conds" "use")
5787 (set_attr "length" "8")]
5791 ;; Conditional move insns
5793 (define_expand "movsicc"
5794 [(set (match_operand:SI 0 "s_register_operand" "")
5795 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
5796 (match_operand:SI 2 "arm_not_operand" "")
5797 (match_operand:SI 3 "arm_not_operand" "")))]
5801 enum rtx_code code = GET_CODE (operands[1]);
5804 if (code == UNEQ || code == LTGT)
5807 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5808 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5812 (define_expand "movsfcc"
5813 [(set (match_operand:SF 0 "s_register_operand" "")
5814 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
5815 (match_operand:SF 2 "s_register_operand" "")
5816 (match_operand:SF 3 "nonmemory_operand" "")))]
5820 enum rtx_code code = GET_CODE (operands[1]);
5823 if (code == UNEQ || code == LTGT)
5826 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
5827 Otherwise, ensure it is a valid FP add operand */
5828 if ((!TARGET_HARD_FLOAT)
5829 || (!fpa_add_operand (operands[3], SFmode)))
5830 operands[3] = force_reg (SFmode, operands[3]);
5832 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5833 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5837 (define_expand "movdfcc"
5838 [(set (match_operand:DF 0 "s_register_operand" "")
5839 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
5840 (match_operand:DF 2 "s_register_operand" "")
5841 (match_operand:DF 3 "fpa_add_operand" "")))]
5842 "TARGET_ARM && TARGET_HARD_FLOAT"
5845 enum rtx_code code = GET_CODE (operands[1]);
5848 if (code == UNEQ || code == LTGT)
5851 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5852 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5856 (define_insn "*movsicc_insn"
5857 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
5859 (match_operator 3 "arm_comparison_operator"
5860 [(match_operand 4 "cc_register" "") (const_int 0)])
5861 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
5862 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
5869 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
5870 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
5871 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
5872 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
5873 [(set_attr "length" "4,4,4,4,8,8,8,8")
5874 (set_attr "conds" "use")]
5877 (define_insn "*movsfcc_soft_insn"
5878 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
5879 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
5880 [(match_operand 4 "cc_register" "") (const_int 0)])
5881 (match_operand:SF 1 "s_register_operand" "0,r")
5882 (match_operand:SF 2 "s_register_operand" "r,0")))]
5883 "TARGET_ARM && TARGET_SOFT_FLOAT"
5887 [(set_attr "conds" "use")]
5891 ;; Jump and linkage insns
5893 (define_expand "jump"
5895 (label_ref (match_operand 0 "" "")))]
5900 (define_insn "*arm_jump"
5902 (label_ref (match_operand 0 "" "")))]
5906 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5908 arm_ccfsm_state += 2;
5911 return \"b%?\\t%l0\";
5914 [(set_attr "predicable" "yes")]
5917 (define_insn "*thumb_jump"
5919 (label_ref (match_operand 0 "" "")))]
5922 if (get_attr_length (insn) == 2)
5924 return \"bl\\t%l0\\t%@ far jump\";
5926 [(set (attr "far_jump")
5928 (eq_attr "length" "4")
5929 (const_string "yes")
5930 (const_string "no")))
5931 (set (attr "length")
5933 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
5934 (le (minus (match_dup 0) (pc)) (const_int 2044)))
5939 (define_expand "call"
5940 [(parallel [(call (match_operand 0 "memory_operand" "")
5941 (match_operand 1 "general_operand" ""))
5942 (use (match_operand 2 "" ""))
5943 (clobber (reg:SI LR_REGNUM))])]
5949 /* In an untyped call, we can get NULL for operand 2. */
5950 if (operands[2] == NULL_RTX)
5951 operands[2] = const0_rtx;
5953 /* This is to decide if we should generate indirect calls by loading the
5954 32 bit address of the callee into a register before performing the
5955 branch and link. operand[2] encodes the long_call/short_call
5956 attribute of the function being called. This attribute is set whenever
5957 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
5958 is used, and the short_call attribute can also be set if function is
5959 declared as static or if it has already been defined in the current
5960 compilation unit. See arm.c and arm.h for info about this. The third
5961 parameter to arm_is_longcall_p is used to tell it which pattern
5963 callee = XEXP (operands[0], 0);
5965 if (GET_CODE (callee) != REG
5966 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
5967 XEXP (operands[0], 0) = force_reg (Pmode, callee);
5971 (define_insn "*call_reg"
5972 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
5973 (match_operand 1 "" ""))
5974 (use (match_operand 2 "" ""))
5975 (clobber (reg:SI LR_REGNUM))]
5978 return output_call (operands);
5980 ;; length is worst case, normally it is only two
5981 [(set_attr "length" "12")
5982 (set_attr "type" "call")]
5985 (define_insn "*call_mem"
5986 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
5987 (match_operand 1 "" ""))
5988 (use (match_operand 2 "" ""))
5989 (clobber (reg:SI LR_REGNUM))]
5992 return output_call_mem (operands);
5994 [(set_attr "length" "12")
5995 (set_attr "type" "call")]
5998 (define_insn "*call_indirect"
5999 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
6000 (match_operand 1 "" ""))
6001 (use (match_operand 2 "" ""))
6002 (clobber (reg:SI LR_REGNUM))]
6006 if (TARGET_CALLER_INTERWORKING)
6007 return \"bl\\t%__interwork_call_via_%0\";
6009 return \"bl\\t%__call_via_%0\";
6011 [(set_attr "type" "call")]
6014 (define_insn "*call_value_indirect"
6015 [(set (match_operand 0 "" "")
6016 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
6017 (match_operand 2 "" "")))
6018 (use (match_operand 3 "" ""))
6019 (clobber (reg:SI LR_REGNUM))]
6023 if (TARGET_CALLER_INTERWORKING)
6024 return \"bl\\t%__interwork_call_via_%1\";
6026 return \"bl\\t%__call_via_%1\";
6028 [(set_attr "type" "call")]
6031 (define_expand "call_value"
6032 [(parallel [(set (match_operand 0 "" "")
6033 (call (match_operand 1 "memory_operand" "")
6034 (match_operand 2 "general_operand" "")))
6035 (use (match_operand 3 "" ""))
6036 (clobber (reg:SI LR_REGNUM))])]
6040 rtx callee = XEXP (operands[1], 0);
6042 /* In an untyped call, we can get NULL for operand 2. */
6043 if (operands[3] == 0)
6044 operands[3] = const0_rtx;
6046 /* See the comment in define_expand \"call\". */
6047 if (GET_CODE (callee) != REG
6048 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
6049 XEXP (operands[1], 0) = force_reg (Pmode, callee);
6053 (define_insn "*call_value_reg"
6054 [(set (match_operand 0 "" "")
6055 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
6056 (match_operand 2 "" "")))
6057 (use (match_operand 3 "" ""))
6058 (clobber (reg:SI LR_REGNUM))]
6061 return output_call (&operands[1]);
6063 [(set_attr "length" "12")
6064 (set_attr "type" "call")]
6067 (define_insn "*call_value_mem"
6068 [(set (match_operand 0 "" "")
6069 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
6070 (match_operand 2 "" "")))
6071 (use (match_operand 3 "" ""))
6072 (clobber (reg:SI LR_REGNUM))]
6073 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
6075 return output_call_mem (&operands[1]);
6077 [(set_attr "length" "12")
6078 (set_attr "type" "call")]
6081 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
6082 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6084 (define_insn "*call_symbol"
6085 [(call (mem:SI (match_operand:SI 0 "" ""))
6086 (match_operand 1 "" ""))
6087 (use (match_operand 2 "" ""))
6088 (clobber (reg:SI LR_REGNUM))]
6090 && (GET_CODE (operands[0]) == SYMBOL_REF)
6091 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6094 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6096 [(set_attr "type" "call")]
6099 (define_insn "*call_value_symbol"
6100 [(set (match_operand 0 "s_register_operand" "")
6101 (call (mem:SI (match_operand:SI 1 "" ""))
6102 (match_operand:SI 2 "" "")))
6103 (use (match_operand 3 "" ""))
6104 (clobber (reg:SI LR_REGNUM))]
6106 && (GET_CODE (operands[1]) == SYMBOL_REF)
6107 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6110 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6112 [(set_attr "type" "call")]
6115 (define_insn "*call_insn"
6116 [(call (mem:SI (match_operand:SI 0 "" ""))
6117 (match_operand:SI 1 "" ""))
6118 (use (match_operand 2 "" ""))
6119 (clobber (reg:SI LR_REGNUM))]
6121 && GET_CODE (operands[0]) == SYMBOL_REF
6122 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6124 [(set_attr "length" "4")
6125 (set_attr "type" "call")]
6128 (define_insn "*call_value_insn"
6129 [(set (match_operand 0 "register_operand" "")
6130 (call (mem:SI (match_operand 1 "" ""))
6131 (match_operand 2 "" "")))
6132 (use (match_operand 3 "" ""))
6133 (clobber (reg:SI LR_REGNUM))]
6135 && GET_CODE (operands[1]) == SYMBOL_REF
6136 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6138 [(set_attr "length" "4")
6139 (set_attr "type" "call")]
6142 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
6143 (define_expand "sibcall"
6144 [(parallel [(call (match_operand 0 "memory_operand" "")
6145 (match_operand 1 "general_operand" ""))
6147 (use (match_operand 2 "" ""))])]
6151 if (operands[2] == NULL_RTX)
6152 operands[2] = const0_rtx;
6156 (define_expand "sibcall_value"
6157 [(parallel [(set (match_operand 0 "register_operand" "")
6158 (call (match_operand 1 "memory_operand" "")
6159 (match_operand 2 "general_operand" "")))
6161 (use (match_operand 3 "" ""))])]
6165 if (operands[3] == NULL_RTX)
6166 operands[3] = const0_rtx;
6170 (define_insn "*sibcall_insn"
6171 [(call (mem:SI (match_operand:SI 0 "" "X"))
6172 (match_operand 1 "" ""))
6174 (use (match_operand 2 "" ""))]
6175 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
6177 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
6179 [(set_attr "type" "call")]
6182 (define_insn "*sibcall_value_insn"
6183 [(set (match_operand 0 "s_register_operand" "")
6184 (call (mem:SI (match_operand:SI 1 "" "X"))
6185 (match_operand 2 "" "")))
6187 (use (match_operand 3 "" ""))]
6188 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
6190 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
6192 [(set_attr "type" "call")]
6195 ;; Often the return insn will be the same as loading from memory, so set attr
6196 (define_insn "return"
6198 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6201 if (arm_ccfsm_state == 2)
6203 arm_ccfsm_state += 2;
6206 return output_return_instruction (const_true_rtx, TRUE, FALSE);
6208 [(set_attr "type" "load")
6209 (set_attr "length" "12")
6210 (set_attr "predicable" "yes")]
6213 (define_insn "*cond_return"
6215 (if_then_else (match_operator 0 "arm_comparison_operator"
6216 [(match_operand 1 "cc_register" "") (const_int 0)])
6219 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6222 if (arm_ccfsm_state == 2)
6224 arm_ccfsm_state += 2;
6227 return output_return_instruction (operands[0], TRUE, FALSE);
6229 [(set_attr "conds" "use")
6230 (set_attr "length" "12")
6231 (set_attr "type" "load")]
6234 (define_insn "*cond_return_inverted"
6236 (if_then_else (match_operator 0 "arm_comparison_operator"
6237 [(match_operand 1 "cc_register" "") (const_int 0)])
6240 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6243 if (arm_ccfsm_state == 2)
6245 arm_ccfsm_state += 2;
6248 return output_return_instruction (operands[0], TRUE, TRUE);
6250 [(set_attr "conds" "use")
6251 (set_attr "type" "load")]
6254 ;; Generate a sequence of instructions to determine if the processor is
6255 ;; in 26-bit or 32-bit mode, and return the appropriate return address
6258 (define_expand "return_addr_mask"
6260 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6262 (set (match_operand:SI 0 "s_register_operand" "")
6263 (if_then_else:SI (eq (match_dup 1) (const_int 0))
6265 (const_int 67108860)))] ; 0x03fffffc
6268 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
6271 (define_insn "*check_arch2"
6272 [(set (match_operand:CC_NOOV 0 "cc_register" "")
6273 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
6276 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
6277 [(set_attr "length" "8")
6278 (set_attr "conds" "set")]
6281 ;; Call subroutine returning any type.
6283 (define_expand "untyped_call"
6284 [(parallel [(call (match_operand 0 "" "")
6286 (match_operand 1 "" "")
6287 (match_operand 2 "" "")])]
6293 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
6295 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6297 rtx set = XVECEXP (operands[2], 0, i);
6299 emit_move_insn (SET_DEST (set), SET_SRC (set));
6302 /* The optimizer does not know that the call sets the function value
6303 registers we stored in the result block. We avoid problems by
6304 claiming that all hard registers are used and clobbered at this
6306 emit_insn (gen_blockage ());
6312 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6313 ;; all of memory. This blocks insns from being moved across this point.
6315 (define_insn "blockage"
6316 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
6319 [(set_attr "length" "0")
6320 (set_attr "type" "block")]
6323 (define_expand "casesi"
6324 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6325 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6326 (match_operand:SI 2 "const_int_operand" "") ; total range
6327 (match_operand:SI 3 "" "") ; table label
6328 (match_operand:SI 4 "" "")] ; Out of range label
6333 if (operands[1] != const0_rtx)
6335 reg = gen_reg_rtx (SImode);
6337 emit_insn (gen_addsi3 (reg, operands[0],
6338 GEN_INT (-INTVAL (operands[1]))));
6342 if (!const_ok_for_arm (INTVAL (operands[2])))
6343 operands[2] = force_reg (SImode, operands[2]);
6345 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6351 ;; The USE in this pattern is needed to tell flow analysis that this is
6352 ;; a CASESI insn. It has no other purpose.
6353 (define_insn "casesi_internal"
6354 [(parallel [(set (pc)
6356 (leu (match_operand:SI 0 "s_register_operand" "r")
6357 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6358 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6359 (label_ref (match_operand 2 "" ""))))
6360 (label_ref (match_operand 3 "" ""))))
6361 (clobber (reg:CC CC_REGNUM))
6362 (use (label_ref (match_dup 2)))])]
6366 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6367 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6369 [(set_attr "conds" "clob")
6370 (set_attr "length" "12")]
6373 (define_expand "indirect_jump"
6375 (match_operand:SI 0 "s_register_operand" ""))]
6380 (define_insn "*arm_indirect_jump"
6382 (match_operand:SI 0 "s_register_operand" "r"))]
6384 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6385 [(set_attr "predicable" "yes")]
6388 ;; Although not supported by the define_expand above,
6389 ;; cse/combine may generate this form.
6390 (define_insn "*load_indirect_jump"
6392 (match_operand:SI 0 "memory_operand" "m"))]
6394 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6395 [(set_attr "type" "load")
6396 (set_attr "pool_range" "4096")
6397 (set_attr "neg_pool_range" "4084")
6398 (set_attr "predicable" "yes")]
6401 (define_insn "*thumb_indirect_jump"
6403 (match_operand:SI 0 "register_operand" "l*r"))]
6406 [(set_attr "conds" "clob")
6407 (set_attr "length" "2")]
6418 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6419 return \"mov\\tr8, r8\";
6421 [(set (attr "length")
6422 (if_then_else (eq_attr "is_thumb" "yes")
6428 ;; Patterns to allow combination of arithmetic, cond code and shifts
6430 (define_insn "*arith_shiftsi"
6431 [(set (match_operand:SI 0 "s_register_operand" "=r")
6432 (match_operator:SI 1 "shiftable_operator"
6433 [(match_operator:SI 3 "shift_operator"
6434 [(match_operand:SI 4 "s_register_operand" "r")
6435 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6436 (match_operand:SI 2 "s_register_operand" "r")]))]
6438 "%i1%?\\t%0, %2, %4%S3"
6439 [(set_attr "predicable" "yes")
6440 (set_attr "shift" "4")
6444 (define_insn "*arith_shiftsi_compare0"
6445 [(set (reg:CC_NOOV CC_REGNUM)
6446 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6447 [(match_operator:SI 3 "shift_operator"
6448 [(match_operand:SI 4 "s_register_operand" "r")
6449 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6450 (match_operand:SI 2 "s_register_operand" "r")])
6452 (set (match_operand:SI 0 "s_register_operand" "=r")
6453 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6456 "%i1%?s\\t%0, %2, %4%S3"
6457 [(set_attr "conds" "set")
6458 (set_attr "shift" "4")
6462 (define_insn "*arith_shiftsi_compare0_scratch"
6463 [(set (reg:CC_NOOV CC_REGNUM)
6464 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6465 [(match_operator:SI 3 "shift_operator"
6466 [(match_operand:SI 4 "s_register_operand" "r")
6467 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6468 (match_operand:SI 2 "s_register_operand" "r")])
6470 (clobber (match_scratch:SI 0 "=r"))]
6472 "%i1%?s\\t%0, %2, %4%S3"
6473 [(set_attr "conds" "set")
6474 (set_attr "shift" "4")
6478 (define_insn "*sub_shiftsi"
6479 [(set (match_operand:SI 0 "s_register_operand" "=r")
6480 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6481 (match_operator:SI 2 "shift_operator"
6482 [(match_operand:SI 3 "s_register_operand" "r")
6483 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6485 "sub%?\\t%0, %1, %3%S2"
6486 [(set_attr "predicable" "yes")
6487 (set_attr "shift" "3")
6491 (define_insn "*sub_shiftsi_compare0"
6492 [(set (reg:CC_NOOV CC_REGNUM)
6494 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6495 (match_operator:SI 2 "shift_operator"
6496 [(match_operand:SI 3 "s_register_operand" "r")
6497 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6499 (set (match_operand:SI 0 "s_register_operand" "=r")
6500 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6503 "sub%?s\\t%0, %1, %3%S2"
6504 [(set_attr "conds" "set")
6505 (set_attr "shift" "3")
6509 (define_insn "*sub_shiftsi_compare0_scratch"
6510 [(set (reg:CC_NOOV CC_REGNUM)
6512 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6513 (match_operator:SI 2 "shift_operator"
6514 [(match_operand:SI 3 "s_register_operand" "r")
6515 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6517 (clobber (match_scratch:SI 0 "=r"))]
6519 "sub%?s\\t%0, %1, %3%S2"
6520 [(set_attr "conds" "set")
6521 (set_attr "shift" "3")
6527 (define_insn "*and_scc"
6528 [(set (match_operand:SI 0 "s_register_operand" "=r")
6529 (and:SI (match_operator:SI 1 "arm_comparison_operator"
6530 [(match_operand 3 "cc_register" "") (const_int 0)])
6531 (match_operand:SI 2 "s_register_operand" "r")))]
6533 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6534 [(set_attr "conds" "use")
6535 (set_attr "length" "8")]
6538 (define_insn "*ior_scc"
6539 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6540 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
6541 [(match_operand 3 "cc_register" "") (const_int 0)])
6542 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6546 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6547 [(set_attr "conds" "use")
6548 (set_attr "length" "4,8")]
6551 (define_insn "*compare_scc"
6552 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6553 (match_operator:SI 1 "arm_comparison_operator"
6554 [(match_operand:SI 2 "s_register_operand" "r,r")
6555 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6556 (clobber (reg:CC CC_REGNUM))]
6559 if (operands[3] == const0_rtx)
6561 if (GET_CODE (operands[1]) == LT)
6562 return \"mov\\t%0, %2, lsr #31\";
6564 if (GET_CODE (operands[1]) == GE)
6565 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6567 if (GET_CODE (operands[1]) == EQ)
6568 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
6571 if (GET_CODE (operands[1]) == NE)
6573 if (which_alternative == 1)
6574 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
6575 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
6577 if (which_alternative == 1)
6578 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6580 output_asm_insn (\"cmp\\t%2, %3\", operands);
6581 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
6583 [(set_attr "conds" "clob")
6584 (set_attr "length" "12")]
6587 (define_insn "*cond_move"
6588 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6589 (if_then_else:SI (match_operator 3 "equality_operator"
6590 [(match_operator 4 "arm_comparison_operator"
6591 [(match_operand 5 "cc_register" "") (const_int 0)])
6593 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6594 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
6597 if (GET_CODE (operands[3]) == NE)
6599 if (which_alternative != 1)
6600 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
6601 if (which_alternative != 0)
6602 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6605 if (which_alternative != 0)
6606 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6607 if (which_alternative != 1)
6608 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
6611 [(set_attr "conds" "use")
6612 (set_attr "length" "4,4,8")]
6615 (define_insn "*cond_arith"
6616 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6617 (match_operator:SI 5 "shiftable_operator"
6618 [(match_operator:SI 4 "arm_comparison_operator"
6619 [(match_operand:SI 2 "s_register_operand" "r,r")
6620 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
6621 (match_operand:SI 1 "s_register_operand" "0,?r")]))
6622 (clobber (reg:CC CC_REGNUM))]
6625 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
6626 return \"%i5\\t%0, %1, %2, lsr #31\";
6628 output_asm_insn (\"cmp\\t%2, %3\", operands);
6629 if (GET_CODE (operands[5]) == AND)
6630 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
6631 else if (GET_CODE (operands[5]) == MINUS)
6632 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
6633 else if (which_alternative != 0)
6634 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6635 return \"%i5%d4\\t%0, %1, #1\";
6637 [(set_attr "conds" "clob")
6638 (set_attr "length" "12")]
6641 (define_insn "*cond_sub"
6642 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6643 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
6644 (match_operator:SI 4 "arm_comparison_operator"
6645 [(match_operand:SI 2 "s_register_operand" "r,r")
6646 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
6647 (clobber (reg:CC CC_REGNUM))]
6650 output_asm_insn (\"cmp\\t%2, %3\", operands);
6651 if (which_alternative != 0)
6652 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6653 return \"sub%d4\\t%0, %1, #1\";
6655 [(set_attr "conds" "clob")
6656 (set_attr "length" "8,12")]
6659 (define_insn "*cmp_ite0"
6660 [(set (match_operand 6 "dominant_cc_register" "")
6663 (match_operator 4 "arm_comparison_operator"
6664 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6665 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6666 (match_operator:SI 5 "arm_comparison_operator"
6667 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6668 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6674 static const char * const opcodes[4][2] =
6676 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6677 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6678 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6679 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6680 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6681 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6682 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6683 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6686 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6688 return opcodes[which_alternative][swap];
6690 [(set_attr "conds" "set")
6691 (set_attr "length" "8")]
6694 (define_insn "*cmp_ite1"
6695 [(set (match_operand 6 "dominant_cc_register" "")
6698 (match_operator 4 "arm_comparison_operator"
6699 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6700 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6701 (match_operator:SI 5 "arm_comparison_operator"
6702 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6703 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6709 static const char * const opcodes[4][2] =
6711 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
6712 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6713 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
6714 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6715 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
6716 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6717 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
6718 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6721 comparison_dominates_p (GET_CODE (operands[5]),
6722 reverse_condition (GET_CODE (operands[4])));
6724 return opcodes[which_alternative][swap];
6726 [(set_attr "conds" "set")
6727 (set_attr "length" "8")]
6730 (define_insn "*cmp_and"
6731 [(set (match_operand 6 "dominant_cc_register" "")
6734 (match_operator 4 "arm_comparison_operator"
6735 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6736 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6737 (match_operator:SI 5 "arm_comparison_operator"
6738 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6739 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6744 static const char *const opcodes[4][2] =
6746 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
6747 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6748 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
6749 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6750 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
6751 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6752 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6753 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6756 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6758 return opcodes[which_alternative][swap];
6760 [(set_attr "conds" "set")
6761 (set_attr "predicable" "no")
6762 (set_attr "length" "8")]
6765 (define_insn "*cmp_ior"
6766 [(set (match_operand 6 "dominant_cc_register" "")
6769 (match_operator 4 "arm_comparison_operator"
6770 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6771 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6772 (match_operator:SI 5 "arm_comparison_operator"
6773 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6774 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
6779 static const char *const opcodes[4][2] =
6781 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
6782 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6783 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
6784 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6785 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
6786 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6787 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
6788 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6791 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6793 return opcodes[which_alternative][swap];
6796 [(set_attr "conds" "set")
6797 (set_attr "length" "8")]
6800 (define_insn_and_split "*ior_scc_scc"
6801 [(set (match_operand:SI 0 "s_register_operand" "=r")
6802 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6803 [(match_operand:SI 1 "s_register_operand" "r")
6804 (match_operand:SI 2 "arm_add_operand" "rIL")])
6805 (match_operator:SI 6 "arm_comparison_operator"
6806 [(match_operand:SI 4 "s_register_operand" "r")
6807 (match_operand:SI 5 "arm_add_operand" "rIL")])))
6808 (clobber (reg:CC CC_REGNUM))]
6810 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
6813 "TARGET_ARM && reload_completed"
6817 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6818 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6820 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
6822 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
6825 [(set_attr "conds" "clob")
6826 (set_attr "length" "16")])
6828 ; If the above pattern is followed by a CMP insn, then the compare is
6829 ; redundant, since we can rework the conditional instruction that follows.
6830 (define_insn_and_split "*ior_scc_scc_cmp"
6831 [(set (match_operand 0 "dominant_cc_register" "")
6832 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
6833 [(match_operand:SI 1 "s_register_operand" "r")
6834 (match_operand:SI 2 "arm_add_operand" "rIL")])
6835 (match_operator:SI 6 "arm_comparison_operator"
6836 [(match_operand:SI 4 "s_register_operand" "r")
6837 (match_operand:SI 5 "arm_add_operand" "rIL")]))
6839 (set (match_operand:SI 7 "s_register_operand" "=r")
6840 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6841 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
6844 "TARGET_ARM && reload_completed"
6848 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6849 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6851 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
6853 [(set_attr "conds" "set")
6854 (set_attr "length" "16")])
6856 (define_insn_and_split "*and_scc_scc"
6857 [(set (match_operand:SI 0 "s_register_operand" "=r")
6858 (and:SI (match_operator:SI 3 "arm_comparison_operator"
6859 [(match_operand:SI 1 "s_register_operand" "r")
6860 (match_operand:SI 2 "arm_add_operand" "rIL")])
6861 (match_operator:SI 6 "arm_comparison_operator"
6862 [(match_operand:SI 4 "s_register_operand" "r")
6863 (match_operand:SI 5 "arm_add_operand" "rIL")])))
6864 (clobber (reg:CC CC_REGNUM))]
6866 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6869 "TARGET_ARM && reload_completed
6870 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6875 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6876 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6878 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
6880 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
6883 [(set_attr "conds" "clob")
6884 (set_attr "length" "16")])
6886 ; If the above pattern is followed by a CMP insn, then the compare is
6887 ; redundant, since we can rework the conditional instruction that follows.
6888 (define_insn_and_split "*and_scc_scc_cmp"
6889 [(set (match_operand 0 "dominant_cc_register" "")
6890 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
6891 [(match_operand:SI 1 "s_register_operand" "r")
6892 (match_operand:SI 2 "arm_add_operand" "rIL")])
6893 (match_operator:SI 6 "arm_comparison_operator"
6894 [(match_operand:SI 4 "s_register_operand" "r")
6895 (match_operand:SI 5 "arm_add_operand" "rIL")]))
6897 (set (match_operand:SI 7 "s_register_operand" "=r")
6898 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6899 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
6902 "TARGET_ARM && reload_completed"
6906 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
6907 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
6909 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
6911 [(set_attr "conds" "set")
6912 (set_attr "length" "16")])
6914 ;; If there is no dominance in the comparison, then we can still save an
6915 ;; instruction in the AND case, since we can know that the second compare
6916 ;; need only zero the value if false (if true, then the value is already
6918 (define_insn_and_split "*and_scc_scc_nodom"
6919 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
6920 (and:SI (match_operator:SI 3 "arm_comparison_operator"
6921 [(match_operand:SI 1 "s_register_operand" "r,r,0")
6922 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
6923 (match_operator:SI 6 "arm_comparison_operator"
6924 [(match_operand:SI 4 "s_register_operand" "r,r,r")
6925 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
6926 (clobber (reg:CC CC_REGNUM))]
6928 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
6931 "TARGET_ARM && reload_completed"
6932 [(parallel [(set (match_dup 0)
6933 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
6934 (clobber (reg:CC CC_REGNUM))])
6935 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
6937 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
6940 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
6941 operands[4], operands[5]),
6943 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
6945 [(set_attr "conds" "clob")
6946 (set_attr "length" "20")])
6948 (define_insn "*negscc"
6949 [(set (match_operand:SI 0 "s_register_operand" "=r")
6950 (neg:SI (match_operator 3 "arm_comparison_operator"
6951 [(match_operand:SI 1 "s_register_operand" "r")
6952 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
6953 (clobber (reg:CC CC_REGNUM))]
6956 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
6957 return \"mov\\t%0, %1, asr #31\";
6959 if (GET_CODE (operands[3]) == NE)
6960 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
6962 if (GET_CODE (operands[3]) == GT)
6963 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
6965 output_asm_insn (\"cmp\\t%1, %2\", operands);
6966 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
6967 return \"mvn%d3\\t%0, #0\";
6969 [(set_attr "conds" "clob")
6970 (set_attr "length" "12")]
6973 (define_insn "movcond"
6974 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6976 (match_operator 5 "arm_comparison_operator"
6977 [(match_operand:SI 3 "s_register_operand" "r,r,r")
6978 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
6979 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6980 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
6981 (clobber (reg:CC CC_REGNUM))]
6984 if (GET_CODE (operands[5]) == LT
6985 && (operands[4] == const0_rtx))
6987 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6989 if (operands[2] == const0_rtx)
6990 return \"and\\t%0, %1, %3, asr #31\";
6991 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
6993 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6995 if (operands[1] == const0_rtx)
6996 return \"bic\\t%0, %2, %3, asr #31\";
6997 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
6999 /* The only case that falls through to here is when both ops 1 & 2
7003 if (GET_CODE (operands[5]) == GE
7004 && (operands[4] == const0_rtx))
7006 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
7008 if (operands[2] == const0_rtx)
7009 return \"bic\\t%0, %1, %3, asr #31\";
7010 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
7012 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
7014 if (operands[1] == const0_rtx)
7015 return \"and\\t%0, %2, %3, asr #31\";
7016 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
7018 /* The only case that falls through to here is when both ops 1 & 2
7021 if (GET_CODE (operands[4]) == CONST_INT
7022 && !const_ok_for_arm (INTVAL (operands[4])))
7023 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
7025 output_asm_insn (\"cmp\\t%3, %4\", operands);
7026 if (which_alternative != 0)
7027 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
7028 if (which_alternative != 1)
7029 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
7032 [(set_attr "conds" "clob")
7033 (set_attr "length" "8,8,12")]
7036 (define_insn "*ifcompare_plus_move"
7037 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7038 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7039 [(match_operand:SI 4 "s_register_operand" "r,r")
7040 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7042 (match_operand:SI 2 "s_register_operand" "r,r")
7043 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
7044 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7045 (clobber (reg:CC CC_REGNUM))]
7048 [(set_attr "conds" "clob")
7049 (set_attr "length" "8,12")]
7052 (define_insn "*if_plus_move"
7053 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7055 (match_operator 4 "arm_comparison_operator"
7056 [(match_operand 5 "cc_register" "") (const_int 0)])
7058 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7059 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
7060 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
7064 sub%d4\\t%0, %2, #%n3
7065 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
7066 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
7067 [(set_attr "conds" "use")
7068 (set_attr "length" "4,4,8,8")
7069 (set_attr "type" "*,*,*,*")]
7072 (define_insn "*ifcompare_move_plus"
7073 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7074 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7075 [(match_operand:SI 4 "s_register_operand" "r,r")
7076 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7077 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7079 (match_operand:SI 2 "s_register_operand" "r,r")
7080 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
7081 (clobber (reg:CC CC_REGNUM))]
7084 [(set_attr "conds" "clob")
7085 (set_attr "length" "8,12")]
7088 (define_insn "*if_move_plus"
7089 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
7091 (match_operator 4 "arm_comparison_operator"
7092 [(match_operand 5 "cc_register" "") (const_int 0)])
7093 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
7095 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
7096 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
7100 sub%D4\\t%0, %2, #%n3
7101 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
7102 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
7103 [(set_attr "conds" "use")
7104 (set_attr "length" "4,4,8,8")
7105 (set_attr "type" "*,*,*,*")]
7108 (define_insn "*ifcompare_arith_arith"
7109 [(set (match_operand:SI 0 "s_register_operand" "=r")
7110 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
7111 [(match_operand:SI 5 "s_register_operand" "r")
7112 (match_operand:SI 6 "arm_add_operand" "rIL")])
7113 (match_operator:SI 8 "shiftable_operator"
7114 [(match_operand:SI 1 "s_register_operand" "r")
7115 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7116 (match_operator:SI 7 "shiftable_operator"
7117 [(match_operand:SI 3 "s_register_operand" "r")
7118 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
7119 (clobber (reg:CC CC_REGNUM))]
7122 [(set_attr "conds" "clob")
7123 (set_attr "length" "12")]
7126 (define_insn "*if_arith_arith"
7127 [(set (match_operand:SI 0 "s_register_operand" "=r")
7128 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
7129 [(match_operand 8 "cc_register" "") (const_int 0)])
7130 (match_operator:SI 6 "shiftable_operator"
7131 [(match_operand:SI 1 "s_register_operand" "r")
7132 (match_operand:SI 2 "arm_rhs_operand" "rI")])
7133 (match_operator:SI 7 "shiftable_operator"
7134 [(match_operand:SI 3 "s_register_operand" "r")
7135 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
7137 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
7138 [(set_attr "conds" "use")
7139 (set_attr "length" "8")]
7142 (define_insn "*ifcompare_arith_move"
7143 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7144 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7145 [(match_operand:SI 2 "s_register_operand" "r,r")
7146 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
7147 (match_operator:SI 7 "shiftable_operator"
7148 [(match_operand:SI 4 "s_register_operand" "r,r")
7149 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
7150 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
7151 (clobber (reg:CC CC_REGNUM))]
7154 /* If we have an operation where (op x 0) is the identity operation and
7155 the conditional operator is LT or GE and we are comparing against zero and
7156 everything is in registers then we can do this in two instructions */
7157 if (operands[3] == const0_rtx
7158 && GET_CODE (operands[7]) != AND
7159 && GET_CODE (operands[5]) == REG
7160 && GET_CODE (operands[1]) == REG
7161 && REGNO (operands[1]) == REGNO (operands[4])
7162 && REGNO (operands[4]) != REGNO (operands[0]))
7164 if (GET_CODE (operands[6]) == LT)
7165 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7166 else if (GET_CODE (operands[6]) == GE)
7167 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
7169 if (GET_CODE (operands[3]) == CONST_INT
7170 && !const_ok_for_arm (INTVAL (operands[3])))
7171 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7173 output_asm_insn (\"cmp\\t%2, %3\", operands);
7174 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
7175 if (which_alternative != 0)
7176 return \"mov%D6\\t%0, %1\";
7179 [(set_attr "conds" "clob")
7180 (set_attr "length" "8,12")]
7183 (define_insn "*if_arith_move"
7184 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7185 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
7186 [(match_operand 6 "cc_register" "") (const_int 0)])
7187 (match_operator:SI 5 "shiftable_operator"
7188 [(match_operand:SI 2 "s_register_operand" "r,r")
7189 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7190 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
7194 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
7195 [(set_attr "conds" "use")
7196 (set_attr "length" "4,8")
7197 (set_attr "type" "*,*")]
7200 (define_insn "*ifcompare_move_arith"
7201 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7202 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
7203 [(match_operand:SI 4 "s_register_operand" "r,r")
7204 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7205 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7206 (match_operator:SI 7 "shiftable_operator"
7207 [(match_operand:SI 2 "s_register_operand" "r,r")
7208 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7209 (clobber (reg:CC CC_REGNUM))]
7212 /* If we have an operation where (op x 0) is the identity operation and
7213 the conditional operator is LT or GE and we are comparing against zero and
7214 everything is in registers then we can do this in two instructions */
7215 if (operands[5] == const0_rtx
7216 && GET_CODE (operands[7]) != AND
7217 && GET_CODE (operands[3]) == REG
7218 && GET_CODE (operands[1]) == REG
7219 && REGNO (operands[1]) == REGNO (operands[2])
7220 && REGNO (operands[2]) != REGNO (operands[0]))
7222 if (GET_CODE (operands[6]) == GE)
7223 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7224 else if (GET_CODE (operands[6]) == LT)
7225 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
7228 if (GET_CODE (operands[5]) == CONST_INT
7229 && !const_ok_for_arm (INTVAL (operands[5])))
7230 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
7232 output_asm_insn (\"cmp\\t%4, %5\", operands);
7234 if (which_alternative != 0)
7235 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
7236 return \"%I7%D6\\t%0, %2, %3\";
7238 [(set_attr "conds" "clob")
7239 (set_attr "length" "8,12")]
7242 (define_insn "*if_move_arith"
7243 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7245 (match_operator 4 "arm_comparison_operator"
7246 [(match_operand 6 "cc_register" "") (const_int 0)])
7247 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
7248 (match_operator:SI 5 "shiftable_operator"
7249 [(match_operand:SI 2 "s_register_operand" "r,r")
7250 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
7254 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
7255 [(set_attr "conds" "use")
7256 (set_attr "length" "4,8")
7257 (set_attr "type" "*,*")]
7260 (define_insn "*ifcompare_move_not"
7261 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7263 (match_operator 5 "arm_comparison_operator"
7264 [(match_operand:SI 3 "s_register_operand" "r,r")
7265 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7266 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7268 (match_operand:SI 2 "s_register_operand" "r,r"))))
7269 (clobber (reg:CC CC_REGNUM))]
7272 [(set_attr "conds" "clob")
7273 (set_attr "length" "8,12")]
7276 (define_insn "*if_move_not"
7277 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7279 (match_operator 4 "arm_comparison_operator"
7280 [(match_operand 3 "cc_register" "") (const_int 0)])
7281 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7282 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7286 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
7287 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
7288 [(set_attr "conds" "use")
7289 (set_attr "length" "4,8,8")]
7292 (define_insn "*ifcompare_not_move"
7293 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7295 (match_operator 5 "arm_comparison_operator"
7296 [(match_operand:SI 3 "s_register_operand" "r,r")
7297 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7299 (match_operand:SI 2 "s_register_operand" "r,r"))
7300 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7301 (clobber (reg:CC CC_REGNUM))]
7304 [(set_attr "conds" "clob")
7305 (set_attr "length" "8,12")]
7308 (define_insn "*if_not_move"
7309 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7311 (match_operator 4 "arm_comparison_operator"
7312 [(match_operand 3 "cc_register" "") (const_int 0)])
7313 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7314 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7318 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
7319 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
7320 [(set_attr "conds" "use")
7321 (set_attr "length" "4,8,8")]
7324 (define_insn "*ifcompare_shift_move"
7325 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7327 (match_operator 6 "arm_comparison_operator"
7328 [(match_operand:SI 4 "s_register_operand" "r,r")
7329 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7330 (match_operator:SI 7 "shift_operator"
7331 [(match_operand:SI 2 "s_register_operand" "r,r")
7332 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7333 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7334 (clobber (reg:CC CC_REGNUM))]
7337 [(set_attr "conds" "clob")
7338 (set_attr "length" "8,12")]
7341 (define_insn "*if_shift_move"
7342 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7344 (match_operator 5 "arm_comparison_operator"
7345 [(match_operand 6 "cc_register" "") (const_int 0)])
7346 (match_operator:SI 4 "shift_operator"
7347 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7348 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7349 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7353 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7354 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7355 [(set_attr "conds" "use")
7356 (set_attr "shift" "2")
7357 (set_attr "length" "4,8,8")]
7360 (define_insn "*ifcompare_move_shift"
7361 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7363 (match_operator 6 "arm_comparison_operator"
7364 [(match_operand:SI 4 "s_register_operand" "r,r")
7365 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7366 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7367 (match_operator:SI 7 "shift_operator"
7368 [(match_operand:SI 2 "s_register_operand" "r,r")
7369 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7370 (clobber (reg:CC CC_REGNUM))]
7373 [(set_attr "conds" "clob")
7374 (set_attr "length" "8,12")]
7377 (define_insn "*if_move_shift"
7378 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7380 (match_operator 5 "arm_comparison_operator"
7381 [(match_operand 6 "cc_register" "") (const_int 0)])
7382 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7383 (match_operator:SI 4 "shift_operator"
7384 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7385 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7389 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7390 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7391 [(set_attr "conds" "use")
7392 (set_attr "shift" "2")
7393 (set_attr "length" "4,8,8")]
7396 (define_insn "*ifcompare_shift_shift"
7397 [(set (match_operand:SI 0 "s_register_operand" "=r")
7399 (match_operator 7 "arm_comparison_operator"
7400 [(match_operand:SI 5 "s_register_operand" "r")
7401 (match_operand:SI 6 "arm_add_operand" "rIL")])
7402 (match_operator:SI 8 "shift_operator"
7403 [(match_operand:SI 1 "s_register_operand" "r")
7404 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7405 (match_operator:SI 9 "shift_operator"
7406 [(match_operand:SI 3 "s_register_operand" "r")
7407 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7408 (clobber (reg:CC CC_REGNUM))]
7411 [(set_attr "conds" "clob")
7412 (set_attr "length" "12")]
7415 (define_insn "*if_shift_shift"
7416 [(set (match_operand:SI 0 "s_register_operand" "=r")
7418 (match_operator 5 "arm_comparison_operator"
7419 [(match_operand 8 "cc_register" "") (const_int 0)])
7420 (match_operator:SI 6 "shift_operator"
7421 [(match_operand:SI 1 "s_register_operand" "r")
7422 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7423 (match_operator:SI 7 "shift_operator"
7424 [(match_operand:SI 3 "s_register_operand" "r")
7425 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7427 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7428 [(set_attr "conds" "use")
7429 (set_attr "shift" "1")
7430 (set_attr "length" "8")]
7433 (define_insn "*ifcompare_not_arith"
7434 [(set (match_operand:SI 0 "s_register_operand" "=r")
7436 (match_operator 6 "arm_comparison_operator"
7437 [(match_operand:SI 4 "s_register_operand" "r")
7438 (match_operand:SI 5 "arm_add_operand" "rIL")])
7439 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7440 (match_operator:SI 7 "shiftable_operator"
7441 [(match_operand:SI 2 "s_register_operand" "r")
7442 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7443 (clobber (reg:CC CC_REGNUM))]
7446 [(set_attr "conds" "clob")
7447 (set_attr "length" "12")]
7450 (define_insn "*if_not_arith"
7451 [(set (match_operand:SI 0 "s_register_operand" "=r")
7453 (match_operator 5 "arm_comparison_operator"
7454 [(match_operand 4 "cc_register" "") (const_int 0)])
7455 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7456 (match_operator:SI 6 "shiftable_operator"
7457 [(match_operand:SI 2 "s_register_operand" "r")
7458 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7460 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7461 [(set_attr "conds" "use")
7462 (set_attr "length" "8")]
7465 (define_insn "*ifcompare_arith_not"
7466 [(set (match_operand:SI 0 "s_register_operand" "=r")
7468 (match_operator 6 "arm_comparison_operator"
7469 [(match_operand:SI 4 "s_register_operand" "r")
7470 (match_operand:SI 5 "arm_add_operand" "rIL")])
7471 (match_operator:SI 7 "shiftable_operator"
7472 [(match_operand:SI 2 "s_register_operand" "r")
7473 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7474 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7475 (clobber (reg:CC CC_REGNUM))]
7478 [(set_attr "conds" "clob")
7479 (set_attr "length" "12")]
7482 (define_insn "*if_arith_not"
7483 [(set (match_operand:SI 0 "s_register_operand" "=r")
7485 (match_operator 5 "arm_comparison_operator"
7486 [(match_operand 4 "cc_register" "") (const_int 0)])
7487 (match_operator:SI 6 "shiftable_operator"
7488 [(match_operand:SI 2 "s_register_operand" "r")
7489 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7490 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7492 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7493 [(set_attr "conds" "use")
7494 (set_attr "length" "8")]
7497 (define_insn "*ifcompare_neg_move"
7498 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7500 (match_operator 5 "arm_comparison_operator"
7501 [(match_operand:SI 3 "s_register_operand" "r,r")
7502 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7503 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7504 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7505 (clobber (reg:CC CC_REGNUM))]
7508 [(set_attr "conds" "clob")
7509 (set_attr "length" "8,12")]
7512 (define_insn "*if_neg_move"
7513 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7515 (match_operator 4 "arm_comparison_operator"
7516 [(match_operand 3 "cc_register" "") (const_int 0)])
7517 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7518 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7522 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7523 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7524 [(set_attr "conds" "use")
7525 (set_attr "length" "4,8,8")]
7528 (define_insn "*ifcompare_move_neg"
7529 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7531 (match_operator 5 "arm_comparison_operator"
7532 [(match_operand:SI 3 "s_register_operand" "r,r")
7533 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7534 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7535 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7536 (clobber (reg:CC CC_REGNUM))]
7539 [(set_attr "conds" "clob")
7540 (set_attr "length" "8,12")]
7543 (define_insn "*if_move_neg"
7544 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7546 (match_operator 4 "arm_comparison_operator"
7547 [(match_operand 3 "cc_register" "") (const_int 0)])
7548 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7549 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7553 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7554 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7555 [(set_attr "conds" "use")
7556 (set_attr "length" "4,8,8")]
7559 (define_insn "*arith_adjacentmem"
7560 [(set (match_operand:SI 0 "s_register_operand" "=r")
7561 (match_operator:SI 1 "shiftable_operator"
7562 [(match_operand:SI 2 "memory_operand" "m")
7563 (match_operand:SI 3 "memory_operand" "m")]))
7564 (clobber (match_scratch:SI 4 "=r"))]
7565 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7570 int val1 = 0, val2 = 0;
7572 if (REGNO (operands[0]) > REGNO (operands[4]))
7574 ldm[1] = operands[4];
7575 ldm[2] = operands[0];
7579 ldm[1] = operands[0];
7580 ldm[2] = operands[4];
7582 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7583 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7584 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7585 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7586 arith[0] = operands[0];
7587 arith[3] = operands[1];
7601 ldm[0] = ops[0] = operands[4];
7602 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7603 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7604 output_add_immediate (ops);
7606 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7608 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7612 ldm[0] = XEXP (operands[3], 0);
7614 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7616 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7620 ldm[0] = XEXP (operands[2], 0);
7622 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7624 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7626 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7629 [(set_attr "length" "12")
7630 (set_attr "predicable" "yes")
7631 (set_attr "type" "load")]
7634 ;; the arm can support extended pre-inc instructions
7636 ;; In all these cases, we use operands 0 and 1 for the register being
7637 ;; incremented because those are the operands that local-alloc will
7638 ;; tie and these are the pair most likely to be tieable (and the ones
7639 ;; that will benefit the most).
7641 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7642 ;; elimination will cause too many headaches.
7644 (define_insn "*strqi_preinc"
7645 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7646 (match_operand:SI 2 "index_operand" "rJ")))
7647 (match_operand:QI 3 "s_register_operand" "r"))
7648 (set (match_operand:SI 0 "s_register_operand" "=r")
7649 (plus:SI (match_dup 1) (match_dup 2)))]
7651 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7652 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7653 && (GET_CODE (operands[2]) != REG
7654 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7655 "str%?b\\t%3, [%0, %2]!"
7656 [(set_attr "type" "store1")
7657 (set_attr "predicable" "yes")]
7660 (define_insn "*strqi_predec"
7661 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7662 (match_operand:SI 2 "s_register_operand" "r")))
7663 (match_operand:QI 3 "s_register_operand" "r"))
7664 (set (match_operand:SI 0 "s_register_operand" "=r")
7665 (minus:SI (match_dup 1) (match_dup 2)))]
7667 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7668 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7669 && (GET_CODE (operands[2]) != REG
7670 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7671 "str%?b\\t%3, [%0, -%2]!"
7672 [(set_attr "type" "store1")
7673 (set_attr "predicable" "yes")]
7676 (define_insn "*loadqi_preinc"
7677 [(set (match_operand:QI 3 "s_register_operand" "=r")
7678 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7679 (match_operand:SI 2 "index_operand" "rJ"))))
7680 (set (match_operand:SI 0 "s_register_operand" "=r")
7681 (plus:SI (match_dup 1) (match_dup 2)))]
7683 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7684 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7685 && (GET_CODE (operands[2]) != REG
7686 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7687 "ldr%?b\\t%3, [%0, %2]!"
7688 [(set_attr "type" "load")
7689 (set_attr "predicable" "yes")]
7692 (define_insn "*loadqi_predec"
7693 [(set (match_operand:QI 3 "s_register_operand" "=r")
7694 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7695 (match_operand:SI 2 "s_register_operand" "r"))))
7696 (set (match_operand:SI 0 "s_register_operand" "=r")
7697 (minus:SI (match_dup 1) (match_dup 2)))]
7699 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7700 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7701 && (GET_CODE (operands[2]) != REG
7702 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7703 "ldr%?b\\t%3, [%0, -%2]!"
7704 [(set_attr "type" "load")
7705 (set_attr "predicable" "yes")]
7708 (define_insn "*loadqisi_preinc"
7709 [(set (match_operand:SI 3 "s_register_operand" "=r")
7711 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7712 (match_operand:SI 2 "index_operand" "rJ")))))
7713 (set (match_operand:SI 0 "s_register_operand" "=r")
7714 (plus:SI (match_dup 1) (match_dup 2)))]
7716 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7717 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7718 && (GET_CODE (operands[2]) != REG
7719 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7720 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
7721 [(set_attr "type" "load")
7722 (set_attr "predicable" "yes")]
7725 (define_insn "*loadqisi_predec"
7726 [(set (match_operand:SI 3 "s_register_operand" "=r")
7728 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7729 (match_operand:SI 2 "s_register_operand" "r")))))
7730 (set (match_operand:SI 0 "s_register_operand" "=r")
7731 (minus:SI (match_dup 1) (match_dup 2)))]
7733 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7734 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7735 && (GET_CODE (operands[2]) != REG
7736 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7737 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
7738 [(set_attr "type" "load")
7739 (set_attr "predicable" "yes")]
7742 (define_insn "*strsi_preinc"
7743 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7744 (match_operand:SI 2 "index_operand" "rJ")))
7745 (match_operand:SI 3 "s_register_operand" "r"))
7746 (set (match_operand:SI 0 "s_register_operand" "=r")
7747 (plus:SI (match_dup 1) (match_dup 2)))]
7749 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7750 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7751 && (GET_CODE (operands[2]) != REG
7752 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7753 "str%?\\t%3, [%0, %2]!"
7754 [(set_attr "type" "store1")
7755 (set_attr "predicable" "yes")]
7758 (define_insn "*strsi_predec"
7759 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7760 (match_operand:SI 2 "s_register_operand" "r")))
7761 (match_operand:SI 3 "s_register_operand" "r"))
7762 (set (match_operand:SI 0 "s_register_operand" "=r")
7763 (minus:SI (match_dup 1) (match_dup 2)))]
7765 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7766 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7767 && (GET_CODE (operands[2]) != REG
7768 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7769 "str%?\\t%3, [%0, -%2]!"
7770 [(set_attr "type" "store1")
7771 (set_attr "predicable" "yes")]
7774 (define_insn "*loadsi_preinc"
7775 [(set (match_operand:SI 3 "s_register_operand" "=r")
7776 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7777 (match_operand:SI 2 "index_operand" "rJ"))))
7778 (set (match_operand:SI 0 "s_register_operand" "=r")
7779 (plus:SI (match_dup 1) (match_dup 2)))]
7781 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7782 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7783 && (GET_CODE (operands[2]) != REG
7784 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7785 "ldr%?\\t%3, [%0, %2]!"
7786 [(set_attr "type" "load")
7787 (set_attr "predicable" "yes")]
7790 (define_insn "*loadsi_predec"
7791 [(set (match_operand:SI 3 "s_register_operand" "=r")
7792 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7793 (match_operand:SI 2 "s_register_operand" "r"))))
7794 (set (match_operand:SI 0 "s_register_operand" "=r")
7795 (minus:SI (match_dup 1) (match_dup 2)))]
7797 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7798 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7799 && (GET_CODE (operands[2]) != REG
7800 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7801 "ldr%?\\t%3, [%0, -%2]!"
7802 [(set_attr "type" "load")
7803 (set_attr "predicable" "yes")]
7806 (define_insn "*loadhi_preinc"
7807 [(set (match_operand:HI 3 "s_register_operand" "=r")
7808 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7809 (match_operand:SI 2 "index_operand" "rJ"))))
7810 (set (match_operand:SI 0 "s_register_operand" "=r")
7811 (plus:SI (match_dup 1) (match_dup 2)))]
7813 && !BYTES_BIG_ENDIAN
7814 && !TARGET_MMU_TRAPS
7816 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7817 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7818 && (GET_CODE (operands[2]) != REG
7819 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7820 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
7821 [(set_attr "type" "load")
7822 (set_attr "predicable" "yes")]
7825 (define_insn "*loadhi_predec"
7826 [(set (match_operand:HI 3 "s_register_operand" "=r")
7827 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7828 (match_operand:SI 2 "s_register_operand" "r"))))
7829 (set (match_operand:SI 0 "s_register_operand" "=r")
7830 (minus:SI (match_dup 1) (match_dup 2)))]
7832 && !BYTES_BIG_ENDIAN
7833 && !TARGET_MMU_TRAPS
7835 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7836 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7837 && (GET_CODE (operands[2]) != REG
7838 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7839 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
7840 [(set_attr "type" "load")
7841 (set_attr "predicable" "yes")]
7844 (define_insn "*strqi_shiftpreinc"
7845 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7846 [(match_operand:SI 3 "s_register_operand" "r")
7847 (match_operand:SI 4 "const_shift_operand" "n")])
7848 (match_operand:SI 1 "s_register_operand" "0")))
7849 (match_operand:QI 5 "s_register_operand" "r"))
7850 (set (match_operand:SI 0 "s_register_operand" "=r")
7851 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7854 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7855 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7856 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7857 "str%?b\\t%5, [%0, %3%S2]!"
7858 [(set_attr "type" "store1")
7859 (set_attr "predicable" "yes")]
7862 (define_insn "*strqi_shiftpredec"
7863 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7864 (match_operator:SI 2 "shift_operator"
7865 [(match_operand:SI 3 "s_register_operand" "r")
7866 (match_operand:SI 4 "const_shift_operand" "n")])))
7867 (match_operand:QI 5 "s_register_operand" "r"))
7868 (set (match_operand:SI 0 "s_register_operand" "=r")
7869 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7872 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7873 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7874 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7875 "str%?b\\t%5, [%0, -%3%S2]!"
7876 [(set_attr "type" "store1")
7877 (set_attr "predicable" "yes")]
7880 (define_insn "*loadqi_shiftpreinc"
7881 [(set (match_operand:QI 5 "s_register_operand" "=r")
7882 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7883 [(match_operand:SI 3 "s_register_operand" "r")
7884 (match_operand:SI 4 "const_shift_operand" "n")])
7885 (match_operand:SI 1 "s_register_operand" "0"))))
7886 (set (match_operand:SI 0 "s_register_operand" "=r")
7887 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7890 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7891 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7892 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7893 "ldr%?b\\t%5, [%0, %3%S2]!"
7894 [(set_attr "type" "load")
7895 (set_attr "predicable" "yes")]
7898 (define_insn "*loadqi_shiftpredec"
7899 [(set (match_operand:QI 5 "s_register_operand" "=r")
7900 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7901 (match_operator:SI 2 "shift_operator"
7902 [(match_operand:SI 3 "s_register_operand" "r")
7903 (match_operand:SI 4 "const_shift_operand" "n")]))))
7904 (set (match_operand:SI 0 "s_register_operand" "=r")
7905 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7908 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7909 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7910 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7911 "ldr%?b\\t%5, [%0, -%3%S2]!"
7912 [(set_attr "type" "load")
7913 (set_attr "predicable" "yes")]
7916 (define_insn "*strsi_shiftpreinc"
7917 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7918 [(match_operand:SI 3 "s_register_operand" "r")
7919 (match_operand:SI 4 "const_shift_operand" "n")])
7920 (match_operand:SI 1 "s_register_operand" "0")))
7921 (match_operand:SI 5 "s_register_operand" "r"))
7922 (set (match_operand:SI 0 "s_register_operand" "=r")
7923 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7926 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7927 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7928 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7929 "str%?\\t%5, [%0, %3%S2]!"
7930 [(set_attr "type" "store1")
7931 (set_attr "predicable" "yes")]
7934 (define_insn "*strsi_shiftpredec"
7935 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7936 (match_operator:SI 2 "shift_operator"
7937 [(match_operand:SI 3 "s_register_operand" "r")
7938 (match_operand:SI 4 "const_shift_operand" "n")])))
7939 (match_operand:SI 5 "s_register_operand" "r"))
7940 (set (match_operand:SI 0 "s_register_operand" "=r")
7941 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7944 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7945 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7946 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7947 "str%?\\t%5, [%0, -%3%S2]!"
7948 [(set_attr "type" "store1")
7949 (set_attr "predicable" "yes")]
7952 (define_insn "*loadsi_shiftpreinc"
7953 [(set (match_operand:SI 5 "s_register_operand" "=r")
7954 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7955 [(match_operand:SI 3 "s_register_operand" "r")
7956 (match_operand:SI 4 "const_shift_operand" "n")])
7957 (match_operand:SI 1 "s_register_operand" "0"))))
7958 (set (match_operand:SI 0 "s_register_operand" "=r")
7959 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7962 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7963 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7964 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7965 "ldr%?\\t%5, [%0, %3%S2]!"
7966 [(set_attr "type" "load")
7967 (set_attr "predicable" "yes")]
7970 (define_insn "*loadsi_shiftpredec"
7971 [(set (match_operand:SI 5 "s_register_operand" "=r")
7972 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7973 (match_operator:SI 2 "shift_operator"
7974 [(match_operand:SI 3 "s_register_operand" "r")
7975 (match_operand:SI 4 "const_shift_operand" "n")]))))
7976 (set (match_operand:SI 0 "s_register_operand" "=r")
7977 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7980 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7981 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7982 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7983 "ldr%?\\t%5, [%0, -%3%S2]!"
7984 [(set_attr "type" "load")
7985 (set_attr "predicable" "yes")])
7987 (define_insn "*loadhi_shiftpreinc"
7988 [(set (match_operand:HI 5 "s_register_operand" "=r")
7989 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
7990 [(match_operand:SI 3 "s_register_operand" "r")
7991 (match_operand:SI 4 "const_shift_operand" "n")])
7992 (match_operand:SI 1 "s_register_operand" "0"))))
7993 (set (match_operand:SI 0 "s_register_operand" "=r")
7994 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7997 && !BYTES_BIG_ENDIAN
7998 && !TARGET_MMU_TRAPS
8000 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8001 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8002 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8003 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
8004 [(set_attr "type" "load")
8005 (set_attr "predicable" "yes")]
8008 (define_insn "*loadhi_shiftpredec"
8009 [(set (match_operand:HI 5 "s_register_operand" "=r")
8010 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8011 (match_operator:SI 2 "shift_operator"
8012 [(match_operand:SI 3 "s_register_operand" "r")
8013 (match_operand:SI 4 "const_shift_operand" "n")]))))
8014 (set (match_operand:SI 0 "s_register_operand" "=r")
8015 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8018 && !BYTES_BIG_ENDIAN
8019 && !TARGET_MMU_TRAPS
8021 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8022 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8023 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8024 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
8025 [(set_attr "type" "load")
8026 (set_attr "predicable" "yes")]
8029 ; It can also support extended post-inc expressions, but combine doesn't
8031 ; It doesn't seem worth adding peepholes for anything but the most common
8032 ; cases since, unlike combine, the increment must immediately follow the load
8033 ; for this pattern to match.
8034 ; We must watch to see that the source/destination register isn't also the
8035 ; same as the base address register, and that if the index is a register,
8036 ; that it is not the same as the base address register. In such cases the
8037 ; instruction that we would generate would have UNPREDICTABLE behavior so
8041 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
8042 (match_operand:QI 2 "s_register_operand" "r"))
8044 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8046 && (REGNO (operands[2]) != REGNO (operands[0]))
8047 && (GET_CODE (operands[1]) != REG
8048 || (REGNO (operands[1]) != REGNO (operands[0])))"
8049 "str%?b\\t%2, [%0], %1"
8053 [(set (match_operand:QI 0 "s_register_operand" "=r")
8054 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
8056 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8058 && REGNO (operands[0]) != REGNO(operands[1])
8059 && (GET_CODE (operands[2]) != REG
8060 || REGNO(operands[0]) != REGNO (operands[2]))"
8061 "ldr%?b\\t%0, [%1], %2"
8065 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
8066 (match_operand:SI 2 "s_register_operand" "r"))
8068 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
8070 && (REGNO (operands[2]) != REGNO (operands[0]))
8071 && (GET_CODE (operands[1]) != REG
8072 || (REGNO (operands[1]) != REGNO (operands[0])))"
8073 "str%?\\t%2, [%0], %1"
8077 [(set (match_operand:HI 0 "s_register_operand" "=r")
8078 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
8080 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8082 && !BYTES_BIG_ENDIAN
8083 && !TARGET_MMU_TRAPS
8085 && REGNO (operands[0]) != REGNO(operands[1])
8086 && (GET_CODE (operands[2]) != REG
8087 || REGNO(operands[0]) != REGNO (operands[2]))"
8088 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
8092 [(set (match_operand:SI 0 "s_register_operand" "=r")
8093 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
8095 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
8097 && REGNO (operands[0]) != REGNO(operands[1])
8098 && (GET_CODE (operands[2]) != REG
8099 || REGNO(operands[0]) != REGNO (operands[2]))"
8100 "ldr%?\\t%0, [%1], %2"
8104 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
8105 (match_operand:SI 1 "index_operand" "rJ")))
8106 (match_operand:QI 2 "s_register_operand" "r"))
8107 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
8109 && (REGNO (operands[2]) != REGNO (operands[0]))
8110 && (GET_CODE (operands[1]) != REG
8111 || (REGNO (operands[1]) != REGNO (operands[0])))"
8112 "str%?b\\t%2, [%0, %1]!"
8116 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
8117 [(match_operand:SI 0 "s_register_operand" "r")
8118 (match_operand:SI 1 "const_int_operand" "n")])
8119 (match_operand:SI 2 "s_register_operand" "+r")))
8120 (match_operand:QI 3 "s_register_operand" "r"))
8121 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
8124 && (REGNO (operands[3]) != REGNO (operands[2]))
8125 && (REGNO (operands[0]) != REGNO (operands[2]))"
8126 "str%?b\\t%3, [%2, %0%S4]!"
8129 ; This pattern is never tried by combine, so do it as a peephole
8132 [(set (match_operand:SI 0 "s_register_operand" "")
8133 (match_operand:SI 1 "s_register_operand" ""))
8134 (set (reg:CC CC_REGNUM)
8135 (compare:CC (match_dup 1) (const_int 0)))]
8138 || (!cirrus_fp_register (operands[0], SImode)
8139 && !cirrus_fp_register (operands[1], SImode)))
8141 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
8142 (set (match_dup 0) (match_dup 1))])]
8146 ; Peepholes to spot possible load- and store-multiples, if the ordering is
8147 ; reversed, check that the memory references aren't volatile.
8150 [(set (match_operand:SI 0 "s_register_operand" "=r")
8151 (match_operand:SI 4 "memory_operand" "m"))
8152 (set (match_operand:SI 1 "s_register_operand" "=r")
8153 (match_operand:SI 5 "memory_operand" "m"))
8154 (set (match_operand:SI 2 "s_register_operand" "=r")
8155 (match_operand:SI 6 "memory_operand" "m"))
8156 (set (match_operand:SI 3 "s_register_operand" "=r")
8157 (match_operand:SI 7 "memory_operand" "m"))]
8158 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8160 return emit_ldm_seq (operands, 4);
8165 [(set (match_operand:SI 0 "s_register_operand" "=r")
8166 (match_operand:SI 3 "memory_operand" "m"))
8167 (set (match_operand:SI 1 "s_register_operand" "=r")
8168 (match_operand:SI 4 "memory_operand" "m"))
8169 (set (match_operand:SI 2 "s_register_operand" "=r")
8170 (match_operand:SI 5 "memory_operand" "m"))]
8171 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8173 return emit_ldm_seq (operands, 3);
8178 [(set (match_operand:SI 0 "s_register_operand" "=r")
8179 (match_operand:SI 2 "memory_operand" "m"))
8180 (set (match_operand:SI 1 "s_register_operand" "=r")
8181 (match_operand:SI 3 "memory_operand" "m"))]
8182 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8184 return emit_ldm_seq (operands, 2);
8189 [(set (match_operand:SI 4 "memory_operand" "=m")
8190 (match_operand:SI 0 "s_register_operand" "r"))
8191 (set (match_operand:SI 5 "memory_operand" "=m")
8192 (match_operand:SI 1 "s_register_operand" "r"))
8193 (set (match_operand:SI 6 "memory_operand" "=m")
8194 (match_operand:SI 2 "s_register_operand" "r"))
8195 (set (match_operand:SI 7 "memory_operand" "=m")
8196 (match_operand:SI 3 "s_register_operand" "r"))]
8197 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
8199 return emit_stm_seq (operands, 4);
8204 [(set (match_operand:SI 3 "memory_operand" "=m")
8205 (match_operand:SI 0 "s_register_operand" "r"))
8206 (set (match_operand:SI 4 "memory_operand" "=m")
8207 (match_operand:SI 1 "s_register_operand" "r"))
8208 (set (match_operand:SI 5 "memory_operand" "=m")
8209 (match_operand:SI 2 "s_register_operand" "r"))]
8210 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
8212 return emit_stm_seq (operands, 3);
8217 [(set (match_operand:SI 2 "memory_operand" "=m")
8218 (match_operand:SI 0 "s_register_operand" "r"))
8219 (set (match_operand:SI 3 "memory_operand" "=m")
8220 (match_operand:SI 1 "s_register_operand" "r"))]
8221 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
8223 return emit_stm_seq (operands, 2);
8228 [(set (match_operand:SI 0 "s_register_operand" "")
8229 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
8231 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
8232 [(match_operand:SI 3 "s_register_operand" "")
8233 (match_operand:SI 4 "arm_rhs_operand" "")]))))
8234 (clobber (match_operand:SI 5 "s_register_operand" ""))]
8236 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
8237 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8242 ;; This split can be used because CC_Z mode implies that the following
8243 ;; branch will be an equality, or an unsigned inequality, so the sign
8244 ;; extension is not needed.
8247 [(set (reg:CC_Z CC_REGNUM)
8249 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
8251 (match_operand 1 "const_int_operand" "")))
8252 (clobber (match_scratch:SI 2 ""))]
8254 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
8255 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
8256 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
8257 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
8259 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
8263 (define_expand "prologue"
8264 [(clobber (const_int 0))]
8267 arm_expand_prologue ();
8269 thumb_expand_prologue ();
8274 (define_expand "epilogue"
8275 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8279 thumb_expand_epilogue ();
8280 else if (USE_RETURN_INSN (FALSE))
8282 emit_jump_insn (gen_return ());
8285 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
8287 gen_rtx_RETURN (VOIDmode)),
8293 ;; Note - although unspec_volatile's USE all hard registers,
8294 ;; USEs are ignored after relaod has completed. Thus we need
8295 ;; to add an unspec of the link register to ensure that flow
8296 ;; does not think that it is unused by the sibcall branch that
8297 ;; will replace the standard function epilogue.
8298 (define_insn "sibcall_epilogue"
8299 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
8300 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
8303 if (USE_RETURN_INSN (FALSE))
8304 return output_return_instruction (const_true_rtx, FALSE, FALSE);
8305 return arm_output_epilogue (FALSE);
8307 ;; Length is absolute worst case
8308 [(set_attr "length" "44")
8309 (set_attr "type" "block")
8310 ;; We don't clobber the conditions, but the potential length of this
8311 ;; operation is sufficient to make conditionalizing the sequence
8312 ;; unlikely to be profitable.
8313 (set_attr "conds" "clob")]
8316 (define_insn "*epilogue_insns"
8317 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
8321 return arm_output_epilogue (TRUE);
8322 else /* TARGET_THUMB */
8323 return thumb_unexpanded_epilogue ();
8325 ; Length is absolute worst case
8326 [(set_attr "length" "44")
8327 (set_attr "type" "block")
8328 ;; We don't clobber the conditions, but the potential length of this
8329 ;; operation is sufficient to make conditionalizing the sequence
8330 ;; unlikely to be profitable.
8331 (set_attr "conds" "clob")]
8334 (define_expand "eh_epilogue"
8335 [(use (match_operand:SI 0 "register_operand" ""))
8336 (use (match_operand:SI 1 "register_operand" ""))
8337 (use (match_operand:SI 2 "register_operand" ""))]
8341 cfun->machine->eh_epilogue_sp_ofs = operands[1];
8342 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
8344 rtx ra = gen_rtx_REG (Pmode, 2);
8346 emit_move_insn (ra, operands[2]);
8349 /* This is a hack -- we may have crystalized the function type too
8351 cfun->machine->func_type = 0;
8355 ;; This split is only used during output to reduce the number of patterns
8356 ;; that need assembler instructions adding to them. We allowed the setting
8357 ;; of the conditions to be implicit during rtl generation so that
8358 ;; the conditional compare patterns would work. However this conflicts to
8359 ;; some extent with the conditional data operations, so we have to split them
8363 [(set (match_operand:SI 0 "s_register_operand" "")
8364 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8365 [(match_operand 2 "" "") (match_operand 3 "" "")])
8367 (match_operand 4 "" "")))
8368 (clobber (reg:CC CC_REGNUM))]
8369 ;; Note we have to suppress this split for the iwmmxt because it
8370 ;; creates a conditional movsi and the iwmmxt_movsi_insn pattern
8371 ;; is not predicable. This sucks.
8372 "TARGET_ARM && reload_completed && ! TARGET_IWMMXT"
8373 [(set (match_dup 5) (match_dup 6))
8374 (cond_exec (match_dup 7)
8375 (set (match_dup 0) (match_dup 4)))]
8378 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8379 operands[2], operands[3]);
8380 enum rtx_code rc = GET_CODE (operands[1]);
8382 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8383 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8384 if (mode == CCFPmode || mode == CCFPEmode)
8385 rc = reverse_condition_maybe_unordered (rc);
8387 rc = reverse_condition (rc);
8389 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
8394 [(set (match_operand:SI 0 "s_register_operand" "")
8395 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8396 [(match_operand 2 "" "") (match_operand 3 "" "")])
8397 (match_operand 4 "" "")
8399 (clobber (reg:CC CC_REGNUM))]
8400 ;; Note we have to suppress this split for the iwmmxt because it
8401 ;; creates a conditional movsi and the iwmmxt_movsi_insn pattern
8402 ;; is not predicable. This sucks.
8403 "TARGET_ARM && reload_completed && ! TARGET_IWMMXT"
8404 [(set (match_dup 5) (match_dup 6))
8405 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
8406 (set (match_dup 0) (match_dup 4)))]
8409 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8410 operands[2], operands[3]);
8412 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
8413 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8418 [(set (match_operand:SI 0 "s_register_operand" "")
8419 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8420 [(match_operand 2 "" "") (match_operand 3 "" "")])
8421 (match_operand 4 "" "")
8422 (match_operand 5 "" "")))
8423 (clobber (reg:CC CC_REGNUM))]
8424 ;; Note we have to suppress this split for the iwmmxt because it
8425 ;; creates a conditional movsi and the iwmmxt_movsi_insn pattern
8426 ;; is not predicable. This sucks.
8427 "TARGET_ARM && reload_completed && ! TARGET_IWMMXT"
8428 [(set (match_dup 6) (match_dup 7))
8429 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8430 (set (match_dup 0) (match_dup 4)))
8431 (cond_exec (match_dup 8)
8432 (set (match_dup 0) (match_dup 5)))]
8435 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8436 operands[2], operands[3]);
8437 enum rtx_code rc = GET_CODE (operands[1]);
8439 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8440 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8441 if (mode == CCFPmode || mode == CCFPEmode)
8442 rc = reverse_condition_maybe_unordered (rc);
8444 rc = reverse_condition (rc);
8446 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8451 [(set (match_operand:SI 0 "s_register_operand" "")
8452 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
8453 [(match_operand:SI 2 "s_register_operand" "")
8454 (match_operand:SI 3 "arm_add_operand" "")])
8455 (match_operand:SI 4 "arm_rhs_operand" "")
8457 (match_operand:SI 5 "s_register_operand" ""))))
8458 (clobber (reg:CC CC_REGNUM))]
8459 ;; Note we have to suppress this split for the iwmmxt because it
8460 ;; creates a conditional movsi and the iwmmxt_movsi_insn pattern
8461 ;; is not predicable. This sucks.
8462 "TARGET_ARM && reload_completed && ! TARGET_IWMMXT"
8463 [(set (match_dup 6) (match_dup 7))
8464 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
8465 (set (match_dup 0) (match_dup 4)))
8466 (cond_exec (match_dup 8)
8467 (set (match_dup 0) (not:SI (match_dup 5))))]
8470 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
8471 operands[2], operands[3]);
8472 enum rtx_code rc = GET_CODE (operands[1]);
8474 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
8475 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8476 if (mode == CCFPmode || mode == CCFPEmode)
8477 rc = reverse_condition_maybe_unordered (rc);
8479 rc = reverse_condition (rc);
8481 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
8485 (define_insn "*cond_move_not"
8486 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8487 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8488 [(match_operand 3 "cc_register" "") (const_int 0)])
8489 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8491 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8495 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8496 [(set_attr "conds" "use")
8497 (set_attr "length" "4,8")]
8500 ;; The next two patterns occur when an AND operation is followed by a
8501 ;; scc insn sequence
8503 (define_insn "*sign_extract_onebit"
8504 [(set (match_operand:SI 0 "s_register_operand" "=r")
8505 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8507 (match_operand:SI 2 "const_int_operand" "n")))
8508 (clobber (reg:CC CC_REGNUM))]
8511 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8512 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8513 return \"mvnne\\t%0, #0\";
8515 [(set_attr "conds" "clob")
8516 (set_attr "length" "8")]
8519 (define_insn "*not_signextract_onebit"
8520 [(set (match_operand:SI 0 "s_register_operand" "=r")
8522 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8524 (match_operand:SI 2 "const_int_operand" "n"))))
8525 (clobber (reg:CC CC_REGNUM))]
8528 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8529 output_asm_insn (\"tst\\t%1, %2\", operands);
8530 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8531 return \"movne\\t%0, #0\";
8533 [(set_attr "conds" "clob")
8534 (set_attr "length" "12")]
8537 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
8538 ;; expressions. For simplicity, the first register is also in the unspec
8540 (define_insn "*push_multi"
8541 [(match_parallel 2 "multi_register_push"
8542 [(set (match_operand:BLK 0 "memory_operand" "=m")
8543 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
8544 UNSPEC_PUSH_MULT))])]
8548 int num_saves = XVECLEN (operands[2], 0);
8550 /* For the StrongARM at least it is faster to
8551 use STR to store only a single register. */
8553 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8559 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8561 for (i = 1; i < num_saves; i++)
8563 strcat (pattern, \", %|\");
8565 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
8568 strcat (pattern, \"}\");
8569 output_asm_insn (pattern, operands);
8574 [(set_attr "type" "store4")]
8577 (define_insn "stack_tie"
8578 [(set (mem:BLK (scratch))
8579 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
8580 (match_operand:SI 1 "s_register_operand" "r")]
8584 [(set_attr "length" "0")]
8587 ;; Similarly for the floating point registers
8588 (define_insn "*push_fp_multi"
8589 [(match_parallel 2 "multi_register_push"
8590 [(set (match_operand:BLK 0 "memory_operand" "=m")
8591 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
8592 UNSPEC_PUSH_MULT))])]
8598 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8599 output_asm_insn (pattern, operands);
8602 [(set_attr "type" "f_store")]
8605 ;; Special patterns for dealing with the constant pool
8607 (define_insn "align_4"
8608 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
8611 assemble_align (32);
8616 (define_insn "align_8"
8617 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
8618 "TARGET_REALLY_IWMMXT"
8620 assemble_align (64);
8625 (define_insn "consttable_end"
8626 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
8629 making_const_table = FALSE;
8634 (define_insn "consttable_1"
8635 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
8638 making_const_table = TRUE;
8639 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
8643 [(set_attr "length" "4")]
8646 (define_insn "consttable_2"
8647 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
8650 making_const_table = TRUE;
8651 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
8655 [(set_attr "length" "4")]
8658 (define_insn "consttable_4"
8659 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
8663 making_const_table = TRUE;
8664 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8669 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8670 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8674 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
8679 [(set_attr "length" "4")]
8682 (define_insn "consttable_8"
8683 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
8687 making_const_table = TRUE;
8688 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8693 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
8694 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
8698 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
8703 [(set_attr "length" "8")]
8706 ;; Miscellaneous Thumb patterns
8708 (define_expand "tablejump"
8709 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
8710 (use (label_ref (match_operand 1 "" "")))])]
8715 /* Hopefully, CSE will eliminate this copy. */
8716 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
8717 rtx reg2 = gen_reg_rtx (SImode);
8719 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
8725 (define_insn "*thumb_tablejump"
8726 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8727 (use (label_ref (match_operand 1 "" "")))]
8730 [(set_attr "length" "2")]
8735 (define_insn "clzsi2"
8736 [(set (match_operand:SI 0 "s_register_operand" "=r")
8737 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
8738 "TARGET_ARM && arm_arch5"
8740 [(set_attr "predicable" "yes")])
8742 (define_expand "ffssi2"
8743 [(set (match_operand:SI 0 "s_register_operand" "")
8744 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
8745 "TARGET_ARM && arm_arch5"
8750 t1 = gen_reg_rtx (SImode);
8751 t2 = gen_reg_rtx (SImode);
8752 t3 = gen_reg_rtx (SImode);
8754 emit_insn (gen_negsi2 (t1, operands[1]));
8755 emit_insn (gen_andsi3 (t2, operands[1], t1));
8756 emit_insn (gen_clzsi2 (t3, t2));
8757 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
8762 (define_expand "ctzsi2"
8763 [(set (match_operand:SI 0 "s_register_operand" "")
8764 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
8765 "TARGET_ARM && arm_arch5"
8770 t1 = gen_reg_rtx (SImode);
8771 t2 = gen_reg_rtx (SImode);
8772 t3 = gen_reg_rtx (SImode);
8774 emit_insn (gen_negsi2 (t1, operands[1]));
8775 emit_insn (gen_andsi3 (t2, operands[1], t1));
8776 emit_insn (gen_clzsi2 (t3, t2));
8777 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
8782 ;; V5E instructions.
8784 (define_insn "prefetch"
8785 [(prefetch (match_operand:SI 0 "address_operand" "p")
8786 (match_operand:SI 1 "" "")
8787 (match_operand:SI 2 "" ""))]
8788 "TARGET_ARM && arm_arch5e"
8791 ;; General predication pattern
8794 [(match_operator 0 "arm_comparison_operator"
8795 [(match_operand 1 "cc_register" "")
8801 (define_insn "prologue_use"
8802 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
8804 "%@ %0 needed for prologue"
8807 ;; Load the FPA co-processor patterns
8809 ;; Load the Maverick co-processor patterns
8810 (include "cirrus.md")
8811 ;; Load the Intel Wireless Multimedia Extension patterns
8812 (include "iwmmxt.md")