1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
33 [(IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (CC_REGNUM 24) ; Condition code pseudo register
41 ;; 3rd operand to select_dominance_cc_mode
50 ;; Note: sin and cos are no-longer used.
53 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
54 ; operand 0 is the result,
55 ; operand 1 the parameter.
56 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60 ; operand 0 is the first register,
61 ; subsequent registers are in parallel (use ...)
63 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
64 ; usage, that is, we will add the pic_register
65 ; value to it before trying to dereference it.
66 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
67 ; GLOBAL_OFFSET_TABLE. The operation is fully
68 ; described by the RTL but must be wrapped to
69 ; prevent combine from trying to rip it apart.
70 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
71 ; being scheduled before the stack adjustment insn.
72 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73 ; this unspec is used to prevent the deletion of
74 ; instructions setting registers for EH handling
75 ; and stack frame generation. Operand 0 is the
77 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93 ;; UNSPEC_VOLATILE Usage:
96 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
98 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99 ; instruction epilogue sequence that isn't expanded
100 ; into normal RTL. Used for both normal and sibcall
102 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
103 ; for inlined constants.
104 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
106 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
108 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
110 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
112 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
114 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
115 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
116 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
117 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
118 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
123 ;;---------------------------------------------------------------------------
126 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127 ; generating ARM code. This is used to control the length of some insn
128 ; patterns that share the same RTL in both ARM and Thumb code.
129 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
131 ; PROG_MODE attribute is used to determine whether condition codes are
132 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
133 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
134 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
140 ;; Operand number of an input operand that is shifted. Zero if the
141 ;; given instruction does not shift one of its input operands.
142 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 (define_attr "shift" "" (const_int 0))
145 ; Floating Point Unit. If we only have floating point emulation, then there
146 ; is no point in scheduling the floating point insns. (Well, for best
147 ; performance we should try and group them together).
148 (define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
149 (const (symbol_ref "arm_fpu_attr")))
151 ; LENGTH of an instruction (in bytes)
152 (define_attr "length" "" (const_int 4))
154 ; POOL_RANGE is how far away from a constant pool entry that this insn
155 ; can be placed. If the distance is zero, then this insn will never
156 ; reference the pool.
157 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
158 ; before its address.
159 (define_attr "pool_range" "" (const_int 0))
160 (define_attr "neg_pool_range" "" (const_int 0))
162 ; An assembler sequence may clobber the condition codes without us knowing.
163 ; If such an insn references the pool, then we have no way of knowing how,
164 ; so use the most conservative value for pool_range.
165 (define_asm_attributes
166 [(set_attr "conds" "clob")
167 (set_attr "length" "4")
168 (set_attr "pool_range" "250")])
170 ; TYPE attribute is used to detect floating point instructions which, if
171 ; running on a co-processor can run in parallel with other, basic instructions
172 ; If write-buffer scheduling is enabled then it can also be used in the
173 ; scheduling of writes.
175 ; Classification of each insn
176 ; normal any data instruction that doesn't hit memory or fp regs
177 ; mult a multiply instruction
178 ; block blockage insn, this blocks all functional units
179 ; float a floating point arithmetic operation (subject to expansion)
180 ; fdivd DFmode floating point division
181 ; fdivs SFmode floating point division
182 ; fmul Floating point multiply
183 ; ffmul Fast floating point multiply
184 ; farith Floating point arithmetic (4 cycle)
185 ; ffarith Fast floating point arithmetic (2 cycle)
186 ; float_em a floating point arithmetic operation that is normally emulated
187 ; even on a machine with an fpa.
188 ; f_load a floating point load from memory
189 ; f_store a floating point store to memory
190 ; f_mem_r a transfer of a floating point register to a real reg via mem
191 ; r_mem_f the reverse of f_mem_r
192 ; f_2_r fast transfer float to arm (no memory needed)
193 ; r_2_f fast transfer arm to float
194 ; call a subroutine call
195 ; load any load from memory
196 ; store1 store 1 word to memory from arm registers
197 ; store2 store 2 words
198 ; store3 store 3 words
199 ; store4 store 4 words
200 ; Additions for Cirrus Maverick co-processor:
201 ; mav_farith Floating point arithmetic (4 cycle)
202 ; mav_dmult Double multiplies (7 cycle)
205 "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4,mav_farith,mav_dmult"
206 (const_string "normal"))
208 ; Load scheduling, set from the arm_ld_sched variable
209 ; initialized by arm_override_options()
210 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
212 ; condition codes: this one is used by final_prescan_insn to speed up
213 ; conditionalizing instructions. It saves having to scan the rtl to see if
214 ; it uses or alters the condition codes.
216 ; USE means that the condition codes are used by the insn in the process of
217 ; outputting code, this means (at present) that we can't use the insn in
220 ; SET means that the purpose of the insn is to set the condition codes in a
221 ; well defined manner.
223 ; CLOB means that the condition codes are altered in an undefined manner, if
224 ; they are altered at all
226 ; JUMP_CLOB is used when the condition cannot be represented by a single
227 ; instruction (UNEQ and LTGT). These cannot be predicated.
229 ; NOCOND means that the condition codes are neither altered nor affect the
230 ; output of this insn
232 (define_attr "conds" "use,set,clob,jump_clob,nocond"
233 (if_then_else (eq_attr "type" "call")
234 (if_then_else (eq_attr "prog_mode" "prog32")
235 (const_string "clob") (const_string "nocond"))
236 (const_string "nocond")))
238 ; Predicable means that the insn can be conditionally executed based on
239 ; an automatically added predicate (additional patterns are generated by
240 ; gen...). We default to 'no' because no Thumb patterns match this rule
241 ; and not all ARM patterns do.
242 (define_attr "predicable" "no,yes" (const_string "no"))
244 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
245 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
246 ; suffer blockages enough to warrant modelling this (and it can adversely
247 ; affect the schedule).
248 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
250 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
251 ; to stall the processor. Used with model_wbuf above.
252 (define_attr "write_conflict" "no,yes"
253 (if_then_else (eq_attr "type"
254 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
256 (const_string "no")))
258 ; Classify the insns into those that take one cycle and those that take more
259 ; than one on the main cpu execution unit.
260 (define_attr "core_cycles" "single,multi"
261 (if_then_else (eq_attr "type"
262 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
263 (const_string "single")
264 (const_string "multi")))
266 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
267 ;; distant label. Only applicable to Thumb code.
268 (define_attr "far_jump" "yes,no" (const_string "no"))
270 (define_automaton "arm")
274 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
276 ; The write buffer on some of the arm6 processors is hard to model exactly.
277 ; There is room in the buffer for up to two addresses and up to eight words
278 ; of memory, but the two needn't be split evenly. When writing the two
279 ; addresses are fully pipelined. However, a read from memory that is not
280 ; currently in the cache will block until the writes have completed.
281 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
282 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
283 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
284 ; cycle to add as well.
285 (define_cpu_unit "write_buf" "arm")
287 ;; Write blockage unit
289 ; The write_blockage unit models (partially), the fact that reads will stall
290 ; until the write buffer empties.
291 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
292 ; so we don't model them here
293 (define_cpu_unit "write_blockage" "arm")
297 (define_cpu_unit "core" "arm")
299 (define_insn_reservation "r_mem_f_wbuf" 5
300 (and (eq_attr "model_wbuf" "yes")
301 (eq_attr "type" "r_mem_f"))
304 (define_insn_reservation "store1_wbuf" 5
305 (and (eq_attr "model_wbuf" "yes")
306 (eq_attr "type" "store1"))
307 "core+write_buf*3+write_blockage*5")
309 (define_insn_reservation "store2_wbuf" 7
310 (and (eq_attr "model_wbuf" "yes")
311 (eq_attr "type" "store2"))
312 "core+write_buf*4+write_blockage*7")
314 (define_insn_reservation "store3_wbuf" 9
315 (and (eq_attr "model_wbuf" "yes")
316 (eq_attr "type" "store3"))
317 "core+write_buf*5+write_blockage*9")
319 (define_insn_reservation "store4_wbuf" 11
320 (and (eq_attr "model_wbuf" "yes")
321 (eq_attr "type" "store4"))
322 "core+write_buf*6+write_blockage*11")
324 (define_insn_reservation "store2" 3
325 (and (eq_attr "model_wbuf" "no")
326 (eq_attr "type" "store2"))
329 (define_insn_reservation "store3" 4
330 (and (eq_attr "model_wbuf" "no")
331 (eq_attr "type" "store3"))
334 (define_insn_reservation "store4" 5
335 (and (eq_attr "model_wbuf" "no")
336 (eq_attr "type" "store4"))
339 (define_insn_reservation "store1_ldsched" 1
340 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1"))
343 (define_insn_reservation "load_ldsched_xscale" 3
344 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
345 (eq_attr "is_xscale" "yes"))
348 (define_insn_reservation "load_ldsched" 2
349 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
350 (eq_attr "is_xscale" "no"))
353 (define_insn_reservation "load_or_store" 2
354 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1"))
357 (define_insn_reservation "mult" 16
358 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult"))
361 (define_insn_reservation "mult_ldsched_strongarm" 3
362 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
363 (eq_attr "type" "mult"))
366 (define_insn_reservation "mult_ldsched" 4
367 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
368 (eq_attr "type" "mult"))
371 (define_insn_reservation "multi_cycle" 32
372 (and (eq_attr "core_cycles" "multi")
373 (eq_attr "type" "!mult,load,store1,store2,store3,store4"))
376 (define_insn_reservation "single_cycle" 1
377 (eq_attr "core_cycles" "single")
381 ;;---------------------------------------------------------------------------
386 ;; Note: For DImode insns, there is normally no reason why operands should
387 ;; not be in the same register, what we don't want is for something being
388 ;; written to partially overlap something that is an input.
389 ;; Cirrus 64bit additions should not be split because we have a native
390 ;; 64bit addition instructions.
392 (define_expand "adddi3"
394 [(set (match_operand:DI 0 "s_register_operand" "")
395 (plus:DI (match_operand:DI 1 "s_register_operand" "")
396 (match_operand:DI 2 "s_register_operand" "")))
397 (clobber (reg:CC CC_REGNUM))])]
402 if (!cirrus_fp_register (operands[0], DImode))
403 operands[0] = force_reg (DImode, operands[0]);
404 if (!cirrus_fp_register (operands[1], DImode))
405 operands[1] = force_reg (DImode, operands[1]);
406 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
412 if (GET_CODE (operands[1]) != REG)
413 operands[1] = force_reg (SImode, operands[1]);
414 if (GET_CODE (operands[2]) != REG)
415 operands[2] = force_reg (SImode, operands[2]);
420 (define_insn "*thumb_adddi3"
421 [(set (match_operand:DI 0 "register_operand" "=l")
422 (plus:DI (match_operand:DI 1 "register_operand" "%0")
423 (match_operand:DI 2 "register_operand" "l")))
424 (clobber (reg:CC CC_REGNUM))
427 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
428 [(set_attr "length" "4")]
431 (define_insn_and_split "*arm_adddi3"
432 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
433 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
434 (match_operand:DI 2 "s_register_operand" "r, 0")))
435 (clobber (reg:CC CC_REGNUM))]
436 "TARGET_ARM && !TARGET_CIRRUS"
438 "TARGET_ARM && reload_completed"
439 [(parallel [(set (reg:CC_C CC_REGNUM)
440 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
442 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
443 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
444 (plus:SI (match_dup 4) (match_dup 5))))]
447 operands[3] = gen_highpart (SImode, operands[0]);
448 operands[0] = gen_lowpart (SImode, operands[0]);
449 operands[4] = gen_highpart (SImode, operands[1]);
450 operands[1] = gen_lowpart (SImode, operands[1]);
451 operands[5] = gen_highpart (SImode, operands[2]);
452 operands[2] = gen_lowpart (SImode, operands[2]);
454 [(set_attr "conds" "clob")
455 (set_attr "length" "8")]
458 (define_insn_and_split "*adddi_sesidi_di"
459 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
460 (plus:DI (sign_extend:DI
461 (match_operand:SI 2 "s_register_operand" "r,r"))
462 (match_operand:DI 1 "s_register_operand" "r,0")))
463 (clobber (reg:CC CC_REGNUM))]
464 "TARGET_ARM && !TARGET_CIRRUS"
466 "TARGET_ARM && reload_completed"
467 [(parallel [(set (reg:CC_C CC_REGNUM)
468 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
470 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
471 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
472 (plus:SI (ashiftrt:SI (match_dup 2)
477 operands[3] = gen_highpart (SImode, operands[0]);
478 operands[0] = gen_lowpart (SImode, operands[0]);
479 operands[4] = gen_highpart (SImode, operands[1]);
480 operands[1] = gen_lowpart (SImode, operands[1]);
481 operands[2] = gen_lowpart (SImode, operands[2]);
483 [(set_attr "conds" "clob")
484 (set_attr "length" "8")]
487 (define_insn_and_split "*adddi_zesidi_di"
488 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
489 (plus:DI (zero_extend:DI
490 (match_operand:SI 2 "s_register_operand" "r,r"))
491 (match_operand:DI 1 "s_register_operand" "r,0")))
492 (clobber (reg:CC CC_REGNUM))]
493 "TARGET_ARM && !TARGET_CIRRUS"
495 "TARGET_ARM && reload_completed"
496 [(parallel [(set (reg:CC_C CC_REGNUM)
497 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
499 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
500 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
501 (plus:SI (match_dup 4) (const_int 0))))]
504 operands[3] = gen_highpart (SImode, operands[0]);
505 operands[0] = gen_lowpart (SImode, operands[0]);
506 operands[4] = gen_highpart (SImode, operands[1]);
507 operands[1] = gen_lowpart (SImode, operands[1]);
508 operands[2] = gen_lowpart (SImode, operands[2]);
510 [(set_attr "conds" "clob")
511 (set_attr "length" "8")]
514 (define_expand "addsi3"
515 [(set (match_operand:SI 0 "s_register_operand" "")
516 (plus:SI (match_operand:SI 1 "s_register_operand" "")
517 (match_operand:SI 2 "reg_or_int_operand" "")))]
520 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
522 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
524 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
530 ; If there is a scratch available, this will be faster than synthesizing the
533 [(match_scratch:SI 3 "r")
534 (set (match_operand:SI 0 "s_register_operand" "")
535 (plus:SI (match_operand:SI 1 "s_register_operand" "")
536 (match_operand:SI 2 "const_int_operand" "")))]
538 !(const_ok_for_arm (INTVAL (operands[2]))
539 || const_ok_for_arm (-INTVAL (operands[2])))
540 && const_ok_for_arm (~INTVAL (operands[2]))"
541 [(set (match_dup 3) (match_dup 2))
542 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
546 (define_insn_and_split "*arm_addsi3"
547 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
548 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
549 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
556 GET_CODE (operands[2]) == CONST_INT
557 && !(const_ok_for_arm (INTVAL (operands[2]))
558 || const_ok_for_arm (-INTVAL (operands[2])))"
559 [(clobber (const_int 0))]
561 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
565 [(set_attr "length" "4,4,16")
566 (set_attr "predicable" "yes")]
569 ;; Register group 'k' is a single register group containing only the stack
570 ;; register. Trying to reload it will always fail catastrophically,
571 ;; so never allow those alternatives to match if reloading is needed.
573 (define_insn "*thumb_addsi3"
574 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
575 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
576 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
579 static const char * const asms[] =
581 \"add\\t%0, %0, %2\",
582 \"sub\\t%0, %0, #%n2\",
583 \"add\\t%0, %1, %2\",
584 \"add\\t%0, %0, %2\",
585 \"add\\t%0, %0, %2\",
586 \"add\\t%0, %1, %2\",
589 if ((which_alternative == 2 || which_alternative == 6)
590 && GET_CODE (operands[2]) == CONST_INT
591 && INTVAL (operands[2]) < 0)
592 return \"sub\\t%0, %1, #%n2\";
593 return asms[which_alternative];
595 [(set_attr "length" "2")]
598 ;; Reloading and elimination of the frame pointer can
599 ;; sometimes cause this optimization to be missed.
601 [(set (match_operand:SI 0 "register_operand" "")
602 (match_operand:SI 1 "const_int_operand" ""))
604 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
606 && REGNO (operands[2]) == STACK_POINTER_REGNUM
607 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
608 && (INTVAL (operands[1]) & 3) == 0"
609 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
613 (define_insn "*addsi3_compare0"
614 [(set (reg:CC_NOOV CC_REGNUM)
616 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
617 (match_operand:SI 2 "arm_add_operand" "rI,L"))
619 (set (match_operand:SI 0 "s_register_operand" "=r,r")
620 (plus:SI (match_dup 1) (match_dup 2)))]
624 sub%?s\\t%0, %1, #%n2"
625 [(set_attr "conds" "set")]
628 (define_insn "*addsi3_compare0_scratch"
629 [(set (reg:CC_NOOV CC_REGNUM)
631 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
632 (match_operand:SI 1 "arm_add_operand" "rI,L"))
638 [(set_attr "conds" "set")]
641 ;; These patterns are the same ones as the two regular addsi3_compare0
642 ;; patterns, except we write them slightly different - the combiner
643 ;; tends to generate them this way.
644 (define_insn "*addsi3_compare0_for_combiner"
645 [(set (reg:CC CC_REGNUM)
647 (match_operand:SI 1 "s_register_operand" "r,r")
648 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
649 (set (match_operand:SI 0 "s_register_operand" "=r,r")
650 (plus:SI (match_dup 1) (match_dup 2)))]
654 sub%?s\\t%0, %1, #%n2"
655 [(set_attr "conds" "set")]
658 (define_insn "*addsi3_compare0_scratch_for_combiner"
659 [(set (reg:CC CC_REGNUM)
661 (match_operand:SI 0 "s_register_operand" "r,r")
662 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
667 [(set_attr "conds" "set")]
670 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
671 ;; addend is a constant.
672 (define_insn "*cmpsi2_addneg"
673 [(set (reg:CC CC_REGNUM)
675 (match_operand:SI 1 "s_register_operand" "r,r")
676 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
677 (set (match_operand:SI 0 "s_register_operand" "=r,r")
678 (plus:SI (match_dup 1)
679 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
680 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
683 add%?s\\t%0, %1, #%n2"
684 [(set_attr "conds" "set")]
687 ;; Convert the sequence
689 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
693 ;; bcs dest ((unsigned)rn >= 1)
694 ;; similarly for the beq variant using bcc.
695 ;; This is a common looping idiom (while (n--))
697 [(set (match_operand:SI 0 "s_register_operand" "")
698 (plus:SI (match_operand:SI 1 "s_register_operand" "")
700 (set (match_operand 2 "cc_register" "")
701 (compare (match_dup 0) (const_int -1)))
703 (if_then_else (match_operator 3 "equality_operator"
704 [(match_dup 2) (const_int 0)])
705 (match_operand 4 "" "")
706 (match_operand 5 "" "")))]
707 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
711 (match_dup 1) (const_int 1)))
712 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
714 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
717 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
718 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
721 operands[2], const0_rtx);"
724 ;; The next four insns work because they compare the result with one of
725 ;; the operands, and we know that the use of the condition code is
726 ;; either GEU or LTU, so we can use the carry flag from the addition
727 ;; instead of doing the compare a second time.
728 (define_insn "*addsi3_compare_op1"
729 [(set (reg:CC_C CC_REGNUM)
731 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
732 (match_operand:SI 2 "arm_add_operand" "rI,L"))
734 (set (match_operand:SI 0 "s_register_operand" "=r,r")
735 (plus:SI (match_dup 1) (match_dup 2)))]
739 sub%?s\\t%0, %1, #%n2"
740 [(set_attr "conds" "set")]
743 (define_insn "*addsi3_compare_op2"
744 [(set (reg:CC_C CC_REGNUM)
746 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
747 (match_operand:SI 2 "arm_add_operand" "rI,L"))
749 (set (match_operand:SI 0 "s_register_operand" "=r,r")
750 (plus:SI (match_dup 1) (match_dup 2)))]
754 sub%?s\\t%0, %1, #%n2"
755 [(set_attr "conds" "set")]
758 (define_insn "*compare_addsi2_op0"
759 [(set (reg:CC_C CC_REGNUM)
761 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
762 (match_operand:SI 1 "arm_add_operand" "rI,L"))
768 [(set_attr "conds" "set")]
771 (define_insn "*compare_addsi2_op1"
772 [(set (reg:CC_C CC_REGNUM)
774 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
775 (match_operand:SI 1 "arm_add_operand" "rI,L"))
781 [(set_attr "conds" "set")]
784 (define_insn "*addsi3_carryin"
785 [(set (match_operand:SI 0 "s_register_operand" "=r")
786 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
787 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
788 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
791 [(set_attr "conds" "use")]
794 (define_insn "*addsi3_carryin_shift"
795 [(set (match_operand:SI 0 "s_register_operand" "=r")
796 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
798 (match_operator:SI 2 "shift_operator"
799 [(match_operand:SI 3 "s_register_operand" "r")
800 (match_operand:SI 4 "reg_or_int_operand" "rM")])
801 (match_operand:SI 1 "s_register_operand" "r"))))]
803 "adc%?\\t%0, %1, %3%S2"
804 [(set_attr "conds" "use")]
807 (define_insn "*addsi3_carryin_alt1"
808 [(set (match_operand:SI 0 "s_register_operand" "=r")
809 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
810 (match_operand:SI 2 "arm_rhs_operand" "rI"))
811 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
814 [(set_attr "conds" "use")]
817 (define_insn "*addsi3_carryin_alt2"
818 [(set (match_operand:SI 0 "s_register_operand" "=r")
819 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
820 (match_operand:SI 1 "s_register_operand" "r"))
821 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
824 [(set_attr "conds" "use")]
827 (define_insn "*addsi3_carryin_alt3"
828 [(set (match_operand:SI 0 "s_register_operand" "=r")
829 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
830 (match_operand:SI 2 "arm_rhs_operand" "rI"))
831 (match_operand:SI 1 "s_register_operand" "r")))]
834 [(set_attr "conds" "use")]
837 (define_insn "incscc"
838 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
839 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
840 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
841 (match_operand:SI 1 "s_register_operand" "0,?r")))]
845 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
846 [(set_attr "conds" "use")
847 (set_attr "length" "4,8")]
850 ; transform ((x << y) - 1) to ~(~(x-1) << y) Where X is a constant.
852 [(set (match_operand:SI 0 "s_register_operand" "")
853 (plus:SI (ashift:SI (match_operand:SI 1 "const_int_operand" "")
854 (match_operand:SI 2 "s_register_operand" ""))
856 (clobber (match_operand:SI 3 "s_register_operand" ""))]
858 [(set (match_dup 3) (match_dup 1))
859 (set (match_dup 0) (not:SI (ashift:SI (match_dup 3) (match_dup 2))))]
861 operands[1] = GEN_INT (~(INTVAL (operands[1]) - 1));
864 (define_expand "addsf3"
865 [(set (match_operand:SF 0 "s_register_operand" "")
866 (plus:SF (match_operand:SF 1 "s_register_operand" "")
867 (match_operand:SF 2 "fpa_add_operand" "")))]
868 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
871 && !cirrus_fp_register (operands[2], SFmode))
872 operands[2] = force_reg (SFmode, operands[2]);
875 (define_expand "adddf3"
876 [(set (match_operand:DF 0 "s_register_operand" "")
877 (plus:DF (match_operand:DF 1 "s_register_operand" "")
878 (match_operand:DF 2 "fpa_add_operand" "")))]
879 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
882 && !cirrus_fp_register (operands[2], DFmode))
883 operands[2] = force_reg (DFmode, operands[2]);
886 (define_expand "subdi3"
888 [(set (match_operand:DI 0 "s_register_operand" "")
889 (minus:DI (match_operand:DI 1 "s_register_operand" "")
890 (match_operand:DI 2 "s_register_operand" "")))
891 (clobber (reg:CC CC_REGNUM))])]
896 && cirrus_fp_register (operands[0], DImode)
897 && cirrus_fp_register (operands[1], DImode))
899 emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
905 if (GET_CODE (operands[1]) != REG)
906 operands[1] = force_reg (SImode, operands[1]);
907 if (GET_CODE (operands[2]) != REG)
908 operands[2] = force_reg (SImode, operands[2]);
913 (define_insn "*arm_subdi3"
914 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
915 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
916 (match_operand:DI 2 "s_register_operand" "r,0,0")))
917 (clobber (reg:CC CC_REGNUM))]
919 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
920 [(set_attr "conds" "clob")
921 (set_attr "length" "8")]
924 (define_insn "*thumb_subdi3"
925 [(set (match_operand:DI 0 "register_operand" "=l")
926 (minus:DI (match_operand:DI 1 "register_operand" "0")
927 (match_operand:DI 2 "register_operand" "l")))
928 (clobber (reg:CC CC_REGNUM))]
930 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
931 [(set_attr "length" "4")]
934 (define_insn "*subdi_di_zesidi"
935 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
936 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
938 (match_operand:SI 2 "s_register_operand" "r,r"))))
939 (clobber (reg:CC CC_REGNUM))]
941 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
942 [(set_attr "conds" "clob")
943 (set_attr "length" "8")]
946 (define_insn "*subdi_di_sesidi"
947 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
948 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
950 (match_operand:SI 2 "s_register_operand" "r,r"))))
951 (clobber (reg:CC CC_REGNUM))]
953 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
954 [(set_attr "conds" "clob")
955 (set_attr "length" "8")]
958 (define_insn "*subdi_zesidi_di"
959 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
960 (minus:DI (zero_extend:DI
961 (match_operand:SI 2 "s_register_operand" "r,r"))
962 (match_operand:DI 1 "s_register_operand" "?r,0")))
963 (clobber (reg:CC CC_REGNUM))]
965 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
966 [(set_attr "conds" "clob")
967 (set_attr "length" "8")]
970 (define_insn "*subdi_sesidi_di"
971 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
972 (minus:DI (sign_extend:DI
973 (match_operand:SI 2 "s_register_operand" "r,r"))
974 (match_operand:DI 1 "s_register_operand" "?r,0")))
975 (clobber (reg:CC CC_REGNUM))]
977 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
978 [(set_attr "conds" "clob")
979 (set_attr "length" "8")]
982 (define_insn "*subdi_zesidi_zesidi"
983 [(set (match_operand:DI 0 "s_register_operand" "=r")
984 (minus:DI (zero_extend:DI
985 (match_operand:SI 1 "s_register_operand" "r"))
987 (match_operand:SI 2 "s_register_operand" "r"))))
988 (clobber (reg:CC CC_REGNUM))]
990 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
991 [(set_attr "conds" "clob")
992 (set_attr "length" "8")]
995 (define_expand "subsi3"
996 [(set (match_operand:SI 0 "s_register_operand" "")
997 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
998 (match_operand:SI 2 "s_register_operand" "")))]
1001 if (GET_CODE (operands[1]) == CONST_INT)
1005 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1008 : preserve_subexpressions_p ()));
1011 else /* TARGET_THUMB */
1012 operands[1] = force_reg (SImode, operands[1]);
1017 (define_insn "*thumb_subsi3_insn"
1018 [(set (match_operand:SI 0 "register_operand" "=l")
1019 (minus:SI (match_operand:SI 1 "register_operand" "l")
1020 (match_operand:SI 2 "register_operand" "l")))]
1023 [(set_attr "length" "2")]
1026 (define_insn_and_split "*arm_subsi3_insn"
1027 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1028 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
1029 (match_operand:SI 2 "s_register_operand" "r,r")))]
1035 && GET_CODE (operands[1]) == CONST_INT
1036 && !const_ok_for_arm (INTVAL (operands[1]))"
1037 [(clobber (const_int 0))]
1039 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
1043 [(set_attr "length" "4,16")
1044 (set_attr "predicable" "yes")]
1048 [(match_scratch:SI 3 "r")
1049 (set (match_operand:SI 0 "s_register_operand" "")
1050 (minus:SI (match_operand:SI 1 "const_int_operand" "")
1051 (match_operand:SI 2 "s_register_operand" "")))]
1053 && !const_ok_for_arm (INTVAL (operands[1]))
1054 && const_ok_for_arm (~INTVAL (operands[1]))"
1055 [(set (match_dup 3) (match_dup 1))
1056 (set (match_dup 0) (minus:SI (match_dup 3) (match_dup 2)))]
1060 (define_insn "*subsi3_compare0"
1061 [(set (reg:CC_NOOV CC_REGNUM)
1063 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1064 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1066 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1067 (minus:SI (match_dup 1) (match_dup 2)))]
1071 rsb%?s\\t%0, %2, %1"
1072 [(set_attr "conds" "set")]
1075 (define_insn "decscc"
1076 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1077 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1078 (match_operator:SI 2 "arm_comparison_operator"
1079 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1083 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1084 [(set_attr "conds" "use")
1085 (set_attr "length" "*,8")]
1088 (define_expand "subsf3"
1089 [(set (match_operand:SF 0 "s_register_operand" "")
1090 (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1091 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1092 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1096 if (!cirrus_fp_register (operands[1], SFmode))
1097 operands[1] = force_reg (SFmode, operands[1]);
1098 if (!cirrus_fp_register (operands[2], SFmode))
1099 operands[2] = force_reg (SFmode, operands[2]);
1103 (define_expand "subdf3"
1104 [(set (match_operand:DF 0 "s_register_operand" "")
1105 (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1106 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1107 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1111 if (!cirrus_fp_register (operands[1], DFmode))
1112 operands[1] = force_reg (DFmode, operands[1]);
1113 if (!cirrus_fp_register (operands[2], DFmode))
1114 operands[2] = force_reg (DFmode, operands[2]);
1119 ;; Multiplication insns
1121 (define_expand "mulsi3"
1122 [(set (match_operand:SI 0 "s_register_operand" "")
1123 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1124 (match_operand:SI 1 "s_register_operand" "")))]
1129 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1130 (define_insn "*arm_mulsi3"
1131 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1132 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1133 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1135 "mul%?\\t%0, %2, %1"
1136 [(set_attr "type" "mult")
1137 (set_attr "predicable" "yes")]
1140 ; Unfortunately with the Thumb the '&'/'0' trick can fails when operands
1141 ; 1 and 2; are the same, because reload will make operand 0 match
1142 ; operand 1 without realizing that this conflicts with operand 2. We fix
1143 ; this by adding another alternative to match this case, and then `reload'
1144 ; it ourselves. This alternative must come first.
1145 (define_insn "*thumb_mulsi3"
1146 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1147 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1148 (match_operand:SI 2 "register_operand" "l,l,l")))]
1151 if (which_alternative < 2)
1152 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1154 return \"mul\\t%0, %0, %2\";
1156 [(set_attr "length" "4,4,2")
1157 (set_attr "type" "mult")]
1160 (define_insn "*mulsi3_compare0"
1161 [(set (reg:CC_NOOV CC_REGNUM)
1162 (compare:CC_NOOV (mult:SI
1163 (match_operand:SI 2 "s_register_operand" "r,r")
1164 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1166 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1167 (mult:SI (match_dup 2) (match_dup 1)))]
1168 "TARGET_ARM && !arm_arch_xscale"
1169 "mul%?s\\t%0, %2, %1"
1170 [(set_attr "conds" "set")
1171 (set_attr "type" "mult")]
1174 (define_insn "*mulsi_compare0_scratch"
1175 [(set (reg:CC_NOOV CC_REGNUM)
1176 (compare:CC_NOOV (mult:SI
1177 (match_operand:SI 2 "s_register_operand" "r,r")
1178 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1180 (clobber (match_scratch:SI 0 "=&r,&r"))]
1181 "TARGET_ARM && !arm_arch_xscale"
1182 "mul%?s\\t%0, %2, %1"
1183 [(set_attr "conds" "set")
1184 (set_attr "type" "mult")]
1187 ;; Unnamed templates to match MLA instruction.
1189 (define_insn "*mulsi3addsi"
1190 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1192 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1193 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1194 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1196 "mla%?\\t%0, %2, %1, %3"
1197 [(set_attr "type" "mult")
1198 (set_attr "predicable" "yes")]
1201 (define_insn "*mulsi3addsi_compare0"
1202 [(set (reg:CC_NOOV CC_REGNUM)
1205 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1206 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1207 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1209 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1210 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1212 "TARGET_ARM && !arm_arch_xscale"
1213 "mla%?s\\t%0, %2, %1, %3"
1214 [(set_attr "conds" "set")
1215 (set_attr "type" "mult")]
1218 (define_insn "*mulsi3addsi_compare0_scratch"
1219 [(set (reg:CC_NOOV CC_REGNUM)
1222 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1223 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1224 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1226 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1227 "TARGET_ARM && !arm_arch_xscale"
1228 "mla%?s\\t%0, %2, %1, %3"
1229 [(set_attr "conds" "set")
1230 (set_attr "type" "mult")]
1233 ;; Unnamed template to match long long multiply-accumulate (smlal)
1235 (define_insn "*mulsidi3adddi"
1236 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1239 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1240 (sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1241 (match_operand:DI 1 "s_register_operand" "0")))]
1242 "TARGET_ARM && arm_fast_multiply"
1243 "smlal%?\\t%Q0, %R0, %3, %2"
1244 [(set_attr "type" "mult")
1245 (set_attr "predicable" "yes")]
1248 (define_insn "mulsidi3"
1249 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1251 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1252 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1253 "TARGET_ARM && arm_fast_multiply"
1254 "smull%?\\t%Q0, %R0, %1, %2"
1255 [(set_attr "type" "mult")
1256 (set_attr "predicable" "yes")]
1259 (define_insn "umulsidi3"
1260 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1262 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
1263 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
1264 "TARGET_ARM && arm_fast_multiply"
1265 "umull%?\\t%Q0, %R0, %1, %2"
1266 [(set_attr "type" "mult")
1267 (set_attr "predicable" "yes")]
1270 ;; Unnamed template to match long long unsigned multiply-accumulate (umlal)
1272 (define_insn "*umulsidi3adddi"
1273 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1276 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
1277 (zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
1278 (match_operand:DI 1 "s_register_operand" "0")))]
1279 "TARGET_ARM && arm_fast_multiply"
1280 "umlal%?\\t%Q0, %R0, %3, %2"
1281 [(set_attr "type" "mult")
1282 (set_attr "predicable" "yes")]
1285 (define_insn "smulsi3_highpart"
1286 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1290 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1291 (sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1293 (clobber (match_scratch:SI 3 "=&r,&r"))]
1294 "TARGET_ARM && arm_fast_multiply"
1295 "smull%?\\t%3, %0, %2, %1"
1296 [(set_attr "type" "mult")
1297 (set_attr "predicable" "yes")]
1300 (define_insn "umulsi3_highpart"
1301 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1305 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r,0"))
1306 (zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
1308 (clobber (match_scratch:SI 3 "=&r,&r"))]
1309 "TARGET_ARM && arm_fast_multiply"
1310 "umull%?\\t%3, %0, %2, %1"
1311 [(set_attr "type" "mult")
1312 (set_attr "predicable" "yes")]
1315 (define_insn "mulhisi3"
1316 [(set (match_operand:SI 0 "s_register_operand" "=r")
1317 (mult:SI (sign_extend:SI
1318 (match_operand:HI 1 "s_register_operand" "%r"))
1320 (match_operand:HI 2 "s_register_operand" "r"))))]
1321 "TARGET_ARM && arm_arch5e"
1322 "smulbb%?\\t%0, %1, %2"
1323 [(set_attr "type" "mult")
1324 (set_attr "predicable" "yes")]
1327 (define_insn "*mulhisi3tb"
1328 [(set (match_operand:SI 0 "s_register_operand" "=r")
1329 (mult:SI (ashiftrt:SI
1330 (match_operand:SI 1 "s_register_operand" "r")
1333 (match_operand:HI 2 "s_register_operand" "r"))))]
1334 "TARGET_ARM && arm_arch5e"
1335 "smultb%?\\t%0, %1, %2"
1336 [(set_attr "type" "mult")
1337 (set_attr "predicable" "yes")]
1340 (define_insn "*mulhisi3bt"
1341 [(set (match_operand:SI 0 "s_register_operand" "=r")
1342 (mult:SI (sign_extend:SI
1343 (match_operand:HI 1 "s_register_operand" "r"))
1345 (match_operand:SI 2 "s_register_operand" "r")
1347 "TARGET_ARM && arm_arch5e"
1348 "smulbt%?\\t%0, %1, %2"
1349 [(set_attr "type" "mult")
1350 (set_attr "predicable" "yes")]
1353 (define_insn "*mulhisi3tt"
1354 [(set (match_operand:SI 0 "s_register_operand" "=r")
1355 (mult:SI (ashiftrt:SI
1356 (match_operand:SI 1 "s_register_operand" "r")
1359 (match_operand:SI 2 "s_register_operand" "r")
1361 "TARGET_ARM && arm_arch5e"
1362 "smultt%?\\t%0, %1, %2"
1363 [(set_attr "type" "mult")
1364 (set_attr "predicable" "yes")]
1367 (define_insn "*mulhisi3addsi"
1368 [(set (match_operand:SI 0 "s_register_operand" "=r")
1369 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
1370 (mult:SI (sign_extend:SI
1371 (match_operand:HI 2 "s_register_operand" "%r"))
1373 (match_operand:HI 3 "s_register_operand" "r")))))]
1374 "TARGET_ARM && arm_arch5e"
1375 "smlabb%?\\t%0, %2, %3, %1"
1376 [(set_attr "type" "mult")
1377 (set_attr "predicable" "yes")]
1380 (define_insn "*mulhidi3adddi"
1381 [(set (match_operand:DI 0 "s_register_operand" "=r")
1383 (match_operand:DI 1 "s_register_operand" "0")
1384 (mult:DI (sign_extend:DI
1385 (match_operand:HI 2 "s_register_operand" "%r"))
1387 (match_operand:HI 3 "s_register_operand" "r")))))]
1388 "TARGET_ARM && arm_arch5e"
1389 "smlalbb%?\\t%Q0, %R0, %2, %3"
1390 [(set_attr "type" "mult")
1391 (set_attr "predicable" "yes")])
1393 (define_expand "mulsf3"
1394 [(set (match_operand:SF 0 "s_register_operand" "")
1395 (mult:SF (match_operand:SF 1 "s_register_operand" "")
1396 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1397 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1400 && !cirrus_fp_register (operands[2], SFmode))
1401 operands[2] = force_reg (SFmode, operands[2]);
1404 (define_expand "muldf3"
1405 [(set (match_operand:DF 0 "s_register_operand" "")
1406 (mult:DF (match_operand:DF 1 "s_register_operand" "")
1407 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1408 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
1411 && !cirrus_fp_register (operands[2], DFmode))
1412 operands[2] = force_reg (DFmode, operands[2]);
1417 (define_expand "divsf3"
1418 [(set (match_operand:SF 0 "s_register_operand" "")
1419 (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
1420 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1421 "TARGET_ARM && TARGET_HARD_FLOAT"
1424 (define_expand "divdf3"
1425 [(set (match_operand:DF 0 "s_register_operand" "")
1426 (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
1427 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1428 "TARGET_ARM && TARGET_HARD_FLOAT"
1433 (define_expand "modsf3"
1434 [(set (match_operand:SF 0 "s_register_operand" "")
1435 (mod:SF (match_operand:SF 1 "s_register_operand" "")
1436 (match_operand:SF 2 "fpa_rhs_operand" "")))]
1437 "TARGET_ARM && TARGET_HARD_FLOAT"
1440 (define_expand "moddf3"
1441 [(set (match_operand:DF 0 "s_register_operand" "")
1442 (mod:DF (match_operand:DF 1 "s_register_operand" "")
1443 (match_operand:DF 2 "fpa_rhs_operand" "")))]
1444 "TARGET_ARM && TARGET_HARD_FLOAT"
1447 ;; Boolean and,ior,xor insns
1449 ;; Split up double word logical operations
1451 ;; Split up simple DImode logical operations. Simply perform the logical
1452 ;; operation on the upper and lower halves of the registers.
1454 [(set (match_operand:DI 0 "s_register_operand" "")
1455 (match_operator:DI 6 "logical_binary_operator"
1456 [(match_operand:DI 1 "s_register_operand" "")
1457 (match_operand:DI 2 "s_register_operand" "")]))]
1458 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1459 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1460 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1463 operands[3] = gen_highpart (SImode, operands[0]);
1464 operands[0] = gen_lowpart (SImode, operands[0]);
1465 operands[4] = gen_highpart (SImode, operands[1]);
1466 operands[1] = gen_lowpart (SImode, operands[1]);
1467 operands[5] = gen_highpart (SImode, operands[2]);
1468 operands[2] = gen_lowpart (SImode, operands[2]);
1473 [(set (match_operand:DI 0 "s_register_operand" "")
1474 (match_operator:DI 6 "logical_binary_operator"
1475 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1476 (match_operand:DI 1 "s_register_operand" "")]))]
1477 "TARGET_ARM && reload_completed"
1478 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1479 (set (match_dup 3) (match_op_dup:SI 6
1480 [(ashiftrt:SI (match_dup 2) (const_int 31))
1484 operands[3] = gen_highpart (SImode, operands[0]);
1485 operands[0] = gen_lowpart (SImode, operands[0]);
1486 operands[4] = gen_highpart (SImode, operands[1]);
1487 operands[1] = gen_lowpart (SImode, operands[1]);
1488 operands[5] = gen_highpart (SImode, operands[2]);
1489 operands[2] = gen_lowpart (SImode, operands[2]);
1493 ;; The zero extend of operand 2 means we can just copy the high part of
1494 ;; operand1 into operand0.
1496 [(set (match_operand:DI 0 "s_register_operand" "")
1498 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1499 (match_operand:DI 1 "s_register_operand" "")))]
1500 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1501 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1502 (set (match_dup 3) (match_dup 4))]
1505 operands[4] = gen_highpart (SImode, operands[1]);
1506 operands[3] = gen_highpart (SImode, operands[0]);
1507 operands[0] = gen_lowpart (SImode, operands[0]);
1508 operands[1] = gen_lowpart (SImode, operands[1]);
1512 ;; The zero extend of operand 2 means we can just copy the high part of
1513 ;; operand1 into operand0.
1515 [(set (match_operand:DI 0 "s_register_operand" "")
1517 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1518 (match_operand:DI 1 "s_register_operand" "")))]
1519 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1520 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1521 (set (match_dup 3) (match_dup 4))]
1524 operands[4] = gen_highpart (SImode, operands[1]);
1525 operands[3] = gen_highpart (SImode, operands[0]);
1526 operands[0] = gen_lowpart (SImode, operands[0]);
1527 operands[1] = gen_lowpart (SImode, operands[1]);
1531 (define_insn "anddi3"
1532 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1533 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1534 (match_operand:DI 2 "s_register_operand" "r,r")))]
1535 "TARGET_ARM && ! TARGET_IWMMXT"
1537 [(set_attr "length" "8")]
1540 (define_insn_and_split "*anddi_zesidi_di"
1541 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1542 (and:DI (zero_extend:DI
1543 (match_operand:SI 2 "s_register_operand" "r,r"))
1544 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1547 "TARGET_ARM && reload_completed"
1548 ; The zero extend of operand 2 clears the high word of the output
1550 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1551 (set (match_dup 3) (const_int 0))]
1554 operands[3] = gen_highpart (SImode, operands[0]);
1555 operands[0] = gen_lowpart (SImode, operands[0]);
1556 operands[1] = gen_lowpart (SImode, operands[1]);
1558 [(set_attr "length" "8")]
1561 (define_insn "*anddi_sesdi_di"
1562 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1563 (and:DI (sign_extend:DI
1564 (match_operand:SI 2 "s_register_operand" "r,r"))
1565 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1568 [(set_attr "length" "8")]
1571 (define_expand "andsi3"
1572 [(set (match_operand:SI 0 "s_register_operand" "")
1573 (and:SI (match_operand:SI 1 "s_register_operand" "")
1574 (match_operand:SI 2 "reg_or_int_operand" "")))]
1579 if (GET_CODE (operands[2]) == CONST_INT)
1581 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1584 ? 0 : preserve_subexpressions_p ()));
1588 else /* TARGET_THUMB */
1590 if (GET_CODE (operands[2]) != CONST_INT)
1591 operands[2] = force_reg (SImode, operands[2]);
1596 if (((unsigned HOST_WIDE_INT) ~INTVAL (operands[2])) < 256)
1598 operands[2] = force_reg (SImode,
1599 GEN_INT (~INTVAL (operands[2])));
1601 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1606 for (i = 9; i <= 31; i++)
1608 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1610 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1614 else if ((((HOST_WIDE_INT) 1) << i) - 1
1615 == ~INTVAL (operands[2]))
1617 rtx shift = GEN_INT (i);
1618 rtx reg = gen_reg_rtx (SImode);
1620 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1621 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1627 operands[2] = force_reg (SImode, operands[2]);
1633 (define_insn_and_split "*arm_andsi3_insn"
1634 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1635 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1636 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1640 bic%?\\t%0, %1, #%B2
1643 && GET_CODE (operands[2]) == CONST_INT
1644 && !(const_ok_for_arm (INTVAL (operands[2]))
1645 || const_ok_for_arm (~INTVAL (operands[2])))"
1646 [(clobber (const_int 0))]
1648 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1652 [(set_attr "length" "4,4,16")
1653 (set_attr "predicable" "yes")]
1656 (define_insn "*thumb_andsi3_insn"
1657 [(set (match_operand:SI 0 "register_operand" "=l")
1658 (and:SI (match_operand:SI 1 "register_operand" "%0")
1659 (match_operand:SI 2 "register_operand" "l")))]
1662 [(set_attr "length" "2")]
1665 (define_insn "*andsi3_compare0"
1666 [(set (reg:CC_NOOV CC_REGNUM)
1668 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1669 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1671 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1672 (and:SI (match_dup 1) (match_dup 2)))]
1676 bic%?s\\t%0, %1, #%B2"
1677 [(set_attr "conds" "set")]
1680 (define_insn "*andsi3_compare0_scratch"
1681 [(set (reg:CC_NOOV CC_REGNUM)
1683 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1684 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1686 (clobber (match_scratch:SI 2 "=X,r"))]
1690 bic%?s\\t%2, %0, #%B1"
1691 [(set_attr "conds" "set")]
1694 (define_insn "*zeroextractsi_compare0_scratch"
1695 [(set (reg:CC_NOOV CC_REGNUM)
1696 (compare:CC_NOOV (zero_extract:SI
1697 (match_operand:SI 0 "s_register_operand" "r")
1698 (match_operand 1 "const_int_operand" "n")
1699 (match_operand 2 "const_int_operand" "n"))
1702 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1703 && INTVAL (operands[1]) > 0
1704 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1705 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1707 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1708 << INTVAL (operands[2]));
1709 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1712 [(set_attr "conds" "set")]
1715 (define_insn "*ne_zeroextractsi"
1716 [(set (match_operand:SI 0 "s_register_operand" "=r")
1717 (ne:SI (zero_extract:SI
1718 (match_operand:SI 1 "s_register_operand" "r")
1719 (match_operand:SI 2 "const_int_operand" "n")
1720 (match_operand:SI 3 "const_int_operand" "n"))
1722 (clobber (reg:CC CC_REGNUM))]
1724 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1725 && INTVAL (operands[2]) > 0
1726 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1727 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1729 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1730 << INTVAL (operands[3]));
1731 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1732 return \"movne\\t%0, #1\";
1734 [(set_attr "conds" "clob")
1735 (set_attr "length" "8")]
1739 [(set (match_operand:SI 0 "s_register_operand" "")
1740 (zero_extract:SI (match_operand:SI 1 "s_register_operand" "")
1741 (match_operand:SI 2 "const_int_operand" "")
1742 (match_operand:SI 3 "const_int_operand" "")))
1743 (clobber (match_operand:SI 4 "s_register_operand" ""))]
1745 [(set (match_dup 4) (ashift:SI (match_dup 1) (match_dup 2)))
1746 (set (match_dup 0) (lshiftrt:SI (match_dup 4) (match_dup 3)))]
1748 HOST_WIDE_INT temp = INTVAL (operands[2]);
1750 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1751 operands[3] = GEN_INT (32 - temp);
1756 [(set (match_operand:SI 0 "s_register_operand" "")
1757 (match_operator:SI 1 "shiftable_operator"
1758 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
1759 (match_operand:SI 3 "const_int_operand" "")
1760 (match_operand:SI 4 "const_int_operand" ""))
1761 (match_operand:SI 5 "s_register_operand" "")]))
1762 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1764 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1767 [(lshiftrt:SI (match_dup 6) (match_dup 4))
1770 HOST_WIDE_INT temp = INTVAL (operands[3]);
1772 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1773 operands[4] = GEN_INT (32 - temp);
1778 [(set (match_operand:SI 0 "s_register_operand" "")
1779 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1780 (match_operand:SI 2 "const_int_operand" "")
1781 (match_operand:SI 3 "const_int_operand" "")))]
1783 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1784 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1786 HOST_WIDE_INT temp = INTVAL (operands[2]);
1788 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1789 operands[3] = GEN_INT (32 - temp);
1794 [(set (match_operand:SI 0 "s_register_operand" "")
1795 (match_operator:SI 1 "shiftable_operator"
1796 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
1797 (match_operand:SI 3 "const_int_operand" "")
1798 (match_operand:SI 4 "const_int_operand" ""))
1799 (match_operand:SI 5 "s_register_operand" "")]))
1800 (clobber (match_operand:SI 6 "s_register_operand" ""))]
1802 [(set (match_dup 6) (ashift:SI (match_dup 2) (match_dup 3)))
1805 [(ashiftrt:SI (match_dup 6) (match_dup 4))
1808 HOST_WIDE_INT temp = INTVAL (operands[3]);
1810 operands[3] = GEN_INT (32 - temp - INTVAL (operands[4]));
1811 operands[4] = GEN_INT (32 - temp);
1815 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1816 ;;; represented by the bitfield, then this will produce incorrect results.
1817 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1818 ;;; which have a real bit-field insert instruction, the truncation happens
1819 ;;; in the bit-field insert instruction itself. Since arm does not have a
1820 ;;; bit-field insert instruction, we would have to emit code here to truncate
1821 ;;; the value before we insert. This loses some of the advantage of having
1822 ;;; this insv pattern, so this pattern needs to be reevalutated.
1824 (define_expand "insv"
1825 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1826 (match_operand:SI 1 "general_operand" "")
1827 (match_operand:SI 2 "general_operand" ""))
1828 (match_operand:SI 3 "reg_or_int_operand" ""))]
1832 int start_bit = INTVAL (operands[2]);
1833 int width = INTVAL (operands[1]);
1834 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1835 rtx target, subtarget;
1837 target = operands[0];
1838 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1839 subreg as the final target. */
1840 if (GET_CODE (target) == SUBREG)
1842 subtarget = gen_reg_rtx (SImode);
1843 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1844 < GET_MODE_SIZE (SImode))
1845 target = SUBREG_REG (target);
1850 if (GET_CODE (operands[3]) == CONST_INT)
1852 /* Since we are inserting a known constant, we may be able to
1853 reduce the number of bits that we have to clear so that
1854 the mask becomes simple. */
1855 /* ??? This code does not check to see if the new mask is actually
1856 simpler. It may not be. */
1857 rtx op1 = gen_reg_rtx (SImode);
1858 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1859 start of this pattern. */
1860 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1861 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1863 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1864 emit_insn (gen_iorsi3 (subtarget, op1,
1865 GEN_INT (op3_value << start_bit)));
1867 else if (start_bit == 0
1868 && !(const_ok_for_arm (mask)
1869 || const_ok_for_arm (~mask)))
1871 /* A Trick, since we are setting the bottom bits in the word,
1872 we can shift operand[3] up, operand[0] down, OR them together
1873 and rotate the result back again. This takes 3 insns, and
1874 the third might be mergeable into another op. */
1875 /* The shift up copes with the possibility that operand[3] is
1876 wider than the bitfield. */
1877 rtx op0 = gen_reg_rtx (SImode);
1878 rtx op1 = gen_reg_rtx (SImode);
1880 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1881 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1882 emit_insn (gen_iorsi3 (op1, op1, op0));
1883 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1885 else if ((width + start_bit == 32)
1886 && !(const_ok_for_arm (mask)
1887 || const_ok_for_arm (~mask)))
1889 /* Similar trick, but slightly less efficient. */
1891 rtx op0 = gen_reg_rtx (SImode);
1892 rtx op1 = gen_reg_rtx (SImode);
1894 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1895 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1896 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1897 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1901 rtx op0 = GEN_INT (mask);
1902 rtx op1 = gen_reg_rtx (SImode);
1903 rtx op2 = gen_reg_rtx (SImode);
1905 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1907 rtx tmp = gen_reg_rtx (SImode);
1909 emit_insn (gen_movsi (tmp, op0));
1913 /* Mask out any bits in operand[3] that are not needed. */
1914 emit_insn (gen_andsi3 (op1, operands[3], op0));
1916 if (GET_CODE (op0) == CONST_INT
1917 && (const_ok_for_arm (mask << start_bit)
1918 || const_ok_for_arm (~(mask << start_bit))))
1920 op0 = GEN_INT (~(mask << start_bit));
1921 emit_insn (gen_andsi3 (op2, operands[0], op0));
1925 if (GET_CODE (op0) == CONST_INT)
1927 rtx tmp = gen_reg_rtx (SImode);
1929 emit_insn (gen_movsi (tmp, op0));
1934 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1936 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1940 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1942 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1945 if (subtarget != target)
1947 /* If TARGET is still a SUBREG, then it must be wider than a word,
1948 so we must be careful only to set the subword we were asked to. */
1949 if (GET_CODE (target) == SUBREG)
1950 emit_move_insn (target, subtarget);
1952 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1959 ; constants for op 2 will never be given to these patterns.
1960 (define_insn_and_split "*anddi_notdi_di"
1961 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1962 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1963 (match_operand:DI 2 "s_register_operand" "0,r")))]
1966 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1967 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1968 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1971 operands[3] = gen_highpart (SImode, operands[0]);
1972 operands[0] = gen_lowpart (SImode, operands[0]);
1973 operands[4] = gen_highpart (SImode, operands[1]);
1974 operands[1] = gen_lowpart (SImode, operands[1]);
1975 operands[5] = gen_highpart (SImode, operands[2]);
1976 operands[2] = gen_lowpart (SImode, operands[2]);
1978 [(set_attr "length" "8")
1979 (set_attr "predicable" "yes")]
1982 (define_insn_and_split "*anddi_notzesidi_di"
1983 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1984 (and:DI (not:DI (zero_extend:DI
1985 (match_operand:SI 2 "s_register_operand" "r,r")))
1986 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1989 bic%?\\t%Q0, %Q1, %2
1991 ; (not (zero_extend ...)) allows us to just copy the high word from
1992 ; operand1 to operand0.
1995 && operands[0] != operands[1]"
1996 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1997 (set (match_dup 3) (match_dup 4))]
2000 operands[3] = gen_highpart (SImode, operands[0]);
2001 operands[0] = gen_lowpart (SImode, operands[0]);
2002 operands[4] = gen_highpart (SImode, operands[1]);
2003 operands[1] = gen_lowpart (SImode, operands[1]);
2005 [(set_attr "length" "4,8")
2006 (set_attr "predicable" "yes")]
2009 (define_insn_and_split "*anddi_notsesidi_di"
2010 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2011 (and:DI (not:DI (sign_extend:DI
2012 (match_operand:SI 2 "s_register_operand" "r,r")))
2013 (match_operand:DI 1 "s_register_operand" "0,r")))]
2016 "TARGET_ARM && reload_completed"
2017 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
2018 (set (match_dup 3) (and:SI (not:SI
2019 (ashiftrt:SI (match_dup 2) (const_int 31)))
2023 operands[3] = gen_highpart (SImode, operands[0]);
2024 operands[0] = gen_lowpart (SImode, operands[0]);
2025 operands[4] = gen_highpart (SImode, operands[1]);
2026 operands[1] = gen_lowpart (SImode, operands[1]);
2028 [(set_attr "length" "8")
2029 (set_attr "predicable" "yes")]
2032 (define_insn "andsi_notsi_si"
2033 [(set (match_operand:SI 0 "s_register_operand" "=r")
2034 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2035 (match_operand:SI 1 "s_register_operand" "r")))]
2037 "bic%?\\t%0, %1, %2"
2038 [(set_attr "predicable" "yes")]
2041 (define_insn "bicsi3"
2042 [(set (match_operand:SI 0 "register_operand" "=l")
2043 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2044 (match_operand:SI 2 "register_operand" "0")))]
2047 [(set_attr "length" "2")]
2050 (define_insn "andsi_not_shiftsi_si"
2051 [(set (match_operand:SI 0 "s_register_operand" "=r")
2052 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2053 [(match_operand:SI 2 "s_register_operand" "r")
2054 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2055 (match_operand:SI 1 "s_register_operand" "r")))]
2057 "bic%?\\t%0, %1, %2%S4"
2058 [(set_attr "predicable" "yes")
2059 (set_attr "shift" "2")
2063 (define_insn "*andsi_notsi_si_compare0"
2064 [(set (reg:CC_NOOV CC_REGNUM)
2066 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2067 (match_operand:SI 1 "s_register_operand" "r"))
2069 (set (match_operand:SI 0 "s_register_operand" "=r")
2070 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2072 "bic%?s\\t%0, %1, %2"
2073 [(set_attr "conds" "set")]
2076 (define_insn "*andsi_notsi_si_compare0_scratch"
2077 [(set (reg:CC_NOOV CC_REGNUM)
2079 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2080 (match_operand:SI 1 "s_register_operand" "r"))
2082 (clobber (match_scratch:SI 0 "=r"))]
2084 "bic%?s\\t%0, %1, %2"
2085 [(set_attr "conds" "set")]
2088 (define_insn "iordi3"
2089 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2090 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2091 (match_operand:DI 2 "s_register_operand" "r,r")))]
2092 "TARGET_ARM && ! TARGET_IWMMXT"
2094 [(set_attr "length" "8")
2095 (set_attr "predicable" "yes")]
2098 (define_insn "*iordi_zesidi_di"
2099 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2100 (ior:DI (zero_extend:DI
2101 (match_operand:SI 2 "s_register_operand" "r,r"))
2102 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2105 orr%?\\t%Q0, %Q1, %2
2107 [(set_attr "length" "4,8")
2108 (set_attr "predicable" "yes")]
2111 (define_insn "*iordi_sesidi_di"
2112 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2113 (ior:DI (sign_extend:DI
2114 (match_operand:SI 2 "s_register_operand" "r,r"))
2115 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2118 [(set_attr "length" "8")
2119 (set_attr "predicable" "yes")]
2122 (define_expand "iorsi3"
2123 [(set (match_operand:SI 0 "s_register_operand" "")
2124 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2125 (match_operand:SI 2 "reg_or_int_operand" "")))]
2128 if (GET_CODE (operands[2]) == CONST_INT)
2132 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2135 ? 0 : preserve_subexpressions_p ()));
2138 else /* TARGET_THUMB */
2139 operands [2] = force_reg (SImode, operands [2]);
2144 (define_insn_and_split "*arm_iorsi3"
2145 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2146 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2147 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2153 && GET_CODE (operands[2]) == CONST_INT
2154 && !const_ok_for_arm (INTVAL (operands[2]))"
2155 [(clobber (const_int 0))]
2157 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2161 [(set_attr "length" "4,16")
2162 (set_attr "predicable" "yes")]
2165 (define_insn "*thumb_iorsi3"
2166 [(set (match_operand:SI 0 "register_operand" "=l")
2167 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2168 (match_operand:SI 2 "register_operand" "l")))]
2171 [(set_attr "length" "2")]
2175 [(match_scratch:SI 3 "r")
2176 (set (match_operand:SI 0 "s_register_operand" "")
2177 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2178 (match_operand:SI 2 "const_int_operand" "")))]
2180 && !const_ok_for_arm (INTVAL (operands[2]))
2181 && const_ok_for_arm (~INTVAL (operands[2]))"
2182 [(set (match_dup 3) (match_dup 2))
2183 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2187 (define_insn "*iorsi3_compare0"
2188 [(set (reg:CC_NOOV CC_REGNUM)
2189 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2190 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2192 (set (match_operand:SI 0 "s_register_operand" "=r")
2193 (ior:SI (match_dup 1) (match_dup 2)))]
2195 "orr%?s\\t%0, %1, %2"
2196 [(set_attr "conds" "set")]
2199 (define_insn "*iorsi3_compare0_scratch"
2200 [(set (reg:CC_NOOV CC_REGNUM)
2201 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2202 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2204 (clobber (match_scratch:SI 0 "=r"))]
2206 "orr%?s\\t%0, %1, %2"
2207 [(set_attr "conds" "set")]
2210 (define_insn "xordi3"
2211 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2212 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2213 (match_operand:DI 2 "s_register_operand" "r,r")))]
2214 "TARGET_ARM && !TARGET_IWMMXT"
2216 [(set_attr "length" "8")
2217 (set_attr "predicable" "yes")]
2220 (define_insn "*xordi_zesidi_di"
2221 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2222 (xor:DI (zero_extend:DI
2223 (match_operand:SI 2 "s_register_operand" "r,r"))
2224 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2227 eor%?\\t%Q0, %Q1, %2
2229 [(set_attr "length" "4,8")
2230 (set_attr "predicable" "yes")]
2233 (define_insn "*xordi_sesidi_di"
2234 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2235 (xor:DI (sign_extend:DI
2236 (match_operand:SI 2 "s_register_operand" "r,r"))
2237 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2240 [(set_attr "length" "8")
2241 (set_attr "predicable" "yes")]
2244 (define_expand "xorsi3"
2245 [(set (match_operand:SI 0 "s_register_operand" "")
2246 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2247 (match_operand:SI 2 "arm_rhs_operand" "")))]
2250 if (GET_CODE (operands[2]) == CONST_INT)
2251 operands[2] = force_reg (SImode, operands[2]);
2255 (define_insn "*arm_xorsi3"
2256 [(set (match_operand:SI 0 "s_register_operand" "=r")
2257 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2258 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2260 "eor%?\\t%0, %1, %2"
2261 [(set_attr "predicable" "yes")]
2264 (define_insn "*thumb_xorsi3"
2265 [(set (match_operand:SI 0 "register_operand" "=l")
2266 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2267 (match_operand:SI 2 "register_operand" "l")))]
2270 [(set_attr "length" "2")]
2273 (define_insn "*xorsi3_compare0"
2274 [(set (reg:CC_NOOV CC_REGNUM)
2275 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2276 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2278 (set (match_operand:SI 0 "s_register_operand" "=r")
2279 (xor:SI (match_dup 1) (match_dup 2)))]
2281 "eor%?s\\t%0, %1, %2"
2282 [(set_attr "conds" "set")]
2285 (define_insn "*xorsi3_compare0_scratch"
2286 [(set (reg:CC_NOOV CC_REGNUM)
2287 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2288 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2292 [(set_attr "conds" "set")]
2295 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2296 ; (NOT D) we can sometimes merge the final NOT into one of the following
2300 [(set (match_operand:SI 0 "s_register_operand" "")
2301 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2302 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2303 (match_operand:SI 3 "arm_rhs_operand" "")))
2304 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2306 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2307 (not:SI (match_dup 3))))
2308 (set (match_dup 0) (not:SI (match_dup 4)))]
2312 (define_insn "*andsi_iorsi3_notsi"
2313 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2314 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2315 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2316 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2318 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2319 [(set_attr "length" "8")
2320 (set_attr "predicable" "yes")]
2324 [(set (match_operand:SI 0 "s_register_operand" "")
2325 (match_operator:SI 1 "logical_binary_operator"
2326 [(zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2327 (match_operand:SI 3 "const_int_operand" "")
2328 (match_operand:SI 4 "const_int_operand" ""))
2329 (match_operator:SI 9 "logical_binary_operator"
2330 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2331 (match_operand:SI 6 "const_int_operand" ""))
2332 (match_operand:SI 7 "s_register_operand" "")])]))
2333 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2335 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2336 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2339 [(ashift:SI (match_dup 2) (match_dup 4))
2343 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2346 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2350 [(set (match_operand:SI 0 "s_register_operand" "")
2351 (match_operator:SI 1 "logical_binary_operator"
2352 [(match_operator:SI 9 "logical_binary_operator"
2353 [(lshiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2354 (match_operand:SI 6 "const_int_operand" ""))
2355 (match_operand:SI 7 "s_register_operand" "")])
2356 (zero_extract:SI (match_operand:SI 2 "s_register_operand" "")
2357 (match_operand:SI 3 "const_int_operand" "")
2358 (match_operand:SI 4 "const_int_operand" ""))]))
2359 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2361 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2362 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2365 [(ashift:SI (match_dup 2) (match_dup 4))
2369 [(lshiftrt:SI (match_dup 8) (match_dup 6))
2372 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2376 [(set (match_operand:SI 0 "s_register_operand" "")
2377 (match_operator:SI 1 "logical_binary_operator"
2378 [(sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2379 (match_operand:SI 3 "const_int_operand" "")
2380 (match_operand:SI 4 "const_int_operand" ""))
2381 (match_operator:SI 9 "logical_binary_operator"
2382 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2383 (match_operand:SI 6 "const_int_operand" ""))
2384 (match_operand:SI 7 "s_register_operand" "")])]))
2385 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2387 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2388 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2391 [(ashift:SI (match_dup 2) (match_dup 4))
2395 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2398 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2402 [(set (match_operand:SI 0 "s_register_operand" "")
2403 (match_operator:SI 1 "logical_binary_operator"
2404 [(match_operator:SI 9 "logical_binary_operator"
2405 [(ashiftrt:SI (match_operand:SI 5 "s_register_operand" "")
2406 (match_operand:SI 6 "const_int_operand" ""))
2407 (match_operand:SI 7 "s_register_operand" "")])
2408 (sign_extract:SI (match_operand:SI 2 "s_register_operand" "")
2409 (match_operand:SI 3 "const_int_operand" "")
2410 (match_operand:SI 4 "const_int_operand" ""))]))
2411 (clobber (match_operand:SI 8 "s_register_operand" ""))]
2413 && GET_CODE (operands[1]) == GET_CODE (operands[9])
2414 && INTVAL (operands[3]) == 32 - INTVAL (operands[6])"
2417 [(ashift:SI (match_dup 2) (match_dup 4))
2421 [(ashiftrt:SI (match_dup 8) (match_dup 6))
2424 operands[4] = GEN_INT (32 - (INTVAL (operands[3]) + INTVAL (operands[4])));
2428 ;; Minimum and maximum insns
2430 (define_insn "smaxsi3"
2431 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2432 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2433 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2434 (clobber (reg:CC CC_REGNUM))]
2437 cmp\\t%1, %2\;movlt\\t%0, %2
2438 cmp\\t%1, %2\;movge\\t%0, %1
2439 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2440 [(set_attr "conds" "clob")
2441 (set_attr "length" "8,8,12")]
2444 (define_insn "sminsi3"
2445 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2446 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2447 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2448 (clobber (reg:CC CC_REGNUM))]
2451 cmp\\t%1, %2\;movge\\t%0, %2
2452 cmp\\t%1, %2\;movlt\\t%0, %1
2453 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2454 [(set_attr "conds" "clob")
2455 (set_attr "length" "8,8,12")]
2458 (define_insn "umaxsi3"
2459 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2460 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2461 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2462 (clobber (reg:CC CC_REGNUM))]
2465 cmp\\t%1, %2\;movcc\\t%0, %2
2466 cmp\\t%1, %2\;movcs\\t%0, %1
2467 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2468 [(set_attr "conds" "clob")
2469 (set_attr "length" "8,8,12")]
2472 (define_insn "uminsi3"
2473 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2474 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2475 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2476 (clobber (reg:CC CC_REGNUM))]
2479 cmp\\t%1, %2\;movcs\\t%0, %2
2480 cmp\\t%1, %2\;movcc\\t%0, %1
2481 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2482 [(set_attr "conds" "clob")
2483 (set_attr "length" "8,8,12")]
2486 (define_insn "*store_minmaxsi"
2487 [(set (match_operand:SI 0 "memory_operand" "=m")
2488 (match_operator:SI 3 "minmax_operator"
2489 [(match_operand:SI 1 "s_register_operand" "r")
2490 (match_operand:SI 2 "s_register_operand" "r")]))
2491 (clobber (reg:CC CC_REGNUM))]
2494 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2496 output_asm_insn (\"cmp\\t%1, %2\", operands);
2497 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2498 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2501 [(set_attr "conds" "clob")
2502 (set_attr "length" "12")
2503 (set_attr "type" "store1")]
2506 ; Reject the frame pointer in operand[1], since reloading this after
2507 ; it has been eliminated can cause carnage.
2508 (define_insn "*minmax_arithsi"
2509 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2510 (match_operator:SI 4 "shiftable_operator"
2511 [(match_operator:SI 5 "minmax_operator"
2512 [(match_operand:SI 2 "s_register_operand" "r,r")
2513 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2514 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2515 (clobber (reg:CC CC_REGNUM))]
2517 && (GET_CODE (operands[1]) != REG
2518 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2519 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2522 enum rtx_code code = GET_CODE (operands[4]);
2524 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2526 output_asm_insn (\"cmp\\t%2, %3\", operands);
2527 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2528 if (which_alternative != 0 || operands[3] != const0_rtx
2529 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2530 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2533 [(set_attr "conds" "clob")
2534 (set_attr "length" "12")]
2538 ;; Shift and rotation insns
2540 (define_expand "ashlsi3"
2541 [(set (match_operand:SI 0 "s_register_operand" "")
2542 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2543 (match_operand:SI 2 "arm_rhs_operand" "")))]
2546 if (GET_CODE (operands[2]) == CONST_INT
2547 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2549 emit_insn (gen_movsi (operands[0], const0_rtx));
2555 (define_insn "*thumb_ashlsi3"
2556 [(set (match_operand:SI 0 "register_operand" "=l,l")
2557 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2558 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2561 [(set_attr "length" "2")]
2564 (define_expand "ashrsi3"
2565 [(set (match_operand:SI 0 "s_register_operand" "")
2566 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2567 (match_operand:SI 2 "arm_rhs_operand" "")))]
2570 if (GET_CODE (operands[2]) == CONST_INT
2571 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2572 operands[2] = GEN_INT (31);
2576 (define_insn "*thumb_ashrsi3"
2577 [(set (match_operand:SI 0 "register_operand" "=l,l")
2578 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2579 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2582 [(set_attr "length" "2")]
2585 (define_expand "lshrsi3"
2586 [(set (match_operand:SI 0 "s_register_operand" "")
2587 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2588 (match_operand:SI 2 "arm_rhs_operand" "")))]
2591 if (GET_CODE (operands[2]) == CONST_INT
2592 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2594 emit_insn (gen_movsi (operands[0], const0_rtx));
2600 (define_insn "*thumb_lshrsi3"
2601 [(set (match_operand:SI 0 "register_operand" "=l,l")
2602 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2603 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2606 [(set_attr "length" "2")]
2609 (define_expand "rotlsi3"
2610 [(set (match_operand:SI 0 "s_register_operand" "")
2611 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2612 (match_operand:SI 2 "reg_or_int_operand" "")))]
2615 if (GET_CODE (operands[2]) == CONST_INT)
2616 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2619 rtx reg = gen_reg_rtx (SImode);
2620 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2626 (define_expand "rotrsi3"
2627 [(set (match_operand:SI 0 "s_register_operand" "")
2628 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2629 (match_operand:SI 2 "arm_rhs_operand" "")))]
2634 if (GET_CODE (operands[2]) == CONST_INT
2635 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2636 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2638 else /* TARGET_THUMB */
2640 if (GET_CODE (operands [2]) == CONST_INT)
2641 operands [2] = force_reg (SImode, operands[2]);
2646 (define_insn "*thumb_rotrsi3"
2647 [(set (match_operand:SI 0 "register_operand" "=l")
2648 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2649 (match_operand:SI 2 "register_operand" "l")))]
2652 [(set_attr "length" "2")]
2655 (define_expand "ashldi3"
2656 [(set (match_operand:DI 0 "s_register_operand" "")
2657 (ashift:DI (match_operand:DI 1 "general_operand" "")
2658 (match_operand:SI 2 "general_operand" "")))]
2659 "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)"
2661 if (! s_register_operand (operands[1], DImode))
2662 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2663 if (! s_register_operand (operands[2], SImode))
2664 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2668 (define_insn "*arm_shiftsi3"
2669 [(set (match_operand:SI 0 "s_register_operand" "=r")
2670 (match_operator:SI 3 "shift_operator"
2671 [(match_operand:SI 1 "s_register_operand" "r")
2672 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2675 [(set_attr "predicable" "yes")
2676 (set_attr "shift" "1")
2680 (define_insn "*shiftsi3_compare0"
2681 [(set (reg:CC_NOOV CC_REGNUM)
2682 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2683 [(match_operand:SI 1 "s_register_operand" "r")
2684 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2686 (set (match_operand:SI 0 "s_register_operand" "=r")
2687 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2689 "mov%?s\\t%0, %1%S3"
2690 [(set_attr "conds" "set")
2691 (set_attr "shift" "1")
2695 (define_insn "*shiftsi3_compare0_scratch"
2696 [(set (reg:CC_NOOV CC_REGNUM)
2697 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2698 [(match_operand:SI 1 "s_register_operand" "r")
2699 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2701 (clobber (match_scratch:SI 0 "=r"))]
2703 "mov%?s\\t%0, %1%S3"
2704 [(set_attr "conds" "set")
2705 (set_attr "shift" "1")
2709 (define_insn "*notsi_shiftsi"
2710 [(set (match_operand:SI 0 "s_register_operand" "=r")
2711 (not:SI (match_operator:SI 3 "shift_operator"
2712 [(match_operand:SI 1 "s_register_operand" "r")
2713 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2716 [(set_attr "predicable" "yes")
2717 (set_attr "shift" "1")
2721 (define_insn "*notsi_shiftsi_compare0"
2722 [(set (reg:CC_NOOV CC_REGNUM)
2723 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2724 [(match_operand:SI 1 "s_register_operand" "r")
2725 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2727 (set (match_operand:SI 0 "s_register_operand" "=r")
2728 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2730 "mvn%?s\\t%0, %1%S3"
2731 [(set_attr "conds" "set")
2732 (set_attr "shift" "1")
2736 (define_insn "*not_shiftsi_compare0_scratch"
2737 [(set (reg:CC_NOOV CC_REGNUM)
2738 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2739 [(match_operand:SI 1 "s_register_operand" "r")
2740 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2742 (clobber (match_scratch:SI 0 "=r"))]
2744 "mvn%?s\\t%0, %1%S3"
2745 [(set_attr "conds" "set")
2746 (set_attr "shift" "1")
2750 ;; We don't really have extzv, but defining this using shifts helps
2751 ;; to reduce register pressure later on.
2753 (define_expand "extzv"
2755 (ashift:SI (match_operand:SI 1 "register_operand" "")
2756 (match_operand:SI 2 "const_int_operand" "")))
2757 (set (match_operand:SI 0 "register_operand" "")
2758 (lshiftrt:SI (match_dup 4)
2759 (match_operand:SI 3 "const_int_operand" "")))]
2763 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2764 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2766 operands[3] = GEN_INT (rshift);
2770 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2774 operands[2] = GEN_INT (lshift);
2775 operands[4] = gen_reg_rtx (SImode);
2780 ;; Unary arithmetic insns
2782 (define_expand "negdi2"
2784 [(set (match_operand:DI 0 "s_register_operand" "")
2785 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2786 (clobber (reg:CC CC_REGNUM))])]
2791 if (GET_CODE (operands[1]) != REG)
2792 operands[1] = force_reg (SImode, operands[1]);
2797 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2798 ;; The second alternative is to allow the common case of a *full* overlap.
2799 (define_insn "*arm_negdi2"
2800 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2801 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2802 (clobber (reg:CC CC_REGNUM))]
2804 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2805 [(set_attr "conds" "clob")
2806 (set_attr "length" "8")]
2809 (define_insn "*thumb_negdi2"
2810 [(set (match_operand:DI 0 "register_operand" "=&l")
2811 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2812 (clobber (reg:CC CC_REGNUM))]
2814 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2815 [(set_attr "length" "6")]
2818 (define_expand "negsi2"
2819 [(set (match_operand:SI 0 "s_register_operand" "")
2820 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2825 (define_insn "*arm_negsi2"
2826 [(set (match_operand:SI 0 "s_register_operand" "=r")
2827 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2829 "rsb%?\\t%0, %1, #0"
2830 [(set_attr "predicable" "yes")]
2833 (define_insn "*thumb_negsi2"
2834 [(set (match_operand:SI 0 "register_operand" "=l")
2835 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2838 [(set_attr "length" "2")]
2841 (define_expand "negsf2"
2842 [(set (match_operand:SF 0 "s_register_operand" "")
2843 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2844 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2848 (define_expand "negdf2"
2849 [(set (match_operand:DF 0 "s_register_operand" "")
2850 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2851 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2854 ;; abssi2 doesn't really clobber the condition codes if a different register
2855 ;; is being set. To keep things simple, assume during rtl manipulations that
2856 ;; it does, but tell the final scan operator the truth. Similarly for
2859 (define_expand "abssi2"
2861 [(set (match_operand:SI 0 "s_register_operand" "")
2862 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2863 (clobber (reg:CC CC_REGNUM))])]
2867 (define_insn "*arm_abssi2"
2868 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2869 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2870 (clobber (reg:CC CC_REGNUM))]
2873 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2874 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2875 [(set_attr "conds" "clob,*")
2876 (set_attr "shift" "1")
2877 ;; predicable can't be set based on the variant, so left as no
2878 (set_attr "length" "8")]
2881 (define_insn "*neg_abssi2"
2882 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2883 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2884 (clobber (reg:CC CC_REGNUM))]
2887 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2888 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2889 [(set_attr "conds" "clob,*")
2890 (set_attr "shift" "1")
2891 ;; predicable can't be set based on the variant, so left as no
2892 (set_attr "length" "8")]
2895 (define_expand "abssf2"
2896 [(set (match_operand:SF 0 "s_register_operand" "")
2897 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2898 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2901 (define_expand "absdf2"
2902 [(set (match_operand:DF 0 "s_register_operand" "")
2903 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2904 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2907 (define_expand "sqrtsf2"
2908 [(set (match_operand:SF 0 "s_register_operand" "")
2909 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2910 "TARGET_ARM && TARGET_HARD_FLOAT"
2913 (define_expand "sqrtdf2"
2914 [(set (match_operand:DF 0 "s_register_operand" "")
2915 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2916 "TARGET_ARM && TARGET_HARD_FLOAT"
2919 (define_insn_and_split "one_cmpldi2"
2920 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2921 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2924 "TARGET_ARM && reload_completed"
2925 [(set (match_dup 0) (not:SI (match_dup 1)))
2926 (set (match_dup 2) (not:SI (match_dup 3)))]
2929 operands[2] = gen_highpart (SImode, operands[0]);
2930 operands[0] = gen_lowpart (SImode, operands[0]);
2931 operands[3] = gen_highpart (SImode, operands[1]);
2932 operands[1] = gen_lowpart (SImode, operands[1]);
2934 [(set_attr "length" "8")
2935 (set_attr "predicable" "yes")]
2938 (define_expand "one_cmplsi2"
2939 [(set (match_operand:SI 0 "s_register_operand" "")
2940 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2945 (define_insn "*arm_one_cmplsi2"
2946 [(set (match_operand:SI 0 "s_register_operand" "=r")
2947 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2950 [(set_attr "predicable" "yes")]
2953 (define_insn "*thumb_one_cmplsi2"
2954 [(set (match_operand:SI 0 "register_operand" "=l")
2955 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2958 [(set_attr "length" "2")]
2961 (define_insn "*notsi_compare0"
2962 [(set (reg:CC_NOOV CC_REGNUM)
2963 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2965 (set (match_operand:SI 0 "s_register_operand" "=r")
2966 (not:SI (match_dup 1)))]
2969 [(set_attr "conds" "set")]
2972 (define_insn "*notsi_compare0_scratch"
2973 [(set (reg:CC_NOOV CC_REGNUM)
2974 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2976 (clobber (match_scratch:SI 0 "=r"))]
2979 [(set_attr "conds" "set")]
2982 ;; Fixed <--> Floating conversion insns
2984 (define_expand "floatsisf2"
2985 [(set (match_operand:SF 0 "s_register_operand" "")
2986 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2987 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2991 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2996 (define_expand "floatsidf2"
2997 [(set (match_operand:DF 0 "s_register_operand" "")
2998 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2999 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3003 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
3008 (define_expand "fix_truncsfsi2"
3009 [(set (match_operand:SI 0 "s_register_operand" "")
3010 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
3011 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3015 if (!cirrus_fp_register (operands[0], SImode))
3016 operands[0] = force_reg (SImode, operands[0]);
3017 if (!cirrus_fp_register (operands[1], SFmode))
3018 operands[1] = force_reg (SFmode, operands[0]);
3019 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
3024 (define_expand "fix_truncdfsi2"
3025 [(set (match_operand:SI 0 "s_register_operand" "")
3026 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
3027 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3031 if (!cirrus_fp_register (operands[1], DFmode))
3032 operands[1] = force_reg (DFmode, operands[0]);
3033 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
3040 (define_expand "truncdfsf2"
3041 [(set (match_operand:SF 0 "s_register_operand" "")
3043 (match_operand:DF 1 "s_register_operand" "")))]
3044 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3048 ;; Zero and sign extension instructions.
3050 (define_insn "zero_extendsidi2"
3051 [(set (match_operand:DI 0 "s_register_operand" "=r")
3052 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3055 if (REGNO (operands[1])
3056 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3057 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3058 return \"mov%?\\t%R0, #0\";
3060 [(set_attr "length" "8")
3061 (set_attr "predicable" "yes")]
3064 (define_insn "zero_extendqidi2"
3065 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
3066 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
3069 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
3070 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
3071 [(set_attr "length" "8")
3072 (set_attr "predicable" "yes")
3073 (set_attr "type" "*,load")
3074 (set_attr "pool_range" "*,4092")
3075 (set_attr "neg_pool_range" "*,4084")]
3078 (define_insn "extendsidi2"
3079 [(set (match_operand:DI 0 "s_register_operand" "=r")
3080 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
3083 if (REGNO (operands[1])
3084 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
3085 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
3086 return \"mov%?\\t%R0, %Q0, asr #31\";
3088 [(set_attr "length" "8")
3089 (set_attr "shift" "1")
3090 (set_attr "predicable" "yes")]
3093 (define_expand "zero_extendhisi2"
3095 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3097 (set (match_operand:SI 0 "s_register_operand" "")
3098 (lshiftrt:SI (match_dup 2) (const_int 16)))]
3104 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3106 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3107 here because the insn below will generate an LDRH instruction
3108 rather than an LDR instruction, so we cannot get an unaligned
3110 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3111 gen_rtx_ZERO_EXTEND (SImode,
3115 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3117 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
3120 if (!s_register_operand (operands[1], HImode))
3121 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3122 operands[1] = gen_lowpart (SImode, operands[1]);
3123 operands[2] = gen_reg_rtx (SImode);
3125 else /* TARGET_THUMB */
3127 if (GET_CODE (operands[1]) == MEM)
3131 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3132 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3139 if (!s_register_operand (operands[1], HImode))
3140 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3141 operands[1] = gen_lowpart (SImode, operands[1]);
3142 operands[2] = gen_reg_rtx (SImode);
3144 ops[0] = operands[2];
3145 ops[1] = operands[1];
3146 ops[2] = GEN_INT (16);
3148 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3149 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3151 ops[0] = operands[0];
3152 ops[1] = operands[2];
3153 ops[2] = GEN_INT (16);
3155 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3156 gen_rtx_LSHIFTRT (SImode, ops[1],
3164 (define_insn "*thumb_zero_extendhisi2"
3165 [(set (match_operand:SI 0 "register_operand" "=l")
3166 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3169 rtx mem = XEXP (operands[1], 0);
3171 if (GET_CODE (mem) == CONST)
3172 mem = XEXP (mem, 0);
3174 if (GET_CODE (mem) == LABEL_REF)
3175 return \"ldr\\t%0, %1\";
3177 if (GET_CODE (mem) == PLUS)
3179 rtx a = XEXP (mem, 0);
3180 rtx b = XEXP (mem, 1);
3182 /* This can happen due to bugs in reload. */
3183 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3186 ops[0] = operands[0];
3189 output_asm_insn (\"mov %0, %1\", ops);
3191 XEXP (mem, 0) = operands[0];
3194 else if ( GET_CODE (a) == LABEL_REF
3195 && GET_CODE (b) == CONST_INT)
3196 return \"ldr\\t%0, %1\";
3199 return \"ldrh\\t%0, %1\";
3201 [(set_attr "length" "4")
3202 (set_attr "type" "load")
3203 (set_attr "pool_range" "60")]
3206 (define_insn "*arm_zero_extendhisi2"
3207 [(set (match_operand:SI 0 "s_register_operand" "=r")
3208 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3209 "TARGET_ARM && arm_arch4"
3211 [(set_attr "type" "load")
3212 (set_attr "predicable" "yes")
3213 (set_attr "pool_range" "256")
3214 (set_attr "neg_pool_range" "244")]
3218 [(set (match_operand:SI 0 "s_register_operand" "")
3219 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3220 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3221 "TARGET_ARM && (!arm_arch4)"
3222 [(set (match_dup 2) (match_dup 1))
3223 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3225 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3231 [(set (match_operand:SI 0 "s_register_operand" "")
3232 (match_operator:SI 3 "shiftable_operator"
3233 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3234 (match_operand:SI 4 "s_register_operand" "")]))
3235 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3236 "TARGET_ARM && (!arm_arch4)"
3237 [(set (match_dup 2) (match_dup 1))
3240 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3242 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3247 (define_expand "zero_extendqisi2"
3248 [(set (match_operand:SI 0 "s_register_operand" "")
3249 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3252 if (GET_CODE (operands[1]) != MEM)
3256 emit_insn (gen_andsi3 (operands[0],
3257 gen_lowpart (SImode, operands[1]),
3260 else /* TARGET_THUMB */
3262 rtx temp = gen_reg_rtx (SImode);
3265 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3266 operands[1] = gen_lowpart (SImode, operands[1]);
3269 ops[1] = operands[1];
3270 ops[2] = GEN_INT (24);
3272 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3273 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3275 ops[0] = operands[0];
3277 ops[2] = GEN_INT (24);
3279 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3280 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3287 (define_insn "*thumb_zero_extendqisi2"
3288 [(set (match_operand:SI 0 "register_operand" "=l")
3289 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3292 [(set_attr "length" "2")
3293 (set_attr "type" "load")
3294 (set_attr "pool_range" "32")]
3297 (define_insn "*arm_zero_extendqisi2"
3298 [(set (match_operand:SI 0 "s_register_operand" "=r")
3299 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3301 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3302 [(set_attr "type" "load")
3303 (set_attr "predicable" "yes")
3304 (set_attr "pool_range" "4096")
3305 (set_attr "neg_pool_range" "4084")]
3309 [(set (match_operand:SI 0 "s_register_operand" "")
3310 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3311 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3312 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3313 [(set (match_dup 2) (match_dup 1))
3314 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3318 (define_insn "*compareqi_eq0"
3319 [(set (reg:CC_Z CC_REGNUM)
3320 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3324 [(set_attr "conds" "set")]
3327 (define_expand "extendhisi2"
3329 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3331 (set (match_operand:SI 0 "s_register_operand" "")
3332 (ashiftrt:SI (match_dup 2)
3337 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3339 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3340 here because the insn below will generate an LDRH instruction
3341 rather than an LDR instruction, so we cannot get an unaligned
3343 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3344 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3348 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3350 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3353 if (!s_register_operand (operands[1], HImode))
3354 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3355 operands[1] = gen_lowpart (SImode, operands[1]);
3356 operands[2] = gen_reg_rtx (SImode);
3362 ops[0] = operands[2];
3363 ops[1] = operands[1];
3364 ops[2] = GEN_INT (16);
3366 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3367 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3369 ops[0] = operands[0];
3370 ops[1] = operands[2];
3371 ops[2] = GEN_INT (16);
3373 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3374 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3381 (define_insn "*thumb_extendhisi2_insn"
3382 [(set (match_operand:SI 0 "register_operand" "=l")
3383 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3384 (clobber (match_scratch:SI 2 "=&l"))]
3389 rtx mem = XEXP (operands[1], 0);
3391 /* This code used to try to use 'V', and fix the address only if it was
3392 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3393 range of QImode offsets, and offsettable_address_p does a QImode
3396 if (GET_CODE (mem) == CONST)
3397 mem = XEXP (mem, 0);
3399 if (GET_CODE (mem) == LABEL_REF)
3400 return \"ldr\\t%0, %1\";
3402 if (GET_CODE (mem) == PLUS)
3404 rtx a = XEXP (mem, 0);
3405 rtx b = XEXP (mem, 1);
3407 if (GET_CODE (a) == LABEL_REF
3408 && GET_CODE (b) == CONST_INT)
3409 return \"ldr\\t%0, %1\";
3411 if (GET_CODE (b) == REG)
3412 return \"ldrsh\\t%0, %1\";
3420 ops[2] = const0_rtx;
3423 if (GET_CODE (ops[1]) != REG)
3429 ops[0] = operands[0];
3430 ops[3] = operands[2];
3431 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3434 [(set_attr "length" "4")
3435 (set_attr "type" "load")
3436 (set_attr "pool_range" "1020")]
3439 (define_expand "extendhisi2_mem"
3440 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3442 (zero_extend:SI (match_dup 7)))
3443 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3444 (set (match_operand:SI 0 "" "")
3445 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3450 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3452 mem1 = gen_rtx_MEM (QImode, addr);
3453 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3454 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3455 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3456 operands[0] = gen_lowpart (SImode, operands[0]);
3458 operands[2] = gen_reg_rtx (SImode);
3459 operands[3] = gen_reg_rtx (SImode);
3460 operands[6] = gen_reg_rtx (SImode);
3463 if (BYTES_BIG_ENDIAN)
3465 operands[4] = operands[2];
3466 operands[5] = operands[3];
3470 operands[4] = operands[3];
3471 operands[5] = operands[2];
3476 (define_insn "*arm_extendhisi_insn"
3477 [(set (match_operand:SI 0 "s_register_operand" "=r")
3478 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3479 "TARGET_ARM && arm_arch4"
3481 [(set_attr "type" "load")
3482 (set_attr "predicable" "yes")
3483 (set_attr "pool_range" "256")
3484 (set_attr "neg_pool_range" "244")]
3488 [(set (match_operand:SI 0 "s_register_operand" "")
3489 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3490 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3491 "TARGET_ARM && (!arm_arch4)"
3492 [(set (match_dup 2) (match_dup 1))
3493 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3495 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3501 [(set (match_operand:SI 0 "s_register_operand" "")
3502 (match_operator:SI 3 "shiftable_operator"
3503 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3504 (match_operand:SI 4 "s_register_operand" "")]))
3505 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3506 "TARGET_ARM && (!arm_arch4)"
3507 [(set (match_dup 2) (match_dup 1))
3510 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3511 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3516 (define_expand "extendqihi2"
3518 (ashift:SI (match_operand:QI 1 "general_operand" "")
3520 (set (match_operand:HI 0 "s_register_operand" "")
3521 (ashiftrt:SI (match_dup 2)
3526 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3528 emit_insn (gen_rtx_SET (VOIDmode,
3530 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3533 if (!s_register_operand (operands[1], QImode))
3534 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3535 operands[0] = gen_lowpart (SImode, operands[0]);
3536 operands[1] = gen_lowpart (SImode, operands[1]);
3537 operands[2] = gen_reg_rtx (SImode);
3541 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3542 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3543 (define_insn "*extendqihi_insn"
3544 [(set (match_operand:HI 0 "s_register_operand" "=r")
3545 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3546 "TARGET_ARM && arm_arch4"
3548 /* If the address is invalid, this will split the instruction into two. */
3549 if (bad_signed_byte_operand (operands[1], VOIDmode))
3551 return \"ldr%?sb\\t%0, %1\";
3553 [(set_attr "type" "load")
3554 (set_attr "predicable" "yes")
3555 (set_attr "length" "8")
3556 (set_attr "pool_range" "256")
3557 (set_attr "neg_pool_range" "244")]
3561 [(set (match_operand:HI 0 "s_register_operand" "")
3562 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3563 "TARGET_ARM && arm_arch4 && reload_completed"
3564 [(set (match_dup 3) (match_dup 1))
3565 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3568 HOST_WIDE_INT offset;
3570 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3571 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3572 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3573 operands[1] = XEXP (operands[1], 0);
3574 if (GET_CODE (operands[1]) == PLUS
3575 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3576 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3577 || const_ok_for_arm (-offset)))
3579 HOST_WIDE_INT low = (offset > 0
3580 ? (offset & 0xff) : -((-offset) & 0xff));
3581 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3582 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3584 /* Ensure the sum is in correct canonical form */
3585 else if (GET_CODE (operands[1]) == PLUS
3586 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3587 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3588 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3589 XEXP (operands[1], 1),
3590 XEXP (operands[1], 0));
3594 (define_expand "extendqisi2"
3596 (ashift:SI (match_operand:QI 1 "general_operand" "")
3598 (set (match_operand:SI 0 "s_register_operand" "")
3599 (ashiftrt:SI (match_dup 2)
3604 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3606 emit_insn (gen_rtx_SET (VOIDmode,
3608 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3611 if (!s_register_operand (operands[1], QImode))
3612 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3613 operands[1] = gen_lowpart (SImode, operands[1]);
3614 operands[2] = gen_reg_rtx (SImode);
3620 ops[0] = operands[2];
3621 ops[1] = operands[1];
3622 ops[2] = GEN_INT (24);
3624 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3625 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3627 ops[0] = operands[0];
3628 ops[1] = operands[2];
3629 ops[2] = GEN_INT (24);
3631 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3632 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3639 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3640 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3641 (define_insn "*arm_extendqisi_insn"
3642 [(set (match_operand:SI 0 "s_register_operand" "=r")
3643 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3644 "TARGET_ARM && arm_arch4"
3646 /* If the address is invalid, this will split the instruction into two. */
3647 if (bad_signed_byte_operand (operands[1], VOIDmode))
3649 return \"ldr%?sb\\t%0, %1\";
3651 [(set_attr "type" "load")
3652 (set_attr "predicable" "yes")
3653 (set_attr "length" "8")
3654 (set_attr "pool_range" "256")
3655 (set_attr "neg_pool_range" "244")]
3659 [(set (match_operand:SI 0 "s_register_operand" "")
3660 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3661 "TARGET_ARM && arm_arch4 && reload_completed"
3662 [(set (match_dup 0) (match_dup 1))
3663 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3666 HOST_WIDE_INT offset;
3668 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3669 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3670 operands[1] = XEXP (operands[1], 0);
3671 if (GET_CODE (operands[1]) == PLUS
3672 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3673 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3674 || const_ok_for_arm (-offset)))
3676 HOST_WIDE_INT low = (offset > 0
3677 ? (offset & 0xff) : -((-offset) & 0xff));
3678 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3679 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3681 /* Ensure the sum is in correct canonical form */
3682 else if (GET_CODE (operands[1]) == PLUS
3683 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3684 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3685 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3686 XEXP (operands[1], 1),
3687 XEXP (operands[1], 0));
3691 (define_insn "*thumb_extendqisi2_insn"
3692 [(set (match_operand:SI 0 "register_operand" "=l,l")
3693 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3698 rtx mem = XEXP (operands[1], 0);
3700 if (GET_CODE (mem) == CONST)
3701 mem = XEXP (mem, 0);
3703 if (GET_CODE (mem) == LABEL_REF)
3704 return \"ldr\\t%0, %1\";
3706 if (GET_CODE (mem) == PLUS
3707 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3708 return \"ldr\\t%0, %1\";
3710 if (which_alternative == 0)
3711 return \"ldrsb\\t%0, %1\";
3713 ops[0] = operands[0];
3715 if (GET_CODE (mem) == PLUS)
3717 rtx a = XEXP (mem, 0);
3718 rtx b = XEXP (mem, 1);
3723 if (GET_CODE (a) == REG)
3725 if (GET_CODE (b) == REG)
3726 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3727 else if (REGNO (a) == REGNO (ops[0]))
3729 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3730 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3731 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3734 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3736 else if (GET_CODE (b) != REG)
3740 if (REGNO (b) == REGNO (ops[0]))
3742 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3743 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3744 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3747 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3750 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3752 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3753 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3754 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3759 ops[2] = const0_rtx;
3761 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3765 [(set_attr "length" "2,6")
3766 (set_attr "type" "load,load")
3767 (set_attr "pool_range" "32,32")]
3770 (define_expand "extendsfdf2"
3771 [(set (match_operand:DF 0 "s_register_operand" "")
3772 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3773 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3777 ;; Move insns (including loads and stores)
3779 ;; XXX Just some ideas about movti.
3780 ;; I don't think these are a good idea on the arm, there just aren't enough
3782 ;;(define_expand "loadti"
3783 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3784 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3787 ;;(define_expand "storeti"
3788 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3789 ;; (match_operand:TI 1 "s_register_operand" ""))]
3792 ;;(define_expand "movti"
3793 ;; [(set (match_operand:TI 0 "general_operand" "")
3794 ;; (match_operand:TI 1 "general_operand" ""))]
3800 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3801 ;; operands[1] = copy_to_reg (operands[1]);
3802 ;; if (GET_CODE (operands[0]) == MEM)
3803 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3804 ;; else if (GET_CODE (operands[1]) == MEM)
3805 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3809 ;; emit_insn (insn);
3813 ;; Recognize garbage generated above.
3816 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3817 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3821 ;; register mem = (which_alternative < 3);
3822 ;; register const char *template;
3824 ;; operands[mem] = XEXP (operands[mem], 0);
3825 ;; switch (which_alternative)
3827 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3828 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3829 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3830 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3831 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3832 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3834 ;; output_asm_insn (template, operands);
3838 (define_expand "movdi"
3839 [(set (match_operand:DI 0 "general_operand" "")
3840 (match_operand:DI 1 "general_operand" ""))]
3845 if (!no_new_pseudos)
3847 if (GET_CODE (operands[0]) != REG)
3848 operands[1] = force_reg (DImode, operands[1]);
3854 (define_insn "*arm_movdi"
3855 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3856 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3857 "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT"
3859 return (output_move_double (operands));
3861 [(set_attr "length" "8")
3862 (set_attr "type" "*,load,store2")
3863 (set_attr "pool_range" "*,1020,*")
3864 (set_attr "neg_pool_range" "*,1008,*")]
3867 ;;; ??? This should have alternatives for constants.
3868 ;;; ??? This was originally identical to the movdf_insn pattern.
3869 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3870 ;;; thumb_reorg with a memory reference.
3871 (define_insn "*thumb_movdi_insn"
3872 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3873 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3876 && ( register_operand (operands[0], DImode)
3877 || register_operand (operands[1], DImode))"
3880 switch (which_alternative)
3884 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3885 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3886 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3888 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3890 operands[1] = GEN_INT (- INTVAL (operands[1]));
3891 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3893 return \"ldmia\\t%1, {%0, %H0}\";
3895 return \"stmia\\t%0, {%1, %H1}\";
3897 return thumb_load_double_from_address (operands);
3899 operands[2] = gen_rtx (MEM, SImode,
3900 plus_constant (XEXP (operands[0], 0), 4));
3901 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3904 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3905 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3906 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3909 [(set_attr "length" "4,4,6,2,2,6,4,4")
3910 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3911 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3914 (define_expand "movsi"
3915 [(set (match_operand:SI 0 "general_operand" "")
3916 (match_operand:SI 1 "general_operand" ""))]
3921 /* Everything except mem = const or mem = mem can be done easily */
3922 if (GET_CODE (operands[0]) == MEM)
3923 operands[1] = force_reg (SImode, operands[1]);
3924 if (GET_CODE (operands[1]) == CONST_INT
3925 && !(const_ok_for_arm (INTVAL (operands[1]))
3926 || const_ok_for_arm (~INTVAL (operands[1]))))
3928 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3931 : preserve_subexpressions_p ()));
3935 else /* TARGET_THUMB.... */
3937 if (!no_new_pseudos)
3939 if (GET_CODE (operands[0]) != REG)
3940 operands[1] = force_reg (SImode, operands[1]);
3945 && (CONSTANT_P (operands[1])
3946 || symbol_mentioned_p (operands[1])
3947 || label_mentioned_p (operands[1])))
3948 operands[1] = legitimize_pic_address (operands[1], SImode,
3949 (no_new_pseudos ? operands[0] : 0));
3953 (define_insn "*arm_movsi_insn"
3954 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3955 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
3956 "TARGET_ARM && ! TARGET_IWMMXT
3957 && ( register_operand (operands[0], SImode)
3958 || register_operand (operands[1], SImode))"
3964 [(set_attr "type" "*,*,load,store1")
3965 (set_attr "predicable" "yes")
3966 (set_attr "pool_range" "*,*,4096,*")
3967 (set_attr "neg_pool_range" "*,*,4084,*")]
3971 [(set (match_operand:SI 0 "s_register_operand" "")
3972 (match_operand:SI 1 "const_int_operand" ""))]
3974 && (!(const_ok_for_arm (INTVAL (operands[1]))
3975 || const_ok_for_arm (~INTVAL (operands[1]))))"
3976 [(clobber (const_int 0))]
3978 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3984 (define_insn "*thumb_movsi_insn"
3985 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3986 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
3988 && ( register_operand (operands[0], SImode)
3989 || register_operand (operands[1], SImode))"
4000 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
4001 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
4002 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
4006 [(set (match_operand:SI 0 "register_operand" "")
4007 (match_operand:SI 1 "const_int_operand" ""))]
4008 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
4009 [(set (match_dup 0) (match_dup 1))
4010 (set (match_dup 0) (neg:SI (match_dup 0)))]
4011 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
4015 [(set (match_operand:SI 0 "register_operand" "")
4016 (match_operand:SI 1 "const_int_operand" ""))]
4017 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
4018 [(set (match_dup 0) (match_dup 1))
4019 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
4022 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
4023 unsigned HOST_WIDE_INT mask = 0xff;
4026 for (i = 0; i < 25; i++)
4027 if ((val & (mask << i)) == val)
4030 /* Shouldn't happen, but we don't want to split if the shift is zero. */
4034 operands[1] = GEN_INT (val >> i);
4035 operands[2] = GEN_INT (i);
4039 ;; When generating pic, we need to load the symbol offset into a register.
4040 ;; So that the optimizer does not confuse this with a normal symbol load
4041 ;; we use an unspec. The offset will be loaded from a constant pool entry,
4042 ;; since that is the only type of relocation we can use.
4044 ;; The rather odd constraints on the following are to force reload to leave
4045 ;; the insn alone, and to force the minipool generation pass to then move
4046 ;; the GOT symbol to memory.
4048 (define_insn "pic_load_addr_arm"
4049 [(set (match_operand:SI 0 "s_register_operand" "=r")
4050 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4051 "TARGET_ARM && flag_pic"
4053 [(set_attr "type" "load")
4054 (set (attr "pool_range") (const_int 4096))
4055 (set (attr "neg_pool_range") (const_int 4084))]
4058 (define_insn "pic_load_addr_thumb"
4059 [(set (match_operand:SI 0 "s_register_operand" "=l")
4060 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
4061 "TARGET_THUMB && flag_pic"
4063 [(set_attr "type" "load")
4064 (set (attr "pool_range") (const_int 1024))]
4067 ;; This variant is used for AOF assembly, since it needs to mention the
4068 ;; pic register in the rtl.
4069 (define_expand "pic_load_addr_based"
4070 [(set (match_operand:SI 0 "s_register_operand" "")
4071 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
4072 "TARGET_ARM && flag_pic"
4073 "operands[2] = pic_offset_table_rtx;"
4076 (define_insn "*pic_load_addr_based_insn"
4077 [(set (match_operand:SI 0 "s_register_operand" "=r")
4078 (unspec:SI [(match_operand 1 "" "")
4079 (match_operand 2 "s_register_operand" "r")]
4081 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
4083 #ifdef AOF_ASSEMBLER
4084 operands[1] = aof_pic_entry (operands[1]);
4086 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
4089 [(set_attr "type" "load")
4090 (set (attr "pool_range")
4091 (if_then_else (eq_attr "is_thumb" "yes")
4094 (set (attr "neg_pool_range")
4095 (if_then_else (eq_attr "is_thumb" "yes")
4100 (define_insn "pic_add_dot_plus_four"
4101 [(set (match_operand:SI 0 "register_operand" "+r")
4102 (unspec:SI [(plus:SI (match_dup 0)
4103 (const (plus:SI (pc) (const_int 4))))]
4105 (use (label_ref (match_operand 1 "" "")))]
4106 "TARGET_THUMB && flag_pic"
4108 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4109 CODE_LABEL_NUMBER (operands[1]));
4110 return \"add\\t%0, %|pc\";
4112 [(set_attr "length" "2")]
4115 (define_insn "pic_add_dot_plus_eight"
4116 [(set (match_operand:SI 0 "register_operand" "+r")
4117 (unspec:SI [(plus:SI (match_dup 0)
4118 (const (plus:SI (pc) (const_int 8))))]
4120 (use (label_ref (match_operand 1 "" "")))]
4121 "TARGET_ARM && flag_pic"
4123 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
4124 CODE_LABEL_NUMBER (operands[1]));
4125 return \"add%?\\t%0, %|pc, %0\";
4127 [(set_attr "predicable" "yes")]
4130 (define_expand "builtin_setjmp_receiver"
4131 [(label_ref (match_operand 0 "" ""))]
4135 arm_finalize_pic (0);
4139 ;; If copying one reg to another we can set the condition codes according to
4140 ;; its value. Such a move is common after a return from subroutine and the
4141 ;; result is being tested against zero.
4143 (define_insn "*movsi_compare0"
4144 [(set (reg:CC CC_REGNUM)
4145 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4147 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4152 sub%?s\\t%0, %1, #0"
4153 [(set_attr "conds" "set")]
4156 ;; Subroutine to store a half word from a register into memory.
4157 ;; Operand 0 is the source register (HImode)
4158 ;; Operand 1 is the destination address in a register (SImode)
4160 ;; In both this routine and the next, we must be careful not to spill
4161 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4162 ;; can generate unrecognizable rtl.
4164 (define_expand "storehi"
4165 [;; store the low byte
4166 (set (match_operand 1 "" "") (match_dup 3))
4167 ;; extract the high byte
4169 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4170 ;; store the high byte
4171 (set (match_dup 4) (match_dup 5))]
4175 rtx op1 = operands[1];
4176 rtx addr = XEXP (op1, 0);
4177 enum rtx_code code = GET_CODE (addr);
4179 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4181 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4183 operands[4] = adjust_address (op1, QImode, 1);
4184 operands[1] = adjust_address (operands[1], QImode, 0);
4185 operands[3] = gen_lowpart (QImode, operands[0]);
4186 operands[0] = gen_lowpart (SImode, operands[0]);
4187 operands[2] = gen_reg_rtx (SImode);
4188 operands[5] = gen_lowpart (QImode, operands[2]);
4192 (define_expand "storehi_bigend"
4193 [(set (match_dup 4) (match_dup 3))
4195 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4196 (set (match_operand 1 "" "") (match_dup 5))]
4200 rtx op1 = operands[1];
4201 rtx addr = XEXP (op1, 0);
4202 enum rtx_code code = GET_CODE (addr);
4204 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4206 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4208 operands[4] = adjust_address (op1, QImode, 1);
4209 operands[1] = adjust_address (operands[1], QImode, 0);
4210 operands[3] = gen_lowpart (QImode, operands[0]);
4211 operands[0] = gen_lowpart (SImode, operands[0]);
4212 operands[2] = gen_reg_rtx (SImode);
4213 operands[5] = gen_lowpart (QImode, operands[2]);
4217 ;; Subroutine to store a half word integer constant into memory.
4218 (define_expand "storeinthi"
4219 [(set (match_operand 0 "" "")
4220 (match_operand 1 "" ""))
4221 (set (match_dup 3) (match_dup 2))]
4225 HOST_WIDE_INT value = INTVAL (operands[1]);
4226 rtx addr = XEXP (operands[0], 0);
4227 rtx op0 = operands[0];
4228 enum rtx_code code = GET_CODE (addr);
4230 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4232 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4234 operands[1] = gen_reg_rtx (SImode);
4235 if (BYTES_BIG_ENDIAN)
4237 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4238 if ((value & 255) == ((value >> 8) & 255))
4239 operands[2] = operands[1];
4242 operands[2] = gen_reg_rtx (SImode);
4243 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4248 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4249 if ((value & 255) == ((value >> 8) & 255))
4250 operands[2] = operands[1];
4253 operands[2] = gen_reg_rtx (SImode);
4254 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4258 operands[3] = adjust_address (op0, QImode, 1);
4259 operands[0] = adjust_address (operands[0], QImode, 0);
4260 operands[2] = gen_lowpart (QImode, operands[2]);
4261 operands[1] = gen_lowpart (QImode, operands[1]);
4265 (define_expand "storehi_single_op"
4266 [(set (match_operand:HI 0 "memory_operand" "")
4267 (match_operand:HI 1 "general_operand" ""))]
4268 "TARGET_ARM && arm_arch4"
4270 if (!s_register_operand (operands[1], HImode))
4271 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4275 (define_expand "movhi"
4276 [(set (match_operand:HI 0 "general_operand" "")
4277 (match_operand:HI 1 "general_operand" ""))]
4282 if (!no_new_pseudos)
4284 if (GET_CODE (operands[0]) == MEM)
4288 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4291 if (GET_CODE (operands[1]) == CONST_INT)
4292 emit_insn (gen_storeinthi (operands[0], operands[1]));
4295 if (GET_CODE (operands[1]) == MEM)
4296 operands[1] = force_reg (HImode, operands[1]);
4297 if (BYTES_BIG_ENDIAN)
4298 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4300 emit_insn (gen_storehi (operands[1], operands[0]));
4304 /* Sign extend a constant, and keep it in an SImode reg. */
4305 else if (GET_CODE (operands[1]) == CONST_INT)
4307 rtx reg = gen_reg_rtx (SImode);
4308 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4310 /* If the constant is already valid, leave it alone. */
4311 if (!const_ok_for_arm (val))
4313 /* If setting all the top bits will make the constant
4314 loadable in a single instruction, then set them.
4315 Otherwise, sign extend the number. */
4317 if (const_ok_for_arm (~(val | ~0xffff)))
4319 else if (val & 0x8000)
4323 emit_insn (gen_movsi (reg, GEN_INT (val)));
4324 operands[1] = gen_lowpart (HImode, reg);
4326 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4327 && GET_CODE (operands[1]) == MEM)
4329 rtx reg = gen_reg_rtx (SImode);
4331 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4332 operands[1] = gen_lowpart (HImode, reg);
4334 else if (!arm_arch4)
4336 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4337 for v4 and up architectures because LDRH instructions will
4338 be used to access the HI values, and these cannot generate
4339 unaligned word access faults in the MMU. */
4340 if (GET_CODE (operands[1]) == MEM)
4342 if (TARGET_MMU_TRAPS)
4345 rtx offset = const0_rtx;
4346 rtx reg = gen_reg_rtx (SImode);
4348 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4349 || (GET_CODE (base) == PLUS
4350 && (GET_CODE (offset = XEXP (base, 1))
4352 && ((INTVAL(offset) & 1) != 1)
4353 && GET_CODE (base = XEXP (base, 0)) == REG))
4354 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4356 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4359 new = gen_rtx_MEM (SImode,
4360 plus_constant (base, new_offset));
4361 MEM_COPY_ATTRIBUTES (new, operands[1]);
4362 emit_insn (gen_movsi (reg, new));
4363 if (((INTVAL (offset) & 2) != 0)
4364 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4366 rtx reg2 = gen_reg_rtx (SImode);
4368 emit_insn (gen_lshrsi3 (reg2, reg,
4374 emit_insn (gen_movhi_bytes (reg, operands[1]));
4376 operands[1] = gen_lowpart (HImode, reg);
4378 else if (BYTES_BIG_ENDIAN)
4381 rtx offset = const0_rtx;
4383 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4384 || (GET_CODE (base) == PLUS
4385 && (GET_CODE (offset = XEXP (base, 1))
4387 && GET_CODE (base = XEXP (base, 0)) == REG))
4388 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4390 rtx reg = gen_reg_rtx (SImode);
4393 if ((INTVAL (offset) & 2) == 2)
4395 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4396 new = gen_rtx_MEM (SImode,
4397 plus_constant (base,
4399 MEM_COPY_ATTRIBUTES (new, operands[1]);
4400 emit_insn (gen_movsi (reg, new));
4404 new = gen_rtx_MEM (SImode,
4405 XEXP (operands[1], 0));
4406 MEM_COPY_ATTRIBUTES (new, operands[1]);
4407 emit_insn (gen_rotated_loadsi (reg, new));
4410 operands[1] = gen_lowpart (HImode, reg);
4414 emit_insn (gen_movhi_bigend (operands[0],
4422 /* Handle loading a large integer during reload */
4423 else if (GET_CODE (operands[1]) == CONST_INT
4424 && !const_ok_for_arm (INTVAL (operands[1]))
4425 && !const_ok_for_arm (~INTVAL (operands[1])))
4427 /* Writing a constant to memory needs a scratch, which should
4428 be handled with SECONDARY_RELOADs. */
4429 if (GET_CODE (operands[0]) != REG)
4432 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4433 emit_insn (gen_movsi (operands[0], operands[1]));
4437 else /* TARGET_THUMB */
4439 if (!no_new_pseudos)
4441 if (GET_CODE (operands[0]) != REG)
4442 operands[1] = force_reg (HImode, operands[1]);
4444 /* ??? We shouldn't really get invalid addresses here, but this can
4445 happen if we are passed a SP (never OK for HImode/QImode) or
4446 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4447 HImode/QImode) relative address. */
4448 /* ??? This should perhaps be fixed elsewhere, for instance, in
4449 fixup_stack_1, by checking for other kinds of invalid addresses,
4450 e.g. a bare reference to a virtual register. This may confuse the
4451 alpha though, which must handle this case differently. */
4452 if (GET_CODE (operands[0]) == MEM
4453 && !memory_address_p (GET_MODE (operands[0]),
4454 XEXP (operands[0], 0)))
4456 = replace_equiv_address (operands[0],
4457 copy_to_reg (XEXP (operands[0], 0)));
4459 if (GET_CODE (operands[1]) == MEM
4460 && !memory_address_p (GET_MODE (operands[1]),
4461 XEXP (operands[1], 0)))
4463 = replace_equiv_address (operands[1],
4464 copy_to_reg (XEXP (operands[1], 0)));
4466 /* Handle loading a large integer during reload */
4467 else if (GET_CODE (operands[1]) == CONST_INT
4468 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4470 /* Writing a constant to memory needs a scratch, which should
4471 be handled with SECONDARY_RELOADs. */
4472 if (GET_CODE (operands[0]) != REG)
4475 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4476 emit_insn (gen_movsi (operands[0], operands[1]));
4483 (define_insn "*thumb_movhi_insn"
4484 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4485 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4487 && ( register_operand (operands[0], HImode)
4488 || register_operand (operands[1], HImode))"
4490 switch (which_alternative)
4492 case 0: return \"add %0, %1, #0\";
4493 case 2: return \"strh %1, %0\";
4494 case 3: return \"mov %0, %1\";
4495 case 4: return \"mov %0, %1\";
4496 case 5: return \"mov %0, %1\";
4499 /* The stack pointer can end up being taken as an index register.
4500 Catch this case here and deal with it. */
4501 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4502 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4503 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4506 ops[0] = operands[0];
4507 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4509 output_asm_insn (\"mov %0, %1\", ops);
4511 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4514 return \"ldrh %0, %1\";
4516 [(set_attr "length" "2,4,2,2,2,2")
4517 (set_attr "type" "*,load,store1,*,*,*")
4518 (set_attr "pool_range" "*,64,*,*,*,*")]
4522 (define_insn "rotated_loadsi"
4523 [(set (match_operand:SI 0 "s_register_operand" "=r")
4524 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4526 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4531 ops[0] = operands[0];
4532 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4533 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4536 [(set_attr "type" "load")
4537 (set_attr "predicable" "yes")]
4540 (define_expand "movhi_bytes"
4541 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4543 (zero_extend:SI (match_dup 6)))
4544 (set (match_operand:SI 0 "" "")
4545 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4550 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4552 mem1 = gen_rtx_MEM (QImode, addr);
4553 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4554 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4555 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4556 operands[0] = gen_lowpart (SImode, operands[0]);
4558 operands[2] = gen_reg_rtx (SImode);
4559 operands[3] = gen_reg_rtx (SImode);
4562 if (BYTES_BIG_ENDIAN)
4564 operands[4] = operands[2];
4565 operands[5] = operands[3];
4569 operands[4] = operands[3];
4570 operands[5] = operands[2];
4575 (define_expand "movhi_bigend"
4577 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4580 (ashiftrt:SI (match_dup 2) (const_int 16)))
4581 (set (match_operand:HI 0 "s_register_operand" "")
4585 operands[2] = gen_reg_rtx (SImode);
4586 operands[3] = gen_reg_rtx (SImode);
4587 operands[4] = gen_lowpart (HImode, operands[3]);
4591 ;; Pattern to recognize insn generated default case above
4592 (define_insn "*movhi_insn_arch4"
4593 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4594 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4597 && (GET_CODE (operands[1]) != CONST_INT
4598 || const_ok_for_arm (INTVAL (operands[1]))
4599 || const_ok_for_arm (~INTVAL (operands[1])))"
4601 mov%?\\t%0, %1\\t%@ movhi
4602 mvn%?\\t%0, #%B1\\t%@ movhi
4603 str%?h\\t%1, %0\\t%@ movhi
4604 ldr%?h\\t%0, %1\\t%@ movhi"
4605 [(set_attr "type" "*,*,store1,load")
4606 (set_attr "predicable" "yes")
4607 (set_attr "pool_range" "*,*,*,256")
4608 (set_attr "neg_pool_range" "*,*,*,244")]
4611 (define_insn "*movhi_insn_littleend"
4612 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4613 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4616 && !BYTES_BIG_ENDIAN
4617 && !TARGET_MMU_TRAPS
4618 && (GET_CODE (operands[1]) != CONST_INT
4619 || const_ok_for_arm (INTVAL (operands[1]))
4620 || const_ok_for_arm (~INTVAL (operands[1])))"
4622 mov%?\\t%0, %1\\t%@ movhi
4623 mvn%?\\t%0, #%B1\\t%@ movhi
4624 ldr%?\\t%0, %1\\t%@ movhi"
4625 [(set_attr "type" "*,*,load")
4626 (set_attr "predicable" "yes")
4627 (set_attr "pool_range" "4096")
4628 (set_attr "neg_pool_range" "4084")]
4631 (define_insn "*movhi_insn_bigend"
4632 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4633 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4637 && !TARGET_MMU_TRAPS
4638 && (GET_CODE (operands[1]) != CONST_INT
4639 || const_ok_for_arm (INTVAL (operands[1]))
4640 || const_ok_for_arm (~INTVAL (operands[1])))"
4642 mov%?\\t%0, %1\\t%@ movhi
4643 mvn%?\\t%0, #%B1\\t%@ movhi
4644 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4645 [(set_attr "type" "*,*,load")
4646 (set_attr "predicable" "yes")
4647 (set_attr "length" "4,4,8")
4648 (set_attr "pool_range" "*,*,4092")
4649 (set_attr "neg_pool_range" "*,*,4084")]
4652 (define_insn "*loadhi_si_bigend"
4653 [(set (match_operand:SI 0 "s_register_operand" "=r")
4654 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4658 && !TARGET_MMU_TRAPS"
4659 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4660 [(set_attr "type" "load")
4661 (set_attr "predicable" "yes")
4662 (set_attr "pool_range" "4096")
4663 (set_attr "neg_pool_range" "4084")]
4666 (define_insn "*movhi_bytes"
4667 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4668 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4669 "TARGET_ARM && TARGET_MMU_TRAPS"
4671 mov%?\\t%0, %1\\t%@ movhi
4672 mvn%?\\t%0, #%B1\\t%@ movhi"
4673 [(set_attr "predicable" "yes")]
4676 (define_insn "thumb_movhi_clobber"
4677 [(set (match_operand:HI 0 "memory_operand" "=m")
4678 (match_operand:HI 1 "register_operand" "l"))
4679 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4685 ;; We use a DImode scratch because we may occasionally need an additional
4686 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4687 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4688 (define_expand "reload_outhi"
4689 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4690 (match_operand:HI 1 "s_register_operand" "r")
4691 (match_operand:DI 2 "s_register_operand" "=&l")])]
4694 arm_reload_out_hi (operands);
4696 thumb_reload_out_hi (operands);
4701 (define_expand "reload_inhi"
4702 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4703 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4704 (match_operand:DI 2 "s_register_operand" "=&r")])]
4705 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4708 arm_reload_in_hi (operands);
4710 thumb_reload_out_hi (operands);
4714 (define_expand "movqi"
4715 [(set (match_operand:QI 0 "general_operand" "")
4716 (match_operand:QI 1 "general_operand" ""))]
4721 /* Everything except mem = const or mem = mem can be done easily */
4723 if (!no_new_pseudos)
4725 if (GET_CODE (operands[1]) == CONST_INT)
4727 rtx reg = gen_reg_rtx (SImode);
4729 emit_insn (gen_movsi (reg, operands[1]));
4730 operands[1] = gen_lowpart (QImode, reg);
4732 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4734 rtx reg = gen_reg_rtx (SImode);
4736 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4737 operands[1] = gen_lowpart (QImode, reg);
4739 if (GET_CODE (operands[0]) == MEM)
4740 operands[1] = force_reg (QImode, operands[1]);
4743 else /* TARGET_THUMB */
4745 if (!no_new_pseudos)
4747 if (GET_CODE (operands[0]) != REG)
4748 operands[1] = force_reg (QImode, operands[1]);
4750 /* ??? We shouldn't really get invalid addresses here, but this can
4751 happen if we are passed a SP (never OK for HImode/QImode) or
4752 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4753 HImode/QImode) relative address. */
4754 /* ??? This should perhaps be fixed elsewhere, for instance, in
4755 fixup_stack_1, by checking for other kinds of invalid addresses,
4756 e.g. a bare reference to a virtual register. This may confuse the
4757 alpha though, which must handle this case differently. */
4758 if (GET_CODE (operands[0]) == MEM
4759 && !memory_address_p (GET_MODE (operands[0]),
4760 XEXP (operands[0], 0)))
4762 = replace_equiv_address (operands[0],
4763 copy_to_reg (XEXP (operands[0], 0)));
4764 if (GET_CODE (operands[1]) == MEM
4765 && !memory_address_p (GET_MODE (operands[1]),
4766 XEXP (operands[1], 0)))
4768 = replace_equiv_address (operands[1],
4769 copy_to_reg (XEXP (operands[1], 0)));
4771 /* Handle loading a large integer during reload */
4772 else if (GET_CODE (operands[1]) == CONST_INT
4773 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4775 /* Writing a constant to memory needs a scratch, which should
4776 be handled with SECONDARY_RELOADs. */
4777 if (GET_CODE (operands[0]) != REG)
4780 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4781 emit_insn (gen_movsi (operands[0], operands[1]));
4789 (define_insn "*arm_movqi_insn"
4790 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4791 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4793 && ( register_operand (operands[0], QImode)
4794 || register_operand (operands[1], QImode))"
4800 [(set_attr "type" "*,*,load,store1")
4801 (set_attr "predicable" "yes")]
4804 (define_insn "*thumb_movqi_insn"
4805 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4806 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4808 && ( register_operand (operands[0], QImode)
4809 || register_operand (operands[1], QImode))"
4817 [(set_attr "length" "2")
4818 (set_attr "type" "*,load,store1,*,*,*")
4819 (set_attr "pool_range" "*,32,*,*,*,*")]
4822 (define_expand "movsf"
4823 [(set (match_operand:SF 0 "general_operand" "")
4824 (match_operand:SF 1 "general_operand" ""))]
4829 if (GET_CODE (operands[0]) == MEM)
4830 operands[1] = force_reg (SFmode, operands[1]);
4832 else /* TARGET_THUMB */
4834 if (!no_new_pseudos)
4836 if (GET_CODE (operands[0]) != REG)
4837 operands[1] = force_reg (SFmode, operands[1]);
4844 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4845 (match_operand:SF 1 "immediate_operand" ""))]
4847 && !TARGET_HARD_FLOAT
4849 && GET_CODE (operands[1]) == CONST_DOUBLE"
4850 [(set (match_dup 2) (match_dup 3))]
4852 operands[2] = gen_lowpart (SImode, operands[0]);
4853 operands[3] = gen_lowpart (SImode, operands[1]);
4854 if (operands[2] == 0 || operands[3] == 0)
4859 (define_insn "*arm_movsf_soft_insn"
4860 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4861 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4864 && TARGET_SOFT_FLOAT
4865 && (GET_CODE (operands[0]) != MEM
4866 || register_operand (operands[1], SFmode))"
4869 ldr%?\\t%0, %1\\t%@ float
4870 str%?\\t%1, %0\\t%@ float"
4871 [(set_attr "length" "4,4,4")
4872 (set_attr "predicable" "yes")
4873 (set_attr "type" "*,load,store1")
4874 (set_attr "pool_range" "*,4096,*")
4875 (set_attr "neg_pool_range" "*,4084,*")]
4878 ;;; ??? This should have alternatives for constants.
4879 (define_insn "*thumb_movsf_insn"
4880 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4881 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4883 && ( register_operand (operands[0], SFmode)
4884 || register_operand (operands[1], SFmode))"
4893 [(set_attr "length" "2")
4894 (set_attr "type" "*,load,store1,load,store1,*,*")
4895 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4898 (define_expand "movdf"
4899 [(set (match_operand:DF 0 "general_operand" "")
4900 (match_operand:DF 1 "general_operand" ""))]
4905 if (GET_CODE (operands[0]) == MEM)
4906 operands[1] = force_reg (DFmode, operands[1]);
4908 else /* TARGET_THUMB */
4910 if (!no_new_pseudos)
4912 if (GET_CODE (operands[0]) != REG)
4913 operands[1] = force_reg (DFmode, operands[1]);
4919 ;; Reloading a df mode value stored in integer regs to memory can require a
4921 (define_expand "reload_outdf"
4922 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4923 (match_operand:DF 1 "s_register_operand" "r")
4924 (match_operand:SI 2 "s_register_operand" "=&r")]
4928 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4931 operands[2] = XEXP (operands[0], 0);
4932 else if (code == POST_INC || code == PRE_DEC)
4934 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4935 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4936 emit_insn (gen_movdi (operands[0], operands[1]));
4939 else if (code == PRE_INC)
4941 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4943 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4946 else if (code == POST_DEC)
4947 operands[2] = XEXP (XEXP (operands[0], 0), 0);
4949 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4950 XEXP (XEXP (operands[0], 0), 1)));
4952 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4955 if (code == POST_DEC)
4956 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4962 (define_insn "*movdf_soft_insn"
4963 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4964 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4965 "TARGET_ARM && TARGET_SOFT_FLOAT
4968 "* return output_move_double (operands);"
4969 [(set_attr "length" "8,8,8")
4970 (set_attr "type" "*,load,store2")
4971 (set_attr "pool_range" "1020")
4972 (set_attr "neg_pool_range" "1008")]
4975 ;;; ??? This should have alternatives for constants.
4976 ;;; ??? This was originally identical to the movdi_insn pattern.
4977 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4978 ;;; thumb_reorg with a memory reference.
4979 (define_insn "*thumb_movdf_insn"
4980 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4981 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
4983 && ( register_operand (operands[0], DFmode)
4984 || register_operand (operands[1], DFmode))"
4986 switch (which_alternative)
4990 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4991 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4992 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4994 return \"ldmia\\t%1, {%0, %H0}\";
4996 return \"stmia\\t%0, {%1, %H1}\";
4998 return thumb_load_double_from_address (operands);
5000 operands[2] = gen_rtx (MEM, SImode,
5001 plus_constant (XEXP (operands[0], 0), 4));
5002 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
5005 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
5006 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
5007 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
5010 [(set_attr "length" "4,2,2,6,4,4")
5011 (set_attr "type" "*,load,store2,load,store2,*")
5012 (set_attr "pool_range" "*,*,*,1020,*,*")]
5016 (define_expand "movv2si"
5017 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
5018 (match_operand:V2SI 1 "general_operand" ""))]
5019 "TARGET_REALLY_IWMMXT"
5023 (define_expand "movv4hi"
5024 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
5025 (match_operand:V4HI 1 "general_operand" ""))]
5026 "TARGET_REALLY_IWMMXT"
5030 (define_expand "movv8qi"
5031 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
5032 (match_operand:V8QI 1 "general_operand" ""))]
5033 "TARGET_REALLY_IWMMXT"
5038 ;; load- and store-multiple insns
5039 ;; The arm can load/store any set of registers, provided that they are in
5040 ;; ascending order; but that is beyond GCC so stick with what it knows.
5042 (define_expand "load_multiple"
5043 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5044 (match_operand:SI 1 "" ""))
5045 (use (match_operand:SI 2 "" ""))])]
5048 /* Support only fixed point registers. */
5049 if (GET_CODE (operands[2]) != CONST_INT
5050 || INTVAL (operands[2]) > 14
5051 || INTVAL (operands[2]) < 2
5052 || GET_CODE (operands[1]) != MEM
5053 || GET_CODE (operands[0]) != REG
5054 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
5055 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5059 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
5060 force_reg (SImode, XEXP (operands[1], 0)),
5061 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
5062 MEM_IN_STRUCT_P(operands[1]),
5063 MEM_SCALAR_P (operands[1]));
5067 ;; Load multiple with write-back
5069 (define_insn "*ldmsi_postinc4"
5070 [(match_parallel 0 "load_multiple_operation"
5071 [(set (match_operand:SI 1 "s_register_operand" "=r")
5072 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5074 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5075 (mem:SI (match_dup 2)))
5076 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5077 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5078 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5079 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
5080 (set (match_operand:SI 6 "arm_hard_register_operand" "")
5081 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
5082 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5083 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
5084 [(set_attr "type" "load")
5085 (set_attr "predicable" "yes")]
5088 (define_insn "*ldmsi_postinc3"
5089 [(match_parallel 0 "load_multiple_operation"
5090 [(set (match_operand:SI 1 "s_register_operand" "=r")
5091 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5093 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5094 (mem:SI (match_dup 2)))
5095 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5096 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
5097 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5098 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
5099 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5100 "ldm%?ia\\t%1!, {%3, %4, %5}"
5101 [(set_attr "type" "load")
5102 (set_attr "predicable" "yes")]
5105 (define_insn "*ldmsi_postinc2"
5106 [(match_parallel 0 "load_multiple_operation"
5107 [(set (match_operand:SI 1 "s_register_operand" "=r")
5108 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5110 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5111 (mem:SI (match_dup 2)))
5112 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5113 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
5114 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5115 "ldm%?ia\\t%1!, {%3, %4}"
5116 [(set_attr "type" "load")
5117 (set_attr "predicable" "yes")]
5120 ;; Ordinary load multiple
5122 (define_insn "*ldmsi4"
5123 [(match_parallel 0 "load_multiple_operation"
5124 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5125 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5126 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5127 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5128 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5129 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5130 (set (match_operand:SI 5 "arm_hard_register_operand" "")
5131 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
5132 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5133 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
5134 [(set_attr "type" "load")
5135 (set_attr "predicable" "yes")]
5138 (define_insn "*ldmsi3"
5139 [(match_parallel 0 "load_multiple_operation"
5140 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5141 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5142 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5143 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5144 (set (match_operand:SI 4 "arm_hard_register_operand" "")
5145 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
5146 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5147 "ldm%?ia\\t%1, {%2, %3, %4}"
5148 [(set_attr "type" "load")
5149 (set_attr "predicable" "yes")]
5152 (define_insn "*ldmsi2"
5153 [(match_parallel 0 "load_multiple_operation"
5154 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5155 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5156 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5157 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5158 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5159 "ldm%?ia\\t%1, {%2, %3}"
5160 [(set_attr "type" "load")
5161 (set_attr "predicable" "yes")]
5164 (define_expand "store_multiple"
5165 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5166 (match_operand:SI 1 "" ""))
5167 (use (match_operand:SI 2 "" ""))])]
5170 /* Support only fixed point registers */
5171 if (GET_CODE (operands[2]) != CONST_INT
5172 || INTVAL (operands[2]) > 14
5173 || INTVAL (operands[2]) < 2
5174 || GET_CODE (operands[1]) != REG
5175 || GET_CODE (operands[0]) != MEM
5176 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5177 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5181 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5182 force_reg (SImode, XEXP (operands[0], 0)),
5183 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5184 MEM_IN_STRUCT_P(operands[0]),
5185 MEM_SCALAR_P (operands[0]));
5189 ;; Store multiple with write-back
5191 (define_insn "*stmsi_postinc4"
5192 [(match_parallel 0 "store_multiple_operation"
5193 [(set (match_operand:SI 1 "s_register_operand" "=r")
5194 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5196 (set (mem:SI (match_dup 2))
5197 (match_operand:SI 3 "arm_hard_register_operand" ""))
5198 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5199 (match_operand:SI 4 "arm_hard_register_operand" ""))
5200 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5201 (match_operand:SI 5 "arm_hard_register_operand" ""))
5202 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5203 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5204 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5205 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5206 [(set_attr "predicable" "yes")
5207 (set_attr "type" "store4")]
5210 (define_insn "*stmsi_postinc3"
5211 [(match_parallel 0 "store_multiple_operation"
5212 [(set (match_operand:SI 1 "s_register_operand" "=r")
5213 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5215 (set (mem:SI (match_dup 2))
5216 (match_operand:SI 3 "arm_hard_register_operand" ""))
5217 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5218 (match_operand:SI 4 "arm_hard_register_operand" ""))
5219 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5220 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5221 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5222 "stm%?ia\\t%1!, {%3, %4, %5}"
5223 [(set_attr "predicable" "yes")
5224 (set_attr "type" "store3")]
5227 (define_insn "*stmsi_postinc2"
5228 [(match_parallel 0 "store_multiple_operation"
5229 [(set (match_operand:SI 1 "s_register_operand" "=r")
5230 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5232 (set (mem:SI (match_dup 2))
5233 (match_operand:SI 3 "arm_hard_register_operand" ""))
5234 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5235 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5236 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5237 "stm%?ia\\t%1!, {%3, %4}"
5238 [(set_attr "predicable" "yes")
5239 (set_attr "type" "store2")]
5242 ;; Ordinary store multiple
5244 (define_insn "*stmsi4"
5245 [(match_parallel 0 "store_multiple_operation"
5246 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5247 (match_operand:SI 2 "arm_hard_register_operand" ""))
5248 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5249 (match_operand:SI 3 "arm_hard_register_operand" ""))
5250 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5251 (match_operand:SI 4 "arm_hard_register_operand" ""))
5252 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5253 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5254 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5255 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5256 [(set_attr "predicable" "yes")
5257 (set_attr "type" "store4")]
5260 (define_insn "*stmsi3"
5261 [(match_parallel 0 "store_multiple_operation"
5262 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5263 (match_operand:SI 2 "arm_hard_register_operand" ""))
5264 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5265 (match_operand:SI 3 "arm_hard_register_operand" ""))
5266 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5267 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5268 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5269 "stm%?ia\\t%1, {%2, %3, %4}"
5270 [(set_attr "predicable" "yes")
5271 (set_attr "type" "store3")]
5274 (define_insn "*stmsi2"
5275 [(match_parallel 0 "store_multiple_operation"
5276 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5277 (match_operand:SI 2 "arm_hard_register_operand" ""))
5278 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5279 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5280 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5281 "stm%?ia\\t%1, {%2, %3}"
5282 [(set_attr "predicable" "yes")
5283 (set_attr "type" "store2")]
5286 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5287 ;; We could let this apply for blocks of less than this, but it clobbers so
5288 ;; many registers that there is then probably a better way.
5290 (define_expand "movstrqi"
5291 [(match_operand:BLK 0 "general_operand" "")
5292 (match_operand:BLK 1 "general_operand" "")
5293 (match_operand:SI 2 "const_int_operand" "")
5294 (match_operand:SI 3 "const_int_operand" "")]
5299 if (arm_gen_movstrqi (operands))
5303 else /* TARGET_THUMB */
5305 if ( INTVAL (operands[3]) != 4
5306 || INTVAL (operands[2]) > 48)
5309 thumb_expand_movstrqi (operands);
5315 ;; Thumb block-move insns
5317 (define_insn "movmem12b"
5318 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5319 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5320 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5321 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5322 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5323 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5324 (set (match_operand:SI 0 "register_operand" "=l")
5325 (plus:SI (match_dup 2) (const_int 12)))
5326 (set (match_operand:SI 1 "register_operand" "=l")
5327 (plus:SI (match_dup 3) (const_int 12)))
5328 (clobber (match_scratch:SI 4 "=&l"))
5329 (clobber (match_scratch:SI 5 "=&l"))
5330 (clobber (match_scratch:SI 6 "=&l"))]
5332 "* return thumb_output_move_mem_multiple (3, operands);"
5333 [(set_attr "length" "4")
5334 ; This isn't entirely accurate... It loads as well, but in terms of
5335 ; scheduling the following insn it is better to consider it as a store
5336 (set_attr "type" "store3")]
5339 (define_insn "movmem8b"
5340 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5341 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5342 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5343 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5344 (set (match_operand:SI 0 "register_operand" "=l")
5345 (plus:SI (match_dup 2) (const_int 8)))
5346 (set (match_operand:SI 1 "register_operand" "=l")
5347 (plus:SI (match_dup 3) (const_int 8)))
5348 (clobber (match_scratch:SI 4 "=&l"))
5349 (clobber (match_scratch:SI 5 "=&l"))]
5351 "* return thumb_output_move_mem_multiple (2, operands);"
5352 [(set_attr "length" "4")
5353 ; This isn't entirely accurate... It loads as well, but in terms of
5354 ; scheduling the following insn it is better to consider it as a store
5355 (set_attr "type" "store2")]
5360 ;; Compare & branch insns
5361 ;; The range calculations are based as follows:
5362 ;; For forward branches, the address calculation returns the address of
5363 ;; the next instruction. This is 2 beyond the branch instruction.
5364 ;; For backward branches, the address calculation returns the address of
5365 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5366 ;; instruction for the shortest sequence, and 4 before the branch instruction
5367 ;; if we have to jump around an unconditional branch.
5368 ;; To the basic branch range the PC offset must be added (this is +4).
5369 ;; So for forward branches we have
5370 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5371 ;; And for backward branches we have
5372 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5374 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5375 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5377 (define_expand "cbranchsi4"
5378 [(set (pc) (if_then_else
5379 (match_operator 0 "arm_comparison_operator"
5380 [(match_operand:SI 1 "s_register_operand" "")
5381 (match_operand:SI 2 "nonmemory_operand" "")])
5382 (label_ref (match_operand 3 "" ""))
5386 if (thumb_cmpneg_operand (operands[2], SImode))
5388 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5389 operands[3], operands[0]));
5392 if (!thumb_cmp_operand (operands[2], SImode))
5393 operands[2] = force_reg (SImode, operands[2]);
5396 (define_insn "*cbranchsi4_insn"
5397 [(set (pc) (if_then_else
5398 (match_operator 0 "arm_comparison_operator"
5399 [(match_operand:SI 1 "s_register_operand" "l,*h")
5400 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5401 (label_ref (match_operand 3 "" ""))
5405 output_asm_insn (\"cmp\\t%1, %2\", operands);
5407 switch (get_attr_length (insn))
5409 case 4: return \"b%d0\\t%l3\";
5410 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5411 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5414 [(set (attr "far_jump")
5416 (eq_attr "length" "8")
5417 (const_string "yes")
5418 (const_string "no")))
5419 (set (attr "length")
5421 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5422 (le (minus (match_dup 3) (pc)) (const_int 256)))
5425 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5426 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5431 (define_insn "cbranchsi4_scratch"
5432 [(set (pc) (if_then_else
5433 (match_operator 4 "arm_comparison_operator"
5434 [(match_operand:SI 1 "s_register_operand" "l,0")
5435 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5436 (label_ref (match_operand 3 "" ""))
5438 (clobber (match_scratch:SI 0 "=l,l"))]
5441 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5443 switch (get_attr_length (insn))
5445 case 4: return \"b%d4\\t%l3\";
5446 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5447 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5450 [(set (attr "far_jump")
5452 (eq_attr "length" "8")
5453 (const_string "yes")
5454 (const_string "no")))
5455 (set (attr "length")
5457 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5458 (le (minus (match_dup 3) (pc)) (const_int 256)))
5461 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5462 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5466 (define_insn "*movsi_cbranchsi4"
5469 (match_operator 3 "arm_comparison_operator"
5470 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5472 (label_ref (match_operand 2 "" ""))
5474 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5478 if (which_alternative == 0)
5479 output_asm_insn (\"cmp\t%0, #0\", operands);
5480 else if (which_alternative == 1)
5481 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5484 output_asm_insn (\"cmp\t%1, #0\", operands);
5485 if (which_alternative == 2)
5486 output_asm_insn (\"mov\t%0, %1\", operands);
5488 output_asm_insn (\"str\t%1, %0\", operands);
5490 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5492 case 4: return \"b%d3\\t%l2\";
5493 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5494 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5497 [(set (attr "far_jump")
5499 (ior (and (gt (symbol_ref ("which_alternative"))
5501 (eq_attr "length" "8"))
5502 (eq_attr "length" "10"))
5503 (const_string "yes")
5504 (const_string "no")))
5505 (set (attr "length")
5507 (le (symbol_ref ("which_alternative"))
5510 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5511 (le (minus (match_dup 2) (pc)) (const_int 256)))
5514 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5515 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5519 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5520 (le (minus (match_dup 2) (pc)) (const_int 256)))
5523 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5524 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5529 (define_insn "*negated_cbranchsi4"
5532 (match_operator 0 "arm_comparison_operator"
5533 [(match_operand:SI 1 "s_register_operand" "l")
5534 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5535 (label_ref (match_operand 3 "" ""))
5539 output_asm_insn (\"cmn\\t%1, %2\", operands);
5540 switch (get_attr_length (insn))
5542 case 4: return \"b%d0\\t%l3\";
5543 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5544 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5547 [(set (attr "far_jump")
5549 (eq_attr "length" "8")
5550 (const_string "yes")
5551 (const_string "no")))
5552 (set (attr "length")
5554 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5555 (le (minus (match_dup 3) (pc)) (const_int 256)))
5558 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5559 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5564 (define_insn "*tbit_cbranch"
5567 (match_operator 0 "equality_operator"
5568 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5570 (match_operand:SI 2 "const_int_operand" "i"))
5572 (label_ref (match_operand 3 "" ""))
5574 (clobber (match_scratch:SI 4 "=l"))]
5579 op[0] = operands[4];
5580 op[1] = operands[1];
5581 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5583 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5584 switch (get_attr_length (insn))
5586 case 4: return \"b%d0\\t%l3\";
5587 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5588 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5591 [(set (attr "far_jump")
5593 (eq_attr "length" "8")
5594 (const_string "yes")
5595 (const_string "no")))
5596 (set (attr "length")
5598 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5599 (le (minus (match_dup 3) (pc)) (const_int 256)))
5602 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5603 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5608 (define_insn "*tstsi3_cbranch"
5611 (match_operator 3 "equality_operator"
5612 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5613 (match_operand:SI 1 "s_register_operand" "l"))
5615 (label_ref (match_operand 2 "" ""))
5620 output_asm_insn (\"tst\\t%0, %1\", operands);
5621 switch (get_attr_length (insn))
5623 case 4: return \"b%d3\\t%l2\";
5624 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5625 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5628 [(set (attr "far_jump")
5630 (eq_attr "length" "8")
5631 (const_string "yes")
5632 (const_string "no")))
5633 (set (attr "length")
5635 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5636 (le (minus (match_dup 2) (pc)) (const_int 256)))
5639 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5640 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5645 (define_insn "*andsi3_cbranch"
5648 (match_operator 5 "equality_operator"
5649 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5650 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5652 (label_ref (match_operand 4 "" ""))
5654 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5655 (and:SI (match_dup 2) (match_dup 3)))
5656 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5660 if (which_alternative == 0)
5661 output_asm_insn (\"and\\t%0, %3\", operands);
5662 else if (which_alternative == 1)
5664 output_asm_insn (\"and\\t%1, %3\", operands);
5665 output_asm_insn (\"mov\\t%0, %1\", operands);
5669 output_asm_insn (\"and\\t%1, %3\", operands);
5670 output_asm_insn (\"str\\t%1, %0\", operands);
5673 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5675 case 4: return \"b%d5\\t%l4\";
5676 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5677 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5680 [(set (attr "far_jump")
5682 (ior (and (eq (symbol_ref ("which_alternative"))
5684 (eq_attr "length" "8"))
5685 (eq_attr "length" "10"))
5686 (const_string "yes")
5687 (const_string "no")))
5688 (set (attr "length")
5690 (eq (symbol_ref ("which_alternative"))
5693 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5694 (le (minus (match_dup 4) (pc)) (const_int 256)))
5697 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5698 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5702 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5703 (le (minus (match_dup 4) (pc)) (const_int 256)))
5706 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5707 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5712 (define_insn "*orrsi3_cbranch_scratch"
5715 (match_operator 4 "equality_operator"
5716 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5717 (match_operand:SI 2 "s_register_operand" "l"))
5719 (label_ref (match_operand 3 "" ""))
5721 (clobber (match_scratch:SI 0 "=l"))]
5725 output_asm_insn (\"orr\\t%0, %2\", operands);
5726 switch (get_attr_length (insn))
5728 case 4: return \"b%d4\\t%l3\";
5729 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5730 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5733 [(set (attr "far_jump")
5735 (eq_attr "length" "8")
5736 (const_string "yes")
5737 (const_string "no")))
5738 (set (attr "length")
5740 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5741 (le (minus (match_dup 3) (pc)) (const_int 256)))
5744 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5745 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5750 (define_insn "*orrsi3_cbranch"
5753 (match_operator 5 "equality_operator"
5754 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5755 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5757 (label_ref (match_operand 4 "" ""))
5759 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5760 (ior:SI (match_dup 2) (match_dup 3)))
5761 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5765 if (which_alternative == 0)
5766 output_asm_insn (\"orr\\t%0, %3\", operands);
5767 else if (which_alternative == 1)
5769 output_asm_insn (\"orr\\t%1, %3\", operands);
5770 output_asm_insn (\"mov\\t%0, %1\", operands);
5774 output_asm_insn (\"orr\\t%1, %3\", operands);
5775 output_asm_insn (\"str\\t%1, %0\", operands);
5778 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5780 case 4: return \"b%d5\\t%l4\";
5781 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5782 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5785 [(set (attr "far_jump")
5787 (ior (and (eq (symbol_ref ("which_alternative"))
5789 (eq_attr "length" "8"))
5790 (eq_attr "length" "10"))
5791 (const_string "yes")
5792 (const_string "no")))
5793 (set (attr "length")
5795 (eq (symbol_ref ("which_alternative"))
5798 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5799 (le (minus (match_dup 4) (pc)) (const_int 256)))
5802 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5803 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5807 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5808 (le (minus (match_dup 4) (pc)) (const_int 256)))
5811 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5812 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5817 (define_insn "*xorsi3_cbranch_scratch"
5820 (match_operator 4 "equality_operator"
5821 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
5822 (match_operand:SI 2 "s_register_operand" "l"))
5824 (label_ref (match_operand 3 "" ""))
5826 (clobber (match_scratch:SI 0 "=l"))]
5830 output_asm_insn (\"eor\\t%0, %2\", operands);
5831 switch (get_attr_length (insn))
5833 case 4: return \"b%d4\\t%l3\";
5834 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5835 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5838 [(set (attr "far_jump")
5840 (eq_attr "length" "8")
5841 (const_string "yes")
5842 (const_string "no")))
5843 (set (attr "length")
5845 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5846 (le (minus (match_dup 3) (pc)) (const_int 256)))
5849 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5850 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5855 (define_insn "*xorsi3_cbranch"
5858 (match_operator 5 "equality_operator"
5859 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5860 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5862 (label_ref (match_operand 4 "" ""))
5864 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5865 (xor:SI (match_dup 2) (match_dup 3)))
5866 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5870 if (which_alternative == 0)
5871 output_asm_insn (\"eor\\t%0, %3\", operands);
5872 else if (which_alternative == 1)
5874 output_asm_insn (\"eor\\t%1, %3\", operands);
5875 output_asm_insn (\"mov\\t%0, %1\", operands);
5879 output_asm_insn (\"eor\\t%1, %3\", operands);
5880 output_asm_insn (\"str\\t%1, %0\", operands);
5883 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5885 case 4: return \"b%d5\\t%l4\";
5886 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5887 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5890 [(set (attr "far_jump")
5892 (ior (and (eq (symbol_ref ("which_alternative"))
5894 (eq_attr "length" "8"))
5895 (eq_attr "length" "10"))
5896 (const_string "yes")
5897 (const_string "no")))
5898 (set (attr "length")
5900 (eq (symbol_ref ("which_alternative"))
5903 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5904 (le (minus (match_dup 4) (pc)) (const_int 256)))
5907 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5908 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5912 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5913 (le (minus (match_dup 4) (pc)) (const_int 256)))
5916 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5917 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5922 (define_insn "*bicsi3_cbranch_scratch"
5925 (match_operator 4 "equality_operator"
5926 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
5927 (match_operand:SI 1 "s_register_operand" "0"))
5929 (label_ref (match_operand 3 "" ""))
5931 (clobber (match_scratch:SI 0 "=l"))]
5935 output_asm_insn (\"bic\\t%0, %2\", operands);
5936 switch (get_attr_length (insn))
5938 case 4: return \"b%d4\\t%l3\";
5939 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5940 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5943 [(set (attr "far_jump")
5945 (eq_attr "length" "8")
5946 (const_string "yes")
5947 (const_string "no")))
5948 (set (attr "length")
5950 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5951 (le (minus (match_dup 3) (pc)) (const_int 256)))
5954 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5955 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5960 (define_insn "*bicsi3_cbranch"
5963 (match_operator 5 "equality_operator"
5964 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5965 (match_operand:SI 2 "s_register_operand" "0,1,1,1"))
5967 (label_ref (match_operand 4 "" ""))
5969 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5970 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
5971 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5975 if (which_alternative == 0)
5976 output_asm_insn (\"bic\\t%0, %3\", operands);
5977 else if (which_alternative == 1)
5979 output_asm_insn (\"bic\\t%1, %3\", operands);
5980 output_asm_insn (\"mov\\t%0, %1\", operands);
5984 output_asm_insn (\"bic\\t%1, %3\", operands);
5985 output_asm_insn (\"str\\t%1, %0\", operands);
5988 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5990 case 4: return \"b%d5\\t%l4\";
5991 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5992 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5995 [(set (attr "far_jump")
5997 (ior (and (eq (symbol_ref ("which_alternative"))
5999 (eq_attr "length" "8"))
6000 (eq_attr "length" "10"))
6001 (const_string "yes")
6002 (const_string "no")))
6003 (set (attr "length")
6005 (eq (symbol_ref ("which_alternative"))
6008 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6009 (le (minus (match_dup 4) (pc)) (const_int 256)))
6012 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6013 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6017 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6018 (le (minus (match_dup 4) (pc)) (const_int 256)))
6021 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6022 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6027 (define_insn "*cbranchne_decr1"
6029 (if_then_else (match_operator 3 "equality_operator"
6030 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
6032 (label_ref (match_operand 4 "" ""))
6034 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6035 (plus:SI (match_dup 2) (const_int -1)))
6036 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6041 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
6043 VOIDmode, operands[2], const1_rtx);
6044 cond[1] = operands[4];
6046 if (which_alternative == 0)
6047 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
6048 else if (which_alternative == 1)
6050 /* We must provide an alternative for a hi reg because reload
6051 cannot handle output reloads on a jump instruction, but we
6052 can't subtract into that. Fortunately a mov from lo to hi
6053 does not clobber the condition codes. */
6054 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6055 output_asm_insn (\"mov\\t%0, %1\", operands);
6059 /* Similarly, but the target is memory. */
6060 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
6061 output_asm_insn (\"str\\t%1, %0\", operands);
6064 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
6067 output_asm_insn (\"b%d0\\t%l1\", cond);
6070 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6071 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
6073 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
6074 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6078 [(set (attr "far_jump")
6080 (ior (and (eq (symbol_ref ("which_alternative"))
6082 (eq_attr "length" "8"))
6083 (eq_attr "length" "10"))
6084 (const_string "yes")
6085 (const_string "no")))
6086 (set_attr_alternative "length"
6090 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6091 (le (minus (match_dup 4) (pc)) (const_int 256)))
6094 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6095 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6100 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6101 (le (minus (match_dup 4) (pc)) (const_int 256)))
6104 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6105 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6110 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6111 (le (minus (match_dup 4) (pc)) (const_int 256)))
6114 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6115 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6120 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
6121 (le (minus (match_dup 4) (pc)) (const_int 256)))
6124 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
6125 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6130 (define_insn "*addsi3_cbranch"
6133 (match_operator 4 "comparison_operator"
6135 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
6136 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
6138 (label_ref (match_operand 5 "" ""))
6141 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
6142 (plus:SI (match_dup 2) (match_dup 3)))
6143 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
6145 && (GET_CODE (operands[4]) == EQ
6146 || GET_CODE (operands[4]) == NE
6147 || GET_CODE (operands[4]) == GE
6148 || GET_CODE (operands[4]) == LT)"
6154 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6155 cond[1] = operands[2];
6156 cond[2] = operands[3];
6158 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6159 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6161 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6163 if (which_alternative >= 3
6164 && which_alternative < 4)
6165 output_asm_insn (\"mov\\t%0, %1\", operands);
6166 else if (which_alternative >= 4)
6167 output_asm_insn (\"str\\t%1, %0\", operands);
6169 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6172 return \"b%d4\\t%l5\";
6174 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6176 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6180 [(set (attr "far_jump")
6182 (ior (and (lt (symbol_ref ("which_alternative"))
6184 (eq_attr "length" "8"))
6185 (eq_attr "length" "10"))
6186 (const_string "yes")
6187 (const_string "no")))
6188 (set (attr "length")
6190 (lt (symbol_ref ("which_alternative"))
6193 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6194 (le (minus (match_dup 5) (pc)) (const_int 256)))
6197 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6198 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6202 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6203 (le (minus (match_dup 5) (pc)) (const_int 256)))
6206 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6207 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6212 (define_insn "*addsi3_cbranch_scratch"
6215 (match_operator 3 "comparison_operator"
6217 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6218 (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6220 (label_ref (match_operand 4 "" ""))
6222 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6224 && (GET_CODE (operands[3]) == EQ
6225 || GET_CODE (operands[3]) == NE
6226 || GET_CODE (operands[3]) == GE
6227 || GET_CODE (operands[3]) == LT)"
6230 switch (which_alternative)
6233 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6236 output_asm_insn (\"cmn\t%1, %2\", operands);
6239 output_asm_insn (\"add\t%0, %1, %2\", operands);
6242 output_asm_insn (\"add\t%0, %0, %2\", operands);
6246 switch (get_attr_length (insn))
6249 return \"b%d3\\t%l4\";
6251 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6253 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6257 [(set (attr "far_jump")
6259 (eq_attr "length" "8")
6260 (const_string "yes")
6261 (const_string "no")))
6262 (set (attr "length")
6264 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6265 (le (minus (match_dup 4) (pc)) (const_int 256)))
6268 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6269 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6274 (define_insn "*subsi3_cbranch"
6277 (match_operator 4 "comparison_operator"
6279 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6280 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6282 (label_ref (match_operand 5 "" ""))
6284 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6285 (minus:SI (match_dup 2) (match_dup 3)))
6286 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6288 && (GET_CODE (operands[4]) == EQ
6289 || GET_CODE (operands[4]) == NE
6290 || GET_CODE (operands[4]) == GE
6291 || GET_CODE (operands[4]) == LT)"
6294 if (which_alternative == 0)
6295 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6296 else if (which_alternative == 1)
6298 /* We must provide an alternative for a hi reg because reload
6299 cannot handle output reloads on a jump instruction, but we
6300 can't subtract into that. Fortunately a mov from lo to hi
6301 does not clobber the condition codes. */
6302 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6303 output_asm_insn (\"mov\\t%0, %1\", operands);
6307 /* Similarly, but the target is memory. */
6308 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6309 output_asm_insn (\"str\\t%1, %0\", operands);
6312 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6315 return \"b%d4\\t%l5\";
6317 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6319 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6323 [(set (attr "far_jump")
6325 (ior (and (eq (symbol_ref ("which_alternative"))
6327 (eq_attr "length" "8"))
6328 (eq_attr "length" "10"))
6329 (const_string "yes")
6330 (const_string "no")))
6331 (set (attr "length")
6333 (eq (symbol_ref ("which_alternative"))
6336 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6337 (le (minus (match_dup 5) (pc)) (const_int 256)))
6340 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6341 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6345 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6346 (le (minus (match_dup 5) (pc)) (const_int 256)))
6349 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6350 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6355 (define_insn "*subsi3_cbranch_scratch"
6358 (match_operator 0 "arm_comparison_operator"
6359 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6360 (match_operand:SI 2 "nonmemory_operand" "l"))
6362 (label_ref (match_operand 3 "" ""))
6365 && (GET_CODE (operands[0]) == EQ
6366 || GET_CODE (operands[0]) == NE
6367 || GET_CODE (operands[0]) == GE
6368 || GET_CODE (operands[0]) == LT)"
6370 output_asm_insn (\"cmp\\t%1, %2\", operands);
6371 switch (get_attr_length (insn))
6373 case 4: return \"b%d0\\t%l3\";
6374 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6375 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6378 [(set (attr "far_jump")
6380 (eq_attr "length" "8")
6381 (const_string "yes")
6382 (const_string "no")))
6383 (set (attr "length")
6385 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6386 (le (minus (match_dup 3) (pc)) (const_int 256)))
6389 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6390 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6395 ;; Comparison and test insns
6397 (define_expand "cmpsi"
6398 [(match_operand:SI 0 "s_register_operand" "")
6399 (match_operand:SI 1 "arm_add_operand" "")]
6402 arm_compare_op0 = operands[0];
6403 arm_compare_op1 = operands[1];
6408 (define_expand "cmpsf"
6409 [(match_operand:SF 0 "s_register_operand" "")
6410 (match_operand:SF 1 "fpa_rhs_operand" "")]
6411 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6413 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
6414 operands[1] = force_reg (SFmode, operands[1]);
6416 arm_compare_op0 = operands[0];
6417 arm_compare_op1 = operands[1];
6422 (define_expand "cmpdf"
6423 [(match_operand:DF 0 "s_register_operand" "")
6424 (match_operand:DF 1 "fpa_rhs_operand" "")]
6425 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6427 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
6428 operands[1] = force_reg (DFmode, operands[1]);
6430 arm_compare_op0 = operands[0];
6431 arm_compare_op1 = operands[1];
6436 (define_insn "*arm_cmpsi_insn"
6437 [(set (reg:CC CC_REGNUM)
6438 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6439 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6444 [(set_attr "conds" "set")]
6447 (define_insn "*cmpsi_shiftsi"
6448 [(set (reg:CC CC_REGNUM)
6449 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6450 (match_operator:SI 3 "shift_operator"
6451 [(match_operand:SI 1 "s_register_operand" "r")
6452 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6455 [(set_attr "conds" "set")
6456 (set_attr "shift" "1")
6460 (define_insn "*cmpsi_shiftsi_swp"
6461 [(set (reg:CC_SWP CC_REGNUM)
6462 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6463 [(match_operand:SI 1 "s_register_operand" "r")
6464 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6465 (match_operand:SI 0 "s_register_operand" "r")))]
6468 [(set_attr "conds" "set")
6469 (set_attr "shift" "1")
6473 (define_insn "*cmpsi_neg_shiftsi"
6474 [(set (reg:CC CC_REGNUM)
6475 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6476 (neg:SI (match_operator:SI 3 "shift_operator"
6477 [(match_operand:SI 1 "s_register_operand" "r")
6478 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6481 [(set_attr "conds" "set")
6482 (set_attr "shift" "1")
6486 ;; Cirrus SF compare instruction
6487 (define_insn "*cirrus_cmpsf"
6488 [(set (reg:CCFP CC_REGNUM)
6489 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6490 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6491 "TARGET_ARM && TARGET_CIRRUS"
6492 "cfcmps%?\\tr15, %V0, %V1"
6493 [(set_attr "type" "mav_farith")
6494 (set_attr "cirrus" "compare")]
6497 ;; Cirrus DF compare instruction
6498 (define_insn "*cirrus_cmpdf"
6499 [(set (reg:CCFP CC_REGNUM)
6500 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6501 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6502 "TARGET_ARM && TARGET_CIRRUS"
6503 "cfcmpd%?\\tr15, %V0, %V1"
6504 [(set_attr "type" "mav_farith")
6505 (set_attr "cirrus" "compare")]
6508 ;; Cirrus DI compare instruction
6509 (define_expand "cmpdi"
6510 [(match_operand:DI 0 "cirrus_fp_register" "")
6511 (match_operand:DI 1 "cirrus_fp_register" "")]
6512 "TARGET_ARM && TARGET_CIRRUS"
6514 arm_compare_op0 = operands[0];
6515 arm_compare_op1 = operands[1];
6519 (define_insn "*cirrus_cmpdi"
6520 [(set (reg:CC CC_REGNUM)
6521 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6522 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6523 "TARGET_ARM && TARGET_CIRRUS"
6524 "cfcmp64%?\\tr15, %V0, %V1"
6525 [(set_attr "type" "mav_farith")
6526 (set_attr "cirrus" "compare")]
6529 ; This insn allows redundant compares to be removed by cse, nothing should
6530 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6531 ; is deleted later on. The match_dup will match the mode here, so that
6532 ; mode changes of the condition codes aren't lost by this even though we don't
6533 ; specify what they are.
6535 (define_insn "*deleted_compare"
6536 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6538 "\\t%@ deleted compare"
6539 [(set_attr "conds" "set")
6540 (set_attr "length" "0")]
6544 ;; Conditional branch insns
6546 (define_expand "beq"
6548 (if_then_else (eq (match_dup 1) (const_int 0))
6549 (label_ref (match_operand 0 "" ""))
6552 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6555 (define_expand "bne"
6557 (if_then_else (ne (match_dup 1) (const_int 0))
6558 (label_ref (match_operand 0 "" ""))
6561 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6564 (define_expand "bgt"
6566 (if_then_else (gt (match_dup 1) (const_int 0))
6567 (label_ref (match_operand 0 "" ""))
6570 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6573 (define_expand "ble"
6575 (if_then_else (le (match_dup 1) (const_int 0))
6576 (label_ref (match_operand 0 "" ""))
6579 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6582 (define_expand "bge"
6584 (if_then_else (ge (match_dup 1) (const_int 0))
6585 (label_ref (match_operand 0 "" ""))
6588 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6591 (define_expand "blt"
6593 (if_then_else (lt (match_dup 1) (const_int 0))
6594 (label_ref (match_operand 0 "" ""))
6597 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6600 (define_expand "bgtu"
6602 (if_then_else (gtu (match_dup 1) (const_int 0))
6603 (label_ref (match_operand 0 "" ""))
6606 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6609 (define_expand "bleu"
6611 (if_then_else (leu (match_dup 1) (const_int 0))
6612 (label_ref (match_operand 0 "" ""))
6615 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6618 (define_expand "bgeu"
6620 (if_then_else (geu (match_dup 1) (const_int 0))
6621 (label_ref (match_operand 0 "" ""))
6624 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6627 (define_expand "bltu"
6629 (if_then_else (ltu (match_dup 1) (const_int 0))
6630 (label_ref (match_operand 0 "" ""))
6633 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6636 (define_expand "bunordered"
6638 (if_then_else (unordered (match_dup 1) (const_int 0))
6639 (label_ref (match_operand 0 "" ""))
6641 "TARGET_ARM && TARGET_HARD_FLOAT"
6642 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6646 (define_expand "bordered"
6648 (if_then_else (ordered (match_dup 1) (const_int 0))
6649 (label_ref (match_operand 0 "" ""))
6651 "TARGET_ARM && TARGET_HARD_FLOAT"
6652 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6656 (define_expand "bungt"
6658 (if_then_else (ungt (match_dup 1) (const_int 0))
6659 (label_ref (match_operand 0 "" ""))
6661 "TARGET_ARM && TARGET_HARD_FLOAT"
6662 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6665 (define_expand "bunlt"
6667 (if_then_else (unlt (match_dup 1) (const_int 0))
6668 (label_ref (match_operand 0 "" ""))
6670 "TARGET_ARM && TARGET_HARD_FLOAT"
6671 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6674 (define_expand "bunge"
6676 (if_then_else (unge (match_dup 1) (const_int 0))
6677 (label_ref (match_operand 0 "" ""))
6679 "TARGET_ARM && TARGET_HARD_FLOAT"
6680 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6683 (define_expand "bunle"
6685 (if_then_else (unle (match_dup 1) (const_int 0))
6686 (label_ref (match_operand 0 "" ""))
6688 "TARGET_ARM && TARGET_HARD_FLOAT"
6689 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6692 ;; The following two patterns need two branch instructions, since there is
6693 ;; no single instruction that will handle all cases.
6694 (define_expand "buneq"
6696 (if_then_else (uneq (match_dup 1) (const_int 0))
6697 (label_ref (match_operand 0 "" ""))
6699 "TARGET_ARM && TARGET_HARD_FLOAT"
6700 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6703 (define_expand "bltgt"
6705 (if_then_else (ltgt (match_dup 1) (const_int 0))
6706 (label_ref (match_operand 0 "" ""))
6708 "TARGET_ARM && TARGET_HARD_FLOAT"
6709 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6713 ;; Patterns to match conditional branch insns.
6716 ; Special pattern to match UNEQ.
6717 (define_insn "*arm_buneq"
6719 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6720 (label_ref (match_operand 0 "" ""))
6722 "TARGET_ARM && TARGET_HARD_FLOAT"
6724 if (arm_ccfsm_state != 0)
6727 return \"bvs\\t%l0\;beq\\t%l0\";
6729 [(set_attr "conds" "jump_clob")
6730 (set_attr "length" "8")]
6733 ; Special pattern to match LTGT.
6734 (define_insn "*arm_bltgt"
6736 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6737 (label_ref (match_operand 0 "" ""))
6739 "TARGET_ARM && TARGET_HARD_FLOAT"
6741 if (arm_ccfsm_state != 0)
6744 return \"bmi\\t%l0\;bgt\\t%l0\";
6746 [(set_attr "conds" "jump_clob")
6747 (set_attr "length" "8")]
6750 (define_insn "*arm_cond_branch"
6752 (if_then_else (match_operator 1 "arm_comparison_operator"
6753 [(match_operand 2 "cc_register" "") (const_int 0)])
6754 (label_ref (match_operand 0 "" ""))
6758 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6760 arm_ccfsm_state += 2;
6763 return \"b%d1\\t%l0\";
6765 [(set_attr "conds" "use")]
6768 ; Special pattern to match reversed UNEQ.
6769 (define_insn "*arm_buneq_reversed"
6771 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6773 (label_ref (match_operand 0 "" ""))))]
6774 "TARGET_ARM && TARGET_HARD_FLOAT"
6776 if (arm_ccfsm_state != 0)
6779 return \"bmi\\t%l0\;bgt\\t%l0\";
6781 [(set_attr "conds" "jump_clob")
6782 (set_attr "length" "8")]
6785 ; Special pattern to match reversed LTGT.
6786 (define_insn "*arm_bltgt_reversed"
6788 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6790 (label_ref (match_operand 0 "" ""))))]
6791 "TARGET_ARM && TARGET_HARD_FLOAT"
6793 if (arm_ccfsm_state != 0)
6796 return \"bvs\\t%l0\;beq\\t%l0\";
6798 [(set_attr "conds" "jump_clob")
6799 (set_attr "length" "8")]
6802 (define_insn "*arm_cond_branch_reversed"
6804 (if_then_else (match_operator 1 "arm_comparison_operator"
6805 [(match_operand 2 "cc_register" "") (const_int 0)])
6807 (label_ref (match_operand 0 "" ""))))]
6810 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6812 arm_ccfsm_state += 2;
6815 return \"b%D1\\t%l0\";
6817 [(set_attr "conds" "use")]
6824 (define_expand "seq"
6825 [(set (match_operand:SI 0 "s_register_operand" "")
6826 (eq:SI (match_dup 1) (const_int 0)))]
6828 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6831 (define_expand "sne"
6832 [(set (match_operand:SI 0 "s_register_operand" "")
6833 (ne:SI (match_dup 1) (const_int 0)))]
6835 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6838 (define_expand "sgt"
6839 [(set (match_operand:SI 0 "s_register_operand" "")
6840 (gt:SI (match_dup 1) (const_int 0)))]
6842 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6845 (define_expand "sle"
6846 [(set (match_operand:SI 0 "s_register_operand" "")
6847 (le:SI (match_dup 1) (const_int 0)))]
6849 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6852 (define_expand "sge"
6853 [(set (match_operand:SI 0 "s_register_operand" "")
6854 (ge:SI (match_dup 1) (const_int 0)))]
6856 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6859 (define_expand "slt"
6860 [(set (match_operand:SI 0 "s_register_operand" "")
6861 (lt:SI (match_dup 1) (const_int 0)))]
6863 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6866 (define_expand "sgtu"
6867 [(set (match_operand:SI 0 "s_register_operand" "")
6868 (gtu:SI (match_dup 1) (const_int 0)))]
6870 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6873 (define_expand "sleu"
6874 [(set (match_operand:SI 0 "s_register_operand" "")
6875 (leu:SI (match_dup 1) (const_int 0)))]
6877 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6880 (define_expand "sgeu"
6881 [(set (match_operand:SI 0 "s_register_operand" "")
6882 (geu:SI (match_dup 1) (const_int 0)))]
6884 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6887 (define_expand "sltu"
6888 [(set (match_operand:SI 0 "s_register_operand" "")
6889 (ltu:SI (match_dup 1) (const_int 0)))]
6891 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6894 (define_expand "sunordered"
6895 [(set (match_operand:SI 0 "s_register_operand" "")
6896 (unordered:SI (match_dup 1) (const_int 0)))]
6897 "TARGET_ARM && TARGET_HARD_FLOAT"
6898 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6902 (define_expand "sordered"
6903 [(set (match_operand:SI 0 "s_register_operand" "")
6904 (ordered:SI (match_dup 1) (const_int 0)))]
6905 "TARGET_ARM && TARGET_HARD_FLOAT"
6906 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6910 (define_expand "sungt"
6911 [(set (match_operand:SI 0 "s_register_operand" "")
6912 (ungt:SI (match_dup 1) (const_int 0)))]
6913 "TARGET_ARM && TARGET_HARD_FLOAT"
6914 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6918 (define_expand "sunge"
6919 [(set (match_operand:SI 0 "s_register_operand" "")
6920 (unge:SI (match_dup 1) (const_int 0)))]
6921 "TARGET_ARM && TARGET_HARD_FLOAT"
6922 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6926 (define_expand "sunlt"
6927 [(set (match_operand:SI 0 "s_register_operand" "")
6928 (unlt:SI (match_dup 1) (const_int 0)))]
6929 "TARGET_ARM && TARGET_HARD_FLOAT"
6930 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6934 (define_expand "sunle"
6935 [(set (match_operand:SI 0 "s_register_operand" "")
6936 (unle:SI (match_dup 1) (const_int 0)))]
6937 "TARGET_ARM && TARGET_HARD_FLOAT"
6938 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6942 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6943 ;;; simple ARM instructions.
6945 ; (define_expand "suneq"
6946 ; [(set (match_operand:SI 0 "s_register_operand" "")
6947 ; (uneq:SI (match_dup 1) (const_int 0)))]
6948 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6952 ; (define_expand "sltgt"
6953 ; [(set (match_operand:SI 0 "s_register_operand" "")
6954 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6955 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6959 (define_insn "*mov_scc"
6960 [(set (match_operand:SI 0 "s_register_operand" "=r")
6961 (match_operator:SI 1 "arm_comparison_operator"
6962 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6964 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6965 [(set_attr "conds" "use")
6966 (set_attr "length" "8")]
6969 (define_insn "*mov_negscc"
6970 [(set (match_operand:SI 0 "s_register_operand" "=r")
6971 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6972 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6974 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6975 [(set_attr "conds" "use")
6976 (set_attr "length" "8")]
6979 (define_insn "*mov_notscc"
6980 [(set (match_operand:SI 0 "s_register_operand" "=r")
6981 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6982 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6984 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6985 [(set_attr "conds" "use")
6986 (set_attr "length" "8")]
6990 ;; Conditional move insns
6992 (define_expand "movsicc"
6993 [(set (match_operand:SI 0 "s_register_operand" "")
6994 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6995 (match_operand:SI 2 "arm_not_operand" "")
6996 (match_operand:SI 3 "arm_not_operand" "")))]
7000 enum rtx_code code = GET_CODE (operands[1]);
7003 if (code == UNEQ || code == LTGT)
7006 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7007 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7011 (define_expand "movsfcc"
7012 [(set (match_operand:SF 0 "s_register_operand" "")
7013 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
7014 (match_operand:SF 2 "s_register_operand" "")
7015 (match_operand:SF 3 "nonmemory_operand" "")))]
7019 enum rtx_code code = GET_CODE (operands[1]);
7022 if (code == UNEQ || code == LTGT)
7025 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
7026 Otherwise, ensure it is a valid FP add operand */
7027 if ((!TARGET_HARD_FLOAT)
7028 || (!fpa_add_operand (operands[3], SFmode)))
7029 operands[3] = force_reg (SFmode, operands[3]);
7031 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7032 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7036 (define_expand "movdfcc"
7037 [(set (match_operand:DF 0 "s_register_operand" "")
7038 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
7039 (match_operand:DF 2 "s_register_operand" "")
7040 (match_operand:DF 3 "fpa_add_operand" "")))]
7041 "TARGET_ARM && TARGET_HARD_FLOAT"
7044 enum rtx_code code = GET_CODE (operands[1]);
7047 if (code == UNEQ || code == LTGT)
7050 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
7051 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
7055 (define_insn "*movsicc_insn"
7056 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
7058 (match_operator 3 "arm_comparison_operator"
7059 [(match_operand 4 "cc_register" "") (const_int 0)])
7060 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
7061 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
7068 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
7069 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
7070 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
7071 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
7072 [(set_attr "length" "4,4,4,4,8,8,8,8")
7073 (set_attr "conds" "use")]
7076 (define_insn "*movsfcc_soft_insn"
7077 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
7078 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
7079 [(match_operand 4 "cc_register" "") (const_int 0)])
7080 (match_operand:SF 1 "s_register_operand" "0,r")
7081 (match_operand:SF 2 "s_register_operand" "r,0")))]
7082 "TARGET_ARM && TARGET_SOFT_FLOAT"
7086 [(set_attr "conds" "use")]
7090 ;; Jump and linkage insns
7092 (define_expand "jump"
7094 (label_ref (match_operand 0 "" "")))]
7099 (define_insn "*arm_jump"
7101 (label_ref (match_operand 0 "" "")))]
7105 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
7107 arm_ccfsm_state += 2;
7110 return \"b%?\\t%l0\";
7113 [(set_attr "predicable" "yes")]
7116 (define_insn "*thumb_jump"
7118 (label_ref (match_operand 0 "" "")))]
7121 if (get_attr_length (insn) == 2)
7123 return \"bl\\t%l0\\t%@ far jump\";
7125 [(set (attr "far_jump")
7127 (eq_attr "length" "4")
7128 (const_string "yes")
7129 (const_string "no")))
7130 (set (attr "length")
7132 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
7133 (le (minus (match_dup 0) (pc)) (const_int 2044)))
7138 (define_expand "call"
7139 [(parallel [(call (match_operand 0 "memory_operand" "")
7140 (match_operand 1 "general_operand" ""))
7141 (use (match_operand 2 "" ""))
7142 (clobber (reg:SI LR_REGNUM))])]
7148 /* In an untyped call, we can get NULL for operand 2. */
7149 if (operands[2] == NULL_RTX)
7150 operands[2] = const0_rtx;
7152 /* This is to decide if we should generate indirect calls by loading the
7153 32 bit address of the callee into a register before performing the
7154 branch and link. operand[2] encodes the long_call/short_call
7155 attribute of the function being called. This attribute is set whenever
7156 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7157 is used, and the short_call attribute can also be set if function is
7158 declared as static or if it has already been defined in the current
7159 compilation unit. See arm.c and arm.h for info about this. The third
7160 parameter to arm_is_longcall_p is used to tell it which pattern
7162 callee = XEXP (operands[0], 0);
7164 if (GET_CODE (callee) != REG
7165 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7166 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7170 (define_insn "*call_reg"
7171 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7172 (match_operand 1 "" ""))
7173 (use (match_operand 2 "" ""))
7174 (clobber (reg:SI LR_REGNUM))]
7177 return output_call (operands);
7179 ;; length is worst case, normally it is only two
7180 [(set_attr "length" "12")
7181 (set_attr "type" "call")]
7184 (define_insn "*call_mem"
7185 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7186 (match_operand 1 "" ""))
7187 (use (match_operand 2 "" ""))
7188 (clobber (reg:SI LR_REGNUM))]
7191 return output_call_mem (operands);
7193 [(set_attr "length" "12")
7194 (set_attr "type" "call")]
7197 (define_insn "*call_indirect"
7198 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7199 (match_operand 1 "" ""))
7200 (use (match_operand 2 "" ""))
7201 (clobber (reg:SI LR_REGNUM))]
7205 if (TARGET_CALLER_INTERWORKING)
7206 return \"bl\\t%__interwork_call_via_%0\";
7208 return \"bl\\t%__call_via_%0\";
7210 [(set_attr "type" "call")]
7213 (define_insn "*call_value_indirect"
7214 [(set (match_operand 0 "" "")
7215 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7216 (match_operand 2 "" "")))
7217 (use (match_operand 3 "" ""))
7218 (clobber (reg:SI LR_REGNUM))]
7222 if (TARGET_CALLER_INTERWORKING)
7223 return \"bl\\t%__interwork_call_via_%1\";
7225 return \"bl\\t%__call_via_%1\";
7227 [(set_attr "type" "call")]
7230 (define_expand "call_value"
7231 [(parallel [(set (match_operand 0 "" "")
7232 (call (match_operand 1 "memory_operand" "")
7233 (match_operand 2 "general_operand" "")))
7234 (use (match_operand 3 "" ""))
7235 (clobber (reg:SI LR_REGNUM))])]
7239 rtx callee = XEXP (operands[1], 0);
7241 /* In an untyped call, we can get NULL for operand 2. */
7242 if (operands[3] == 0)
7243 operands[3] = const0_rtx;
7245 /* See the comment in define_expand \"call\". */
7246 if (GET_CODE (callee) != REG
7247 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7248 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7252 (define_insn "*call_value_reg"
7253 [(set (match_operand 0 "" "")
7254 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7255 (match_operand 2 "" "")))
7256 (use (match_operand 3 "" ""))
7257 (clobber (reg:SI LR_REGNUM))]
7260 return output_call (&operands[1]);
7262 [(set_attr "length" "12")
7263 (set_attr "type" "call")]
7266 (define_insn "*call_value_mem"
7267 [(set (match_operand 0 "" "")
7268 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7269 (match_operand 2 "" "")))
7270 (use (match_operand 3 "" ""))
7271 (clobber (reg:SI LR_REGNUM))]
7272 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7274 return output_call_mem (&operands[1]);
7276 [(set_attr "length" "12")
7277 (set_attr "type" "call")]
7280 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7281 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7283 (define_insn "*call_symbol"
7284 [(call (mem:SI (match_operand:SI 0 "" ""))
7285 (match_operand 1 "" ""))
7286 (use (match_operand 2 "" ""))
7287 (clobber (reg:SI LR_REGNUM))]
7289 && (GET_CODE (operands[0]) == SYMBOL_REF)
7290 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7293 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7295 [(set_attr "type" "call")]
7298 (define_insn "*call_value_symbol"
7299 [(set (match_operand 0 "s_register_operand" "")
7300 (call (mem:SI (match_operand:SI 1 "" ""))
7301 (match_operand:SI 2 "" "")))
7302 (use (match_operand 3 "" ""))
7303 (clobber (reg:SI LR_REGNUM))]
7305 && (GET_CODE (operands[1]) == SYMBOL_REF)
7306 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7309 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7311 [(set_attr "type" "call")]
7314 (define_insn "*call_insn"
7315 [(call (mem:SI (match_operand:SI 0 "" ""))
7316 (match_operand:SI 1 "" ""))
7317 (use (match_operand 2 "" ""))
7318 (clobber (reg:SI LR_REGNUM))]
7320 && GET_CODE (operands[0]) == SYMBOL_REF
7321 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7323 [(set_attr "length" "4")
7324 (set_attr "type" "call")]
7327 (define_insn "*call_value_insn"
7328 [(set (match_operand 0 "register_operand" "")
7329 (call (mem:SI (match_operand 1 "" ""))
7330 (match_operand 2 "" "")))
7331 (use (match_operand 3 "" ""))
7332 (clobber (reg:SI LR_REGNUM))]
7334 && GET_CODE (operands[1]) == SYMBOL_REF
7335 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7337 [(set_attr "length" "4")
7338 (set_attr "type" "call")]
7341 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7342 (define_expand "sibcall"
7343 [(parallel [(call (match_operand 0 "memory_operand" "")
7344 (match_operand 1 "general_operand" ""))
7346 (use (match_operand 2 "" ""))])]
7350 if (operands[2] == NULL_RTX)
7351 operands[2] = const0_rtx;
7355 (define_expand "sibcall_value"
7356 [(parallel [(set (match_operand 0 "register_operand" "")
7357 (call (match_operand 1 "memory_operand" "")
7358 (match_operand 2 "general_operand" "")))
7360 (use (match_operand 3 "" ""))])]
7364 if (operands[3] == NULL_RTX)
7365 operands[3] = const0_rtx;
7369 (define_insn "*sibcall_insn"
7370 [(call (mem:SI (match_operand:SI 0 "" "X"))
7371 (match_operand 1 "" ""))
7373 (use (match_operand 2 "" ""))]
7374 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7376 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7378 [(set_attr "type" "call")]
7381 (define_insn "*sibcall_value_insn"
7382 [(set (match_operand 0 "s_register_operand" "")
7383 (call (mem:SI (match_operand:SI 1 "" "X"))
7384 (match_operand 2 "" "")))
7386 (use (match_operand 3 "" ""))]
7387 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7389 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7391 [(set_attr "type" "call")]
7394 ;; Often the return insn will be the same as loading from memory, so set attr
7395 (define_insn "return"
7397 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7400 if (arm_ccfsm_state == 2)
7402 arm_ccfsm_state += 2;
7405 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7407 [(set_attr "type" "load")
7408 (set_attr "length" "12")
7409 (set_attr "predicable" "yes")]
7412 (define_insn "*cond_return"
7414 (if_then_else (match_operator 0 "arm_comparison_operator"
7415 [(match_operand 1 "cc_register" "") (const_int 0)])
7418 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7421 if (arm_ccfsm_state == 2)
7423 arm_ccfsm_state += 2;
7426 return output_return_instruction (operands[0], TRUE, FALSE);
7428 [(set_attr "conds" "use")
7429 (set_attr "length" "12")
7430 (set_attr "type" "load")]
7433 (define_insn "*cond_return_inverted"
7435 (if_then_else (match_operator 0 "arm_comparison_operator"
7436 [(match_operand 1 "cc_register" "") (const_int 0)])
7439 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7442 if (arm_ccfsm_state == 2)
7444 arm_ccfsm_state += 2;
7447 return output_return_instruction (operands[0], TRUE, TRUE);
7449 [(set_attr "conds" "use")
7450 (set_attr "type" "load")]
7453 ;; Generate a sequence of instructions to determine if the processor is
7454 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7457 (define_expand "return_addr_mask"
7459 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7461 (set (match_operand:SI 0 "s_register_operand" "")
7462 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7464 (const_int 67108860)))] ; 0x03fffffc
7467 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7470 (define_insn "*check_arch2"
7471 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7472 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7475 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7476 [(set_attr "length" "8")
7477 (set_attr "conds" "set")]
7480 ;; Call subroutine returning any type.
7482 (define_expand "untyped_call"
7483 [(parallel [(call (match_operand 0 "" "")
7485 (match_operand 1 "" "")
7486 (match_operand 2 "" "")])]
7492 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7494 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7496 rtx set = XVECEXP (operands[2], 0, i);
7498 emit_move_insn (SET_DEST (set), SET_SRC (set));
7501 /* The optimizer does not know that the call sets the function value
7502 registers we stored in the result block. We avoid problems by
7503 claiming that all hard registers are used and clobbered at this
7505 emit_insn (gen_blockage ());
7511 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7512 ;; all of memory. This blocks insns from being moved across this point.
7514 (define_insn "blockage"
7515 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7518 [(set_attr "length" "0")
7519 (set_attr "type" "block")]
7522 (define_expand "casesi"
7523 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7524 (match_operand:SI 1 "const_int_operand" "") ; lower bound
7525 (match_operand:SI 2 "const_int_operand" "") ; total range
7526 (match_operand:SI 3 "" "") ; table label
7527 (match_operand:SI 4 "" "")] ; Out of range label
7532 if (operands[1] != const0_rtx)
7534 reg = gen_reg_rtx (SImode);
7536 emit_insn (gen_addsi3 (reg, operands[0],
7537 GEN_INT (-INTVAL (operands[1]))));
7541 if (!const_ok_for_arm (INTVAL (operands[2])))
7542 operands[2] = force_reg (SImode, operands[2]);
7544 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7550 ;; The USE in this pattern is needed to tell flow analysis that this is
7551 ;; a CASESI insn. It has no other purpose.
7552 (define_insn "casesi_internal"
7553 [(parallel [(set (pc)
7555 (leu (match_operand:SI 0 "s_register_operand" "r")
7556 (match_operand:SI 1 "arm_rhs_operand" "rI"))
7557 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7558 (label_ref (match_operand 2 "" ""))))
7559 (label_ref (match_operand 3 "" ""))))
7560 (clobber (reg:CC CC_REGNUM))
7561 (use (label_ref (match_dup 2)))])]
7565 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7566 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7568 [(set_attr "conds" "clob")
7569 (set_attr "length" "12")]
7572 (define_expand "indirect_jump"
7574 (match_operand:SI 0 "s_register_operand" ""))]
7579 (define_insn "*arm_indirect_jump"
7581 (match_operand:SI 0 "s_register_operand" "r"))]
7583 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7584 [(set_attr "predicable" "yes")]
7587 ;; Although not supported by the define_expand above,
7588 ;; cse/combine may generate this form.
7589 (define_insn "*load_indirect_jump"
7591 (match_operand:SI 0 "memory_operand" "m"))]
7593 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7594 [(set_attr "type" "load")
7595 (set_attr "pool_range" "4096")
7596 (set_attr "neg_pool_range" "4084")
7597 (set_attr "predicable" "yes")]
7600 (define_insn "*thumb_indirect_jump"
7602 (match_operand:SI 0 "register_operand" "l*r"))]
7605 [(set_attr "conds" "clob")
7606 (set_attr "length" "2")]
7617 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7618 return \"mov\\tr8, r8\";
7620 [(set (attr "length")
7621 (if_then_else (eq_attr "is_thumb" "yes")
7627 ;; Patterns to allow combination of arithmetic, cond code and shifts
7629 (define_insn "*arith_shiftsi"
7630 [(set (match_operand:SI 0 "s_register_operand" "=r")
7631 (match_operator:SI 1 "shiftable_operator"
7632 [(match_operator:SI 3 "shift_operator"
7633 [(match_operand:SI 4 "s_register_operand" "r")
7634 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7635 (match_operand:SI 2 "s_register_operand" "r")]))]
7637 "%i1%?\\t%0, %2, %4%S3"
7638 [(set_attr "predicable" "yes")
7639 (set_attr "shift" "4")
7644 [(set (match_operand:SI 0 "s_register_operand" "")
7645 (match_operator:SI 1 "shiftable_operator"
7646 [(match_operator:SI 2 "shiftable_operator"
7647 [(match_operator:SI 3 "shift_operator"
7648 [(match_operand:SI 4 "s_register_operand" "")
7649 (match_operand:SI 5 "reg_or_int_operand" "")])
7650 (match_operand:SI 6 "s_register_operand" "")])
7651 (match_operand:SI 7 "arm_rhs_operand" "")]))
7652 (clobber (match_operand:SI 8 "s_register_operand" ""))]
7655 (match_op_dup 2 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7658 (match_op_dup 1 [(match_dup 8) (match_dup 7)]))]
7661 (define_insn "*arith_shiftsi_compare0"
7662 [(set (reg:CC_NOOV CC_REGNUM)
7663 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7664 [(match_operator:SI 3 "shift_operator"
7665 [(match_operand:SI 4 "s_register_operand" "r")
7666 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7667 (match_operand:SI 2 "s_register_operand" "r")])
7669 (set (match_operand:SI 0 "s_register_operand" "=r")
7670 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7673 "%i1%?s\\t%0, %2, %4%S3"
7674 [(set_attr "conds" "set")
7675 (set_attr "shift" "4")
7679 (define_insn "*arith_shiftsi_compare0_scratch"
7680 [(set (reg:CC_NOOV CC_REGNUM)
7681 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7682 [(match_operator:SI 3 "shift_operator"
7683 [(match_operand:SI 4 "s_register_operand" "r")
7684 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7685 (match_operand:SI 2 "s_register_operand" "r")])
7687 (clobber (match_scratch:SI 0 "=r"))]
7689 "%i1%?s\\t%0, %2, %4%S3"
7690 [(set_attr "conds" "set")
7691 (set_attr "shift" "4")
7695 (define_insn "*sub_shiftsi"
7696 [(set (match_operand:SI 0 "s_register_operand" "=r")
7697 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7698 (match_operator:SI 2 "shift_operator"
7699 [(match_operand:SI 3 "s_register_operand" "r")
7700 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7702 "sub%?\\t%0, %1, %3%S2"
7703 [(set_attr "predicable" "yes")
7704 (set_attr "shift" "3")
7708 (define_insn "*sub_shiftsi_compare0"
7709 [(set (reg:CC_NOOV CC_REGNUM)
7711 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7712 (match_operator:SI 2 "shift_operator"
7713 [(match_operand:SI 3 "s_register_operand" "r")
7714 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7716 (set (match_operand:SI 0 "s_register_operand" "=r")
7717 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7720 "sub%?s\\t%0, %1, %3%S2"
7721 [(set_attr "conds" "set")
7722 (set_attr "shift" "3")
7726 (define_insn "*sub_shiftsi_compare0_scratch"
7727 [(set (reg:CC_NOOV CC_REGNUM)
7729 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7730 (match_operator:SI 2 "shift_operator"
7731 [(match_operand:SI 3 "s_register_operand" "r")
7732 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7734 (clobber (match_scratch:SI 0 "=r"))]
7736 "sub%?s\\t%0, %1, %3%S2"
7737 [(set_attr "conds" "set")
7738 (set_attr "shift" "3")
7744 (define_insn "*and_scc"
7745 [(set (match_operand:SI 0 "s_register_operand" "=r")
7746 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7747 [(match_operand 3 "cc_register" "") (const_int 0)])
7748 (match_operand:SI 2 "s_register_operand" "r")))]
7750 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7751 [(set_attr "conds" "use")
7752 (set_attr "length" "8")]
7755 (define_insn "*ior_scc"
7756 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7757 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7758 [(match_operand 3 "cc_register" "") (const_int 0)])
7759 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7763 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7764 [(set_attr "conds" "use")
7765 (set_attr "length" "4,8")]
7768 (define_insn "*compare_scc"
7769 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7770 (match_operator:SI 1 "arm_comparison_operator"
7771 [(match_operand:SI 2 "s_register_operand" "r,r")
7772 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7773 (clobber (reg:CC CC_REGNUM))]
7776 if (operands[3] == const0_rtx)
7778 if (GET_CODE (operands[1]) == LT)
7779 return \"mov\\t%0, %2, lsr #31\";
7781 if (GET_CODE (operands[1]) == GE)
7782 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7784 if (GET_CODE (operands[1]) == EQ)
7785 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
7788 if (GET_CODE (operands[1]) == NE)
7790 if (which_alternative == 1)
7791 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7792 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7794 if (which_alternative == 1)
7795 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7797 output_asm_insn (\"cmp\\t%2, %3\", operands);
7798 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7800 [(set_attr "conds" "clob")
7801 (set_attr "length" "12")]
7804 (define_insn "*cond_move"
7805 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7806 (if_then_else:SI (match_operator 3 "equality_operator"
7807 [(match_operator 4 "arm_comparison_operator"
7808 [(match_operand 5 "cc_register" "") (const_int 0)])
7810 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7811 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7814 if (GET_CODE (operands[3]) == NE)
7816 if (which_alternative != 1)
7817 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7818 if (which_alternative != 0)
7819 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7822 if (which_alternative != 0)
7823 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7824 if (which_alternative != 1)
7825 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7828 [(set_attr "conds" "use")
7829 (set_attr "length" "4,4,8")]
7832 (define_insn "*cond_arith"
7833 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7834 (match_operator:SI 5 "shiftable_operator"
7835 [(match_operator:SI 4 "arm_comparison_operator"
7836 [(match_operand:SI 2 "s_register_operand" "r,r")
7837 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7838 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7839 (clobber (reg:CC CC_REGNUM))]
7842 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7843 return \"%i5\\t%0, %1, %2, lsr #31\";
7845 output_asm_insn (\"cmp\\t%2, %3\", operands);
7846 if (GET_CODE (operands[5]) == AND)
7847 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7848 else if (GET_CODE (operands[5]) == MINUS)
7849 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7850 else if (which_alternative != 0)
7851 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7852 return \"%i5%d4\\t%0, %1, #1\";
7854 [(set_attr "conds" "clob")
7855 (set_attr "length" "12")]
7858 (define_insn "*cond_sub"
7859 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7860 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7861 (match_operator:SI 4 "arm_comparison_operator"
7862 [(match_operand:SI 2 "s_register_operand" "r,r")
7863 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7864 (clobber (reg:CC CC_REGNUM))]
7867 output_asm_insn (\"cmp\\t%2, %3\", operands);
7868 if (which_alternative != 0)
7869 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7870 return \"sub%d4\\t%0, %1, #1\";
7872 [(set_attr "conds" "clob")
7873 (set_attr "length" "8,12")]
7876 (define_insn "*cmp_ite0"
7877 [(set (match_operand 6 "dominant_cc_register" "")
7880 (match_operator 4 "arm_comparison_operator"
7881 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7882 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7883 (match_operator:SI 5 "arm_comparison_operator"
7884 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7885 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7891 static const char * const opcodes[4][2] =
7893 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7894 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7895 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7896 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7897 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7898 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7899 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7900 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7903 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7905 return opcodes[which_alternative][swap];
7907 [(set_attr "conds" "set")
7908 (set_attr "length" "8")]
7911 (define_insn "*cmp_ite1"
7912 [(set (match_operand 6 "dominant_cc_register" "")
7915 (match_operator 4 "arm_comparison_operator"
7916 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7917 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7918 (match_operator:SI 5 "arm_comparison_operator"
7919 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7920 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7926 static const char * const opcodes[4][2] =
7928 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7929 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7930 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7931 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7932 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7933 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7934 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7935 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7938 comparison_dominates_p (GET_CODE (operands[5]),
7939 reverse_condition (GET_CODE (operands[4])));
7941 return opcodes[which_alternative][swap];
7943 [(set_attr "conds" "set")
7944 (set_attr "length" "8")]
7947 (define_insn "*cmp_and"
7948 [(set (match_operand 6 "dominant_cc_register" "")
7951 (match_operator 4 "arm_comparison_operator"
7952 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7953 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7954 (match_operator:SI 5 "arm_comparison_operator"
7955 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7956 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7961 static const char *const opcodes[4][2] =
7963 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7964 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7965 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7966 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7967 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7968 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7969 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7970 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7973 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7975 return opcodes[which_alternative][swap];
7977 [(set_attr "conds" "set")
7978 (set_attr "predicable" "no")
7979 (set_attr "length" "8")]
7982 (define_insn "*cmp_ior"
7983 [(set (match_operand 6 "dominant_cc_register" "")
7986 (match_operator 4 "arm_comparison_operator"
7987 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7988 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7989 (match_operator:SI 5 "arm_comparison_operator"
7990 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7991 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7996 static const char *const opcodes[4][2] =
7998 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7999 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
8000 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
8001 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
8002 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
8003 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
8004 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
8005 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
8008 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
8010 return opcodes[which_alternative][swap];
8013 [(set_attr "conds" "set")
8014 (set_attr "length" "8")]
8017 (define_insn_and_split "*ior_scc_scc"
8018 [(set (match_operand:SI 0 "s_register_operand" "=r")
8019 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8020 [(match_operand:SI 1 "s_register_operand" "r")
8021 (match_operand:SI 2 "arm_add_operand" "rIL")])
8022 (match_operator:SI 6 "arm_comparison_operator"
8023 [(match_operand:SI 4 "s_register_operand" "r")
8024 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8025 (clobber (reg:CC CC_REGNUM))]
8027 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
8030 "TARGET_ARM && reload_completed"
8034 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8035 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8037 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8039 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8042 [(set_attr "conds" "clob")
8043 (set_attr "length" "16")])
8045 ; If the above pattern is followed by a CMP insn, then the compare is
8046 ; redundant, since we can rework the conditional instruction that follows.
8047 (define_insn_and_split "*ior_scc_scc_cmp"
8048 [(set (match_operand 0 "dominant_cc_register" "")
8049 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
8050 [(match_operand:SI 1 "s_register_operand" "r")
8051 (match_operand:SI 2 "arm_add_operand" "rIL")])
8052 (match_operator:SI 6 "arm_comparison_operator"
8053 [(match_operand:SI 4 "s_register_operand" "r")
8054 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8056 (set (match_operand:SI 7 "s_register_operand" "=r")
8057 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8058 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8061 "TARGET_ARM && reload_completed"
8065 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8066 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8068 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8070 [(set_attr "conds" "set")
8071 (set_attr "length" "16")])
8073 (define_insn_and_split "*and_scc_scc"
8074 [(set (match_operand:SI 0 "s_register_operand" "=r")
8075 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8076 [(match_operand:SI 1 "s_register_operand" "r")
8077 (match_operand:SI 2 "arm_add_operand" "rIL")])
8078 (match_operator:SI 6 "arm_comparison_operator"
8079 [(match_operand:SI 4 "s_register_operand" "r")
8080 (match_operand:SI 5 "arm_add_operand" "rIL")])))
8081 (clobber (reg:CC CC_REGNUM))]
8083 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8086 "TARGET_ARM && reload_completed
8087 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8092 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8093 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8095 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
8097 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
8100 [(set_attr "conds" "clob")
8101 (set_attr "length" "16")])
8103 ; If the above pattern is followed by a CMP insn, then the compare is
8104 ; redundant, since we can rework the conditional instruction that follows.
8105 (define_insn_and_split "*and_scc_scc_cmp"
8106 [(set (match_operand 0 "dominant_cc_register" "")
8107 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
8108 [(match_operand:SI 1 "s_register_operand" "r")
8109 (match_operand:SI 2 "arm_add_operand" "rIL")])
8110 (match_operator:SI 6 "arm_comparison_operator"
8111 [(match_operand:SI 4 "s_register_operand" "r")
8112 (match_operand:SI 5 "arm_add_operand" "rIL")]))
8114 (set (match_operand:SI 7 "s_register_operand" "=r")
8115 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8116 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
8119 "TARGET_ARM && reload_completed"
8123 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
8124 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
8126 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
8128 [(set_attr "conds" "set")
8129 (set_attr "length" "16")])
8131 ;; If there is no dominance in the comparison, then we can still save an
8132 ;; instruction in the AND case, since we can know that the second compare
8133 ;; need only zero the value if false (if true, then the value is already
8135 (define_insn_and_split "*and_scc_scc_nodom"
8136 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
8137 (and:SI (match_operator:SI 3 "arm_comparison_operator"
8138 [(match_operand:SI 1 "s_register_operand" "r,r,0")
8139 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
8140 (match_operator:SI 6 "arm_comparison_operator"
8141 [(match_operand:SI 4 "s_register_operand" "r,r,r")
8142 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
8143 (clobber (reg:CC CC_REGNUM))]
8145 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
8148 "TARGET_ARM && reload_completed"
8149 [(parallel [(set (match_dup 0)
8150 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
8151 (clobber (reg:CC CC_REGNUM))])
8152 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
8154 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
8157 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
8158 operands[4], operands[5]),
8160 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
8162 [(set_attr "conds" "clob")
8163 (set_attr "length" "20")])
8166 [(set (reg:CC_NOOV CC_REGNUM)
8167 (compare:CC_NOOV (ior:SI
8168 (and:SI (match_operand:SI 0 "s_register_operand" "")
8170 (match_operator:SI 1 "comparison_operator"
8171 [(match_operand:SI 2 "s_register_operand" "")
8172 (match_operand:SI 3 "arm_add_operand" "")]))
8174 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8177 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8179 (set (reg:CC_NOOV CC_REGNUM)
8180 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8185 [(set (reg:CC_NOOV CC_REGNUM)
8186 (compare:CC_NOOV (ior:SI
8187 (match_operator:SI 1 "comparison_operator"
8188 [(match_operand:SI 2 "s_register_operand" "")
8189 (match_operand:SI 3 "arm_add_operand" "")])
8190 (and:SI (match_operand:SI 0 "s_register_operand" "")
8193 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8196 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8198 (set (reg:CC_NOOV CC_REGNUM)
8199 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8203 (define_insn "*negscc"
8204 [(set (match_operand:SI 0 "s_register_operand" "=r")
8205 (neg:SI (match_operator 3 "arm_comparison_operator"
8206 [(match_operand:SI 1 "s_register_operand" "r")
8207 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8208 (clobber (reg:CC CC_REGNUM))]
8211 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8212 return \"mov\\t%0, %1, asr #31\";
8214 if (GET_CODE (operands[3]) == NE)
8215 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8217 if (GET_CODE (operands[3]) == GT)
8218 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8220 output_asm_insn (\"cmp\\t%1, %2\", operands);
8221 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8222 return \"mvn%d3\\t%0, #0\";
8224 [(set_attr "conds" "clob")
8225 (set_attr "length" "12")]
8228 (define_insn "movcond"
8229 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8231 (match_operator 5 "arm_comparison_operator"
8232 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8233 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8234 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8235 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8236 (clobber (reg:CC CC_REGNUM))]
8239 if (GET_CODE (operands[5]) == LT
8240 && (operands[4] == const0_rtx))
8242 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8244 if (operands[2] == const0_rtx)
8245 return \"and\\t%0, %1, %3, asr #31\";
8246 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8248 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8250 if (operands[1] == const0_rtx)
8251 return \"bic\\t%0, %2, %3, asr #31\";
8252 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8254 /* The only case that falls through to here is when both ops 1 & 2
8258 if (GET_CODE (operands[5]) == GE
8259 && (operands[4] == const0_rtx))
8261 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8263 if (operands[2] == const0_rtx)
8264 return \"bic\\t%0, %1, %3, asr #31\";
8265 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8267 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8269 if (operands[1] == const0_rtx)
8270 return \"and\\t%0, %2, %3, asr #31\";
8271 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8273 /* The only case that falls through to here is when both ops 1 & 2
8276 if (GET_CODE (operands[4]) == CONST_INT
8277 && !const_ok_for_arm (INTVAL (operands[4])))
8278 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8280 output_asm_insn (\"cmp\\t%3, %4\", operands);
8281 if (which_alternative != 0)
8282 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8283 if (which_alternative != 1)
8284 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8287 [(set_attr "conds" "clob")
8288 (set_attr "length" "8,8,12")]
8291 (define_insn "*ifcompare_plus_move"
8292 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8293 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8294 [(match_operand:SI 4 "s_register_operand" "r,r")
8295 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8297 (match_operand:SI 2 "s_register_operand" "r,r")
8298 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8299 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8300 (clobber (reg:CC CC_REGNUM))]
8303 [(set_attr "conds" "clob")
8304 (set_attr "length" "8,12")]
8307 (define_insn "*if_plus_move"
8308 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8310 (match_operator 4 "arm_comparison_operator"
8311 [(match_operand 5 "cc_register" "") (const_int 0)])
8313 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8314 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8315 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8319 sub%d4\\t%0, %2, #%n3
8320 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8321 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8322 [(set_attr "conds" "use")
8323 (set_attr "length" "4,4,8,8")
8324 (set_attr "type" "*,*,*,*")]
8327 (define_insn "*ifcompare_move_plus"
8328 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8329 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8330 [(match_operand:SI 4 "s_register_operand" "r,r")
8331 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8332 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8334 (match_operand:SI 2 "s_register_operand" "r,r")
8335 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8336 (clobber (reg:CC CC_REGNUM))]
8339 [(set_attr "conds" "clob")
8340 (set_attr "length" "8,12")]
8343 (define_insn "*if_move_plus"
8344 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8346 (match_operator 4 "arm_comparison_operator"
8347 [(match_operand 5 "cc_register" "") (const_int 0)])
8348 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8350 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8351 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8355 sub%D4\\t%0, %2, #%n3
8356 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8357 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8358 [(set_attr "conds" "use")
8359 (set_attr "length" "4,4,8,8")
8360 (set_attr "type" "*,*,*,*")]
8363 (define_insn "*ifcompare_arith_arith"
8364 [(set (match_operand:SI 0 "s_register_operand" "=r")
8365 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8366 [(match_operand:SI 5 "s_register_operand" "r")
8367 (match_operand:SI 6 "arm_add_operand" "rIL")])
8368 (match_operator:SI 8 "shiftable_operator"
8369 [(match_operand:SI 1 "s_register_operand" "r")
8370 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8371 (match_operator:SI 7 "shiftable_operator"
8372 [(match_operand:SI 3 "s_register_operand" "r")
8373 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8374 (clobber (reg:CC CC_REGNUM))]
8377 [(set_attr "conds" "clob")
8378 (set_attr "length" "12")]
8381 (define_insn "*if_arith_arith"
8382 [(set (match_operand:SI 0 "s_register_operand" "=r")
8383 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8384 [(match_operand 8 "cc_register" "") (const_int 0)])
8385 (match_operator:SI 6 "shiftable_operator"
8386 [(match_operand:SI 1 "s_register_operand" "r")
8387 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8388 (match_operator:SI 7 "shiftable_operator"
8389 [(match_operand:SI 3 "s_register_operand" "r")
8390 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8392 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8393 [(set_attr "conds" "use")
8394 (set_attr "length" "8")]
8397 (define_insn "*ifcompare_arith_move"
8398 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8399 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8400 [(match_operand:SI 2 "s_register_operand" "r,r")
8401 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8402 (match_operator:SI 7 "shiftable_operator"
8403 [(match_operand:SI 4 "s_register_operand" "r,r")
8404 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8405 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8406 (clobber (reg:CC CC_REGNUM))]
8409 /* If we have an operation where (op x 0) is the identity operation and
8410 the conditional operator is LT or GE and we are comparing against zero and
8411 everything is in registers then we can do this in two instructions */
8412 if (operands[3] == const0_rtx
8413 && GET_CODE (operands[7]) != AND
8414 && GET_CODE (operands[5]) == REG
8415 && GET_CODE (operands[1]) == REG
8416 && REGNO (operands[1]) == REGNO (operands[4])
8417 && REGNO (operands[4]) != REGNO (operands[0]))
8419 if (GET_CODE (operands[6]) == LT)
8420 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8421 else if (GET_CODE (operands[6]) == GE)
8422 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8424 if (GET_CODE (operands[3]) == CONST_INT
8425 && !const_ok_for_arm (INTVAL (operands[3])))
8426 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8428 output_asm_insn (\"cmp\\t%2, %3\", operands);
8429 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8430 if (which_alternative != 0)
8431 return \"mov%D6\\t%0, %1\";
8434 [(set_attr "conds" "clob")
8435 (set_attr "length" "8,12")]
8438 (define_insn "*if_arith_move"
8439 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8440 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8441 [(match_operand 6 "cc_register" "") (const_int 0)])
8442 (match_operator:SI 5 "shiftable_operator"
8443 [(match_operand:SI 2 "s_register_operand" "r,r")
8444 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8445 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8449 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8450 [(set_attr "conds" "use")
8451 (set_attr "length" "4,8")
8452 (set_attr "type" "*,*")]
8455 (define_insn "*ifcompare_move_arith"
8456 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8457 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8458 [(match_operand:SI 4 "s_register_operand" "r,r")
8459 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8460 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8461 (match_operator:SI 7 "shiftable_operator"
8462 [(match_operand:SI 2 "s_register_operand" "r,r")
8463 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8464 (clobber (reg:CC CC_REGNUM))]
8467 /* If we have an operation where (op x 0) is the identity operation and
8468 the conditional operator is LT or GE and we are comparing against zero and
8469 everything is in registers then we can do this in two instructions */
8470 if (operands[5] == const0_rtx
8471 && GET_CODE (operands[7]) != AND
8472 && GET_CODE (operands[3]) == REG
8473 && GET_CODE (operands[1]) == REG
8474 && REGNO (operands[1]) == REGNO (operands[2])
8475 && REGNO (operands[2]) != REGNO (operands[0]))
8477 if (GET_CODE (operands[6]) == GE)
8478 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8479 else if (GET_CODE (operands[6]) == LT)
8480 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8483 if (GET_CODE (operands[5]) == CONST_INT
8484 && !const_ok_for_arm (INTVAL (operands[5])))
8485 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8487 output_asm_insn (\"cmp\\t%4, %5\", operands);
8489 if (which_alternative != 0)
8490 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8491 return \"%I7%D6\\t%0, %2, %3\";
8493 [(set_attr "conds" "clob")
8494 (set_attr "length" "8,12")]
8497 (define_insn "*if_move_arith"
8498 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8500 (match_operator 4 "arm_comparison_operator"
8501 [(match_operand 6 "cc_register" "") (const_int 0)])
8502 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8503 (match_operator:SI 5 "shiftable_operator"
8504 [(match_operand:SI 2 "s_register_operand" "r,r")
8505 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8509 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8510 [(set_attr "conds" "use")
8511 (set_attr "length" "4,8")
8512 (set_attr "type" "*,*")]
8515 (define_insn "*ifcompare_move_not"
8516 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8518 (match_operator 5 "arm_comparison_operator"
8519 [(match_operand:SI 3 "s_register_operand" "r,r")
8520 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8521 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8523 (match_operand:SI 2 "s_register_operand" "r,r"))))
8524 (clobber (reg:CC CC_REGNUM))]
8527 [(set_attr "conds" "clob")
8528 (set_attr "length" "8,12")]
8531 (define_insn "*if_move_not"
8532 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8534 (match_operator 4 "arm_comparison_operator"
8535 [(match_operand 3 "cc_register" "") (const_int 0)])
8536 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8537 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8541 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8542 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8543 [(set_attr "conds" "use")
8544 (set_attr "length" "4,8,8")]
8547 (define_insn "*ifcompare_not_move"
8548 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8550 (match_operator 5 "arm_comparison_operator"
8551 [(match_operand:SI 3 "s_register_operand" "r,r")
8552 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8554 (match_operand:SI 2 "s_register_operand" "r,r"))
8555 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8556 (clobber (reg:CC CC_REGNUM))]
8559 [(set_attr "conds" "clob")
8560 (set_attr "length" "8,12")]
8563 (define_insn "*if_not_move"
8564 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8566 (match_operator 4 "arm_comparison_operator"
8567 [(match_operand 3 "cc_register" "") (const_int 0)])
8568 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8569 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8573 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8574 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8575 [(set_attr "conds" "use")
8576 (set_attr "length" "4,8,8")]
8579 (define_insn "*ifcompare_shift_move"
8580 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8582 (match_operator 6 "arm_comparison_operator"
8583 [(match_operand:SI 4 "s_register_operand" "r,r")
8584 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8585 (match_operator:SI 7 "shift_operator"
8586 [(match_operand:SI 2 "s_register_operand" "r,r")
8587 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8588 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8589 (clobber (reg:CC CC_REGNUM))]
8592 [(set_attr "conds" "clob")
8593 (set_attr "length" "8,12")]
8596 (define_insn "*if_shift_move"
8597 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8599 (match_operator 5 "arm_comparison_operator"
8600 [(match_operand 6 "cc_register" "") (const_int 0)])
8601 (match_operator:SI 4 "shift_operator"
8602 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8603 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8604 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8608 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8609 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8610 [(set_attr "conds" "use")
8611 (set_attr "shift" "2")
8612 (set_attr "length" "4,8,8")]
8615 (define_insn "*ifcompare_move_shift"
8616 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8618 (match_operator 6 "arm_comparison_operator"
8619 [(match_operand:SI 4 "s_register_operand" "r,r")
8620 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8621 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8622 (match_operator:SI 7 "shift_operator"
8623 [(match_operand:SI 2 "s_register_operand" "r,r")
8624 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8625 (clobber (reg:CC CC_REGNUM))]
8628 [(set_attr "conds" "clob")
8629 (set_attr "length" "8,12")]
8632 (define_insn "*if_move_shift"
8633 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8635 (match_operator 5 "arm_comparison_operator"
8636 [(match_operand 6 "cc_register" "") (const_int 0)])
8637 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8638 (match_operator:SI 4 "shift_operator"
8639 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8640 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8644 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8645 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8646 [(set_attr "conds" "use")
8647 (set_attr "shift" "2")
8648 (set_attr "length" "4,8,8")]
8651 (define_insn "*ifcompare_shift_shift"
8652 [(set (match_operand:SI 0 "s_register_operand" "=r")
8654 (match_operator 7 "arm_comparison_operator"
8655 [(match_operand:SI 5 "s_register_operand" "r")
8656 (match_operand:SI 6 "arm_add_operand" "rIL")])
8657 (match_operator:SI 8 "shift_operator"
8658 [(match_operand:SI 1 "s_register_operand" "r")
8659 (match_operand:SI 2 "arm_rhs_operand" "rM")])
8660 (match_operator:SI 9 "shift_operator"
8661 [(match_operand:SI 3 "s_register_operand" "r")
8662 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8663 (clobber (reg:CC CC_REGNUM))]
8666 [(set_attr "conds" "clob")
8667 (set_attr "length" "12")]
8670 (define_insn "*if_shift_shift"
8671 [(set (match_operand:SI 0 "s_register_operand" "=r")
8673 (match_operator 5 "arm_comparison_operator"
8674 [(match_operand 8 "cc_register" "") (const_int 0)])
8675 (match_operator:SI 6 "shift_operator"
8676 [(match_operand:SI 1 "s_register_operand" "r")
8677 (match_operand:SI 2 "arm_rhs_operand" "rM")])
8678 (match_operator:SI 7 "shift_operator"
8679 [(match_operand:SI 3 "s_register_operand" "r")
8680 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8682 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8683 [(set_attr "conds" "use")
8684 (set_attr "shift" "1")
8685 (set_attr "length" "8")]
8688 (define_insn "*ifcompare_not_arith"
8689 [(set (match_operand:SI 0 "s_register_operand" "=r")
8691 (match_operator 6 "arm_comparison_operator"
8692 [(match_operand:SI 4 "s_register_operand" "r")
8693 (match_operand:SI 5 "arm_add_operand" "rIL")])
8694 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8695 (match_operator:SI 7 "shiftable_operator"
8696 [(match_operand:SI 2 "s_register_operand" "r")
8697 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8698 (clobber (reg:CC CC_REGNUM))]
8701 [(set_attr "conds" "clob")
8702 (set_attr "length" "12")]
8705 (define_insn "*if_not_arith"
8706 [(set (match_operand:SI 0 "s_register_operand" "=r")
8708 (match_operator 5 "arm_comparison_operator"
8709 [(match_operand 4 "cc_register" "") (const_int 0)])
8710 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8711 (match_operator:SI 6 "shiftable_operator"
8712 [(match_operand:SI 2 "s_register_operand" "r")
8713 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8715 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8716 [(set_attr "conds" "use")
8717 (set_attr "length" "8")]
8720 (define_insn "*ifcompare_arith_not"
8721 [(set (match_operand:SI 0 "s_register_operand" "=r")
8723 (match_operator 6 "arm_comparison_operator"
8724 [(match_operand:SI 4 "s_register_operand" "r")
8725 (match_operand:SI 5 "arm_add_operand" "rIL")])
8726 (match_operator:SI 7 "shiftable_operator"
8727 [(match_operand:SI 2 "s_register_operand" "r")
8728 (match_operand:SI 3 "arm_rhs_operand" "rI")])
8729 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8730 (clobber (reg:CC CC_REGNUM))]
8733 [(set_attr "conds" "clob")
8734 (set_attr "length" "12")]
8737 (define_insn "*if_arith_not"
8738 [(set (match_operand:SI 0 "s_register_operand" "=r")
8740 (match_operator 5 "arm_comparison_operator"
8741 [(match_operand 4 "cc_register" "") (const_int 0)])
8742 (match_operator:SI 6 "shiftable_operator"
8743 [(match_operand:SI 2 "s_register_operand" "r")
8744 (match_operand:SI 3 "arm_rhs_operand" "rI")])
8745 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
8747 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8748 [(set_attr "conds" "use")
8749 (set_attr "length" "8")]
8752 (define_insn "*ifcompare_neg_move"
8753 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8755 (match_operator 5 "arm_comparison_operator"
8756 [(match_operand:SI 3 "s_register_operand" "r,r")
8757 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8758 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
8759 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8760 (clobber (reg:CC CC_REGNUM))]
8763 [(set_attr "conds" "clob")
8764 (set_attr "length" "8,12")]
8767 (define_insn "*if_neg_move"
8768 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8770 (match_operator 4 "arm_comparison_operator"
8771 [(match_operand 3 "cc_register" "") (const_int 0)])
8772 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8773 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8777 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8778 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8779 [(set_attr "conds" "use")
8780 (set_attr "length" "4,8,8")]
8783 (define_insn "*ifcompare_move_neg"
8784 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8786 (match_operator 5 "arm_comparison_operator"
8787 [(match_operand:SI 3 "s_register_operand" "r,r")
8788 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8789 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8790 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8791 (clobber (reg:CC CC_REGNUM))]
8794 [(set_attr "conds" "clob")
8795 (set_attr "length" "8,12")]
8798 (define_insn "*if_move_neg"
8799 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8801 (match_operator 4 "arm_comparison_operator"
8802 [(match_operand 3 "cc_register" "") (const_int 0)])
8803 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8804 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8808 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8809 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8810 [(set_attr "conds" "use")
8811 (set_attr "length" "4,8,8")]
8814 (define_insn "*arith_adjacentmem"
8815 [(set (match_operand:SI 0 "s_register_operand" "=r")
8816 (match_operator:SI 1 "shiftable_operator"
8817 [(match_operand:SI 2 "memory_operand" "m")
8818 (match_operand:SI 3 "memory_operand" "m")]))
8819 (clobber (match_scratch:SI 4 "=r"))]
8820 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8825 int val1 = 0, val2 = 0;
8827 if (REGNO (operands[0]) > REGNO (operands[4]))
8829 ldm[1] = operands[4];
8830 ldm[2] = operands[0];
8834 ldm[1] = operands[0];
8835 ldm[2] = operands[4];
8837 if (GET_CODE (XEXP (operands[2], 0)) != REG)
8838 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8839 if (GET_CODE (XEXP (operands[3], 0)) != REG)
8840 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8841 arith[0] = operands[0];
8842 arith[3] = operands[1];
8856 ldm[0] = ops[0] = operands[4];
8857 ops[1] = XEXP (XEXP (operands[2], 0), 0);
8858 ops[2] = XEXP (XEXP (operands[2], 0), 1);
8859 output_add_immediate (ops);
8861 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8863 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8867 ldm[0] = XEXP (operands[3], 0);
8869 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8871 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8875 ldm[0] = XEXP (operands[2], 0);
8877 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8879 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8881 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8884 [(set_attr "length" "12")
8885 (set_attr "predicable" "yes")
8886 (set_attr "type" "load")]
8889 ;; the arm can support extended pre-inc instructions
8891 ;; In all these cases, we use operands 0 and 1 for the register being
8892 ;; incremented because those are the operands that local-alloc will
8893 ;; tie and these are the pair most likely to be tieable (and the ones
8894 ;; that will benefit the most).
8896 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8897 ;; elimination will cause too many headaches.
8899 (define_insn "*strqi_preinc"
8900 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8901 (match_operand:SI 2 "index_operand" "rJ")))
8902 (match_operand:QI 3 "s_register_operand" "r"))
8903 (set (match_operand:SI 0 "s_register_operand" "=r")
8904 (plus:SI (match_dup 1) (match_dup 2)))]
8906 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8907 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8908 && (GET_CODE (operands[2]) != REG
8909 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8910 "str%?b\\t%3, [%0, %2]!"
8911 [(set_attr "type" "store1")
8912 (set_attr "predicable" "yes")]
8915 (define_insn "*strqi_predec"
8916 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8917 (match_operand:SI 2 "s_register_operand" "r")))
8918 (match_operand:QI 3 "s_register_operand" "r"))
8919 (set (match_operand:SI 0 "s_register_operand" "=r")
8920 (minus:SI (match_dup 1) (match_dup 2)))]
8922 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8923 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8924 && (GET_CODE (operands[2]) != REG
8925 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8926 "str%?b\\t%3, [%0, -%2]!"
8927 [(set_attr "type" "store1")
8928 (set_attr "predicable" "yes")]
8931 (define_insn "*loadqi_preinc"
8932 [(set (match_operand:QI 3 "s_register_operand" "=r")
8933 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8934 (match_operand:SI 2 "index_operand" "rJ"))))
8935 (set (match_operand:SI 0 "s_register_operand" "=r")
8936 (plus:SI (match_dup 1) (match_dup 2)))]
8938 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8939 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8940 && (GET_CODE (operands[2]) != REG
8941 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8942 "ldr%?b\\t%3, [%0, %2]!"
8943 [(set_attr "type" "load")
8944 (set_attr "predicable" "yes")]
8947 (define_insn "*loadqi_predec"
8948 [(set (match_operand:QI 3 "s_register_operand" "=r")
8949 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8950 (match_operand:SI 2 "s_register_operand" "r"))))
8951 (set (match_operand:SI 0 "s_register_operand" "=r")
8952 (minus:SI (match_dup 1) (match_dup 2)))]
8954 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8955 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8956 && (GET_CODE (operands[2]) != REG
8957 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8958 "ldr%?b\\t%3, [%0, -%2]!"
8959 [(set_attr "type" "load")
8960 (set_attr "predicable" "yes")]
8963 (define_insn "*loadqisi_preinc"
8964 [(set (match_operand:SI 3 "s_register_operand" "=r")
8966 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8967 (match_operand:SI 2 "index_operand" "rJ")))))
8968 (set (match_operand:SI 0 "s_register_operand" "=r")
8969 (plus:SI (match_dup 1) (match_dup 2)))]
8971 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8972 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8973 && (GET_CODE (operands[2]) != REG
8974 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8975 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8976 [(set_attr "type" "load")
8977 (set_attr "predicable" "yes")]
8980 (define_insn "*loadqisi_predec"
8981 [(set (match_operand:SI 3 "s_register_operand" "=r")
8983 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8984 (match_operand:SI 2 "s_register_operand" "r")))))
8985 (set (match_operand:SI 0 "s_register_operand" "=r")
8986 (minus:SI (match_dup 1) (match_dup 2)))]
8988 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8989 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8990 && (GET_CODE (operands[2]) != REG
8991 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8992 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8993 [(set_attr "type" "load")
8994 (set_attr "predicable" "yes")]
8997 (define_insn "*strsi_preinc"
8998 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8999 (match_operand:SI 2 "index_operand" "rJ")))
9000 (match_operand:SI 3 "s_register_operand" "r"))
9001 (set (match_operand:SI 0 "s_register_operand" "=r")
9002 (plus:SI (match_dup 1) (match_dup 2)))]
9004 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9005 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9006 && (GET_CODE (operands[2]) != REG
9007 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9008 "str%?\\t%3, [%0, %2]!"
9009 [(set_attr "type" "store1")
9010 (set_attr "predicable" "yes")]
9013 (define_insn "*strsi_predec"
9014 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9015 (match_operand:SI 2 "s_register_operand" "r")))
9016 (match_operand:SI 3 "s_register_operand" "r"))
9017 (set (match_operand:SI 0 "s_register_operand" "=r")
9018 (minus:SI (match_dup 1) (match_dup 2)))]
9020 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9021 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9022 && (GET_CODE (operands[2]) != REG
9023 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9024 "str%?\\t%3, [%0, -%2]!"
9025 [(set_attr "type" "store1")
9026 (set_attr "predicable" "yes")]
9029 (define_insn "*loadsi_preinc"
9030 [(set (match_operand:SI 3 "s_register_operand" "=r")
9031 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9032 (match_operand:SI 2 "index_operand" "rJ"))))
9033 (set (match_operand:SI 0 "s_register_operand" "=r")
9034 (plus:SI (match_dup 1) (match_dup 2)))]
9036 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9037 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9038 && (GET_CODE (operands[2]) != REG
9039 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9040 "ldr%?\\t%3, [%0, %2]!"
9041 [(set_attr "type" "load")
9042 (set_attr "predicable" "yes")]
9045 (define_insn "*loadsi_predec"
9046 [(set (match_operand:SI 3 "s_register_operand" "=r")
9047 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9048 (match_operand:SI 2 "s_register_operand" "r"))))
9049 (set (match_operand:SI 0 "s_register_operand" "=r")
9050 (minus:SI (match_dup 1) (match_dup 2)))]
9052 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9053 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9054 && (GET_CODE (operands[2]) != REG
9055 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9056 "ldr%?\\t%3, [%0, -%2]!"
9057 [(set_attr "type" "load")
9058 (set_attr "predicable" "yes")]
9061 (define_insn "*loadhi_preinc"
9062 [(set (match_operand:HI 3 "s_register_operand" "=r")
9063 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
9064 (match_operand:SI 2 "index_operand" "rJ"))))
9065 (set (match_operand:SI 0 "s_register_operand" "=r")
9066 (plus:SI (match_dup 1) (match_dup 2)))]
9068 && !BYTES_BIG_ENDIAN
9069 && !TARGET_MMU_TRAPS
9071 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9072 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9073 && (GET_CODE (operands[2]) != REG
9074 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9075 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
9076 [(set_attr "type" "load")
9077 (set_attr "predicable" "yes")]
9080 (define_insn "*loadhi_predec"
9081 [(set (match_operand:HI 3 "s_register_operand" "=r")
9082 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9083 (match_operand:SI 2 "s_register_operand" "r"))))
9084 (set (match_operand:SI 0 "s_register_operand" "=r")
9085 (minus:SI (match_dup 1) (match_dup 2)))]
9087 && !BYTES_BIG_ENDIAN
9088 && !TARGET_MMU_TRAPS
9090 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9091 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9092 && (GET_CODE (operands[2]) != REG
9093 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
9094 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
9095 [(set_attr "type" "load")
9096 (set_attr "predicable" "yes")]
9099 (define_insn "*strqi_shiftpreinc"
9100 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9101 [(match_operand:SI 3 "s_register_operand" "r")
9102 (match_operand:SI 4 "const_shift_operand" "n")])
9103 (match_operand:SI 1 "s_register_operand" "0")))
9104 (match_operand:QI 5 "s_register_operand" "r"))
9105 (set (match_operand:SI 0 "s_register_operand" "=r")
9106 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9109 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9110 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9111 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9112 "str%?b\\t%5, [%0, %3%S2]!"
9113 [(set_attr "type" "store1")
9114 (set_attr "predicable" "yes")]
9117 (define_insn "*strqi_shiftpredec"
9118 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9119 (match_operator:SI 2 "shift_operator"
9120 [(match_operand:SI 3 "s_register_operand" "r")
9121 (match_operand:SI 4 "const_shift_operand" "n")])))
9122 (match_operand:QI 5 "s_register_operand" "r"))
9123 (set (match_operand:SI 0 "s_register_operand" "=r")
9124 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9127 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9128 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9129 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9130 "str%?b\\t%5, [%0, -%3%S2]!"
9131 [(set_attr "type" "store1")
9132 (set_attr "predicable" "yes")]
9135 (define_insn "*loadqi_shiftpreinc"
9136 [(set (match_operand:QI 5 "s_register_operand" "=r")
9137 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
9138 [(match_operand:SI 3 "s_register_operand" "r")
9139 (match_operand:SI 4 "const_shift_operand" "n")])
9140 (match_operand:SI 1 "s_register_operand" "0"))))
9141 (set (match_operand:SI 0 "s_register_operand" "=r")
9142 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9145 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9146 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9147 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9148 "ldr%?b\\t%5, [%0, %3%S2]!"
9149 [(set_attr "type" "load")
9150 (set_attr "predicable" "yes")]
9153 (define_insn "*loadqi_shiftpredec"
9154 [(set (match_operand:QI 5 "s_register_operand" "=r")
9155 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9156 (match_operator:SI 2 "shift_operator"
9157 [(match_operand:SI 3 "s_register_operand" "r")
9158 (match_operand:SI 4 "const_shift_operand" "n")]))))
9159 (set (match_operand:SI 0 "s_register_operand" "=r")
9160 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9163 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9164 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9165 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9166 "ldr%?b\\t%5, [%0, -%3%S2]!"
9167 [(set_attr "type" "load")
9168 (set_attr "predicable" "yes")]
9171 (define_insn "*strsi_shiftpreinc"
9172 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9173 [(match_operand:SI 3 "s_register_operand" "r")
9174 (match_operand:SI 4 "const_shift_operand" "n")])
9175 (match_operand:SI 1 "s_register_operand" "0")))
9176 (match_operand:SI 5 "s_register_operand" "r"))
9177 (set (match_operand:SI 0 "s_register_operand" "=r")
9178 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9181 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9182 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9183 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9184 "str%?\\t%5, [%0, %3%S2]!"
9185 [(set_attr "type" "store1")
9186 (set_attr "predicable" "yes")]
9189 (define_insn "*strsi_shiftpredec"
9190 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9191 (match_operator:SI 2 "shift_operator"
9192 [(match_operand:SI 3 "s_register_operand" "r")
9193 (match_operand:SI 4 "const_shift_operand" "n")])))
9194 (match_operand:SI 5 "s_register_operand" "r"))
9195 (set (match_operand:SI 0 "s_register_operand" "=r")
9196 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9199 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9200 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9201 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9202 "str%?\\t%5, [%0, -%3%S2]!"
9203 [(set_attr "type" "store1")
9204 (set_attr "predicable" "yes")]
9207 (define_insn "*loadsi_shiftpreinc"
9208 [(set (match_operand:SI 5 "s_register_operand" "=r")
9209 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9210 [(match_operand:SI 3 "s_register_operand" "r")
9211 (match_operand:SI 4 "const_shift_operand" "n")])
9212 (match_operand:SI 1 "s_register_operand" "0"))))
9213 (set (match_operand:SI 0 "s_register_operand" "=r")
9214 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9217 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9218 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9219 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9220 "ldr%?\\t%5, [%0, %3%S2]!"
9221 [(set_attr "type" "load")
9222 (set_attr "predicable" "yes")]
9225 (define_insn "*loadsi_shiftpredec"
9226 [(set (match_operand:SI 5 "s_register_operand" "=r")
9227 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9228 (match_operator:SI 2 "shift_operator"
9229 [(match_operand:SI 3 "s_register_operand" "r")
9230 (match_operand:SI 4 "const_shift_operand" "n")]))))
9231 (set (match_operand:SI 0 "s_register_operand" "=r")
9232 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9235 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9236 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9237 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9238 "ldr%?\\t%5, [%0, -%3%S2]!"
9239 [(set_attr "type" "load")
9240 (set_attr "predicable" "yes")])
9242 (define_insn "*loadhi_shiftpreinc"
9243 [(set (match_operand:HI 5 "s_register_operand" "=r")
9244 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
9245 [(match_operand:SI 3 "s_register_operand" "r")
9246 (match_operand:SI 4 "const_shift_operand" "n")])
9247 (match_operand:SI 1 "s_register_operand" "0"))))
9248 (set (match_operand:SI 0 "s_register_operand" "=r")
9249 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9252 && !BYTES_BIG_ENDIAN
9253 && !TARGET_MMU_TRAPS
9255 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9256 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9257 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9258 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
9259 [(set_attr "type" "load")
9260 (set_attr "predicable" "yes")]
9263 (define_insn "*loadhi_shiftpredec"
9264 [(set (match_operand:HI 5 "s_register_operand" "=r")
9265 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9266 (match_operator:SI 2 "shift_operator"
9267 [(match_operand:SI 3 "s_register_operand" "r")
9268 (match_operand:SI 4 "const_shift_operand" "n")]))))
9269 (set (match_operand:SI 0 "s_register_operand" "=r")
9270 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9273 && !BYTES_BIG_ENDIAN
9274 && !TARGET_MMU_TRAPS
9276 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9277 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9278 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9279 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
9280 [(set_attr "type" "load")
9281 (set_attr "predicable" "yes")]
9284 ; It can also support extended post-inc expressions, but combine doesn't
9286 ; It doesn't seem worth adding peepholes for anything but the most common
9287 ; cases since, unlike combine, the increment must immediately follow the load
9288 ; for this pattern to match.
9289 ; We must watch to see that the source/destination register isn't also the
9290 ; same as the base address register, and that if the index is a register,
9291 ; that it is not the same as the base address register. In such cases the
9292 ; instruction that we would generate would have UNPREDICTABLE behavior so
9296 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9297 (match_operand:QI 2 "s_register_operand" "r"))
9299 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9301 && (REGNO (operands[2]) != REGNO (operands[0]))
9302 && (GET_CODE (operands[1]) != REG
9303 || (REGNO (operands[1]) != REGNO (operands[0])))"
9304 "str%?b\\t%2, [%0], %1"
9308 [(set (match_operand:QI 0 "s_register_operand" "=r")
9309 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9311 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9313 && REGNO (operands[0]) != REGNO(operands[1])
9314 && (GET_CODE (operands[2]) != REG
9315 || REGNO(operands[0]) != REGNO (operands[2]))"
9316 "ldr%?b\\t%0, [%1], %2"
9320 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9321 (match_operand:SI 2 "s_register_operand" "r"))
9323 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9325 && (REGNO (operands[2]) != REGNO (operands[0]))
9326 && (GET_CODE (operands[1]) != REG
9327 || (REGNO (operands[1]) != REGNO (operands[0])))"
9328 "str%?\\t%2, [%0], %1"
9332 [(set (match_operand:HI 0 "s_register_operand" "=r")
9333 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
9335 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9337 && !BYTES_BIG_ENDIAN
9338 && !TARGET_MMU_TRAPS
9340 && REGNO (operands[0]) != REGNO(operands[1])
9341 && (GET_CODE (operands[2]) != REG
9342 || REGNO(operands[0]) != REGNO (operands[2]))"
9343 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
9347 [(set (match_operand:SI 0 "s_register_operand" "=r")
9348 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9350 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9352 && REGNO (operands[0]) != REGNO(operands[1])
9353 && (GET_CODE (operands[2]) != REG
9354 || REGNO(operands[0]) != REGNO (operands[2]))"
9355 "ldr%?\\t%0, [%1], %2"
9359 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9360 (match_operand:SI 1 "index_operand" "rJ")))
9361 (match_operand:QI 2 "s_register_operand" "r"))
9362 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9364 && (REGNO (operands[2]) != REGNO (operands[0]))
9365 && (GET_CODE (operands[1]) != REG
9366 || (REGNO (operands[1]) != REGNO (operands[0])))"
9367 "str%?b\\t%2, [%0, %1]!"
9371 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9372 [(match_operand:SI 0 "s_register_operand" "r")
9373 (match_operand:SI 1 "const_int_operand" "n")])
9374 (match_operand:SI 2 "s_register_operand" "+r")))
9375 (match_operand:QI 3 "s_register_operand" "r"))
9376 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9379 && (REGNO (operands[3]) != REGNO (operands[2]))
9380 && (REGNO (operands[0]) != REGNO (operands[2]))"
9381 "str%?b\\t%3, [%2, %0%S4]!"
9384 ; This pattern is never tried by combine, so do it as a peephole
9387 [(set (match_operand:SI 0 "s_register_operand" "")
9388 (match_operand:SI 1 "s_register_operand" ""))
9389 (set (reg:CC CC_REGNUM)
9390 (compare:CC (match_dup 1) (const_int 0)))]
9393 || (!cirrus_fp_register (operands[0], SImode)
9394 && !cirrus_fp_register (operands[1], SImode)))
9396 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9397 (set (match_dup 0) (match_dup 1))])]
9401 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9402 ; reversed, check that the memory references aren't volatile.
9405 [(set (match_operand:SI 0 "s_register_operand" "=r")
9406 (match_operand:SI 4 "memory_operand" "m"))
9407 (set (match_operand:SI 1 "s_register_operand" "=r")
9408 (match_operand:SI 5 "memory_operand" "m"))
9409 (set (match_operand:SI 2 "s_register_operand" "=r")
9410 (match_operand:SI 6 "memory_operand" "m"))
9411 (set (match_operand:SI 3 "s_register_operand" "=r")
9412 (match_operand:SI 7 "memory_operand" "m"))]
9413 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9415 return emit_ldm_seq (operands, 4);
9420 [(set (match_operand:SI 0 "s_register_operand" "=r")
9421 (match_operand:SI 3 "memory_operand" "m"))
9422 (set (match_operand:SI 1 "s_register_operand" "=r")
9423 (match_operand:SI 4 "memory_operand" "m"))
9424 (set (match_operand:SI 2 "s_register_operand" "=r")
9425 (match_operand:SI 5 "memory_operand" "m"))]
9426 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9428 return emit_ldm_seq (operands, 3);
9433 [(set (match_operand:SI 0 "s_register_operand" "=r")
9434 (match_operand:SI 2 "memory_operand" "m"))
9435 (set (match_operand:SI 1 "s_register_operand" "=r")
9436 (match_operand:SI 3 "memory_operand" "m"))]
9437 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9439 return emit_ldm_seq (operands, 2);
9444 [(set (match_operand:SI 4 "memory_operand" "=m")
9445 (match_operand:SI 0 "s_register_operand" "r"))
9446 (set (match_operand:SI 5 "memory_operand" "=m")
9447 (match_operand:SI 1 "s_register_operand" "r"))
9448 (set (match_operand:SI 6 "memory_operand" "=m")
9449 (match_operand:SI 2 "s_register_operand" "r"))
9450 (set (match_operand:SI 7 "memory_operand" "=m")
9451 (match_operand:SI 3 "s_register_operand" "r"))]
9452 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9454 return emit_stm_seq (operands, 4);
9459 [(set (match_operand:SI 3 "memory_operand" "=m")
9460 (match_operand:SI 0 "s_register_operand" "r"))
9461 (set (match_operand:SI 4 "memory_operand" "=m")
9462 (match_operand:SI 1 "s_register_operand" "r"))
9463 (set (match_operand:SI 5 "memory_operand" "=m")
9464 (match_operand:SI 2 "s_register_operand" "r"))]
9465 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9467 return emit_stm_seq (operands, 3);
9472 [(set (match_operand:SI 2 "memory_operand" "=m")
9473 (match_operand:SI 0 "s_register_operand" "r"))
9474 (set (match_operand:SI 3 "memory_operand" "=m")
9475 (match_operand:SI 1 "s_register_operand" "r"))]
9476 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9478 return emit_stm_seq (operands, 2);
9483 [(set (match_operand:SI 0 "s_register_operand" "")
9484 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9486 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9487 [(match_operand:SI 3 "s_register_operand" "")
9488 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9489 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9491 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9492 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9497 ;; This split can be used because CC_Z mode implies that the following
9498 ;; branch will be an equality, or an unsigned inequality, so the sign
9499 ;; extension is not needed.
9502 [(set (reg:CC_Z CC_REGNUM)
9504 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9506 (match_operand 1 "const_int_operand" "")))
9507 (clobber (match_scratch:SI 2 ""))]
9509 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9510 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9511 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9512 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9514 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9518 (define_expand "prologue"
9519 [(clobber (const_int 0))]
9522 arm_expand_prologue ();
9524 thumb_expand_prologue ();
9529 (define_expand "epilogue"
9530 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9534 thumb_expand_epilogue ();
9535 else if (USE_RETURN_INSN (FALSE))
9537 emit_jump_insn (gen_return ());
9540 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9542 gen_rtx_RETURN (VOIDmode)),
9548 ;; Note - although unspec_volatile's USE all hard registers,
9549 ;; USEs are ignored after relaod has completed. Thus we need
9550 ;; to add an unspec of the link register to ensure that flow
9551 ;; does not think that it is unused by the sibcall branch that
9552 ;; will replace the standard function epilogue.
9553 (define_insn "sibcall_epilogue"
9554 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9555 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9558 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9559 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9560 return arm_output_epilogue (next_nonnote_insn (insn));
9562 ;; Length is absolute worst case
9563 [(set_attr "length" "44")
9564 (set_attr "type" "block")
9565 ;; We don't clobber the conditions, but the potential length of this
9566 ;; operation is sufficient to make conditionalizing the sequence
9567 ;; unlikely to be profitable.
9568 (set_attr "conds" "clob")]
9571 (define_insn "*epilogue_insns"
9572 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9576 return arm_output_epilogue (NULL);
9577 else /* TARGET_THUMB */
9578 return thumb_unexpanded_epilogue ();
9580 ; Length is absolute worst case
9581 [(set_attr "length" "44")
9582 (set_attr "type" "block")
9583 ;; We don't clobber the conditions, but the potential length of this
9584 ;; operation is sufficient to make conditionalizing the sequence
9585 ;; unlikely to be profitable.
9586 (set_attr "conds" "clob")]
9589 (define_expand "eh_epilogue"
9590 [(use (match_operand:SI 0 "register_operand" ""))
9591 (use (match_operand:SI 1 "register_operand" ""))
9592 (use (match_operand:SI 2 "register_operand" ""))]
9596 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9597 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9599 rtx ra = gen_rtx_REG (Pmode, 2);
9601 emit_move_insn (ra, operands[2]);
9604 /* This is a hack -- we may have crystalized the function type too
9606 cfun->machine->func_type = 0;
9610 ;; This split is only used during output to reduce the number of patterns
9611 ;; that need assembler instructions adding to them. We allowed the setting
9612 ;; of the conditions to be implicit during rtl generation so that
9613 ;; the conditional compare patterns would work. However this conflicts to
9614 ;; some extent with the conditional data operations, so we have to split them
9618 [(set (match_operand:SI 0 "s_register_operand" "")
9619 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9620 [(match_operand 2 "" "") (match_operand 3 "" "")])
9622 (match_operand 4 "" "")))
9623 (clobber (reg:CC CC_REGNUM))]
9624 "TARGET_ARM && reload_completed"
9625 [(set (match_dup 5) (match_dup 6))
9626 (cond_exec (match_dup 7)
9627 (set (match_dup 0) (match_dup 4)))]
9630 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9631 operands[2], operands[3]);
9632 enum rtx_code rc = GET_CODE (operands[1]);
9634 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9635 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9636 if (mode == CCFPmode || mode == CCFPEmode)
9637 rc = reverse_condition_maybe_unordered (rc);
9639 rc = reverse_condition (rc);
9641 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9646 [(set (match_operand:SI 0 "s_register_operand" "")
9647 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9648 [(match_operand 2 "" "") (match_operand 3 "" "")])
9649 (match_operand 4 "" "")
9651 (clobber (reg:CC CC_REGNUM))]
9652 "TARGET_ARM && reload_completed"
9653 [(set (match_dup 5) (match_dup 6))
9654 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9655 (set (match_dup 0) (match_dup 4)))]
9658 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9659 operands[2], operands[3]);
9661 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9662 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9667 [(set (match_operand:SI 0 "s_register_operand" "")
9668 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9669 [(match_operand 2 "" "") (match_operand 3 "" "")])
9670 (match_operand 4 "" "")
9671 (match_operand 5 "" "")))
9672 (clobber (reg:CC CC_REGNUM))]
9673 "TARGET_ARM && reload_completed"
9674 [(set (match_dup 6) (match_dup 7))
9675 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9676 (set (match_dup 0) (match_dup 4)))
9677 (cond_exec (match_dup 8)
9678 (set (match_dup 0) (match_dup 5)))]
9681 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9682 operands[2], operands[3]);
9683 enum rtx_code rc = GET_CODE (operands[1]);
9685 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9686 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9687 if (mode == CCFPmode || mode == CCFPEmode)
9688 rc = reverse_condition_maybe_unordered (rc);
9690 rc = reverse_condition (rc);
9692 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9697 [(set (match_operand:SI 0 "s_register_operand" "")
9698 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9699 [(match_operand:SI 2 "s_register_operand" "")
9700 (match_operand:SI 3 "arm_add_operand" "")])
9701 (match_operand:SI 4 "arm_rhs_operand" "")
9703 (match_operand:SI 5 "s_register_operand" ""))))
9704 (clobber (reg:CC CC_REGNUM))]
9705 "TARGET_ARM && reload_completed"
9706 [(set (match_dup 6) (match_dup 7))
9707 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9708 (set (match_dup 0) (match_dup 4)))
9709 (cond_exec (match_dup 8)
9710 (set (match_dup 0) (not:SI (match_dup 5))))]
9713 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9714 operands[2], operands[3]);
9715 enum rtx_code rc = GET_CODE (operands[1]);
9717 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9718 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
9719 if (mode == CCFPmode || mode == CCFPEmode)
9720 rc = reverse_condition_maybe_unordered (rc);
9722 rc = reverse_condition (rc);
9724 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9728 (define_insn "*cond_move_not"
9729 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9730 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9731 [(match_operand 3 "cc_register" "") (const_int 0)])
9732 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9734 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9738 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9739 [(set_attr "conds" "use")
9740 (set_attr "length" "4,8")]
9743 ;; The next two patterns occur when an AND operation is followed by a
9744 ;; scc insn sequence
9746 (define_insn "*sign_extract_onebit"
9747 [(set (match_operand:SI 0 "s_register_operand" "=r")
9748 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9750 (match_operand:SI 2 "const_int_operand" "n")))
9751 (clobber (reg:CC CC_REGNUM))]
9754 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9755 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9756 return \"mvnne\\t%0, #0\";
9758 [(set_attr "conds" "clob")
9759 (set_attr "length" "8")]
9762 (define_insn "*not_signextract_onebit"
9763 [(set (match_operand:SI 0 "s_register_operand" "=r")
9765 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9767 (match_operand:SI 2 "const_int_operand" "n"))))
9768 (clobber (reg:CC CC_REGNUM))]
9771 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9772 output_asm_insn (\"tst\\t%1, %2\", operands);
9773 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9774 return \"movne\\t%0, #0\";
9776 [(set_attr "conds" "clob")
9777 (set_attr "length" "12")]
9780 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
9781 ;; expressions. For simplicity, the first register is also in the unspec
9783 (define_insn "*push_multi"
9784 [(match_parallel 2 "multi_register_push"
9785 [(set (match_operand:BLK 0 "memory_operand" "=m")
9786 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9787 UNSPEC_PUSH_MULT))])]
9791 int num_saves = XVECLEN (operands[2], 0);
9793 /* For the StrongARM at least it is faster to
9794 use STR to store only a single register. */
9796 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9802 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9804 for (i = 1; i < num_saves; i++)
9806 strcat (pattern, \", %|\");
9808 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9811 strcat (pattern, \"}\");
9812 output_asm_insn (pattern, operands);
9817 [(set_attr "type" "store4")]
9820 (define_insn "stack_tie"
9821 [(set (mem:BLK (scratch))
9822 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9823 (match_operand:SI 1 "s_register_operand" "r")]
9827 [(set_attr "length" "0")]
9830 ;; Similarly for the floating point registers
9831 (define_insn "*push_fp_multi"
9832 [(match_parallel 2 "multi_register_push"
9833 [(set (match_operand:BLK 0 "memory_operand" "=m")
9834 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9835 UNSPEC_PUSH_MULT))])]
9841 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9842 output_asm_insn (pattern, operands);
9845 [(set_attr "type" "f_store")]
9848 ;; Special patterns for dealing with the constant pool
9850 (define_insn "align_4"
9851 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9854 assemble_align (32);
9859 (define_insn "align_8"
9860 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9861 "TARGET_REALLY_IWMMXT"
9863 assemble_align (64);
9868 (define_insn "consttable_end"
9869 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9872 making_const_table = FALSE;
9877 (define_insn "consttable_1"
9878 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9881 making_const_table = TRUE;
9882 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9886 [(set_attr "length" "4")]
9889 (define_insn "consttable_2"
9890 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9893 making_const_table = TRUE;
9894 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9898 [(set_attr "length" "4")]
9901 (define_insn "consttable_4"
9902 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9906 making_const_table = TRUE;
9907 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9912 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9913 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9917 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9922 [(set_attr "length" "4")]
9925 (define_insn "consttable_8"
9926 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9930 making_const_table = TRUE;
9931 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9936 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9937 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9941 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9946 [(set_attr "length" "8")]
9949 ;; Miscellaneous Thumb patterns
9951 (define_expand "tablejump"
9952 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9953 (use (label_ref (match_operand 1 "" "")))])]
9958 /* Hopefully, CSE will eliminate this copy. */
9959 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9960 rtx reg2 = gen_reg_rtx (SImode);
9962 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9968 (define_insn "*thumb_tablejump"
9969 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9970 (use (label_ref (match_operand 1 "" "")))]
9973 [(set_attr "length" "2")]
9978 (define_insn "clzsi2"
9979 [(set (match_operand:SI 0 "s_register_operand" "=r")
9980 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
9981 "TARGET_ARM && arm_arch5"
9983 [(set_attr "predicable" "yes")])
9985 (define_expand "ffssi2"
9986 [(set (match_operand:SI 0 "s_register_operand" "")
9987 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9988 "TARGET_ARM && arm_arch5"
9993 t1 = gen_reg_rtx (SImode);
9994 t2 = gen_reg_rtx (SImode);
9995 t3 = gen_reg_rtx (SImode);
9997 emit_insn (gen_negsi2 (t1, operands[1]));
9998 emit_insn (gen_andsi3 (t2, operands[1], t1));
9999 emit_insn (gen_clzsi2 (t3, t2));
10000 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
10005 (define_expand "ctzsi2"
10006 [(set (match_operand:SI 0 "s_register_operand" "")
10007 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
10008 "TARGET_ARM && arm_arch5"
10013 t1 = gen_reg_rtx (SImode);
10014 t2 = gen_reg_rtx (SImode);
10015 t3 = gen_reg_rtx (SImode);
10017 emit_insn (gen_negsi2 (t1, operands[1]));
10018 emit_insn (gen_andsi3 (t2, operands[1], t1));
10019 emit_insn (gen_clzsi2 (t3, t2));
10020 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
10025 ;; V5E instructions.
10027 (define_insn "prefetch"
10028 [(prefetch (match_operand:SI 0 "address_operand" "p")
10029 (match_operand:SI 1 "" "")
10030 (match_operand:SI 2 "" ""))]
10031 "TARGET_ARM && arm_arch5e"
10034 ;; General predication pattern
10037 [(match_operator 0 "arm_comparison_operator"
10038 [(match_operand 1 "cc_register" "")
10044 (define_insn "prologue_use"
10045 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
10047 "%@ %0 needed for prologue"
10050 ;; Load the FPA co-processor patterns
10052 ;; Load the Maverick co-processor patterns
10053 (include "cirrus.md")
10054 ;; Load the Intel Wireless Multimedia Extension patterns
10055 (include "iwmmxt.md")