1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
3 ;; 2001, 2002, 2003 Free Software Foundation, Inc.
4 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
5 ;; and Martin Simmons (@harleqn.co.uk).
6 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
8 ;; This file is part of GCC.
10 ;; GCC is free software; you can redistribute it and/or modify it
11 ;; under the terms of the GNU General Public License as published
12 ;; by the Free Software Foundation; either version 2, or (at your
13 ;; option) any later version.
15 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
16 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18 ;; License for more details.
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GCC; see the file COPYING. If not, write to
22 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
25 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
28 ;;---------------------------------------------------------------------------
33 [(IP_REGNUM 12) ; Scratch register
34 (SP_REGNUM 13) ; Stack pointer
35 (LR_REGNUM 14) ; Return address register
36 (PC_REGNUM 15) ; Program counter
37 (CC_REGNUM 24) ; Condition code pseudo register
41 ;; 3rd operand to select_dominance_cc_mode
50 ;; Note: sin and cos are no-longer used.
53 [(UNSPEC_SIN 0) ; `sin' operation (MODE_FLOAT):
54 ; operand 0 is the result,
55 ; operand 1 the parameter.
56 (UNPSEC_COS 1) ; `cos' operation (MODE_FLOAT):
57 ; operand 0 is the result,
58 ; operand 1 the parameter.
59 (UNSPEC_PUSH_MULT 2) ; `push multiple' operation:
60 ; operand 0 is the first register,
61 ; subsequent registers are in parallel (use ...)
63 (UNSPEC_PIC_SYM 3) ; A symbol that has been treated properly for pic
64 ; usage, that is, we will add the pic_register
65 ; value to it before trying to dereference it.
66 (UNSPEC_PIC_BASE 4) ; Adding the PC value to the offset to the
67 ; GLOBAL_OFFSET_TABLE. The operation is fully
68 ; described by the RTL but must be wrapped to
69 ; prevent combine from trying to rip it apart.
70 (UNSPEC_PRLG_STK 5) ; A special barrier that prevents frame accesses
71 ; being scheduled before the stack adjustment insn.
72 (UNSPEC_PROLOGUE_USE 6) ; As USE insns are not meaningful after reload,
73 ; this unspec is used to prevent the deletion of
74 ; instructions setting registers for EH handling
75 ; and stack frame generation. Operand 0 is the
77 (UNSPEC_CHECK_ARCH 7); Set CCs to indicate 26-bit or 32-bit mode.
78 (UNSPEC_WSHUFH 8) ; Used by the intrinsic form of the iWMMXt WSHUFH instruction.
79 (UNSPEC_WACC 9) ; Used by the intrinsic form of the iWMMXt WACC instruction.
80 (UNSPEC_TMOVMSK 10) ; Used by the intrinsic form of the iWMMXt TMOVMSK instruction.
81 (UNSPEC_WSAD 11) ; Used by the intrinsic form of the iWMMXt WSAD instruction.
82 (UNSPEC_WSADZ 12) ; Used by the intrinsic form of the iWMMXt WSADZ instruction.
83 (UNSPEC_WMACS 13) ; Used by the intrinsic form of the iWMMXt WMACS instruction.
84 (UNSPEC_WMACU 14) ; Used by the intrinsic form of the iWMMXt WMACU instruction.
85 (UNSPEC_WMACSZ 15) ; Used by the intrinsic form of the iWMMXt WMACSZ instruction.
86 (UNSPEC_WMACUZ 16) ; Used by the intrinsic form of the iWMMXt WMACUZ instruction.
87 (UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
88 (UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
89 (UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
93 ;; UNSPEC_VOLATILE Usage:
96 [(VUNSPEC_BLOCKAGE 0) ; `blockage' insn to prevent scheduling across an
98 (VUNSPEC_EPILOGUE 1) ; `epilogue' insn, used to represent any part of the
99 ; instruction epilogue sequence that isn't expanded
100 ; into normal RTL. Used for both normal and sibcall
102 (VUNSPEC_ALIGN 2) ; `align' insn. Used at the head of a minipool table
103 ; for inlined constants.
104 (VUNSPEC_POOL_END 3) ; `end-of-table'. Used to mark the end of a minipool
106 (VUNSPEC_POOL_1 4) ; `pool-entry(1)'. An entry in the constant pool for
108 (VUNSPEC_POOL_2 5) ; `pool-entry(2)'. An entry in the constant pool for
110 (VUNSPEC_POOL_4 6) ; `pool-entry(4)'. An entry in the constant pool for
112 (VUNSPEC_POOL_8 7) ; `pool-entry(8)'. An entry in the constant pool for
114 (VUNSPEC_TMRC 8) ; Used by the iWMMXt TMRC instruction.
115 (VUNSPEC_TMCR 9) ; Used by the iWMMXt TMCR instruction.
116 (VUNSPEC_ALIGN8 10) ; 8-byte alignment version of VUNSPEC_ALIGN
117 (VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
118 (VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
119 (VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
123 ;;---------------------------------------------------------------------------
126 ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when
127 ; generating ARM code. This is used to control the length of some insn
128 ; patterns that share the same RTL in both ARM and Thumb code.
129 (define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
131 ; PROG_MODE attribute is used to determine whether condition codes are
132 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
133 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
134 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
136 ; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
137 ; scheduling decisions for the load unit and the multiplier.
138 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
140 ;; Operand number of an input operand that is shifted. Zero if the
141 ;; given instruction does not shift one of its input operands.
142 (define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
143 (define_attr "shift" "" (const_int 0))
145 ; Floating Point Unit. If we only have floating point emulation, then there
146 ; is no point in scheduling the floating point insns. (Well, for best
147 ; performance we should try and group them together).
148 (define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
149 (const (symbol_ref "arm_fpu_attr")))
151 ; LENGTH of an instruction (in bytes)
152 (define_attr "length" "" (const_int 4))
154 ; POOL_RANGE is how far away from a constant pool entry that this insn
155 ; can be placed. If the distance is zero, then this insn will never
156 ; reference the pool.
157 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
158 ; before its address.
159 (define_attr "pool_range" "" (const_int 0))
160 (define_attr "neg_pool_range" "" (const_int 0))
162 ; An assembler sequence may clobber the condition codes without us knowing.
163 ; If such an insn references the pool, then we have no way of knowing how,
164 ; so use the most conservative value for pool_range.
165 (define_asm_attributes
166 [(set_attr "conds" "clob")
167 (set_attr "length" "4")
168 (set_attr "pool_range" "250")])
170 ; TYPE attribute is used to detect floating point instructions which, if
171 ; running on a co-processor can run in parallel with other, basic instructions
172 ; If write-buffer scheduling is enabled then it can also be used in the
173 ; scheduling of writes.
175 ; Classification of each insn
176 ; normal any data instruction that doesn't hit memory or fp regs
177 ; mult a multiply instruction
178 ; block blockage insn, this blocks all functional units
179 ; float a floating point arithmetic operation (subject to expansion)
180 ; fdivd DFmode floating point division
181 ; fdivs SFmode floating point division
182 ; fmul Floating point multiply
183 ; ffmul Fast floating point multiply
184 ; farith Floating point arithmetic (4 cycle)
185 ; ffarith Fast floating point arithmetic (2 cycle)
186 ; float_em a floating point arithmetic operation that is normally emulated
187 ; even on a machine with an fpa.
188 ; f_load a floating point load from memory
189 ; f_store a floating point store to memory
190 ; f_mem_r a transfer of a floating point register to a real reg via mem
191 ; r_mem_f the reverse of f_mem_r
192 ; f_2_r fast transfer float to arm (no memory needed)
193 ; r_2_f fast transfer arm to float
194 ; call a subroutine call
195 ; load any load from memory
196 ; store1 store 1 word to memory from arm registers
197 ; store2 store 2 words
198 ; store3 store 3 words
199 ; store4 store 4 words
200 ; Additions for Cirrus Maverick co-processor:
201 ; mav_farith Floating point arithmetic (4 cycle)
202 ; mav_dmult Double multiplies (7 cycle)
205 "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4,mav_farith,mav_dmult"
206 (const_string "normal"))
208 ; Load scheduling, set from the arm_ld_sched variable
209 ; initialized by arm_override_options()
210 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
212 ; condition codes: this one is used by final_prescan_insn to speed up
213 ; conditionalizing instructions. It saves having to scan the rtl to see if
214 ; it uses or alters the condition codes.
216 ; USE means that the condition codes are used by the insn in the process of
217 ; outputting code, this means (at present) that we can't use the insn in
220 ; SET means that the purpose of the insn is to set the condition codes in a
221 ; well defined manner.
223 ; CLOB means that the condition codes are altered in an undefined manner, if
224 ; they are altered at all
226 ; JUMP_CLOB is used when the condition cannot be represented by a single
227 ; instruction (UNEQ and LTGT). These cannot be predicated.
229 ; NOCOND means that the condition codes are neither altered nor affect the
230 ; output of this insn
232 (define_attr "conds" "use,set,clob,jump_clob,nocond"
233 (if_then_else (eq_attr "type" "call")
234 (if_then_else (eq_attr "prog_mode" "prog32")
235 (const_string "clob") (const_string "nocond"))
236 (const_string "nocond")))
238 ; Predicable means that the insn can be conditionally executed based on
239 ; an automatically added predicate (additional patterns are generated by
240 ; gen...). We default to 'no' because no Thumb patterns match this rule
241 ; and not all ARM patterns do.
242 (define_attr "predicable" "no,yes" (const_string "no"))
244 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
245 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
246 ; suffer blockages enough to warrant modelling this (and it can adversely
247 ; affect the schedule).
248 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
250 ; WRITE_CONFLICT implies that a read following an unrelated write is likely
251 ; to stall the processor. Used with model_wbuf above.
252 (define_attr "write_conflict" "no,yes"
253 (if_then_else (eq_attr "type"
254 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
256 (const_string "no")))
258 ; Classify the insns into those that take one cycle and those that take more
259 ; than one on the main cpu execution unit.
260 (define_attr "core_cycles" "single,multi"
261 (if_then_else (eq_attr "type"
262 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
263 (const_string "single")
264 (const_string "multi")))
266 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
267 ;; distant label. Only applicable to Thumb code.
268 (define_attr "far_jump" "yes,no" (const_string "no"))
270 (define_automaton "arm")
274 ; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
276 ; The write buffer on some of the arm6 processors is hard to model exactly.
277 ; There is room in the buffer for up to two addresses and up to eight words
278 ; of memory, but the two needn't be split evenly. When writing the two
279 ; addresses are fully pipelined. However, a read from memory that is not
280 ; currently in the cache will block until the writes have completed.
281 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
282 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
283 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
284 ; cycle to add as well.
285 (define_cpu_unit "write_buf" "arm")
287 ;; Write blockage unit
289 ; The write_blockage unit models (partially), the fact that reads will stall
290 ; until the write buffer empties.
291 ; The f_mem_r and r_mem_f could also block, but they are to the stack,
292 ; so we don't model them here
293 (define_cpu_unit "write_blockage" "arm")
297 (define_cpu_unit "core" "arm")
299 (define_insn_reservation "r_mem_f_wbuf" 5
300 (and (eq_attr "model_wbuf" "yes")
301 (eq_attr "type" "r_mem_f"))
304 (define_insn_reservation "store1_wbuf" 5
305 (and (eq_attr "model_wbuf" "yes")
306 (eq_attr "type" "store1"))
307 "core+write_buf*3+write_blockage*5")
309 (define_insn_reservation "store2_wbuf" 7
310 (and (eq_attr "model_wbuf" "yes")
311 (eq_attr "type" "store2"))
312 "core+write_buf*4+write_blockage*7")
314 (define_insn_reservation "store3_wbuf" 9
315 (and (eq_attr "model_wbuf" "yes")
316 (eq_attr "type" "store3"))
317 "core+write_buf*5+write_blockage*9")
319 (define_insn_reservation "store4_wbuf" 11
320 (and (eq_attr "model_wbuf" "yes")
321 (eq_attr "type" "store4"))
322 "core+write_buf*6+write_blockage*11")
324 (define_insn_reservation "store2" 3
325 (and (eq_attr "model_wbuf" "no")
326 (eq_attr "type" "store2"))
329 (define_insn_reservation "store3" 4
330 (and (eq_attr "model_wbuf" "no")
331 (eq_attr "type" "store3"))
334 (define_insn_reservation "store4" 5
335 (and (eq_attr "model_wbuf" "no")
336 (eq_attr "type" "store4"))
339 (define_insn_reservation "store1_ldsched" 1
340 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1"))
343 (define_insn_reservation "load_ldsched_xscale" 3
344 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
345 (eq_attr "is_xscale" "yes"))
348 (define_insn_reservation "load_ldsched" 2
349 (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
350 (eq_attr "is_xscale" "no"))
353 (define_insn_reservation "load_or_store" 2
354 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1"))
357 (define_insn_reservation "mult" 16
358 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult"))
361 (define_insn_reservation "mult_ldsched_strongarm" 3
362 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
363 (eq_attr "type" "mult"))
366 (define_insn_reservation "mult_ldsched" 4
367 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
368 (eq_attr "type" "mult"))
371 (define_insn_reservation "multi_cycle" 32
372 (and (eq_attr "core_cycles" "multi")
373 (eq_attr "type" "!mult,load,store1,store2,store3,store4"))
376 (define_insn_reservation "single_cycle" 1
377 (eq_attr "core_cycles" "single")
381 ;;---------------------------------------------------------------------------
386 ;; Note: For DImode insns, there is normally no reason why operands should
387 ;; not be in the same register, what we don't want is for something being
388 ;; written to partially overlap something that is an input.
389 ;; Cirrus 64bit additions should not be split because we have a native
390 ;; 64bit addition instructions.
392 (define_expand "adddi3"
394 [(set (match_operand:DI 0 "s_register_operand" "")
395 (plus:DI (match_operand:DI 1 "s_register_operand" "")
396 (match_operand:DI 2 "s_register_operand" "")))
397 (clobber (reg:CC CC_REGNUM))])]
402 if (!cirrus_fp_register (operands[0], DImode))
403 operands[0] = force_reg (DImode, operands[0]);
404 if (!cirrus_fp_register (operands[1], DImode))
405 operands[1] = force_reg (DImode, operands[1]);
406 emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
412 if (GET_CODE (operands[1]) != REG)
413 operands[1] = force_reg (SImode, operands[1]);
414 if (GET_CODE (operands[2]) != REG)
415 operands[2] = force_reg (SImode, operands[2]);
420 (define_insn "*thumb_adddi3"
421 [(set (match_operand:DI 0 "register_operand" "=l")
422 (plus:DI (match_operand:DI 1 "register_operand" "%0")
423 (match_operand:DI 2 "register_operand" "l")))
424 (clobber (reg:CC CC_REGNUM))
427 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
428 [(set_attr "length" "4")]
431 (define_insn_and_split "*arm_adddi3"
432 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
433 (plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
434 (match_operand:DI 2 "s_register_operand" "r, 0")))
435 (clobber (reg:CC CC_REGNUM))]
436 "TARGET_ARM && !TARGET_CIRRUS"
438 "TARGET_ARM && reload_completed"
439 [(parallel [(set (reg:CC_C CC_REGNUM)
440 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
442 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
443 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
444 (plus:SI (match_dup 4) (match_dup 5))))]
447 operands[3] = gen_highpart (SImode, operands[0]);
448 operands[0] = gen_lowpart (SImode, operands[0]);
449 operands[4] = gen_highpart (SImode, operands[1]);
450 operands[1] = gen_lowpart (SImode, operands[1]);
451 operands[5] = gen_highpart (SImode, operands[2]);
452 operands[2] = gen_lowpart (SImode, operands[2]);
454 [(set_attr "conds" "clob")
455 (set_attr "length" "8")]
458 (define_insn_and_split "*adddi_sesidi_di"
459 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
460 (plus:DI (sign_extend:DI
461 (match_operand:SI 2 "s_register_operand" "r,r"))
462 (match_operand:DI 1 "s_register_operand" "r,0")))
463 (clobber (reg:CC CC_REGNUM))]
464 "TARGET_ARM && !TARGET_CIRRUS"
466 "TARGET_ARM && reload_completed"
467 [(parallel [(set (reg:CC_C CC_REGNUM)
468 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
470 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
471 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
472 (plus:SI (ashiftrt:SI (match_dup 2)
477 operands[3] = gen_highpart (SImode, operands[0]);
478 operands[0] = gen_lowpart (SImode, operands[0]);
479 operands[4] = gen_highpart (SImode, operands[1]);
480 operands[1] = gen_lowpart (SImode, operands[1]);
481 operands[2] = gen_lowpart (SImode, operands[2]);
483 [(set_attr "conds" "clob")
484 (set_attr "length" "8")]
487 (define_insn_and_split "*adddi_zesidi_di"
488 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
489 (plus:DI (zero_extend:DI
490 (match_operand:SI 2 "s_register_operand" "r,r"))
491 (match_operand:DI 1 "s_register_operand" "r,0")))
492 (clobber (reg:CC CC_REGNUM))]
493 "TARGET_ARM && !TARGET_CIRRUS"
495 "TARGET_ARM && reload_completed"
496 [(parallel [(set (reg:CC_C CC_REGNUM)
497 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
499 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
500 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
501 (plus:SI (match_dup 4) (const_int 0))))]
504 operands[3] = gen_highpart (SImode, operands[0]);
505 operands[0] = gen_lowpart (SImode, operands[0]);
506 operands[4] = gen_highpart (SImode, operands[1]);
507 operands[1] = gen_lowpart (SImode, operands[1]);
508 operands[2] = gen_lowpart (SImode, operands[2]);
510 [(set_attr "conds" "clob")
511 (set_attr "length" "8")]
514 (define_expand "addsi3"
515 [(set (match_operand:SI 0 "s_register_operand" "")
516 (plus:SI (match_operand:SI 1 "s_register_operand" "")
517 (match_operand:SI 2 "reg_or_int_operand" "")))]
520 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
522 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
524 (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
530 ; If there is a scratch available, this will be faster than synthesizing the
533 [(match_scratch:SI 3 "r")
534 (set (match_operand:SI 0 "s_register_operand" "")
535 (plus:SI (match_operand:SI 1 "s_register_operand" "")
536 (match_operand:SI 2 "const_int_operand" "")))]
538 !(const_ok_for_arm (INTVAL (operands[2]))
539 || const_ok_for_arm (-INTVAL (operands[2])))
540 && const_ok_for_arm (~INTVAL (operands[2]))"
541 [(set (match_dup 3) (match_dup 2))
542 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))]
546 (define_insn_and_split "*arm_addsi3"
547 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
548 (plus:SI (match_operand:SI 1 "s_register_operand" "%r,r,r")
549 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
556 GET_CODE (operands[2]) == CONST_INT
557 && !(const_ok_for_arm (INTVAL (operands[2]))
558 || const_ok_for_arm (-INTVAL (operands[2])))"
559 [(clobber (const_int 0))]
561 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
565 [(set_attr "length" "4,4,16")
566 (set_attr "predicable" "yes")]
569 ;; Register group 'k' is a single register group containing only the stack
570 ;; register. Trying to reload it will always fail catastrophically,
571 ;; so never allow those alternatives to match if reloading is needed.
573 (define_insn "*thumb_addsi3"
574 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
575 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
576 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
579 static const char * const asms[] =
581 \"add\\t%0, %0, %2\",
582 \"sub\\t%0, %0, #%n2\",
583 \"add\\t%0, %1, %2\",
584 \"add\\t%0, %0, %2\",
585 \"add\\t%0, %0, %2\",
586 \"add\\t%0, %1, %2\",
589 if ((which_alternative == 2 || which_alternative == 6)
590 && GET_CODE (operands[2]) == CONST_INT
591 && INTVAL (operands[2]) < 0)
592 return \"sub\\t%0, %1, #%n2\";
593 return asms[which_alternative];
595 [(set_attr "length" "2")]
598 ;; Reloading and elimination of the frame pointer can
599 ;; sometimes cause this optimization to be missed.
601 [(set (match_operand:SI 0 "register_operand" "")
602 (match_operand:SI 1 "const_int_operand" ""))
604 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
606 && REGNO (operands[2]) == STACK_POINTER_REGNUM
607 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
608 && (INTVAL (operands[1]) & 3) == 0"
609 [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
613 (define_insn "*addsi3_compare0"
614 [(set (reg:CC_NOOV CC_REGNUM)
616 (plus:SI (match_operand:SI 1 "s_register_operand" "r, r")
617 (match_operand:SI 2 "arm_add_operand" "rI,L"))
619 (set (match_operand:SI 0 "s_register_operand" "=r,r")
620 (plus:SI (match_dup 1) (match_dup 2)))]
624 sub%?s\\t%0, %1, #%n2"
625 [(set_attr "conds" "set")]
628 (define_insn "*addsi3_compare0_scratch"
629 [(set (reg:CC_NOOV CC_REGNUM)
631 (plus:SI (match_operand:SI 0 "s_register_operand" "r, r")
632 (match_operand:SI 1 "arm_add_operand" "rI,L"))
638 [(set_attr "conds" "set")]
641 ;; These patterns are the same ones as the two regular addsi3_compare0
642 ;; patterns, except we write them slightly different - the combiner
643 ;; tends to generate them this way.
644 (define_insn "*addsi3_compare0_for_combiner"
645 [(set (reg:CC CC_REGNUM)
647 (match_operand:SI 1 "s_register_operand" "r,r")
648 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
649 (set (match_operand:SI 0 "s_register_operand" "=r,r")
650 (plus:SI (match_dup 1) (match_dup 2)))]
654 sub%?s\\t%0, %1, #%n2"
655 [(set_attr "conds" "set")]
658 (define_insn "*addsi3_compare0_scratch_for_combiner"
659 [(set (reg:CC CC_REGNUM)
661 (match_operand:SI 0 "s_register_operand" "r,r")
662 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
667 [(set_attr "conds" "set")]
670 ;; This is the canonicalization of addsi3_compare0_for_combiner when the
671 ;; addend is a constant.
672 (define_insn "*cmpsi2_addneg"
673 [(set (reg:CC CC_REGNUM)
675 (match_operand:SI 1 "s_register_operand" "r,r")
676 (match_operand:SI 2 "arm_addimm_operand" "I,L")))
677 (set (match_operand:SI 0 "s_register_operand" "=r,r")
678 (plus:SI (match_dup 1)
679 (match_operand:SI 3 "arm_addimm_operand" "L,I")))]
680 "TARGET_ARM && INTVAL (operands[2]) == -INTVAL (operands[3])"
683 add%?s\\t%0, %1, #%n2"
684 [(set_attr "conds" "set")]
687 ;; Convert the sequence
689 ;; cmn rd, #1 (equivalent to cmp rd, #-1)
693 ;; bcs dest ((unsigned)rn >= 1)
694 ;; similarly for the beq variant using bcc.
695 ;; This is a common looping idiom (while (n--))
697 [(set (match_operand:SI 0 "s_register_operand" "")
698 (plus:SI (match_operand:SI 1 "s_register_operand" "")
700 (set (match_operand 2 "cc_register" "")
701 (compare (match_dup 0) (const_int -1)))
703 (if_then_else (match_operator 3 "equality_operator"
704 [(match_dup 2) (const_int 0)])
705 (match_operand 4 "" "")
706 (match_operand 5 "" "")))]
707 "TARGET_ARM && peep2_reg_dead_p (3, operands[2])"
711 (match_dup 1) (const_int 1)))
712 (set (match_dup 0) (plus:SI (match_dup 1) (const_int -1)))])
714 (if_then_else (match_op_dup 3 [(match_dup 2) (const_int 0)])
717 "operands[2] = gen_rtx_REG (CCmode, CC_REGNUM);
718 operands[3] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
721 operands[2], const0_rtx);"
724 ;; The next four insns work because they compare the result with one of
725 ;; the operands, and we know that the use of the condition code is
726 ;; either GEU or LTU, so we can use the carry flag from the addition
727 ;; instead of doing the compare a second time.
728 (define_insn "*addsi3_compare_op1"
729 [(set (reg:CC_C CC_REGNUM)
731 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
732 (match_operand:SI 2 "arm_add_operand" "rI,L"))
734 (set (match_operand:SI 0 "s_register_operand" "=r,r")
735 (plus:SI (match_dup 1) (match_dup 2)))]
739 sub%?s\\t%0, %1, #%n2"
740 [(set_attr "conds" "set")]
743 (define_insn "*addsi3_compare_op2"
744 [(set (reg:CC_C CC_REGNUM)
746 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
747 (match_operand:SI 2 "arm_add_operand" "rI,L"))
749 (set (match_operand:SI 0 "s_register_operand" "=r,r")
750 (plus:SI (match_dup 1) (match_dup 2)))]
754 sub%?s\\t%0, %1, #%n2"
755 [(set_attr "conds" "set")]
758 (define_insn "*compare_addsi2_op0"
759 [(set (reg:CC_C CC_REGNUM)
761 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
762 (match_operand:SI 1 "arm_add_operand" "rI,L"))
768 [(set_attr "conds" "set")]
771 (define_insn "*compare_addsi2_op1"
772 [(set (reg:CC_C CC_REGNUM)
774 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
775 (match_operand:SI 1 "arm_add_operand" "rI,L"))
781 [(set_attr "conds" "set")]
784 (define_insn "*addsi3_carryin"
785 [(set (match_operand:SI 0 "s_register_operand" "=r")
786 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
787 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
788 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
791 [(set_attr "conds" "use")]
794 (define_insn "*addsi3_carryin_shift"
795 [(set (match_operand:SI 0 "s_register_operand" "")
796 (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
798 (match_operator:SI 2 "shift_operator"
799 [(match_operand:SI 3 "s_register_operand" "")
800 (match_operand:SI 4 "reg_or_int_operand" "")])
801 (match_operand:SI 1 "s_register_operand" ""))))]
803 "adc%?\\t%0, %1, %3%S2"
804 [(set_attr "conds" "use")]
807 (define_insn "*addsi3_carryin_alt1"
808 [(set (match_operand:SI 0 "s_register_operand" "=r")
809 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
810 (match_operand:SI 2 "arm_rhs_operand" "rI"))
811 (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))))]
814 [(set_attr "conds" "use")]
817 (define_insn "*addsi3_carryin_alt2"
818 [(set (match_operand:SI 0 "s_register_operand" "=r")
819 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
820 (match_operand:SI 1 "s_register_operand" "r"))
821 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
824 [(set_attr "conds" "use")]
827 (define_insn "*addsi3_carryin_alt3"
828 [(set (match_operand:SI 0 "s_register_operand" "=r")
829 (plus:SI (plus:SI (ltu:SI (reg:CC_C CC_REGNUM) (const_int 0))
830 (match_operand:SI 2 "arm_rhs_operand" "rI"))
831 (match_operand:SI 1 "s_register_operand" "r")))]
834 [(set_attr "conds" "use")]
837 (define_insn "incscc"
838 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
839 (plus:SI (match_operator:SI 2 "arm_comparison_operator"
840 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
841 (match_operand:SI 1 "s_register_operand" "0,?r")))]
845 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
846 [(set_attr "conds" "use")
847 (set_attr "length" "4,8")]
850 ; 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-accumlate (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-accumlate (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 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "")
1758 (match_operand:SI 2 "const_int_operand" "")
1759 (match_operand:SI 3 "const_int_operand" "")))]
1761 [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))
1762 (set (match_dup 0) (ashiftrt:SI (match_dup 0) (match_dup 3)))]
1764 HOST_WIDE_INT temp = INTVAL (operands[2]);
1766 operands[2] = GEN_INT (32 - temp - INTVAL (operands[3]));
1767 operands[3] = GEN_INT (32 - temp);
1771 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1772 ;;; represented by the bitfield, then this will produce incorrect results.
1773 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1774 ;;; which have a real bit-field insert instruction, the truncation happens
1775 ;;; in the bit-field insert instruction itself. Since arm does not have a
1776 ;;; bit-field insert instruction, we would have to emit code here to truncate
1777 ;;; the value before we insert. This loses some of the advantage of having
1778 ;;; this insv pattern, so this pattern needs to be reevalutated.
1780 (define_expand "insv"
1781 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1782 (match_operand:SI 1 "general_operand" "")
1783 (match_operand:SI 2 "general_operand" ""))
1784 (match_operand:SI 3 "reg_or_int_operand" ""))]
1788 int start_bit = INTVAL (operands[2]);
1789 int width = INTVAL (operands[1]);
1790 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1791 rtx target, subtarget;
1793 target = operands[0];
1794 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1795 subreg as the final target. */
1796 if (GET_CODE (target) == SUBREG)
1798 subtarget = gen_reg_rtx (SImode);
1799 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1800 < GET_MODE_SIZE (SImode))
1801 target = SUBREG_REG (target);
1806 if (GET_CODE (operands[3]) == CONST_INT)
1808 /* Since we are inserting a known constant, we may be able to
1809 reduce the number of bits that we have to clear so that
1810 the mask becomes simple. */
1811 /* ??? This code does not check to see if the new mask is actually
1812 simpler. It may not be. */
1813 rtx op1 = gen_reg_rtx (SImode);
1814 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1815 start of this pattern. */
1816 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1817 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1819 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1820 emit_insn (gen_iorsi3 (subtarget, op1,
1821 GEN_INT (op3_value << start_bit)));
1823 else if (start_bit == 0
1824 && !(const_ok_for_arm (mask)
1825 || const_ok_for_arm (~mask)))
1827 /* A Trick, since we are setting the bottom bits in the word,
1828 we can shift operand[3] up, operand[0] down, OR them together
1829 and rotate the result back again. This takes 3 insns, and
1830 the third might be mergeable into another op. */
1831 /* The shift up copes with the possibility that operand[3] is
1832 wider than the bitfield. */
1833 rtx op0 = gen_reg_rtx (SImode);
1834 rtx op1 = gen_reg_rtx (SImode);
1836 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1837 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1838 emit_insn (gen_iorsi3 (op1, op1, op0));
1839 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1841 else if ((width + start_bit == 32)
1842 && !(const_ok_for_arm (mask)
1843 || const_ok_for_arm (~mask)))
1845 /* Similar trick, but slightly less efficient. */
1847 rtx op0 = gen_reg_rtx (SImode);
1848 rtx op1 = gen_reg_rtx (SImode);
1850 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1851 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1852 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1853 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1857 rtx op0 = GEN_INT (mask);
1858 rtx op1 = gen_reg_rtx (SImode);
1859 rtx op2 = gen_reg_rtx (SImode);
1861 if (!(const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1863 rtx tmp = gen_reg_rtx (SImode);
1865 emit_insn (gen_movsi (tmp, op0));
1869 /* Mask out any bits in operand[3] that are not needed. */
1870 emit_insn (gen_andsi3 (op1, operands[3], op0));
1872 if (GET_CODE (op0) == CONST_INT
1873 && (const_ok_for_arm (mask << start_bit)
1874 || const_ok_for_arm (~(mask << start_bit))))
1876 op0 = GEN_INT (~(mask << start_bit));
1877 emit_insn (gen_andsi3 (op2, operands[0], op0));
1881 if (GET_CODE (op0) == CONST_INT)
1883 rtx tmp = gen_reg_rtx (SImode);
1885 emit_insn (gen_movsi (tmp, op0));
1890 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1892 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1896 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1898 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1901 if (subtarget != target)
1903 /* If TARGET is still a SUBREG, then it must be wider than a word,
1904 so we must be careful only to set the subword we were asked to. */
1905 if (GET_CODE (target) == SUBREG)
1906 emit_move_insn (target, subtarget);
1908 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1915 ; constants for op 2 will never be given to these patterns.
1916 (define_insn_and_split "*anddi_notdi_di"
1917 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1918 (and:DI (not:DI (match_operand:DI 1 "s_register_operand" "r,0"))
1919 (match_operand:DI 2 "s_register_operand" "0,r")))]
1922 "TARGET_ARM && reload_completed && ! IS_IWMMXT_REGNUM (REGNO (operands[0]))"
1923 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1924 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1927 operands[3] = gen_highpart (SImode, operands[0]);
1928 operands[0] = gen_lowpart (SImode, operands[0]);
1929 operands[4] = gen_highpart (SImode, operands[1]);
1930 operands[1] = gen_lowpart (SImode, operands[1]);
1931 operands[5] = gen_highpart (SImode, operands[2]);
1932 operands[2] = gen_lowpart (SImode, operands[2]);
1934 [(set_attr "length" "8")
1935 (set_attr "predicable" "yes")]
1938 (define_insn_and_split "*anddi_notzesidi_di"
1939 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1940 (and:DI (not:DI (zero_extend:DI
1941 (match_operand:SI 2 "s_register_operand" "r,r")))
1942 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1945 bic%?\\t%Q0, %Q1, %2
1947 ; (not (zero_extend ...)) allows us to just copy the high word from
1948 ; operand1 to operand0.
1951 && operands[0] != operands[1]"
1952 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1953 (set (match_dup 3) (match_dup 4))]
1956 operands[3] = gen_highpart (SImode, operands[0]);
1957 operands[0] = gen_lowpart (SImode, operands[0]);
1958 operands[4] = gen_highpart (SImode, operands[1]);
1959 operands[1] = gen_lowpart (SImode, operands[1]);
1961 [(set_attr "length" "4,8")
1962 (set_attr "predicable" "yes")]
1965 (define_insn_and_split "*anddi_notsesidi_di"
1966 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1967 (and:DI (not:DI (sign_extend:DI
1968 (match_operand:SI 2 "s_register_operand" "r,r")))
1969 (match_operand:DI 1 "s_register_operand" "0,r")))]
1972 "TARGET_ARM && reload_completed"
1973 [(set (match_dup 0) (and:SI (not:SI (match_dup 2)) (match_dup 1)))
1974 (set (match_dup 3) (and:SI (not:SI
1975 (ashiftrt:SI (match_dup 2) (const_int 31)))
1979 operands[3] = gen_highpart (SImode, operands[0]);
1980 operands[0] = gen_lowpart (SImode, operands[0]);
1981 operands[4] = gen_highpart (SImode, operands[1]);
1982 operands[1] = gen_lowpart (SImode, operands[1]);
1984 [(set_attr "length" "8")
1985 (set_attr "predicable" "yes")]
1988 (define_insn "andsi_notsi_si"
1989 [(set (match_operand:SI 0 "s_register_operand" "=r")
1990 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1991 (match_operand:SI 1 "s_register_operand" "r")))]
1993 "bic%?\\t%0, %1, %2"
1994 [(set_attr "predicable" "yes")]
1997 (define_insn "bicsi3"
1998 [(set (match_operand:SI 0 "register_operand" "=l")
1999 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
2000 (match_operand:SI 2 "register_operand" "0")))]
2003 [(set_attr "length" "2")]
2006 (define_insn "andsi_not_shiftsi_si"
2007 [(set (match_operand:SI 0 "s_register_operand" "=r")
2008 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
2009 [(match_operand:SI 2 "s_register_operand" "r")
2010 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
2011 (match_operand:SI 1 "s_register_operand" "r")))]
2013 "bic%?\\t%0, %1, %2%S4"
2014 [(set_attr "predicable" "yes")
2015 (set_attr "shift" "2")
2019 (define_insn "*andsi_notsi_si_compare0"
2020 [(set (reg:CC_NOOV CC_REGNUM)
2022 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2023 (match_operand:SI 1 "s_register_operand" "r"))
2025 (set (match_operand:SI 0 "s_register_operand" "=r")
2026 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2028 "bic%?s\\t%0, %1, %2"
2029 [(set_attr "conds" "set")]
2032 (define_insn "*andsi_notsi_si_compare0_scratch"
2033 [(set (reg:CC_NOOV CC_REGNUM)
2035 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2036 (match_operand:SI 1 "s_register_operand" "r"))
2038 (clobber (match_scratch:SI 0 "=r"))]
2040 "bic%?s\\t%0, %1, %2"
2041 [(set_attr "conds" "set")]
2044 (define_insn "iordi3"
2045 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2046 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2047 (match_operand:DI 2 "s_register_operand" "r,r")))]
2048 "TARGET_ARM && ! TARGET_IWMMXT"
2050 [(set_attr "length" "8")
2051 (set_attr "predicable" "yes")]
2054 (define_insn "*iordi_zesidi_di"
2055 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2056 (ior:DI (zero_extend:DI
2057 (match_operand:SI 2 "s_register_operand" "r,r"))
2058 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2061 orr%?\\t%Q0, %Q1, %2
2063 [(set_attr "length" "4,8")
2064 (set_attr "predicable" "yes")]
2067 (define_insn "*iordi_sesidi_di"
2068 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2069 (ior:DI (sign_extend:DI
2070 (match_operand:SI 2 "s_register_operand" "r,r"))
2071 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2074 [(set_attr "length" "8")
2075 (set_attr "predicable" "yes")]
2078 (define_expand "iorsi3"
2079 [(set (match_operand:SI 0 "s_register_operand" "")
2080 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2081 (match_operand:SI 2 "reg_or_int_operand" "")))]
2084 if (GET_CODE (operands[2]) == CONST_INT)
2088 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2091 ? 0 : preserve_subexpressions_p ()));
2094 else /* TARGET_THUMB */
2095 operands [2] = force_reg (SImode, operands [2]);
2100 (define_insn_and_split "*arm_iorsi3"
2101 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2102 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2103 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2109 && GET_CODE (operands[2]) == CONST_INT
2110 && !const_ok_for_arm (INTVAL (operands[2]))"
2111 [(clobber (const_int 0))]
2113 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2117 [(set_attr "length" "4,16")
2118 (set_attr "predicable" "yes")]
2121 (define_insn "*thumb_iorsi3"
2122 [(set (match_operand:SI 0 "register_operand" "=l")
2123 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2124 (match_operand:SI 2 "register_operand" "l")))]
2127 [(set_attr "length" "2")]
2131 [(match_scratch:SI 3 "r")
2132 (set (match_operand:SI 0 "s_register_operand" "")
2133 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2134 (match_operand:SI 2 "const_int_operand" "")))]
2136 && !const_ok_for_arm (INTVAL (operands[2]))
2137 && const_ok_for_arm (~INTVAL (operands[2]))"
2138 [(set (match_dup 3) (match_dup 2))
2139 (set (match_dup 0) (ior:SI (match_dup 1) (match_dup 3)))]
2143 (define_insn "*iorsi3_compare0"
2144 [(set (reg:CC_NOOV CC_REGNUM)
2145 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2146 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2148 (set (match_operand:SI 0 "s_register_operand" "=r")
2149 (ior:SI (match_dup 1) (match_dup 2)))]
2151 "orr%?s\\t%0, %1, %2"
2152 [(set_attr "conds" "set")]
2155 (define_insn "*iorsi3_compare0_scratch"
2156 [(set (reg:CC_NOOV CC_REGNUM)
2157 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2158 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2160 (clobber (match_scratch:SI 0 "=r"))]
2162 "orr%?s\\t%0, %1, %2"
2163 [(set_attr "conds" "set")]
2166 (define_insn "xordi3"
2167 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2168 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2169 (match_operand:DI 2 "s_register_operand" "r,r")))]
2170 "TARGET_ARM && !TARGET_IWMMXT"
2172 [(set_attr "length" "8")
2173 (set_attr "predicable" "yes")]
2176 (define_insn "*xordi_zesidi_di"
2177 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2178 (xor:DI (zero_extend:DI
2179 (match_operand:SI 2 "s_register_operand" "r,r"))
2180 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2183 eor%?\\t%Q0, %Q1, %2
2185 [(set_attr "length" "4,8")
2186 (set_attr "predicable" "yes")]
2189 (define_insn "*xordi_sesidi_di"
2190 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2191 (xor:DI (sign_extend:DI
2192 (match_operand:SI 2 "s_register_operand" "r,r"))
2193 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2196 [(set_attr "length" "8")
2197 (set_attr "predicable" "yes")]
2200 (define_expand "xorsi3"
2201 [(set (match_operand:SI 0 "s_register_operand" "")
2202 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2203 (match_operand:SI 2 "arm_rhs_operand" "")))]
2206 if (GET_CODE (operands[2]) == CONST_INT)
2207 operands[2] = force_reg (SImode, operands[2]);
2211 (define_insn "*arm_xorsi3"
2212 [(set (match_operand:SI 0 "s_register_operand" "=r")
2213 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2214 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2216 "eor%?\\t%0, %1, %2"
2217 [(set_attr "predicable" "yes")]
2220 (define_insn "*thumb_xorsi3"
2221 [(set (match_operand:SI 0 "register_operand" "=l")
2222 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2223 (match_operand:SI 2 "register_operand" "l")))]
2226 [(set_attr "length" "2")]
2229 (define_insn "*xorsi3_compare0"
2230 [(set (reg:CC_NOOV CC_REGNUM)
2231 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2232 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2234 (set (match_operand:SI 0 "s_register_operand" "=r")
2235 (xor:SI (match_dup 1) (match_dup 2)))]
2237 "eor%?s\\t%0, %1, %2"
2238 [(set_attr "conds" "set")]
2241 (define_insn "*xorsi3_compare0_scratch"
2242 [(set (reg:CC_NOOV CC_REGNUM)
2243 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2244 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2248 [(set_attr "conds" "set")]
2251 ; By splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2252 ; (NOT D) we can sometimes merge the final NOT into one of the following
2256 [(set (match_operand:SI 0 "s_register_operand" "")
2257 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" ""))
2258 (not:SI (match_operand:SI 2 "arm_rhs_operand" "")))
2259 (match_operand:SI 3 "arm_rhs_operand" "")))
2260 (clobber (match_operand:SI 4 "s_register_operand" ""))]
2262 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2263 (not:SI (match_dup 3))))
2264 (set (match_dup 0) (not:SI (match_dup 4)))]
2268 (define_insn "*andsi_iorsi3_notsi"
2269 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2270 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2271 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2272 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2274 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2275 [(set_attr "length" "8")
2276 (set_attr "predicable" "yes")]
2281 ;; Minimum and maximum insns
2283 (define_insn "smaxsi3"
2284 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2285 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2286 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2287 (clobber (reg:CC CC_REGNUM))]
2290 cmp\\t%1, %2\;movlt\\t%0, %2
2291 cmp\\t%1, %2\;movge\\t%0, %1
2292 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2293 [(set_attr "conds" "clob")
2294 (set_attr "length" "8,8,12")]
2297 (define_insn "sminsi3"
2298 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2299 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2300 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2301 (clobber (reg:CC CC_REGNUM))]
2304 cmp\\t%1, %2\;movge\\t%0, %2
2305 cmp\\t%1, %2\;movlt\\t%0, %1
2306 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2307 [(set_attr "conds" "clob")
2308 (set_attr "length" "8,8,12")]
2311 (define_insn "umaxsi3"
2312 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2313 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2314 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2315 (clobber (reg:CC CC_REGNUM))]
2318 cmp\\t%1, %2\;movcc\\t%0, %2
2319 cmp\\t%1, %2\;movcs\\t%0, %1
2320 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2321 [(set_attr "conds" "clob")
2322 (set_attr "length" "8,8,12")]
2325 (define_insn "uminsi3"
2326 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2327 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2328 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2329 (clobber (reg:CC CC_REGNUM))]
2332 cmp\\t%1, %2\;movcs\\t%0, %2
2333 cmp\\t%1, %2\;movcc\\t%0, %1
2334 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2335 [(set_attr "conds" "clob")
2336 (set_attr "length" "8,8,12")]
2339 (define_insn "*store_minmaxsi"
2340 [(set (match_operand:SI 0 "memory_operand" "=m")
2341 (match_operator:SI 3 "minmax_operator"
2342 [(match_operand:SI 1 "s_register_operand" "r")
2343 (match_operand:SI 2 "s_register_operand" "r")]))
2344 (clobber (reg:CC CC_REGNUM))]
2347 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2349 output_asm_insn (\"cmp\\t%1, %2\", operands);
2350 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2351 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2354 [(set_attr "conds" "clob")
2355 (set_attr "length" "12")
2356 (set_attr "type" "store1")]
2359 ; Reject the frame pointer in operand[1], since reloading this after
2360 ; it has been eliminated can cause carnage.
2361 (define_insn "*minmax_arithsi"
2362 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2363 (match_operator:SI 4 "shiftable_operator"
2364 [(match_operator:SI 5 "minmax_operator"
2365 [(match_operand:SI 2 "s_register_operand" "r,r")
2366 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2367 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2368 (clobber (reg:CC CC_REGNUM))]
2370 && (GET_CODE (operands[1]) != REG
2371 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2372 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2375 enum rtx_code code = GET_CODE (operands[4]);
2377 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2379 output_asm_insn (\"cmp\\t%2, %3\", operands);
2380 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2381 if (which_alternative != 0 || operands[3] != const0_rtx
2382 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2383 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2386 [(set_attr "conds" "clob")
2387 (set_attr "length" "12")]
2391 ;; Shift and rotation insns
2393 (define_expand "ashlsi3"
2394 [(set (match_operand:SI 0 "s_register_operand" "")
2395 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2396 (match_operand:SI 2 "arm_rhs_operand" "")))]
2399 if (GET_CODE (operands[2]) == CONST_INT
2400 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2402 emit_insn (gen_movsi (operands[0], const0_rtx));
2408 (define_insn "*thumb_ashlsi3"
2409 [(set (match_operand:SI 0 "register_operand" "=l,l")
2410 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2411 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2414 [(set_attr "length" "2")]
2417 (define_expand "ashrsi3"
2418 [(set (match_operand:SI 0 "s_register_operand" "")
2419 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2420 (match_operand:SI 2 "arm_rhs_operand" "")))]
2423 if (GET_CODE (operands[2]) == CONST_INT
2424 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2425 operands[2] = GEN_INT (31);
2429 (define_insn "*thumb_ashrsi3"
2430 [(set (match_operand:SI 0 "register_operand" "=l,l")
2431 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2432 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2435 [(set_attr "length" "2")]
2438 (define_expand "lshrsi3"
2439 [(set (match_operand:SI 0 "s_register_operand" "")
2440 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2441 (match_operand:SI 2 "arm_rhs_operand" "")))]
2444 if (GET_CODE (operands[2]) == CONST_INT
2445 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2447 emit_insn (gen_movsi (operands[0], const0_rtx));
2453 (define_insn "*thumb_lshrsi3"
2454 [(set (match_operand:SI 0 "register_operand" "=l,l")
2455 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2456 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2459 [(set_attr "length" "2")]
2462 (define_expand "rotlsi3"
2463 [(set (match_operand:SI 0 "s_register_operand" "")
2464 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2465 (match_operand:SI 2 "reg_or_int_operand" "")))]
2468 if (GET_CODE (operands[2]) == CONST_INT)
2469 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2472 rtx reg = gen_reg_rtx (SImode);
2473 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2479 (define_expand "rotrsi3"
2480 [(set (match_operand:SI 0 "s_register_operand" "")
2481 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2482 (match_operand:SI 2 "arm_rhs_operand" "")))]
2487 if (GET_CODE (operands[2]) == CONST_INT
2488 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2489 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2491 else /* TARGET_THUMB */
2493 if (GET_CODE (operands [2]) == CONST_INT)
2494 operands [2] = force_reg (SImode, operands[2]);
2499 (define_insn "*thumb_rotrsi3"
2500 [(set (match_operand:SI 0 "register_operand" "=l")
2501 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2502 (match_operand:SI 2 "register_operand" "l")))]
2505 [(set_attr "length" "2")]
2508 (define_expand "ashldi3"
2509 [(set (match_operand:DI 0 "s_register_operand" "")
2510 (ashift:DI (match_operand:DI 1 "general_operand" "")
2511 (match_operand:SI 2 "general_operand" "")))]
2512 "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)"
2514 if (! s_register_operand (operands[1], DImode))
2515 operands[1] = copy_to_mode_reg (DImode, operands[1]);
2516 if (! s_register_operand (operands[2], SImode))
2517 operands[2] = copy_to_mode_reg (SImode, operands[2]);
2521 (define_insn "*arm_shiftsi3"
2522 [(set (match_operand:SI 0 "s_register_operand" "=r")
2523 (match_operator:SI 3 "shift_operator"
2524 [(match_operand:SI 1 "s_register_operand" "r")
2525 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2528 [(set_attr "predicable" "yes")
2529 (set_attr "shift" "1")
2533 (define_insn "*shiftsi3_compare0"
2534 [(set (reg:CC_NOOV CC_REGNUM)
2535 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2536 [(match_operand:SI 1 "s_register_operand" "r")
2537 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2539 (set (match_operand:SI 0 "s_register_operand" "=r")
2540 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2542 "mov%?s\\t%0, %1%S3"
2543 [(set_attr "conds" "set")
2544 (set_attr "shift" "1")
2548 (define_insn "*shiftsi3_compare0_scratch"
2549 [(set (reg:CC_NOOV CC_REGNUM)
2550 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2551 [(match_operand:SI 1 "s_register_operand" "r")
2552 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2554 (clobber (match_scratch:SI 0 "=r"))]
2556 "mov%?s\\t%0, %1%S3"
2557 [(set_attr "conds" "set")
2558 (set_attr "shift" "1")
2562 (define_insn "*notsi_shiftsi"
2563 [(set (match_operand:SI 0 "s_register_operand" "=r")
2564 (not:SI (match_operator:SI 3 "shift_operator"
2565 [(match_operand:SI 1 "s_register_operand" "r")
2566 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2569 [(set_attr "predicable" "yes")
2570 (set_attr "shift" "1")
2574 (define_insn "*notsi_shiftsi_compare0"
2575 [(set (reg:CC_NOOV CC_REGNUM)
2576 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2577 [(match_operand:SI 1 "s_register_operand" "r")
2578 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2580 (set (match_operand:SI 0 "s_register_operand" "=r")
2581 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2583 "mvn%?s\\t%0, %1%S3"
2584 [(set_attr "conds" "set")
2585 (set_attr "shift" "1")
2589 (define_insn "*not_shiftsi_compare0_scratch"
2590 [(set (reg:CC_NOOV CC_REGNUM)
2591 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2592 [(match_operand:SI 1 "s_register_operand" "r")
2593 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2595 (clobber (match_scratch:SI 0 "=r"))]
2597 "mvn%?s\\t%0, %1%S3"
2598 [(set_attr "conds" "set")
2599 (set_attr "shift" "1")
2603 ;; We don't really have extzv, but defining this using shifts helps
2604 ;; to reduce register pressure later on.
2606 (define_expand "extzv"
2608 (ashift:SI (match_operand:SI 1 "register_operand" "")
2609 (match_operand:SI 2 "const_int_operand" "")))
2610 (set (match_operand:SI 0 "register_operand" "")
2611 (lshiftrt:SI (match_dup 4)
2612 (match_operand:SI 3 "const_int_operand" "")))]
2616 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2617 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2619 operands[3] = GEN_INT (rshift);
2623 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2627 operands[2] = GEN_INT (lshift);
2628 operands[4] = gen_reg_rtx (SImode);
2633 ;; Unary arithmetic insns
2635 (define_expand "negdi2"
2637 [(set (match_operand:DI 0 "s_register_operand" "")
2638 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2639 (clobber (reg:CC CC_REGNUM))])]
2644 if (GET_CODE (operands[1]) != REG)
2645 operands[1] = force_reg (SImode, operands[1]);
2650 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2651 ;; The second alternative is to allow the common case of a *full* overlap.
2652 (define_insn "*arm_negdi2"
2653 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2654 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2655 (clobber (reg:CC CC_REGNUM))]
2657 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2658 [(set_attr "conds" "clob")
2659 (set_attr "length" "8")]
2662 (define_insn "*thumb_negdi2"
2663 [(set (match_operand:DI 0 "register_operand" "=&l")
2664 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2665 (clobber (reg:CC CC_REGNUM))]
2667 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2668 [(set_attr "length" "6")]
2671 (define_expand "negsi2"
2672 [(set (match_operand:SI 0 "s_register_operand" "")
2673 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2678 (define_insn "*arm_negsi2"
2679 [(set (match_operand:SI 0 "s_register_operand" "=r")
2680 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2682 "rsb%?\\t%0, %1, #0"
2683 [(set_attr "predicable" "yes")]
2686 (define_insn "*thumb_negsi2"
2687 [(set (match_operand:SI 0 "register_operand" "=l")
2688 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2691 [(set_attr "length" "2")]
2694 (define_expand "negsf2"
2695 [(set (match_operand:SF 0 "s_register_operand" "")
2696 (neg:SF (match_operand:SF 1 "s_register_operand" "")))]
2697 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2701 (define_expand "negdf2"
2702 [(set (match_operand:DF 0 "s_register_operand" "")
2703 (neg:DF (match_operand:DF 1 "s_register_operand" "")))]
2704 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2707 ;; abssi2 doesn't really clobber the condition codes if a different register
2708 ;; is being set. To keep things simple, assume during rtl manipulations that
2709 ;; it does, but tell the final scan operator the truth. Similarly for
2712 (define_expand "abssi2"
2714 [(set (match_operand:SI 0 "s_register_operand" "")
2715 (abs:SI (match_operand:SI 1 "s_register_operand" "")))
2716 (clobber (reg:CC CC_REGNUM))])]
2720 (define_insn "*arm_abssi2"
2721 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2722 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2723 (clobber (reg:CC CC_REGNUM))]
2726 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2727 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2728 [(set_attr "conds" "clob,*")
2729 (set_attr "shift" "1")
2730 ;; predicable can't be set based on the variant, so left as no
2731 (set_attr "length" "8")]
2734 (define_insn "*neg_abssi2"
2735 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2736 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2737 (clobber (reg:CC CC_REGNUM))]
2740 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2741 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2742 [(set_attr "conds" "clob,*")
2743 (set_attr "shift" "1")
2744 ;; predicable can't be set based on the variant, so left as no
2745 (set_attr "length" "8")]
2748 (define_expand "abssf2"
2749 [(set (match_operand:SF 0 "s_register_operand" "")
2750 (abs:SF (match_operand:SF 1 "s_register_operand" "")))]
2751 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2754 (define_expand "absdf2"
2755 [(set (match_operand:DF 0 "s_register_operand" "")
2756 (abs:DF (match_operand:DF 1 "s_register_operand" "")))]
2757 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2760 (define_expand "sqrtsf2"
2761 [(set (match_operand:SF 0 "s_register_operand" "")
2762 (sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
2763 "TARGET_ARM && TARGET_HARD_FLOAT"
2766 (define_expand "sqrtdf2"
2767 [(set (match_operand:DF 0 "s_register_operand" "")
2768 (sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
2769 "TARGET_ARM && TARGET_HARD_FLOAT"
2772 (define_insn_and_split "one_cmpldi2"
2773 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2774 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2777 "TARGET_ARM && reload_completed"
2778 [(set (match_dup 0) (not:SI (match_dup 1)))
2779 (set (match_dup 2) (not:SI (match_dup 3)))]
2782 operands[2] = gen_highpart (SImode, operands[0]);
2783 operands[0] = gen_lowpart (SImode, operands[0]);
2784 operands[3] = gen_highpart (SImode, operands[1]);
2785 operands[1] = gen_lowpart (SImode, operands[1]);
2787 [(set_attr "length" "8")
2788 (set_attr "predicable" "yes")]
2791 (define_expand "one_cmplsi2"
2792 [(set (match_operand:SI 0 "s_register_operand" "")
2793 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2798 (define_insn "*arm_one_cmplsi2"
2799 [(set (match_operand:SI 0 "s_register_operand" "=r")
2800 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2803 [(set_attr "predicable" "yes")]
2806 (define_insn "*thumb_one_cmplsi2"
2807 [(set (match_operand:SI 0 "register_operand" "=l")
2808 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2811 [(set_attr "length" "2")]
2814 (define_insn "*notsi_compare0"
2815 [(set (reg:CC_NOOV CC_REGNUM)
2816 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2818 (set (match_operand:SI 0 "s_register_operand" "=r")
2819 (not:SI (match_dup 1)))]
2822 [(set_attr "conds" "set")]
2825 (define_insn "*notsi_compare0_scratch"
2826 [(set (reg:CC_NOOV CC_REGNUM)
2827 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2829 (clobber (match_scratch:SI 0 "=r"))]
2832 [(set_attr "conds" "set")]
2835 ;; Fixed <--> Floating conversion insns
2837 (define_expand "floatsisf2"
2838 [(set (match_operand:SF 0 "s_register_operand" "")
2839 (float:SF (match_operand:SI 1 "s_register_operand" "")))]
2840 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2844 emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
2849 (define_expand "floatsidf2"
2850 [(set (match_operand:DF 0 "s_register_operand" "")
2851 (float:DF (match_operand:SI 1 "s_register_operand" "")))]
2852 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2856 emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
2861 (define_expand "fix_truncsfsi2"
2862 [(set (match_operand:SI 0 "s_register_operand" "")
2863 (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
2864 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2868 if (!cirrus_fp_register (operands[0], SImode))
2869 operands[0] = force_reg (SImode, operands[0]);
2870 if (!cirrus_fp_register (operands[1], SFmode))
2871 operands[1] = force_reg (SFmode, operands[0]);
2872 emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
2877 (define_expand "fix_truncdfsi2"
2878 [(set (match_operand:SI 0 "s_register_operand" "")
2879 (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
2880 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2884 if (!cirrus_fp_register (operands[1], DFmode))
2885 operands[1] = force_reg (DFmode, operands[0]);
2886 emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
2893 (define_expand "truncdfsf2"
2894 [(set (match_operand:SF 0 "s_register_operand" "")
2896 (match_operand:DF 1 "s_register_operand" "")))]
2897 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
2901 ;; Zero and sign extension instructions.
2903 (define_insn "zero_extendsidi2"
2904 [(set (match_operand:DI 0 "s_register_operand" "=r")
2905 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2908 if (REGNO (operands[1])
2909 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2910 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2911 return \"mov%?\\t%R0, #0\";
2913 [(set_attr "length" "8")
2914 (set_attr "predicable" "yes")]
2917 (define_insn "zero_extendqidi2"
2918 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2919 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2922 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2923 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2924 [(set_attr "length" "8")
2925 (set_attr "predicable" "yes")
2926 (set_attr "type" "*,load")
2927 (set_attr "pool_range" "*,4092")
2928 (set_attr "neg_pool_range" "*,4084")]
2931 (define_insn "extendsidi2"
2932 [(set (match_operand:DI 0 "s_register_operand" "=r")
2933 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2936 if (REGNO (operands[1])
2937 != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2938 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2939 return \"mov%?\\t%R0, %Q0, asr #31\";
2941 [(set_attr "length" "8")
2942 (set_attr "shift" "1")
2943 (set_attr "predicable" "yes")]
2946 (define_expand "zero_extendhisi2"
2948 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2950 (set (match_operand:SI 0 "s_register_operand" "")
2951 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2957 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2959 /* Note: We do not have to worry about TARGET_MMU_TRAPS
2960 here because the insn below will generate an LDRH instruction
2961 rather than an LDR instruction, so we cannot get an unaligned
2963 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2964 gen_rtx_ZERO_EXTEND (SImode,
2968 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2970 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2973 if (!s_register_operand (operands[1], HImode))
2974 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2975 operands[1] = gen_lowpart (SImode, operands[1]);
2976 operands[2] = gen_reg_rtx (SImode);
2978 else /* TARGET_THUMB */
2980 if (GET_CODE (operands[1]) == MEM)
2984 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
2985 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
2992 if (!s_register_operand (operands[1], HImode))
2993 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2994 operands[1] = gen_lowpart (SImode, operands[1]);
2995 operands[2] = gen_reg_rtx (SImode);
2997 ops[0] = operands[2];
2998 ops[1] = operands[1];
2999 ops[2] = GEN_INT (16);
3001 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3002 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3004 ops[0] = operands[0];
3005 ops[1] = operands[2];
3006 ops[2] = GEN_INT (16);
3008 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3009 gen_rtx_LSHIFTRT (SImode, ops[1],
3017 (define_insn "*thumb_zero_extendhisi2"
3018 [(set (match_operand:SI 0 "register_operand" "=l")
3019 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3022 rtx mem = XEXP (operands[1], 0);
3024 if (GET_CODE (mem) == CONST)
3025 mem = XEXP (mem, 0);
3027 if (GET_CODE (mem) == LABEL_REF)
3028 return \"ldr\\t%0, %1\";
3030 if (GET_CODE (mem) == PLUS)
3032 rtx a = XEXP (mem, 0);
3033 rtx b = XEXP (mem, 1);
3035 /* This can happen due to bugs in reload. */
3036 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3039 ops[0] = operands[0];
3042 output_asm_insn (\"mov %0, %1\", ops);
3044 XEXP (mem, 0) = operands[0];
3047 else if ( GET_CODE (a) == LABEL_REF
3048 && GET_CODE (b) == CONST_INT)
3049 return \"ldr\\t%0, %1\";
3052 return \"ldrh\\t%0, %1\";
3054 [(set_attr "length" "4")
3055 (set_attr "type" "load")
3056 (set_attr "pool_range" "60")]
3059 (define_insn "*arm_zero_extendhisi2"
3060 [(set (match_operand:SI 0 "s_register_operand" "=r")
3061 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3062 "TARGET_ARM && arm_arch4"
3064 [(set_attr "type" "load")
3065 (set_attr "predicable" "yes")
3066 (set_attr "pool_range" "256")
3067 (set_attr "neg_pool_range" "244")]
3071 [(set (match_operand:SI 0 "s_register_operand" "")
3072 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3073 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3074 "TARGET_ARM && (!arm_arch4)"
3075 [(set (match_dup 2) (match_dup 1))
3076 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3078 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3084 [(set (match_operand:SI 0 "s_register_operand" "")
3085 (match_operator:SI 3 "shiftable_operator"
3086 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3087 (match_operand:SI 4 "s_register_operand" "")]))
3088 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3089 "TARGET_ARM && (!arm_arch4)"
3090 [(set (match_dup 2) (match_dup 1))
3093 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3095 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3100 (define_expand "zero_extendqisi2"
3101 [(set (match_operand:SI 0 "s_register_operand" "")
3102 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3105 if (GET_CODE (operands[1]) != MEM)
3109 emit_insn (gen_andsi3 (operands[0],
3110 gen_lowpart (SImode, operands[1]),
3113 else /* TARGET_THUMB */
3115 rtx temp = gen_reg_rtx (SImode);
3118 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3119 operands[1] = gen_lowpart (SImode, operands[1]);
3122 ops[1] = operands[1];
3123 ops[2] = GEN_INT (24);
3125 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3126 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3128 ops[0] = operands[0];
3130 ops[2] = GEN_INT (24);
3132 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3133 gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3140 (define_insn "*thumb_zero_extendqisi2"
3141 [(set (match_operand:SI 0 "register_operand" "=l")
3142 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3145 [(set_attr "length" "2")
3146 (set_attr "type" "load")
3147 (set_attr "pool_range" "32")]
3150 (define_insn "*arm_zero_extendqisi2"
3151 [(set (match_operand:SI 0 "s_register_operand" "=r")
3152 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3154 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3155 [(set_attr "type" "load")
3156 (set_attr "predicable" "yes")
3157 (set_attr "pool_range" "4096")
3158 (set_attr "neg_pool_range" "4084")]
3162 [(set (match_operand:SI 0 "s_register_operand" "")
3163 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3164 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3165 "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && ! BYTES_BIG_ENDIAN"
3166 [(set (match_dup 2) (match_dup 1))
3167 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3171 (define_insn "*compareqi_eq0"
3172 [(set (reg:CC_Z CC_REGNUM)
3173 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3177 [(set_attr "conds" "set")]
3180 (define_expand "extendhisi2"
3182 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3184 (set (match_operand:SI 0 "s_register_operand" "")
3185 (ashiftrt:SI (match_dup 2)
3190 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3192 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3193 here because the insn below will generate an LDRH instruction
3194 rather than an LDR instruction, so we cannot get an unaligned
3196 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3197 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3201 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3203 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3206 if (!s_register_operand (operands[1], HImode))
3207 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3208 operands[1] = gen_lowpart (SImode, operands[1]);
3209 operands[2] = gen_reg_rtx (SImode);
3215 ops[0] = operands[2];
3216 ops[1] = operands[1];
3217 ops[2] = GEN_INT (16);
3219 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3220 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3222 ops[0] = operands[0];
3223 ops[1] = operands[2];
3224 ops[2] = GEN_INT (16);
3226 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3227 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3234 (define_insn "*thumb_extendhisi2_insn"
3235 [(set (match_operand:SI 0 "register_operand" "=l")
3236 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3237 (clobber (match_scratch:SI 2 "=&l"))]
3242 rtx mem = XEXP (operands[1], 0);
3244 /* This code used to try to use 'V', and fix the address only if it was
3245 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3246 range of QImode offsets, and offsettable_address_p does a QImode
3249 if (GET_CODE (mem) == CONST)
3250 mem = XEXP (mem, 0);
3252 if (GET_CODE (mem) == LABEL_REF)
3253 return \"ldr\\t%0, %1\";
3255 if (GET_CODE (mem) == PLUS)
3257 rtx a = XEXP (mem, 0);
3258 rtx b = XEXP (mem, 1);
3260 if (GET_CODE (a) == LABEL_REF
3261 && GET_CODE (b) == CONST_INT)
3262 return \"ldr\\t%0, %1\";
3264 if (GET_CODE (b) == REG)
3265 return \"ldrsh\\t%0, %1\";
3273 ops[2] = const0_rtx;
3276 if (GET_CODE (ops[1]) != REG)
3282 ops[0] = operands[0];
3283 ops[3] = operands[2];
3284 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3287 [(set_attr "length" "4")
3288 (set_attr "type" "load")
3289 (set_attr "pool_range" "1020")]
3292 (define_expand "extendhisi2_mem"
3293 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3295 (zero_extend:SI (match_dup 7)))
3296 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3297 (set (match_operand:SI 0 "" "")
3298 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3303 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3305 mem1 = gen_rtx_MEM (QImode, addr);
3306 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3307 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3308 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3309 operands[0] = gen_lowpart (SImode, operands[0]);
3311 operands[2] = gen_reg_rtx (SImode);
3312 operands[3] = gen_reg_rtx (SImode);
3313 operands[6] = gen_reg_rtx (SImode);
3316 if (BYTES_BIG_ENDIAN)
3318 operands[4] = operands[2];
3319 operands[5] = operands[3];
3323 operands[4] = operands[3];
3324 operands[5] = operands[2];
3329 (define_insn "*arm_extendhisi_insn"
3330 [(set (match_operand:SI 0 "s_register_operand" "=r")
3331 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3332 "TARGET_ARM && arm_arch4"
3334 [(set_attr "type" "load")
3335 (set_attr "predicable" "yes")
3336 (set_attr "pool_range" "256")
3337 (set_attr "neg_pool_range" "244")]
3341 [(set (match_operand:SI 0 "s_register_operand" "")
3342 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3343 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3344 "TARGET_ARM && (!arm_arch4)"
3345 [(set (match_dup 2) (match_dup 1))
3346 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3348 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3354 [(set (match_operand:SI 0 "s_register_operand" "")
3355 (match_operator:SI 3 "shiftable_operator"
3356 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3357 (match_operand:SI 4 "s_register_operand" "")]))
3358 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3359 "TARGET_ARM && (!arm_arch4)"
3360 [(set (match_dup 2) (match_dup 1))
3363 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3364 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3369 (define_expand "extendqihi2"
3371 (ashift:SI (match_operand:QI 1 "general_operand" "")
3373 (set (match_operand:HI 0 "s_register_operand" "")
3374 (ashiftrt:SI (match_dup 2)
3379 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3381 emit_insn (gen_rtx_SET (VOIDmode,
3383 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3386 if (!s_register_operand (operands[1], QImode))
3387 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3388 operands[0] = gen_lowpart (SImode, operands[0]);
3389 operands[1] = gen_lowpart (SImode, operands[1]);
3390 operands[2] = gen_reg_rtx (SImode);
3394 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3395 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3396 (define_insn "*extendqihi_insn"
3397 [(set (match_operand:HI 0 "s_register_operand" "=r")
3398 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3399 "TARGET_ARM && arm_arch4"
3401 /* If the address is invalid, this will split the instruction into two. */
3402 if (bad_signed_byte_operand (operands[1], VOIDmode))
3404 return \"ldr%?sb\\t%0, %1\";
3406 [(set_attr "type" "load")
3407 (set_attr "predicable" "yes")
3408 (set_attr "length" "8")
3409 (set_attr "pool_range" "256")
3410 (set_attr "neg_pool_range" "244")]
3414 [(set (match_operand:HI 0 "s_register_operand" "")
3415 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3416 "TARGET_ARM && arm_arch4 && reload_completed"
3417 [(set (match_dup 3) (match_dup 1))
3418 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3421 HOST_WIDE_INT offset;
3423 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3424 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3425 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3426 operands[1] = XEXP (operands[1], 0);
3427 if (GET_CODE (operands[1]) == PLUS
3428 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3429 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3430 || const_ok_for_arm (-offset)))
3432 HOST_WIDE_INT low = (offset > 0
3433 ? (offset & 0xff) : -((-offset) & 0xff));
3434 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3435 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3437 /* Ensure the sum is in correct canonical form */
3438 else if (GET_CODE (operands[1]) == PLUS
3439 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3440 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3441 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3442 XEXP (operands[1], 1),
3443 XEXP (operands[1], 0));
3447 (define_expand "extendqisi2"
3449 (ashift:SI (match_operand:QI 1 "general_operand" "")
3451 (set (match_operand:SI 0 "s_register_operand" "")
3452 (ashiftrt:SI (match_dup 2)
3457 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3459 emit_insn (gen_rtx_SET (VOIDmode,
3461 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3464 if (!s_register_operand (operands[1], QImode))
3465 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3466 operands[1] = gen_lowpart (SImode, operands[1]);
3467 operands[2] = gen_reg_rtx (SImode);
3473 ops[0] = operands[2];
3474 ops[1] = operands[1];
3475 ops[2] = GEN_INT (24);
3477 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3478 gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3480 ops[0] = operands[0];
3481 ops[1] = operands[2];
3482 ops[2] = GEN_INT (24);
3484 emit_insn (gen_rtx_SET (VOIDmode, ops[0],
3485 gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3492 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3493 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3494 (define_insn "*arm_extendqisi_insn"
3495 [(set (match_operand:SI 0 "s_register_operand" "=r")
3496 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3497 "TARGET_ARM && arm_arch4"
3499 /* If the address is invalid, this will split the instruction into two. */
3500 if (bad_signed_byte_operand (operands[1], VOIDmode))
3502 return \"ldr%?sb\\t%0, %1\";
3504 [(set_attr "type" "load")
3505 (set_attr "predicable" "yes")
3506 (set_attr "length" "8")
3507 (set_attr "pool_range" "256")
3508 (set_attr "neg_pool_range" "244")]
3512 [(set (match_operand:SI 0 "s_register_operand" "")
3513 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3514 "TARGET_ARM && arm_arch4 && reload_completed"
3515 [(set (match_dup 0) (match_dup 1))
3516 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3519 HOST_WIDE_INT offset;
3521 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3522 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3523 operands[1] = XEXP (operands[1], 0);
3524 if (GET_CODE (operands[1]) == PLUS
3525 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3526 && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3527 || const_ok_for_arm (-offset)))
3529 HOST_WIDE_INT low = (offset > 0
3530 ? (offset & 0xff) : -((-offset) & 0xff));
3531 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3532 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3534 /* Ensure the sum is in correct canonical form */
3535 else if (GET_CODE (operands[1]) == PLUS
3536 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3537 && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
3538 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3539 XEXP (operands[1], 1),
3540 XEXP (operands[1], 0));
3544 (define_insn "*thumb_extendqisi2_insn"
3545 [(set (match_operand:SI 0 "register_operand" "=l,l")
3546 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3551 rtx mem = XEXP (operands[1], 0);
3553 if (GET_CODE (mem) == CONST)
3554 mem = XEXP (mem, 0);
3556 if (GET_CODE (mem) == LABEL_REF)
3557 return \"ldr\\t%0, %1\";
3559 if (GET_CODE (mem) == PLUS
3560 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3561 return \"ldr\\t%0, %1\";
3563 if (which_alternative == 0)
3564 return \"ldrsb\\t%0, %1\";
3566 ops[0] = operands[0];
3568 if (GET_CODE (mem) == PLUS)
3570 rtx a = XEXP (mem, 0);
3571 rtx b = XEXP (mem, 1);
3576 if (GET_CODE (a) == REG)
3578 if (GET_CODE (b) == REG)
3579 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3580 else if (REGNO (a) == REGNO (ops[0]))
3582 output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
3583 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3584 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3587 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3589 else if (GET_CODE (b) != REG)
3593 if (REGNO (b) == REGNO (ops[0]))
3595 output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
3596 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3597 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3600 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3603 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3605 output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
3606 output_asm_insn (\"lsl\\t%0, %0, #24\", ops);
3607 output_asm_insn (\"asr\\t%0, %0, #24\", ops);
3612 ops[2] = const0_rtx;
3614 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3618 [(set_attr "length" "2,6")
3619 (set_attr "type" "load,load")
3620 (set_attr "pool_range" "32,32")]
3623 (define_expand "extendsfdf2"
3624 [(set (match_operand:DF 0 "s_register_operand" "")
3625 (float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
3626 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
3630 ;; Move insns (including loads and stores)
3632 ;; XXX Just some ideas about movti.
3633 ;; I don't think these are a good idea on the arm, there just aren't enough
3635 ;;(define_expand "loadti"
3636 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3637 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3640 ;;(define_expand "storeti"
3641 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3642 ;; (match_operand:TI 1 "s_register_operand" ""))]
3645 ;;(define_expand "movti"
3646 ;; [(set (match_operand:TI 0 "general_operand" "")
3647 ;; (match_operand:TI 1 "general_operand" ""))]
3653 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3654 ;; operands[1] = copy_to_reg (operands[1]);
3655 ;; if (GET_CODE (operands[0]) == MEM)
3656 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3657 ;; else if (GET_CODE (operands[1]) == MEM)
3658 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3662 ;; emit_insn (insn);
3666 ;; Recognize garbage generated above.
3669 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3670 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3674 ;; register mem = (which_alternative < 3);
3675 ;; register const char *template;
3677 ;; operands[mem] = XEXP (operands[mem], 0);
3678 ;; switch (which_alternative)
3680 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3681 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3682 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3683 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3684 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3685 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3687 ;; output_asm_insn (template, operands);
3691 (define_expand "movdi"
3692 [(set (match_operand:DI 0 "general_operand" "")
3693 (match_operand:DI 1 "general_operand" ""))]
3698 if (!no_new_pseudos)
3700 if (GET_CODE (operands[0]) != REG)
3701 operands[1] = force_reg (DImode, operands[1]);
3707 (define_insn "*arm_movdi"
3708 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
3709 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3710 "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT"
3712 return (output_move_double (operands));
3714 [(set_attr "length" "8")
3715 (set_attr "type" "*,load,store2")
3716 (set_attr "pool_range" "*,1020,*")
3717 (set_attr "neg_pool_range" "*,1008,*")]
3720 ;;; ??? This should have alternatives for constants.
3721 ;;; ??? This was originally identical to the movdf_insn pattern.
3722 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3723 ;;; thumb_reorg with a memory reference.
3724 (define_insn "*thumb_movdi_insn"
3725 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
3726 (match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
3729 && ( register_operand (operands[0], DImode)
3730 || register_operand (operands[1], DImode))"
3733 switch (which_alternative)
3737 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3738 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3739 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3741 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3743 operands[1] = GEN_INT (- INTVAL (operands[1]));
3744 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3746 return \"ldmia\\t%1, {%0, %H0}\";
3748 return \"stmia\\t%0, {%1, %H1}\";
3750 return thumb_load_double_from_address (operands);
3752 operands[2] = gen_rtx (MEM, SImode,
3753 plus_constant (XEXP (operands[0], 0), 4));
3754 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3757 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3758 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3759 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3762 [(set_attr "length" "4,4,6,2,2,6,4,4")
3763 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3764 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3767 (define_expand "movsi"
3768 [(set (match_operand:SI 0 "general_operand" "")
3769 (match_operand:SI 1 "general_operand" ""))]
3774 /* Everything except mem = const or mem = mem can be done easily */
3775 if (GET_CODE (operands[0]) == MEM)
3776 operands[1] = force_reg (SImode, operands[1]);
3777 if (GET_CODE (operands[1]) == CONST_INT
3778 && !(const_ok_for_arm (INTVAL (operands[1]))
3779 || const_ok_for_arm (~INTVAL (operands[1]))))
3781 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3784 : preserve_subexpressions_p ()));
3788 else /* TARGET_THUMB.... */
3790 if (!no_new_pseudos)
3792 if (GET_CODE (operands[0]) != REG)
3793 operands[1] = force_reg (SImode, operands[1]);
3798 && (CONSTANT_P (operands[1])
3799 || symbol_mentioned_p (operands[1])
3800 || label_mentioned_p (operands[1])))
3801 operands[1] = legitimize_pic_address (operands[1], SImode,
3802 (no_new_pseudos ? operands[0] : 0));
3806 (define_insn "*arm_movsi_insn"
3807 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
3808 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
3809 "TARGET_ARM && ! TARGET_IWMMXT
3810 && ( register_operand (operands[0], SImode)
3811 || register_operand (operands[1], SImode))"
3817 [(set_attr "type" "*,*,load,store1")
3818 (set_attr "predicable" "yes")
3819 (set_attr "pool_range" "*,*,4096,*")
3820 (set_attr "neg_pool_range" "*,*,4084,*")]
3824 [(set (match_operand:SI 0 "s_register_operand" "")
3825 (match_operand:SI 1 "const_int_operand" ""))]
3827 && (!(const_ok_for_arm (INTVAL (operands[1]))
3828 || const_ok_for_arm (~INTVAL (operands[1]))))"
3829 [(clobber (const_int 0))]
3831 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3837 (define_insn "*thumb_movsi_insn"
3838 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
3839 (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
3841 && ( register_operand (operands[0], SImode)
3842 || register_operand (operands[1], SImode))"
3853 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3854 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3855 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3859 [(set (match_operand:SI 0 "register_operand" "")
3860 (match_operand:SI 1 "const_int_operand" ""))]
3861 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3862 [(set (match_dup 0) (match_dup 1))
3863 (set (match_dup 0) (neg:SI (match_dup 0)))]
3864 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3868 [(set (match_operand:SI 0 "register_operand" "")
3869 (match_operand:SI 1 "const_int_operand" ""))]
3870 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3871 [(set (match_dup 0) (match_dup 1))
3872 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3875 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3876 unsigned HOST_WIDE_INT mask = 0xff;
3879 for (i = 0; i < 25; i++)
3880 if ((val & (mask << i)) == val)
3883 /* Shouldn't happen, but we don't want to split if the shift is zero. */
3887 operands[1] = GEN_INT (val >> i);
3888 operands[2] = GEN_INT (i);
3892 ;; When generating pic, we need to load the symbol offset into a register.
3893 ;; So that the optimizer does not confuse this with a normal symbol load
3894 ;; we use an unspec. The offset will be loaded from a constant pool entry,
3895 ;; since that is the only type of relocation we can use.
3897 ;; The rather odd constraints on the following are to force reload to leave
3898 ;; the insn alone, and to force the minipool generation pass to then move
3899 ;; the GOT symbol to memory.
3901 (define_insn "pic_load_addr_arm"
3902 [(set (match_operand:SI 0 "s_register_operand" "=r")
3903 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3904 "TARGET_ARM && flag_pic"
3906 [(set_attr "type" "load")
3907 (set (attr "pool_range") (const_int 4096))
3908 (set (attr "neg_pool_range") (const_int 4084))]
3911 (define_insn "pic_load_addr_thumb"
3912 [(set (match_operand:SI 0 "s_register_operand" "=l")
3913 (unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
3914 "TARGET_THUMB && flag_pic"
3916 [(set_attr "type" "load")
3917 (set (attr "pool_range") (const_int 1024))]
3920 ;; This variant is used for AOF assembly, since it needs to mention the
3921 ;; pic register in the rtl.
3922 (define_expand "pic_load_addr_based"
3923 [(set (match_operand:SI 0 "s_register_operand" "")
3924 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
3925 "TARGET_ARM && flag_pic"
3926 "operands[2] = pic_offset_table_rtx;"
3929 (define_insn "*pic_load_addr_based_insn"
3930 [(set (match_operand:SI 0 "s_register_operand" "=r")
3931 (unspec:SI [(match_operand 1 "" "")
3932 (match_operand 2 "s_register_operand" "r")]
3934 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
3936 #ifdef AOF_ASSEMBLER
3937 operands[1] = aof_pic_entry (operands[1]);
3939 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3942 [(set_attr "type" "load")
3943 (set (attr "pool_range")
3944 (if_then_else (eq_attr "is_thumb" "yes")
3947 (set (attr "neg_pool_range")
3948 (if_then_else (eq_attr "is_thumb" "yes")
3953 (define_insn "pic_add_dot_plus_four"
3954 [(set (match_operand:SI 0 "register_operand" "+r")
3955 (unspec:SI [(plus:SI (match_dup 0)
3956 (const (plus:SI (pc) (const_int 4))))]
3958 (use (label_ref (match_operand 1 "" "")))]
3959 "TARGET_THUMB && flag_pic"
3961 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3962 CODE_LABEL_NUMBER (operands[1]));
3963 return \"add\\t%0, %|pc\";
3965 [(set_attr "length" "2")]
3968 (define_insn "pic_add_dot_plus_eight"
3969 [(set (match_operand:SI 0 "register_operand" "+r")
3970 (unspec:SI [(plus:SI (match_dup 0)
3971 (const (plus:SI (pc) (const_int 8))))]
3973 (use (label_ref (match_operand 1 "" "")))]
3974 "TARGET_ARM && flag_pic"
3976 (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
3977 CODE_LABEL_NUMBER (operands[1]));
3978 return \"add%?\\t%0, %|pc, %0\";
3980 [(set_attr "predicable" "yes")]
3983 (define_expand "builtin_setjmp_receiver"
3984 [(label_ref (match_operand 0 "" ""))]
3988 arm_finalize_pic (0);
3992 ;; If copying one reg to another we can set the condition codes according to
3993 ;; its value. Such a move is common after a return from subroutine and the
3994 ;; result is being tested against zero.
3996 (define_insn "*movsi_compare0"
3997 [(set (reg:CC CC_REGNUM)
3998 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4000 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4005 sub%?s\\t%0, %1, #0"
4006 [(set_attr "conds" "set")]
4009 ;; Subroutine to store a half word from a register into memory.
4010 ;; Operand 0 is the source register (HImode)
4011 ;; Operand 1 is the destination address in a register (SImode)
4013 ;; In both this routine and the next, we must be careful not to spill
4014 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4015 ;; can generate unrecognizable rtl.
4017 (define_expand "storehi"
4018 [;; store the low byte
4019 (set (match_operand 1 "" "") (match_dup 3))
4020 ;; extract the high byte
4022 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4023 ;; store the high byte
4024 (set (match_dup 4) (match_dup 5))]
4028 rtx op1 = operands[1];
4029 rtx addr = XEXP (op1, 0);
4030 enum rtx_code code = GET_CODE (addr);
4032 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4034 op1 = replace_equiv_address (operands[1], force_reg (SImode, addr));
4036 operands[4] = adjust_address (op1, QImode, 1);
4037 operands[1] = adjust_address (operands[1], QImode, 0);
4038 operands[3] = gen_lowpart (QImode, operands[0]);
4039 operands[0] = gen_lowpart (SImode, operands[0]);
4040 operands[2] = gen_reg_rtx (SImode);
4041 operands[5] = gen_lowpart (QImode, operands[2]);
4045 (define_expand "storehi_bigend"
4046 [(set (match_dup 4) (match_dup 3))
4048 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4049 (set (match_operand 1 "" "") (match_dup 5))]
4053 rtx op1 = operands[1];
4054 rtx addr = XEXP (op1, 0);
4055 enum rtx_code code = GET_CODE (addr);
4057 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4059 op1 = replace_equiv_address (op1, force_reg (SImode, addr));
4061 operands[4] = adjust_address (op1, QImode, 1);
4062 operands[1] = adjust_address (operands[1], QImode, 0);
4063 operands[3] = gen_lowpart (QImode, operands[0]);
4064 operands[0] = gen_lowpart (SImode, operands[0]);
4065 operands[2] = gen_reg_rtx (SImode);
4066 operands[5] = gen_lowpart (QImode, operands[2]);
4070 ;; Subroutine to store a half word integer constant into memory.
4071 (define_expand "storeinthi"
4072 [(set (match_operand 0 "" "")
4073 (match_operand 1 "" ""))
4074 (set (match_dup 3) (match_dup 2))]
4078 HOST_WIDE_INT value = INTVAL (operands[1]);
4079 rtx addr = XEXP (operands[0], 0);
4080 rtx op0 = operands[0];
4081 enum rtx_code code = GET_CODE (addr);
4083 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4085 op0 = replace_equiv_address (op0, force_reg (SImode, addr));
4087 operands[1] = gen_reg_rtx (SImode);
4088 if (BYTES_BIG_ENDIAN)
4090 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4091 if ((value & 255) == ((value >> 8) & 255))
4092 operands[2] = operands[1];
4095 operands[2] = gen_reg_rtx (SImode);
4096 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4101 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4102 if ((value & 255) == ((value >> 8) & 255))
4103 operands[2] = operands[1];
4106 operands[2] = gen_reg_rtx (SImode);
4107 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4111 operands[3] = adjust_address (op0, QImode, 1);
4112 operands[0] = adjust_address (operands[0], QImode, 0);
4113 operands[2] = gen_lowpart (QImode, operands[2]);
4114 operands[1] = gen_lowpart (QImode, operands[1]);
4118 (define_expand "storehi_single_op"
4119 [(set (match_operand:HI 0 "memory_operand" "")
4120 (match_operand:HI 1 "general_operand" ""))]
4121 "TARGET_ARM && arm_arch4"
4123 if (!s_register_operand (operands[1], HImode))
4124 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4128 (define_expand "movhi"
4129 [(set (match_operand:HI 0 "general_operand" "")
4130 (match_operand:HI 1 "general_operand" ""))]
4135 if (!no_new_pseudos)
4137 if (GET_CODE (operands[0]) == MEM)
4141 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4144 if (GET_CODE (operands[1]) == CONST_INT)
4145 emit_insn (gen_storeinthi (operands[0], operands[1]));
4148 if (GET_CODE (operands[1]) == MEM)
4149 operands[1] = force_reg (HImode, operands[1]);
4150 if (BYTES_BIG_ENDIAN)
4151 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4153 emit_insn (gen_storehi (operands[1], operands[0]));
4157 /* Sign extend a constant, and keep it in an SImode reg. */
4158 else if (GET_CODE (operands[1]) == CONST_INT)
4160 rtx reg = gen_reg_rtx (SImode);
4161 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4163 /* If the constant is already valid, leave it alone. */
4164 if (!const_ok_for_arm (val))
4166 /* If setting all the top bits will make the constant
4167 loadable in a single instruction, then set them.
4168 Otherwise, sign extend the number. */
4170 if (const_ok_for_arm (~(val | ~0xffff)))
4172 else if (val & 0x8000)
4176 emit_insn (gen_movsi (reg, GEN_INT (val)));
4177 operands[1] = gen_lowpart (HImode, reg);
4179 else if (arm_arch4 && !no_new_pseudos && optimize > 0
4180 && GET_CODE (operands[1]) == MEM)
4182 rtx reg = gen_reg_rtx (SImode);
4184 emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
4185 operands[1] = gen_lowpart (HImode, reg);
4187 else if (!arm_arch4)
4189 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4190 for v4 and up architectures because LDRH instructions will
4191 be used to access the HI values, and these cannot generate
4192 unaligned word access faults in the MMU. */
4193 if (GET_CODE (operands[1]) == MEM)
4195 if (TARGET_MMU_TRAPS)
4198 rtx offset = const0_rtx;
4199 rtx reg = gen_reg_rtx (SImode);
4201 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4202 || (GET_CODE (base) == PLUS
4203 && (GET_CODE (offset = XEXP (base, 1))
4205 && ((INTVAL(offset) & 1) != 1)
4206 && GET_CODE (base = XEXP (base, 0)) == REG))
4207 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4209 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4212 new = gen_rtx_MEM (SImode,
4213 plus_constant (base, new_offset));
4214 MEM_COPY_ATTRIBUTES (new, operands[1]);
4215 emit_insn (gen_movsi (reg, new));
4216 if (((INTVAL (offset) & 2) != 0)
4217 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4219 rtx reg2 = gen_reg_rtx (SImode);
4221 emit_insn (gen_lshrsi3 (reg2, reg,
4227 emit_insn (gen_movhi_bytes (reg, operands[1]));
4229 operands[1] = gen_lowpart (HImode, reg);
4231 else if (BYTES_BIG_ENDIAN)
4234 rtx offset = const0_rtx;
4236 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4237 || (GET_CODE (base) == PLUS
4238 && (GET_CODE (offset = XEXP (base, 1))
4240 && GET_CODE (base = XEXP (base, 0)) == REG))
4241 && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
4243 rtx reg = gen_reg_rtx (SImode);
4246 if ((INTVAL (offset) & 2) == 2)
4248 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4249 new = gen_rtx_MEM (SImode,
4250 plus_constant (base,
4252 MEM_COPY_ATTRIBUTES (new, operands[1]);
4253 emit_insn (gen_movsi (reg, new));
4257 new = gen_rtx_MEM (SImode,
4258 XEXP (operands[1], 0));
4259 MEM_COPY_ATTRIBUTES (new, operands[1]);
4260 emit_insn (gen_rotated_loadsi (reg, new));
4263 operands[1] = gen_lowpart (HImode, reg);
4267 emit_insn (gen_movhi_bigend (operands[0],
4275 /* Handle loading a large integer during reload */
4276 else if (GET_CODE (operands[1]) == CONST_INT
4277 && !const_ok_for_arm (INTVAL (operands[1]))
4278 && !const_ok_for_arm (~INTVAL (operands[1])))
4280 /* Writing a constant to memory needs a scratch, which should
4281 be handled with SECONDARY_RELOADs. */
4282 if (GET_CODE (operands[0]) != REG)
4285 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4286 emit_insn (gen_movsi (operands[0], operands[1]));
4290 else /* TARGET_THUMB */
4292 if (!no_new_pseudos)
4294 if (GET_CODE (operands[0]) != REG)
4295 operands[1] = force_reg (HImode, operands[1]);
4297 /* ??? We shouldn't really get invalid addresses here, but this can
4298 happen if we are passed a SP (never OK for HImode/QImode) or
4299 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4300 HImode/QImode) relative address. */
4301 /* ??? This should perhaps be fixed elsewhere, for instance, in
4302 fixup_stack_1, by checking for other kinds of invalid addresses,
4303 e.g. a bare reference to a virtual register. This may confuse the
4304 alpha though, which must handle this case differently. */
4305 if (GET_CODE (operands[0]) == MEM
4306 && !memory_address_p (GET_MODE (operands[0]),
4307 XEXP (operands[0], 0)))
4309 = replace_equiv_address (operands[0],
4310 copy_to_reg (XEXP (operands[0], 0)));
4312 if (GET_CODE (operands[1]) == MEM
4313 && !memory_address_p (GET_MODE (operands[1]),
4314 XEXP (operands[1], 0)))
4316 = replace_equiv_address (operands[1],
4317 copy_to_reg (XEXP (operands[1], 0)));
4319 /* Handle loading a large integer during reload */
4320 else if (GET_CODE (operands[1]) == CONST_INT
4321 && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4323 /* Writing a constant to memory needs a scratch, which should
4324 be handled with SECONDARY_RELOADs. */
4325 if (GET_CODE (operands[0]) != REG)
4328 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4329 emit_insn (gen_movsi (operands[0], operands[1]));
4336 (define_insn "*thumb_movhi_insn"
4337 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l, m,*r,*h,l")
4338 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4340 && ( register_operand (operands[0], HImode)
4341 || register_operand (operands[1], HImode))"
4343 switch (which_alternative)
4345 case 0: return \"add %0, %1, #0\";
4346 case 2: return \"strh %1, %0\";
4347 case 3: return \"mov %0, %1\";
4348 case 4: return \"mov %0, %1\";
4349 case 5: return \"mov %0, %1\";
4352 /* The stack pointer can end up being taken as an index register.
4353 Catch this case here and deal with it. */
4354 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4355 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4356 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4359 ops[0] = operands[0];
4360 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4362 output_asm_insn (\"mov %0, %1\", ops);
4364 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4367 return \"ldrh %0, %1\";
4369 [(set_attr "length" "2,4,2,2,2,2")
4370 (set_attr "type" "*,load,store1,*,*,*")
4371 (set_attr "pool_range" "*,64,*,*,*,*")]
4375 (define_insn "rotated_loadsi"
4376 [(set (match_operand:SI 0 "s_register_operand" "=r")
4377 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4379 "TARGET_ARM && (!TARGET_MMU_TRAPS)"
4384 ops[0] = operands[0];
4385 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4386 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4389 [(set_attr "type" "load")
4390 (set_attr "predicable" "yes")]
4393 (define_expand "movhi_bytes"
4394 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4396 (zero_extend:SI (match_dup 6)))
4397 (set (match_operand:SI 0 "" "")
4398 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4403 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4405 mem1 = gen_rtx_MEM (QImode, addr);
4406 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4407 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4408 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4409 operands[0] = gen_lowpart (SImode, operands[0]);
4411 operands[2] = gen_reg_rtx (SImode);
4412 operands[3] = gen_reg_rtx (SImode);
4415 if (BYTES_BIG_ENDIAN)
4417 operands[4] = operands[2];
4418 operands[5] = operands[3];
4422 operands[4] = operands[3];
4423 operands[5] = operands[2];
4428 (define_expand "movhi_bigend"
4430 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4433 (ashiftrt:SI (match_dup 2) (const_int 16)))
4434 (set (match_operand:HI 0 "s_register_operand" "")
4438 operands[2] = gen_reg_rtx (SImode);
4439 operands[3] = gen_reg_rtx (SImode);
4440 operands[4] = gen_lowpart (HImode, operands[3]);
4444 ;; Pattern to recognize insn generated default case above
4445 (define_insn "*movhi_insn_arch4"
4446 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4447 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4450 && (GET_CODE (operands[1]) != CONST_INT
4451 || const_ok_for_arm (INTVAL (operands[1]))
4452 || const_ok_for_arm (~INTVAL (operands[1])))"
4454 mov%?\\t%0, %1\\t%@ movhi
4455 mvn%?\\t%0, #%B1\\t%@ movhi
4456 str%?h\\t%1, %0\\t%@ movhi
4457 ldr%?h\\t%0, %1\\t%@ movhi"
4458 [(set_attr "type" "*,*,store1,load")
4459 (set_attr "predicable" "yes")
4460 (set_attr "pool_range" "*,*,*,256")
4461 (set_attr "neg_pool_range" "*,*,*,244")]
4464 (define_insn "*movhi_insn_littleend"
4465 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4466 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4469 && !BYTES_BIG_ENDIAN
4470 && !TARGET_MMU_TRAPS
4471 && (GET_CODE (operands[1]) != CONST_INT
4472 || const_ok_for_arm (INTVAL (operands[1]))
4473 || const_ok_for_arm (~INTVAL (operands[1])))"
4475 mov%?\\t%0, %1\\t%@ movhi
4476 mvn%?\\t%0, #%B1\\t%@ movhi
4477 ldr%?\\t%0, %1\\t%@ movhi"
4478 [(set_attr "type" "*,*,load")
4479 (set_attr "predicable" "yes")
4480 (set_attr "pool_range" "4096")
4481 (set_attr "neg_pool_range" "4084")]
4484 (define_insn "*movhi_insn_bigend"
4485 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4486 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4490 && !TARGET_MMU_TRAPS
4491 && (GET_CODE (operands[1]) != CONST_INT
4492 || const_ok_for_arm (INTVAL (operands[1]))
4493 || const_ok_for_arm (~INTVAL (operands[1])))"
4495 mov%?\\t%0, %1\\t%@ movhi
4496 mvn%?\\t%0, #%B1\\t%@ movhi
4497 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4498 [(set_attr "type" "*,*,load")
4499 (set_attr "predicable" "yes")
4500 (set_attr "length" "4,4,8")
4501 (set_attr "pool_range" "*,*,4092")
4502 (set_attr "neg_pool_range" "*,*,4084")]
4505 (define_insn "*loadhi_si_bigend"
4506 [(set (match_operand:SI 0 "s_register_operand" "=r")
4507 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4511 && !TARGET_MMU_TRAPS"
4512 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4513 [(set_attr "type" "load")
4514 (set_attr "predicable" "yes")
4515 (set_attr "pool_range" "4096")
4516 (set_attr "neg_pool_range" "4084")]
4519 (define_insn "*movhi_bytes"
4520 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4521 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4522 "TARGET_ARM && TARGET_MMU_TRAPS"
4524 mov%?\\t%0, %1\\t%@ movhi
4525 mvn%?\\t%0, #%B1\\t%@ movhi"
4526 [(set_attr "predicable" "yes")]
4529 (define_insn "thumb_movhi_clobber"
4530 [(set (match_operand:HI 0 "memory_operand" "=m")
4531 (match_operand:HI 1 "register_operand" "l"))
4532 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4538 ;; We use a DImode scratch because we may occasionally need an additional
4539 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4540 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4541 (define_expand "reload_outhi"
4542 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4543 (match_operand:HI 1 "s_register_operand" "r")
4544 (match_operand:DI 2 "s_register_operand" "=&l")])]
4547 arm_reload_out_hi (operands);
4549 thumb_reload_out_hi (operands);
4554 (define_expand "reload_inhi"
4555 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4556 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4557 (match_operand:DI 2 "s_register_operand" "=&r")])]
4558 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4561 arm_reload_in_hi (operands);
4563 thumb_reload_out_hi (operands);
4567 (define_expand "movqi"
4568 [(set (match_operand:QI 0 "general_operand" "")
4569 (match_operand:QI 1 "general_operand" ""))]
4574 /* Everything except mem = const or mem = mem can be done easily */
4576 if (!no_new_pseudos)
4578 if (GET_CODE (operands[1]) == CONST_INT)
4580 rtx reg = gen_reg_rtx (SImode);
4582 emit_insn (gen_movsi (reg, operands[1]));
4583 operands[1] = gen_lowpart (QImode, reg);
4585 if (GET_CODE (operands[1]) == MEM && optimize > 0)
4587 rtx reg = gen_reg_rtx (SImode);
4589 emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
4590 operands[1] = gen_lowpart (QImode, reg);
4592 if (GET_CODE (operands[0]) == MEM)
4593 operands[1] = force_reg (QImode, operands[1]);
4596 else /* TARGET_THUMB */
4598 if (!no_new_pseudos)
4600 if (GET_CODE (operands[0]) != REG)
4601 operands[1] = force_reg (QImode, operands[1]);
4603 /* ??? We shouldn't really get invalid addresses here, but this can
4604 happen if we are passed a SP (never OK for HImode/QImode) or
4605 virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
4606 HImode/QImode) relative address. */
4607 /* ??? This should perhaps be fixed elsewhere, for instance, in
4608 fixup_stack_1, by checking for other kinds of invalid addresses,
4609 e.g. a bare reference to a virtual register. This may confuse the
4610 alpha though, which must handle this case differently. */
4611 if (GET_CODE (operands[0]) == MEM
4612 && !memory_address_p (GET_MODE (operands[0]),
4613 XEXP (operands[0], 0)))
4615 = replace_equiv_address (operands[0],
4616 copy_to_reg (XEXP (operands[0], 0)));
4617 if (GET_CODE (operands[1]) == MEM
4618 && !memory_address_p (GET_MODE (operands[1]),
4619 XEXP (operands[1], 0)))
4621 = replace_equiv_address (operands[1],
4622 copy_to_reg (XEXP (operands[1], 0)));
4624 /* Handle loading a large integer during reload */
4625 else if (GET_CODE (operands[1]) == CONST_INT
4626 && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4628 /* Writing a constant to memory needs a scratch, which should
4629 be handled with SECONDARY_RELOADs. */
4630 if (GET_CODE (operands[0]) != REG)
4633 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4634 emit_insn (gen_movsi (operands[0], operands[1]));
4642 (define_insn "*arm_movqi_insn"
4643 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4644 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4646 && ( register_operand (operands[0], QImode)
4647 || register_operand (operands[1], QImode))"
4653 [(set_attr "type" "*,*,load,store1")
4654 (set_attr "predicable" "yes")]
4657 (define_insn "*thumb_movqi_insn"
4658 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4659 (match_operand:QI 1 "general_operand" "l, m,l,*h,*r,I"))]
4661 && ( register_operand (operands[0], QImode)
4662 || register_operand (operands[1], QImode))"
4670 [(set_attr "length" "2")
4671 (set_attr "type" "*,load,store1,*,*,*")
4672 (set_attr "pool_range" "*,32,*,*,*,*")]
4675 (define_expand "movsf"
4676 [(set (match_operand:SF 0 "general_operand" "")
4677 (match_operand:SF 1 "general_operand" ""))]
4682 if (GET_CODE (operands[0]) == MEM)
4683 operands[1] = force_reg (SFmode, operands[1]);
4685 else /* TARGET_THUMB */
4687 if (!no_new_pseudos)
4689 if (GET_CODE (operands[0]) != REG)
4690 operands[1] = force_reg (SFmode, operands[1]);
4697 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4698 (match_operand:SF 1 "immediate_operand" ""))]
4700 && !TARGET_HARD_FLOAT
4702 && GET_CODE (operands[1]) == CONST_DOUBLE"
4703 [(set (match_dup 2) (match_dup 3))]
4705 operands[2] = gen_lowpart (SImode, operands[0]);
4706 operands[3] = gen_lowpart (SImode, operands[1]);
4707 if (operands[2] == 0 || operands[3] == 0)
4712 (define_insn "*arm_movsf_soft_insn"
4713 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4714 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4717 && TARGET_SOFT_FLOAT
4718 && (GET_CODE (operands[0]) != MEM
4719 || register_operand (operands[1], SFmode))"
4722 ldr%?\\t%0, %1\\t%@ float
4723 str%?\\t%1, %0\\t%@ float"
4724 [(set_attr "length" "4,4,4")
4725 (set_attr "predicable" "yes")
4726 (set_attr "type" "*,load,store1")
4727 (set_attr "pool_range" "*,4096,*")
4728 (set_attr "neg_pool_range" "*,4084,*")]
4731 ;;; ??? This should have alternatives for constants.
4732 (define_insn "*thumb_movsf_insn"
4733 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l, m,*r,*h")
4734 (match_operand:SF 1 "general_operand" "l, >,l,mF,l,*h,*r"))]
4736 && ( register_operand (operands[0], SFmode)
4737 || register_operand (operands[1], SFmode))"
4746 [(set_attr "length" "2")
4747 (set_attr "type" "*,load,store1,load,store1,*,*")
4748 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4751 (define_expand "movdf"
4752 [(set (match_operand:DF 0 "general_operand" "")
4753 (match_operand:DF 1 "general_operand" ""))]
4758 if (GET_CODE (operands[0]) == MEM)
4759 operands[1] = force_reg (DFmode, operands[1]);
4761 else /* TARGET_THUMB */
4763 if (!no_new_pseudos)
4765 if (GET_CODE (operands[0]) != REG)
4766 operands[1] = force_reg (DFmode, operands[1]);
4772 ;; Reloading a df mode value stored in integer regs to memory can require a
4774 (define_expand "reload_outdf"
4775 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4776 (match_operand:DF 1 "s_register_operand" "r")
4777 (match_operand:SI 2 "s_register_operand" "=&r")]
4781 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4784 operands[2] = XEXP (operands[0], 0);
4785 else if (code == POST_INC || code == PRE_DEC)
4787 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4788 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4789 emit_insn (gen_movdi (operands[0], operands[1]));
4792 else if (code == PRE_INC)
4794 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4796 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4799 else if (code == POST_DEC)
4800 operands[2] = XEXP (XEXP (operands[0], 0), 0);
4802 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4803 XEXP (XEXP (operands[0], 0), 1)));
4805 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4808 if (code == POST_DEC)
4809 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4815 (define_insn "*movdf_soft_insn"
4816 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4817 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4818 "TARGET_ARM && TARGET_SOFT_FLOAT
4821 "* return output_move_double (operands);"
4822 [(set_attr "length" "8,8,8")
4823 (set_attr "type" "*,load,store2")
4824 (set_attr "pool_range" "1020")
4825 (set_attr "neg_pool_range" "1008")]
4828 ;;; ??? This should have alternatives for constants.
4829 ;;; ??? This was originally identical to the movdi_insn pattern.
4830 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4831 ;;; thumb_reorg with a memory reference.
4832 (define_insn "*thumb_movdf_insn"
4833 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l, m,*r")
4834 (match_operand:DF 1 "general_operand" "l, >,l,mF,l,*r"))]
4836 && ( register_operand (operands[0], DFmode)
4837 || register_operand (operands[1], DFmode))"
4839 switch (which_alternative)
4843 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4844 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4845 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4847 return \"ldmia\\t%1, {%0, %H0}\";
4849 return \"stmia\\t%0, {%1, %H1}\";
4851 return thumb_load_double_from_address (operands);
4853 operands[2] = gen_rtx (MEM, SImode,
4854 plus_constant (XEXP (operands[0], 0), 4));
4855 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4858 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4859 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4860 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4863 [(set_attr "length" "4,2,2,6,4,4")
4864 (set_attr "type" "*,load,store2,load,store2,*")
4865 (set_attr "pool_range" "*,*,*,1020,*,*")]
4869 (define_expand "movv2si"
4870 [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
4871 (match_operand:V2SI 1 "general_operand" ""))]
4872 "TARGET_REALLY_IWMMXT"
4876 (define_expand "movv4hi"
4877 [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
4878 (match_operand:V4HI 1 "general_operand" ""))]
4879 "TARGET_REALLY_IWMMXT"
4883 (define_expand "movv8qi"
4884 [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
4885 (match_operand:V8QI 1 "general_operand" ""))]
4886 "TARGET_REALLY_IWMMXT"
4891 ;; load- and store-multiple insns
4892 ;; The arm can load/store any set of registers, provided that they are in
4893 ;; ascending order; but that is beyond GCC so stick with what it knows.
4895 (define_expand "load_multiple"
4896 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4897 (match_operand:SI 1 "" ""))
4898 (use (match_operand:SI 2 "" ""))])]
4901 /* Support only fixed point registers. */
4902 if (GET_CODE (operands[2]) != CONST_INT
4903 || INTVAL (operands[2]) > 14
4904 || INTVAL (operands[2]) < 2
4905 || GET_CODE (operands[1]) != MEM
4906 || GET_CODE (operands[0]) != REG
4907 || REGNO (operands[0]) > (LAST_ARM_REGNUM - 1)
4908 || REGNO (operands[0]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
4912 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
4913 force_reg (SImode, XEXP (operands[1], 0)),
4914 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
4915 MEM_IN_STRUCT_P(operands[1]),
4916 MEM_SCALAR_P (operands[1]));
4920 ;; Load multiple with write-back
4922 (define_insn "*ldmsi_postinc4"
4923 [(match_parallel 0 "load_multiple_operation"
4924 [(set (match_operand:SI 1 "s_register_operand" "=r")
4925 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4927 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4928 (mem:SI (match_dup 2)))
4929 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4930 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4931 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4932 (mem:SI (plus:SI (match_dup 2) (const_int 8))))
4933 (set (match_operand:SI 6 "arm_hard_register_operand" "")
4934 (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
4935 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
4936 "ldm%?ia\\t%1!, {%3, %4, %5, %6}"
4937 [(set_attr "type" "load")
4938 (set_attr "predicable" "yes")]
4941 (define_insn "*ldmsi_postinc3"
4942 [(match_parallel 0 "load_multiple_operation"
4943 [(set (match_operand:SI 1 "s_register_operand" "=r")
4944 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4946 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4947 (mem:SI (match_dup 2)))
4948 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4949 (mem:SI (plus:SI (match_dup 2) (const_int 4))))
4950 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4951 (mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
4952 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4953 "ldm%?ia\\t%1!, {%3, %4, %5}"
4954 [(set_attr "type" "load")
4955 (set_attr "predicable" "yes")]
4958 (define_insn "*ldmsi_postinc2"
4959 [(match_parallel 0 "load_multiple_operation"
4960 [(set (match_operand:SI 1 "s_register_operand" "=r")
4961 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
4963 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4964 (mem:SI (match_dup 2)))
4965 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4966 (mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
4967 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
4968 "ldm%?ia\\t%1!, {%3, %4}"
4969 [(set_attr "type" "load")
4970 (set_attr "predicable" "yes")]
4973 ;; Ordinary load multiple
4975 (define_insn "*ldmsi4"
4976 [(match_parallel 0 "load_multiple_operation"
4977 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4978 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4979 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4980 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4981 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4982 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
4983 (set (match_operand:SI 5 "arm_hard_register_operand" "")
4984 (mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
4985 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
4986 "ldm%?ia\\t%1, {%2, %3, %4, %5}"
4987 [(set_attr "type" "load")
4988 (set_attr "predicable" "yes")]
4991 (define_insn "*ldmsi3"
4992 [(match_parallel 0 "load_multiple_operation"
4993 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
4994 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
4995 (set (match_operand:SI 3 "arm_hard_register_operand" "")
4996 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
4997 (set (match_operand:SI 4 "arm_hard_register_operand" "")
4998 (mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
4999 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5000 "ldm%?ia\\t%1, {%2, %3, %4}"
5001 [(set_attr "type" "load")
5002 (set_attr "predicable" "yes")]
5005 (define_insn "*ldmsi2"
5006 [(match_parallel 0 "load_multiple_operation"
5007 [(set (match_operand:SI 2 "arm_hard_register_operand" "")
5008 (mem:SI (match_operand:SI 1 "s_register_operand" "r")))
5009 (set (match_operand:SI 3 "arm_hard_register_operand" "")
5010 (mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
5011 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5012 "ldm%?ia\\t%1, {%2, %3}"
5013 [(set_attr "type" "load")
5014 (set_attr "predicable" "yes")]
5017 (define_expand "store_multiple"
5018 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5019 (match_operand:SI 1 "" ""))
5020 (use (match_operand:SI 2 "" ""))])]
5023 /* Support only fixed point registers */
5024 if (GET_CODE (operands[2]) != CONST_INT
5025 || INTVAL (operands[2]) > 14
5026 || INTVAL (operands[2]) < 2
5027 || GET_CODE (operands[1]) != REG
5028 || GET_CODE (operands[0]) != MEM
5029 || REGNO (operands[1]) > (LAST_ARM_REGNUM - 1)
5030 || REGNO (operands[1]) + INTVAL (operands[2]) > LAST_ARM_REGNUM)
5034 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5035 force_reg (SImode, XEXP (operands[0], 0)),
5036 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5037 MEM_IN_STRUCT_P(operands[0]),
5038 MEM_SCALAR_P (operands[0]));
5042 ;; Store multiple with write-back
5044 (define_insn "*stmsi_postinc4"
5045 [(match_parallel 0 "store_multiple_operation"
5046 [(set (match_operand:SI 1 "s_register_operand" "=r")
5047 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5049 (set (mem:SI (match_dup 2))
5050 (match_operand:SI 3 "arm_hard_register_operand" ""))
5051 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5052 (match_operand:SI 4 "arm_hard_register_operand" ""))
5053 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5054 (match_operand:SI 5 "arm_hard_register_operand" ""))
5055 (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
5056 (match_operand:SI 6 "arm_hard_register_operand" ""))])]
5057 "TARGET_ARM && XVECLEN (operands[0], 0) == 5"
5058 "stm%?ia\\t%1!, {%3, %4, %5, %6}"
5059 [(set_attr "predicable" "yes")
5060 (set_attr "type" "store4")]
5063 (define_insn "*stmsi_postinc3"
5064 [(match_parallel 0 "store_multiple_operation"
5065 [(set (match_operand:SI 1 "s_register_operand" "=r")
5066 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5068 (set (mem:SI (match_dup 2))
5069 (match_operand:SI 3 "arm_hard_register_operand" ""))
5070 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5071 (match_operand:SI 4 "arm_hard_register_operand" ""))
5072 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5073 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5074 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5075 "stm%?ia\\t%1!, {%3, %4, %5}"
5076 [(set_attr "predicable" "yes")
5077 (set_attr "type" "store3")]
5080 (define_insn "*stmsi_postinc2"
5081 [(match_parallel 0 "store_multiple_operation"
5082 [(set (match_operand:SI 1 "s_register_operand" "=r")
5083 (plus:SI (match_operand:SI 2 "s_register_operand" "1")
5085 (set (mem:SI (match_dup 2))
5086 (match_operand:SI 3 "arm_hard_register_operand" ""))
5087 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5088 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5089 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5090 "stm%?ia\\t%1!, {%3, %4}"
5091 [(set_attr "predicable" "yes")
5092 (set_attr "type" "store2")]
5095 ;; Ordinary store multiple
5097 (define_insn "*stmsi4"
5098 [(match_parallel 0 "store_multiple_operation"
5099 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5100 (match_operand:SI 2 "arm_hard_register_operand" ""))
5101 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5102 (match_operand:SI 3 "arm_hard_register_operand" ""))
5103 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5104 (match_operand:SI 4 "arm_hard_register_operand" ""))
5105 (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
5106 (match_operand:SI 5 "arm_hard_register_operand" ""))])]
5107 "TARGET_ARM && XVECLEN (operands[0], 0) == 4"
5108 "stm%?ia\\t%1, {%2, %3, %4, %5}"
5109 [(set_attr "predicable" "yes")
5110 (set_attr "type" "store4")]
5113 (define_insn "*stmsi3"
5114 [(match_parallel 0 "store_multiple_operation"
5115 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5116 (match_operand:SI 2 "arm_hard_register_operand" ""))
5117 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5118 (match_operand:SI 3 "arm_hard_register_operand" ""))
5119 (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
5120 (match_operand:SI 4 "arm_hard_register_operand" ""))])]
5121 "TARGET_ARM && XVECLEN (operands[0], 0) == 3"
5122 "stm%?ia\\t%1, {%2, %3, %4}"
5123 [(set_attr "predicable" "yes")
5124 (set_attr "type" "store3")]
5127 (define_insn "*stmsi2"
5128 [(match_parallel 0 "store_multiple_operation"
5129 [(set (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5130 (match_operand:SI 2 "arm_hard_register_operand" ""))
5131 (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
5132 (match_operand:SI 3 "arm_hard_register_operand" ""))])]
5133 "TARGET_ARM && XVECLEN (operands[0], 0) == 2"
5134 "stm%?ia\\t%1, {%2, %3}"
5135 [(set_attr "predicable" "yes")
5136 (set_attr "type" "store2")]
5139 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5140 ;; We could let this apply for blocks of less than this, but it clobbers so
5141 ;; many registers that there is then probably a better way.
5143 (define_expand "movstrqi"
5144 [(match_operand:BLK 0 "general_operand" "")
5145 (match_operand:BLK 1 "general_operand" "")
5146 (match_operand:SI 2 "const_int_operand" "")
5147 (match_operand:SI 3 "const_int_operand" "")]
5152 if (arm_gen_movstrqi (operands))
5156 else /* TARGET_THUMB */
5158 if ( INTVAL (operands[3]) != 4
5159 || INTVAL (operands[2]) > 48)
5162 thumb_expand_movstrqi (operands);
5168 ;; Thumb block-move insns
5170 (define_insn "movmem12b"
5171 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5172 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5173 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5174 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5175 (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
5176 (mem:SI (plus:SI (match_dup 3) (const_int 8))))
5177 (set (match_operand:SI 0 "register_operand" "=l")
5178 (plus:SI (match_dup 2) (const_int 12)))
5179 (set (match_operand:SI 1 "register_operand" "=l")
5180 (plus:SI (match_dup 3) (const_int 12)))
5181 (clobber (match_scratch:SI 4 "=&l"))
5182 (clobber (match_scratch:SI 5 "=&l"))
5183 (clobber (match_scratch:SI 6 "=&l"))]
5185 "* return thumb_output_move_mem_multiple (3, operands);"
5186 [(set_attr "length" "4")
5187 ; This isn't entirely accurate... It loads as well, but in terms of
5188 ; scheduling the following insn it is better to consider it as a store
5189 (set_attr "type" "store3")]
5192 (define_insn "movmem8b"
5193 [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
5194 (mem:SI (match_operand:SI 3 "register_operand" "1")))
5195 (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
5196 (mem:SI (plus:SI (match_dup 3) (const_int 4))))
5197 (set (match_operand:SI 0 "register_operand" "=l")
5198 (plus:SI (match_dup 2) (const_int 8)))
5199 (set (match_operand:SI 1 "register_operand" "=l")
5200 (plus:SI (match_dup 3) (const_int 8)))
5201 (clobber (match_scratch:SI 4 "=&l"))
5202 (clobber (match_scratch:SI 5 "=&l"))]
5204 "* return thumb_output_move_mem_multiple (2, operands);"
5205 [(set_attr "length" "4")
5206 ; This isn't entirely accurate... It loads as well, but in terms of
5207 ; scheduling the following insn it is better to consider it as a store
5208 (set_attr "type" "store2")]
5213 ;; Compare & branch insns
5214 ;; The range calculations are based as follows:
5215 ;; For forward branches, the address calculation returns the address of
5216 ;; the next instruction. This is 2 beyond the branch instruction.
5217 ;; For backward branches, the address calculation returns the address of
5218 ;; the first instruction in this pattern (cmp). This is 2 before the branch
5219 ;; instruction for the shortest sequence, and 4 before the branch instruction
5220 ;; if we have to jump around an unconditional branch.
5221 ;; To the basic branch range the PC offset must be added (this is +4).
5222 ;; So for forward branches we have
5223 ;; (pos_range - pos_base_offs + pc_offs) = (pos_range - 2 + 4).
5224 ;; And for backward branches we have
5225 ;; (neg_range - neg_base_offs + pc_offs) = (neg_range - (-2 or -4) + 4).
5227 ;; For a 'b' pos_range = 2046, neg_range = -2048 giving (-2040->2048).
5228 ;; For a 'b<cond>' pos_range = 254, neg_range = -256 giving (-250 ->256).
5230 (define_expand "cbranchsi4"
5231 [(set (pc) (if_then_else
5232 (match_operator 0 "arm_comparison_operator"
5233 [(match_operand:SI 1 "s_register_operand" "")
5234 (match_operand:SI 2 "nonmemory_operand" "")])
5235 (label_ref (match_operand 3 "" ""))
5239 if (thumb_cmpneg_operand (operands[2], SImode))
5241 emit_jump_insn (gen_cbranchsi4_scratch (NULL, operands[1], operands[2],
5242 operands[3], operands[0]));
5245 if (!thumb_cmp_operand (operands[2], SImode))
5246 operands[2] = force_reg (SImode, operands[2]);
5249 (define_insn "*cbranchsi4_insn"
5250 [(set (pc) (if_then_else
5251 (match_operator 0 "arm_comparison_operator"
5252 [(match_operand:SI 1 "s_register_operand" "l,*h")
5253 (match_operand:SI 2 "thumb_cmp_operand" "lI*h,*r")])
5254 (label_ref (match_operand 3 "" ""))
5258 output_asm_insn (\"cmp\\t%1, %2\", operands);
5260 switch (get_attr_length (insn))
5262 case 4: return \"b%d0\\t%l3\";
5263 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5264 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5267 [(set (attr "far_jump")
5269 (eq_attr "length" "8")
5270 (const_string "yes")
5271 (const_string "no")))
5272 (set (attr "length")
5274 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5275 (le (minus (match_dup 3) (pc)) (const_int 256)))
5278 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5279 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5284 (define_insn "cbranchsi4_scratch"
5285 [(set (pc) (if_then_else
5286 (match_operator 4 "arm_comparison_operator"
5287 [(match_operand:SI 1 "s_register_operand" "l,0")
5288 (match_operand:SI 2 "thumb_cmpneg_operand" "L,J")])
5289 (label_ref (match_operand 3 "" ""))
5291 (clobber (match_scratch:SI 0 "=l,l"))]
5294 output_asm_insn (\"add\\t%0, %1, #%n2\", operands);
5296 switch (get_attr_length (insn))
5298 case 4: return \"b%d4\\t%l3\";
5299 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5300 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5303 [(set (attr "far_jump")
5305 (eq_attr "length" "8")
5306 (const_string "yes")
5307 (const_string "no")))
5308 (set (attr "length")
5310 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5311 (le (minus (match_dup 3) (pc)) (const_int 256)))
5314 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5315 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5319 (define_insn "*movsi_cbranchsi4"
5322 (match_operator 3 "arm_comparison_operator"
5323 [(match_operand:SI 1 "s_register_operand" "0,l,l,l")
5325 (label_ref (match_operand 2 "" ""))
5327 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*h,*m")
5331 if (which_alternative == 0)
5332 output_asm_insn (\"cmp\t%0, #0\", operands);
5333 else if (which_alternative == 1)
5334 output_asm_insn (\"sub\t%0, %1, #0\", operands);
5337 output_asm_insn (\"cmp\t%1, #0\", operands);
5338 if (which_alternative == 2)
5339 output_asm_insn (\"mov\t%0, %1\", operands);
5341 output_asm_insn (\"str\t%1, %0\", operands);
5343 switch (get_attr_length (insn) - ((which_alternative > 1) ? 2 : 0))
5345 case 4: return \"b%d3\\t%l2\";
5346 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5347 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5350 [(set (attr "far_jump")
5352 (ior (and (gt (symbol_ref ("which_alternative"))
5354 (eq_attr "length" "8"))
5355 (eq_attr "length" "10"))
5356 (const_string "yes")
5357 (const_string "no")))
5358 (set (attr "length")
5360 (le (symbol_ref ("which_alternative"))
5363 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5364 (le (minus (match_dup 2) (pc)) (const_int 256)))
5367 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5368 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5372 (and (ge (minus (match_dup 2) (pc)) (const_int -248))
5373 (le (minus (match_dup 2) (pc)) (const_int 256)))
5376 (and (ge (minus (match_dup 2) (pc)) (const_int -2038))
5377 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5382 (define_insn "*negated_cbranchsi4"
5385 (match_operator 0 "arm_comparison_operator"
5386 [(match_operand:SI 1 "s_register_operand" "l")
5387 (neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
5388 (label_ref (match_operand 3 "" ""))
5392 output_asm_insn (\"cmn\\t%1, %2\", operands);
5393 switch (get_attr_length (insn))
5395 case 4: return \"b%d0\\t%l3\";
5396 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5397 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5400 [(set (attr "far_jump")
5402 (eq_attr "length" "8")
5403 (const_string "yes")
5404 (const_string "no")))
5405 (set (attr "length")
5407 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5408 (le (minus (match_dup 3) (pc)) (const_int 256)))
5411 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5412 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5417 (define_insn "*tbit_cbranch"
5420 (match_operator 0 "equality_operator"
5421 [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
5423 (match_operand:SI 2 "const_int_operand" "i"))
5425 (label_ref (match_operand 3 "" ""))
5427 (clobber (match_scratch:SI 4 "=l"))]
5432 op[0] = operands[4];
5433 op[1] = operands[1];
5434 op[2] = GEN_INT (32 - 1 - INTVAL (operands[2]));
5436 output_asm_insn (\"lsl\\t%0, %1, %2\", op);
5437 switch (get_attr_length (insn))
5439 case 4: return \"b%d0\\t%l3\";
5440 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5441 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5444 [(set (attr "far_jump")
5446 (eq_attr "length" "8")
5447 (const_string "yes")
5448 (const_string "no")))
5449 (set (attr "length")
5451 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5452 (le (minus (match_dup 3) (pc)) (const_int 256)))
5455 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5456 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5461 (define_insn "*tstsi3_cbranch"
5464 (match_operator 3 "equality_operator"
5465 [(and:SI (match_operand:SI 0 "s_register_operand" "%l")
5466 (match_operand:SI 1 "s_register_operand" "l"))
5468 (label_ref (match_operand 2 "" ""))
5473 output_asm_insn (\"tst\\t%0, %1\", operands);
5474 switch (get_attr_length (insn))
5476 case 4: return \"b%d3\\t%l2\";
5477 case 6: return \"b%D3\\t.LCB%=\;b\\t%l2\\t%@long jump\\n.LCB%=:\";
5478 default: return \"b%D3\\t.LCB%=\;bl\\t%l2\\t%@far jump\\n.LCB%=:\";
5481 [(set (attr "far_jump")
5483 (eq_attr "length" "8")
5484 (const_string "yes")
5485 (const_string "no")))
5486 (set (attr "length")
5488 (and (ge (minus (match_dup 2) (pc)) (const_int -250))
5489 (le (minus (match_dup 2) (pc)) (const_int 256)))
5492 (and (ge (minus (match_dup 2) (pc)) (const_int -2040))
5493 (le (minus (match_dup 2) (pc)) (const_int 2048)))
5498 (define_insn "*andsi3_cbranch"
5501 (match_operator 5 "equality_operator"
5502 [(and:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5503 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5505 (label_ref (match_operand 4 "" ""))
5507 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5508 (and:SI (match_dup 2) (match_dup 3)))
5509 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5513 if (which_alternative == 0)
5514 output_asm_insn (\"and\\t%0, %3\", operands);
5515 else if (which_alternative == 1)
5517 output_asm_insn (\"and\\t%1, %3\", operands);
5518 output_asm_insn (\"mov\\t%0, %1\", operands);
5522 output_asm_insn (\"and\\t%1, %3\", operands);
5523 output_asm_insn (\"str\\t%1, %0\", operands);
5526 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5528 case 4: return \"b%d5\\t%l4\";
5529 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5530 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5533 [(set (attr "far_jump")
5535 (ior (and (eq (symbol_ref ("which_alternative"))
5537 (eq_attr "length" "8"))
5538 (eq_attr "length" "10"))
5539 (const_string "yes")
5540 (const_string "no")))
5541 (set (attr "length")
5543 (eq (symbol_ref ("which_alternative"))
5546 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5547 (le (minus (match_dup 4) (pc)) (const_int 256)))
5550 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5551 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5555 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5556 (le (minus (match_dup 4) (pc)) (const_int 256)))
5559 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5560 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5565 (define_insn "*orrsi3_cbranch_scratch"
5568 (match_operator 4 "equality_operator"
5569 [(ior:SI (match_operand:SI 1 "s_register_operand" "%0")
5570 (match_operand:SI 2 "s_register_operand" "l"))
5572 (label_ref (match_operand 3 "" ""))
5574 (clobber (match_scratch:SI 0 "=l"))]
5578 output_asm_insn (\"orr\\t%0, %2\", operands);
5579 switch (get_attr_length (insn))
5581 case 4: return \"b%d4\\t%l3\";
5582 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5583 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5586 [(set (attr "far_jump")
5588 (eq_attr "length" "8")
5589 (const_string "yes")
5590 (const_string "no")))
5591 (set (attr "length")
5593 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5594 (le (minus (match_dup 3) (pc)) (const_int 256)))
5597 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5598 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5603 (define_insn "*orrsi3_cbranch"
5606 (match_operator 5 "equality_operator"
5607 [(ior:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5608 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5610 (label_ref (match_operand 4 "" ""))
5612 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5613 (ior:SI (match_dup 2) (match_dup 3)))
5614 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5618 if (which_alternative == 0)
5619 output_asm_insn (\"orr\\t%0, %3\", operands);
5620 else if (which_alternative == 1)
5622 output_asm_insn (\"orr\\t%1, %3\", operands);
5623 output_asm_insn (\"mov\\t%0, %1\", operands);
5627 output_asm_insn (\"orr\\t%1, %3\", operands);
5628 output_asm_insn (\"str\\t%1, %0\", operands);
5631 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5633 case 4: return \"b%d5\\t%l4\";
5634 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5635 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5638 [(set (attr "far_jump")
5640 (ior (and (eq (symbol_ref ("which_alternative"))
5642 (eq_attr "length" "8"))
5643 (eq_attr "length" "10"))
5644 (const_string "yes")
5645 (const_string "no")))
5646 (set (attr "length")
5648 (eq (symbol_ref ("which_alternative"))
5651 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5652 (le (minus (match_dup 4) (pc)) (const_int 256)))
5655 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5656 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5660 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5661 (le (minus (match_dup 4) (pc)) (const_int 256)))
5664 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5665 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5670 (define_insn "*xorsi3_cbranch_scratch"
5673 (match_operator 4 "equality_operator"
5674 [(xor:SI (match_operand:SI 1 "s_register_operand" "%0")
5675 (match_operand:SI 2 "s_register_operand" "l"))
5677 (label_ref (match_operand 3 "" ""))
5679 (clobber (match_scratch:SI 0 "=l"))]
5683 output_asm_insn (\"eor\\t%0, %2\", operands);
5684 switch (get_attr_length (insn))
5686 case 4: return \"b%d4\\t%l3\";
5687 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5688 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5691 [(set (attr "far_jump")
5693 (eq_attr "length" "8")
5694 (const_string "yes")
5695 (const_string "no")))
5696 (set (attr "length")
5698 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5699 (le (minus (match_dup 3) (pc)) (const_int 256)))
5702 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5703 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5708 (define_insn "*xorsi3_cbranch"
5711 (match_operator 5 "equality_operator"
5712 [(xor:SI (match_operand:SI 2 "s_register_operand" "%0,1,1,1")
5713 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5715 (label_ref (match_operand 4 "" ""))
5717 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5718 (xor:SI (match_dup 2) (match_dup 3)))
5719 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5723 if (which_alternative == 0)
5724 output_asm_insn (\"eor\\t%0, %3\", operands);
5725 else if (which_alternative == 1)
5727 output_asm_insn (\"eor\\t%1, %3\", operands);
5728 output_asm_insn (\"mov\\t%0, %1\", operands);
5732 output_asm_insn (\"eor\\t%1, %3\", operands);
5733 output_asm_insn (\"str\\t%1, %0\", operands);
5736 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5738 case 4: return \"b%d5\\t%l4\";
5739 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5740 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5743 [(set (attr "far_jump")
5745 (ior (and (eq (symbol_ref ("which_alternative"))
5747 (eq_attr "length" "8"))
5748 (eq_attr "length" "10"))
5749 (const_string "yes")
5750 (const_string "no")))
5751 (set (attr "length")
5753 (eq (symbol_ref ("which_alternative"))
5756 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5757 (le (minus (match_dup 4) (pc)) (const_int 256)))
5760 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5761 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5765 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5766 (le (minus (match_dup 4) (pc)) (const_int 256)))
5769 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5770 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5775 (define_insn "*bicsi3_cbranch_scratch"
5778 (match_operator 4 "equality_operator"
5779 [(and:SI (not:SI (match_operand:SI 2 "s_register_operand" "l"))
5780 (match_operand:SI 1 "s_register_operand" "0"))
5782 (label_ref (match_operand 3 "" ""))
5784 (clobber (match_scratch:SI 0 "=l"))]
5788 output_asm_insn (\"bic\\t%0, %2\", operands);
5789 switch (get_attr_length (insn))
5791 case 4: return \"b%d4\\t%l3\";
5792 case 6: return \"b%D4\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5793 default: return \"b%D4\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5796 [(set (attr "far_jump")
5798 (eq_attr "length" "8")
5799 (const_string "yes")
5800 (const_string "no")))
5801 (set (attr "length")
5803 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5804 (le (minus (match_dup 3) (pc)) (const_int 256)))
5807 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5808 (le (minus (match_dup 3) (pc)) (const_int 2048)))
5813 (define_insn "*bicsi3_cbranch"
5816 (match_operator 5 "equality_operator"
5817 [(and:SI (not:SI (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
5818 (match_operand:SI 2 "s_register_operand" "0,1,1,1"))
5820 (label_ref (match_operand 4 "" ""))
5822 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5823 (and:SI (not:SI (match_dup 3)) (match_dup 2)))
5824 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5828 if (which_alternative == 0)
5829 output_asm_insn (\"bic\\t%0, %3\", operands);
5830 else if (which_alternative == 1)
5832 output_asm_insn (\"bic\\t%1, %3\", operands);
5833 output_asm_insn (\"mov\\t%0, %1\", operands);
5837 output_asm_insn (\"bic\\t%1, %3\", operands);
5838 output_asm_insn (\"str\\t%1, %0\", operands);
5841 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5843 case 4: return \"b%d5\\t%l4\";
5844 case 6: return \"b%D5\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
5845 default: return \"b%D5\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5848 [(set (attr "far_jump")
5850 (ior (and (eq (symbol_ref ("which_alternative"))
5852 (eq_attr "length" "8"))
5853 (eq_attr "length" "10"))
5854 (const_string "yes")
5855 (const_string "no")))
5856 (set (attr "length")
5858 (eq (symbol_ref ("which_alternative"))
5861 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5862 (le (minus (match_dup 4) (pc)) (const_int 256)))
5865 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5866 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5870 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5871 (le (minus (match_dup 4) (pc)) (const_int 256)))
5874 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5875 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5880 (define_insn "*cbranchne_decr1"
5882 (if_then_else (match_operator 3 "equality_operator"
5883 [(match_operand:SI 2 "s_register_operand" "l,l,1,l")
5885 (label_ref (match_operand 4 "" ""))
5887 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
5888 (plus:SI (match_dup 2) (const_int -1)))
5889 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
5894 cond[0] = gen_rtx_fmt_ee ((GET_CODE (operands[3]) == NE
5896 VOIDmode, operands[2], const1_rtx);
5897 cond[1] = operands[4];
5899 if (which_alternative == 0)
5900 output_asm_insn (\"sub\\t%0, %2, #1\", operands);
5901 else if (which_alternative == 1)
5903 /* We must provide an alternative for a hi reg because reload
5904 cannot handle output reloads on a jump instruction, but we
5905 can't subtract into that. Fortunately a mov from lo to hi
5906 does not clobber the condition codes. */
5907 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
5908 output_asm_insn (\"mov\\t%0, %1\", operands);
5912 /* Similarly, but the target is memory. */
5913 output_asm_insn (\"sub\\t%1, %2, #1\", operands);
5914 output_asm_insn (\"str\\t%1, %0\", operands);
5917 switch (get_attr_length (insn) - (which_alternative ? 2 : 0))
5920 output_asm_insn (\"b%d0\\t%l1\", cond);
5923 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
5924 return \"b\\t%l4\\t%@long jump\\n.LCB%=:\";
5926 output_asm_insn (\"b%D0\\t.LCB%=\", cond);
5927 return \"bl\\t%l4\\t%@far jump\\n.LCB%=:\";
5931 [(set (attr "far_jump")
5933 (ior (and (eq (symbol_ref ("which_alternative"))
5935 (eq_attr "length" "8"))
5936 (eq_attr "length" "10"))
5937 (const_string "yes")
5938 (const_string "no")))
5939 (set_attr_alternative "length"
5943 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
5944 (le (minus (match_dup 4) (pc)) (const_int 256)))
5947 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
5948 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5953 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5954 (le (minus (match_dup 4) (pc)) (const_int 256)))
5957 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5958 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5963 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5964 (le (minus (match_dup 4) (pc)) (const_int 256)))
5967 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5968 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5973 (and (ge (minus (match_dup 4) (pc)) (const_int -248))
5974 (le (minus (match_dup 4) (pc)) (const_int 256)))
5977 (and (ge (minus (match_dup 4) (pc)) (const_int -2038))
5978 (le (minus (match_dup 4) (pc)) (const_int 2048)))
5983 (define_insn "*addsi3_cbranch"
5986 (match_operator 4 "comparison_operator"
5988 (match_operand:SI 2 "s_register_operand" "%l,0,*0,1,1,1")
5989 (match_operand:SI 3 "reg_or_int_operand" "lL,IJ,*r,lIJ,lIJ,lIJ"))
5991 (label_ref (match_operand 5 "" ""))
5994 (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,l,*!h,*?h,*?m,*?m")
5995 (plus:SI (match_dup 2) (match_dup 3)))
5996 (clobber (match_scratch:SI 1 "=X,X,X,l,&l,&l"))]
5998 && (GET_CODE (operands[4]) == EQ
5999 || GET_CODE (operands[4]) == NE
6000 || GET_CODE (operands[4]) == GE
6001 || GET_CODE (operands[4]) == LT)"
6007 cond[0] = (which_alternative < 3) ? operands[0] : operands[1];
6008 cond[1] = operands[2];
6009 cond[2] = operands[3];
6011 if (GET_CODE (cond[2]) == CONST_INT && INTVAL (cond[2]) < 0)
6012 output_asm_insn (\"sub\\t%0, %1, #%n2\", cond);
6014 output_asm_insn (\"add\\t%0, %1, %2\", cond);
6016 if (which_alternative >= 3
6017 && which_alternative < 4)
6018 output_asm_insn (\"mov\\t%0, %1\", operands);
6019 else if (which_alternative >= 4)
6020 output_asm_insn (\"str\\t%1, %0\", operands);
6022 switch (get_attr_length (insn) - ((which_alternative >= 3) ? 2 : 0))
6025 return \"b%d4\\t%l5\";
6027 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6029 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6033 [(set (attr "far_jump")
6035 (ior (and (lt (symbol_ref ("which_alternative"))
6037 (eq_attr "length" "8"))
6038 (eq_attr "length" "10"))
6039 (const_string "yes")
6040 (const_string "no")))
6041 (set (attr "length")
6043 (lt (symbol_ref ("which_alternative"))
6046 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6047 (le (minus (match_dup 5) (pc)) (const_int 256)))
6050 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6051 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6055 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6056 (le (minus (match_dup 5) (pc)) (const_int 256)))
6059 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6060 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6065 (define_insn "*addsi3_cbranch_scratch"
6068 (match_operator 3 "comparison_operator"
6070 (match_operand:SI 1 "s_register_operand" "%l,l,l,0")
6071 (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
6073 (label_ref (match_operand 4 "" ""))
6075 (clobber (match_scratch:SI 0 "=X,X,l,l"))]
6077 && (GET_CODE (operands[3]) == EQ
6078 || GET_CODE (operands[3]) == NE
6079 || GET_CODE (operands[3]) == GE
6080 || GET_CODE (operands[3]) == LT)"
6083 switch (which_alternative)
6086 output_asm_insn (\"cmp\t%1, #%n2\", operands);
6089 output_asm_insn (\"cmn\t%1, %2\", operands);
6092 output_asm_insn (\"add\t%0, %1, %2\", operands);
6095 output_asm_insn (\"add\t%0, %0, %2\", operands);
6099 switch (get_attr_length (insn))
6102 return \"b%d3\\t%l4\";
6104 return \"b%D3\\t.LCB%=\;b\\t%l4\\t%@long jump\\n.LCB%=:\";
6106 return \"b%D3\\t.LCB%=\;bl\\t%l4\\t%@far jump\\n.LCB%=:\";
6110 [(set (attr "far_jump")
6112 (eq_attr "length" "8")
6113 (const_string "yes")
6114 (const_string "no")))
6115 (set (attr "length")
6117 (and (ge (minus (match_dup 4) (pc)) (const_int -250))
6118 (le (minus (match_dup 4) (pc)) (const_int 256)))
6121 (and (ge (minus (match_dup 4) (pc)) (const_int -2040))
6122 (le (minus (match_dup 4) (pc)) (const_int 2048)))
6127 (define_insn "*subsi3_cbranch"
6130 (match_operator 4 "comparison_operator"
6132 (match_operand:SI 2 "s_register_operand" "l,l,1,l")
6133 (match_operand:SI 3 "s_register_operand" "l,l,l,l"))
6135 (label_ref (match_operand 5 "" ""))
6137 (set (match_operand:SI 0 "thumb_cbrch_target_operand" "=l,*?h,*?m,*?m")
6138 (minus:SI (match_dup 2) (match_dup 3)))
6139 (clobber (match_scratch:SI 1 "=X,l,&l,&l"))]
6141 && (GET_CODE (operands[4]) == EQ
6142 || GET_CODE (operands[4]) == NE
6143 || GET_CODE (operands[4]) == GE
6144 || GET_CODE (operands[4]) == LT)"
6147 if (which_alternative == 0)
6148 output_asm_insn (\"sub\\t%0, %2, %3\", operands);
6149 else if (which_alternative == 1)
6151 /* We must provide an alternative for a hi reg because reload
6152 cannot handle output reloads on a jump instruction, but we
6153 can't subtract into that. Fortunately a mov from lo to hi
6154 does not clobber the condition codes. */
6155 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6156 output_asm_insn (\"mov\\t%0, %1\", operands);
6160 /* Similarly, but the target is memory. */
6161 output_asm_insn (\"sub\\t%1, %2, %3\", operands);
6162 output_asm_insn (\"str\\t%1, %0\", operands);
6165 switch (get_attr_length (insn) - ((which_alternative != 0) ? 2 : 0))
6168 return \"b%d4\\t%l5\";
6170 return \"b%D4\\t.LCB%=\;b\\t%l5\\t%@long jump\\n.LCB%=:\";
6172 return \"b%D4\\t.LCB%=\;bl\\t%l5\\t%@far jump\\n.LCB%=:\";
6176 [(set (attr "far_jump")
6178 (ior (and (eq (symbol_ref ("which_alternative"))
6180 (eq_attr "length" "8"))
6181 (eq_attr "length" "10"))
6182 (const_string "yes")
6183 (const_string "no")))
6184 (set (attr "length")
6186 (eq (symbol_ref ("which_alternative"))
6189 (and (ge (minus (match_dup 5) (pc)) (const_int -250))
6190 (le (minus (match_dup 5) (pc)) (const_int 256)))
6193 (and (ge (minus (match_dup 5) (pc)) (const_int -2040))
6194 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6198 (and (ge (minus (match_dup 5) (pc)) (const_int -248))
6199 (le (minus (match_dup 5) (pc)) (const_int 256)))
6202 (and (ge (minus (match_dup 5) (pc)) (const_int -2038))
6203 (le (minus (match_dup 5) (pc)) (const_int 2048)))
6208 (define_insn "*subsi3_cbranch_scratch"
6211 (match_operator 0 "arm_comparison_operator"
6212 [(minus:SI (match_operand:SI 1 "register_operand" "l")
6213 (match_operand:SI 2 "nonmemory_operand" "l"))
6215 (label_ref (match_operand 3 "" ""))
6218 && (GET_CODE (operands[0]) == EQ
6219 || GET_CODE (operands[0]) == NE
6220 || GET_CODE (operands[0]) == GE
6221 || GET_CODE (operands[0]) == LT)"
6223 output_asm_insn (\"cmp\\t%1, %2\", operands);
6224 switch (get_attr_length (insn))
6226 case 4: return \"b%d0\\t%l3\";
6227 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
6228 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
6231 [(set (attr "far_jump")
6233 (eq_attr "length" "8")
6234 (const_string "yes")
6235 (const_string "no")))
6236 (set (attr "length")
6238 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
6239 (le (minus (match_dup 3) (pc)) (const_int 256)))
6242 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
6243 (le (minus (match_dup 3) (pc)) (const_int 2048)))
6248 ;; Comparison and test insns
6250 (define_expand "cmpsi"
6251 [(match_operand:SI 0 "s_register_operand" "")
6252 (match_operand:SI 1 "arm_add_operand" "")]
6255 arm_compare_op0 = operands[0];
6256 arm_compare_op1 = operands[1];
6261 (define_expand "cmpsf"
6262 [(match_operand:SF 0 "s_register_operand" "")
6263 (match_operand:SF 1 "fpa_rhs_operand" "")]
6264 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6266 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
6267 operands[1] = force_reg (SFmode, operands[1]);
6269 arm_compare_op0 = operands[0];
6270 arm_compare_op1 = operands[1];
6275 (define_expand "cmpdf"
6276 [(match_operand:DF 0 "s_register_operand" "")
6277 (match_operand:DF 1 "fpa_rhs_operand" "")]
6278 "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
6280 if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
6281 operands[1] = force_reg (DFmode, operands[1]);
6283 arm_compare_op0 = operands[0];
6284 arm_compare_op1 = operands[1];
6289 (define_insn "*arm_cmpsi_insn"
6290 [(set (reg:CC CC_REGNUM)
6291 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
6292 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
6297 [(set_attr "conds" "set")]
6300 (define_insn "*cmpsi_shiftsi"
6301 [(set (reg:CC CC_REGNUM)
6302 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6303 (match_operator:SI 3 "shift_operator"
6304 [(match_operand:SI 1 "s_register_operand" "r")
6305 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
6308 [(set_attr "conds" "set")
6309 (set_attr "shift" "1")
6313 (define_insn "*cmpsi_shiftsi_swp"
6314 [(set (reg:CC_SWP CC_REGNUM)
6315 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
6316 [(match_operand:SI 1 "s_register_operand" "r")
6317 (match_operand:SI 2 "reg_or_int_operand" "rM")])
6318 (match_operand:SI 0 "s_register_operand" "r")))]
6321 [(set_attr "conds" "set")
6322 (set_attr "shift" "1")
6326 (define_insn "*cmpsi_neg_shiftsi"
6327 [(set (reg:CC CC_REGNUM)
6328 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
6329 (neg:SI (match_operator:SI 3 "shift_operator"
6330 [(match_operand:SI 1 "s_register_operand" "r")
6331 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
6334 [(set_attr "conds" "set")
6335 (set_attr "shift" "1")
6339 ;; Cirrus SF compare instruction
6340 (define_insn "*cirrus_cmpsf"
6341 [(set (reg:CCFP CC_REGNUM)
6342 (compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
6343 (match_operand:SF 1 "cirrus_fp_register" "v")))]
6344 "TARGET_ARM && TARGET_CIRRUS"
6345 "cfcmps%?\\tr15, %V0, %V1"
6346 [(set_attr "type" "mav_farith")
6347 (set_attr "cirrus" "compare")]
6350 ;; Cirrus DF compare instruction
6351 (define_insn "*cirrus_cmpdf"
6352 [(set (reg:CCFP CC_REGNUM)
6353 (compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
6354 (match_operand:DF 1 "cirrus_fp_register" "v")))]
6355 "TARGET_ARM && TARGET_CIRRUS"
6356 "cfcmpd%?\\tr15, %V0, %V1"
6357 [(set_attr "type" "mav_farith")
6358 (set_attr "cirrus" "compare")]
6361 ;; Cirrus DI compare instruction
6362 (define_expand "cmpdi"
6363 [(match_operand:DI 0 "cirrus_fp_register" "")
6364 (match_operand:DI 1 "cirrus_fp_register" "")]
6365 "TARGET_ARM && TARGET_CIRRUS"
6367 arm_compare_op0 = operands[0];
6368 arm_compare_op1 = operands[1];
6372 (define_insn "*cirrus_cmpdi"
6373 [(set (reg:CC CC_REGNUM)
6374 (compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
6375 (match_operand:DI 1 "cirrus_fp_register" "v")))]
6376 "TARGET_ARM && TARGET_CIRRUS"
6377 "cfcmp64%?\\tr15, %V0, %V1"
6378 [(set_attr "type" "mav_farith")
6379 (set_attr "cirrus" "compare")]
6382 ; This insn allows redundant compares to be removed by cse, nothing should
6383 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
6384 ; is deleted later on. The match_dup will match the mode here, so that
6385 ; mode changes of the condition codes aren't lost by this even though we don't
6386 ; specify what they are.
6388 (define_insn "*deleted_compare"
6389 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
6391 "\\t%@ deleted compare"
6392 [(set_attr "conds" "set")
6393 (set_attr "length" "0")]
6397 ;; Conditional branch insns
6399 (define_expand "beq"
6401 (if_then_else (eq (match_dup 1) (const_int 0))
6402 (label_ref (match_operand 0 "" ""))
6405 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6408 (define_expand "bne"
6410 (if_then_else (ne (match_dup 1) (const_int 0))
6411 (label_ref (match_operand 0 "" ""))
6414 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6417 (define_expand "bgt"
6419 (if_then_else (gt (match_dup 1) (const_int 0))
6420 (label_ref (match_operand 0 "" ""))
6423 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6426 (define_expand "ble"
6428 (if_then_else (le (match_dup 1) (const_int 0))
6429 (label_ref (match_operand 0 "" ""))
6432 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6435 (define_expand "bge"
6437 (if_then_else (ge (match_dup 1) (const_int 0))
6438 (label_ref (match_operand 0 "" ""))
6441 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6444 (define_expand "blt"
6446 (if_then_else (lt (match_dup 1) (const_int 0))
6447 (label_ref (match_operand 0 "" ""))
6450 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6453 (define_expand "bgtu"
6455 (if_then_else (gtu (match_dup 1) (const_int 0))
6456 (label_ref (match_operand 0 "" ""))
6459 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6462 (define_expand "bleu"
6464 (if_then_else (leu (match_dup 1) (const_int 0))
6465 (label_ref (match_operand 0 "" ""))
6468 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6471 (define_expand "bgeu"
6473 (if_then_else (geu (match_dup 1) (const_int 0))
6474 (label_ref (match_operand 0 "" ""))
6477 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6480 (define_expand "bltu"
6482 (if_then_else (ltu (match_dup 1) (const_int 0))
6483 (label_ref (match_operand 0 "" ""))
6486 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6489 (define_expand "bunordered"
6491 (if_then_else (unordered (match_dup 1) (const_int 0))
6492 (label_ref (match_operand 0 "" ""))
6494 "TARGET_ARM && TARGET_HARD_FLOAT"
6495 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6499 (define_expand "bordered"
6501 (if_then_else (ordered (match_dup 1) (const_int 0))
6502 (label_ref (match_operand 0 "" ""))
6504 "TARGET_ARM && TARGET_HARD_FLOAT"
6505 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6509 (define_expand "bungt"
6511 (if_then_else (ungt (match_dup 1) (const_int 0))
6512 (label_ref (match_operand 0 "" ""))
6514 "TARGET_ARM && TARGET_HARD_FLOAT"
6515 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
6518 (define_expand "bunlt"
6520 (if_then_else (unlt (match_dup 1) (const_int 0))
6521 (label_ref (match_operand 0 "" ""))
6523 "TARGET_ARM && TARGET_HARD_FLOAT"
6524 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
6527 (define_expand "bunge"
6529 (if_then_else (unge (match_dup 1) (const_int 0))
6530 (label_ref (match_operand 0 "" ""))
6532 "TARGET_ARM && TARGET_HARD_FLOAT"
6533 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
6536 (define_expand "bunle"
6538 (if_then_else (unle (match_dup 1) (const_int 0))
6539 (label_ref (match_operand 0 "" ""))
6541 "TARGET_ARM && TARGET_HARD_FLOAT"
6542 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
6545 ;; The following two patterns need two branch instructions, since there is
6546 ;; no single instruction that will handle all cases.
6547 (define_expand "buneq"
6549 (if_then_else (uneq (match_dup 1) (const_int 0))
6550 (label_ref (match_operand 0 "" ""))
6552 "TARGET_ARM && TARGET_HARD_FLOAT"
6553 "operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
6556 (define_expand "bltgt"
6558 (if_then_else (ltgt (match_dup 1) (const_int 0))
6559 (label_ref (match_operand 0 "" ""))
6561 "TARGET_ARM && TARGET_HARD_FLOAT"
6562 "operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
6566 ;; Patterns to match conditional branch insns.
6569 ; Special pattern to match UNEQ.
6570 (define_insn "*arm_buneq"
6572 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6573 (label_ref (match_operand 0 "" ""))
6575 "TARGET_ARM && TARGET_HARD_FLOAT"
6577 if (arm_ccfsm_state != 0)
6580 return \"bvs\\t%l0\;beq\\t%l0\";
6582 [(set_attr "conds" "jump_clob")
6583 (set_attr "length" "8")]
6586 ; Special pattern to match LTGT.
6587 (define_insn "*arm_bltgt"
6589 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6590 (label_ref (match_operand 0 "" ""))
6592 "TARGET_ARM && TARGET_HARD_FLOAT"
6594 if (arm_ccfsm_state != 0)
6597 return \"bmi\\t%l0\;bgt\\t%l0\";
6599 [(set_attr "conds" "jump_clob")
6600 (set_attr "length" "8")]
6603 (define_insn "*arm_cond_branch"
6605 (if_then_else (match_operator 1 "arm_comparison_operator"
6606 [(match_operand 2 "cc_register" "") (const_int 0)])
6607 (label_ref (match_operand 0 "" ""))
6611 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6613 arm_ccfsm_state += 2;
6616 return \"b%d1\\t%l0\";
6618 [(set_attr "conds" "use")]
6621 ; Special pattern to match reversed UNEQ.
6622 (define_insn "*arm_buneq_reversed"
6624 (if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
6626 (label_ref (match_operand 0 "" ""))))]
6627 "TARGET_ARM && TARGET_HARD_FLOAT"
6629 if (arm_ccfsm_state != 0)
6632 return \"bmi\\t%l0\;bgt\\t%l0\";
6634 [(set_attr "conds" "jump_clob")
6635 (set_attr "length" "8")]
6638 ; Special pattern to match reversed LTGT.
6639 (define_insn "*arm_bltgt_reversed"
6641 (if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
6643 (label_ref (match_operand 0 "" ""))))]
6644 "TARGET_ARM && TARGET_HARD_FLOAT"
6646 if (arm_ccfsm_state != 0)
6649 return \"bvs\\t%l0\;beq\\t%l0\";
6651 [(set_attr "conds" "jump_clob")
6652 (set_attr "length" "8")]
6655 (define_insn "*arm_cond_branch_reversed"
6657 (if_then_else (match_operator 1 "arm_comparison_operator"
6658 [(match_operand 2 "cc_register" "") (const_int 0)])
6660 (label_ref (match_operand 0 "" ""))))]
6663 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6665 arm_ccfsm_state += 2;
6668 return \"b%D1\\t%l0\";
6670 [(set_attr "conds" "use")]
6677 (define_expand "seq"
6678 [(set (match_operand:SI 0 "s_register_operand" "")
6679 (eq:SI (match_dup 1) (const_int 0)))]
6681 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
6684 (define_expand "sne"
6685 [(set (match_operand:SI 0 "s_register_operand" "")
6686 (ne:SI (match_dup 1) (const_int 0)))]
6688 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
6691 (define_expand "sgt"
6692 [(set (match_operand:SI 0 "s_register_operand" "")
6693 (gt:SI (match_dup 1) (const_int 0)))]
6695 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
6698 (define_expand "sle"
6699 [(set (match_operand:SI 0 "s_register_operand" "")
6700 (le:SI (match_dup 1) (const_int 0)))]
6702 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
6705 (define_expand "sge"
6706 [(set (match_operand:SI 0 "s_register_operand" "")
6707 (ge:SI (match_dup 1) (const_int 0)))]
6709 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
6712 (define_expand "slt"
6713 [(set (match_operand:SI 0 "s_register_operand" "")
6714 (lt:SI (match_dup 1) (const_int 0)))]
6716 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
6719 (define_expand "sgtu"
6720 [(set (match_operand:SI 0 "s_register_operand" "")
6721 (gtu:SI (match_dup 1) (const_int 0)))]
6723 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
6726 (define_expand "sleu"
6727 [(set (match_operand:SI 0 "s_register_operand" "")
6728 (leu:SI (match_dup 1) (const_int 0)))]
6730 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
6733 (define_expand "sgeu"
6734 [(set (match_operand:SI 0 "s_register_operand" "")
6735 (geu:SI (match_dup 1) (const_int 0)))]
6737 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
6740 (define_expand "sltu"
6741 [(set (match_operand:SI 0 "s_register_operand" "")
6742 (ltu:SI (match_dup 1) (const_int 0)))]
6744 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
6747 (define_expand "sunordered"
6748 [(set (match_operand:SI 0 "s_register_operand" "")
6749 (unordered:SI (match_dup 1) (const_int 0)))]
6750 "TARGET_ARM && TARGET_HARD_FLOAT"
6751 "operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
6755 (define_expand "sordered"
6756 [(set (match_operand:SI 0 "s_register_operand" "")
6757 (ordered:SI (match_dup 1) (const_int 0)))]
6758 "TARGET_ARM && TARGET_HARD_FLOAT"
6759 "operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
6763 (define_expand "sungt"
6764 [(set (match_operand:SI 0 "s_register_operand" "")
6765 (ungt:SI (match_dup 1) (const_int 0)))]
6766 "TARGET_ARM && TARGET_HARD_FLOAT"
6767 "operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
6771 (define_expand "sunge"
6772 [(set (match_operand:SI 0 "s_register_operand" "")
6773 (unge:SI (match_dup 1) (const_int 0)))]
6774 "TARGET_ARM && TARGET_HARD_FLOAT"
6775 "operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
6779 (define_expand "sunlt"
6780 [(set (match_operand:SI 0 "s_register_operand" "")
6781 (unlt:SI (match_dup 1) (const_int 0)))]
6782 "TARGET_ARM && TARGET_HARD_FLOAT"
6783 "operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
6787 (define_expand "sunle"
6788 [(set (match_operand:SI 0 "s_register_operand" "")
6789 (unle:SI (match_dup 1) (const_int 0)))]
6790 "TARGET_ARM && TARGET_HARD_FLOAT"
6791 "operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
6795 ;;; DO NOT add patterns for SUNEQ or SLTGT, these can't be represented with
6796 ;;; simple ARM instructions.
6798 ; (define_expand "suneq"
6799 ; [(set (match_operand:SI 0 "s_register_operand" "")
6800 ; (uneq:SI (match_dup 1) (const_int 0)))]
6801 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6805 ; (define_expand "sltgt"
6806 ; [(set (match_operand:SI 0 "s_register_operand" "")
6807 ; (ltgt:SI (match_dup 1) (const_int 0)))]
6808 ; "TARGET_ARM && TARGET_HARD_FLOAT"
6812 (define_insn "*mov_scc"
6813 [(set (match_operand:SI 0 "s_register_operand" "=r")
6814 (match_operator:SI 1 "arm_comparison_operator"
6815 [(match_operand 2 "cc_register" "") (const_int 0)]))]
6817 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
6818 [(set_attr "conds" "use")
6819 (set_attr "length" "8")]
6822 (define_insn "*mov_negscc"
6823 [(set (match_operand:SI 0 "s_register_operand" "=r")
6824 (neg:SI (match_operator:SI 1 "arm_comparison_operator"
6825 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6827 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
6828 [(set_attr "conds" "use")
6829 (set_attr "length" "8")]
6832 (define_insn "*mov_notscc"
6833 [(set (match_operand:SI 0 "s_register_operand" "=r")
6834 (not:SI (match_operator:SI 1 "arm_comparison_operator"
6835 [(match_operand 2 "cc_register" "") (const_int 0)])))]
6837 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
6838 [(set_attr "conds" "use")
6839 (set_attr "length" "8")]
6843 ;; Conditional move insns
6845 (define_expand "movsicc"
6846 [(set (match_operand:SI 0 "s_register_operand" "")
6847 (if_then_else:SI (match_operand 1 "arm_comparison_operator" "")
6848 (match_operand:SI 2 "arm_not_operand" "")
6849 (match_operand:SI 3 "arm_not_operand" "")))]
6853 enum rtx_code code = GET_CODE (operands[1]);
6856 if (code == UNEQ || code == LTGT)
6859 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6860 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6864 (define_expand "movsfcc"
6865 [(set (match_operand:SF 0 "s_register_operand" "")
6866 (if_then_else:SF (match_operand 1 "arm_comparison_operator" "")
6867 (match_operand:SF 2 "s_register_operand" "")
6868 (match_operand:SF 3 "nonmemory_operand" "")))]
6872 enum rtx_code code = GET_CODE (operands[1]);
6875 if (code == UNEQ || code == LTGT)
6878 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
6879 Otherwise, ensure it is a valid FP add operand */
6880 if ((!TARGET_HARD_FLOAT)
6881 || (!fpa_add_operand (operands[3], SFmode)))
6882 operands[3] = force_reg (SFmode, operands[3]);
6884 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6885 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6889 (define_expand "movdfcc"
6890 [(set (match_operand:DF 0 "s_register_operand" "")
6891 (if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
6892 (match_operand:DF 2 "s_register_operand" "")
6893 (match_operand:DF 3 "fpa_add_operand" "")))]
6894 "TARGET_ARM && TARGET_HARD_FLOAT"
6897 enum rtx_code code = GET_CODE (operands[1]);
6900 if (code == UNEQ || code == LTGT)
6903 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
6904 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
6908 (define_insn "*movsicc_insn"
6909 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
6911 (match_operator 3 "arm_comparison_operator"
6912 [(match_operand 4 "cc_register" "") (const_int 0)])
6913 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
6914 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
6921 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
6922 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
6923 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
6924 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
6925 [(set_attr "length" "4,4,4,4,8,8,8,8")
6926 (set_attr "conds" "use")]
6929 (define_insn "*movsfcc_soft_insn"
6930 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
6931 (if_then_else:SF (match_operator 3 "arm_comparison_operator"
6932 [(match_operand 4 "cc_register" "") (const_int 0)])
6933 (match_operand:SF 1 "s_register_operand" "0,r")
6934 (match_operand:SF 2 "s_register_operand" "r,0")))]
6935 "TARGET_ARM && TARGET_SOFT_FLOAT"
6939 [(set_attr "conds" "use")]
6943 ;; Jump and linkage insns
6945 (define_expand "jump"
6947 (label_ref (match_operand 0 "" "")))]
6952 (define_insn "*arm_jump"
6954 (label_ref (match_operand 0 "" "")))]
6958 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
6960 arm_ccfsm_state += 2;
6963 return \"b%?\\t%l0\";
6966 [(set_attr "predicable" "yes")]
6969 (define_insn "*thumb_jump"
6971 (label_ref (match_operand 0 "" "")))]
6974 if (get_attr_length (insn) == 2)
6976 return \"bl\\t%l0\\t%@ far jump\";
6978 [(set (attr "far_jump")
6980 (eq_attr "length" "4")
6981 (const_string "yes")
6982 (const_string "no")))
6983 (set (attr "length")
6985 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
6986 (le (minus (match_dup 0) (pc)) (const_int 2044)))
6991 (define_expand "call"
6992 [(parallel [(call (match_operand 0 "memory_operand" "")
6993 (match_operand 1 "general_operand" ""))
6994 (use (match_operand 2 "" ""))
6995 (clobber (reg:SI LR_REGNUM))])]
7001 /* In an untyped call, we can get NULL for operand 2. */
7002 if (operands[2] == NULL_RTX)
7003 operands[2] = const0_rtx;
7005 /* This is to decide if we should generate indirect calls by loading the
7006 32 bit address of the callee into a register before performing the
7007 branch and link. operand[2] encodes the long_call/short_call
7008 attribute of the function being called. This attribute is set whenever
7009 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
7010 is used, and the short_call attribute can also be set if function is
7011 declared as static or if it has already been defined in the current
7012 compilation unit. See arm.c and arm.h for info about this. The third
7013 parameter to arm_is_longcall_p is used to tell it which pattern
7015 callee = XEXP (operands[0], 0);
7017 if (GET_CODE (callee) != REG
7018 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
7019 XEXP (operands[0], 0) = force_reg (Pmode, callee);
7023 (define_insn "*call_reg"
7024 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
7025 (match_operand 1 "" ""))
7026 (use (match_operand 2 "" ""))
7027 (clobber (reg:SI LR_REGNUM))]
7030 return output_call (operands);
7032 ;; length is worst case, normally it is only two
7033 [(set_attr "length" "12")
7034 (set_attr "type" "call")]
7037 (define_insn "*call_mem"
7038 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
7039 (match_operand 1 "" ""))
7040 (use (match_operand 2 "" ""))
7041 (clobber (reg:SI LR_REGNUM))]
7044 return output_call_mem (operands);
7046 [(set_attr "length" "12")
7047 (set_attr "type" "call")]
7050 (define_insn "*call_indirect"
7051 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
7052 (match_operand 1 "" ""))
7053 (use (match_operand 2 "" ""))
7054 (clobber (reg:SI LR_REGNUM))]
7058 if (TARGET_CALLER_INTERWORKING)
7059 return \"bl\\t%__interwork_call_via_%0\";
7061 return \"bl\\t%__call_via_%0\";
7063 [(set_attr "type" "call")]
7066 (define_insn "*call_value_indirect"
7067 [(set (match_operand 0 "" "")
7068 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
7069 (match_operand 2 "" "")))
7070 (use (match_operand 3 "" ""))
7071 (clobber (reg:SI LR_REGNUM))]
7075 if (TARGET_CALLER_INTERWORKING)
7076 return \"bl\\t%__interwork_call_via_%1\";
7078 return \"bl\\t%__call_via_%1\";
7080 [(set_attr "type" "call")]
7083 (define_expand "call_value"
7084 [(parallel [(set (match_operand 0 "" "")
7085 (call (match_operand 1 "memory_operand" "")
7086 (match_operand 2 "general_operand" "")))
7087 (use (match_operand 3 "" ""))
7088 (clobber (reg:SI LR_REGNUM))])]
7092 rtx callee = XEXP (operands[1], 0);
7094 /* In an untyped call, we can get NULL for operand 2. */
7095 if (operands[3] == 0)
7096 operands[3] = const0_rtx;
7098 /* See the comment in define_expand \"call\". */
7099 if (GET_CODE (callee) != REG
7100 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
7101 XEXP (operands[1], 0) = force_reg (Pmode, callee);
7105 (define_insn "*call_value_reg"
7106 [(set (match_operand 0 "" "")
7107 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
7108 (match_operand 2 "" "")))
7109 (use (match_operand 3 "" ""))
7110 (clobber (reg:SI LR_REGNUM))]
7113 return output_call (&operands[1]);
7115 [(set_attr "length" "12")
7116 (set_attr "type" "call")]
7119 (define_insn "*call_value_mem"
7120 [(set (match_operand 0 "" "")
7121 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
7122 (match_operand 2 "" "")))
7123 (use (match_operand 3 "" ""))
7124 (clobber (reg:SI LR_REGNUM))]
7125 "TARGET_ARM && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
7127 return output_call_mem (&operands[1]);
7129 [(set_attr "length" "12")
7130 (set_attr "type" "call")]
7133 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
7134 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
7136 (define_insn "*call_symbol"
7137 [(call (mem:SI (match_operand:SI 0 "" ""))
7138 (match_operand 1 "" ""))
7139 (use (match_operand 2 "" ""))
7140 (clobber (reg:SI LR_REGNUM))]
7142 && (GET_CODE (operands[0]) == SYMBOL_REF)
7143 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7146 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
7148 [(set_attr "type" "call")]
7151 (define_insn "*call_value_symbol"
7152 [(set (match_operand 0 "s_register_operand" "")
7153 (call (mem:SI (match_operand:SI 1 "" ""))
7154 (match_operand:SI 2 "" "")))
7155 (use (match_operand 3 "" ""))
7156 (clobber (reg:SI LR_REGNUM))]
7158 && (GET_CODE (operands[1]) == SYMBOL_REF)
7159 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7162 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
7164 [(set_attr "type" "call")]
7167 (define_insn "*call_insn"
7168 [(call (mem:SI (match_operand:SI 0 "" ""))
7169 (match_operand:SI 1 "" ""))
7170 (use (match_operand 2 "" ""))
7171 (clobber (reg:SI LR_REGNUM))]
7173 && GET_CODE (operands[0]) == SYMBOL_REF
7174 && !arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
7176 [(set_attr "length" "4")
7177 (set_attr "type" "call")]
7180 (define_insn "*call_value_insn"
7181 [(set (match_operand 0 "register_operand" "")
7182 (call (mem:SI (match_operand 1 "" ""))
7183 (match_operand 2 "" "")))
7184 (use (match_operand 3 "" ""))
7185 (clobber (reg:SI LR_REGNUM))]
7187 && GET_CODE (operands[1]) == SYMBOL_REF
7188 && !arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
7190 [(set_attr "length" "4")
7191 (set_attr "type" "call")]
7194 ;; We may also be able to do sibcalls for Thumb, but it's much harder...
7195 (define_expand "sibcall"
7196 [(parallel [(call (match_operand 0 "memory_operand" "")
7197 (match_operand 1 "general_operand" ""))
7199 (use (match_operand 2 "" ""))])]
7203 if (operands[2] == NULL_RTX)
7204 operands[2] = const0_rtx;
7208 (define_expand "sibcall_value"
7209 [(parallel [(set (match_operand 0 "register_operand" "")
7210 (call (match_operand 1 "memory_operand" "")
7211 (match_operand 2 "general_operand" "")))
7213 (use (match_operand 3 "" ""))])]
7217 if (operands[3] == NULL_RTX)
7218 operands[3] = const0_rtx;
7222 (define_insn "*sibcall_insn"
7223 [(call (mem:SI (match_operand:SI 0 "" "X"))
7224 (match_operand 1 "" ""))
7226 (use (match_operand 2 "" ""))]
7227 "TARGET_ARM && GET_CODE (operands[0]) == SYMBOL_REF"
7229 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7231 [(set_attr "type" "call")]
7234 (define_insn "*sibcall_value_insn"
7235 [(set (match_operand 0 "s_register_operand" "")
7236 (call (mem:SI (match_operand:SI 1 "" "X"))
7237 (match_operand 2 "" "")))
7239 (use (match_operand 3 "" ""))]
7240 "TARGET_ARM && GET_CODE (operands[1]) == SYMBOL_REF"
7242 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7244 [(set_attr "type" "call")]
7247 ;; Often the return insn will be the same as loading from memory, so set attr
7248 (define_insn "return"
7250 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
7253 if (arm_ccfsm_state == 2)
7255 arm_ccfsm_state += 2;
7258 return output_return_instruction (const_true_rtx, TRUE, FALSE);
7260 [(set_attr "type" "load")
7261 (set_attr "length" "12")
7262 (set_attr "predicable" "yes")]
7265 (define_insn "*cond_return"
7267 (if_then_else (match_operator 0 "arm_comparison_operator"
7268 [(match_operand 1 "cc_register" "") (const_int 0)])
7271 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7274 if (arm_ccfsm_state == 2)
7276 arm_ccfsm_state += 2;
7279 return output_return_instruction (operands[0], TRUE, FALSE);
7281 [(set_attr "conds" "use")
7282 (set_attr "length" "12")
7283 (set_attr "type" "load")]
7286 (define_insn "*cond_return_inverted"
7288 (if_then_else (match_operator 0 "arm_comparison_operator"
7289 [(match_operand 1 "cc_register" "") (const_int 0)])
7292 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
7295 if (arm_ccfsm_state == 2)
7297 arm_ccfsm_state += 2;
7300 return output_return_instruction (operands[0], TRUE, TRUE);
7302 [(set_attr "conds" "use")
7303 (set_attr "type" "load")]
7306 ;; Generate a sequence of instructions to determine if the processor is
7307 ;; in 26-bit or 32-bit mode, and return the appropriate return address
7310 (define_expand "return_addr_mask"
7312 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7314 (set (match_operand:SI 0 "s_register_operand" "")
7315 (if_then_else:SI (eq (match_dup 1) (const_int 0))
7317 (const_int 67108860)))] ; 0x03fffffc
7320 operands[1] = gen_rtx_REG (CC_NOOVmode, CC_REGNUM);
7323 (define_insn "*check_arch2"
7324 [(set (match_operand:CC_NOOV 0 "cc_register" "")
7325 (compare:CC_NOOV (unspec [(const_int 0)] UNSPEC_CHECK_ARCH)
7328 "teq\\t%|r0, %|r0\;teq\\t%|pc, %|pc"
7329 [(set_attr "length" "8")
7330 (set_attr "conds" "set")]
7333 ;; Call subroutine returning any type.
7335 (define_expand "untyped_call"
7336 [(parallel [(call (match_operand 0 "" "")
7338 (match_operand 1 "" "")
7339 (match_operand 2 "" "")])]
7345 emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
7347 for (i = 0; i < XVECLEN (operands[2], 0); i++)
7349 rtx set = XVECEXP (operands[2], 0, i);
7351 emit_move_insn (SET_DEST (set), SET_SRC (set));
7354 /* The optimizer does not know that the call sets the function value
7355 registers we stored in the result block. We avoid problems by
7356 claiming that all hard registers are used and clobbered at this
7358 emit_insn (gen_blockage ());
7364 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
7365 ;; all of memory. This blocks insns from being moved across this point.
7367 (define_insn "blockage"
7368 [(unspec_volatile [(const_int 0)] VUNSPEC_BLOCKAGE)]
7371 [(set_attr "length" "0")
7372 (set_attr "type" "block")]
7375 (define_expand "casesi"
7376 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
7377 (match_operand:SI 1 "const_int_operand" "") ; lower bound
7378 (match_operand:SI 2 "const_int_operand" "") ; total range
7379 (match_operand:SI 3 "" "") ; table label
7380 (match_operand:SI 4 "" "")] ; Out of range label
7385 if (operands[1] != const0_rtx)
7387 reg = gen_reg_rtx (SImode);
7389 emit_insn (gen_addsi3 (reg, operands[0],
7390 GEN_INT (-INTVAL (operands[1]))));
7394 if (!const_ok_for_arm (INTVAL (operands[2])))
7395 operands[2] = force_reg (SImode, operands[2]);
7397 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
7403 ;; The USE in this pattern is needed to tell flow analysis that this is
7404 ;; a CASESI insn. It has no other purpose.
7405 (define_insn "casesi_internal"
7406 [(parallel [(set (pc)
7408 (leu (match_operand:SI 0 "s_register_operand" "r")
7409 (match_operand:SI 1 "arm_rhs_operand" "rI"))
7410 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
7411 (label_ref (match_operand 2 "" ""))))
7412 (label_ref (match_operand 3 "" ""))))
7413 (clobber (reg:CC CC_REGNUM))
7414 (use (label_ref (match_dup 2)))])]
7418 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
7419 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
7421 [(set_attr "conds" "clob")
7422 (set_attr "length" "12")]
7425 (define_expand "indirect_jump"
7427 (match_operand:SI 0 "s_register_operand" ""))]
7432 (define_insn "*arm_indirect_jump"
7434 (match_operand:SI 0 "s_register_operand" "r"))]
7436 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
7437 [(set_attr "predicable" "yes")]
7440 ;; Although not supported by the define_expand above,
7441 ;; cse/combine may generate this form.
7442 (define_insn "*load_indirect_jump"
7444 (match_operand:SI 0 "memory_operand" "m"))]
7446 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
7447 [(set_attr "type" "load")
7448 (set_attr "pool_range" "4096")
7449 (set_attr "neg_pool_range" "4084")
7450 (set_attr "predicable" "yes")]
7453 (define_insn "*thumb_indirect_jump"
7455 (match_operand:SI 0 "register_operand" "l*r"))]
7458 [(set_attr "conds" "clob")
7459 (set_attr "length" "2")]
7470 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
7471 return \"mov\\tr8, r8\";
7473 [(set (attr "length")
7474 (if_then_else (eq_attr "is_thumb" "yes")
7480 ;; Patterns to allow combination of arithmetic, cond code and shifts
7482 (define_insn "*arith_shiftsi"
7483 [(set (match_operand:SI 0 "s_register_operand" "=r")
7484 (match_operator:SI 1 "shiftable_operator"
7485 [(match_operator:SI 3 "shift_operator"
7486 [(match_operand:SI 4 "s_register_operand" "r")
7487 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7488 (match_operand:SI 2 "s_register_operand" "r")]))]
7490 "%i1%?\\t%0, %2, %4%S3"
7491 [(set_attr "predicable" "yes")
7492 (set_attr "shift" "4")
7496 (define_insn "*arith_shiftsi_compare0"
7497 [(set (reg:CC_NOOV CC_REGNUM)
7498 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7499 [(match_operator:SI 3 "shift_operator"
7500 [(match_operand:SI 4 "s_register_operand" "r")
7501 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7502 (match_operand:SI 2 "s_register_operand" "r")])
7504 (set (match_operand:SI 0 "s_register_operand" "=r")
7505 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
7508 "%i1%?s\\t%0, %2, %4%S3"
7509 [(set_attr "conds" "set")
7510 (set_attr "shift" "4")
7514 (define_insn "*arith_shiftsi_compare0_scratch"
7515 [(set (reg:CC_NOOV CC_REGNUM)
7516 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
7517 [(match_operator:SI 3 "shift_operator"
7518 [(match_operand:SI 4 "s_register_operand" "r")
7519 (match_operand:SI 5 "reg_or_int_operand" "rI")])
7520 (match_operand:SI 2 "s_register_operand" "r")])
7522 (clobber (match_scratch:SI 0 "=r"))]
7524 "%i1%?s\\t%0, %2, %4%S3"
7525 [(set_attr "conds" "set")
7526 (set_attr "shift" "4")
7530 (define_insn "*sub_shiftsi"
7531 [(set (match_operand:SI 0 "s_register_operand" "=r")
7532 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7533 (match_operator:SI 2 "shift_operator"
7534 [(match_operand:SI 3 "s_register_operand" "r")
7535 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
7537 "sub%?\\t%0, %1, %3%S2"
7538 [(set_attr "predicable" "yes")
7539 (set_attr "shift" "3")
7543 (define_insn "*sub_shiftsi_compare0"
7544 [(set (reg:CC_NOOV CC_REGNUM)
7546 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7547 (match_operator:SI 2 "shift_operator"
7548 [(match_operand:SI 3 "s_register_operand" "r")
7549 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7551 (set (match_operand:SI 0 "s_register_operand" "=r")
7552 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7555 "sub%?s\\t%0, %1, %3%S2"
7556 [(set_attr "conds" "set")
7557 (set_attr "shift" "3")
7561 (define_insn "*sub_shiftsi_compare0_scratch"
7562 [(set (reg:CC_NOOV CC_REGNUM)
7564 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
7565 (match_operator:SI 2 "shift_operator"
7566 [(match_operand:SI 3 "s_register_operand" "r")
7567 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
7569 (clobber (match_scratch:SI 0 "=r"))]
7571 "sub%?s\\t%0, %1, %3%S2"
7572 [(set_attr "conds" "set")
7573 (set_attr "shift" "3")
7579 (define_insn "*and_scc"
7580 [(set (match_operand:SI 0 "s_register_operand" "=r")
7581 (and:SI (match_operator:SI 1 "arm_comparison_operator"
7582 [(match_operand 3 "cc_register" "") (const_int 0)])
7583 (match_operand:SI 2 "s_register_operand" "r")))]
7585 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
7586 [(set_attr "conds" "use")
7587 (set_attr "length" "8")]
7590 (define_insn "*ior_scc"
7591 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7592 (ior:SI (match_operator:SI 2 "arm_comparison_operator"
7593 [(match_operand 3 "cc_register" "") (const_int 0)])
7594 (match_operand:SI 1 "s_register_operand" "0,?r")))]
7598 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
7599 [(set_attr "conds" "use")
7600 (set_attr "length" "4,8")]
7603 (define_insn "*compare_scc"
7604 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7605 (match_operator:SI 1 "arm_comparison_operator"
7606 [(match_operand:SI 2 "s_register_operand" "r,r")
7607 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
7608 (clobber (reg:CC CC_REGNUM))]
7611 if (operands[3] == const0_rtx)
7613 if (GET_CODE (operands[1]) == LT)
7614 return \"mov\\t%0, %2, lsr #31\";
7616 if (GET_CODE (operands[1]) == GE)
7617 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
7619 if (GET_CODE (operands[1]) == EQ)
7620 return \"rsbs\\t%0, %2, #1\;movcc\\t%0, #0\";
7623 if (GET_CODE (operands[1]) == NE)
7625 if (which_alternative == 1)
7626 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
7627 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
7629 if (which_alternative == 1)
7630 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
7632 output_asm_insn (\"cmp\\t%2, %3\", operands);
7633 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
7635 [(set_attr "conds" "clob")
7636 (set_attr "length" "12")]
7639 (define_insn "*cond_move"
7640 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7641 (if_then_else:SI (match_operator 3 "equality_operator"
7642 [(match_operator 4 "arm_comparison_operator"
7643 [(match_operand 5 "cc_register" "") (const_int 0)])
7645 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
7646 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
7649 if (GET_CODE (operands[3]) == NE)
7651 if (which_alternative != 1)
7652 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
7653 if (which_alternative != 0)
7654 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
7657 if (which_alternative != 0)
7658 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7659 if (which_alternative != 1)
7660 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
7663 [(set_attr "conds" "use")
7664 (set_attr "length" "4,4,8")]
7667 (define_insn "*cond_arith"
7668 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7669 (match_operator:SI 5 "shiftable_operator"
7670 [(match_operator:SI 4 "arm_comparison_operator"
7671 [(match_operand:SI 2 "s_register_operand" "r,r")
7672 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
7673 (match_operand:SI 1 "s_register_operand" "0,?r")]))
7674 (clobber (reg:CC CC_REGNUM))]
7677 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
7678 return \"%i5\\t%0, %1, %2, lsr #31\";
7680 output_asm_insn (\"cmp\\t%2, %3\", operands);
7681 if (GET_CODE (operands[5]) == AND)
7682 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
7683 else if (GET_CODE (operands[5]) == MINUS)
7684 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
7685 else if (which_alternative != 0)
7686 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7687 return \"%i5%d4\\t%0, %1, #1\";
7689 [(set_attr "conds" "clob")
7690 (set_attr "length" "12")]
7693 (define_insn "*cond_sub"
7694 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7695 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
7696 (match_operator:SI 4 "arm_comparison_operator"
7697 [(match_operand:SI 2 "s_register_operand" "r,r")
7698 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
7699 (clobber (reg:CC CC_REGNUM))]
7702 output_asm_insn (\"cmp\\t%2, %3\", operands);
7703 if (which_alternative != 0)
7704 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
7705 return \"sub%d4\\t%0, %1, #1\";
7707 [(set_attr "conds" "clob")
7708 (set_attr "length" "8,12")]
7711 (define_insn "*cmp_ite0"
7712 [(set (match_operand 6 "dominant_cc_register" "")
7715 (match_operator 4 "arm_comparison_operator"
7716 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7717 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7718 (match_operator:SI 5 "arm_comparison_operator"
7719 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7720 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7726 static const char * const opcodes[4][2] =
7728 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7729 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7730 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7731 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7732 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7733 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7734 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7735 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7738 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7740 return opcodes[which_alternative][swap];
7742 [(set_attr "conds" "set")
7743 (set_attr "length" "8")]
7746 (define_insn "*cmp_ite1"
7747 [(set (match_operand 6 "dominant_cc_register" "")
7750 (match_operator 4 "arm_comparison_operator"
7751 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7752 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7753 (match_operator:SI 5 "arm_comparison_operator"
7754 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7755 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
7761 static const char * const opcodes[4][2] =
7763 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\",
7764 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7765 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\",
7766 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7767 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\",
7768 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7769 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
7770 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7773 comparison_dominates_p (GET_CODE (operands[5]),
7774 reverse_condition (GET_CODE (operands[4])));
7776 return opcodes[which_alternative][swap];
7778 [(set_attr "conds" "set")
7779 (set_attr "length" "8")]
7782 (define_insn "*cmp_and"
7783 [(set (match_operand 6 "dominant_cc_register" "")
7786 (match_operator 4 "arm_comparison_operator"
7787 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7788 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7789 (match_operator:SI 5 "arm_comparison_operator"
7790 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7791 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7796 static const char *const opcodes[4][2] =
7798 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",
7799 \"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
7800 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\",
7801 \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
7802 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\",
7803 \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
7804 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
7805 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
7808 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7810 return opcodes[which_alternative][swap];
7812 [(set_attr "conds" "set")
7813 (set_attr "predicable" "no")
7814 (set_attr "length" "8")]
7817 (define_insn "*cmp_ior"
7818 [(set (match_operand 6 "dominant_cc_register" "")
7821 (match_operator 4 "arm_comparison_operator"
7822 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
7823 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
7824 (match_operator:SI 5 "arm_comparison_operator"
7825 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
7826 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")]))
7831 static const char *const opcodes[4][2] =
7833 {\"cmp\\t%0, %1\;cmp%D4\\t%2, %3\",
7834 \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
7835 {\"cmn\\t%0, #%n1\;cmp%D4\\t%2, %3\",
7836 \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
7837 {\"cmp\\t%0, %1\;cmn%D4\\t%2, #%n3\",
7838 \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
7839 {\"cmn\\t%0, #%n1\;cmn%D4\\t%2, #%n3\",
7840 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
7843 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
7845 return opcodes[which_alternative][swap];
7848 [(set_attr "conds" "set")
7849 (set_attr "length" "8")]
7852 (define_insn_and_split "*ior_scc_scc"
7853 [(set (match_operand:SI 0 "s_register_operand" "=r")
7854 (ior:SI (match_operator:SI 3 "arm_comparison_operator"
7855 [(match_operand:SI 1 "s_register_operand" "r")
7856 (match_operand:SI 2 "arm_add_operand" "rIL")])
7857 (match_operator:SI 6 "arm_comparison_operator"
7858 [(match_operand:SI 4 "s_register_operand" "r")
7859 (match_operand:SI 5 "arm_add_operand" "rIL")])))
7860 (clobber (reg:CC CC_REGNUM))]
7862 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_OR_Y)
7865 "TARGET_ARM && reload_completed"
7869 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7870 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7872 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
7874 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
7877 [(set_attr "conds" "clob")
7878 (set_attr "length" "16")])
7880 ; If the above pattern is followed by a CMP insn, then the compare is
7881 ; redundant, since we can rework the conditional instruction that follows.
7882 (define_insn_and_split "*ior_scc_scc_cmp"
7883 [(set (match_operand 0 "dominant_cc_register" "")
7884 (compare (ior:SI (match_operator:SI 3 "arm_comparison_operator"
7885 [(match_operand:SI 1 "s_register_operand" "r")
7886 (match_operand:SI 2 "arm_add_operand" "rIL")])
7887 (match_operator:SI 6 "arm_comparison_operator"
7888 [(match_operand:SI 4 "s_register_operand" "r")
7889 (match_operand:SI 5 "arm_add_operand" "rIL")]))
7891 (set (match_operand:SI 7 "s_register_operand" "=r")
7892 (ior:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7893 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
7896 "TARGET_ARM && reload_completed"
7900 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7901 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7903 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
7905 [(set_attr "conds" "set")
7906 (set_attr "length" "16")])
7908 (define_insn_and_split "*and_scc_scc"
7909 [(set (match_operand:SI 0 "s_register_operand" "=r")
7910 (and:SI (match_operator:SI 3 "arm_comparison_operator"
7911 [(match_operand:SI 1 "s_register_operand" "r")
7912 (match_operand:SI 2 "arm_add_operand" "rIL")])
7913 (match_operator:SI 6 "arm_comparison_operator"
7914 [(match_operand:SI 4 "s_register_operand" "r")
7915 (match_operand:SI 5 "arm_add_operand" "rIL")])))
7916 (clobber (reg:CC CC_REGNUM))]
7918 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7921 "TARGET_ARM && reload_completed
7922 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7927 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7928 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7930 (set (match_dup 0) (ne:SI (match_dup 7) (const_int 0)))]
7932 = gen_rtx_REG (arm_select_dominance_cc_mode (operands[3], operands[6],
7935 [(set_attr "conds" "clob")
7936 (set_attr "length" "16")])
7938 ; If the above pattern is followed by a CMP insn, then the compare is
7939 ; redundant, since we can rework the conditional instruction that follows.
7940 (define_insn_and_split "*and_scc_scc_cmp"
7941 [(set (match_operand 0 "dominant_cc_register" "")
7942 (compare (and:SI (match_operator:SI 3 "arm_comparison_operator"
7943 [(match_operand:SI 1 "s_register_operand" "r")
7944 (match_operand:SI 2 "arm_add_operand" "rIL")])
7945 (match_operator:SI 6 "arm_comparison_operator"
7946 [(match_operand:SI 4 "s_register_operand" "r")
7947 (match_operand:SI 5 "arm_add_operand" "rIL")]))
7949 (set (match_operand:SI 7 "s_register_operand" "=r")
7950 (and:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7951 (match_op_dup 6 [(match_dup 4) (match_dup 5)])))]
7954 "TARGET_ARM && reload_completed"
7958 (match_op_dup 3 [(match_dup 1) (match_dup 2)])
7959 (match_op_dup 6 [(match_dup 4) (match_dup 5)]))
7961 (set (match_dup 7) (ne:SI (match_dup 0) (const_int 0)))]
7963 [(set_attr "conds" "set")
7964 (set_attr "length" "16")])
7966 ;; If there is no dominance in the comparison, then we can still save an
7967 ;; instruction in the AND case, since we can know that the second compare
7968 ;; need only zero the value if false (if true, then the value is already
7970 (define_insn_and_split "*and_scc_scc_nodom"
7971 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
7972 (and:SI (match_operator:SI 3 "arm_comparison_operator"
7973 [(match_operand:SI 1 "s_register_operand" "r,r,0")
7974 (match_operand:SI 2 "arm_add_operand" "rIL,0,rIL")])
7975 (match_operator:SI 6 "arm_comparison_operator"
7976 [(match_operand:SI 4 "s_register_operand" "r,r,r")
7977 (match_operand:SI 5 "arm_add_operand" "rIL,rIL,rIL")])))
7978 (clobber (reg:CC CC_REGNUM))]
7980 && (arm_select_dominance_cc_mode (operands[3], operands[6], DOM_CC_X_AND_Y)
7983 "TARGET_ARM && reload_completed"
7984 [(parallel [(set (match_dup 0)
7985 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
7986 (clobber (reg:CC CC_REGNUM))])
7987 (set (match_dup 7) (match_op_dup 8 [(match_dup 4) (match_dup 5)]))
7989 (if_then_else:SI (match_op_dup 6 [(match_dup 7) (const_int 0)])
7992 "operands[7] = gen_rtx_REG (SELECT_CC_MODE (GET_CODE (operands[6]),
7993 operands[4], operands[5]),
7995 operands[8] = gen_rtx_COMPARE (GET_MODE (operands[7]), operands[4],
7997 [(set_attr "conds" "clob")
7998 (set_attr "length" "20")])
8001 [(set (reg:CC_NOOV CC_REGNUM)
8002 (compare:CC_NOOV (ior:SI
8003 (and:SI (match_operand:SI 0 "s_register_operand" "")
8005 (match_operator:SI 1 "comparison_operator"
8006 [(match_operand:SI 2 "s_register_operand" "")
8007 (match_operand:SI 3 "arm_add_operand" "")]))
8009 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8012 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8014 (set (reg:CC_NOOV CC_REGNUM)
8015 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8020 [(set (reg:CC_NOOV CC_REGNUM)
8021 (compare:CC_NOOV (ior:SI
8022 (match_operator:SI 1 "comparison_operator"
8023 [(match_operand:SI 2 "s_register_operand" "")
8024 (match_operand:SI 3 "arm_add_operand" "")])
8025 (and:SI (match_operand:SI 0 "s_register_operand" "")
8028 (clobber (match_operand:SI 4 "s_register_operand" ""))]
8031 (ior:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
8033 (set (reg:CC_NOOV CC_REGNUM)
8034 (compare:CC_NOOV (and:SI (match_dup 4) (const_int 1))
8038 (define_insn "*negscc"
8039 [(set (match_operand:SI 0 "s_register_operand" "=r")
8040 (neg:SI (match_operator 3 "arm_comparison_operator"
8041 [(match_operand:SI 1 "s_register_operand" "r")
8042 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
8043 (clobber (reg:CC CC_REGNUM))]
8046 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
8047 return \"mov\\t%0, %1, asr #31\";
8049 if (GET_CODE (operands[3]) == NE)
8050 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
8052 if (GET_CODE (operands[3]) == GT)
8053 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
8055 output_asm_insn (\"cmp\\t%1, %2\", operands);
8056 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
8057 return \"mvn%d3\\t%0, #0\";
8059 [(set_attr "conds" "clob")
8060 (set_attr "length" "12")]
8063 (define_insn "movcond"
8064 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8066 (match_operator 5 "arm_comparison_operator"
8067 [(match_operand:SI 3 "s_register_operand" "r,r,r")
8068 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
8069 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
8070 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
8071 (clobber (reg:CC CC_REGNUM))]
8074 if (GET_CODE (operands[5]) == LT
8075 && (operands[4] == const0_rtx))
8077 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8079 if (operands[2] == const0_rtx)
8080 return \"and\\t%0, %1, %3, asr #31\";
8081 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
8083 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8085 if (operands[1] == const0_rtx)
8086 return \"bic\\t%0, %2, %3, asr #31\";
8087 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
8089 /* The only case that falls through to here is when both ops 1 & 2
8093 if (GET_CODE (operands[5]) == GE
8094 && (operands[4] == const0_rtx))
8096 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
8098 if (operands[2] == const0_rtx)
8099 return \"bic\\t%0, %1, %3, asr #31\";
8100 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
8102 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
8104 if (operands[1] == const0_rtx)
8105 return \"and\\t%0, %2, %3, asr #31\";
8106 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
8108 /* The only case that falls through to here is when both ops 1 & 2
8111 if (GET_CODE (operands[4]) == CONST_INT
8112 && !const_ok_for_arm (INTVAL (operands[4])))
8113 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
8115 output_asm_insn (\"cmp\\t%3, %4\", operands);
8116 if (which_alternative != 0)
8117 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
8118 if (which_alternative != 1)
8119 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
8122 [(set_attr "conds" "clob")
8123 (set_attr "length" "8,8,12")]
8126 (define_insn "*ifcompare_plus_move"
8127 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8128 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8129 [(match_operand:SI 4 "s_register_operand" "r,r")
8130 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8132 (match_operand:SI 2 "s_register_operand" "r,r")
8133 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
8134 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8135 (clobber (reg:CC CC_REGNUM))]
8138 [(set_attr "conds" "clob")
8139 (set_attr "length" "8,12")]
8142 (define_insn "*if_plus_move"
8143 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8145 (match_operator 4 "arm_comparison_operator"
8146 [(match_operand 5 "cc_register" "") (const_int 0)])
8148 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8149 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
8150 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
8154 sub%d4\\t%0, %2, #%n3
8155 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
8156 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
8157 [(set_attr "conds" "use")
8158 (set_attr "length" "4,4,8,8")
8159 (set_attr "type" "*,*,*,*")]
8162 (define_insn "*ifcompare_move_plus"
8163 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8164 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8165 [(match_operand:SI 4 "s_register_operand" "r,r")
8166 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8167 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8169 (match_operand:SI 2 "s_register_operand" "r,r")
8170 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
8171 (clobber (reg:CC CC_REGNUM))]
8174 [(set_attr "conds" "clob")
8175 (set_attr "length" "8,12")]
8178 (define_insn "*if_move_plus"
8179 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
8181 (match_operator 4 "arm_comparison_operator"
8182 [(match_operand 5 "cc_register" "") (const_int 0)])
8183 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
8185 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
8186 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
8190 sub%D4\\t%0, %2, #%n3
8191 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
8192 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
8193 [(set_attr "conds" "use")
8194 (set_attr "length" "4,4,8,8")
8195 (set_attr "type" "*,*,*,*")]
8198 (define_insn "*ifcompare_arith_arith"
8199 [(set (match_operand:SI 0 "s_register_operand" "=r")
8200 (if_then_else:SI (match_operator 9 "arm_comparison_operator"
8201 [(match_operand:SI 5 "s_register_operand" "r")
8202 (match_operand:SI 6 "arm_add_operand" "rIL")])
8203 (match_operator:SI 8 "shiftable_operator"
8204 [(match_operand:SI 1 "s_register_operand" "r")
8205 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8206 (match_operator:SI 7 "shiftable_operator"
8207 [(match_operand:SI 3 "s_register_operand" "r")
8208 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
8209 (clobber (reg:CC CC_REGNUM))]
8212 [(set_attr "conds" "clob")
8213 (set_attr "length" "12")]
8216 (define_insn "*if_arith_arith"
8217 [(set (match_operand:SI 0 "s_register_operand" "=r")
8218 (if_then_else:SI (match_operator 5 "arm_comparison_operator"
8219 [(match_operand 8 "cc_register" "") (const_int 0)])
8220 (match_operator:SI 6 "shiftable_operator"
8221 [(match_operand:SI 1 "s_register_operand" "r")
8222 (match_operand:SI 2 "arm_rhs_operand" "rI")])
8223 (match_operator:SI 7 "shiftable_operator"
8224 [(match_operand:SI 3 "s_register_operand" "r")
8225 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
8227 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
8228 [(set_attr "conds" "use")
8229 (set_attr "length" "8")]
8232 (define_insn "*ifcompare_arith_move"
8233 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8234 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8235 [(match_operand:SI 2 "s_register_operand" "r,r")
8236 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
8237 (match_operator:SI 7 "shiftable_operator"
8238 [(match_operand:SI 4 "s_register_operand" "r,r")
8239 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
8240 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
8241 (clobber (reg:CC CC_REGNUM))]
8244 /* If we have an operation where (op x 0) is the identity operation and
8245 the conditional operator is LT or GE and we are comparing against zero and
8246 everything is in registers then we can do this in two instructions */
8247 if (operands[3] == const0_rtx
8248 && GET_CODE (operands[7]) != AND
8249 && GET_CODE (operands[5]) == REG
8250 && GET_CODE (operands[1]) == REG
8251 && REGNO (operands[1]) == REGNO (operands[4])
8252 && REGNO (operands[4]) != REGNO (operands[0]))
8254 if (GET_CODE (operands[6]) == LT)
8255 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8256 else if (GET_CODE (operands[6]) == GE)
8257 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
8259 if (GET_CODE (operands[3]) == CONST_INT
8260 && !const_ok_for_arm (INTVAL (operands[3])))
8261 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
8263 output_asm_insn (\"cmp\\t%2, %3\", operands);
8264 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
8265 if (which_alternative != 0)
8266 return \"mov%D6\\t%0, %1\";
8269 [(set_attr "conds" "clob")
8270 (set_attr "length" "8,12")]
8273 (define_insn "*if_arith_move"
8274 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8275 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
8276 [(match_operand 6 "cc_register" "") (const_int 0)])
8277 (match_operator:SI 5 "shiftable_operator"
8278 [(match_operand:SI 2 "s_register_operand" "r,r")
8279 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
8280 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
8284 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
8285 [(set_attr "conds" "use")
8286 (set_attr "length" "4,8")
8287 (set_attr "type" "*,*")]
8290 (define_insn "*ifcompare_move_arith"
8291 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8292 (if_then_else:SI (match_operator 6 "arm_comparison_operator"
8293 [(match_operand:SI 4 "s_register_operand" "r,r")
8294 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8295 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8296 (match_operator:SI 7 "shiftable_operator"
8297 [(match_operand:SI 2 "s_register_operand" "r,r")
8298 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
8299 (clobber (reg:CC CC_REGNUM))]
8302 /* If we have an operation where (op x 0) is the identity operation and
8303 the conditional operator is LT or GE and we are comparing against zero and
8304 everything is in registers then we can do this in two instructions */
8305 if (operands[5] == const0_rtx
8306 && GET_CODE (operands[7]) != AND
8307 && GET_CODE (operands[3]) == REG
8308 && GET_CODE (operands[1]) == REG
8309 && REGNO (operands[1]) == REGNO (operands[2])
8310 && REGNO (operands[2]) != REGNO (operands[0]))
8312 if (GET_CODE (operands[6]) == GE)
8313 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8314 else if (GET_CODE (operands[6]) == LT)
8315 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
8318 if (GET_CODE (operands[5]) == CONST_INT
8319 && !const_ok_for_arm (INTVAL (operands[5])))
8320 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
8322 output_asm_insn (\"cmp\\t%4, %5\", operands);
8324 if (which_alternative != 0)
8325 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
8326 return \"%I7%D6\\t%0, %2, %3\";
8328 [(set_attr "conds" "clob")
8329 (set_attr "length" "8,12")]
8332 (define_insn "*if_move_arith"
8333 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8335 (match_operator 4 "arm_comparison_operator"
8336 [(match_operand 6 "cc_register" "") (const_int 0)])
8337 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8338 (match_operator:SI 5 "shiftable_operator"
8339 [(match_operand:SI 2 "s_register_operand" "r,r")
8340 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
8344 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
8345 [(set_attr "conds" "use")
8346 (set_attr "length" "4,8")
8347 (set_attr "type" "*,*")]
8350 (define_insn "*ifcompare_move_not"
8351 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8353 (match_operator 5 "arm_comparison_operator"
8354 [(match_operand:SI 3 "s_register_operand" "r,r")
8355 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8356 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8358 (match_operand:SI 2 "s_register_operand" "r,r"))))
8359 (clobber (reg:CC CC_REGNUM))]
8362 [(set_attr "conds" "clob")
8363 (set_attr "length" "8,12")]
8366 (define_insn "*if_move_not"
8367 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8369 (match_operator 4 "arm_comparison_operator"
8370 [(match_operand 3 "cc_register" "") (const_int 0)])
8371 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8372 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8376 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
8377 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
8378 [(set_attr "conds" "use")
8379 (set_attr "length" "4,8,8")]
8382 (define_insn "*ifcompare_not_move"
8383 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8385 (match_operator 5 "arm_comparison_operator"
8386 [(match_operand:SI 3 "s_register_operand" "r,r")
8387 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8389 (match_operand:SI 2 "s_register_operand" "r,r"))
8390 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8391 (clobber (reg:CC CC_REGNUM))]
8394 [(set_attr "conds" "clob")
8395 (set_attr "length" "8,12")]
8398 (define_insn "*if_not_move"
8399 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8401 (match_operator 4 "arm_comparison_operator"
8402 [(match_operand 3 "cc_register" "") (const_int 0)])
8403 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8404 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8408 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
8409 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
8410 [(set_attr "conds" "use")
8411 (set_attr "length" "4,8,8")]
8414 (define_insn "*ifcompare_shift_move"
8415 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8417 (match_operator 6 "arm_comparison_operator"
8418 [(match_operand:SI 4 "s_register_operand" "r,r")
8419 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8420 (match_operator:SI 7 "shift_operator"
8421 [(match_operand:SI 2 "s_register_operand" "r,r")
8422 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
8423 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8424 (clobber (reg:CC CC_REGNUM))]
8427 [(set_attr "conds" "clob")
8428 (set_attr "length" "8,12")]
8431 (define_insn "*if_shift_move"
8432 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8434 (match_operator 5 "arm_comparison_operator"
8435 [(match_operand 6 "cc_register" "") (const_int 0)])
8436 (match_operator:SI 4 "shift_operator"
8437 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8438 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
8439 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8443 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
8444 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
8445 [(set_attr "conds" "use")
8446 (set_attr "shift" "2")
8447 (set_attr "length" "4,8,8")]
8450 (define_insn "*ifcompare_move_shift"
8451 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8453 (match_operator 6 "arm_comparison_operator"
8454 [(match_operand:SI 4 "s_register_operand" "r,r")
8455 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
8456 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8457 (match_operator:SI 7 "shift_operator"
8458 [(match_operand:SI 2 "s_register_operand" "r,r")
8459 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
8460 (clobber (reg:CC CC_REGNUM))]
8463 [(set_attr "conds" "clob")
8464 (set_attr "length" "8,12")]
8467 (define_insn "*if_move_shift"
8468 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8470 (match_operator 5 "arm_comparison_operator"
8471 [(match_operand 6 "cc_register" "") (const_int 0)])
8472 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8473 (match_operator:SI 4 "shift_operator"
8474 [(match_operand:SI 2 "s_register_operand" "r,r,r")
8475 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
8479 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
8480 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
8481 [(set_attr "conds" "use")
8482 (set_attr "shift" "2")
8483 (set_attr "length" "4,8,8")]
8486 (define_insn "*ifcompare_shift_shift"
8487 [(set (match_operand:SI 0 "s_register_operand" "=r")
8489 (match_operator 7 "arm_comparison_operator"
8490 [(match_operand:SI 5 "s_register_operand" "r")
8491 (match_operand:SI 6 "arm_add_operand" "rIL")])
8492 (match_operator:SI 8 "shift_operator"
8493 [(match_operand:SI 1 "s_register_operand" "r")
8494 (match_operand:SI 2 "arm_rhs_operand" "rM")])
8495 (match_operator:SI 9 "shift_operator"
8496 [(match_operand:SI 3 "s_register_operand" "r")
8497 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
8498 (clobber (reg:CC CC_REGNUM))]
8501 [(set_attr "conds" "clob")
8502 (set_attr "length" "12")]
8505 (define_insn "*if_shift_shift"
8506 [(set (match_operand:SI 0 "s_register_operand" "=r")
8508 (match_operator 5 "arm_comparison_operator"
8509 [(match_operand 8 "cc_register" "") (const_int 0)])
8510 (match_operator:SI 6 "shift_operator"
8511 [(match_operand:SI 1 "s_register_operand" "r")
8512 (match_operand:SI 2 "arm_rhs_operand" "rM")])
8513 (match_operator:SI 7 "shift_operator"
8514 [(match_operand:SI 3 "s_register_operand" "r")
8515 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
8517 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
8518 [(set_attr "conds" "use")
8519 (set_attr "shift" "1")
8520 (set_attr "length" "8")]
8523 (define_insn "*ifcompare_not_arith"
8524 [(set (match_operand:SI 0 "s_register_operand" "=r")
8526 (match_operator 6 "arm_comparison_operator"
8527 [(match_operand:SI 4 "s_register_operand" "r")
8528 (match_operand:SI 5 "arm_add_operand" "rIL")])
8529 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8530 (match_operator:SI 7 "shiftable_operator"
8531 [(match_operand:SI 2 "s_register_operand" "r")
8532 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
8533 (clobber (reg:CC CC_REGNUM))]
8536 [(set_attr "conds" "clob")
8537 (set_attr "length" "12")]
8540 (define_insn "*if_not_arith"
8541 [(set (match_operand:SI 0 "s_register_operand" "=r")
8543 (match_operator 5 "arm_comparison_operator"
8544 [(match_operand 4 "cc_register" "") (const_int 0)])
8545 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
8546 (match_operator:SI 6 "shiftable_operator"
8547 [(match_operand:SI 2 "s_register_operand" "r")
8548 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
8550 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
8551 [(set_attr "conds" "use")
8552 (set_attr "length" "8")]
8555 (define_insn "*ifcompare_arith_not"
8556 [(set (match_operand:SI 0 "s_register_operand" "=r")
8558 (match_operator 6 "arm_comparison_operator"
8559 [(match_operand:SI 4 "s_register_operand" "r")
8560 (match_operand:SI 5 "arm_add_operand" "rIL")])
8561 (match_operator:SI 7 "shiftable_operator"
8562 [(match_operand:SI 2 "s_register_operand" "r")
8563 (match_operand:SI 3 "arm_rhs_operand" "rI")])
8564 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
8565 (clobber (reg:CC CC_REGNUM))]
8568 [(set_attr "conds" "clob")
8569 (set_attr "length" "12")]
8572 (define_insn "*if_arith_not"
8573 [(set (match_operand:SI 0 "s_register_operand" "=r")
8575 (match_operator 5 "arm_comparison_operator"
8576 [(match_operand 4 "cc_register" "") (const_int 0)])
8577 (match_operator:SI 6 "shiftable_operator"
8578 [(match_operand:SI 2 "s_register_operand" "r")
8579 (match_operand:SI 3 "arm_rhs_operand" "rI")])
8580 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
8582 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
8583 [(set_attr "conds" "use")
8584 (set_attr "length" "8")]
8587 (define_insn "*ifcompare_neg_move"
8588 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8590 (match_operator 5 "arm_comparison_operator"
8591 [(match_operand:SI 3 "s_register_operand" "r,r")
8592 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8593 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
8594 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
8595 (clobber (reg:CC CC_REGNUM))]
8598 [(set_attr "conds" "clob")
8599 (set_attr "length" "8,12")]
8602 (define_insn "*if_neg_move"
8603 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8605 (match_operator 4 "arm_comparison_operator"
8606 [(match_operand 3 "cc_register" "") (const_int 0)])
8607 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
8608 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
8612 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
8613 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
8614 [(set_attr "conds" "use")
8615 (set_attr "length" "4,8,8")]
8618 (define_insn "*ifcompare_move_neg"
8619 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8621 (match_operator 5 "arm_comparison_operator"
8622 [(match_operand:SI 3 "s_register_operand" "r,r")
8623 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
8624 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
8625 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
8626 (clobber (reg:CC CC_REGNUM))]
8629 [(set_attr "conds" "clob")
8630 (set_attr "length" "8,12")]
8633 (define_insn "*if_move_neg"
8634 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
8636 (match_operator 4 "arm_comparison_operator"
8637 [(match_operand 3 "cc_register" "") (const_int 0)])
8638 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
8639 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
8643 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
8644 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
8645 [(set_attr "conds" "use")
8646 (set_attr "length" "4,8,8")]
8649 (define_insn "*arith_adjacentmem"
8650 [(set (match_operand:SI 0 "s_register_operand" "=r")
8651 (match_operator:SI 1 "shiftable_operator"
8652 [(match_operand:SI 2 "memory_operand" "m")
8653 (match_operand:SI 3 "memory_operand" "m")]))
8654 (clobber (match_scratch:SI 4 "=r"))]
8655 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
8660 int val1 = 0, val2 = 0;
8662 if (REGNO (operands[0]) > REGNO (operands[4]))
8664 ldm[1] = operands[4];
8665 ldm[2] = operands[0];
8669 ldm[1] = operands[0];
8670 ldm[2] = operands[4];
8672 if (GET_CODE (XEXP (operands[2], 0)) != REG)
8673 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
8674 if (GET_CODE (XEXP (operands[3], 0)) != REG)
8675 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
8676 arith[0] = operands[0];
8677 arith[3] = operands[1];
8691 ldm[0] = ops[0] = operands[4];
8692 ops[1] = XEXP (XEXP (operands[2], 0), 0);
8693 ops[2] = XEXP (XEXP (operands[2], 0), 1);
8694 output_add_immediate (ops);
8696 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8698 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8702 ldm[0] = XEXP (operands[3], 0);
8704 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8706 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8710 ldm[0] = XEXP (operands[2], 0);
8712 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
8714 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
8716 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
8719 [(set_attr "length" "12")
8720 (set_attr "predicable" "yes")
8721 (set_attr "type" "load")]
8724 ;; the arm can support extended pre-inc instructions
8726 ;; In all these cases, we use operands 0 and 1 for the register being
8727 ;; incremented because those are the operands that local-alloc will
8728 ;; tie and these are the pair most likely to be tieable (and the ones
8729 ;; that will benefit the most).
8731 ;; We reject the frame pointer if it occurs anywhere in these patterns since
8732 ;; elimination will cause too many headaches.
8734 (define_insn "*strqi_preinc"
8735 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8736 (match_operand:SI 2 "index_operand" "rJ")))
8737 (match_operand:QI 3 "s_register_operand" "r"))
8738 (set (match_operand:SI 0 "s_register_operand" "=r")
8739 (plus:SI (match_dup 1) (match_dup 2)))]
8741 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8742 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8743 && (GET_CODE (operands[2]) != REG
8744 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8745 "str%?b\\t%3, [%0, %2]!"
8746 [(set_attr "type" "store1")
8747 (set_attr "predicable" "yes")]
8750 (define_insn "*strqi_predec"
8751 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8752 (match_operand:SI 2 "s_register_operand" "r")))
8753 (match_operand:QI 3 "s_register_operand" "r"))
8754 (set (match_operand:SI 0 "s_register_operand" "=r")
8755 (minus:SI (match_dup 1) (match_dup 2)))]
8757 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8758 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8759 && (GET_CODE (operands[2]) != REG
8760 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8761 "str%?b\\t%3, [%0, -%2]!"
8762 [(set_attr "type" "store1")
8763 (set_attr "predicable" "yes")]
8766 (define_insn "*loadqi_preinc"
8767 [(set (match_operand:QI 3 "s_register_operand" "=r")
8768 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8769 (match_operand:SI 2 "index_operand" "rJ"))))
8770 (set (match_operand:SI 0 "s_register_operand" "=r")
8771 (plus:SI (match_dup 1) (match_dup 2)))]
8773 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8774 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8775 && (GET_CODE (operands[2]) != REG
8776 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8777 "ldr%?b\\t%3, [%0, %2]!"
8778 [(set_attr "type" "load")
8779 (set_attr "predicable" "yes")]
8782 (define_insn "*loadqi_predec"
8783 [(set (match_operand:QI 3 "s_register_operand" "=r")
8784 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8785 (match_operand:SI 2 "s_register_operand" "r"))))
8786 (set (match_operand:SI 0 "s_register_operand" "=r")
8787 (minus:SI (match_dup 1) (match_dup 2)))]
8789 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8790 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8791 && (GET_CODE (operands[2]) != REG
8792 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8793 "ldr%?b\\t%3, [%0, -%2]!"
8794 [(set_attr "type" "load")
8795 (set_attr "predicable" "yes")]
8798 (define_insn "*loadqisi_preinc"
8799 [(set (match_operand:SI 3 "s_register_operand" "=r")
8801 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8802 (match_operand:SI 2 "index_operand" "rJ")))))
8803 (set (match_operand:SI 0 "s_register_operand" "=r")
8804 (plus:SI (match_dup 1) (match_dup 2)))]
8806 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8807 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8808 && (GET_CODE (operands[2]) != REG
8809 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8810 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
8811 [(set_attr "type" "load")
8812 (set_attr "predicable" "yes")]
8815 (define_insn "*loadqisi_predec"
8816 [(set (match_operand:SI 3 "s_register_operand" "=r")
8818 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8819 (match_operand:SI 2 "s_register_operand" "r")))))
8820 (set (match_operand:SI 0 "s_register_operand" "=r")
8821 (minus:SI (match_dup 1) (match_dup 2)))]
8823 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8824 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8825 && (GET_CODE (operands[2]) != REG
8826 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8827 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
8828 [(set_attr "type" "load")
8829 (set_attr "predicable" "yes")]
8832 (define_insn "*strsi_preinc"
8833 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8834 (match_operand:SI 2 "index_operand" "rJ")))
8835 (match_operand:SI 3 "s_register_operand" "r"))
8836 (set (match_operand:SI 0 "s_register_operand" "=r")
8837 (plus:SI (match_dup 1) (match_dup 2)))]
8839 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8840 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8841 && (GET_CODE (operands[2]) != REG
8842 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8843 "str%?\\t%3, [%0, %2]!"
8844 [(set_attr "type" "store1")
8845 (set_attr "predicable" "yes")]
8848 (define_insn "*strsi_predec"
8849 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8850 (match_operand:SI 2 "s_register_operand" "r")))
8851 (match_operand:SI 3 "s_register_operand" "r"))
8852 (set (match_operand:SI 0 "s_register_operand" "=r")
8853 (minus:SI (match_dup 1) (match_dup 2)))]
8855 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8856 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8857 && (GET_CODE (operands[2]) != REG
8858 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8859 "str%?\\t%3, [%0, -%2]!"
8860 [(set_attr "type" "store1")
8861 (set_attr "predicable" "yes")]
8864 (define_insn "*loadsi_preinc"
8865 [(set (match_operand:SI 3 "s_register_operand" "=r")
8866 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8867 (match_operand:SI 2 "index_operand" "rJ"))))
8868 (set (match_operand:SI 0 "s_register_operand" "=r")
8869 (plus:SI (match_dup 1) (match_dup 2)))]
8871 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8872 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8873 && (GET_CODE (operands[2]) != REG
8874 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8875 "ldr%?\\t%3, [%0, %2]!"
8876 [(set_attr "type" "load")
8877 (set_attr "predicable" "yes")]
8880 (define_insn "*loadsi_predec"
8881 [(set (match_operand:SI 3 "s_register_operand" "=r")
8882 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8883 (match_operand:SI 2 "s_register_operand" "r"))))
8884 (set (match_operand:SI 0 "s_register_operand" "=r")
8885 (minus:SI (match_dup 1) (match_dup 2)))]
8887 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8888 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8889 && (GET_CODE (operands[2]) != REG
8890 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8891 "ldr%?\\t%3, [%0, -%2]!"
8892 [(set_attr "type" "load")
8893 (set_attr "predicable" "yes")]
8896 (define_insn "*loadhi_preinc"
8897 [(set (match_operand:HI 3 "s_register_operand" "=r")
8898 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
8899 (match_operand:SI 2 "index_operand" "rJ"))))
8900 (set (match_operand:SI 0 "s_register_operand" "=r")
8901 (plus:SI (match_dup 1) (match_dup 2)))]
8903 && !BYTES_BIG_ENDIAN
8904 && !TARGET_MMU_TRAPS
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 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
8911 [(set_attr "type" "load")
8912 (set_attr "predicable" "yes")]
8915 (define_insn "*loadhi_predec"
8916 [(set (match_operand:HI 3 "s_register_operand" "=r")
8917 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8918 (match_operand:SI 2 "s_register_operand" "r"))))
8919 (set (match_operand:SI 0 "s_register_operand" "=r")
8920 (minus:SI (match_dup 1) (match_dup 2)))]
8922 && !BYTES_BIG_ENDIAN
8923 && !TARGET_MMU_TRAPS
8925 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8926 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8927 && (GET_CODE (operands[2]) != REG
8928 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
8929 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
8930 [(set_attr "type" "load")
8931 (set_attr "predicable" "yes")]
8934 (define_insn "*strqi_shiftpreinc"
8935 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8936 [(match_operand:SI 3 "s_register_operand" "r")
8937 (match_operand:SI 4 "const_shift_operand" "n")])
8938 (match_operand:SI 1 "s_register_operand" "0")))
8939 (match_operand:QI 5 "s_register_operand" "r"))
8940 (set (match_operand:SI 0 "s_register_operand" "=r")
8941 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8944 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8945 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8946 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8947 "str%?b\\t%5, [%0, %3%S2]!"
8948 [(set_attr "type" "store1")
8949 (set_attr "predicable" "yes")]
8952 (define_insn "*strqi_shiftpredec"
8953 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8954 (match_operator:SI 2 "shift_operator"
8955 [(match_operand:SI 3 "s_register_operand" "r")
8956 (match_operand:SI 4 "const_shift_operand" "n")])))
8957 (match_operand:QI 5 "s_register_operand" "r"))
8958 (set (match_operand:SI 0 "s_register_operand" "=r")
8959 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8962 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8963 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8964 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8965 "str%?b\\t%5, [%0, -%3%S2]!"
8966 [(set_attr "type" "store1")
8967 (set_attr "predicable" "yes")]
8970 (define_insn "*loadqi_shiftpreinc"
8971 [(set (match_operand:QI 5 "s_register_operand" "=r")
8972 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
8973 [(match_operand:SI 3 "s_register_operand" "r")
8974 (match_operand:SI 4 "const_shift_operand" "n")])
8975 (match_operand:SI 1 "s_register_operand" "0"))))
8976 (set (match_operand:SI 0 "s_register_operand" "=r")
8977 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
8980 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8981 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
8982 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
8983 "ldr%?b\\t%5, [%0, %3%S2]!"
8984 [(set_attr "type" "load")
8985 (set_attr "predicable" "yes")]
8988 (define_insn "*loadqi_shiftpredec"
8989 [(set (match_operand:QI 5 "s_register_operand" "=r")
8990 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
8991 (match_operator:SI 2 "shift_operator"
8992 [(match_operand:SI 3 "s_register_operand" "r")
8993 (match_operand:SI 4 "const_shift_operand" "n")]))))
8994 (set (match_operand:SI 0 "s_register_operand" "=r")
8995 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
8998 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
8999 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9000 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9001 "ldr%?b\\t%5, [%0, -%3%S2]!"
9002 [(set_attr "type" "load")
9003 (set_attr "predicable" "yes")]
9006 (define_insn "*strsi_shiftpreinc"
9007 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9008 [(match_operand:SI 3 "s_register_operand" "r")
9009 (match_operand:SI 4 "const_shift_operand" "n")])
9010 (match_operand:SI 1 "s_register_operand" "0")))
9011 (match_operand:SI 5 "s_register_operand" "r"))
9012 (set (match_operand:SI 0 "s_register_operand" "=r")
9013 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9016 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9017 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9018 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9019 "str%?\\t%5, [%0, %3%S2]!"
9020 [(set_attr "type" "store1")
9021 (set_attr "predicable" "yes")]
9024 (define_insn "*strsi_shiftpredec"
9025 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9026 (match_operator:SI 2 "shift_operator"
9027 [(match_operand:SI 3 "s_register_operand" "r")
9028 (match_operand:SI 4 "const_shift_operand" "n")])))
9029 (match_operand:SI 5 "s_register_operand" "r"))
9030 (set (match_operand:SI 0 "s_register_operand" "=r")
9031 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9034 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9035 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9036 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9037 "str%?\\t%5, [%0, -%3%S2]!"
9038 [(set_attr "type" "store1")
9039 (set_attr "predicable" "yes")]
9042 (define_insn "*loadsi_shiftpreinc"
9043 [(set (match_operand:SI 5 "s_register_operand" "=r")
9044 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
9045 [(match_operand:SI 3 "s_register_operand" "r")
9046 (match_operand:SI 4 "const_shift_operand" "n")])
9047 (match_operand:SI 1 "s_register_operand" "0"))))
9048 (set (match_operand:SI 0 "s_register_operand" "=r")
9049 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9052 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9053 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9054 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9055 "ldr%?\\t%5, [%0, %3%S2]!"
9056 [(set_attr "type" "load")
9057 (set_attr "predicable" "yes")]
9060 (define_insn "*loadsi_shiftpredec"
9061 [(set (match_operand:SI 5 "s_register_operand" "=r")
9062 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9063 (match_operator:SI 2 "shift_operator"
9064 [(match_operand:SI 3 "s_register_operand" "r")
9065 (match_operand:SI 4 "const_shift_operand" "n")]))))
9066 (set (match_operand:SI 0 "s_register_operand" "=r")
9067 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9070 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9071 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9072 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9073 "ldr%?\\t%5, [%0, -%3%S2]!"
9074 [(set_attr "type" "load")
9075 (set_attr "predicable" "yes")])
9077 (define_insn "*loadhi_shiftpreinc"
9078 [(set (match_operand:HI 5 "s_register_operand" "=r")
9079 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
9080 [(match_operand:SI 3 "s_register_operand" "r")
9081 (match_operand:SI 4 "const_shift_operand" "n")])
9082 (match_operand:SI 1 "s_register_operand" "0"))))
9083 (set (match_operand:SI 0 "s_register_operand" "=r")
9084 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9087 && !BYTES_BIG_ENDIAN
9088 && !TARGET_MMU_TRAPS
9090 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9091 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9092 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9093 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
9094 [(set_attr "type" "load")
9095 (set_attr "predicable" "yes")]
9098 (define_insn "*loadhi_shiftpredec"
9099 [(set (match_operand:HI 5 "s_register_operand" "=r")
9100 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
9101 (match_operator:SI 2 "shift_operator"
9102 [(match_operand:SI 3 "s_register_operand" "r")
9103 (match_operand:SI 4 "const_shift_operand" "n")]))))
9104 (set (match_operand:SI 0 "s_register_operand" "=r")
9105 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
9108 && !BYTES_BIG_ENDIAN
9109 && !TARGET_MMU_TRAPS
9111 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
9112 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
9113 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
9114 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
9115 [(set_attr "type" "load")
9116 (set_attr "predicable" "yes")]
9119 ; It can also support extended post-inc expressions, but combine doesn't
9121 ; It doesn't seem worth adding peepholes for anything but the most common
9122 ; cases since, unlike combine, the increment must immediately follow the load
9123 ; for this pattern to match.
9124 ; We must watch to see that the source/destination register isn't also the
9125 ; same as the base address register, and that if the index is a register,
9126 ; that it is not the same as the base address register. In such cases the
9127 ; instruction that we would generate would have UNPREDICTABLE behavior so
9131 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
9132 (match_operand:QI 2 "s_register_operand" "r"))
9134 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9136 && (REGNO (operands[2]) != REGNO (operands[0]))
9137 && (GET_CODE (operands[1]) != REG
9138 || (REGNO (operands[1]) != REGNO (operands[0])))"
9139 "str%?b\\t%2, [%0], %1"
9143 [(set (match_operand:QI 0 "s_register_operand" "=r")
9144 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
9146 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9148 && REGNO (operands[0]) != REGNO(operands[1])
9149 && (GET_CODE (operands[2]) != REG
9150 || REGNO(operands[0]) != REGNO (operands[2]))"
9151 "ldr%?b\\t%0, [%1], %2"
9155 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
9156 (match_operand:SI 2 "s_register_operand" "r"))
9158 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
9160 && (REGNO (operands[2]) != REGNO (operands[0]))
9161 && (GET_CODE (operands[1]) != REG
9162 || (REGNO (operands[1]) != REGNO (operands[0])))"
9163 "str%?\\t%2, [%0], %1"
9167 [(set (match_operand:HI 0 "s_register_operand" "=r")
9168 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
9170 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9172 && !BYTES_BIG_ENDIAN
9173 && !TARGET_MMU_TRAPS
9175 && REGNO (operands[0]) != REGNO(operands[1])
9176 && (GET_CODE (operands[2]) != REG
9177 || REGNO(operands[0]) != REGNO (operands[2]))"
9178 "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
9182 [(set (match_operand:SI 0 "s_register_operand" "=r")
9183 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
9185 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
9187 && REGNO (operands[0]) != REGNO(operands[1])
9188 && (GET_CODE (operands[2]) != REG
9189 || REGNO(operands[0]) != REGNO (operands[2]))"
9190 "ldr%?\\t%0, [%1], %2"
9194 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
9195 (match_operand:SI 1 "index_operand" "rJ")))
9196 (match_operand:QI 2 "s_register_operand" "r"))
9197 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
9199 && (REGNO (operands[2]) != REGNO (operands[0]))
9200 && (GET_CODE (operands[1]) != REG
9201 || (REGNO (operands[1]) != REGNO (operands[0])))"
9202 "str%?b\\t%2, [%0, %1]!"
9206 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
9207 [(match_operand:SI 0 "s_register_operand" "r")
9208 (match_operand:SI 1 "const_int_operand" "n")])
9209 (match_operand:SI 2 "s_register_operand" "+r")))
9210 (match_operand:QI 3 "s_register_operand" "r"))
9211 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
9214 && (REGNO (operands[3]) != REGNO (operands[2]))
9215 && (REGNO (operands[0]) != REGNO (operands[2]))"
9216 "str%?b\\t%3, [%2, %0%S4]!"
9219 ; This pattern is never tried by combine, so do it as a peephole
9222 [(set (match_operand:SI 0 "s_register_operand" "")
9223 (match_operand:SI 1 "s_register_operand" ""))
9224 (set (reg:CC CC_REGNUM)
9225 (compare:CC (match_dup 1) (const_int 0)))]
9228 || (!cirrus_fp_register (operands[0], SImode)
9229 && !cirrus_fp_register (operands[1], SImode)))
9231 [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
9232 (set (match_dup 0) (match_dup 1))])]
9236 ; Peepholes to spot possible load- and store-multiples, if the ordering is
9237 ; reversed, check that the memory references aren't volatile.
9240 [(set (match_operand:SI 0 "s_register_operand" "=r")
9241 (match_operand:SI 4 "memory_operand" "m"))
9242 (set (match_operand:SI 1 "s_register_operand" "=r")
9243 (match_operand:SI 5 "memory_operand" "m"))
9244 (set (match_operand:SI 2 "s_register_operand" "=r")
9245 (match_operand:SI 6 "memory_operand" "m"))
9246 (set (match_operand:SI 3 "s_register_operand" "=r")
9247 (match_operand:SI 7 "memory_operand" "m"))]
9248 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9250 return emit_ldm_seq (operands, 4);
9255 [(set (match_operand:SI 0 "s_register_operand" "=r")
9256 (match_operand:SI 3 "memory_operand" "m"))
9257 (set (match_operand:SI 1 "s_register_operand" "=r")
9258 (match_operand:SI 4 "memory_operand" "m"))
9259 (set (match_operand:SI 2 "s_register_operand" "=r")
9260 (match_operand:SI 5 "memory_operand" "m"))]
9261 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9263 return emit_ldm_seq (operands, 3);
9268 [(set (match_operand:SI 0 "s_register_operand" "=r")
9269 (match_operand:SI 2 "memory_operand" "m"))
9270 (set (match_operand:SI 1 "s_register_operand" "=r")
9271 (match_operand:SI 3 "memory_operand" "m"))]
9272 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9274 return emit_ldm_seq (operands, 2);
9279 [(set (match_operand:SI 4 "memory_operand" "=m")
9280 (match_operand:SI 0 "s_register_operand" "r"))
9281 (set (match_operand:SI 5 "memory_operand" "=m")
9282 (match_operand:SI 1 "s_register_operand" "r"))
9283 (set (match_operand:SI 6 "memory_operand" "=m")
9284 (match_operand:SI 2 "s_register_operand" "r"))
9285 (set (match_operand:SI 7 "memory_operand" "=m")
9286 (match_operand:SI 3 "s_register_operand" "r"))]
9287 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
9289 return emit_stm_seq (operands, 4);
9294 [(set (match_operand:SI 3 "memory_operand" "=m")
9295 (match_operand:SI 0 "s_register_operand" "r"))
9296 (set (match_operand:SI 4 "memory_operand" "=m")
9297 (match_operand:SI 1 "s_register_operand" "r"))
9298 (set (match_operand:SI 5 "memory_operand" "=m")
9299 (match_operand:SI 2 "s_register_operand" "r"))]
9300 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
9302 return emit_stm_seq (operands, 3);
9307 [(set (match_operand:SI 2 "memory_operand" "=m")
9308 (match_operand:SI 0 "s_register_operand" "r"))
9309 (set (match_operand:SI 3 "memory_operand" "=m")
9310 (match_operand:SI 1 "s_register_operand" "r"))]
9311 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
9313 return emit_stm_seq (operands, 2);
9318 [(set (match_operand:SI 0 "s_register_operand" "")
9319 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
9321 (neg:SI (match_operator:SI 2 "arm_comparison_operator"
9322 [(match_operand:SI 3 "s_register_operand" "")
9323 (match_operand:SI 4 "arm_rhs_operand" "")]))))
9324 (clobber (match_operand:SI 5 "s_register_operand" ""))]
9326 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
9327 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
9332 ;; This split can be used because CC_Z mode implies that the following
9333 ;; branch will be an equality, or an unsigned inequality, so the sign
9334 ;; extension is not needed.
9337 [(set (reg:CC_Z CC_REGNUM)
9339 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
9341 (match_operand 1 "const_int_operand" "")))
9342 (clobber (match_scratch:SI 2 ""))]
9344 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
9345 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
9346 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
9347 (set (reg:CC CC_REGNUM) (compare:CC (match_dup 2) (match_dup 1)))]
9349 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
9353 (define_expand "prologue"
9354 [(clobber (const_int 0))]
9357 arm_expand_prologue ();
9359 thumb_expand_prologue ();
9364 (define_expand "epilogue"
9365 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9369 thumb_expand_epilogue ();
9370 else if (USE_RETURN_INSN (FALSE))
9372 emit_jump_insn (gen_return ());
9375 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
9377 gen_rtx_RETURN (VOIDmode)),
9383 ;; Note - although unspec_volatile's USE all hard registers,
9384 ;; USEs are ignored after relaod has completed. Thus we need
9385 ;; to add an unspec of the link register to ensure that flow
9386 ;; does not think that it is unused by the sibcall branch that
9387 ;; will replace the standard function epilogue.
9388 (define_insn "sibcall_epilogue"
9389 [(parallel [(unspec:SI [(reg:SI LR_REGNUM)] UNSPEC_PROLOGUE_USE)
9390 (unspec_volatile [(return)] VUNSPEC_EPILOGUE)])]
9393 if (use_return_insn (FALSE, next_nonnote_insn (insn)))
9394 return output_return_instruction (const_true_rtx, FALSE, FALSE);
9395 return arm_output_epilogue (next_nonnote_insn (insn));
9397 ;; Length is absolute worst case
9398 [(set_attr "length" "44")
9399 (set_attr "type" "block")
9400 ;; We don't clobber the conditions, but the potential length of this
9401 ;; operation is sufficient to make conditionalizing the sequence
9402 ;; unlikely to be profitable.
9403 (set_attr "conds" "clob")]
9406 (define_insn "*epilogue_insns"
9407 [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
9411 return arm_output_epilogue (NULL);
9412 else /* TARGET_THUMB */
9413 return thumb_unexpanded_epilogue ();
9415 ; Length is absolute worst case
9416 [(set_attr "length" "44")
9417 (set_attr "type" "block")
9418 ;; We don't clobber the conditions, but the potential length of this
9419 ;; operation is sufficient to make conditionalizing the sequence
9420 ;; unlikely to be profitable.
9421 (set_attr "conds" "clob")]
9424 (define_expand "eh_epilogue"
9425 [(use (match_operand:SI 0 "register_operand" ""))
9426 (use (match_operand:SI 1 "register_operand" ""))
9427 (use (match_operand:SI 2 "register_operand" ""))]
9431 cfun->machine->eh_epilogue_sp_ofs = operands[1];
9432 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
9434 rtx ra = gen_rtx_REG (Pmode, 2);
9436 emit_move_insn (ra, operands[2]);
9439 /* This is a hack -- we may have crystalized the function type too
9441 cfun->machine->func_type = 0;
9445 ;; This split is only used during output to reduce the number of patterns
9446 ;; that need assembler instructions adding to them. We allowed the setting
9447 ;; of the conditions to be implicit during rtl generation so that
9448 ;; the conditional compare patterns would work. However this conflicts to
9449 ;; some extent with the conditional data operations, so we have to split them
9453 [(set (match_operand:SI 0 "s_register_operand" "")
9454 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9455 [(match_operand 2 "" "") (match_operand 3 "" "")])
9457 (match_operand 4 "" "")))
9458 (clobber (reg:CC CC_REGNUM))]
9459 "TARGET_ARM && reload_completed"
9460 [(set (match_dup 5) (match_dup 6))
9461 (cond_exec (match_dup 7)
9462 (set (match_dup 0) (match_dup 4)))]
9465 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9466 operands[2], operands[3]);
9467 enum rtx_code rc = GET_CODE (operands[1]);
9469 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9470 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9471 if (mode == CCFPmode || mode == CCFPEmode)
9472 rc = reverse_condition_maybe_unordered (rc);
9474 rc = reverse_condition (rc);
9476 operands[7] = gen_rtx_fmt_ee (rc, VOIDmode, operands[5], const0_rtx);
9481 [(set (match_operand:SI 0 "s_register_operand" "")
9482 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9483 [(match_operand 2 "" "") (match_operand 3 "" "")])
9484 (match_operand 4 "" "")
9486 (clobber (reg:CC CC_REGNUM))]
9487 "TARGET_ARM && reload_completed"
9488 [(set (match_dup 5) (match_dup 6))
9489 (cond_exec (match_op_dup 1 [(match_dup 5) (const_int 0)])
9490 (set (match_dup 0) (match_dup 4)))]
9493 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9494 operands[2], operands[3]);
9496 operands[5] = gen_rtx_REG (mode, CC_REGNUM);
9497 operands[6] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9502 [(set (match_operand:SI 0 "s_register_operand" "")
9503 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9504 [(match_operand 2 "" "") (match_operand 3 "" "")])
9505 (match_operand 4 "" "")
9506 (match_operand 5 "" "")))
9507 (clobber (reg:CC CC_REGNUM))]
9508 "TARGET_ARM && reload_completed"
9509 [(set (match_dup 6) (match_dup 7))
9510 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9511 (set (match_dup 0) (match_dup 4)))
9512 (cond_exec (match_dup 8)
9513 (set (match_dup 0) (match_dup 5)))]
9516 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9517 operands[2], operands[3]);
9518 enum rtx_code rc = GET_CODE (operands[1]);
9520 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9521 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
9522 if (mode == CCFPmode || mode == CCFPEmode)
9523 rc = reverse_condition_maybe_unordered (rc);
9525 rc = reverse_condition (rc);
9527 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9532 [(set (match_operand:SI 0 "s_register_operand" "")
9533 (if_then_else:SI (match_operator 1 "arm_comparison_operator"
9534 [(match_operand:SI 2 "s_register_operand" "")
9535 (match_operand:SI 3 "arm_add_operand" "")])
9536 (match_operand:SI 4 "arm_rhs_operand" "")
9538 (match_operand:SI 5 "s_register_operand" ""))))
9539 (clobber (reg:CC CC_REGNUM))]
9540 "TARGET_ARM && reload_completed"
9541 [(set (match_dup 6) (match_dup 7))
9542 (cond_exec (match_op_dup 1 [(match_dup 6) (const_int 0)])
9543 (set (match_dup 0) (match_dup 4)))
9544 (cond_exec (match_dup 8)
9545 (set (match_dup 0) (not:SI (match_dup 5))))]
9548 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]),
9549 operands[2], operands[3]);
9550 enum rtx_code rc = GET_CODE (operands[1]);
9552 operands[6] = gen_rtx_REG (mode, CC_REGNUM);
9553 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
9554 if (mode == CCFPmode || mode == CCFPEmode)
9555 rc = reverse_condition_maybe_unordered (rc);
9557 rc = reverse_condition (rc);
9559 operands[8] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx);
9563 (define_insn "*cond_move_not"
9564 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
9565 (if_then_else:SI (match_operator 4 "arm_comparison_operator"
9566 [(match_operand 3 "cc_register" "") (const_int 0)])
9567 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
9569 (match_operand:SI 2 "s_register_operand" "r,r"))))]
9573 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
9574 [(set_attr "conds" "use")
9575 (set_attr "length" "4,8")]
9578 ;; The next two patterns occur when an AND operation is followed by a
9579 ;; scc insn sequence
9581 (define_insn "*sign_extract_onebit"
9582 [(set (match_operand:SI 0 "s_register_operand" "=r")
9583 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9585 (match_operand:SI 2 "const_int_operand" "n")))
9586 (clobber (reg:CC CC_REGNUM))]
9589 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9590 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
9591 return \"mvnne\\t%0, #0\";
9593 [(set_attr "conds" "clob")
9594 (set_attr "length" "8")]
9597 (define_insn "*not_signextract_onebit"
9598 [(set (match_operand:SI 0 "s_register_operand" "=r")
9600 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
9602 (match_operand:SI 2 "const_int_operand" "n"))))
9603 (clobber (reg:CC CC_REGNUM))]
9606 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
9607 output_asm_insn (\"tst\\t%1, %2\", operands);
9608 output_asm_insn (\"mvneq\\t%0, #0\", operands);
9609 return \"movne\\t%0, #0\";
9611 [(set_attr "conds" "clob")
9612 (set_attr "length" "12")]
9615 ;; Push multiple registers to the stack. Registers are in parallel (use ...)
9616 ;; expressions. For simplicity, the first register is also in the unspec
9618 (define_insn "*push_multi"
9619 [(match_parallel 2 "multi_register_push"
9620 [(set (match_operand:BLK 0 "memory_operand" "=m")
9621 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")]
9622 UNSPEC_PUSH_MULT))])]
9626 int num_saves = XVECLEN (operands[2], 0);
9628 /* For the StrongARM at least it is faster to
9629 use STR to store only a single register. */
9631 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
9637 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
9639 for (i = 1; i < num_saves; i++)
9641 strcat (pattern, \", %|\");
9643 reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i), 0))]);
9646 strcat (pattern, \"}\");
9647 output_asm_insn (pattern, operands);
9652 [(set_attr "type" "store4")]
9655 (define_insn "stack_tie"
9656 [(set (mem:BLK (scratch))
9657 (unspec:BLK [(match_operand:SI 0 "s_register_operand" "r")
9658 (match_operand:SI 1 "s_register_operand" "r")]
9662 [(set_attr "length" "0")]
9665 ;; Similarly for the floating point registers
9666 (define_insn "*push_fp_multi"
9667 [(match_parallel 2 "multi_register_push"
9668 [(set (match_operand:BLK 0 "memory_operand" "=m")
9669 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
9670 UNSPEC_PUSH_MULT))])]
9676 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
9677 output_asm_insn (pattern, operands);
9680 [(set_attr "type" "f_store")]
9683 ;; Special patterns for dealing with the constant pool
9685 (define_insn "align_4"
9686 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN)]
9689 assemble_align (32);
9694 (define_insn "align_8"
9695 [(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
9696 "TARGET_REALLY_IWMMXT"
9698 assemble_align (64);
9703 (define_insn "consttable_end"
9704 [(unspec_volatile [(const_int 0)] VUNSPEC_POOL_END)]
9707 making_const_table = FALSE;
9712 (define_insn "consttable_1"
9713 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_1)]
9716 making_const_table = TRUE;
9717 assemble_integer (operands[0], 1, BITS_PER_WORD, 1);
9721 [(set_attr "length" "4")]
9724 (define_insn "consttable_2"
9725 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_2)]
9728 making_const_table = TRUE;
9729 assemble_integer (operands[0], 2, BITS_PER_WORD, 1);
9733 [(set_attr "length" "4")]
9736 (define_insn "consttable_4"
9737 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_4)]
9741 making_const_table = TRUE;
9742 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9747 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9748 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9752 assemble_integer (operands[0], 4, BITS_PER_WORD, 1);
9757 [(set_attr "length" "4")]
9760 (define_insn "consttable_8"
9761 [(unspec_volatile [(match_operand 0 "" "")] VUNSPEC_POOL_8)]
9765 making_const_table = TRUE;
9766 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
9771 REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
9772 assemble_real (r, GET_MODE (operands[0]), BITS_PER_WORD);
9776 assemble_integer (operands[0], 8, BITS_PER_WORD, 1);
9781 [(set_attr "length" "8")]
9784 ;; Miscellaneous Thumb patterns
9786 (define_expand "tablejump"
9787 [(parallel [(set (pc) (match_operand:SI 0 "register_operand" ""))
9788 (use (label_ref (match_operand 1 "" "")))])]
9793 /* Hopefully, CSE will eliminate this copy. */
9794 rtx reg1 = copy_addr_to_reg (gen_rtx_LABEL_REF (Pmode, operands[1]));
9795 rtx reg2 = gen_reg_rtx (SImode);
9797 emit_insn (gen_addsi3 (reg2, operands[0], reg1));
9803 (define_insn "*thumb_tablejump"
9804 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
9805 (use (label_ref (match_operand 1 "" "")))]
9808 [(set_attr "length" "2")]
9813 (define_insn "clzsi2"
9814 [(set (match_operand:SI 0 "s_register_operand" "=r")
9815 (clz:SI (match_operand:SI 1 "s_register_operand" "r")))]
9816 "TARGET_ARM && arm_arch5"
9818 [(set_attr "predicable" "yes")])
9820 (define_expand "ffssi2"
9821 [(set (match_operand:SI 0 "s_register_operand" "")
9822 (ffs:SI (match_operand:SI 1 "s_register_operand" "")))]
9823 "TARGET_ARM && arm_arch5"
9828 t1 = gen_reg_rtx (SImode);
9829 t2 = gen_reg_rtx (SImode);
9830 t3 = gen_reg_rtx (SImode);
9832 emit_insn (gen_negsi2 (t1, operands[1]));
9833 emit_insn (gen_andsi3 (t2, operands[1], t1));
9834 emit_insn (gen_clzsi2 (t3, t2));
9835 emit_insn (gen_subsi3 (operands[0], GEN_INT (32), t3));
9840 (define_expand "ctzsi2"
9841 [(set (match_operand:SI 0 "s_register_operand" "")
9842 (ctz:SI (match_operand:SI 1 "s_register_operand" "")))]
9843 "TARGET_ARM && arm_arch5"
9848 t1 = gen_reg_rtx (SImode);
9849 t2 = gen_reg_rtx (SImode);
9850 t3 = gen_reg_rtx (SImode);
9852 emit_insn (gen_negsi2 (t1, operands[1]));
9853 emit_insn (gen_andsi3 (t2, operands[1], t1));
9854 emit_insn (gen_clzsi2 (t3, t2));
9855 emit_insn (gen_subsi3 (operands[0], GEN_INT (31), t3));
9860 ;; V5E instructions.
9862 (define_insn "prefetch"
9863 [(prefetch (match_operand:SI 0 "address_operand" "p")
9864 (match_operand:SI 1 "" "")
9865 (match_operand:SI 2 "" ""))]
9866 "TARGET_ARM && arm_arch5e"
9869 ;; General predication pattern
9872 [(match_operator 0 "arm_comparison_operator"
9873 [(match_operand 1 "cc_register" "")
9879 (define_insn "prologue_use"
9880 [(unspec:SI [(match_operand:SI 0 "register_operand" "")] UNSPEC_PROLOGUE_USE)]
9882 "%@ %0 needed for prologue"
9885 ;; Load the FPA co-processor patterns
9887 ;; Load the Maverick co-processor patterns
9888 (include "cirrus.md")
9889 ;; Load the Intel Wireless Multimedia Extension patterns
9890 (include "iwmmxt.md")